]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - test/test_journal.rb
journal: more postgres tests
[user/henk/code/ruby/rbot.git] / test / test_journal.rb
1 $:.unshift File.join(File.dirname(__FILE__), '../lib')
2
3 require 'test/unit'
4 require 'rbot/ircbot'
5 require 'rbot/journal'
6 require 'rbot/journal/postgres.rb'
7
8 DAY=60*60*24
9
10 class JournalMessageTest < Test::Unit::TestCase
11
12   include Irc::Bot::Journal
13
14   def test_get
15     m = JournalMessage.create('foo', {'bar': 42, 'baz': nil, 'qux': {'quxx': 23}})
16     assert_equal(42, m.get('bar'))
17     assert_raise ArgumentError do
18       m.get('nope')
19     end
20     assert_nil(m.get('nope', nil))
21     assert_nil(m.get('baz'))
22     assert_equal(23, m.get('qux.quxx'))
23   end
24
25 end
26
27 class QueryTest < Test::Unit::TestCase
28
29   include Irc::Bot::Journal
30
31   def test_define
32
33     q = Query.define do
34       id 'foo'
35       id 'bar', 'baz'
36       topic 'log.irc.*'
37       topic 'log.core', 'baz'
38       timestamp from: Time.now, to: Time.now + 60 * 10
39       payload 'action': :privmsg, 'alice': 'bob'
40       payload 'channel': '#rbot'
41       payload 'foo.bar': 'baz'
42     end
43     assert_equal(['foo', 'bar', 'baz'], q.id)
44     assert_equal(['log.irc.*', 'log.core', 'baz'], q.topic)
45     assert_equal([:from, :to], q.timestamp.keys)
46     assert_equal(Time, q.timestamp[:to].class)
47     assert_equal(Time, q.timestamp[:from].class)
48     assert_equal({
49       'action': :privmsg, 'alice': 'bob',
50       'channel': '#rbot',
51       'foo.bar': 'baz'
52     }, q.payload)
53
54   end
55
56   def test_topic_matches
57     q = Query.define do
58       topic 'foo'
59     end
60     assert_true(q.topic_matches?('foo'))
61     assert_false(q.topic_matches?('bar'))
62     assert_false(q.topic_matches?('foo.bar'))
63
64     q = Query.define do
65       topic 'foo.bar'
66     end
67     assert_false(q.topic_matches?('foo'))
68     assert_false(q.topic_matches?('bar'))
69     assert_true(q.topic_matches?('foo.bar'))
70
71     q = Query.define do
72       topic 'foo.*'
73     end
74     assert_false(q.topic_matches?('foo'))
75     assert_false(q.topic_matches?('bar'))
76     assert_true(q.topic_matches?('foo.bar'))
77     assert_true(q.topic_matches?('foo.baz'))
78
79     q = Query.define do
80       topic '*.bar'
81     end
82     assert_false(q.topic_matches?('foo'))
83     assert_false(q.topic_matches?('bar'))
84     assert_true(q.topic_matches?('foo.bar'))
85     assert_true(q.topic_matches?('bar.bar'))
86     assert_false(q.topic_matches?('foo.foo'))
87
88     q = Query.define do
89       topic '*.*'
90     end
91     assert_false(q.topic_matches?('foo'))
92     assert_true(q.topic_matches?('foo.bar'))
93
94     q = Query.define do
95       topic 'foo'
96       topic 'bar'
97       topic 'baz.alice.bob.*.foo'
98     end
99     assert_true(q.topic_matches?('foo'))
100     assert_true(q.topic_matches?('bar'))
101     assert_true(q.topic_matches?('baz.alice.bob.asdf.foo'))
102     assert_false(q.topic_matches?('baz.alice.bob..foo'))
103
104   end
105   def test_matches
106     q = Query.define do
107       #id 'foo', 'bar'
108       topic 'log.irc.*', 'log.core'
109       timestamp from: Time.now - DAY, to: Time.now + DAY
110       payload 'action': 'privmsg', 'foo.bar': 'baz'
111     end
112     assert_true(q.matches? JournalMessage.create('log.irc.raw', {'action' => 'privmsg'}))
113     assert_false(q.matches? JournalMessage.create('baz', {}))
114     assert_true(q.matches? JournalMessage.create('log.core', {foo: {bar: 'baz'}}))
115
116     # tests timestamp from/to:
117     assert_true(q.matches? JournalMessage.new(
118       id: 'foo',
119       topic: 'log.core',
120       timestamp: Time.now,
121       payload: {action: 'privmsg'}))
122     assert_false(q.matches? JournalMessage.new(
123       id: 'foo',
124       topic: 'log.core',
125       timestamp: Time.now - DAY*3,
126       payload: {action: 'privmsg'}))
127     assert_false(q.matches? JournalMessage.new(
128       id: 'foo',
129       topic: 'log.core',
130       timestamp: Time.now + DAY*3,
131       payload: {action: 'privmsg'}))
132   end
133
134 end
135
136 class JournalBrokerTest < Test::Unit::TestCase
137
138   include Irc::Bot::Journal
139
140   def test_publish
141     received = []
142     journal = JournalBroker.new(consumer: Proc.new { |message|
143       received << message
144     })
145
146     # publish some messages:
147     journal.publish 'log.irc',
148       source: 'alice', message: '<3 pg'
149     journal.publish 'log.irc',
150       source: 'bob', message: 'mysql > pg'
151     journal.publish 'log.irc',
152       source: 'alice', target: 'bob', action: :kick
153
154     # wait for messages to be consumed:
155     sleep 0.1
156     assert_equal(3, received.length)
157   end
158
159   def test_subscribe
160     received = []
161     journal = JournalBroker.new
162
163     # subscribe to messages:
164     sub = journal.subscribe(Query.define { topic 'foo' }) do |message|
165       received << message
166     end
167
168     # publish some messages:
169     journal.publish 'foo', {}
170     journal.publish 'bar', {}
171     journal.publish 'foo', {}
172
173     # wait for messages to be consumed:
174     sleep 0.1
175     assert_equal(2, received.length)
176
177     received.clear
178
179     journal.publish 'foo', {}
180     sleep 0.1
181     sub.cancel
182     journal.publish 'foo', {}
183     sleep 0.1
184     assert_equal(1, received.length)
185   end
186
187 end
188
189 class JournalStoragePostgresTest < Test::Unit::TestCase
190
191   include Irc::Bot::Journal
192
193   def setup
194     @storage = Storage::PostgresStorage.new(
195       uri: ENV['DB_URI'] || 'postgresql://localhost/rbot_journal',
196       drop: true)
197   end
198
199   def teardown
200     @storage.drop
201   end
202
203   def test_query_to_sql
204     q = Query.define do
205       id 'foo'
206       id 'bar', 'baz'
207       topic 'log.irc.*'
208       topic 'log.core', 'baz'
209       timestamp from: Time.now, to: Time.now + 60 * 10
210       payload 'action': :privmsg, 'alice': 'bob'
211       payload 'channel': '#rbot'
212       payload 'foo.bar': 'baz'
213     end
214     sql = @storage.query_to_sql(q)
215     assert_equal("(id = $1 OR id = $2 OR id = $3) AND (topic ILIKE $4 OR topic ILIKE $5 OR topic ILIKE $6) AND (timestamp >= $7 AND timestamp <= $8) AND (payload->>'action' = $9 OR payload->>'alice' = $10 OR payload->>'channel' = $11 OR payload->'foo'->>'bar' = $12)", sql[0])
216     q = Query.define do
217       id 'foo'
218     end
219     assert_equal('(id = $1)', @storage.query_to_sql(q)[0])
220     q = Query.define do
221       topic 'foo.*.bar'
222     end
223     assert_equal('(topic ILIKE $1)', @storage.query_to_sql(q)[0])
224     assert_equal(['foo.%.bar'], @storage.query_to_sql(q)[1])
225   end
226
227   def test_operations
228     # insertion
229     m = JournalMessage.create('log.core', {foo: {bar: 'baz'}})
230     @storage.insert(m)
231
232     # query by id
233     res = @storage.find(Query.define { id m.id })
234     assert_equal(1, res.length)
235     assert_equal(m, res.first)
236
237     # check timestamp was returned correctly:
238     assert_equal(m.timestamp.strftime('%Y-%m-%d %H:%M:%S%z'),
239                  res.first.timestamp.strftime('%Y-%m-%d %H:%M:%S%z'))
240
241     # check if payload was returned correctly:
242     assert_equal({'foo' => {'bar' => 'baz'}}, res.first.payload)
243
244     # query by topic
245     assert_equal(m, @storage.find(Query.define { topic('log.core') }).first)
246     assert_equal(m, @storage.find(Query.define { topic('log.*') }).first)
247     assert_equal(m, @storage.find(Query.define { topic('*.*') }).first)
248
249     # query by timestamp range
250     assert_equal(1, @storage.find(Query.define {
251       timestamp(from: Time.now-DAY, to: Time.now+DAY) }).length)
252     assert_equal(0, @storage.find(Query.define {
253       timestamp(from: Time.now-DAY*2, to: Time.now-DAY) }).length)
254
255     # query by payload
256     res = @storage.find(Query.define { payload('foo.bar' => 'baz') })
257     assert_equal(m, res.first)
258     res = @storage.find(Query.define { payload('foo.bar' => 'x') })
259     assert_true(res.empty?)
260
261     # without arguments: find and count
262     assert_equal(1, @storage.count)
263     assert_equal(m, @storage.find.first)
264   end
265
266   def test_operations_multiple
267     # test operations on multiple messages
268     # insert a bunch:
269     @storage.insert(JournalMessage.create('test.topic', {name: 'one'}))
270     @storage.insert(JournalMessage.create('test.topic', {name: 'two'}))
271     @storage.insert(JournalMessage.create('test.topic', {name: 'three'}))
272     @storage.insert(JournalMessage.create('archived.topic', {name: 'four'},
273                                           timestamp: Time.now - DAY*100))
274     @storage.insert(JournalMessage.create('complex', {name: 'five', country: {
275       name: 'Italy'
276     }}))
277     @storage.insert(JournalMessage.create('complex', {name: 'six', country: {
278       name: 'Austria'
279     }}))
280
281
282   end
283
284   def test_journal
285     received = []
286     # this journal persists messages in the test storage:
287     journal = JournalBroker.new(storage: @storage)
288
289
290   end
291
292 end
293