Merge lp:~cmiller/desktopcouch/defer-dbus-until-after-plugins into lp:desktopcouch
- defer-dbus-until-after-plugins
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Chad Miller |
Approved revision: | 281 |
Merged at revision: | 274 |
Proposed branch: | lp:~cmiller/desktopcouch/defer-dbus-until-after-plugins |
Merge into: | lp:desktopcouch |
Diff against target: |
718 lines (+243/-135) 10 files modified
desktopcouch/application/local_files.py (+3/-1) desktopcouch/application/platform/windows/tests/test_base_dirs.py (+2/-2) desktopcouch/application/plugins/__init__.py (+13/-3) desktopcouch/application/plugins/tests/test_plugins.py (+3/-1) desktopcouch/application/plugins/tests/test_ubuntuone_pairing.py (+33/-8) desktopcouch/application/plugins/ubuntuone_pairing.py (+62/-43) desktopcouch/application/service.py (+27/-4) desktopcouch/application/tests/test_service.py (+88/-62) desktopcouch/records/tests/test_mocked_server.py (+4/-3) desktopcouch/recordtypes/contacts/tests/test_view.py (+8/-8) |
To merge this branch: | bzr merge lp:~cmiller/desktopcouch/defer-dbus-until-after-plugins |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
dobey (community) | Approve | ||
Natalia Bidart (community) | Approve | ||
Review via email: mp+57589@code.launchpad.net |
Commit message
Add ability for plugins to delay DBus service activation until they are finished processing. Make ubuntuone_pairing plugin use this. (LP: #760236)
Description of the change
Natalia Bidart (nataliabidart) wrote : | # |
Also, a test run failed with:
=======
[FAIL]
Traceback (most recent call last):
File "/usr/lib/
testMethod()
File "/home/
self.
File "/usr/lib/
assertion_
File "/usr/lib/
raise self.failureExc
exceptions.
desktopcouch.
Natalia Bidart (nataliabidart) wrote : | # |
I can't reproduce the test failure in trunk, so it seems like something in this branch is generating that failure?
Natalia Bidart (nataliabidart) wrote : | # |
Chad,
I re ran the test suite several times and the test case will not fail anymore, looks like a transient error (that should be debugged but I don't want to delay your branch anymore).
I'm approving so you can move on, but please fix all the (new) "Reimport" errors from pylint before landing.
Thanks!
Chad Miller (cmiller) wrote : | # |
I've run this test in a loop more than 1200 times, and can't reproduce it. We've seen something like it on trunk before, though.
dobey (dobey) : | # |
Chad Miller (cmiller) wrote : | # |
The attempt to merge lp:~cmiller/desktopcouch/defer-dbus-until-after-plugins into lp:desktopcouch failed. Below is the output from the failed tests.
Apache CouchDB has started, time to relax.
Browse your desktop CouchDB at file://
desktopcouch.
TestMigration
test_
test_
test_
test_
TestRegistration
test_
desktopcouch.
TestCouchdbIo
test_
test_
test_mkuri ... [OK]
test_
test_
test_
desktopcouch.
TestNetworkIO
test_
desktopcouch.
TestGnomeKeyring
test_
test_
test_
test_
test_
test_
test_
desktopcouch.
BaseDirsTestCase
test_
test_
test_
test_
desktopcouch.
TestKeyring
test_
test_
test_
test_
desktopcouch.
TestLoadPlugins
test_
desktopcouch.
TestUbuntoneP
test_
...
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The attempt to merge lp:~cmiller/desktopcouch/defer-dbus-until-after-plugins into lp:desktopcouch failed. Below is the output from the failed tests.
Apache CouchDB has started, time to relax.
Browse your desktop CouchDB at file://
desktopcouch.
TestMigration
test_
test_
test_
test_
TestRegistration
test_
desktopcouch.
TestUbuntoneP
test_
test_
test_
test_
TestUbuntuOne
test_
test_
test_
desktopcouch.
TestLoadPlugins
test_
desktopcouch.
TestNetworkIO
test_
desktopcouch.
TestCouchdbIo
test_
test_
test_mkuri ... [OK]
test_
test_
test_
desktopcouch.
TestService
test_
test_
test_
File "/usr/lib/
testMethod()
File "/usr/lib/
result = test_method()
File "/home/
put_
exceptions.
[ERROR]
desktopcouch.
TestKeyringIn
test_with_auth ... [OK]
test_
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The attempt to merge lp:~cmiller/desktopcouch/defer-dbus-until-after-plugins into lp:desktopcouch failed. Below is the output from the failed tests.
Apache CouchDB has started, time to relax.
Browse your desktop CouchDB at file://
desktopcouch.
TestMigration
test_
test_
test_
test_
TestRegistration
test_
desktopcouch.
TestUbuntoneP
test_
test_
test_
test_
TestUbuntuOne
test_
test_
test_
desktopcouch.
TestLoadPlugins
test_
desktopcouch.
TestNetworkIO
test_
desktopcouch.
TestCouchdbIo
test_
test_
test_mkuri ... [OK]
test_
test_
test_
desktopcouch.
TestService
test_
test_
test_
File "/usr/lib/
testMethod()
File "/usr/lib/
result = test_method()
File "/home/
put_
exceptions.
[ERROR]
desktopcouch.
TestKeyringIn
test_with_auth ... [OK]
test_
dobey (dobey) wrote : | # |
Something very weird is going on in the tests here. This change seems to fix it here:
=== modified file 'desktopcouch/
--- desktopcouch/
+++ desktopcouch/
@@ -136,11 +136,13 @@ class TestUbuntuOnePl
+ old_pair = uone.pair_
+ uone.pair_
def test_got_
"""Check that pairing is called for Ubuntu One."""
@@ -148,11 +150,13 @@ class TestUbuntuOnePl
+ old_pair = uone.pair_
+ uone.pair_
def test_listen_
"""Test that listening to credentails works."""
- 281. By Chad Miller
-
Save and restore the monkey-patched pair_with_ubuntuone function. I have no idea how this was working, but tests fail elsewhere.
Preview Diff
1 | === modified file 'desktopcouch/application/local_files.py' | |||
2 | --- desktopcouch/application/local_files.py 2011-04-08 20:31:22 +0000 | |||
3 | +++ desktopcouch/application/local_files.py 2011-04-15 21:47:33 +0000 | |||
4 | @@ -83,9 +83,11 @@ | |||
5 | 83 | if "-hashed-" in bookmark_file_contents: | 83 | if "-hashed-" in bookmark_file_contents: |
6 | 84 | raise ValueError("Basic-auth cred lost.") | 84 | raise ValueError("Basic-auth cred lost.") |
7 | 85 | # trial run, check sanity. | 85 | # trial run, check sanity. |
8 | 86 | # pylint: disable=W0106 | ||
9 | 86 | re.findall( | 87 | re.findall( |
10 | 87 | "<!-- !!([^!]+)!!([^!]+)!! -->", | 88 | "<!-- !!([^!]+)!!([^!]+)!! -->", |
11 | 88 | bookmark_file_contents)[-1] | 89 | bookmark_file_contents)[-1] |
12 | 90 | # pylint: enable=W0106 | ||
13 | 89 | self._fill_from_file(self.file_name_used) | 91 | self._fill_from_file(self.file_name_used) |
14 | 90 | return | 92 | return |
15 | 91 | except (IOError, ValueError, IndexError): | 93 | except (IOError, ValueError, IndexError): |
16 | @@ -196,7 +198,7 @@ | |||
17 | 196 | for d in (run_dir, db_dir, config_dir): | 198 | for d in (run_dir, db_dir, config_dir): |
18 | 197 | try: | 199 | try: |
19 | 198 | os.makedirs(d, 0700) | 200 | os.makedirs(d, 0700) |
21 | 199 | except OSError, ex: | 201 | except OSError: |
22 | 200 | pass # Probably that it already exists. | 202 | pass # Probably that it already exists. |
23 | 201 | try: | 203 | try: |
24 | 202 | os.chmod(d, 0700) | 204 | os.chmod(d, 0700) |
25 | 203 | 205 | ||
26 | === modified file 'desktopcouch/application/platform/windows/tests/test_base_dirs.py' | |||
27 | --- desktopcouch/application/platform/windows/tests/test_base_dirs.py 2011-01-25 17:58:49 +0000 | |||
28 | +++ desktopcouch/application/platform/windows/tests/test_base_dirs.py 2011-04-15 21:47:33 +0000 | |||
29 | @@ -63,7 +63,7 @@ | |||
30 | 63 | self.mocker.result('hive') | 63 | self.mocker.result('hive') |
31 | 64 | self._winreg.OpenKey('hive', SHELL_FOLDERS_KEY) | 64 | self._winreg.OpenKey('hive', SHELL_FOLDERS_KEY) |
32 | 65 | self.mocker.result('key') | 65 | self.mocker.result('key') |
34 | 66 | self._winreg.QueryInfoKey('key')[1] | 66 | self._winreg.QueryInfoKey('key')[1] # pylint: disable=W0106 |
35 | 67 | self.mocker.throw(Exception('Cannot get info.')) | 67 | self.mocker.throw(Exception('Cannot get info.')) |
36 | 68 | self._winreg.CloseKey('hive') | 68 | self._winreg.CloseKey('hive') |
37 | 69 | self._winreg.CloseKey('key') | 69 | self._winreg.CloseKey('key') |
38 | @@ -78,7 +78,7 @@ | |||
39 | 78 | self.mocker.result('hive') | 78 | self.mocker.result('hive') |
40 | 79 | self._winreg.OpenKey('hive', SHELL_FOLDERS_KEY) | 79 | self._winreg.OpenKey('hive', SHELL_FOLDERS_KEY) |
41 | 80 | self.mocker.result('key') | 80 | self.mocker.result('key') |
43 | 81 | self._winreg.QueryInfoKey('key')[1] | 81 | self._winreg.QueryInfoKey('key')[1] # pylint: disable=W0106 |
44 | 82 | self.mocker.result(1) | 82 | self.mocker.result(1) |
45 | 83 | self._winreg.EnumValue('key', 0) | 83 | self._winreg.EnumValue('key', 0) |
46 | 84 | self.mocker.result(('AppData', 'path', 1)) | 84 | self.mocker.result(('AppData', 'path', 1)) |
47 | 85 | 85 | ||
48 | === modified file 'desktopcouch/application/plugins/__init__.py' | |||
49 | --- desktopcouch/application/plugins/__init__.py 2011-01-24 14:30:34 +0000 | |||
50 | +++ desktopcouch/application/plugins/__init__.py 2011-04-15 21:47:33 +0000 | |||
51 | @@ -19,8 +19,18 @@ | |||
52 | 19 | DESKTOPCOUCH_PLUGIN_PATHS = [os.path.join(os.path.dirname(__file__))] | 19 | DESKTOPCOUCH_PLUGIN_PATHS = [os.path.join(os.path.dirname(__file__))] |
53 | 20 | 20 | ||
54 | 21 | 21 | ||
57 | 22 | def load_plugins(couchdb_port): | 22 | def load_plugins(couchdb_port, blocking_semaphores, gobject): |
58 | 23 | """Load the desktopcouch application plug-ins.""" | 23 | """Load the desktopcouch application plug-ins. |
59 | 24 | |||
60 | 25 | The blocking_semaphores set is OPTIONALLY mutated by any plugin to signal | ||
61 | 26 | that the service is not ready until a plugin has finished its asynchronous | ||
62 | 27 | operations. Plugins may add a distinguishing object to the set, and it | ||
63 | 28 | must remove what it adds when it is finished. | ||
64 | 29 | |||
65 | 30 | couchdb -- the integer of the port number of the running couchdb | ||
66 | 31 | blocking_semaphores -- the set() of semaphores, which we will mutate | ||
67 | 32 | gobject -- the mainloop module. always 'gobject' except when testing. | ||
68 | 33 | """ | ||
69 | 24 | plugin_names = set() | 34 | plugin_names = set() |
70 | 25 | for path in DESKTOPCOUCH_PLUGIN_PATHS: | 35 | for path in DESKTOPCOUCH_PLUGIN_PATHS: |
71 | 26 | try: | 36 | try: |
72 | @@ -37,6 +47,6 @@ | |||
73 | 37 | modpath = name.replace(os.path.sep, '.')[:-3] | 47 | modpath = name.replace(os.path.sep, '.')[:-3] |
74 | 38 | try: | 48 | try: |
75 | 39 | plugin = __import__(modpath, None, None, ['']) | 49 | plugin = __import__(modpath, None, None, ['']) |
77 | 40 | plugin.plugin_init(couchdb_port) | 50 | plugin.plugin_init(couchdb_port, blocking_semaphores, gobject) |
78 | 41 | except (ImportError, AttributeError): | 51 | except (ImportError, AttributeError): |
79 | 42 | logging.warning('Failed to load plug-in: %s', modpath) | 52 | logging.warning('Failed to load plug-in: %s', modpath) |
80 | 43 | 53 | ||
81 | === modified file 'desktopcouch/application/plugins/tests/test_plugins.py' | |||
82 | --- desktopcouch/application/plugins/tests/test_plugins.py 2011-01-26 22:32:59 +0000 | |||
83 | +++ desktopcouch/application/plugins/tests/test_plugins.py 2011-04-15 21:47:33 +0000 | |||
84 | @@ -28,6 +28,8 @@ | |||
85 | 28 | 28 | ||
86 | 29 | def setUp(self): | 29 | def setUp(self): |
87 | 30 | self.couchdb_port = platform.find_port(ctx=test_context) | 30 | self.couchdb_port = platform.find_port(ctx=test_context) |
88 | 31 | self.blockers = set() | ||
89 | 32 | self.gobject = None | ||
90 | 31 | 33 | ||
91 | 32 | def test_load_plugins(self): | 34 | def test_load_plugins(self): |
92 | 33 | """Test that plug-ins are loaded correctly.""" | 35 | """Test that plug-ins are loaded correctly.""" |
93 | @@ -44,7 +46,7 @@ | |||
94 | 44 | self._imported = modname | 46 | self._imported = modname |
95 | 45 | old_import = __import__ | 47 | old_import = __import__ |
96 | 46 | __builtins__['__import__'] = _fake_import | 48 | __builtins__['__import__'] = _fake_import |
98 | 47 | plugins.load_plugins(self.couchdb_port) | 49 | plugins.load_plugins(self.couchdb_port, self.blockers, self.gobject) |
99 | 48 | __builtins__['__import__'] = old_import | 50 | __builtins__['__import__'] = old_import |
100 | 49 | plugins.DESKTOPCOUCH_PLUGIN_PATHS = old_paths | 51 | plugins.DESKTOPCOUCH_PLUGIN_PATHS = old_paths |
101 | 50 | self.assertEqual(self._imported, __name__) | 52 | self.assertEqual(self._imported, __name__) |
102 | 51 | 53 | ||
103 | === modified file 'desktopcouch/application/plugins/tests/test_ubuntuone_pairing.py' | |||
104 | --- desktopcouch/application/plugins/tests/test_ubuntuone_pairing.py 2011-01-26 22:32:59 +0000 | |||
105 | +++ desktopcouch/application/plugins/tests/test_ubuntuone_pairing.py 2011-04-15 21:47:33 +0000 | |||
106 | @@ -38,9 +38,11 @@ | |||
107 | 38 | self.couchdb_port = self.mocker.mock() | 38 | self.couchdb_port = self.mocker.mock() |
108 | 39 | self.put_static_paired_service = self.mocker.mock() | 39 | self.put_static_paired_service = self.mocker.mock() |
109 | 40 | self.database_class = self.mocker.mock() | 40 | self.database_class = self.mocker.mock() |
110 | 41 | self.blocking_semaphores = self.mocker.mock() | ||
111 | 41 | 42 | ||
112 | 42 | def test_pair_with_ubuntuone_no_view(self): | 43 | def test_pair_with_ubuntuone_no_view(self): |
113 | 43 | """Test that when the view is not present it is indeed created.""" | 44 | """Test that when the view is not present it is indeed created.""" |
114 | 45 | # plugin_init adds name to blocking semaphores, but we remove it. | ||
115 | 44 | self.couchdb.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD) | 46 | self.couchdb.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD) |
116 | 45 | self.mocker.result(False) | 47 | self.mocker.result(False) |
117 | 46 | # we are interested in the fact that the view is created | 48 | # we are interested in the fact that the view is created |
118 | @@ -50,8 +52,11 @@ | |||
119 | 50 | self.couchdb.execute_view(U1_PAIR_RECORD, U1_PAIR_RECORD) | 52 | self.couchdb.execute_view(U1_PAIR_RECORD, U1_PAIR_RECORD) |
120 | 51 | self.mocker.result([]) | 53 | self.mocker.result([]) |
121 | 52 | self.put_static_paired_service(None, 'ubuntuone', ctx=None, uri=ANY) | 54 | self.put_static_paired_service(None, 'ubuntuone', ctx=None, uri=ANY) |
122 | 55 | self.blocking_semaphores.discard(ANY) | ||
123 | 56 | |||
124 | 53 | self.mocker.replay() | 57 | self.mocker.replay() |
126 | 54 | pair_with_ubuntuone(self.couchdb_port, self.couchdb, | 58 | pair_with_ubuntuone(self.couchdb_port, self.blocking_semaphores, |
127 | 59 | management_db=self.couchdb, | ||
128 | 55 | db_class=self.database_class, | 60 | db_class=self.database_class, |
129 | 56 | put_service_fn=self.put_static_paired_service) | 61 | put_service_fn=self.put_static_paired_service) |
130 | 57 | self.mocker.verify() | 62 | self.mocker.verify() |
131 | @@ -59,21 +64,27 @@ | |||
132 | 59 | def test_pair_with_ubuntuone_no_record(self): | 64 | def test_pair_with_ubuntuone_no_record(self): |
133 | 60 | """Ensure pairing is not done when there are no records .""" | 65 | """Ensure pairing is not done when there are no records .""" |
134 | 61 | # execute the steps when no records are returned by the view | 66 | # execute the steps when no records are returned by the view |
135 | 67 | # plugin_init adds name to blocking semaphores, but we remove it. | ||
136 | 62 | self.couchdb.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD) | 68 | self.couchdb.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD) |
137 | 63 | self.mocker.result(True) | 69 | self.mocker.result(True) |
138 | 64 | self.couchdb.execute_view(U1_PAIR_RECORD, U1_PAIR_RECORD) | 70 | self.couchdb.execute_view(U1_PAIR_RECORD, U1_PAIR_RECORD) |
139 | 65 | self.mocker.result([]) | 71 | self.mocker.result([]) |
140 | 66 | self.put_static_paired_service(None, 'ubuntuone', ctx=None, uri=ANY) | 72 | self.put_static_paired_service(None, 'ubuntuone', ctx=None, uri=ANY) |
141 | 73 | self.blocking_semaphores.discard(ANY) | ||
142 | 74 | |||
143 | 67 | self.mocker.replay() | 75 | self.mocker.replay() |
145 | 68 | pair_with_ubuntuone(self.couchdb_port, self.couchdb, | 76 | pair_with_ubuntuone(self.couchdb_port, self.blocking_semaphores, |
146 | 77 | management_db=self.couchdb, | ||
147 | 69 | db_class=self.database_class, | 78 | db_class=self.database_class, |
148 | 70 | put_service_fn=self.put_static_paired_service) | 79 | put_service_fn=self.put_static_paired_service) |
149 | 80 | |||
150 | 71 | self.mocker.verify() | 81 | self.mocker.verify() |
151 | 72 | 82 | ||
152 | 73 | def test_pair_with_ubuntuone_user_deleted_record(self): | 83 | def test_pair_with_ubuntuone_user_deleted_record(self): |
153 | 74 | """Ensure pairing is not done when the user explicitly removed it.""" | 84 | """Ensure pairing is not done when the user explicitly removed it.""" |
154 | 75 | # create a mock object that will be the result from the view | 85 | # create a mock object that will be the result from the view |
155 | 76 | row = self.mocker.mock() | 86 | row = self.mocker.mock() |
156 | 87 | # plugin_init adds name to blocking semaphores, but we remove it. | ||
157 | 77 | # execute the steps to show that the user deleted the record | 88 | # execute the steps to show that the user deleted the record |
158 | 78 | self.couchdb.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD) | 89 | self.couchdb.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD) |
159 | 79 | self.mocker.result(True) | 90 | self.mocker.result(True) |
160 | @@ -82,14 +93,18 @@ | |||
161 | 82 | # FIXME does this do anything? | 93 | # FIXME does this do anything? |
162 | 83 | _ = row.value | 94 | _ = row.value |
163 | 84 | self.mocker.result(1) | 95 | self.mocker.result(1) |
164 | 96 | self.blocking_semaphores.discard(ANY) | ||
165 | 97 | |||
166 | 85 | self.mocker.replay() | 98 | self.mocker.replay() |
168 | 86 | pair_with_ubuntuone(self.couchdb_port, self.couchdb) | 99 | pair_with_ubuntuone(self.couchdb_port, self.blocking_semaphores, |
169 | 100 | management_db=self.couchdb) | ||
170 | 87 | self.mocker.verify() | 101 | self.mocker.verify() |
171 | 88 | 102 | ||
172 | 89 | def test_pair_with_ubuntuone_record_present(self): | 103 | def test_pair_with_ubuntuone_record_present(self): |
173 | 90 | """Ensure pairing is not done when the record is already present.""" | 104 | """Ensure pairing is not done when the record is already present.""" |
174 | 91 | # create a mock object that will be the result from the view | 105 | # create a mock object that will be the result from the view |
175 | 92 | row = self.mocker.mock() | 106 | row = self.mocker.mock() |
176 | 107 | # plugin_init adds name to blocking semaphores, but we remove it. | ||
177 | 93 | # execute the steps to show that the user deleted the record | 108 | # execute the steps to show that the user deleted the record |
178 | 94 | self.couchdb.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD) | 109 | self.couchdb.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD) |
179 | 95 | self.mocker.result(True) | 110 | self.mocker.result(True) |
180 | @@ -98,8 +113,11 @@ | |||
181 | 98 | # FIXME does this do anything? | 113 | # FIXME does this do anything? |
182 | 99 | _ = row.value | 114 | _ = row.value |
183 | 100 | self.mocker.result(0) | 115 | self.mocker.result(0) |
184 | 116 | self.blocking_semaphores.discard(ANY) | ||
185 | 117 | |||
186 | 101 | self.mocker.replay() | 118 | self.mocker.replay() |
188 | 102 | pair_with_ubuntuone(self.couchdb_port, self.couchdb) | 119 | pair_with_ubuntuone(self.couchdb_port, self.blocking_semaphores, |
189 | 120 | management_db=self.couchdb) | ||
190 | 103 | self.mocker.verify() | 121 | self.mocker.verify() |
191 | 104 | 122 | ||
192 | 105 | 123 | ||
193 | @@ -109,6 +127,7 @@ | |||
194 | 109 | def setUp(self): | 127 | def setUp(self): |
195 | 110 | super(TestUbuntuOnePlugin, self).setUp() | 128 | super(TestUbuntuOnePlugin, self).setUp() |
196 | 111 | self.couchdb_port = self.mocker.mock() | 129 | self.couchdb_port = self.mocker.mock() |
197 | 130 | self.blocking_semaphores = self.mocker.mock() | ||
198 | 112 | self.called = False | 131 | self.called = False |
199 | 113 | 132 | ||
200 | 114 | def test_got_new_credentials_other(self): | 133 | def test_got_new_credentials_other(self): |
201 | @@ -117,21 +136,27 @@ | |||
202 | 117 | """Fail if we get called.""" | 136 | """Fail if we get called.""" |
203 | 118 | self.called = True | 137 | self.called = True |
204 | 119 | 138 | ||
205 | 139 | saved_pair = uone.pair_with_ubuntuone | ||
206 | 120 | uone.pair_with_ubuntuone = fail_if_called | 140 | uone.pair_with_ubuntuone = fail_if_called |
208 | 121 | uone.got_new_credentials(self.couchdb_port, 'Unknown App', {}) | 141 | uone.got_new_credentials(self.couchdb_port, self.blocking_semaphores, |
209 | 142 | 'Unknown App', {}) | ||
210 | 122 | self.assertFalse(self.called, 'pair_with_ubuntuone was not expected.') | 143 | self.assertFalse(self.called, 'pair_with_ubuntuone was not expected.') |
211 | 123 | self.mocker.replay() | 144 | self.mocker.replay() |
212 | 145 | uone.pair_with_ubuntuone = saved_pair | ||
213 | 124 | 146 | ||
214 | 125 | def test_got_new_credentials(self): | 147 | def test_got_new_credentials(self): |
215 | 126 | """Check that pairing is called for Ubuntu One.""" | 148 | """Check that pairing is called for Ubuntu One.""" |
217 | 127 | def pass_if_called(db=None): | 149 | def pass_if_called(db=None, semaphores=None): |
218 | 128 | """Check that pair_with_ubuntuone was called.""" | 150 | """Check that pair_with_ubuntuone was called.""" |
219 | 129 | self.called = True | 151 | self.called = True |
220 | 130 | 152 | ||
221 | 153 | saved_pair = uone.pair_with_ubuntuone | ||
222 | 131 | uone.pair_with_ubuntuone = pass_if_called | 154 | uone.pair_with_ubuntuone = pass_if_called |
224 | 132 | uone.got_new_credentials(self.couchdb_port, uone.APP_NAME, {}) | 155 | uone.got_new_credentials(self.couchdb_port, self.blocking_semaphores, |
225 | 156 | uone.APP_NAME, {}) | ||
226 | 133 | self.assertTrue(self.called, 'pair_with_ubuntuone was not called.') | 157 | self.assertTrue(self.called, 'pair_with_ubuntuone was not called.') |
227 | 134 | self.mocker.replay() | 158 | self.mocker.replay() |
228 | 159 | uone.pair_with_ubuntuone = saved_pair | ||
229 | 135 | 160 | ||
230 | 136 | def test_listen_to_dbus(self): | 161 | def test_listen_to_dbus(self): |
231 | 137 | """Test that listening to credentails works.""" | 162 | """Test that listening to credentails works.""" |
232 | @@ -161,4 +186,4 @@ | |||
233 | 161 | 186 | ||
234 | 162 | self.mocker.replay() | 187 | self.mocker.replay() |
235 | 163 | 188 | ||
237 | 164 | uone.listen_to_dbus(self.couchdb_port) | 189 | uone.listen_to_dbus(self.couchdb_port, self.blocking_semaphores) |
238 | 165 | 190 | ||
239 | === modified file 'desktopcouch/application/plugins/ubuntuone_pairing.py' | |||
240 | --- desktopcouch/application/plugins/ubuntuone_pairing.py 2011-01-27 19:25:23 +0000 | |||
241 | +++ desktopcouch/application/plugins/ubuntuone_pairing.py 2011-04-15 21:47:33 +0000 | |||
242 | @@ -24,6 +24,7 @@ | |||
243 | 24 | from desktopcouch.application.server import DesktopDatabase | 24 | from desktopcouch.application.server import DesktopDatabase |
244 | 25 | from ubuntuone.clientdefs import APP_NAME | 25 | from ubuntuone.clientdefs import APP_NAME |
245 | 26 | 26 | ||
246 | 27 | PLUGIN_NAME = __name__ | ||
247 | 27 | U1_PAIR_RECORD = "ubuntu_one_pair_record" | 28 | U1_PAIR_RECORD = "ubuntu_one_pair_record" |
248 | 28 | MAP_JS = """function(doc) { | 29 | MAP_JS = """function(doc) { |
249 | 29 | if (doc.service_name == "ubuntuone") { | 30 | if (doc.service_name == "ubuntuone") { |
250 | @@ -33,48 +34,57 @@ | |||
251 | 33 | """ | 34 | """ |
252 | 34 | 35 | ||
253 | 35 | 36 | ||
255 | 36 | def pair_with_ubuntuone(couchdb_port, management_db=None, | 37 | def pair_with_ubuntuone(couchdb_port, blocking_semaphores, |
256 | 38 | management_db=None, | ||
257 | 37 | db_class=DesktopDatabase, | 39 | db_class=DesktopDatabase, |
258 | 38 | put_service_fn=put_static_paired_service): | 40 | put_service_fn=put_static_paired_service): |
259 | 39 | """Adds a pairing record with ubuntu one when needed.""" | 41 | """Adds a pairing record with ubuntu one when needed.""" |
292 | 40 | # Use explicit uri so that we do not access dbus service. | 42 | try: |
293 | 41 | uri = "http://localhost:%s" % (couchdb_port,) | 43 | # Use explicit uri so that we do not access dbus service. |
294 | 42 | if not management_db: | 44 | uri = "http://localhost:%s" % (couchdb_port,) |
295 | 43 | management_db = db_class("management", uri=uri, create=True, ctx=None) | 45 | if not management_db: |
296 | 44 | # we indeed have credentials to add to the pairing records | 46 | management_db = db_class("management", uri=uri, create=True, |
297 | 45 | # but first we ensure that the required view is present | 47 | ctx=None) |
298 | 46 | if not management_db.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD): | 48 | # we indeed have credentials to add to the pairing records |
299 | 47 | management_db.add_view( | 49 | # but first we ensure that the required view is present |
300 | 48 | U1_PAIR_RECORD, MAP_JS, design_doc=U1_PAIR_RECORD) | 50 | if not management_db.view_exists(U1_PAIR_RECORD, U1_PAIR_RECORD): |
301 | 49 | view_results = management_db.execute_view(U1_PAIR_RECORD, U1_PAIR_RECORD) | 51 | management_db.add_view( |
302 | 50 | pairing_found = False | 52 | U1_PAIR_RECORD, MAP_JS, design_doc=U1_PAIR_RECORD) |
303 | 51 | # Results should contain either one row or no rows | 53 | view_results = management_db.execute_view(U1_PAIR_RECORD, |
304 | 52 | # If there is one row, its value will be 0, meaning that there is | 54 | U1_PAIR_RECORD) |
305 | 53 | # already an Ubuntu One pairing record, or 1, meaning that there | 55 | pairing_found = False |
306 | 54 | # was an Ubuntu One pairing record but it has since been unpaired | 56 | # Results should contain either one row or no rows |
307 | 55 | # Only create a new record if there is not one already. Specifically, | 57 | # If there is one row, its value will be 0, meaning that there is |
308 | 56 | # do not add the record if there is a deleted one, as this means | 58 | # already an Ubuntu One pairing record, or 1, meaning that there |
309 | 57 | # that the user explicitly unpaired it! | 59 | # was an Ubuntu One pairing record but it has since been unpaired |
310 | 58 | for row in view_results: | 60 | # Only create a new record if there is not one already. Specifically, |
311 | 59 | pairing_found = True | 61 | # do not add the record if there is a deleted one, as this means |
312 | 60 | if row.value == 1: | 62 | # that the user explicitly unpaired it! |
313 | 61 | logging.debug("Not adding desktopcouch pairing since the user " | 63 | for row in view_results: |
314 | 62 | "has explicitly unpaired with Ubuntu One") | 64 | pairing_found = True |
315 | 63 | else: | 65 | if row.value == 1: |
316 | 64 | logging.debug("Not adding desktopcouch pairing since we are " | 66 | logging.debug("Not adding desktopcouch pairing since the user " |
317 | 65 | "already paired") | 67 | "has explicitly unpaired with Ubuntu One") |
318 | 66 | if not pairing_found: | 68 | else: |
319 | 67 | put_service_fn(None, "ubuntuone", uri=uri, ctx=None) | 69 | logging.debug("Not adding desktopcouch pairing since we are " |
320 | 68 | logging.debug("Pairing desktopcouch with Ubuntu One") | 70 | "already paired") |
321 | 69 | 71 | if not pairing_found: | |
322 | 70 | 72 | put_service_fn(None, "ubuntuone", uri=uri, ctx=None) | |
323 | 71 | def got_new_credentials(couchdb_port, app_name, credentials): | 73 | logging.debug("Pairing desktopcouch with Ubuntu One") |
324 | 74 | |||
325 | 75 | finally: | ||
326 | 76 | logging.info("removing semaphore for %s", PLUGIN_NAME) | ||
327 | 77 | blocking_semaphores.discard(PLUGIN_NAME) | ||
328 | 78 | |||
329 | 79 | |||
330 | 80 | def got_new_credentials(couchdb_port, blocking_semaphores, | ||
331 | 81 | app_name, credentials): | ||
332 | 72 | """Pair with Ubuntu One when we get the new credentials.""" | 82 | """Pair with Ubuntu One when we get the new credentials.""" |
333 | 73 | if app_name == APP_NAME: | 83 | if app_name == APP_NAME: |
338 | 74 | pair_with_ubuntuone(couchdb_port) | 84 | pair_with_ubuntuone(couchdb_port, blocking_semaphores) |
339 | 75 | 85 | ||
340 | 76 | 86 | ||
341 | 77 | def listen_to_dbus(couchdb_port): | 87 | def listen_to_dbus(couchdb_port, blocking_semaphores): |
342 | 78 | """Set up the signal handler on D-Bus for Ubuntu One pairing.""" | 88 | """Set up the signal handler on D-Bus for Ubuntu One pairing.""" |
343 | 79 | import dbus | 89 | import dbus |
344 | 80 | bus = dbus.SessionBus() | 90 | bus = dbus.SessionBus() |
345 | @@ -82,7 +92,9 @@ | |||
346 | 82 | try: | 92 | try: |
347 | 83 | import ubuntu_sso | 93 | import ubuntu_sso |
348 | 84 | 94 | ||
350 | 85 | receiver = lambda *args: got_new_credentials(couchdb_port, *args) | 95 | receiver = lambda *args: \ |
351 | 96 | got_new_credentials(couchdb_port, blocking_semaphores, | ||
352 | 97 | *args) | ||
353 | 86 | 98 | ||
354 | 87 | iface = ubuntu_sso.DBUS_CREDENTIALS_IFACE | 99 | iface = ubuntu_sso.DBUS_CREDENTIALS_IFACE |
355 | 88 | bus.add_signal_receiver(handler_function=receiver, | 100 | bus.add_signal_receiver(handler_function=receiver, |
356 | @@ -96,13 +108,20 @@ | |||
357 | 96 | sso_backend.find_credentials(APP_NAME, {}) | 108 | sso_backend.find_credentials(APP_NAME, {}) |
358 | 97 | except ImportError: | 109 | except ImportError: |
359 | 98 | logging.info('Ubuntu SSO is not available.') | 110 | logging.info('Ubuntu SSO is not available.') |
363 | 99 | 111 | blocking_semaphores.discard(PLUGIN_NAME) | |
364 | 100 | 112 | ||
365 | 101 | def plugin_init(couchdb_port): | 113 | |
366 | 114 | def plugin_init(couchdb_port, blocking_semaphores, gobject): | ||
367 | 102 | """Set up the signal handler for pairing with Ubuntu One.""" | 115 | """Set up the signal handler for pairing with Ubuntu One.""" |
368 | 103 | logging.info('Loaded Ubuntu One extension for desktopcouch.') | 116 | logging.info('Loaded Ubuntu One extension for desktopcouch.') |
369 | 104 | if sys.platform == 'win32': | 117 | if sys.platform == 'win32': |
370 | 105 | logging.warning('Windows support for Ubuntu One is not yet ready.') | 118 | logging.warning('Windows support for Ubuntu One is not yet ready.') |
371 | 106 | else: | 119 | else: |
374 | 107 | import gobject | 120 | |
375 | 108 | gobject.idle_add(listen_to_dbus, couchdb_port) | 121 | # Signal that we are critical for desktopcouch usage, and the server |
376 | 122 | # must not begin until we are finished. We are responsible for | ||
377 | 123 | # removing this item from the list. | ||
378 | 124 | logging.info("adding %s to to blocking semaphore list", PLUGIN_NAME) | ||
379 | 125 | blocking_semaphores.add(PLUGIN_NAME) | ||
380 | 126 | |||
381 | 127 | gobject.idle_add(listen_to_dbus, couchdb_port, blocking_semaphores) | ||
382 | 109 | 128 | ||
383 | === modified file 'desktopcouch/application/service.py' | |||
384 | --- desktopcouch/application/service.py 2011-01-31 21:49:22 +0000 | |||
385 | +++ desktopcouch/application/service.py 2011-04-15 21:47:33 +0000 | |||
386 | @@ -39,6 +39,7 @@ | |||
387 | 39 | import logging | 39 | import logging |
388 | 40 | import logging.handlers | 40 | import logging.handlers |
389 | 41 | import signal | 41 | import signal |
390 | 42 | import gobject | ||
391 | 42 | 43 | ||
392 | 43 | from desktopcouch.application import local_files | 44 | from desktopcouch.application import local_files |
393 | 44 | from desktopcouch.application import replication | 45 | from desktopcouch.application import replication |
394 | @@ -84,7 +85,8 @@ | |||
395 | 84 | replication_actions=replication, | 85 | replication_actions=replication, |
396 | 85 | advertiser_factory=PortAdvertiser, set_logging=set_up_logging, | 86 | advertiser_factory=PortAdvertiser, set_logging=set_up_logging, |
397 | 86 | fork=os.fork, nice=os.nice, | 87 | fork=os.fork, nice=os.nice, |
399 | 87 | kill=os.kill, sleep=time.sleep): | 88 | kill=os.kill, sleep=time.sleep, set_type=set, |
400 | 89 | gobject_module=gobject): | ||
401 | 88 | self._mainloop = main_loop | 90 | self._mainloop = main_loop |
402 | 89 | self._pid_finder = pid_finder | 91 | self._pid_finder = pid_finder |
403 | 90 | self._port_finder = port_finder | 92 | self._port_finder = port_finder |
404 | @@ -97,6 +99,8 @@ | |||
405 | 97 | self._nice = nice | 99 | self._nice = nice |
406 | 98 | self._kill = kill | 100 | self._kill = kill |
407 | 99 | self._sleep = sleep | 101 | self._sleep = sleep |
408 | 102 | self._set = set_type | ||
409 | 103 | self._gobject = gobject_module | ||
410 | 100 | # pylint: enable=C0301 | 104 | # pylint: enable=C0301 |
411 | 101 | 105 | ||
412 | 102 | def _start_replicator_main(self, couchdb_port): | 106 | def _start_replicator_main(self, couchdb_port): |
413 | @@ -112,11 +116,30 @@ | |||
414 | 112 | replication.tear_down(*replication_runtime) | 116 | replication.tear_down(*replication_runtime) |
415 | 113 | 117 | ||
416 | 114 | def _start_server_main(self, couchdb_port): | 118 | def _start_server_main(self, couchdb_port): |
419 | 115 | """Start server.""" | 119 | """Start server answering DBus calls, and run plugins first.""" |
420 | 116 | self._advertiser_factory(self._mainloop.stop, self._ctx) | 120 | |
421 | 121 | def if_all_semaphores_cleared(blocking_semaphores, | ||
422 | 122 | func, *args, **kwargs): | ||
423 | 123 | """Run a function if no semaphores exist, else try later.""" | ||
424 | 124 | if blocking_semaphores: | ||
425 | 125 | return True # Make idle call try us again. | ||
426 | 126 | else: | ||
427 | 127 | func(*args, **kwargs) | ||
428 | 128 | return False # Handled! | ||
429 | 129 | |||
430 | 130 | blocking_semaphores = self._set() | ||
431 | 131 | load_plugins(couchdb_port, blocking_semaphores, self._gobject) | ||
432 | 132 | |||
433 | 133 | # Answering queries on DBus signals that we are ready for users | ||
434 | 134 | # to connect. We mustn't begin that until every plugin has a chance | ||
435 | 135 | # to run to completion if it needs it. | ||
436 | 136 | self._gobject.idle_add(if_all_semaphores_cleared, blocking_semaphores, | ||
437 | 137 | self._advertiser_factory, | ||
438 | 138 | self._mainloop.stop, | ||
439 | 139 | self._ctx) | ||
440 | 140 | |||
441 | 117 | logging.debug("starting dbus main loop") | 141 | logging.debug("starting dbus main loop") |
442 | 118 | try: | 142 | try: |
443 | 119 | load_plugins(couchdb_port) | ||
444 | 120 | self._mainloop.run() | 143 | self._mainloop.run() |
445 | 121 | finally: | 144 | finally: |
446 | 122 | logging.debug("ending dbus main loop") | 145 | logging.debug("ending dbus main loop") |
447 | 123 | 146 | ||
448 | === modified file 'desktopcouch/application/tests/test_service.py' | |||
449 | --- desktopcouch/application/tests/test_service.py 2011-01-27 19:25:23 +0000 | |||
450 | +++ desktopcouch/application/tests/test_service.py 2011-04-15 21:47:33 +0000 | |||
451 | @@ -37,6 +37,8 @@ | |||
452 | 37 | self._replication = self.mocker.mock() | 37 | self._replication = self.mocker.mock() |
453 | 38 | self._advertiser = self.mocker.mock() | 38 | self._advertiser = self.mocker.mock() |
454 | 39 | self._resources = self.mocker.mock() | 39 | self._resources = self.mocker.mock() |
455 | 40 | self._set = self.mocker.mock() | ||
456 | 41 | self._gobject = self.mocker.mock() | ||
457 | 40 | self._service = DesktopcouchService(self._mainloop, | 42 | self._service = DesktopcouchService(self._mainloop, |
458 | 41 | pid_finder=self._pid_finder, | 43 | pid_finder=self._pid_finder, |
459 | 42 | port_finder=self._port_finder, | 44 | port_finder=self._port_finder, |
460 | @@ -48,65 +50,89 @@ | |||
461 | 48 | fork=self._fork, | 50 | fork=self._fork, |
462 | 49 | nice=self._nice, | 51 | nice=self._nice, |
463 | 50 | kill=self._kill, | 52 | kill=self._kill, |
523 | 51 | sleep=self._sleep) | 53 | sleep=self._sleep, |
524 | 52 | 54 | set_type=self._set, | |
525 | 53 | def test_start_new_desktopcouch_no_extensions(self): | 55 | gobject_module=self._gobject) |
526 | 54 | """Test that desktopcouch is started. | 56 | |
527 | 55 | 57 | self.gobject_idle_task_list = list() | |
528 | 56 | We test that when the pid cannot be found we ensure | 58 | |
529 | 57 | that the desktopcouch instance is started and that the | 59 | def test_start_new_desktopcouch_with_plugins(self): |
530 | 58 | start as the dbus service, | 60 | """Test that desktopcouch is started. |
531 | 59 | """ | 61 | |
532 | 60 | self._pid_finder(start_if_not_running=False, ctx=self._ctx) | 62 | We test that when the pid cannot be found we ensure |
533 | 61 | self.mocker.result(None) | 63 | that the desktopcouch instance is started and that the |
534 | 62 | self._pid_finder(start_if_not_running=True, ctx=self._ctx) | 64 | start as the dbus service, |
535 | 63 | self.mocker.result(self._pid_result) | 65 | """ |
536 | 64 | self._port_finder(pid=self._pid_result, ctx=self._ctx) | 66 | self._pid_finder(start_if_not_running=False, ctx=self._ctx) |
537 | 65 | self.mocker.result(self._port_result) | 67 | self.mocker.result(None) |
538 | 66 | self._fork() | 68 | self._pid_finder(start_if_not_running=True, ctx=self._ctx) |
539 | 67 | self.mocker.result(234) | 69 | self.mocker.result(self._pid_result) |
540 | 68 | self._fork() | 70 | self._port_finder(pid=self._pid_result, ctx=self._ctx) |
541 | 69 | self.mocker.result(234) | 71 | self.mocker.result(self._port_result) |
542 | 70 | # XXX: call this? | 72 | self._fork() |
543 | 71 | self._mainloop.stop # pylint: disable=W0104 | 73 | self.mocker.result(234) # We are parent |
544 | 72 | self.mocker.result(ANY) | 74 | self._fork() |
545 | 73 | self._advertiser(ANY, self._ctx) | 75 | self.mocker.result(234) # We are parent |
546 | 74 | self._mainloop.run() | 76 | |
547 | 75 | self._stop_couchdb(ctx=self._ctx) | 77 | # plugins load |
548 | 76 | self._kill(234, signal.SIGTERM) | 78 | semaphores = self.mocker.mock() |
549 | 77 | self._sleep(1) | 79 | self._set() |
550 | 78 | self._kill(234, signal.SIGKILL) | 80 | self.mocker.result(semaphores) |
551 | 79 | self.mocker.replay() | 81 | |
552 | 80 | self._service.start() | 82 | self._mainloop.stop # pylint: disable=W0104 |
553 | 81 | 83 | self.mocker.result(ANY) | |
554 | 82 | def test_start_new_desktopcouch_extensions(self): | 84 | |
555 | 83 | """Test that desktopcouch is started. | 85 | self._gobject.idle_add(ANY, self._port_result, semaphores) |
556 | 84 | 86 | self._gobject.idle_add(ANY, semaphores, self._advertiser, ANY, | |
557 | 85 | We test that when the pid cannot be found we ensure | 87 | self._ctx) |
558 | 86 | that the desktopcouch instance is started and that the | 88 | |
559 | 87 | start as the dbus service, | 89 | self._mainloop.run() |
560 | 88 | """ | 90 | |
561 | 89 | self._pid_finder(start_if_not_running=False, ctx=self._ctx) | 91 | # Tasks are added to the mainloop's idle queue. With that^ |
562 | 90 | self.mocker.result(None) | 92 | # mainloop.run, they'd be called. Simulate their call. |
563 | 91 | self._pid_finder(start_if_not_running=True, ctx=self._ctx) | 93 | |
564 | 92 | self.mocker.result(self._pid_result) | 94 | # Idle loop to add plugins calls a plugin. ubuntuone_pairing |
565 | 93 | self._port_finder(pid=self._pid_result, ctx=self._ctx) | 95 | semaphores.add(ANY) # A plugin asserts it must be completed. |
566 | 94 | self.mocker.result(self._port_result) | 96 | |
567 | 95 | self._fork() | 97 | # Idle loop calls plugin for ubuntuone_pairing, which fires up DBus |
568 | 96 | self.mocker.result(234) | 98 | # client to get credentials from ubuntu-login app. When that returns, |
569 | 97 | self._fork() | 99 | # it calls got_new_credentials, which calls pair_with_ubuntuone. |
570 | 98 | self.mocker.result(234) | 100 | |
571 | 99 | # XXX: call this? | 101 | # Mock call to pair_with_ubuntuone |
572 | 100 | self._mainloop.stop # pylint: disable=W0104 | 102 | management_db = self.mocker.mock() |
573 | 101 | self.mocker.result(ANY) | 103 | put_service_fn = self.mocker.mock() |
574 | 102 | self._advertiser(ANY, self._ctx) | 104 | |
575 | 103 | self._mainloop.run() | 105 | bool(management_db) |
576 | 104 | self._stop_couchdb(ctx=self._ctx) | 106 | self.mocker.result(True) |
577 | 105 | self._kill(234, signal.SIGTERM) | 107 | |
578 | 106 | self._sleep(1) | 108 | management_db.view_exists(ANY, ANY) |
579 | 107 | self._kill(234, signal.SIGKILL) | 109 | self.mocker.result(False) |
580 | 108 | self.mocker.replay() | 110 | management_db.add_view(ANY, ANY, design_doc=ANY) |
581 | 109 | self._service.start() | 111 | |
582 | 112 | row = self.mocker.mock() | ||
583 | 113 | management_db.execute_view(ANY, ANY) | ||
584 | 114 | self.mocker.result([row]) | ||
585 | 115 | |||
586 | 116 | row.value # pylint: disable=W0104 | ||
587 | 117 | self.mocker.result(1) | ||
588 | 118 | |||
589 | 119 | semaphores.discard(ANY) | ||
590 | 120 | |||
591 | 121 | # and then dbus service is ready to answer queries. | ||
592 | 122 | |||
593 | 123 | self._stop_couchdb(ctx=self._ctx) | ||
594 | 124 | self._kill(234, signal.SIGTERM) | ||
595 | 125 | self._sleep(1) | ||
596 | 126 | self._kill(234, signal.SIGKILL) | ||
597 | 127 | |||
598 | 128 | self.mocker.replay() | ||
599 | 129 | |||
600 | 130 | self._service.start() | ||
601 | 131 | # Manually do what dbus idle-loop would do. | ||
602 | 132 | import desktopcouch.application.plugins.ubuntuone_pairing as u_p | ||
603 | 133 | u_p.pair_with_ubuntuone(self._port_result, semaphores, | ||
604 | 134 | management_db=management_db, | ||
605 | 135 | put_service_fn=put_service_fn) | ||
606 | 110 | 136 | ||
607 | 111 | def test_start_desktopcouch_replication(self): | 137 | def test_start_desktopcouch_replication(self): |
608 | 112 | """ Test that the repliciation works. | 138 | """ Test that the repliciation works. |
609 | @@ -119,7 +145,7 @@ | |||
610 | 119 | self._port_finder(pid=self._pid_result, ctx=self._ctx) | 145 | self._port_finder(pid=self._pid_result, ctx=self._ctx) |
611 | 120 | self.mocker.result(self._port_result) | 146 | self.mocker.result(self._port_result) |
612 | 121 | self._fork() | 147 | self._fork() |
614 | 122 | self.mocker.result(0) | 148 | self.mocker.result(0) # We are child process |
615 | 123 | self._nice(10) | 149 | self._nice(10) |
616 | 124 | self._replication.set_up(ANY) | 150 | self._replication.set_up(ANY) |
617 | 125 | self._mainloop.run() | 151 | self._mainloop.run() |
618 | @@ -146,9 +172,9 @@ | |||
619 | 146 | self._port_finder(pid=self._pid_result, ctx=self._ctx) | 172 | self._port_finder(pid=self._pid_result, ctx=self._ctx) |
620 | 147 | self.mocker.result(self._port_result) | 173 | self.mocker.result(self._port_result) |
621 | 148 | self._fork() | 174 | self._fork() |
623 | 149 | self.mocker.result(567) | 175 | self.mocker.result(567) # We are parent process |
624 | 150 | self._fork() | 176 | self._fork() |
626 | 151 | self.mocker.result(0) | 177 | self.mocker.result(0) # We are child process |
627 | 152 | self._sleep(ANY) | 178 | self._sleep(ANY) |
628 | 153 | self._ctx.db_dir # searching for files # pylint: disable=W0104 | 179 | self._ctx.db_dir # searching for files # pylint: disable=W0104 |
629 | 154 | self.mocker.result("/tmp/migration-data/does/not/exist") | 180 | self.mocker.result("/tmp/migration-data/does/not/exist") |
630 | 155 | 181 | ||
631 | === modified file 'desktopcouch/records/tests/test_mocked_server.py' | |||
632 | --- desktopcouch/records/tests/test_mocked_server.py 2011-04-04 18:54:26 +0000 | |||
633 | +++ desktopcouch/records/tests/test_mocked_server.py 2011-04-15 21:47:33 +0000 | |||
634 | @@ -61,6 +61,7 @@ | |||
635 | 61 | 61 | ||
636 | 62 | 62 | ||
637 | 63 | class TestMockedCouchDatabaseCreateStates(MockerTestCase): | 63 | class TestMockedCouchDatabaseCreateStates(MockerTestCase): |
638 | 64 | """Mocked Couch Database tests for create= flag states.""" | ||
639 | 64 | def setUp(self): | 65 | def setUp(self): |
640 | 65 | """Set up tests.""" | 66 | """Set up tests.""" |
641 | 66 | super(TestMockedCouchDatabaseCreateStates, self).setUp() | 67 | super(TestMockedCouchDatabaseCreateStates, self).setUp() |
642 | @@ -85,7 +86,7 @@ | |||
643 | 85 | self.mocker.result({'update_seq': []}) | 86 | self.mocker.result({'update_seq': []}) |
644 | 86 | 87 | ||
645 | 87 | self.mocker.replay() | 88 | self.mocker.replay() |
647 | 88 | database = DesktopDatabase(self.dbname, uri=self.uri, | 89 | DesktopDatabase(self.dbname, uri=self.uri, |
648 | 89 | record_factory=self.record_factory, create=True, | 90 | record_factory=self.record_factory, create=True, |
649 | 90 | server_class=self.server_class, | 91 | server_class=self.server_class, |
650 | 91 | oauth_tokens=self.oauth_tokens, ctx=self.ctx) | 92 | oauth_tokens=self.oauth_tokens, ctx=self.ctx) |
651 | @@ -105,7 +106,7 @@ | |||
652 | 105 | info["update_seq"] | 106 | info["update_seq"] |
653 | 106 | self.mocker.result({}) | 107 | self.mocker.result({}) |
654 | 107 | self.mocker.replay() | 108 | self.mocker.replay() |
656 | 108 | database = DesktopDatabase(self.dbname, uri=self.uri, | 109 | DesktopDatabase(self.dbname, uri=self.uri, |
657 | 109 | record_factory=self.record_factory, create=True, | 110 | record_factory=self.record_factory, create=True, |
658 | 110 | server_class=self.server_class, | 111 | server_class=self.server_class, |
659 | 111 | oauth_tokens=self.oauth_tokens, ctx=self.ctx) | 112 | oauth_tokens=self.oauth_tokens, ctx=self.ctx) |
660 | @@ -140,7 +141,7 @@ | |||
661 | 140 | self.mocker.result({}) | 141 | self.mocker.result({}) |
662 | 141 | 142 | ||
663 | 142 | self.mocker.replay() | 143 | self.mocker.replay() |
665 | 143 | database = DesktopDatabase(self.dbname, uri=self.uri, | 144 | DesktopDatabase(self.dbname, uri=self.uri, |
666 | 144 | record_factory=self.record_factory, create=False, | 145 | record_factory=self.record_factory, create=False, |
667 | 145 | server_class=self.server_class, | 146 | server_class=self.server_class, |
668 | 146 | oauth_tokens=self.oauth_tokens, ctx=self.ctx) | 147 | oauth_tokens=self.oauth_tokens, ctx=self.ctx) |
669 | 147 | 148 | ||
670 | === modified file 'desktopcouch/recordtypes/contacts/tests/test_view.py' | |||
671 | --- desktopcouch/recordtypes/contacts/tests/test_view.py 2011-01-05 22:21:04 +0000 | |||
672 | +++ desktopcouch/recordtypes/contacts/tests/test_view.py 2011-04-15 21:47:33 +0000 | |||
673 | @@ -280,29 +280,29 @@ | |||
674 | 280 | 280 | ||
675 | 281 | contacts = list( | 281 | contacts = list( |
676 | 282 | view.find_contacts_starting(self.db, first_name="Frances")) | 282 | view.find_contacts_starting(self.db, first_name="Frances")) |
678 | 283 | self.assertEqual(len(contacts), 1) | 283 | self.assertEqual(len(contacts), 1, "Length of 1. %s" % (contacts,)) |
679 | 284 | 284 | ||
680 | 285 | contacts = list( | 285 | contacts = list( |
681 | 286 | view.find_contacts_starting(self.db, birth_date="1918")) | 286 | view.find_contacts_starting(self.db, birth_date="1918")) |
683 | 287 | self.assertEqual(len(contacts), 1) | 287 | self.assertEqual(len(contacts), 1, "Length of 1. %s" % (contacts,)) |
684 | 288 | 288 | ||
685 | 289 | contacts = list( | 289 | contacts = list( |
686 | 290 | view.find_contacts_starting(self.db, birth_date="1918-08")) | 290 | view.find_contacts_starting(self.db, birth_date="1918-08")) |
688 | 291 | self.assertEqual(len(contacts), 1) | 291 | self.assertEqual(len(contacts), 1, "Length of 1. %s" % (contacts,)) |
689 | 292 | 292 | ||
690 | 293 | contacts = list( | 293 | contacts = list( |
691 | 294 | view.find_contacts_starting(self.db, wedding_date="1970")) | 294 | view.find_contacts_starting(self.db, wedding_date="1970")) |
693 | 295 | self.assertEqual(len(contacts), 1) | 295 | self.assertEqual(len(contacts), 1, "Length of 1. %s" % (contacts,)) |
694 | 296 | 296 | ||
695 | 297 | contacts = list( | 297 | contacts = list( |
696 | 298 | view.find_contacts_starting( | 298 | view.find_contacts_starting( |
697 | 299 | self.db, email_addressesaddress="blah.example.com")) | 299 | self.db, email_addressesaddress="blah.example.com")) |
699 | 300 | self.assertEqual(len(contacts), 1) | 300 | self.assertEqual(len(contacts), 1, "Length of 1. %s" % (contacts,)) |
700 | 301 | 301 | ||
701 | 302 | contacts = list( | 302 | contacts = list( |
702 | 303 | view.find_contacts_starting( | 303 | view.find_contacts_starting( |
703 | 304 | self.db, email_addressesaddress="berkeley")) | 304 | self.db, email_addressesaddress="berkeley")) |
705 | 305 | self.assertEqual(len(contacts), 1) | 305 | self.assertEqual(len(contacts), 1, "Length of 1. %s" % (contacts,)) |
706 | 306 | 306 | ||
707 | 307 | contacts = list( | 307 | contacts = list( |
708 | 308 | view.find_contacts_starting(self.db, first_name="random")) | 308 | view.find_contacts_starting(self.db, first_name="random")) |
709 | @@ -317,7 +317,7 @@ | |||
710 | 317 | 317 | ||
711 | 318 | contacts = list( | 318 | contacts = list( |
712 | 319 | view.find_contacts_exact(self.db, first_name="Frances")) | 319 | view.find_contacts_exact(self.db, first_name="Frances")) |
714 | 320 | self.assertEqual(len(contacts), 1) | 320 | self.assertEqual(len(contacts), 1, "Length of 1. %s" % (contacts,)) |
715 | 321 | 321 | ||
716 | 322 | contacts = list(view.find_contacts_exact(self.db, birth_date="-08-23")) | 322 | contacts = list(view.find_contacts_exact(self.db, birth_date="-08-23")) |
718 | 323 | self.assertEqual(len(contacts), 1) | 323 | self.assertEqual(len(contacts), 1, "Length of 1. %s" % (contacts,)) |
Can you please make the docstring of load_plugins pep-257 compliant?
Also, I don't understand why you're passing gobject around, is that really needed?