3 from zope.interface import implements
4 from twisted.internet import defer
5 from twisted.python import failure
6 from twisted.application import service
7 from allmydata import uri, dirnode
8 from allmydata.interfaces import IURI, IMutableFileNode, IFileNode, \
9 FileTooLargeError, ICheckable
10 from allmydata.immutable import checker
11 from allmydata.immutable.encode import NotEnoughSharesError
12 from allmydata.util import log
14 class FakeCHKFileNode:
15 """I provide IFileNode, but all of my data is stored in a class-level
20 def __init__(self, u, client):
22 self.my_uri = u.to_string()
26 def get_readonly_uri(self):
28 def get_verifier(self):
29 return IURI(self.my_uri).get_verifier()
30 def check(self, verify=False, repair=False):
31 r = checker.Results(None)
34 return defer.succeed(r)
37 def is_readonly(self):
40 def download(self, target):
41 if self.my_uri not in self.all_contents:
42 f = failure.Failure(NotEnoughSharesError())
45 data = self.all_contents[self.my_uri]
46 target.open(len(data))
49 return defer.maybeDeferred(target.finish)
50 def download_to_data(self):
51 if self.my_uri not in self.all_contents:
52 return defer.fail(NotEnoughSharesError())
53 data = self.all_contents[self.my_uri]
54 return defer.succeed(data)
56 data = self.all_contents[self.my_uri]
59 def make_chk_file_uri(size):
60 return uri.CHKFileURI(key=os.urandom(16),
61 uri_extension_hash=os.urandom(32),
66 def create_chk_filenode(client, contents):
67 u = make_chk_file_uri(len(contents))
68 n = FakeCHKFileNode(u, client)
69 FakeCHKFileNode.all_contents[u.to_string()] = contents
73 class FakeMutableFileNode:
74 """I provide IMutableFileNode, but all of my data is stored in a
75 class-level dictionary."""
77 implements(IMutableFileNode, ICheckable)
78 MUTABLE_SIZELIMIT = 10000
81 def __init__(self, client):
83 self.my_uri = make_mutable_file_uri()
84 self.storage_index = self.my_uri.storage_index
85 def create(self, initial_contents, key_generator=None):
86 if len(initial_contents) > self.MUTABLE_SIZELIMIT:
87 raise FileTooLargeError("SDMF is limited to one segment, and "
88 "%d > %d" % (len(initial_contents),
89 self.MUTABLE_SIZELIMIT))
90 self.all_contents[self.storage_index] = initial_contents
91 return defer.succeed(self)
92 def init_from_uri(self, myuri):
93 self.my_uri = IURI(myuri)
94 self.storage_index = self.my_uri.storage_index
97 return self.my_uri.to_string()
98 def get_readonly(self):
99 return self.my_uri.get_readonly()
100 def get_readonly_uri(self):
101 return self.my_uri.get_readonly().to_string()
102 def is_readonly(self):
103 return self.my_uri.is_readonly()
104 def is_mutable(self):
105 return self.my_uri.is_mutable()
106 def get_writekey(self):
109 return "?" # TODO: see mutable.MutableFileNode.get_size
111 def get_storage_index(self):
112 return self.storage_index
114 def check(self, verify=False, repair=False):
115 r = checker.Results(None)
118 return defer.succeed(r)
120 def deep_check(self, verify=False, repair=False):
121 d = self.check(verify, repair)
123 dr = DeepCheckResults(self.storage_index)
129 def download_best_version(self):
130 return defer.succeed(self.all_contents[self.storage_index])
131 def overwrite(self, new_contents):
132 if len(new_contents) > self.MUTABLE_SIZELIMIT:
133 raise FileTooLargeError("SDMF is limited to one segment, and "
134 "%d > %d" % (len(new_contents),
135 self.MUTABLE_SIZELIMIT))
136 assert not self.is_readonly()
137 self.all_contents[self.storage_index] = new_contents
138 return defer.succeed(None)
139 def modify(self, modifier):
140 # this does not implement FileTooLargeError, but the real one does
141 return defer.maybeDeferred(self._modify, modifier)
142 def _modify(self, modifier):
143 assert not self.is_readonly()
144 old_contents = self.all_contents[self.storage_index]
145 self.all_contents[self.storage_index] = modifier(old_contents)
148 def download(self, target):
149 if self.storage_index not in self.all_contents:
150 f = failure.Failure(NotEnoughSharesError())
153 data = self.all_contents[self.storage_index]
154 target.open(len(data))
157 return defer.maybeDeferred(target.finish)
158 def download_to_data(self):
159 if self.storage_index not in self.all_contents:
160 return defer.fail(NotEnoughSharesError())
161 data = self.all_contents[self.storage_index]
162 return defer.succeed(data)
164 def make_mutable_file_uri():
165 return uri.WriteableSSKFileURI(writekey=os.urandom(16),
166 fingerprint=os.urandom(32))
167 def make_verifier_uri():
168 return uri.SSKVerifierURI(storage_index=os.urandom(16),
169 fingerprint=os.urandom(32))
171 class FakeDirectoryNode(dirnode.NewDirectoryNode):
172 """This offers IDirectoryNode, but uses a FakeMutableFileNode for the
173 backing store, so it doesn't go to the grid. The child data is still
174 encrypted and serialized, so this isn't useful for tests that want to
175 look inside the dirnodes and check their contents.
177 filenode_class = FakeMutableFileNode
179 class LoggingServiceParent(service.MultiService):
180 def log(self, *args, **kwargs):
181 return log.msg(*args, **kwargs)