1 $:.unshift File.join(File.dirname(__FILE__), '../lib')
6 require 'rbot/journal/postgres.rb'
10 class JournalMessageTest < Test::Unit::TestCase
12 include Irc::Bot::Journal
15 m = JournalMessage.create('foo', {'bar': 42, 'baz': nil, 'qux': {'quxx': 23}})
16 assert_equal(42, m.get('bar'))
17 assert_raise ArgumentError do
20 assert_nil(m.get('nope', nil))
21 assert_nil(m.get('baz'))
22 assert_equal(23, m.get('qux.quxx'))
27 class QueryTest < Test::Unit::TestCase
29 include Irc::Bot::Journal
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'
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)
49 'action': :privmsg, 'alice': 'bob',
56 def test_topic_matches
60 assert_true(q.topic_matches?('foo'))
61 assert_false(q.topic_matches?('bar'))
62 assert_false(q.topic_matches?('foo.bar'))
67 assert_false(q.topic_matches?('foo'))
68 assert_false(q.topic_matches?('bar'))
69 assert_true(q.topic_matches?('foo.bar'))
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'))
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'))
91 assert_false(q.topic_matches?('foo'))
92 assert_true(q.topic_matches?('foo.bar'))
97 topic 'baz.alice.bob.*.foo'
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'))
108 topic 'log.irc.*', 'log.core'
109 timestamp from: Time.now - DAY, to: Time.now + DAY
110 payload 'action': 'privmsg', 'foo.bar': 'baz'
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'}}))
116 # tests timestamp from/to:
117 assert_true(q.matches? JournalMessage.new(
121 payload: {action: 'privmsg'}))
122 assert_false(q.matches? JournalMessage.new(
125 timestamp: Time.now - DAY*3,
126 payload: {action: 'privmsg'}))
127 assert_false(q.matches? JournalMessage.new(
130 timestamp: Time.now + DAY*3,
131 payload: {action: 'privmsg'}))
136 class JournalBrokerTest < Test::Unit::TestCase
138 include Irc::Bot::Journal
142 journal = JournalBroker.new(consumer: Proc.new { |message|
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
154 # wait for messages to be consumed:
156 assert_equal(3, received.length)
161 journal = JournalBroker.new
163 # subscribe to messages:
164 sub = journal.subscribe(Query.define { topic 'foo' }) do |message|
168 # publish some messages:
169 journal.publish 'foo', {}
170 journal.publish 'bar', {}
171 journal.publish 'foo', {}
173 # wait for messages to be consumed:
175 assert_equal(2, received.length)
179 journal.publish 'foo', {}
182 journal.publish 'foo', {}
184 assert_equal(1, received.length)
189 class JournalStoragePostgresTest < Test::Unit::TestCase
191 include Irc::Bot::Journal
194 @storage = Storage::PostgresStorage.new(
195 uri: ENV['DB_URI'] || 'postgresql://localhost/rbot_journal',
203 def test_query_to_sql
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'
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])
219 assert_equal('(id = $1)', @storage.query_to_sql(q)[0])
223 assert_equal('(topic ILIKE $1)', @storage.query_to_sql(q)[0])
224 assert_equal(['foo.%.bar'], @storage.query_to_sql(q)[1])
229 m = JournalMessage.create('log.core', {foo: {bar: 'baz'}})
233 res = @storage.find(Query.define { id m.id })
234 assert_equal(1, res.length)
235 assert_equal(m, res.first)
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'))
241 # check if payload was returned correctly:
242 assert_equal({'foo' => {'bar' => 'baz'}}, res.first.payload)
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)
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)
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?)
261 # without arguments: find and count
262 assert_equal(1, @storage.count)
263 assert_equal(m, @storage.find.first)
266 def test_operations_multiple
267 # test operations on multiple messages
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: {
277 @storage.insert(JournalMessage.create('complex', {name: 'six', country: {
286 # this journal persists messages in the test storage:
287 journal = JournalBroker.new(storage: @storage)