fluent-plugin-droonga 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +40 -0
  5. data/LICENSE.txt +14 -0
  6. data/README.md +18 -0
  7. data/Rakefile +25 -0
  8. data/benchmark/benchmark.rb +123 -0
  9. data/benchmark/utils.rb +243 -0
  10. data/benchmark/watch/benchmark-notify.rb +143 -0
  11. data/benchmark/watch/benchmark-notify.sh +19 -0
  12. data/benchmark/watch/benchmark-publish.rb +120 -0
  13. data/benchmark/watch/benchmark-scan.rb +210 -0
  14. data/benchmark/watch/catalog.json +32 -0
  15. data/benchmark/watch/fluentd.conf +12 -0
  16. data/bin/grn2jsons +85 -0
  17. data/fluent-plugin-droonga.gemspec +41 -0
  18. data/lib/droonga/adapter.rb +156 -0
  19. data/lib/droonga/catalog.rb +153 -0
  20. data/lib/droonga/command_mapper.rb +45 -0
  21. data/lib/droonga/engine.rb +83 -0
  22. data/lib/droonga/executor.rb +289 -0
  23. data/lib/droonga/handler.rb +140 -0
  24. data/lib/droonga/handler_plugin.rb +35 -0
  25. data/lib/droonga/job_queue.rb +83 -0
  26. data/lib/droonga/job_queue_schema.rb +65 -0
  27. data/lib/droonga/logger.rb +34 -0
  28. data/lib/droonga/plugin.rb +41 -0
  29. data/lib/droonga/plugin/adapter/groonga/select.rb +88 -0
  30. data/lib/droonga/plugin/adapter_groonga.rb +40 -0
  31. data/lib/droonga/plugin/handler/groonga/column_create.rb +103 -0
  32. data/lib/droonga/plugin/handler/groonga/table_create.rb +100 -0
  33. data/lib/droonga/plugin/handler_add.rb +44 -0
  34. data/lib/droonga/plugin/handler_forward.rb +70 -0
  35. data/lib/droonga/plugin/handler_groonga.rb +52 -0
  36. data/lib/droonga/plugin/handler_proxy.rb +82 -0
  37. data/lib/droonga/plugin/handler_search.rb +33 -0
  38. data/lib/droonga/plugin/handler_watch.rb +102 -0
  39. data/lib/droonga/proxy.rb +371 -0
  40. data/lib/droonga/searcher.rb +415 -0
  41. data/lib/droonga/server.rb +112 -0
  42. data/lib/droonga/sweeper.rb +42 -0
  43. data/lib/droonga/watch_schema.rb +88 -0
  44. data/lib/droonga/watcher.rb +256 -0
  45. data/lib/droonga/worker.rb +51 -0
  46. data/lib/fluent/plugin/out_droonga.rb +56 -0
  47. data/lib/groonga_command_converter.rb +137 -0
  48. data/sample/cluster/catalog.json +43 -0
  49. data/sample/cluster/fluentd.conf +12 -0
  50. data/sample/fluentd.conf +8 -0
  51. data/test/fixtures/catalog.json +43 -0
  52. data/test/fixtures/document.grn +23 -0
  53. data/test/helper.rb +24 -0
  54. data/test/helper/fixture.rb +28 -0
  55. data/test/helper/sandbox.rb +73 -0
  56. data/test/helper/stub_worker.rb +27 -0
  57. data/test/helper/watch_helper.rb +35 -0
  58. data/test/plugin/adapter/groonga/test_select.rb +176 -0
  59. data/test/plugin/handler/groonga/test_column_create.rb +127 -0
  60. data/test/plugin/handler/groonga/test_table_create.rb +140 -0
  61. data/test/plugin/handler/test_handler_add.rb +135 -0
  62. data/test/plugin/handler/test_handler_groonga.rb +64 -0
  63. data/test/plugin/handler/test_handler_search.rb +512 -0
  64. data/test/plugin/handler/test_handler_watch.rb +168 -0
  65. data/test/run-test.rb +55 -0
  66. data/test/test_adapter.rb +48 -0
  67. data/test/test_catalog.rb +59 -0
  68. data/test/test_command_mapper.rb +44 -0
  69. data/test/test_groonga_command_converter.rb +242 -0
  70. data/test/test_handler.rb +53 -0
  71. data/test/test_job_queue_schema.rb +45 -0
  72. data/test/test_output.rb +99 -0
  73. data/test/test_sweeper.rb +95 -0
  74. data/test/test_watch_schema.rb +57 -0
  75. data/test/test_watcher.rb +336 -0
  76. data/test/test_worker.rb +144 -0
  77. metadata +299 -0
@@ -0,0 +1,53 @@
1
+ # Copyright (C) 2013 droonga project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "droonga/handler"
17
+
18
+ class HandlerTest < Test::Unit::TestCase
19
+ class HandlableTest < self
20
+ class SearchHandler < Droonga::Handler
21
+ command :search
22
+ def search(request)
23
+ :search_response
24
+ end
25
+ end
26
+
27
+ class StatusHandler < Droonga::Handler
28
+ command :status
29
+ def status(request)
30
+ :status_response
31
+ end
32
+ end
33
+
34
+ class Worker
35
+ def context
36
+ nil
37
+ end
38
+ end
39
+
40
+ def setup
41
+ context = Worker.new
42
+ @search_handler = SearchHandler.new(context)
43
+ end
44
+
45
+ def test_true
46
+ assert_true(@search_handler.handlable?(:search))
47
+ end
48
+
49
+ def test_false
50
+ assert_false(@search_handler.handlable?(:status))
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,45 @@
1
+ # Copyright (C) 2013 droonga project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "helper"
17
+
18
+ require "droonga/job_queue_schema"
19
+
20
+ class JobQueueSchemaTest < Test::Unit::TestCase
21
+ def setup
22
+ @database_path = @temporary_directory + "droonga/db"
23
+ @queue_name = "DroongaQueue"
24
+ end
25
+
26
+ def test_ensure_created
27
+ schema = Droonga::JobQueueSchema.new(@database_path.to_s, @queue_name)
28
+
29
+ assert_not_predicate(@database_path, :exist?)
30
+ schema.ensure_created
31
+ assert_predicate(@database_path, :exist?)
32
+
33
+ context = Groonga::Context.new
34
+ dumped_commands = nil
35
+ context.open_database(@database_path.to_s) do |database|
36
+ dumped_commands = Groonga::DatabaseDumper.dump(:context => context,
37
+ :database => database)
38
+ end
39
+ context.close
40
+ assert_equal(<<-SCHEMA, dumped_commands)
41
+ table_create #{@queue_name} TABLE_NO_KEY
42
+ column_create #{@queue_name} message COLUMN_SCALAR Text
43
+ SCHEMA
44
+ end
45
+ end
@@ -0,0 +1,99 @@
1
+ # Copyright (C) 2013 droonga project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "fluent/plugin/out_droonga"
17
+
18
+ module OutputStub
19
+ class Worker
20
+ attr_reader :processed_record
21
+ def initialize(response)
22
+ @response = response
23
+ @processed_record = nil
24
+ end
25
+
26
+ def dispatch(tag, time, record)
27
+ @processed_record = record
28
+ @response
29
+ end
30
+
31
+ def shutdown
32
+ end
33
+ end
34
+
35
+ class Logger
36
+ attr_reader :tag, :options
37
+ attr_reader :posted_tag, :posted_message
38
+ def initialize(tag, options)
39
+ @tag = tag
40
+ @options = options
41
+ end
42
+
43
+ def post(tag, message)
44
+ @posted_tag = tag
45
+ @posted_message = message
46
+ end
47
+
48
+ def close
49
+ end
50
+ end
51
+
52
+ class Output < Fluent::DroongaOutput
53
+ attr_reader :worker
54
+ def initialize(response)
55
+ @response = response
56
+ super()
57
+ end
58
+
59
+ def start
60
+ @worker = Worker.new(@response)
61
+ end
62
+
63
+ def create_logger(tag, options)
64
+ Logger.new(tag, options)
65
+ end
66
+ end
67
+ end
68
+
69
+ class OutputTest < Test::Unit::TestCase
70
+ setup
71
+ def setup_fluent
72
+ Fluent::Test.setup
73
+ end
74
+
75
+ def test_exec
76
+ response = {}
77
+ driver = create_driver("droonga.message", response)
78
+ request = {"hello" => "world"}
79
+ time = Time.parse("2012-10-26T08:45:42Z").to_i
80
+ driver.run do
81
+ driver.emit(request, time)
82
+ end
83
+ assert_equal(request, @output.worker.processed_record)
84
+ end
85
+
86
+ private
87
+ def create_driver(tag, response)
88
+ @output = OutputStub::Output.new(response)
89
+ driver = Fluent::Test::OutputTestDriver.new(@output, tag)
90
+ driver.configure(configuration)
91
+ driver
92
+ end
93
+
94
+ def configuration
95
+ <<-EOC
96
+ n_workers 0
97
+ EOC
98
+ end
99
+ end
@@ -0,0 +1,95 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "droonga/watcher"
19
+ require "droonga/sweeper"
20
+
21
+ class SweeperTest < Test::Unit::TestCase
22
+ include WatchHelper
23
+
24
+ def setup
25
+ setup_database
26
+ setup_schema
27
+ @context = Groonga::Context.default
28
+ @watcher = Droonga::Watcher.new(@context)
29
+ @sweeper = Droonga::Sweeper.new(@context)
30
+ end
31
+
32
+ def teardown
33
+ @watcher = nil
34
+ @sweeper = nil
35
+ teardown_database
36
+ end
37
+
38
+ private
39
+ def subscriber_table
40
+ @context["Subscriber"]
41
+ end
42
+
43
+ def existing_subscribers
44
+ subscriber_table.select.collect(&:_key)
45
+ end
46
+
47
+ public
48
+ class SweepSubscribersTest < self
49
+ NINE_MINUTES_IN_SECONDS = 9 * 60
50
+ TEN_MINUTES_IN_SECONDS = 10 * 60
51
+ ELEVEN_MINUTES_IN_SECONDS = 11 * 60
52
+
53
+ def setup
54
+ super
55
+ @now = Time.now
56
+ setup_expired_subscribers
57
+ end
58
+
59
+ def test_single_term
60
+ @sweeper.sweep_expired_subscribers(:now => @now)
61
+ assert_equal(
62
+ ["subscriber1", "subscriber2"],
63
+ existing_subscribers
64
+ )
65
+ end
66
+
67
+ private
68
+ def setup_expired_subscribers
69
+ request1 = {
70
+ :route => "localhost:23003/output",
71
+ :condition => "たいやき",
72
+ :query => "たいやき".to_json,
73
+ :subscriber => "subscriber1",
74
+ }
75
+ @watcher.subscribe(request1)
76
+ request2 = {
77
+ :route => "localhost:23003/output",
78
+ :condition => "たいやき",
79
+ :query => "たいやき".to_json,
80
+ :subscriber => "subscriber2",
81
+ }
82
+ @watcher.subscribe(request2)
83
+ request3 = {
84
+ :route => "localhost:23003/output",
85
+ :condition => "たいやき",
86
+ :query => "たいやき".to_json,
87
+ :subscriber => "subscriber3",
88
+ }
89
+ @watcher.subscribe(request3)
90
+ subscriber_table["subscriber1"].last_modified = @now - NINE_MINUTES_IN_SECONDS
91
+ subscriber_table["subscriber2"].last_modified = @now - TEN_MINUTES_IN_SECONDS
92
+ subscriber_table["subscriber3"].last_modified = @now - ELEVEN_MINUTES_IN_SECONDS
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,57 @@
1
+ # Copyright (C) 2013 droonga project
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ require "helper"
17
+
18
+ require "droonga/watch_schema"
19
+
20
+ class WatchSchemaTest < Test::Unit::TestCase
21
+ def setup
22
+ @database_path = @temporary_directory + "droonga/watch/db"
23
+ @context = Groonga::Context.default
24
+ FileUtils.mkdir_p(File.dirname(@database_path))
25
+ @context.create_database(@database_path.to_s)
26
+ end
27
+
28
+ def test_ensure_created
29
+ schema = Droonga::WatchSchema.new(@context)
30
+ schema.ensure_created
31
+
32
+ dumped_commands = nil
33
+ @context.open_database(@database_path.to_s) do |database|
34
+ dumped_commands = Groonga::DatabaseDumper.dump(:context => @context,
35
+ :database => database)
36
+ end
37
+ assert_equal(<<-SCHEMA, dumped_commands)
38
+ table_create Keyword TABLE_PAT_KEY|KEY_NORMALIZE --key_type ShortText
39
+
40
+ table_create Query TABLE_HASH_KEY --key_type ShortText
41
+
42
+ table_create Route TABLE_HASH_KEY --key_type ShortText
43
+
44
+ table_create Subscriber TABLE_HASH_KEY --key_type ShortText
45
+ column_create Subscriber last_modified COLUMN_SCALAR Time
46
+
47
+ column_create Query keywords COLUMN_VECTOR Keyword
48
+
49
+ column_create Subscriber route COLUMN_SCALAR Route
50
+ column_create Subscriber subscriptions COLUMN_VECTOR Query
51
+
52
+ column_create Keyword queries COLUMN_INDEX Query keywords
53
+
54
+ column_create Query subscribers COLUMN_INDEX Subscriber subscriptions
55
+ SCHEMA
56
+ end
57
+ end
@@ -0,0 +1,336 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "droonga/watcher"
19
+
20
+ class WatcherTest < Test::Unit::TestCase
21
+ include WatchHelper
22
+
23
+ def setup
24
+ setup_database
25
+ setup_schema
26
+ setup_watcher
27
+ end
28
+
29
+ def teardown
30
+ teardown_watcher
31
+ teardown_database
32
+ end
33
+
34
+ private
35
+ def setup_watcher
36
+ @context = Groonga::Context.default
37
+ @watcher = Droonga::Watcher.new(@context)
38
+ end
39
+
40
+ def teardown_watcher
41
+ @watcher = nil
42
+ end
43
+
44
+ def subscriber_table
45
+ @context["Subscriber"]
46
+ end
47
+
48
+ def query_table
49
+ @context["Query"]
50
+ end
51
+
52
+ def keyword_table
53
+ @context["Keyword"]
54
+ end
55
+
56
+ def existing_subscribers
57
+ subscriber_table.select.collect(&:_key)
58
+ end
59
+
60
+ def existing_queries
61
+ query_table.select.collect(&:_key)
62
+ end
63
+
64
+ def existing_keywords
65
+ keyword_table.select.collect(&:_key)
66
+ end
67
+
68
+ def existing_records
69
+ {
70
+ :subscribers => existing_subscribers,
71
+ :queries => existing_queries,
72
+ :keywords => existing_keywords,
73
+ }
74
+ end
75
+
76
+ def normalize_subscriber(subscriber)
77
+ return nil if subscriber.nil?
78
+ {
79
+ :_key => subscriber._key,
80
+ :subscriptions => subscriber.subscriptions.collect(&:_key),
81
+ :route => subscriber.route._key,
82
+ }
83
+ end
84
+
85
+ def normalize_queries(queries)
86
+ return nil if queries.nil?
87
+ queries.collect do |query|
88
+ normalize_query(query)
89
+ end
90
+ end
91
+
92
+ def normalize_query(query)
93
+ return nil if query.nil?
94
+ {
95
+ :_key => query._key,
96
+ :keywords => query.keywords.collect(&:_key),
97
+ }
98
+ end
99
+
100
+ public
101
+ class SubscribeTest < self
102
+ def test_single_term
103
+ request = {
104
+ :route => "localhost:23003/output",
105
+ :condition => "たいやき",
106
+ :query => "たいやき".to_json,
107
+ :subscriber => "localhost",
108
+ }
109
+ @watcher.subscribe(request)
110
+
111
+ assert_equal(
112
+ {:subscribers => ["localhost"],
113
+ :queries => ["たいやき".to_json],
114
+ :keywords => ["たいやき"]},
115
+ existing_records
116
+ )
117
+ assert_equal(
118
+ {:_key => "localhost",
119
+ :subscriptions => ["たいやき".to_json],
120
+ :route => "localhost:23003/output"},
121
+ normalize_subscriber(subscriber_table.first)
122
+ )
123
+ assert_equal(
124
+ [{:_key => "たいやき".to_json, :keywords => ["たいやき"]}],
125
+ normalize_queries(subscriber_table.first.subscriptions)
126
+ )
127
+ end
128
+
129
+ =begin
130
+ # this test will be activated when condition with multiple tabs is supproted.
131
+ def test_multiple_terms
132
+ request = {
133
+ :route => "localhost:23003/output",
134
+ :condition => "たいやき たこやき",
135
+ :query => "たいやき たこやき".to_json,
136
+ :subscriber => "localhost",
137
+ }
138
+ @watcher.subscribe(request)
139
+
140
+ assert_equal(["localhost"], existing_subscribers)
141
+ assert_equal(
142
+ {:_key => "localhost",
143
+ :subscriptions => ["たいやき たこやき".to_json],
144
+ :route => "localhost:23003/output"},
145
+ normalize_subscriber(subscriber_table.first)
146
+ )
147
+ assert_equal(["たいやき たこやき".to_json], existing_queries)
148
+ assert_equal(["たいやき", "たこやき"], existing_keywords)
149
+ end
150
+ =end
151
+
152
+ def test_same_condition_multiple_times
153
+ request = {
154
+ :route => "localhost:23003/output",
155
+ :condition => "たいやき",
156
+ :query => "たいやき".to_json,
157
+ :subscriber => "localhost",
158
+ }
159
+ @watcher.subscribe(request)
160
+ @watcher.subscribe(request)
161
+ assert_equal(
162
+ {:subscribers => ["localhost"],
163
+ :queries => ["たいやき".to_json],
164
+ :keywords => ["たいやき"]},
165
+ existing_records
166
+ )
167
+ end
168
+
169
+ def test_different_conditions
170
+ request1 = {
171
+ :route => "localhost:23003/output",
172
+ :condition => "たいやき",
173
+ :query => "たいやき".to_json,
174
+ :subscriber => "localhost",
175
+ }
176
+ @watcher.subscribe(request1)
177
+ request2 = {
178
+ :route => "localhost:23003/output",
179
+ :condition => "たこやき",
180
+ :query => "たこやき".to_json,
181
+ :subscriber => "localhost",
182
+ }
183
+ @watcher.subscribe(request2)
184
+ assert_equal(
185
+ {:subscribers => ["localhost"],
186
+ :queries => ["たいやき".to_json, "たこやき".to_json],
187
+ :keywords => ["たいやき", "たこやき"]},
188
+ existing_records
189
+ )
190
+ assert_equal(
191
+ {:_key => "localhost",
192
+ :subscriptions => ["たいやき".to_json, "たこやき".to_json],
193
+ :route => "localhost:23003/output"},
194
+ normalize_subscriber(subscriber_table.first)
195
+ )
196
+ end
197
+
198
+ def test_multiple_subscribers
199
+ request = {
200
+ :route => "localhost:23003/output",
201
+ :condition => "たいやき",
202
+ :query => "たいやき".to_json,
203
+ :subscriber => "subscriber1",
204
+ }
205
+ @watcher.subscribe(request)
206
+ request = {
207
+ :route => "localhost:23003/output",
208
+ :condition => "たこやき",
209
+ :query => "たこやき".to_json,
210
+ :subscriber => "subscriber2",
211
+ }
212
+ @watcher.subscribe(request)
213
+ assert_equal(
214
+ {:subscribers => ["subscriber1", "subscriber2"],
215
+ :queries => ["たいやき".to_json, "たこやき".to_json],
216
+ :keywords => ["たいやき", "たこやき"]},
217
+ existing_records
218
+ )
219
+ assert_equal([["たいやき".to_json],
220
+ ["たこやき".to_json]],
221
+ [subscriber_table["subscriber1"].subscriptions.collect(&:_key),
222
+ subscriber_table["subscriber2"].subscriptions.collect(&:_key)])
223
+ end
224
+ end
225
+
226
+ class UnsubscribeTest < self
227
+ def setup
228
+ super
229
+ setup_subscriptions
230
+ end
231
+
232
+ def test_with_query_multiple_times
233
+ @watcher.unsubscribe(
234
+ :route => "localhost:23003/output",
235
+ :query => "たいやき".to_json,
236
+ :subscriber => "subscriber1",
237
+ )
238
+ assert_equal(
239
+ {:subscribers => ["subscriber1", "subscriber2"],
240
+ :queries => ["たいやき".to_json, "たこやき".to_json],
241
+ :keywords => ["たいやき", "たこやき"]},
242
+ existing_records
243
+ )
244
+
245
+ @watcher.unsubscribe(
246
+ :route => "localhost:23003/output",
247
+ :query => "たこやき".to_json,
248
+ :subscriber => "subscriber1",
249
+ )
250
+ assert_equal(
251
+ {:subscribers => ["subscriber2"],
252
+ :queries => ["たいやき".to_json, "たこやき".to_json],
253
+ :keywords => ["たいやき", "たこやき"]},
254
+ existing_records
255
+ )
256
+ end
257
+
258
+ def test_with_query_watched_by_multiple_subscribers
259
+ @watcher.unsubscribe(
260
+ :route => "localhost:23003/output",
261
+ :query => "たいやき".to_json,
262
+ :subscriber => "subscriber1",
263
+ )
264
+ assert_equal(
265
+ {:subscribers => ["subscriber1", "subscriber2"],
266
+ :queries => ["たいやき".to_json, "たこやき".to_json],
267
+ :keywords => ["たいやき", "たこやき"]},
268
+ existing_records
269
+ )
270
+
271
+ @watcher.unsubscribe(
272
+ :route => "localhost:23003/output",
273
+ :query => "たいやき".to_json,
274
+ :subscriber => "subscriber2",
275
+ )
276
+ assert_equal(
277
+ {:subscribers => ["subscriber1", "subscriber2"],
278
+ :queries => ["たこやき".to_json],
279
+ :keywords => ["たこやき"]},
280
+ existing_records
281
+ )
282
+ end
283
+
284
+ def test_without_query
285
+ request = {
286
+ :route => "localhost:23003/output",
287
+ :subscriber => "subscriber1",
288
+ }
289
+ @watcher.unsubscribe(request)
290
+ assert_equal(
291
+ {:subscribers => ["subscriber2"],
292
+ :queries => ["たいやき".to_json, "たこやき".to_json],
293
+ :keywords => ["たいやき", "たこやき"]},
294
+ existing_records
295
+ )
296
+ end
297
+
298
+ private
299
+ def setup_subscriptions
300
+ request1_1 = {
301
+ :route => "localhost:23003/output",
302
+ :condition => "たいやき",
303
+ :query => "たいやき".to_json,
304
+ :subscriber => "subscriber1",
305
+ }
306
+ @watcher.subscribe(request1_1)
307
+ request1_2 = {
308
+ :route => "localhost:23003/output",
309
+ :condition => "たこやき",
310
+ :query => "たこやき".to_json,
311
+ :subscriber => "subscriber1",
312
+ }
313
+ @watcher.subscribe(request1_2)
314
+ request2_1 = {
315
+ :route => "localhost:23003/output",
316
+ :condition => "たいやき",
317
+ :query => "たいやき".to_json,
318
+ :subscriber => "subscriber2",
319
+ }
320
+ @watcher.subscribe(request2_1)
321
+ request2_2 = {
322
+ :route => "localhost:23003/output",
323
+ :condition => "たこやき",
324
+ :query => "たこやき".to_json,
325
+ :subscriber => "subscriber2",
326
+ }
327
+ @watcher.subscribe(request2_2)
328
+ assert_equal(
329
+ {:subscribers => ["subscriber1", "subscriber2"],
330
+ :queries => ["たいやき".to_json, "たこやき".to_json],
331
+ :keywords => ["たいやき", "たこやき"]},
332
+ existing_records
333
+ )
334
+ end
335
+ end
336
+ end