Merge lp:~thekorn/zeitgeist/fix-595411-remote_testcases into lp:zeitgeist/0.1

Proposed by Markus Korn
Status: Merged
Merged at revision: 1522
Proposed branch: lp:~thekorn/zeitgeist/fix-595411-remote_testcases
Merge into: lp:zeitgeist/0.1
Diff against target: 224 lines (+97/-30)
5 files modified
_zeitgeist/engine/remote.py (+8/-1)
test/engine-extension-test.py (+12/-1)
test/engine-test.py (+10/-0)
test/remote-test.py (+28/-28)
test/testutils.py (+39/-0)
To merge this branch: bzr merge lp:~thekorn/zeitgeist/fix-595411-remote_testcases
Reviewer Review Type Date Requested Status
Siegfried Gevatter Needs Fixing
Seif Lotfy Approve
Review via email: mp+30628@code.launchpad.net

Commit message

- it always restores the values of os.environ if changed to zeitgeist specific values
- make sure to call the test methods (self.assertEquals() etc.) in the main process, and not in a callback, this exposes failures in the test report
- added RemoteTestCase.{deleteEventsAndWait,findRelatedEventsAndWait} in testutils.py
- small API CHANGE of the experimental DeleteEvents()-method: this method now returns a time-tuple describing the intervall where events were changed, otherwise there won't be any direct way to test this method (without using a monitor)

Description of the change

This branch fixes a few issues in our testsuite:
- it always restores the values of os.environ if changed to zeitgeist specific values
- make sure to call the test methods (self.assertEquals() etc.) in the main process, and not in a callback, this exposes failures in the test report
- added RemoteTestCase.{deleteEventsAndWait,findRelatedEventsAndWait} in testutils.py
- small API CHANGE of the experimental DeleteEvents()-method: this method now returns a time-tuple describing the intervall where events were changed, otherwise there won't be any direct way to test this method (without using a monitor).

To post a comment you must log in.
Revision history for this message
Seif Lotfy (seif) wrote :

Code seems clean, some nifty test cases and it works smoothly
Good Job

Revision history for this message
Seif Lotfy (seif) wrote :

Seif Lotfy wrote 24 seconds ago
Code seems clean, some nifty test cases and it works smoothly
Good Job

review: Approve
Revision history for this message
Markus Korn (thekorn) wrote :

ok, merged into lp:zeitgeist as rev 1522, thanks seif for the review

Revision history for this message
Siegfried Gevatter (rainct) wrote :

Good work fixing the tests!

As I said on IRC, I disagree with this chunk:
> small API CHANGE of the experimental DeleteEvents()-method: this method
> now returns a time-tuple describing the intervall where events were

Have you thought about it?

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '_zeitgeist/engine/remote.py'
2--- _zeitgeist/engine/remote.py 2010-07-01 07:34:26 +0000
3+++ _zeitgeist/engine/remote.py 2010-07-22 09:54:43 +0000
4@@ -308,7 +308,7 @@
5
6 @dbus.service.method(constants.DBUS_INTERFACE,
7 in_signature="au",
8- out_signature="",
9+ out_signature="(ii)",
10 sender_keyword="sender")
11 def DeleteEvents(self, event_ids, sender):
12 """Delete a set of events from the log given their IDs
13@@ -324,6 +324,13 @@
14 # have been deleted before or the IDs might even have been invalid.
15 self._notifications.notify_delete(
16 TimeRange(timestamps[0], timestamps[1]), event_ids)
17+ if timestamps is None:
18+ # unknown event id, see doc of delete_events()
19+ return (-1, -1)
20+ timestamp_start, timestamp_end = timestamps
21+ timestamp_start = timestamp_start if timestamp_start is not None else -1
22+ timestamp_end = timestamp_end if timestamp_end is not None else -1
23+ return (timestamp_start, timestamp_end)
24
25 @dbus.service.method(constants.DBUS_INTERFACE, in_signature="", out_signature="")
26 def DeleteLog(self):
27
28=== modified file 'test/engine-extension-test.py'
29--- test/engine-extension-test.py 2010-07-01 07:38:58 +0000
30+++ test/engine-extension-test.py 2010-07-22 09:54:43 +0000
31@@ -32,10 +32,21 @@
32
33 def setUp (self):
34 constants.DATABASE_FILE = ":memory:"
35- constants.DEFAULT_EXTENSIONS = []
36+ self.save_default_ext = os.environ.get("ZEITGEIST_DEFAULT_EXTENSIONS")
37+ self.save_extra_ext = os.environ.get("ZEITGEIST_EXTRA_EXTENSIONS")
38+ os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"] = ""
39+ os.environ["ZEITGEIST_EXTRA_EXTENSIONS"] = ""
40 self.engine = get_engine()
41
42 def tearDown (self):
43+ if self.save_default_ext is not None:
44+ os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"] = self.save_default_ext
45+ else:
46+ del os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"]
47+ if self.save_extra_ext is not None:
48+ os.environ["ZEITGEIST_EXTRA_EXTENSIONS"] = self.save_extra_ext
49+ else:
50+ del os.environ["ZEITGEIST_EXTRA_EXTENSIONS"]
51 self.engine.close()
52 _zeitgeist.engine._engine = None
53
54
55=== modified file 'test/engine-test.py'
56--- test/engine-test.py 2010-07-01 08:04:55 +0000
57+++ test/engine-test.py 2010-07-22 09:54:43 +0000
58@@ -40,6 +40,8 @@
59 class _engineTestClass(unittest.TestCase):
60
61 def setUp (self):
62+ self.save_default_ext = os.environ.get("ZEITGEIST_DEFAULT_EXTENSIONS")
63+ self.save_extra_ext = os.environ.get("ZEITGEIST_EXTRA_EXTENSIONS")
64 os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"] = ""
65 os.environ["ZEITGEIST_EXTRA_EXTENSIONS"] = ""
66 global test_event_1
67@@ -55,6 +57,14 @@
68 self.engine = get_engine()
69
70 def tearDown (self):
71+ if self.save_default_ext is not None:
72+ os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"] = self.save_default_ext
73+ else:
74+ del os.environ["ZEITGEIST_DEFAULT_EXTENSIONS"]
75+ if self.save_extra_ext is not None:
76+ os.environ["ZEITGEIST_EXTRA_EXTENSIONS"] = self.save_extra_ext
77+ else:
78+ del os.environ["ZEITGEIST_EXTRA_EXTENSIONS"]
79 self.engine.close()
80 _zeitgeist.engine._engine = None
81
82
83=== modified file 'test/remote-test.py'
84--- test/remote-test.py 2010-05-15 13:05:14 +0000
85+++ test/remote-test.py 2010-07-22 09:54:43 +0000
86@@ -252,27 +252,28 @@
87 self.assertEquals(1, result.pop())
88
89 def testDeleteEvents(self):
90- result = []
91- mainloop = gobject.MainLoop()
92+ """ delete all events with actor == firefox """
93 events = parse_events("test/data/five_events.js")
94- self.client.insert_events(events)
95+ self.insertEventsAndWait(events)
96
97 event = Event()
98 event.actor = "firefox"
99
100- ids = self.findEventIdsAndWait([event])
101-
102- def callback():
103- ids = self.findEventIdsAndWait([])
104- self.assertEquals(2, len(ids))
105-
106- self.client.delete_events(ids, callback)
107+ # get event ids with actor == firefox
108+ ff_ids = self.findEventIdsAndWait([event])
109+ # delete this events
110+ time_range = self.deleteEventsAndWait(ff_ids)
111+ # got timerange of deleted events
112+ self.assertEquals(2, len(time_range))
113+ # get all events, the one with actor == firefox should
114+ # not be there
115+ ids = self.findEventIdsAndWait([])
116+ self.assertEquals(2, len(ids))
117+ self.assertEquals(0, len(set(ff_ids) & set(ids)))
118
119 def testFindByRandomActorAndGet(self):
120- result = []
121- mainloop = gobject.MainLoop()
122 events = parse_events("test/data/five_events.js")
123- self.client.insert_events(events)
124+ self.insertEventsAndWait(events)
125
126 template = Event.new_for_values(actor="/usr/bliblablu")
127
128@@ -283,35 +284,34 @@
129 self.assertEquals(len(events), 0)
130
131 def testFindRelated(self):
132- mainloop = gobject.MainLoop()
133 events = parse_events("test/data/apriori_events.js")
134- self.client.insert_events(events)
135-
136- def callback(uris):
137- mainloop.quit()
138- self.assertEquals(uris, ["i2", "i1", "i3", "i5"])
139-
140- result = self.client.find_related_uris_for_uris(["i4"], callback, num_events=4, result_type=0)
141- mainloop.run()
142+ self.insertEventsAndWait(events)
143+
144+ uris = self.findRelatedAndWait(["i4"], num_events=4, result_type=0)
145+ self.assertEquals(set(uris), set(["i2", "i1", "i3", "i5"]))
146
147 def testFindEventsForValues(self):
148- mainloop = gobject.MainLoop()
149+ mainloop = gobject.MainLoop() # we don't have an *AndWait-helper method
150+ # for the method we would like to test,
151+ # this is why we need our own local loop
152 events = parse_events("test/data/apriori_events.js")
153- self.client.insert_events(events)
154+ self.insertEventsAndWait(events)
155
156+ result = []
157 def callback(events):
158+ result.extend(events)
159 mainloop.quit()
160- self.assertEquals(len(events), 1)
161- self.assertEquals(events[0].actor, "firefox")
162
163- result = self.client.find_events_for_values(callback, actor="firefox", num_events=1)
164+ self.client.find_events_for_values(callback, actor="firefox", num_events=1)
165 mainloop.run()
166+ self.assertEquals(len(result), 1)
167+ self.assertEquals(result[0].actor, "firefox")
168
169 def testDataSourcesRegistry(self):
170 """ Ensure that the DataSourceRegistry extension is there. If we'd want
171 to do any actual value checking we need to change testutils.py to
172 use a ZEITGEIST_DATA_PATH other than ~/.local/share. """
173- iface = ZeitgeistDBusInterface()
174+ iface = self.client._iface # we know that client._iface is as clean as possible
175 registry = iface.get_extension("DataSourceRegistry", "data_source_registry")
176 registry.GetDataSources()
177
178
179=== modified file 'test/testutils.py'
180--- test/testutils.py 2010-05-15 13:05:14 +0000
181+++ test/testutils.py 2010-07-22 09:54:43 +0000
182@@ -181,3 +181,42 @@
183 self.client.get_events(event_ids, collect_events_and_quit)
184 mainloop.run()
185 return result
186+
187+ def deleteEventsAndWait(self, event_ids):
188+ """
189+ Delete events given by their id and run a loop until the result
190+ containing a timetuple describing the interval of changes is
191+ returned.
192+
193+ This method is basically just a hack to invoke an async method
194+ in a blocking manner.
195+ """
196+ mainloop = gobject.MainLoop()
197+ result = []
198+
199+ def collect_timestamp_and_quit(timestamps):
200+ result.append(timestamps)
201+ mainloop.quit()
202+
203+ self.client.delete_events(event_ids, collect_timestamp_and_quit)
204+ mainloop.run()
205+ return result[0]
206+
207+ def findRelatedAndWait(self, subject_uris, num_events, result_type):
208+ """
209+ Find related subject uris to given uris and return them.
210+
211+ This method is basically just a hack to invoke an async method
212+ in a blocking manner.
213+ """
214+ mainloop = gobject.MainLoop()
215+ result = []
216+
217+ def callback(uri_list):
218+ result.extend(uri_list)
219+ mainloop.quit()
220+
221+ self.client.find_related_uris_for_uris(subject_uris, callback,
222+ num_events=num_events, result_type=result_type)
223+ mainloop.run()
224+ return result

Subscribers

People subscribed via source and target branches