riak-client 2.1.0 → 2.2.0.pre1

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/Guardfile +15 -9
  4. data/README.markdown +118 -9
  5. data/lib/riak/bucket.rb +16 -1
  6. data/lib/riak/bucket_properties.rb +67 -0
  7. data/lib/riak/bucket_type.rb +48 -0
  8. data/lib/riak/bucket_typed/bucket.rb +113 -0
  9. data/lib/riak/client/beefcake/bucket_properties_operator.rb +178 -0
  10. data/lib/riak/client/beefcake/message_overlay.rb +42 -20
  11. data/lib/riak/client/beefcake/object_methods.rb +1 -1
  12. data/lib/riak/client/beefcake/socket.rb +6 -6
  13. data/lib/riak/client/beefcake_protobuffs_backend.rb +44 -60
  14. data/lib/riak/client/protobuffs_backend.rb +8 -8
  15. data/lib/riak/client.rb +7 -2
  16. data/lib/riak/crdt/base.rb +29 -1
  17. data/lib/riak/crdt/counter.rb +7 -3
  18. data/lib/riak/crdt/inner_flag.rb +1 -1
  19. data/lib/riak/crdt/map.rb +7 -3
  20. data/lib/riak/crdt/set.rb +7 -4
  21. data/lib/riak/errors/failed_request.rb +2 -0
  22. data/lib/riak/errors/search_error.rb +29 -0
  23. data/lib/riak/locale/en.yml +7 -0
  24. data/lib/riak/map_reduce.rb +70 -6
  25. data/lib/riak/robject.rb +19 -3
  26. data/lib/riak/search/index.rb +73 -0
  27. data/lib/riak/search/query.rb +133 -0
  28. data/lib/riak/search/result_collection.rb +91 -0
  29. data/lib/riak/search/result_document.rb +59 -0
  30. data/lib/riak/search/schema.rb +65 -0
  31. data/lib/riak/search.rb +10 -0
  32. data/lib/riak/secondary_index.rb +6 -0
  33. data/lib/riak/version.rb +1 -1
  34. data/spec/fixtures/yz_schema_template.xml +18 -0
  35. data/spec/integration/riak/bucket_types_spec.rb +218 -39
  36. data/spec/integration/riak/conflict_resolution_spec.rb +96 -0
  37. data/spec/integration/riak/crdt_spec.rb +30 -2
  38. data/spec/integration/riak/properties_spec.rb +69 -0
  39. data/spec/integration/riak/search_spec.rb +104 -0
  40. data/spec/integration/riak/secondary_index_spec.rb +18 -0
  41. data/spec/riak/beefcake_protobuffs_backend/bucket_properties_operator_spec.rb +247 -0
  42. data/spec/riak/bucket_properties_spec.rb +114 -0
  43. data/spec/riak/bucket_type_spec.rb +34 -0
  44. data/spec/riak/bucket_typed/bucket.rb +43 -0
  45. data/spec/riak/client_spec.rb +16 -8
  46. data/spec/riak/crdt/counter_spec.rb +2 -1
  47. data/spec/riak/crdt/map_spec.rb +2 -1
  48. data/spec/riak/crdt/set_spec.rb +2 -1
  49. data/spec/riak/map_reduce_spec.rb +169 -124
  50. data/spec/riak/search/index_spec.rb +62 -0
  51. data/spec/riak/search/query_spec.rb +88 -0
  52. data/spec/riak/search/result_collection_spec.rb +87 -0
  53. data/spec/riak/search/result_document_spec.rb +63 -0
  54. data/spec/riak/search/schema_spec.rb +63 -0
  55. data/spec/spec_helper.rb +2 -1
  56. data/spec/support/search_config.rb +81 -0
  57. data/spec/support/test_client.yml +14 -7
  58. metadata +44 -5
@@ -1,93 +1,138 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Riak::MapReduce do
4
- before :each do
5
- @client = Riak::Client.new
6
- @backend = double("Backend")
7
- allow(@client).to receive(:backend).and_yield(@backend)
8
- @mr = Riak::MapReduce.new(@client)
4
+
5
+ let(:backend){ double 'Backend' }
6
+ let(:client) do
7
+ Riak::Client.new.tap do |c|
8
+ allow(c).to receive(:backend).and_yield(backend)
9
+ end
9
10
  end
11
+ let(:mr) { Riak::MapReduce.new(client) }
12
+
13
+ let(:bucket_type){ client.bucket_type 'type' }
14
+ let(:typed_bucket){ bucket_type.bucket 'bucket' }
15
+ let(:typed_object){ Riak::RObject.new typed_bucket, 'key' }
16
+
17
+ let(:default_type){ client.bucket_type Riak::BucketType::DEFAULT_NAME }
18
+ let(:default_bucket){ default_type.bucket 'bucket' }
19
+ let(:default_object){ Riak::RObject.new default_bucket, 'key' }
10
20
 
11
21
  it "requires a client" do
12
22
  expect { Riak::MapReduce.new }.to raise_error
13
- expect { Riak::MapReduce.new(@client) }.not_to raise_error
23
+ expect { Riak::MapReduce.new(client) }.not_to raise_error
14
24
  end
15
25
 
16
26
  it "initializes the inputs and query to empty arrays" do
17
- expect(@mr.inputs).to eq([])
18
- expect(@mr.query).to eq([])
27
+ expect(mr.inputs).to eq([])
28
+ expect(mr.query).to eq([])
19
29
  end
20
30
 
21
31
  it "yields itself when given a block on initializing" do
22
- @mr2 = nil
23
- @mr = Riak::MapReduce.new(@client) do |mr|
24
- @mr2 = mr
32
+ mapred2 = nil
33
+ mapred = Riak::MapReduce.new(client) do |mr|
34
+ mapred2 = mr
25
35
  end
26
- expect(@mr2).to eq(@mr)
36
+ expect(mapred2).to eq(mapred)
27
37
  end
28
38
 
29
39
  describe "adding inputs" do
30
40
  it "returns self for chaining" do
31
- expect(@mr.add("foo", "bar")).to eq(@mr)
41
+ expect(mr.add("foo", "bar")).to eq(mr)
32
42
  end
33
43
 
34
44
  it "adds bucket/key pairs to the inputs" do
35
- @mr.add("foo","bar")
36
- expect(@mr.inputs).to eq([["foo","bar"]])
45
+ mr.add("foo","bar")
46
+ expect(mr.inputs).to eq([["foo","bar"]])
37
47
  end
38
48
 
39
49
  it "adds an array containing a bucket/key pair to the inputs" do
40
- @mr.add(["foo","bar"])
41
- expect(@mr.inputs).to eq([["foo","bar"]])
50
+ mr.add(["foo","bar"])
51
+ expect(mr.inputs).to eq([["foo","bar"]])
42
52
  end
43
53
 
44
54
  it "adds an object to the inputs by its bucket and key" do
45
- bucket = Riak::Bucket.new(@client, "foo")
55
+ bucket = Riak::Bucket.new(client, "foo")
46
56
  obj = Riak::RObject.new(bucket, "bar")
47
- @mr.add(obj)
48
- expect(@mr.inputs).to eq([["foo", "bar"]])
57
+ mr.add(obj)
58
+ expect(mr.inputs).to eq([["foo", "bar"]])
59
+ end
60
+
61
+ it 'adds a bucket-typed object to the inputs' do
62
+ mr.add typed_object
63
+ expect(mr.inputs).to eq [[typed_bucket.name,
64
+ typed_object.key,
65
+ '',
66
+ typed_bucket.type.name
67
+ ]]
49
68
  end
50
69
 
51
70
  it "adds an array containing a bucket/key/key-data triple to the inputs" do
52
- @mr.add(["foo","bar",1000])
53
- expect(@mr.inputs).to eq([["foo","bar",1000]])
71
+ mr.add(["foo","bar",1000])
72
+ expect(mr.inputs).to eq([["foo","bar",1000]])
54
73
  end
55
74
 
56
75
  it "uses a bucket name as the single input" do
57
- @mr.add(Riak::Bucket.new(@client, "foo"))
58
- expect(@mr.inputs).to eq("foo")
59
- @mr.add("docs")
60
- expect(@mr.inputs).to eq("docs")
76
+ mr.add(Riak::Bucket.new(client, "foo"))
77
+ expect(mr.inputs).to eq("foo")
78
+ mr.add("docs")
79
+ expect(mr.inputs).to eq("docs")
80
+ end
81
+
82
+ it 'accepts a bucket typed bucket as a single input' do
83
+ mr.add typed_bucket
84
+ expect(mr.inputs).to eq([bucket_type.name, typed_bucket.name ])
85
+ end
86
+
87
+ it "doesn't pass a default bucket type name" do
88
+ mr.add default_bucket
89
+ expect(mr.inputs).to eq default_bucket.name
61
90
  end
62
91
 
63
92
  it "accepts a list of key-filters along with a bucket" do
64
- @mr.add("foo", [[:tokenize, "-", 3], [:string_to_int], [:between, 2009, 2010]])
65
- expect(@mr.inputs).to eq({:bucket => "foo", :key_filters => [[:tokenize, "-", 3], [:string_to_int], [:between, 2009, 2010]]})
93
+ mr.add("foo", [[:tokenize, "-", 3], [:string_to_int], [:between, 2009, 2010]])
94
+ expect(mr.inputs).to eq({:bucket => "foo", :key_filters => [[:tokenize, "-", 3], [:string_to_int], [:between, 2009, 2010]]})
95
+ end
96
+
97
+ it 'accepts a list of key-filters along with a bucket-typed bucket' do
98
+ filters = [
99
+ [:tokenize, '-', 3],
100
+ [:string_to_int],
101
+ [:between, 2009, 2010]
102
+ ]
103
+
104
+ mr.add(typed_bucket, filters)
105
+
106
+ expect(mr.inputs).to eq(
107
+ bucket: [typed_bucket.type.name,
108
+ typed_bucket.name],
109
+ key_filters: filters
110
+ )
66
111
  end
67
112
 
68
113
  it "adds a bucket and filter list via a builder block" do
69
- @mr.filter("foo") do
114
+ mr.filter("foo") do
70
115
  tokenize "-", 3
71
116
  string_to_int
72
117
  between 2009, 2010
73
118
  end
74
- expect(@mr.inputs).to eq({:bucket => "foo", :key_filters => [[:tokenize, "-", 3], [:string_to_int], [:between, 2009, 2010]]})
119
+ expect(mr.inputs).to eq({:bucket => "foo", :key_filters => [[:tokenize, "-", 3], [:string_to_int], [:between, 2009, 2010]]})
75
120
  end
76
121
 
77
122
  context "using secondary indexes as inputs" do
78
123
  it "sets the inputs for equality" do
79
- expect(@mr.index("foo", "email_bin", "sean@basho.com")).to eq(@mr)
80
- expect(@mr.inputs).to eq({:bucket => "foo", :index => "email_bin", :key => "sean@basho.com"})
124
+ expect(mr.index("foo", "email_bin", "sean@basho.com")).to eq(mr)
125
+ expect(mr.inputs).to eq({:bucket => "foo", :index => "email_bin", :key => "sean@basho.com"})
81
126
  end
82
127
 
83
128
  it "sets the inputs for a range" do
84
- expect(@mr.index("foo", "rank_int", 10..20)).to eq(@mr)
85
- expect(@mr.inputs).to eq({:bucket => "foo", :index => "rank_int", :start => 10, :end => 20})
129
+ expect(mr.index("foo", "rank_int", 10..20)).to eq(mr)
130
+ expect(mr.inputs).to eq({:bucket => "foo", :index => "rank_int", :start => 10, :end => 20})
86
131
  end
87
132
 
88
133
  it "raises an error when given an invalid query" do
89
- expect { @mr.index("foo", "rank_int", 1.0348) }.to raise_error(ArgumentError)
90
- expect { @mr.index("foo", "rank_int", Range.new(1.03, 1.05)) }.to raise_error(ArgumentError)
134
+ expect { mr.index("foo", "rank_int", 1.0348) }.to raise_error(ArgumentError)
135
+ expect { mr.index("foo", "rank_int", Range.new(1.03, 1.05)) }.to raise_error(ArgumentError)
91
136
  end
92
137
  end
93
138
 
@@ -100,32 +145,32 @@ describe Riak::MapReduce do
100
145
  after { Riak.url_decoding = @urldecode }
101
146
 
102
147
  it "adds bucket/key pairs to the inputs with bucket and key escaped" do
103
- @mr.add("[foo]","(bar)")
104
- expect(@mr.inputs).to eq([["%5Bfoo%5D","%28bar%29"]])
148
+ mr.add("[foo]","(bar)")
149
+ expect(mr.inputs).to eq([["%5Bfoo%5D","%28bar%29"]])
105
150
  end
106
151
 
107
152
  it "adds an escaped array containing a bucket/key pair to the inputs" do
108
- @mr.add(["[foo]","(bar)"])
109
- expect(@mr.inputs).to eq([["%5Bfoo%5D","%28bar%29"]])
153
+ mr.add(["[foo]","(bar)"])
154
+ expect(mr.inputs).to eq([["%5Bfoo%5D","%28bar%29"]])
110
155
  end
111
156
 
112
157
  it "adds an object to the inputs by its escaped bucket and key" do
113
- bucket = Riak::Bucket.new(@client, "[foo]")
158
+ bucket = Riak::Bucket.new(client, "[foo]")
114
159
  obj = Riak::RObject.new(bucket, "(bar)")
115
- @mr.add(obj)
116
- expect(@mr.inputs).to eq([["%5Bfoo%5D", "%28bar%29"]])
160
+ mr.add(obj)
161
+ expect(mr.inputs).to eq([["%5Bfoo%5D", "%28bar%29"]])
117
162
  end
118
163
 
119
164
  it "adds an escaped array containing a bucket/key/key-data triple to the inputs" do
120
- @mr.add(["[foo]","(bar)","[]()"])
121
- expect(@mr.inputs).to eq([["%5Bfoo%5D", "%28bar%29","[]()"]])
165
+ mr.add(["[foo]","(bar)","[]()"])
166
+ expect(mr.inputs).to eq([["%5Bfoo%5D", "%28bar%29","[]()"]])
122
167
  end
123
168
 
124
169
  it "uses an escaped bucket name as the single input" do
125
- @mr.add(Riak::Bucket.new(@client, "[foo]"))
126
- expect(@mr.inputs).to eq("%5Bfoo%5D")
127
- @mr.add("docs")
128
- expect(@mr.inputs).to eq("docs")
170
+ mr.add(Riak::Bucket.new(client, "[foo]"))
171
+ expect(mr.inputs).to eq("%5Bfoo%5D")
172
+ mr.add("docs")
173
+ expect(mr.inputs).to eq("docs")
129
174
  end
130
175
  end
131
176
 
@@ -134,32 +179,32 @@ describe Riak::MapReduce do
134
179
  after { Riak.url_decoding = @urldecode }
135
180
 
136
181
  it "adds bucket/key pairs to the inputs with bucket and key unescaped" do
137
- @mr.add("[foo]","(bar)")
138
- expect(@mr.inputs).to eq([["[foo]","(bar)"]])
182
+ mr.add("[foo]","(bar)")
183
+ expect(mr.inputs).to eq([["[foo]","(bar)"]])
139
184
  end
140
185
 
141
186
  it "adds an unescaped array containing a bucket/key pair to the inputs" do
142
- @mr.add(["[foo]","(bar)"])
143
- expect(@mr.inputs).to eq([["[foo]","(bar)"]])
187
+ mr.add(["[foo]","(bar)"])
188
+ expect(mr.inputs).to eq([["[foo]","(bar)"]])
144
189
  end
145
190
 
146
191
  it "adds an object to the inputs by its unescaped bucket and key" do
147
- bucket = Riak::Bucket.new(@client, "[foo]")
192
+ bucket = Riak::Bucket.new(client, "[foo]")
148
193
  obj = Riak::RObject.new(bucket, "(bar)")
149
- @mr.add(obj)
150
- expect(@mr.inputs).to eq([["[foo]","(bar)"]])
194
+ mr.add(obj)
195
+ expect(mr.inputs).to eq([["[foo]","(bar)"]])
151
196
  end
152
197
 
153
198
  it "adds an unescaped array containing a bucket/key/key-data triple to the inputs" do
154
- @mr.add(["[foo]","(bar)","[]()"])
155
- expect(@mr.inputs).to eq([["[foo]","(bar)","[]()"]])
199
+ mr.add(["[foo]","(bar)","[]()"])
200
+ expect(mr.inputs).to eq([["[foo]","(bar)","[]()"]])
156
201
  end
157
202
 
158
203
  it "uses an unescaped bucket name as the single input" do
159
- @mr.add(Riak::Bucket.new(@client, "[foo]"))
160
- expect(@mr.inputs).to eq("[foo]")
161
- @mr.add("docs")
162
- expect(@mr.inputs).to eq("docs")
204
+ mr.add(Riak::Bucket.new(client, "[foo]"))
205
+ expect(mr.inputs).to eq("[foo]")
206
+ mr.add("docs")
207
+ expect(mr.inputs).to eq("docs")
163
208
  end
164
209
  end
165
210
  end
@@ -169,32 +214,32 @@ describe Riak::MapReduce do
169
214
  after { Riak.escaper = @oldesc }
170
215
 
171
216
  it "adds bucket/key pairs to the inputs with bucket and key escaped" do
172
- @mr.add("[foo]","(bar)")
173
- expect(@mr.inputs).to eq([["%5Bfoo%5D","%28bar%29"]])
217
+ mr.add("[foo]","(bar)")
218
+ expect(mr.inputs).to eq([["%5Bfoo%5D","%28bar%29"]])
174
219
  end
175
220
 
176
221
  it "adds an escaped array containing a bucket/key pair to the inputs" do
177
- @mr.add(["[foo]","(bar)"])
178
- expect(@mr.inputs).to eq([["%5Bfoo%5D","%28bar%29"]])
222
+ mr.add(["[foo]","(bar)"])
223
+ expect(mr.inputs).to eq([["%5Bfoo%5D","%28bar%29"]])
179
224
  end
180
225
 
181
226
  it "adds an object to the inputs by its escaped bucket and key" do
182
- bucket = Riak::Bucket.new(@client, "[foo]")
227
+ bucket = Riak::Bucket.new(client, "[foo]")
183
228
  obj = Riak::RObject.new(bucket, "(bar)")
184
- @mr.add(obj)
185
- expect(@mr.inputs).to eq([["%5Bfoo%5D", "%28bar%29"]])
229
+ mr.add(obj)
230
+ expect(mr.inputs).to eq([["%5Bfoo%5D", "%28bar%29"]])
186
231
  end
187
232
 
188
233
  it "adds an escaped array containing a bucket/key/key-data triple to the inputs" do
189
- @mr.add(["[foo]","(bar)","[]()"])
190
- expect(@mr.inputs).to eq([["%5Bfoo%5D", "%28bar%29","[]()"]])
234
+ mr.add(["[foo]","(bar)","[]()"])
235
+ expect(mr.inputs).to eq([["%5Bfoo%5D", "%28bar%29","[]()"]])
191
236
  end
192
237
 
193
238
  it "uses an escaped bucket name as the single input" do
194
- @mr.add(Riak::Bucket.new(@client, "[foo]"))
195
- expect(@mr.inputs).to eq("%5Bfoo%5D")
196
- @mr.add("docs")
197
- expect(@mr.inputs).to eq("docs")
239
+ mr.add(Riak::Bucket.new(client, "[foo]"))
240
+ expect(mr.inputs).to eq("%5Bfoo%5D")
241
+ mr.add("docs")
242
+ expect(mr.inputs).to eq("docs")
198
243
  end
199
244
  end
200
245
 
@@ -203,14 +248,14 @@ describe Riak::MapReduce do
203
248
  after { Riak.disable_list_keys_warnings = true }
204
249
 
205
250
  it "warns about list-keys on buckets" do
206
- expect(@mr).to receive(:warn).twice
207
- @mr.add("foo")
208
- @mr.add(Riak::Bucket.new(@client, "foo"))
251
+ expect(mr).to receive(:warn).twice
252
+ mr.add("foo")
253
+ mr.add(Riak::Bucket.new(client, "foo"))
209
254
  end
210
255
 
211
256
  it "warns about list-keys on key-filters" do
212
- expect(@mr).to receive(:warn)
213
- @mr.filter("foo") { matches "bar" }
257
+ expect(mr).to receive(:warn)
258
+ mr.filter("foo") { matches "bar" }
214
259
  end
215
260
  end
216
261
  end
@@ -218,39 +263,39 @@ describe Riak::MapReduce do
218
263
  [:map, :reduce].each do |type|
219
264
  describe "adding #{type} phases" do
220
265
  it "returns self for chaining" do
221
- expect(@mr.send(type, "function(){}")).to eq(@mr)
266
+ expect(mr.send(type, "function(){}")).to eq(mr)
222
267
  end
223
268
 
224
269
  it "accepts a function string" do
225
- @mr.send(type, "function(){}")
226
- expect(@mr.query.size).to eq(1)
227
- phase = @mr.query.first
270
+ mr.send(type, "function(){}")
271
+ expect(mr.query.size).to eq(1)
272
+ phase = mr.query.first
228
273
  expect(phase.function).to eq("function(){}")
229
274
  expect(phase.type).to eq(type)
230
275
  end
231
276
 
232
277
  it "accepts a function and options" do
233
- @mr.send(type, "function(){}", :keep => true)
234
- expect(@mr.query.size).to eq(1)
235
- phase = @mr.query.first
278
+ mr.send(type, "function(){}", :keep => true)
279
+ expect(mr.query.size).to eq(1)
280
+ phase = mr.query.first
236
281
  expect(phase.function).to eq("function(){}")
237
282
  expect(phase.type).to eq(type)
238
283
  expect(phase.keep).to be_truthy
239
284
  end
240
285
 
241
286
  it "accepts a module/function pair" do
242
- @mr.send(type, ["riak","mapsomething"])
243
- expect(@mr.query.size).to eq(1)
244
- phase = @mr.query.first
287
+ mr.send(type, ["riak","mapsomething"])
288
+ expect(mr.query.size).to eq(1)
289
+ phase = mr.query.first
245
290
  expect(phase.function).to eq(["riak", "mapsomething"])
246
291
  expect(phase.type).to eq(type)
247
292
  expect(phase.language).to eq("erlang")
248
293
  end
249
294
 
250
295
  it "accepts a module/function pair with extra options" do
251
- @mr.send(type, ["riak", "mapsomething"], :arg => [1000])
252
- expect(@mr.query.size).to eq(1)
253
- phase = @mr.query.first
296
+ mr.send(type, ["riak", "mapsomething"], :arg => [1000])
297
+ expect(mr.query.size).to eq(1)
298
+ phase = mr.query.first
254
299
  expect(phase.function).to eq(["riak", "mapsomething"])
255
300
  expect(phase.type).to eq(type)
256
301
  expect(phase.language).to eq("erlang")
@@ -261,22 +306,22 @@ describe Riak::MapReduce do
261
306
 
262
307
  describe "adding link phases" do
263
308
  it "returns self for chaining" do
264
- expect(@mr.link({})).to eq(@mr)
309
+ expect(mr.link({})).to eq(mr)
265
310
  end
266
311
 
267
312
  it "accepts a WalkSpec" do
268
- @mr.link(Riak::WalkSpec.new(:tag => "next"))
269
- expect(@mr.query.size).to eq(1)
270
- phase = @mr.query.first
313
+ mr.link(Riak::WalkSpec.new(:tag => "next"))
314
+ expect(mr.query.size).to eq(1)
315
+ phase = mr.query.first
271
316
  expect(phase.type).to eq(:link)
272
317
  expect(phase.function).to be_kind_of(Riak::WalkSpec)
273
318
  expect(phase.function.tag).to eq("next")
274
319
  end
275
320
 
276
321
  it "accepts a WalkSpec and a hash of options" do
277
- @mr.link(Riak::WalkSpec.new(:bucket => "foo"), :keep => true)
278
- expect(@mr.query.size).to eq(1)
279
- phase = @mr.query.first
322
+ mr.link(Riak::WalkSpec.new(:bucket => "foo"), :keep => true)
323
+ expect(mr.query.size).to eq(1)
324
+ phase = mr.query.first
280
325
  expect(phase.type).to eq(:link)
281
326
  expect(phase.function).to be_kind_of(Riak::WalkSpec)
282
327
  expect(phase.function.bucket).to eq("foo")
@@ -284,9 +329,9 @@ describe Riak::MapReduce do
284
329
  end
285
330
 
286
331
  it "accepts a hash of options intermingled with the walk spec options" do
287
- @mr.link(:tag => "snakes", :arg => [1000])
288
- expect(@mr.query.size).to eq(1)
289
- phase = @mr.query.first
332
+ mr.link(:tag => "snakes", :arg => [1000])
333
+ expect(mr.query.size).to eq(1)
334
+ phase = mr.query.first
290
335
  expect(phase.arg).to eq([1000])
291
336
  expect(phase.function).to be_kind_of(Riak::WalkSpec)
292
337
  expect(phase.function.tag).to eq("snakes")
@@ -295,59 +340,59 @@ describe Riak::MapReduce do
295
340
 
296
341
  describe "converting to JSON for the job" do
297
342
  it "includes the inputs and query keys" do
298
- expect(@mr.to_json).to match(/"inputs":/)
343
+ expect(mr.to_json).to match(/"inputs":/)
299
344
  end
300
345
 
301
346
  it "maps phases to their JSON equivalents" do
302
347
  phase = Riak::MapReduce::Phase.new(:type => :map, :function => "function(){}")
303
- @mr.query << phase
304
- expect(@mr.to_json).to include('"source":"function(){}"')
305
- expect(@mr.to_json).to include('"query":[{"map":{')
348
+ mr.query << phase
349
+ expect(mr.to_json).to include('"source":"function(){}"')
350
+ expect(mr.to_json).to include('"query":[{"map":{')
306
351
  end
307
352
 
308
353
  it "emits only the bucket name when the input is the whole bucket" do
309
- @mr.add("foo")
310
- expect(@mr.to_json).to include('"inputs":"foo"')
354
+ mr.add("foo")
355
+ expect(mr.to_json).to include('"inputs":"foo"')
311
356
  end
312
357
 
313
358
  it "emits an array of inputs when there are multiple inputs" do
314
- @mr.add("foo","bar",1000).add("foo","baz")
315
- expect(@mr.to_json).to include('"inputs":[["foo","bar",1000],["foo","baz"]]')
359
+ mr.add("foo","bar",1000).add("foo","baz")
360
+ expect(mr.to_json).to include('"inputs":[["foo","bar",1000],["foo","baz"]]')
316
361
  end
317
362
 
318
363
  it "adds the timeout value when set" do
319
- @mr.timeout(50000)
320
- expect(@mr.to_json).to include('"timeout":50000')
364
+ mr.timeout(50000)
365
+ expect(mr.to_json).to include('"timeout":50000')
321
366
  end
322
367
  end
323
368
 
324
369
  it "returns self from setting the timeout" do
325
- expect(@mr.timeout(5000)).to eq(@mr)
370
+ expect(mr.timeout(5000)).to eq(mr)
326
371
  end
327
372
 
328
373
  describe "executing the map reduce job" do
329
374
  before :each do
330
- @mr.map("Riak.mapValues",:keep => true)
375
+ mr.map("Riak.mapValues",:keep => true)
331
376
  end
332
377
 
333
378
  it "submits the query to the backend" do
334
- expect(@backend).to receive(:mapred).with(@mr).and_return([])
335
- expect(@mr.run).to eq([])
379
+ expect(backend).to receive(:mapred).with(mr).and_return([])
380
+ expect(mr.run).to eq([])
336
381
  end
337
382
 
338
383
  it "passes the given block to the backend for streaming" do
339
384
  arr = []
340
- expect(@backend).to receive(:mapred).with(@mr).and_yield("foo").and_yield("bar")
341
- @mr.run {|v| arr << v }
385
+ expect(backend).to receive(:mapred).with(mr).and_yield("foo").and_yield("bar")
386
+ mr.run {|v| arr << v }
342
387
  expect(arr).to eq(["foo", "bar"])
343
388
  end
344
389
 
345
390
  it "interprets failed requests with JSON content-types as map reduce errors" do
346
- allow(@backend).to receive(:mapred).
391
+ allow(backend).to receive(:mapred).
347
392
  and_raise(Riak::ProtobuffsFailedRequest.new(:server_error, '{"error":"syntax error"}'))
348
- expect{ @mr.run }.to raise_error(Riak::MapReduceError)
393
+ expect{ mr.run }.to raise_error(Riak::MapReduceError)
349
394
  begin
350
- @mr.run
395
+ mr.run
351
396
  rescue Riak::MapReduceError => mre
352
397
  expect(mre.message).to include('{"error":"syntax error"}')
353
398
  else
@@ -356,9 +401,9 @@ describe Riak::MapReduce do
356
401
  end
357
402
 
358
403
  it "re-raises non-JSON error responses" do
359
- allow(@backend).to receive(:mapred).
404
+ allow(backend).to receive(:mapred).
360
405
  and_raise(Riak::ProtobuffsFailedRequest.new(:server_error, 'Oops, you bwoke it.'))
361
- expect { @mr.run }.to raise_error(Riak::FailedRequest)
406
+ expect { mr.run }.to raise_error(Riak::FailedRequest)
362
407
  end
363
408
  end
364
409
  end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ require 'riak/search/index'
3
+
4
+ describe Riak::Search::Index do
5
+ let(:index_name){ 'index_name' }
6
+ let(:schema_name){ 'schema_name' }
7
+
8
+ let(:index_exists_expectation) do
9
+ expect(backend).to receive(:get_search_index).
10
+ with(index_name).
11
+ and_return(index_exists_response)
12
+ end
13
+
14
+ let(:index_exists_response) do
15
+ instance_double(
16
+ 'Riak::Client::BeefcakeProtobuffsBackend::RpbYokozunaIndexGetResp',
17
+ index: [{ name: index_name, schema: schema_name, n_val: 3 }]
18
+ )
19
+ end
20
+
21
+ let(:client){ instance_double 'Riak::Client' }
22
+ let(:backend) do
23
+ be = instance_double 'Riak::Client::BeefcakeProtobuffsBackend'
24
+ allow(client).to receive(:backend).and_yield(be)
25
+ be
26
+ end
27
+
28
+ subject { described_class.new client, index_name }
29
+
30
+ it 'creates index objects with a client and index name' do
31
+ expect{ described_class.new client, index_name }.to_not raise_error
32
+ end
33
+
34
+ it 'tests for index existence' do
35
+ index_exists_expectation
36
+ expect(subject).to be_exists
37
+ end
38
+
39
+ it 'permits index creation' do
40
+ expect(backend).to receive(:get_search_index).
41
+ with(index_name).
42
+ and_raise(Riak::ProtobuffsFailedRequest.new(:not_found, 'not found'))
43
+
44
+ expect(backend).to receive(:create_search_index).
45
+ with(index_name, nil, nil)
46
+
47
+ expect{ subject.create! }.to_not raise_error
48
+ end
49
+
50
+ it 'raises an error when creating an index that already exists' do
51
+ index_exists_expectation
52
+
53
+ expect{ subject.create! }.to raise_error(Riak::SearchError::IndexExistsError)
54
+ end
55
+
56
+ it 'returns data about the index' do
57
+ index_exists_expectation
58
+
59
+ expect(subject.n_val).to eq 3
60
+ expect(subject.schema).to eq schema_name
61
+ end
62
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+ require 'riak/search/query'
3
+
4
+ describe Riak::Search::Query do
5
+ let(:client) do
6
+ instance_double('Riak::Client').tap do |c|
7
+ allow(c).to receive(:backend).and_yield(backend)
8
+ end
9
+ end
10
+ let(:index) do
11
+ instance_double(
12
+ 'Riak::Search::Index',
13
+ name: index_name,
14
+ 'exists?' => true).tap do |i|
15
+ allow(i).to receive(:is_a?).with(String).and_return(false)
16
+ allow(i).to receive(:is_a?).with(Riak::Search::Index).and_return(true)
17
+ end
18
+ end
19
+ let(:backend){ instance_double 'Riak::Client::BeefcakeProtobuffsBackend' }
20
+
21
+ let(:index_name){ 'yokozuna' }
22
+ let(:term){ 'bitcask' }
23
+
24
+ let(:raw_results) do
25
+ {
26
+ "max_score"=>0.7729485034942627,
27
+ "num_found"=>3,
28
+ "docs"=>[
29
+ {"score"=>"7.72948500000000038312e-01",
30
+ "_yz_rb"=>"search_test-1419261439-ew70sak2qr",
31
+ "_yz_rt"=>"yokozuna",
32
+ "_yz_rk"=>"bitcask-10"},
33
+ {"score"=>"2.35808490000000009479e-01",
34
+ "_yz_rb"=>"search_test-1419261439-ew70sak2qr",
35
+ "_yz_rt"=>"yokozuna",
36
+ "_yz_rk"=>"bitcask-9"},
37
+ {"score"=>"6.73738599999999937529e-02",
38
+ "_yz_rb"=>"search_test-1419261439-ew70sak2qr",
39
+ "_yz_rt"=>"yokozuna",
40
+ "_yz_rk"=>"bitcask-4"}
41
+ ]
42
+ }
43
+ end
44
+
45
+ subject { described_class.new client, index, term }
46
+
47
+ it 'creates query objects with a client, index, and query string' do
48
+ expect{ described_class.new client, index, term }.to_not raise_error
49
+ end
50
+
51
+ it 'creates query objects with a client, index name, and query string' do
52
+ class_double('Riak::Search::Index', new: index).as_stubbed_const
53
+ allow(index).to receive(:is_a?).with(Riak::Search::Index).and_return(true)
54
+
55
+ expect{ described_class.new client, index_name, term }.to_not raise_error
56
+ end
57
+
58
+ it 'errors when querying with a non-existent index' do
59
+ expect(index).to receive(:exists?).and_return(false)
60
+ expect{ described_class.new client, index, term }.to raise_error(Riak::SearchError::IndexNonExistError)
61
+ end
62
+
63
+ it 'allows specifying other query options on creation' do
64
+ expect(backend).to receive(:search).
65
+ with(index_name, term, hash_including(rows: 5)).
66
+ and_return(raw_results)
67
+
68
+ q = described_class.new client, index, term, rows: 5
69
+ expect{ q.results }.to_not raise_error
70
+ end
71
+
72
+ it 'allows specifying query options with accessors' do
73
+ expect(backend).to receive(:search).
74
+ with(index_name, term, hash_including(rows: 5)).
75
+ and_return(raw_results)
76
+
77
+ subject.rows = 5
78
+ expect{ subject.results }.to_not raise_error
79
+ end
80
+
81
+ it 'returns a ResultCollection' do
82
+ expect(backend).to receive(:search).
83
+ with(index_name, term, instance_of(Hash)).
84
+ and_return(raw_results)
85
+
86
+ expect(subject.results).to be_a Riak::Search::ResultCollection
87
+ end
88
+ end