droonga-engine 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -1
  3. data/Rakefile +6 -0
  4. data/bin/droonga-engine-absorb-data +14 -14
  5. data/bin/droonga-engine-catalog-generate +24 -12
  6. data/bin/droonga-engine-catalog-modify +13 -7
  7. data/bin/droonga-engine-join +8 -8
  8. data/bin/droonga-engine-set-role +1 -1
  9. data/bin/droonga-engine-unjoin +2 -2
  10. data/lib/droonga/address.rb +3 -0
  11. data/lib/droonga/cluster.rb +16 -10
  12. data/lib/droonga/command/droonga_engine_service.rb +5 -2
  13. data/lib/droonga/command/remote_command_base.rb +3 -3
  14. data/lib/droonga/distributed_command_planner.rb +11 -1
  15. data/lib/droonga/engine.rb +12 -11
  16. data/lib/droonga/engine/version.rb +2 -2
  17. data/lib/droonga/engine_node.rb +28 -28
  18. data/lib/droonga/engine_state.rb +41 -36
  19. data/lib/droonga/forward_buffer.rb +21 -10
  20. data/lib/droonga/node_role.rb +2 -0
  21. data/lib/droonga/plugins/groonga/select.rb +3 -0
  22. data/lib/droonga/plugins/search.rb +3 -1
  23. data/lib/droonga/plugins/search/distributed_search_planner.rb +17 -5
  24. data/lib/droonga/plugins/system/statistics.rb +1 -0
  25. data/lib/droonga/searcher.rb +13 -4
  26. data/test/command/config/single_slice/catalog.json +38 -0
  27. data/test/command/config/single_slice/droonga-engine.yaml +4 -0
  28. data/test/command/run-test.rb +3 -2
  29. data/test/command/suite/catalog/fetch.expected.single_slice +50 -0
  30. data/test/command/suite/dump/column/index.expected.single_slice +86 -0
  31. data/test/command/suite/dump/column/scalar.expected.single_slice +52 -0
  32. data/test/command/suite/dump/column/vector.expected.single_slice +55 -0
  33. data/test/command/suite/dump/record/scalar.expected.single_slice +52 -0
  34. data/test/command/suite/dump/record/vector/reference.expected.single_slice +117 -0
  35. data/test/command/suite/dump/table/array.expected.single_slice +39 -0
  36. data/test/command/suite/dump/table/double_array_trie.expected.single_slice +40 -0
  37. data/test/command/suite/dump/table/hash.expected.single_slice +40 -0
  38. data/test/command/suite/dump/table/patricia_trie.expected.single_slice +40 -0
  39. data/test/command/suite/message/error/missing-dataset.test +3 -0
  40. data/test/command/suite/search/condition/query/nonexistent_column.expected.single_slice +26 -0
  41. data/test/command/suite/search/condition/query/syntax_error.expected.single_slice +26 -0
  42. data/test/command/suite/search/error/unknown-source.expected.single_slice +28 -0
  43. data/test/command/suite/search/output/attributes/invalid.expected.single_slice +24 -0
  44. data/test/command/suite/system/absorb-data/records.catalog.json.single_slice +44 -0
  45. data/test/command/suite/system/absorb-data/records.expected.single_slice +32 -0
  46. data/test/command/suite/system/statistics/object/count/per-volume/empty.test +1 -0
  47. data/test/command/suite/system/statistics/object/count/record.expected.single_slice +11 -0
  48. data/test/command/suite/system/statistics/object/count/schema.expected.single_slice +11 -0
  49. data/test/unit/catalog/test_generator.rb +3 -2
  50. data/test/unit/helper.rb +2 -1
  51. data/test/unit/helper/stub_serf.rb +28 -0
  52. data/test/unit/plugins/system/statistics/test_object_count.rb +135 -0
  53. data/test/unit/plugins/system/statistics/test_object_count_per_volume.rb +149 -0
  54. data/test/unit/plugins/test_basic.rb +0 -406
  55. data/test/unit/test_address.rb +111 -10
  56. data/test/unit/test_cluster.rb +232 -0
  57. data/test/unit/test_differ.rb +49 -0
  58. data/test/unit/test_engine_node.rb +556 -0
  59. data/test/unit/test_engine_state.rb +151 -0
  60. data/test/unit/test_forward_buffer.rb +106 -0
  61. data/test/unit/test_node_name.rb +160 -0
  62. data/test/unit/test_node_role.rb +53 -0
  63. data/test/unit/test_reducer.rb +525 -0
  64. metadata +111 -49
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014 Droonga Project
1
+ # Copyright (C) 2014-2015 Droonga Project
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -28,19 +28,80 @@ class AddressTest < Test::Unit::TestCase
28
28
  Droonga::Address.parse(string)
29
29
  end
30
30
 
31
- def test_full
32
- assert_equal(address("192.168.0.1", 2929, "droonga", "local_name"),
33
- parse("192.168.0.1:2929/droonga.local_name"))
31
+ data(:full => {
32
+ :input => "node29:2929/droonga.local_name",
33
+ :host => "node29",
34
+ :port => 2929,
35
+ :tag => "droonga",
36
+ :local_name => "local_name",
37
+ },
38
+ :ip_address => {
39
+ :input => "192.168.0.1:2929/droonga.local_name",
40
+ :host => "192.168.0.1",
41
+ :port => 2929,
42
+ :tag => "droonga",
43
+ :local_name => "local_name",
44
+ },
45
+ :internal_name => {
46
+ :input => "node29:2929/droonga.\#1",
47
+ :host => "node29",
48
+ :port => 2929,
49
+ :tag => "droonga",
50
+ :local_name => "#1",
51
+ },
52
+ :no_local_name => {
53
+ :input => "node29:2929/droonga",
54
+ :host => "node29",
55
+ :port => 2929,
56
+ :tag => "droonga",
57
+ :local_name => nil,
58
+ })
59
+ def test_success(data)
60
+ assert_equal(address(data[:host], data[:port], data[:tag],
61
+ data[:local_name]),
62
+ parse(data[:input]))
34
63
  end
35
64
 
36
- def test_internal_name
37
- assert_equal(address("192.168.0.1", 2929, "droonga", "#1"),
38
- parse("192.168.0.1:2929/droonga.\#1"))
65
+ data(:no_host => ":2929/droonga",
66
+ :no_port => "192.168.0.1/droonga",
67
+ :no_tag => "192.168.0.1:2929",
68
+ :blank => "",
69
+ :nil => nil)
70
+ def test_fail(input)
71
+ assert_raise(ArgumentError) do
72
+ parse(input)
73
+ end
74
+ end
75
+ end
76
+
77
+ class AttributeTest < self
78
+ def test_attributes
79
+ address = address("192.168.0.1", 2929, "droonga", "000")
80
+ assert_equal({:host => "192.168.0.1",
81
+ :port => 2929,
82
+ :tag => "droonga",
83
+ :local_name => "000"},
84
+ {:host => address.host,
85
+ :port => address.port,
86
+ :tag => address.tag,
87
+ :local_name => address.local_name})
88
+ end
89
+ end
90
+
91
+ class ComparisonTest < self
92
+ def test_address_vs_string
93
+ string = "192.168.0.1:2929/droonga.000"
94
+ address = address("192.168.0.1", 2929, "droonga", "000")
95
+ assert_true(address == string)
39
96
  end
40
97
 
41
- def test_no_name
42
- assert_equal(address("192.168.0.1", 2929, "droonga", nil),
43
- parse("192.168.0.1:2929/droonga"))
98
+ #XXX This is a confusable behavior. It seems should be true
99
+ # but actually false, so you have to be careful when you
100
+ # compare string with Address.
101
+ def test_string_vs_address
102
+ string = "192.168.0.1:2929/droonga.000"
103
+ address = address("192.168.0.1", 2929, "droonga", "000")
104
+ assert_false(string == address)
44
105
  end
45
106
  end
46
107
 
@@ -49,5 +110,45 @@ class AddressTest < Test::Unit::TestCase
49
110
  assert_equal("192.168.0.1:2929/droonga",
50
111
  address("192.168.0.1", 2929, "droonga", "000").node)
51
112
  end
113
+
114
+ data(:full => {
115
+ :expected => "192.168.0.1:2929/droonga.000",
116
+ :host => "192.168.0.1",
117
+ :port => 2929,
118
+ :tag => "droonga",
119
+ :local_name => "000",
120
+ },
121
+ :no_local_name => {
122
+ :expected => "192.168.0.1:2929/droonga",
123
+ :host => "192.168.0.1",
124
+ :port => 2929,
125
+ :tag => "droonga",
126
+ :local_name => nil,
127
+ })
128
+ def test_string(data)
129
+ assert_equal(data[:expected],
130
+ address(data[:host], data[:port], data[:tag],
131
+ data[:local_name]).to_s)
132
+ end
133
+
134
+ data(:full => {
135
+ :expected => ["192.168.0.1", 2929, "droonga", "000"],
136
+ :host => "192.168.0.1",
137
+ :port => 2929,
138
+ :tag => "droonga",
139
+ :local_name => "000",
140
+ },
141
+ :no_local_name => {
142
+ :expected => ["192.168.0.1", 2929, "droonga", nil],
143
+ :host => "192.168.0.1",
144
+ :port => 2929,
145
+ :tag => "droonga",
146
+ :local_name => nil,
147
+ })
148
+ def test_array(data)
149
+ assert_equal(data[:expected],
150
+ address(data[:host], data[:port], data[:tag],
151
+ data[:local_name]).to_a)
152
+ end
52
153
  end
53
154
  end
@@ -0,0 +1,232 @@
1
+ # Copyright (C) 2014-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
+
16
+ require "droonga/cluster"
17
+ require "droonga/node_role"
18
+
19
+ class ClusterTest < Test::Unit::TestCase
20
+ class StubCatalog
21
+ attr_accessor :all_nodes
22
+
23
+ def initialize(all_nodes)
24
+ @all_nodes = all_nodes || []
25
+ end
26
+ end
27
+
28
+ class StubEngineNode < Droonga::EngineNode
29
+ attr_reader :forwarded_messages, :bounced_messages
30
+
31
+ def initialize(params)
32
+ @forwarded_messages = []
33
+ @bounced_messages = []
34
+ super
35
+ end
36
+
37
+ def resume
38
+ end
39
+
40
+ def forward(message, destination)
41
+ @forwarded_messages << {:message => message,
42
+ :destination => destination}
43
+ end
44
+
45
+ def bounce(message)
46
+ @bounced_messages << message
47
+ end
48
+
49
+ private
50
+ def sender_role
51
+ Droonga::NodeRole::SERVICE_PROVIDER
52
+ end
53
+
54
+ def create_buffer
55
+ []
56
+ end
57
+ end
58
+
59
+ class Cluster < Droonga::Cluster
60
+ def reload
61
+ end
62
+
63
+ def start
64
+ engine_nodes # instantiate it
65
+ end
66
+
67
+ private
68
+ def create_engine_node(params)
69
+ StubEngineNode.new(params)
70
+ end
71
+ end
72
+
73
+ def create_cluster(options={})
74
+ catalog = StubCatalog.new(options[:all_nodes])
75
+ Cluster.new(:state => options[:state],
76
+ :catalog => catalog)
77
+ end
78
+
79
+ def test_engine_nodes
80
+ cluster = create_cluster(:all_nodes => [
81
+ "node29:2929/droonga",
82
+ "node30:2929/droonga",
83
+ ])
84
+ assert_equal([
85
+ {:class => StubEngineNode,
86
+ :name => "node29:2929/droonga"},
87
+ {:class => StubEngineNode,
88
+ :name => "node30:2929/droonga"},
89
+ ],
90
+ cluster.engine_nodes.collect do |node|
91
+ {:class => node.class,
92
+ :name => node.name}
93
+ end)
94
+ end
95
+
96
+ def test_engine_node_names
97
+ cluster = create_cluster(:all_nodes => [
98
+ "node29:2929/droonga",
99
+ "node30:2929/droonga",
100
+ ])
101
+ assert_equal([
102
+ "node29:2929/droonga",
103
+ "node30:2929/droonga",
104
+ ],
105
+ cluster.engine_node_names)
106
+ end
107
+
108
+ def test_engine_nodes_status
109
+ cluster = create_cluster(:state => {
110
+ "node29:2929/droonga" => {
111
+ "live" => true,
112
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
113
+ },
114
+ "node30:2929/droonga" => {
115
+ "live" => true,
116
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
117
+ },
118
+ },
119
+ :all_nodes => [
120
+ "node29:2929/droonga",
121
+ "node30:2929/droonga",
122
+ ])
123
+ assert_equal({
124
+ "node29:2929/droonga" => {
125
+ "status" => "active",
126
+ },
127
+ "node30:2929/droonga" => {
128
+ "status" => "active",
129
+ },
130
+ },
131
+ cluster.engine_nodes_status)
132
+ end
133
+
134
+ def test_readable_nodes
135
+ cluster = create_cluster(:state => {
136
+ "node29:2929/droonga" => {
137
+ "live" => true,
138
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
139
+ },
140
+ "node30:2929/droonga" => {
141
+ "live" => false,
142
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
143
+ },
144
+ },
145
+ :all_nodes => [
146
+ "node29:2929/droonga",
147
+ "node30:2929/droonga",
148
+ ])
149
+ assert_equal([
150
+ "node29:2929/droonga",
151
+ ],
152
+ cluster.readable_nodes)
153
+ end
154
+
155
+ def test_writable_nodes
156
+ cluster = create_cluster(:all_nodes => [
157
+ "node29:2929/droonga",
158
+ "node30:2929/droonga",
159
+ ])
160
+ assert_equal([
161
+ "node29:2929/droonga",
162
+ "node30:2929/droonga",
163
+ ],
164
+ cluster.writable_nodes)
165
+ end
166
+
167
+ def test_forward
168
+ cluster = create_cluster(:state => {
169
+ "node29:2929/droonga" => {
170
+ "live" => true,
171
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
172
+ },
173
+ "node30:2929/droonga" => {
174
+ "live" => true,
175
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
176
+ },
177
+ },
178
+ :all_nodes => [
179
+ "node29:2929/droonga",
180
+ "node30:2929/droonga",
181
+ ])
182
+ cluster.start
183
+ cluster.forward({"id" => 1},
184
+ {"to" => "node29:2929/droonga"})
185
+ assert_equal([
186
+ {:name => "node29:2929/droonga",
187
+ :forwarded => [
188
+ {:message => {"id" => 1},
189
+ :destination => {"to" => "node29:2929/droonga"}}
190
+ ]},
191
+ {:name => "node30:2929/droonga",
192
+ :forwarded => []}
193
+ ],
194
+ cluster.engine_nodes.collect do |node|
195
+ {:name => node.name,
196
+ :forwarded => node.forwarded_messages}
197
+ end)
198
+ end
199
+
200
+ def test_bounce
201
+ cluster = create_cluster(:state => {
202
+ "node29:2929/droonga" => {
203
+ "live" => true,
204
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
205
+ },
206
+ "node30:2929/droonga" => {
207
+ "live" => true,
208
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
209
+ },
210
+ },
211
+ :all_nodes => [
212
+ "node29:2929/droonga",
213
+ "node30:2929/droonga",
214
+ ])
215
+ cluster.start
216
+ cluster.bounce({"id" => 1,
217
+ "targetRole" => Droonga::NodeRole::ABSORB_SOURCE})
218
+ assert_equal([
219
+ {:name => "node29:2929/droonga",
220
+ :bounced => []},
221
+ {:name => "node30:2929/droonga",
222
+ :bounced => [
223
+ {"id" => 1,
224
+ "targetRole" => Droonga::NodeRole::ABSORB_SOURCE},
225
+ ]}
226
+ ],
227
+ cluster.engine_nodes.collect do |node|
228
+ {:name => node.name,
229
+ :bounced => node.bounced_messages}
230
+ end)
231
+ end
232
+ end
@@ -0,0 +1,49 @@
1
+ # Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
+
16
+ require "droonga/differ"
17
+
18
+ class DifferTest < Test::Unit::TestCase
19
+ data(:string => {
20
+ :left => "a",
21
+ :right => "b",
22
+ :expected => "\"a\" <=> \"b\"",
23
+ },
24
+ :numeric => {
25
+ :left => 0,
26
+ :right => 1,
27
+ :expected => "0 <=> 1",
28
+ },
29
+ :hash => {
30
+ :left => {:a => 0, :b => 1},
31
+ :right => {:a => 0, :b => 2},
32
+ :expected => {:b => "1 <=> 2"},
33
+ },
34
+ :array => {
35
+ :left => [0, 1, 2],
36
+ :right => [0, 1, 3],
37
+ :expected => {2 => "2 <=> 3"},
38
+ },
39
+ :nested => {
40
+ :left => {:a => 0, :b => {:aa => 0, :bb => 1}},
41
+ :right => {:a => 1, :b => {:aa => 0, :bb => 2}},
42
+ :expected => {:a => "0 <=> 1",
43
+ :b => {:bb => "1 <=> 2"}},
44
+ })
45
+ def test_diff(data)
46
+ assert_equal(data[:expected],
47
+ Droonga::Differ.diff(data[:left], data[:right]))
48
+ end
49
+ end
@@ -0,0 +1,556 @@
1
+ # Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
+
16
+ require "droonga/engine_node"
17
+ require "droonga/node_role"
18
+
19
+ class EngineNodeTest < Test::Unit::TestCase
20
+ def node(params)
21
+ Droonga::EngineNode.new(params)
22
+ end
23
+
24
+ data(:no_state => {
25
+ :expected => Droonga::NodeRole::SERVICE_PROVIDER,
26
+ :state => nil,
27
+ },
28
+ :valid => {
29
+ :expected => Droonga::NodeRole::ABSORB_SOURCE,
30
+ :state => {
31
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
32
+ },
33
+ },
34
+ :invalid => {
35
+ :expected => Droonga::NodeRole::SERVICE_PROVIDER,
36
+ :state => {
37
+ "role" => "unknown",
38
+ },
39
+ })
40
+ def test_role(data)
41
+ assert_equal(data[:expected],
42
+ node(:name => "node29:2929/droonga",
43
+ :state => data[:state]).role)
44
+ end
45
+
46
+ data(:no_state => nil,
47
+ :live_info => {
48
+ "live" => true,
49
+ })
50
+ def test_live(state)
51
+ assert_true(node(:name => "node29:2929/droonga",
52
+ :state => state).live?)
53
+ end
54
+
55
+ data(:no_live_info => {
56
+ },
57
+ :live_info => {
58
+ "live" => false,
59
+ })
60
+ def test_not_live(state)
61
+ assert_false(node(:name => "node29:2929/droonga",
62
+ :state => state).live?)
63
+ end
64
+
65
+ data(:valid => {
66
+ :state => {
67
+ "live" => true,
68
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
69
+ },
70
+ :expected => {
71
+ "name" => "node29:2929/droonga",
72
+ "live" => true,
73
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
74
+ "status" => "active",
75
+ },
76
+ })
77
+ def test_to_json(data)
78
+ json = node(:name => "node29:2929/droonga",
79
+ :state => data[:state]).to_json
80
+ assert_equal(data[:expected], json)
81
+ end
82
+
83
+ class Buffered < Droonga::EngineNode
84
+ private
85
+ def create_buffer
86
+ [0]
87
+ end
88
+ end
89
+
90
+ class NotBuffered < Droonga::EngineNode
91
+ private
92
+ def create_buffer
93
+ []
94
+ end
95
+ end
96
+
97
+ class FromServiceProvider < self
98
+ class BufferedEngineNode < Buffered
99
+ private
100
+ def sender_role
101
+ Droonga::NodeRole::SERVICE_PROVIDER
102
+ end
103
+ end
104
+
105
+ class NotBufferedEngineNode < NotBuffered
106
+ private
107
+ def sender_role
108
+ Droonga::NodeRole::SERVICE_PROVIDER
109
+ end
110
+ end
111
+
112
+ class EngineNode < NotBufferedEngineNode
113
+ end
114
+
115
+ data(:same_role => {
116
+ "live" => true,
117
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
118
+ })
119
+ def test_forwardable(state)
120
+ assert_true(EngineNode.new(:name => "node29:2929/droonga",
121
+ :state => state).forwardable?)
122
+ end
123
+
124
+ data(:dead => {
125
+ "live" => false,
126
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
127
+ },
128
+ :to_absorb_source => {
129
+ "live" => true,
130
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
131
+ },
132
+ :to_absorb_destination => {
133
+ "live" => true,
134
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
135
+ })
136
+ def test_not_forwardable(state)
137
+ assert_false(EngineNode.new(:name => "node29:2929/droonga",
138
+ :state => state).forwardable?)
139
+ end
140
+
141
+ data(:same_role_with_no_unprocessed_message => {
142
+ :state => {
143
+ "live" => true,
144
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
145
+ },
146
+ :class => NotBufferedEngineNode,
147
+ })
148
+ def test_readable(data)
149
+ assert_true(data[:class].new(:name => "node29:2929/droonga",
150
+ :state => data[:state]).readable?)
151
+ end
152
+
153
+ data(:dead => {
154
+ :state => {
155
+ "live" => false,
156
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
157
+ },
158
+ :class => NotBufferedEngineNode,
159
+ },
160
+ :have_unprocessed_message_in_other_node => {
161
+ :state => {
162
+ "live" => true,
163
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
164
+ "have_unprocessed_messages" => true,
165
+ },
166
+ :class => NotBufferedEngineNode,
167
+ },
168
+ :have_unprocessed_message => {
169
+ :state => {
170
+ "live" => true,
171
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
172
+ },
173
+ :class => BufferedEngineNode,
174
+ },
175
+ :to_absorb_source => {
176
+ :state => {
177
+ "live" => true,
178
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
179
+ },
180
+ :class => NotBufferedEngineNode,
181
+ },
182
+ :to_absorb_destination => {
183
+ :state => {
184
+ "live" => true,
185
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
186
+ },
187
+ :class => NotBufferedEngineNode,
188
+ })
189
+ def test_not_readable(data)
190
+ assert_false(data[:class].new(:name => "node29:2929/droonga",
191
+ :state => data[:state]).readable?)
192
+ end
193
+
194
+ data(:same_role => {
195
+ "live" => true,
196
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
197
+ },
198
+ :to_absorb_source => {
199
+ "live" => true,
200
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
201
+ },
202
+ :to_absorb_destination => {
203
+ "live" => true,
204
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
205
+ },
206
+ :to_dead => {
207
+ "live" => false,
208
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
209
+ },
210
+ :to_node_have_unprocessed_message => {
211
+ "live" => true,
212
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
213
+ "have_unprocessed_messages" => true,
214
+ })
215
+ def test_writable(state)
216
+ assert_true(EngineNode.new(:name => "node29:2929/droonga",
217
+ :state => state).writable?)
218
+ end
219
+
220
+ data(:dead => {
221
+ :state => {
222
+ "live" => false,
223
+ },
224
+ :expected => "dead",
225
+ },
226
+ :readable => {
227
+ :state => {
228
+ "live" => true,
229
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
230
+ },
231
+ :expected => "active",
232
+ },
233
+ :not_readable_but_writable => {
234
+ :state => {
235
+ "live" => true,
236
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
237
+ },
238
+ :expected => "inactive",
239
+ })
240
+ def test_status(data)
241
+ assert_equal(data[:expected],
242
+ EngineNode.new(:name => "node29:2929/droonga",
243
+ :state => data[:state]).status)
244
+ end
245
+ end
246
+
247
+ class FromAbsorbSource < self
248
+ class BufferedEngineNode < Buffered
249
+ private
250
+ def sender_role
251
+ Droonga::NodeRole::ABSORB_SOURCE
252
+ end
253
+ end
254
+
255
+ class NotBufferedEngineNode < NotBuffered
256
+ private
257
+ def sender_role
258
+ Droonga::NodeRole::ABSORB_SOURCE
259
+ end
260
+ end
261
+
262
+ class EngineNode < NotBufferedEngineNode
263
+ end
264
+
265
+ data(:same_role => {
266
+ "live" => true,
267
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
268
+ })
269
+ def test_forwardable(state)
270
+ assert_true(EngineNode.new(:name => "node29:2929/droonga",
271
+ :state => state).forwardable?)
272
+ end
273
+
274
+ data(:dead => {
275
+ "live" => false,
276
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
277
+ },
278
+ :to_service_provider => {
279
+ "live" => true,
280
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
281
+ },
282
+ :to_absorb_destination => {
283
+ "live" => true,
284
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
285
+ })
286
+ def test_not_forwardable(state)
287
+ assert_false(EngineNode.new(:name => "node29:2929/droonga",
288
+ :state => state).forwardable?)
289
+ end
290
+
291
+ data(:same_role_with_no_unprocessed_message => {
292
+ :state => {
293
+ "live" => true,
294
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
295
+ },
296
+ :class => NotBufferedEngineNode,
297
+ },
298
+ :have_unprocessed_message_in_other_node => {
299
+ :state => {
300
+ "live" => true,
301
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
302
+ "have_unprocessed_messages" => true,
303
+ },
304
+ :class => NotBufferedEngineNode,
305
+ })
306
+ def test_readable(data)
307
+ assert_true(data[:class].new(:name => "node29:2929/droonga",
308
+ :state => data[:state]).readable?)
309
+ end
310
+
311
+ data(:dead => {
312
+ :state => {
313
+ "live" => false,
314
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
315
+ },
316
+ :class => NotBufferedEngineNode,
317
+ },
318
+ :have_unprocessed_message => {
319
+ :state => {
320
+ "live" => true,
321
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
322
+ },
323
+ :class => BufferedEngineNode,
324
+ },
325
+ :to_service_provider => {
326
+ :state => {
327
+ "live" => true,
328
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
329
+ },
330
+ :class => NotBufferedEngineNode,
331
+ },
332
+ :to_absorb_destination => {
333
+ :state => {
334
+ "live" => true,
335
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
336
+ },
337
+ :class => NotBufferedEngineNode,
338
+ })
339
+ def test_not_readable(data)
340
+ assert_false(data[:class].new(:name => "node29:2929/droonga",
341
+ :state => data[:state]).readable?)
342
+ end
343
+
344
+ data(:same_role => {
345
+ "live" => true,
346
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
347
+ },
348
+ :to_dead => {
349
+ "live" => false,
350
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
351
+ },
352
+ :to_node_have_unprocessed_message => {
353
+ "live" => true,
354
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
355
+ "have_unprocessed_messages" => true,
356
+ })
357
+ def test_writable(state)
358
+ assert_true(EngineNode.new(:name => "node29:2929/droonga",
359
+ :state => state).writable?)
360
+ end
361
+
362
+ data(:to_service_provider => {
363
+ "live" => true,
364
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
365
+ },
366
+ :to_absorb_destination => {
367
+ "live" => true,
368
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
369
+ })
370
+ def test_not_writable(state)
371
+ assert_false(EngineNode.new(:name => "node29:2929/droonga",
372
+ :state => state).writable?)
373
+ end
374
+
375
+ data(:dead => {
376
+ :state => {
377
+ "live" => false,
378
+ },
379
+ :expected => "dead",
380
+ },
381
+ :readable => {
382
+ :state => {
383
+ "live" => true,
384
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
385
+ },
386
+ :expected => "active",
387
+ },
388
+ :not_readable_but_writable => {
389
+ :state => {
390
+ "live" => true,
391
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
392
+ },
393
+ :expected => "inactive",
394
+ })
395
+ def test_status(data)
396
+ assert_equal(data[:expected],
397
+ EngineNode.new(:name => "node29:2929/droonga",
398
+ :state => data[:state]).status)
399
+ end
400
+ end
401
+
402
+ class FromAbsorbDestination < self
403
+ class BufferedEngineNode < Buffered
404
+ private
405
+ def sender_role
406
+ Droonga::NodeRole::ABSORB_DESTINATION
407
+ end
408
+ end
409
+
410
+ class NotBufferedEngineNode < NotBuffered
411
+ private
412
+ def sender_role
413
+ Droonga::NodeRole::ABSORB_DESTINATION
414
+ end
415
+ end
416
+
417
+ class EngineNode < NotBufferedEngineNode
418
+ end
419
+
420
+ data(:same_role => {
421
+ "live" => true,
422
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
423
+ })
424
+ def test_forwardable(state)
425
+ assert_true(EngineNode.new(:name => "node29:2929/droonga",
426
+ :state => state).forwardable?)
427
+ end
428
+
429
+ data(:dead => {
430
+ "live" => false,
431
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
432
+ },
433
+ :to_service_provider => {
434
+ "live" => true,
435
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
436
+ },
437
+ :to_absorb_source => {
438
+ "live" => true,
439
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
440
+ })
441
+ def test_not_forwardable(state)
442
+ assert_false(EngineNode.new(:name => "node29:2929/droonga",
443
+ :state => state).forwardable?)
444
+ end
445
+
446
+ data(:same_role_with_no_unprocessed_message => {
447
+ :state => {
448
+ "live" => true,
449
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
450
+ },
451
+ :class => NotBufferedEngineNode,
452
+ },
453
+ :have_unprocessed_message_in_other_node => {
454
+ :state => {
455
+ "live" => true,
456
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
457
+ "have_unprocessed_messages" => true,
458
+ },
459
+ :class => NotBufferedEngineNode,
460
+ })
461
+ def test_readable(data)
462
+ assert_true(data[:class].new(:name => "node29:2929/droonga",
463
+ :state => data[:state]).readable?)
464
+ end
465
+
466
+ data(:dead => {
467
+ :state => {
468
+ "live" => false,
469
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
470
+ },
471
+ :class => NotBufferedEngineNode,
472
+ },
473
+ :have_unprocessed_message => {
474
+ :state => {
475
+ "live" => true,
476
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
477
+ },
478
+ :class => BufferedEngineNode,
479
+ },
480
+ :to_service_provider => {
481
+ :state => {
482
+ "live" => true,
483
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
484
+ },
485
+ :class => NotBufferedEngineNode,
486
+ },
487
+ :to_absorb_source => {
488
+ :state => {
489
+ "live" => true,
490
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
491
+ },
492
+ :class => NotBufferedEngineNode,
493
+ })
494
+ def test_not_readable(data)
495
+ assert_false(data[:class].new(:name => "node29:2929/droonga",
496
+ :state => data[:state]).readable?)
497
+ end
498
+
499
+ data(:same_role => {
500
+ "live" => true,
501
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
502
+ },
503
+ :to_dead => {
504
+ "live" => false,
505
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
506
+ },
507
+ :to_node_have_unprocessed_message => {
508
+ "live" => true,
509
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
510
+ "have_unprocessed_messages" => true,
511
+ })
512
+ def test_writable(state)
513
+ assert_true(EngineNode.new(:name => "node29:2929/droonga",
514
+ :state => state).writable?)
515
+ end
516
+
517
+ data(:to_service_provider => {
518
+ "live" => true,
519
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
520
+ },
521
+ :to_absorb_source => {
522
+ "live" => true,
523
+ "role" => Droonga::NodeRole::ABSORB_SOURCE,
524
+ })
525
+ def test_not_writable(state)
526
+ assert_false(EngineNode.new(:name => "node29:2929/droonga",
527
+ :state => state).writable?)
528
+ end
529
+
530
+ data(:dead => {
531
+ :state => {
532
+ "live" => false,
533
+ },
534
+ :expected => "dead",
535
+ },
536
+ :readable => {
537
+ :state => {
538
+ "live" => true,
539
+ "role" => Droonga::NodeRole::ABSORB_DESTINATION,
540
+ },
541
+ :expected => "active",
542
+ },
543
+ :not_readable_but_writable => {
544
+ :state => {
545
+ "live" => true,
546
+ "role" => Droonga::NodeRole::SERVICE_PROVIDER,
547
+ },
548
+ :expected => "inactive",
549
+ })
550
+ def test_status(data)
551
+ assert_equal(data[:expected],
552
+ EngineNode.new(:name => "node29:2929/droonga",
553
+ :state => data[:state]).status)
554
+ end
555
+ end
556
+ end