Merge lp:~thisfred/desktopcouch/fix-unique-id-test into lp:desktopcouch

Proposed by Eric Casteleijn
Status: Merged
Approved by: Vincenzo Di Somma
Approved revision: 202
Merged at revision: 200
Proposed branch: lp:~thisfred/desktopcouch/fix-unique-id-test
Merge into: lp:desktopcouch
Diff against target: 444 lines (+128/-90)
2 files modified
desktopcouch/pair/couchdb_pairing/couchdb_io.py (+73/-50)
desktopcouch/pair/tests/test_couchdb_io.py (+55/-40)
To merge this branch: bzr merge lp:~thisfred/desktopcouch/fix-unique-id-test
Reviewer Review Type Date Requested Status
Manuel de la Peña (community) Approve
Vincenzo Di Somma (community) Approve
dobey (community) Approve
Review via email: mp+40461@code.launchpad.net

Commit message

This fixes get_my_host_unique_id to pass the context it gets to the methods it calls, so that tests talk to the correct database.

Description of the change

This fixes get_my_host_unique_id to pass the context it gets to the methods it calls, so that tests talk to the correct database.

To post a comment you must log in.
Revision history for this message
Manuel de la Peña (mandel) wrote :

+1 I like those pylint error out too :)

Revision history for this message
dobey (dobey) :
review: Approve
Revision history for this message
Vincenzo Di Somma (vds) wrote :

+1

review: Approve
Revision history for this message
Manuel de la Peña (mandel) wrote :

me stupid :P, I forgot to approve

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'desktopcouch/pair/couchdb_pairing/couchdb_io.py'
2--- desktopcouch/pair/couchdb_pairing/couchdb_io.py 2010-11-03 02:47:32 +0000
3+++ desktopcouch/pair/couchdb_pairing/couchdb_io.py 2010-11-09 17:39:48 +0000
4@@ -33,22 +33,29 @@
5 PAIRED_SERVER_RECORD_TYPE = RECTYPE_BASE + "paired_server"
6 MY_ID_RECORD_TYPE = RECTYPE_BASE + "server_identity"
7
8-def obsfuscate(d):
9- def maybe_hide(k, v):
10- if hasattr(k, "endswith") and k.endswith("secret"):
11- return "".join(rep for rep, vi in zip(cycle('Hidden'), v))
12+
13+def obsfuscate(dictionary):
14+ """Obfuscate a string by replacing all secret values."""
15+ def maybe_hide(key, value):
16+ """Replace with gibberish where necessary."""
17+ if hasattr(key, "endswith") and key.endswith("secret"):
18+ return "".join(rep for rep, vi in zip(cycle('Hidden'), value))
19 else:
20- return v
21-
22- if not hasattr(d, "iteritems"):
23- return d
24- return dict((k, maybe_hide(k, obsfuscate(v))) for k, v in d.iteritems())
25+ return value
26+
27+ if not hasattr(dictionary, "iteritems"):
28+ return dictionary
29+ return dict(
30+ (key, maybe_hide(key, obsfuscate(value))) for key, value
31+ in dictionary.iteritems())
32+
33
34 def mkuri(hostname, port, has_ssl=False, path="", auth_pair=None):
35 """Create a URI from parts."""
36 protocol = "https" if has_ssl else "http"
37 if auth_pair:
38- auth = (":".join(map(urllib.quote, auth_pair)) + "@")
39+ auth = (":".join(
40+ map(urllib.quote, auth_pair)) + "@") # pylint: disable-msg=W0141
41 else:
42 auth = ""
43 if (protocol, port) in (("http", 80), ("https", 443)):
44@@ -57,13 +64,14 @@
45 port = str(port)
46 return "%s://%s%s:%s/%s" % (protocol, auth, hostname, port, path)
47
48-def _get_db(name, create=True, uri=None,
49- ctx=local_files.DEFAULT_CONTEXT):
50+
51+def _get_db(name, create=True, uri=None, ctx=local_files.DEFAULT_CONTEXT):
52 """Get (and create?) a database."""
53 return server.CouchDatabase(name, create=create, uri=uri, ctx=ctx)
54
55+
56 def put_paired_host(oauth_data, uri=None,
57- ctx=local_files.DEFAULT_CONTEXT, **kwargs):
58+ ctx=local_files.DEFAULT_CONTEXT, **kwargs):
59 """Create a new paired-host record. OAuth information is required, and
60 after the uri, keyword parameters are added to the record."""
61 pairing_id = str(uuid.uuid4())
62@@ -80,25 +88,28 @@
63 "token_secret": str(oauth_data["token_secret"]),
64 }
65 data.update(kwargs)
66- d = _get_db("management", uri=uri, ctx=ctx)
67- r = Record(data)
68- record_id = d.put_record(r)
69+ database = _get_db("management", uri=uri, ctx=ctx)
70+ record = Record(data)
71+ record_id = database.put_record(record)
72 return record_id
73
74+
75 def put_static_paired_service(oauth_data, service_name, uri=None,
76- ctx=local_files.DEFAULT_CONTEXT):
77+ ctx=local_files.DEFAULT_CONTEXT):
78 """Create a new service record."""
79 return put_paired_host(oauth_data, uri=uri, service_name=service_name,
80 pull_from_server=True, push_to_server=True, ctx=ctx)
81
82+
83 def put_dynamic_paired_host(hostname, remote_uuid, oauth_data, uri=None,
84- ctx=local_files.DEFAULT_CONTEXT):
85+ ctx=local_files.DEFAULT_CONTEXT):
86 """Create a new dynamic-host record."""
87 return put_paired_host(oauth_data, uri=uri, pairing_identifier=remote_uuid,
88 push_to_server=True, server=hostname, ctx=ctx)
89
90-def get_static_paired_hosts(uri=None,
91- ctx=local_files.DEFAULT_CONTEXT, port=None):
92+
93+def get_static_paired_hosts(uri=None, # pylint: disable-msg=R0914
94+ ctx=local_files.DEFAULT_CONTEXT, port=None):
95 """Retreive a list of static hosts' information in the form of
96 (ID, service name, to_push, to_pull) ."""
97 if not uri and port is not None:
98@@ -121,6 +132,7 @@
99 logging.debug("static pairings are %s", unique_hosts)
100 return unique_hosts
101
102+
103 def get_database_names_replicatable(uri, oauth_tokens=None, service=False,
104 ctx=local_files.DEFAULT_CONTEXT, user_id=None):
105 """Find a list of local databases, minus dbs that we do not want to
106@@ -143,7 +155,7 @@
107 "Got list of databases from %s/_all_dbs?user_id=%s:\n %s",
108 couchdb_server, user_id, all_dbs)
109
110- except socket.error, e:
111+ except socket.error:
112 logging.error("Can't get list of databases from %s", couchdb_server)
113 return set()
114
115@@ -158,14 +170,17 @@
116
117 return set([n for n in all_dbs - excluded if not n.startswith("_")])
118
119+
120 def get_my_host_unique_id(uri=None, create=True,
121- ctx=local_files.DEFAULT_CONTEXT):
122+ ctx=local_files.DEFAULT_CONTEXT):
123 """Returns a list of ids we call ourselves. We complain in the log if it's
124 more than one, but it's really no error. If there are zero (id est, we've
125 never paired with anyone), then returns None."""
126
127 db = _get_db("management", uri=uri, ctx=ctx)
128- ids = _get_management_data(MY_ID_RECORD_TYPE, "self_identity", uri=uri)
129+ db.ensure_full_commit()
130+ ids = _get_management_data(
131+ MY_ID_RECORD_TYPE, "self_identity", uri=uri, ctx=ctx)
132 ids = list(set(ids)) # uniqify
133 if len(ids) > 1:
134 logging.error("DANGER! We have more than one record claiming to be "
135@@ -178,16 +193,15 @@
136 if not create:
137 return None
138 else:
139- data = { "self_identity": str(uuid.uuid4()),
140- "record_type": MY_ID_RECORD_TYPE,
141- }
142+ data = {"self_identity": str(uuid.uuid4()),
143+ "record_type": MY_ID_RECORD_TYPE}
144 data["_id"] = data["self_identity"]
145 db.put_record(Record(data))
146 logging.debug("set new self-identity value: %r", data["self_identity"])
147 return [data["self_identity"]]
148
149-def get_all_known_pairings(uri=None,
150- ctx=local_files.DEFAULT_CONTEXT):
151+
152+def get_all_known_pairings(uri=None, ctx=local_files.DEFAULT_CONTEXT):
153 """Info dicts about all pairings, even if marked "unpaired", keyed on
154 hostid with another dict as the value."""
155 d = {}
156@@ -204,8 +218,10 @@
157 d[hostid] = v
158 return d
159
160+
161 def _get_management_data(record_type, key, uri=None,
162- ctx=local_files.DEFAULT_CONTEXT):
163+ ctx=local_files.DEFAULT_CONTEXT):
164+ """Get the management data from couchdb."""
165 db = _get_db("management", uri=uri, ctx=ctx)
166 results = db.get_all_records(record_type=record_type)
167 values = list()
168@@ -226,19 +242,20 @@
169 logging.debug("found %d %s records", len(values), key)
170 return values
171
172+
173 def create_database(dst_host, dst_port, dst_name, use_ssl=False,
174- oauth_tokens=None):
175+ oauth_tokens=None):
176 """Given parts, create a database."""
177 dst_url = mkuri(dst_host, dst_port, use_ssl)
178 return server.CouchDatabase(dst_name, dst_url, create=True,
179 oauth_tokens=oauth_tokens)
180
181-def replicate(source_database, target_database, target_host=None,
182- target_port=None, source_host=None, source_port=None,
183- source_ssl=False, target_ssl=False, source_oauth=None,
184- target_oauth=None, local_uri=None):
185+
186+def replicate(source_database, target_database, # pylint: disable-msg=R0914
187+ target_host=None, target_port=None, source_host=None,
188+ source_port=None, source_ssl=False, target_ssl=False,
189+ source_oauth=None, target_oauth=None, local_uri=None):
190 """This replication is instant and blocking, and does not persist. """
191-
192 try:
193 if target_host:
194 # Target databases must exist before replicating to them.
195@@ -251,9 +268,10 @@
196 else:
197 server.CouchDatabase(target_database, create=True, uri=local_uri)
198 logging.debug("db exists, and we're ready to replicate")
199- except:
200- logging.exception("can't create/verify %r %s:%d oauth=%s",
201- target_database, target_host, target_port, obsfuscate(target_oauth))
202+ except: # pylint: disable-msg=W0702
203+ logging.exception(
204+ "can't create/verify %r %s:%d oauth=%s", target_database,
205+ target_host, target_port, obsfuscate(target_oauth))
206 if source_host:
207 source = mkuri(source_host, source_port, source_ssl, urllib.quote(
208 source_database, safe=""))
209@@ -285,20 +303,20 @@
210 "asking %r to replicate %s to %s", obsfuscate(local_uri),
211 obsfuscate(source), obsfuscate(target),)
212
213- ### All until python-couchdb gets a Server.replicate() function
214+ # All until python-couchdb gets a Server.replicate() function
215 local_server = server.OAuthCapableServer(local_uri)
216 resp, data = local_server.resource.post(path='/_replicate',
217 content=record)
218-
219- logging.debug("replicate result: %r %r", obsfuscate(resp), obsfuscate(data))
220- ###
221- except:
222+ logging.debug(
223+ "replicate result: %r %r", obsfuscate(resp), obsfuscate(data))
224+ except: # pylint: disable-msg=W0702
225 logging.exception("can't replicate %r %r <== %r", source_database,
226 local_uri, obsfuscate(record))
227
228+
229 def get_pairings(uri=None, ctx=local_files.DEFAULT_CONTEXT):
230 """Get a list of paired servers."""
231- db = _get_db("management", create=True, uri=None, ctx=ctx)
232+ db = _get_db("management", create=True, uri=uri, ctx=ctx)
233
234 design_doc = "paired_servers"
235 if not db.view_exists("paired_servers", design_doc):
236@@ -306,8 +324,10 @@
237 if (doc.record_type == %r && ! doc.unpaired) // unset or False
238 if (doc.application_annotations &&
239 doc.application_annotations["Ubuntu One"] &&
240- doc.application_annotations["Ubuntu One"].private_application_annotations &&
241- doc.application_annotations["Ubuntu One"].private_application_annotations.deleted) {
242+ doc.application_annotations[
243+ "Ubuntu One"].private_application_annotations &&
244+ doc.application_annotations[
245+ "Ubuntu One"].private_application_annotations.deleted) {
246 // don't emit deleted or unpaired items
247 } else {
248 if (doc.server) {
249@@ -316,22 +336,25 @@
250 emit(doc.service_name, doc);
251 }
252 }
253- }""" % (PAIRED_SERVER_RECORD_TYPE,)
254+ }""" % (PAIRED_SERVER_RECORD_TYPE,)
255 db.add_view("paired_servers", map_js, None, design_doc)
256
257 return db.execute_view("paired_servers")
258
259+
260 def remove_pairing(record_id, is_reconciled, uri=None,
261- ctx=local_files.DEFAULT_CONTEXT):
262+ ctx=local_files.DEFAULT_CONTEXT):
263 """Remove a pairing record (or mark it as dead so it can be cleaned up
264 properly later)."""
265- db = _get_db("management", create=True, uri=None, ctx=ctx)
266+ db = _get_db("management", create=True, uri=uri, ctx=ctx)
267 if is_reconciled:
268 db.delete_record(record_id)
269 else:
270- db.update_fields(record_id, { "unpaired": True })
271+ db.update_fields(record_id, {"unpaired": True})
272+
273
274 def expunge_pairing(host_id, uri=None):
275+ """Remove pairing record for host_id."""
276 try:
277 d = get_all_known_pairings(uri)
278 record_id = d[host_id]["record_id"]
279
280=== modified file 'desktopcouch/pair/tests/test_couchdb_io.py'
281--- desktopcouch/pair/tests/test_couchdb_io.py 2010-11-02 21:20:35 +0000
282+++ desktopcouch/pair/tests/test_couchdb_io.py 2010-11-09 17:39:48 +0000
283@@ -1,3 +1,4 @@
284+"""Test Couchdb IO"""
285 # Copyright 2009 Canonical Ltd.
286 #
287 # This file is part of desktopcouch.
288@@ -31,7 +32,9 @@
289 import socket
290 URI = None # use autodiscovery that desktopcouch.tests permits.
291
292+
293 class TestCouchdbIo(unittest.TestCase):
294+ """Test case for Couchdb IO"""
295
296 def setUp(self):
297 """setup each test"""
298@@ -64,22 +67,39 @@
299
300 def tearDown(self):
301 """tear down each test"""
302- del self.mgt_database._server['management']
303- del self.mgt_database._server['foo']
304-
305+ del self.mgt_database._server['management'] # pylint: disable-msg=W0212
306+ del self.mgt_database._server['foo'] # pylint: disable-msg=W0212
307
308 def test_obsfuscation(self):
309- t = {'url': 'https://couchdb.one.ubuntu.com/u%2Fb2%2Fc8%2F276%2Ftest', 'auth': {'oauth': {'consumer_secret': 'SeCrEtSe', 'token': '3XRjQrWX92TTTJFDTWJJ', 'consumer_key': 'ubuntuone', 'token_secret': 'jBmSeCrEtawkefwklefliwuregqwlkeh347wq87w4fiuq4fyu3q4fiqwu4fqwfiqufM6xjsPwSeCrEt4'}}}
310+ """Test the obfuscation of sensitive data."""
311+ t = {
312+ 'url':
313+ 'https://couchdb.one.ubuntu.com/u%2Fb2%2Fc8%2F276%2Ftest',
314+ 'auth': {
315+ 'oauth': {
316+ 'consumer_secret': 'SeCrEtSe',
317+ 'token': '3XRjQrWX92TTTJFDTWJJ',
318+ 'consumer_key': 'ubuntuone',
319+ 'token_secret': 'jBmSeCrEtawkefwklefliwuregqwlkeh347wq87w4f'
320+ 'iuq4fyu3q4fiqwu4fqwfiqufM6xjsPwSeCrEt4'}}}
321 cleaned_t = couchdb_io.obsfuscate(t)
322- self.failIf("SeCrEt" in str(cleaned_t), {'url': 'https://couchdb.one.ubuntu.com/u%2Fb2%2Fc8%2F276%2Ftest', 'auth': {'oauth': {'consumer_secret': 'HiddenHidd', 'token': '3XRjQrWX92TTTJFDTWJJ', 'consumer_key': 'ubuntuone', 'token_secret': 'HiddenHiddenHiddenHiddenHiddenHiddenHiddenHiddenHiddenHiddenHiddenHiddenHiddenHi'}}})
323-
324+ self.failIf(
325+ "SeCrEt" in str(cleaned_t), {
326+ 'url':
327+ 'https://couchdb.one.ubuntu.com/u%2Fb2%2Fc8%2F276%2Ftest',
328+ 'auth': {'oauth': {
329+ 'consumer_secret': 'HiddenHidd',
330+ 'token': '3XRjQrWX92TTTJFDTWJJ',
331+ 'consumer_key': 'ubuntuone',
332+ 'token_secret': 'HiddenHiddenHiddenHiddenHiddenHiddenHidden'
333+ 'HiddenHiddenHiddenHiddenHiddenHiddenHi'}}})
334 self.assertEqual(couchdb_io.obsfuscate(""), "")
335 self.assertEqual(couchdb_io.obsfuscate({}), {})
336- self.assertEqual(couchdb_io.obsfuscate({1:{}}), {1:{}})
337- self.assertEqual(couchdb_io.obsfuscate({1:1}), {1:1})
338-
339-
340- def test_put_static_paired_service(self):
341+ self.assertEqual(couchdb_io.obsfuscate({1: {}}), {1: {}})
342+ self.assertEqual(couchdb_io.obsfuscate({1: 1}), {1: 1})
343+
344+ def test_put_static_paired_service(self): # pylint: disable-msg=R0201
345+ """Test putting a static paired service."""
346 service_name = "dummyfortest"
347 oauth_data = {
348 "consumer_key": str("abcdef"),
349@@ -87,10 +107,14 @@
350 "token": str("opqrst"),
351 "token_secret": str("uvwxyz"),
352 }
353- couchdb_io.put_static_paired_service(oauth_data, service_name, uri=URI, ctx=test_environment.test_context)
354- pairings = list(couchdb_io.get_pairings(ctx=test_environment.test_context))
355+ couchdb_io.put_static_paired_service(
356+ oauth_data, service_name, uri=URI,
357+ ctx=test_environment.test_context)
358+ couchdb_io.get_pairings(ctx=test_environment.test_context)
359+ # Assert something?
360
361 def test_put_dynamic_paired_host(self):
362+ """Test putting a dynamically paired host."""
363 hostname = "host%d" % (os.getpid(),)
364 remote_uuid = str(uuid.uuid4())
365 oauth_data = {
366@@ -107,20 +131,24 @@
367 couchdb_io.put_dynamic_paired_host(hostname, remote_uuid, oauth_data,
368 uri=URI, ctx=test_environment.test_context)
369
370- pairings = list(couchdb_io.get_pairings(ctx=test_environment.test_context))
371- self.assertEqual(4, len(pairings)) # 3, plus 1 from setUp()
372+ pairings = list(couchdb_io.get_pairings(
373+ ctx=test_environment.test_context))
374+ # 3, plus 1 from setUp()
375+ self.assertEqual(4, len(pairings))
376 self.assertEqual(pairings[0].value["oauth"], oauth_data)
377 self.assertEqual(pairings[0].value["server"], hostname)
378 self.assertEqual(pairings[0].value["pairing_identifier"], remote_uuid)
379
380 for i, row in enumerate(pairings):
381- couchdb_io.remove_pairing(row.id, i == 1, ctx=test_environment.test_context)
382+ couchdb_io.remove_pairing(
383+ row.id, i == 1, ctx=test_environment.test_context)
384
385- pairings = list(couchdb_io.get_pairings(ctx=test_environment.test_context))
386+ pairings = list(
387+ couchdb_io.get_pairings(ctx=test_environment.test_context))
388 self.assertEqual(0, len(pairings))
389
390-
391 def test_get_database_names_replicatable_bad_server(self):
392+ """Test get database names from the wrong url."""
393 hostname = "test.desktopcouch.example.com"
394 try:
395 socket.gethostbyname(hostname)
396@@ -136,39 +164,26 @@
397 pass
398
399 def test_get_database_names_replicatable(self):
400- names = couchdb_io.get_database_names_replicatable(uri=URI, ctx=test_environment.test_context)
401+ """Test get the names of replicatable databases."""
402+ names = couchdb_io.get_database_names_replicatable(
403+ uri=URI, ctx=test_environment.test_context)
404 self.assertFalse('management' in names)
405 self.assertTrue('foo' in names)
406 self.assertFalse('bar' in names, names) # is excluded
407
408 def test_get_my_host_unique_id(self):
409- got = couchdb_io.get_my_host_unique_id(uri=URI, ctx=test_environment.test_context)
410- again = couchdb_io.get_my_host_unique_id(uri=URI, ctx=test_environment.test_context)
411+ """Test get the unique id of the host record."""
412+ got = couchdb_io.get_my_host_unique_id(
413+ uri=URI, ctx=test_environment.test_context)
414+ again = couchdb_io.get_my_host_unique_id(
415+ uri=URI, ctx=test_environment.test_context)
416 self.assertEquals(len(got), 1)
417 self.assertEquals(got, again)
418
419 def test_mkuri(self):
420+ """Test creating a URI."""
421 uri = couchdb_io.mkuri(
422 'fnord.org', 55241, has_ssl=True, path='a/b/c',
423 auth_pair=('f o o', 'b=a=r'))
424 self.assertEquals(
425 'https://f%20o%20o:b%3Da%3Dr@fnord.org:55241/a/b/c', uri)
426-
427- def Xtest_replication_good(self):
428- pass
429-
430- def Xtest_replication_no_oauth_remote(self):
431- pass
432-
433- def Xtest_replication_bad_oauth_remote(self):
434- pass
435-
436- def Xtest_replication_no_oauth_local(self):
437- pass
438-
439- def Xtest_replication_bad_oauth_local(self):
440- pass
441-
442-
443-if __name__ == "__main__":
444- unittest.main()

Subscribers

People subscribed via source and target branches