libcouchbase-mapo 1.4.1

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 (104) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +38 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +24 -0
  8. data/README.md +445 -0
  9. data/Rakefile +76 -0
  10. data/ext/README.md +6 -0
  11. data/ext/Rakefile +19 -0
  12. data/lib/libcouchbase.rb +40 -0
  13. data/lib/libcouchbase/bucket.rb +825 -0
  14. data/lib/libcouchbase/callbacks.rb +69 -0
  15. data/lib/libcouchbase/connection.rb +886 -0
  16. data/lib/libcouchbase/design_docs.rb +92 -0
  17. data/lib/libcouchbase/error.rb +68 -0
  18. data/lib/libcouchbase/ext/libcouchbase.rb +1175 -0
  19. data/lib/libcouchbase/ext/libcouchbase/cmdbase.rb +23 -0
  20. data/lib/libcouchbase/ext/libcouchbase/cmdcounter.rb +36 -0
  21. data/lib/libcouchbase/ext/libcouchbase/cmdendure.rb +26 -0
  22. data/lib/libcouchbase/ext/libcouchbase/cmdfts.rb +24 -0
  23. data/lib/libcouchbase/ext/libcouchbase/cmdget.rb +30 -0
  24. data/lib/libcouchbase/ext/libcouchbase/cmdgetreplica.rb +49 -0
  25. data/lib/libcouchbase/ext/libcouchbase/cmdhttp.rb +58 -0
  26. data/lib/libcouchbase/ext/libcouchbase/cmdn1ql.rb +40 -0
  27. data/lib/libcouchbase/ext/libcouchbase/cmdobseqno.rb +33 -0
  28. data/lib/libcouchbase/ext/libcouchbase/cmdobserve.rb +30 -0
  29. data/lib/libcouchbase/ext/libcouchbase/cmdstore.rb +40 -0
  30. data/lib/libcouchbase/ext/libcouchbase/cmdstoredur.rb +45 -0
  31. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +61 -0
  32. data/lib/libcouchbase/ext/libcouchbase/cmdverbosity.rb +29 -0
  33. data/lib/libcouchbase/ext/libcouchbase/cmdviewquery.rb +61 -0
  34. data/lib/libcouchbase/ext/libcouchbase/contigbuf.rb +14 -0
  35. data/lib/libcouchbase/ext/libcouchbase/create_st.rb +15 -0
  36. data/lib/libcouchbase/ext/libcouchbase/create_st0.rb +23 -0
  37. data/lib/libcouchbase/ext/libcouchbase/create_st1.rb +26 -0
  38. data/lib/libcouchbase/ext/libcouchbase/create_st2.rb +32 -0
  39. data/lib/libcouchbase/ext/libcouchbase/create_st3.rb +26 -0
  40. data/lib/libcouchbase/ext/libcouchbase/crst_u.rb +20 -0
  41. data/lib/libcouchbase/ext/libcouchbase/durability_opts_st_v.rb +11 -0
  42. data/lib/libcouchbase/ext/libcouchbase/durability_opts_t.rb +14 -0
  43. data/lib/libcouchbase/ext/libcouchbase/durabilityopt_sv0.rb +63 -0
  44. data/lib/libcouchbase/ext/libcouchbase/enums.rb +1007 -0
  45. data/lib/libcouchbase/ext/libcouchbase/fragbuf.rb +18 -0
  46. data/lib/libcouchbase/ext/libcouchbase/ftshandle.rb +7 -0
  47. data/lib/libcouchbase/ext/libcouchbase/histogram.rb +34 -0
  48. data/lib/libcouchbase/ext/libcouchbase/http_request_t.rb +7 -0
  49. data/lib/libcouchbase/ext/libcouchbase/keybuf.rb +20 -0
  50. data/lib/libcouchbase/ext/libcouchbase/multicmd_ctx.rb +30 -0
  51. data/lib/libcouchbase/ext/libcouchbase/mutation_token.rb +17 -0
  52. data/lib/libcouchbase/ext/libcouchbase/n1qlhandle.rb +7 -0
  53. data/lib/libcouchbase/ext/libcouchbase/n1qlparams.rb +7 -0
  54. data/lib/libcouchbase/ext/libcouchbase/respbase.rb +29 -0
  55. data/lib/libcouchbase/ext/libcouchbase/respcounter.rb +32 -0
  56. data/lib/libcouchbase/ext/libcouchbase/respendure.rb +49 -0
  57. data/lib/libcouchbase/ext/libcouchbase/respfts.rb +40 -0
  58. data/lib/libcouchbase/ext/libcouchbase/respget.rb +44 -0
  59. data/lib/libcouchbase/ext/libcouchbase/resphttp.rb +48 -0
  60. data/lib/libcouchbase/ext/libcouchbase/respmcversion.rb +38 -0
  61. data/lib/libcouchbase/ext/libcouchbase/respn1ql.rb +41 -0
  62. data/lib/libcouchbase/ext/libcouchbase/respobseqno.rb +52 -0
  63. data/lib/libcouchbase/ext/libcouchbase/respobserve.rb +41 -0
  64. data/lib/libcouchbase/ext/libcouchbase/respserverbase.rb +32 -0
  65. data/lib/libcouchbase/ext/libcouchbase/respstats.rb +38 -0
  66. data/lib/libcouchbase/ext/libcouchbase/respstore.rb +32 -0
  67. data/lib/libcouchbase/ext/libcouchbase/respstoredur.rb +38 -0
  68. data/lib/libcouchbase/ext/libcouchbase/respsubdoc.rb +35 -0
  69. data/lib/libcouchbase/ext/libcouchbase/respviewquery.rb +67 -0
  70. data/lib/libcouchbase/ext/libcouchbase/sdentry.rb +22 -0
  71. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +31 -0
  72. data/lib/libcouchbase/ext/libcouchbase/t.rb +7 -0
  73. data/lib/libcouchbase/ext/libcouchbase/valbuf.rb +22 -0
  74. data/lib/libcouchbase/ext/libcouchbase/valbuf_u_buf.rb +14 -0
  75. data/lib/libcouchbase/ext/libcouchbase/viewhandle.rb +7 -0
  76. data/lib/libcouchbase/ext/libcouchbase_libuv.rb +22 -0
  77. data/lib/libcouchbase/ext/tasks.rb +39 -0
  78. data/lib/libcouchbase/n1ql.rb +78 -0
  79. data/lib/libcouchbase/query_full_text.rb +147 -0
  80. data/lib/libcouchbase/query_n1ql.rb +123 -0
  81. data/lib/libcouchbase/query_view.rb +135 -0
  82. data/lib/libcouchbase/results_fiber.rb +281 -0
  83. data/lib/libcouchbase/results_native.rb +220 -0
  84. data/lib/libcouchbase/subdoc_request.rb +139 -0
  85. data/lib/libcouchbase/version.rb +5 -0
  86. data/libcouchbase.gemspec +68 -0
  87. data/spec/bucket_spec.rb +290 -0
  88. data/spec/connection_spec.rb +257 -0
  89. data/spec/design_docs_spec.rb +31 -0
  90. data/spec/error_spec.rb +26 -0
  91. data/spec/fts_spec.rb +135 -0
  92. data/spec/n1ql_spec.rb +206 -0
  93. data/spec/results_libuv_spec.rb +244 -0
  94. data/spec/results_native_spec.rb +259 -0
  95. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/design.json +1 -0
  96. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/data-0000.cbb +0 -0
  97. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/failover.json +1 -0
  98. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/meta.json +1 -0
  99. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/seqno.json +1 -0
  100. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/snapshot_markers.json +1 -0
  101. data/spec/subdoc_spec.rb +192 -0
  102. data/spec/view_spec.rb +201 -0
  103. data/windows_build.md +36 -0
  104. metadata +265 -0
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require 'libcouchbase'
4
+
5
+
6
+ describe Libcouchbase::N1QL, n1ql_query: true do
7
+ before :each do
8
+ @bucket = Libcouchbase::Bucket.new
9
+ @n1ql = @bucket.n1ql
10
+ @log = []
11
+ end
12
+
13
+ after :each do
14
+ @bucket = nil
15
+ @log = nil
16
+ end
17
+
18
+ it "should build a basic query" do
19
+ @n1ql.select('*').from(:default).where('port == 10001')
20
+ expect(@n1ql.to_s).to eq("SELECT *\nFROM default\nWHERE port == 10001\n")
21
+ end
22
+
23
+ describe 'perform native queries' do
24
+ before :each do
25
+ @n1ql.select('*').from(:default).where('type == "mod"')
26
+ end
27
+
28
+ it "should iterate results" do
29
+ results = @n1ql.results
30
+ @log << results.to_a.count
31
+ @log << results.count
32
+ @log << results.collect { |res| res.nil? }
33
+ expect(@log).to eq([12, 12,
34
+ [false, false, false, false, false,
35
+ false, false, false, false, false,
36
+ false, false
37
+ ]])
38
+ end
39
+
40
+ it "should cancel iteration when an error occurs" do
41
+ results = @n1ql.results
42
+ begin
43
+ count = 0
44
+ results.collect { |res|
45
+ raise 'err' if count > 0
46
+ @log << res.nil?
47
+ count += 1
48
+ }
49
+ rescue => e
50
+ @log << :error
51
+ end
52
+ @log << results.count
53
+ expect(@log).to eq([false, :error, 12])
54
+ end
55
+
56
+ it "should cancel iteration when an error occurs in row modifer" do
57
+ count = 0
58
+ results = @n1ql.results do |row|
59
+ raise 'err' if count > 0
60
+ count += 1
61
+ row
62
+ end
63
+
64
+ begin
65
+ count = 0
66
+ results.collect { |res|
67
+ @log << res.nil?
68
+ }
69
+ rescue => e
70
+ @log << e.message
71
+ end
72
+ expect(@log).to eq([false, 'err'])
73
+ end
74
+ end
75
+
76
+ describe 'perform queries in libuv reactor' do
77
+ before :each do
78
+ @n1ql.select('*').from(:default).where('type == "mod"')
79
+ @reactor = ::Libuv::Reactor.default
80
+ end
81
+
82
+ it "should iterate results" do
83
+ @reactor.run { |reactor|
84
+ results = @n1ql.results
85
+ @log << results.to_a.count
86
+ @log << results.count
87
+ @log << results.collect { |res| res.nil? }
88
+ }
89
+
90
+ expect(@log).to eq([12, 12,
91
+ [false, false, false, false, false,
92
+ false, false, false, false, false,
93
+ false, false
94
+ ]]
95
+ )
96
+ end
97
+
98
+ it "should cancel iteration when an error occurs" do
99
+ @reactor.run { |reactor|
100
+ results = @n1ql.results
101
+ begin
102
+ count = 0
103
+ results.collect { |res|
104
+ raise 'err' if count > 0
105
+ @log << res.nil?
106
+ count += 1
107
+ }
108
+ rescue => e
109
+ @log << :error
110
+ end
111
+ @log << results.count
112
+ }
113
+ expect(@log).to eq([false, :error, 12])
114
+ end
115
+
116
+ it "should cancel iteration when an error occurs in row modifer" do
117
+ @reactor.run { |reactor|
118
+ count = 0
119
+ results = @n1ql.results do |row|
120
+ raise 'err' if count > 0
121
+ count += 1
122
+ row
123
+ end
124
+
125
+ begin
126
+ count = 0
127
+ results.collect { |res|
128
+ @log << res.nil?
129
+ }
130
+ rescue => e
131
+ @log << e.message
132
+ end
133
+ }
134
+ expect(@log).to eq([false, 'err'])
135
+ end
136
+ end
137
+
138
+ describe 'perform queries in event machine' do
139
+ require 'em-synchrony'
140
+
141
+ before :each do
142
+ @n1ql.select('*').from(:default).where('type == "mod"')
143
+ end
144
+
145
+ it "should iterate results" do
146
+ EM.synchrony {
147
+ results = @n1ql.results
148
+ @log << results.to_a.count
149
+ @log << results.count
150
+ @log << results.collect { |res| res.nil? }
151
+
152
+ EM.stop
153
+ }
154
+
155
+ expect(@log).to eq([12, 12,
156
+ [false, false, false, false, false,
157
+ false, false, false, false, false,
158
+ false, false
159
+ ]]
160
+ )
161
+ end
162
+
163
+ it "should cancel iteration when an error occurs" do
164
+ EM.synchrony {
165
+ results = @n1ql.results
166
+ begin
167
+ count = 0
168
+ results.collect { |res|
169
+ raise 'err' if count > 0
170
+ @log << res.nil?
171
+ count += 1
172
+ }
173
+ rescue => e
174
+ @log << :error
175
+ end
176
+ @log << results.count
177
+
178
+ EM.stop
179
+ }
180
+ expect(@log).to eq([false, :error, 12])
181
+ end
182
+
183
+ it "should cancel iteration when an error occurs in row modifer" do
184
+ EM.synchrony {
185
+ count = 0
186
+ results = @n1ql.results do |row|
187
+ raise 'err' if count > 0
188
+ count += 1
189
+ row
190
+ end
191
+
192
+ begin
193
+ count = 0
194
+ results.collect { |res|
195
+ @log << res.nil?
196
+ }
197
+ rescue => e
198
+ @log << e.message
199
+ end
200
+
201
+ EM.stop
202
+ }
203
+ expect(@log).to eq([false, 'err'])
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,244 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require 'libcouchbase'
4
+ require 'uv-rays'
5
+
6
+
7
+ class MockQuery
8
+ def initialize(log, preloaded = 0)
9
+ @count = 4
10
+ @preloaded = preloaded
11
+ @log = log
12
+ end
13
+
14
+ attr_accessor :preloaded
15
+
16
+ def get_count(metadata)
17
+ metadata[:total_rows]
18
+ end
19
+
20
+ def perform(limit: @count, **options, &blk)
21
+ @curr = 0
22
+ @callback = blk
23
+ @limit = limit
24
+
25
+ if @sched
26
+ @sched.cancel
27
+ @sched = nil
28
+ end
29
+ @error = nil
30
+
31
+ preloaded.times { |i| blk.call(false, i) }
32
+ next_item(preloaded)
33
+ end
34
+
35
+ def next_item(i = 0)
36
+ if i == @limit
37
+ @sched = reactor.scheduler.in(50) do
38
+ @callback.call(:final, {total_rows: @count})
39
+ end
40
+ else
41
+ @sched = reactor.scheduler.in(100) do
42
+ @log << :new_row
43
+ next_item(i + 1)
44
+ @callback.call(false, i)
45
+ end
46
+ end
47
+ end
48
+
49
+ def cancel
50
+ return if @error
51
+ if @sched
52
+ @sched.cancel
53
+ @sched = nil
54
+ end
55
+ @error = :cancelled
56
+ @sched = reactor.scheduler.in(50) do
57
+ @callback.call(:final, {total_rows: @count})
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ describe Libcouchbase::ResultsLibuv do
64
+ before :each do
65
+ @log = []
66
+ @reactor = ::Libuv::Reactor.default
67
+ @reactor.notifier do |err|
68
+ @reactor.stop
69
+ @log << err
70
+ end
71
+ @timeout = @reactor.timer do
72
+ @timeout.close
73
+ @reactor.stop
74
+ @log << "test timed out"
75
+ end
76
+ @timeout.start(5000)
77
+ @timeout.unref
78
+ @query = MockQuery.new(@log)
79
+ @view = Libcouchbase::ResultsLibuv.new(@query)
80
+ expect(@log).to eq([])
81
+ end
82
+
83
+ after :each do
84
+ @timeout.close
85
+ end
86
+
87
+ it "should stream the response" do
88
+ @reactor.run { |reactor|
89
+ @view.each {|i| @log << i }
90
+ }
91
+
92
+ expect(@log).to eq([:new_row, 0, :new_row, 1, :new_row, 2, :new_row, 3])
93
+ expect(@view.complete_result_set).to be(true)
94
+ expect(@view.query_in_progress).to be(false)
95
+ expect(@view.query_completed).to be(true)
96
+ end
97
+
98
+ it "should continue to stream the response even if some has already been loaded" do
99
+ @reactor.run { |reactor|
100
+ @query.preloaded = 2
101
+ @view.each {|i| @log << i }
102
+ }
103
+
104
+ expect(@view.complete_result_set).to be(true)
105
+ expect(@view.query_in_progress).to be(false)
106
+ expect(@view.query_completed).to be(true)
107
+ expect(@log).to eq([0, 1, :new_row, 2, :new_row, 3])
108
+ end
109
+
110
+ it "should only load what is required" do
111
+ @reactor.run { |reactor|
112
+ @log << @view.take(2)
113
+ @log << @view.first
114
+ expect(@view.complete_result_set).to be(false)
115
+ expect(@view.query_in_progress).to be(false)
116
+ expect(@view.query_completed).to be(true)
117
+ @log << @view.to_a
118
+ }
119
+
120
+ expect(@view.complete_result_set).to be(true)
121
+ expect(@view.query_in_progress).to be(false)
122
+ expect(@view.query_completed).to be(true)
123
+ expect(@log).to eq([:new_row, :new_row, [0, 1], 0, :new_row, :new_row, :new_row, :new_row, [0, 1, 2, 3]])
124
+ end
125
+
126
+ it "should load only once" do
127
+ @reactor.run { |reactor|
128
+ @log << @view.to_a
129
+ @log << @view.to_a
130
+ }
131
+
132
+ expect(@log).to eq([:new_row, :new_row, :new_row, :new_row, [0, 1, 2, 3], [0, 1, 2, 3]])
133
+ end
134
+
135
+ it "should work as an enumerable" do
136
+ @reactor.run { |reactor|
137
+ enum = @view.each
138
+ @log << enum.next
139
+ @log << enum.next
140
+ }
141
+
142
+ expect(@log).to eq([:new_row, :new_row, :new_row, :new_row, 0, 1])
143
+ end
144
+
145
+ it "should return count" do
146
+ @reactor.run { |reactor|
147
+ @log << @view.count
148
+ @log << @view.count
149
+ }
150
+
151
+ expect(@log).to eq([:new_row, 4, 4])
152
+ end
153
+
154
+ it "should handle exceptions" do
155
+ @reactor.run { |reactor|
156
+ begin
157
+ @view.each {|i|
158
+ @log << i
159
+ raise 'what what'
160
+ }
161
+ rescue => e
162
+ @log << e.message
163
+ end
164
+ }
165
+
166
+ expect(@log).to eq([:new_row, 0, 'what what'])
167
+ end
168
+
169
+ it "should handle row modifier exceptions" do
170
+ count = 0
171
+
172
+ @view = Libcouchbase::ResultsLibuv.new(@query) { |view|
173
+ if count == 1
174
+ raise 'what what'
175
+ end
176
+ count += 1
177
+ view
178
+ }
179
+
180
+ @reactor.run { |reactor|
181
+ begin
182
+ @view.each {|i| @log << i }
183
+ rescue => e
184
+ @log << e.message
185
+ end
186
+ }
187
+
188
+ expect(@log).to eq([:new_row, 0, :new_row, 'what what'])
189
+ end
190
+
191
+ it "should handle row modifier exceptions on a short query" do
192
+ count = 0
193
+
194
+ @view = Libcouchbase::ResultsLibuv.new(@query) { |view|
195
+ raise 'what what'
196
+ }
197
+
198
+ @reactor.run { |reactor|
199
+ begin
200
+ @view.first
201
+ rescue => e
202
+ @log << e.message
203
+ end
204
+ }
205
+
206
+ expect(@log).to eq([:new_row, 'what what'])
207
+ end
208
+
209
+ it "should handle multiple exceptions" do
210
+ count = 0
211
+
212
+ @view = Libcouchbase::ResultsLibuv.new(@query) { |view|
213
+ if count == 1
214
+ raise 'second'
215
+ end
216
+ count += 1
217
+ view
218
+ }
219
+
220
+ @reactor.run { |reactor|
221
+ begin
222
+ @view.each {|i|
223
+ @log << i
224
+ raise 'first'
225
+ }
226
+ rescue => e
227
+ @log << e.message
228
+ end
229
+ }
230
+
231
+ expect(@log).to eq([:new_row, 0, 'first'])
232
+ end
233
+
234
+ it "should support streaming the response so results are not all stored in memory" do
235
+ @reactor.run { |reactor|
236
+ @view.stream {|i| @log << i }
237
+ }
238
+
239
+ expect(@view.complete_result_set).to be(false)
240
+ expect(@view.query_in_progress).to be(false)
241
+ expect(@view.query_completed).to be(true)
242
+ expect(@log).to eq([:new_row, 0, :new_row, 1, :new_row, 2, :new_row, 3])
243
+ end
244
+ end
@@ -0,0 +1,259 @@
1
+ # frozen_string_literal: true, encoding: ASCII-8BIT
2
+
3
+ require 'libcouchbase'
4
+ require 'uv-rays'
5
+
6
+
7
+ class NativeMockQuery
8
+ def initialize(log, thread = nil, preloaded = 0)
9
+ @count = 4
10
+ @preloaded = preloaded
11
+ @log = log
12
+ @thread = thread
13
+ end
14
+
15
+ attr_accessor :preloaded
16
+
17
+ def get_count(metadata)
18
+ metadata[:total_rows]
19
+ end
20
+
21
+ def perform(limit: @count, **options, &blk)
22
+ @wait = Thread.new do
23
+ @thread.run {
24
+ @curr = 0
25
+ @callback = blk
26
+ @limit = limit
27
+ @error = nil
28
+
29
+ preloaded.times { |i| blk.call(false, i) }
30
+ next_item(preloaded)
31
+ }
32
+ end
33
+ end
34
+
35
+ def wait_join
36
+ @wait.join
37
+ end
38
+
39
+ def next_item(i = 0)
40
+ if i == @limit
41
+ @sched = @thread.scheduler.in(50) do
42
+ @sched = nil
43
+ @callback.call(:final, {total_rows: @count})
44
+ end
45
+ else
46
+ @sched = @thread.scheduler.in(100) do
47
+ @log << :new_row
48
+ next_item(i + 1)
49
+ @callback.call(false, i)
50
+ end
51
+ end
52
+ end
53
+
54
+ def cancel
55
+ return if @error
56
+ @error = :cancelled
57
+
58
+ @thread.schedule {
59
+ if @sched
60
+ @sched.cancel
61
+ @sched = @thread.scheduler.in(50) do
62
+ @sched = nil
63
+ @callback.call(:final, {total_rows: @count})
64
+ end
65
+ end
66
+ }
67
+ end
68
+ end
69
+
70
+
71
+ describe Libcouchbase::ResultsNative do
72
+ before :each do
73
+ reactor = ::Libuv::Reactor.default
74
+ @qlog = []
75
+ @query = NativeMockQuery.new(@qlog, reactor)
76
+ @log = []
77
+ @view = Libcouchbase::ResultsNative.new(@query)
78
+ expect(@log).to eq([])
79
+ end
80
+
81
+ it "should stream the response" do
82
+ @view.each {|i| @log << i }
83
+
84
+ @query.wait_join
85
+
86
+ expect(@view.complete_result_set).to be(true)
87
+ expect(@view.query_in_progress).to be(false)
88
+ expect(@view.query_completed).to be(true)
89
+ expect(@qlog).to eq([:new_row, :new_row, :new_row, :new_row])
90
+ expect(@log).to eq([0, 1, 2, 3])
91
+ end
92
+
93
+ it "should continue to stream the response even if some has already been loaded" do
94
+ @query.preloaded = 2
95
+ @view.each {|i| @log << i }
96
+
97
+ @query.wait_join
98
+
99
+ expect(@view.complete_result_set).to be(true)
100
+ expect(@view.query_in_progress).to be(false)
101
+ expect(@view.query_completed).to be(true)
102
+ expect(@qlog).to eq([:new_row, :new_row])
103
+ expect(@log).to eq([0, 1, 2, 3])
104
+ end
105
+
106
+ it "should only load what is required" do
107
+ @log << @view.take(2)
108
+ expect(@view.complete_result_set).to be(false)
109
+ expect(@view.query_in_progress).to be(false)
110
+ expect(@view.query_completed).to be(true)
111
+
112
+ @log << @view.first
113
+ expect(@view.complete_result_set).to be(false)
114
+ expect(@view.query_in_progress).to be(false)
115
+ expect(@view.query_completed).to be(true)
116
+
117
+ # Wait join here as the default loop will
118
+ # be started again on a new thread
119
+ # without this wait we might end up in a deadlock...
120
+ # Don't worry, the test is sound - seriously
121
+ @query.wait_join
122
+
123
+ @log << @view.to_a
124
+ expect(@view.complete_result_set).to be(true)
125
+ expect(@view.query_in_progress).to be(false)
126
+ expect(@view.query_completed).to be(true)
127
+
128
+ @query.wait_join
129
+
130
+ expect(@qlog).to eq([:new_row, :new_row, :new_row, :new_row, :new_row, :new_row])
131
+ expect(@log).to eq([[0, 1], 0, [0, 1, 2, 3]])
132
+ end
133
+
134
+ it "should load only once" do
135
+ @log << @view.to_a
136
+ @log << @view.to_a
137
+
138
+ @query.wait_join
139
+ expect(@qlog).to eq([:new_row, :new_row, :new_row, :new_row])
140
+ expect(@log).to eq([[0, 1, 2, 3], [0, 1, 2, 3]])
141
+ end
142
+
143
+ it "should work as an enumerable" do
144
+ enum = @view.each
145
+ @log << enum.next
146
+ @log << enum.next
147
+
148
+ @query.wait_join
149
+
150
+ expect(@qlog).to eq([:new_row, :new_row, :new_row, :new_row])
151
+ expect(@log).to eq([0, 1])
152
+ end
153
+
154
+ it "should return count" do
155
+ @log << @view.count
156
+ @log << @view.count
157
+
158
+ @query.wait_join
159
+
160
+ expect(@qlog).to eq([:new_row])
161
+ expect(@log).to eq([4, 4])
162
+ end
163
+
164
+ it "should handle exceptions" do
165
+ begin
166
+ @view.each {|i|
167
+ @log << i
168
+ raise 'what what'
169
+ }
170
+ rescue => e
171
+ @log << e.message
172
+ end
173
+
174
+ @query.wait_join
175
+
176
+ expect(@qlog).to eq([:new_row])
177
+ expect(@log).to eq([0, 'what what'])
178
+ end
179
+
180
+ it "should handle row modifier exceptions" do
181
+ count = 0
182
+
183
+ @view = Libcouchbase::ResultsNative.new(@query) { |view|
184
+ if count == 1
185
+ raise 'what what'
186
+ end
187
+ count += 1
188
+ view
189
+ }
190
+
191
+ begin
192
+ @view.each {|i| @log << i }
193
+ rescue => e
194
+ @log << e.message
195
+ end
196
+
197
+ @query.wait_join
198
+
199
+ expect(@qlog).to eq([:new_row, :new_row])
200
+ expect(@log).to eq([0, 'what what'])
201
+ end
202
+
203
+ it "should handle row modifier exceptions on a short query" do
204
+ count = 0
205
+
206
+ @view = Libcouchbase::ResultsNative.new(@query) { |view|
207
+ raise 'what what'
208
+ }
209
+
210
+ begin
211
+ @view.first
212
+ rescue => e
213
+ @log << e.message
214
+ end
215
+
216
+ @query.wait_join
217
+
218
+ expect(@qlog).to eq([:new_row])
219
+ expect(@log).to eq(['what what'])
220
+ end
221
+
222
+ it "should handle multiple exceptions" do
223
+ count = 0
224
+
225
+ @view = Libcouchbase::ResultsNative.new(@query) { |view|
226
+ if count == 1
227
+ raise 'second'
228
+ end
229
+ count += 1
230
+ view
231
+ }
232
+
233
+ begin
234
+ @view.each {|i|
235
+ @log << i
236
+ raise 'first'
237
+ }
238
+ rescue => e
239
+ @log << e.message
240
+ end
241
+
242
+ @query.wait_join
243
+
244
+ expect(@qlog).to eq([:new_row])
245
+ expect(@log).to eq([0, 'first'])
246
+ end
247
+
248
+ it "should support streaming the response so results are not all stored in memory" do
249
+ @view.stream {|i| @log << i }
250
+
251
+ @query.wait_join
252
+
253
+ expect(@view.complete_result_set).to be(false)
254
+ expect(@view.query_in_progress).to be(false)
255
+ expect(@view.query_completed).to be(true)
256
+ expect(@qlog).to eq([:new_row, :new_row, :new_row, :new_row])
257
+ expect(@log).to eq([0, 1, 2, 3])
258
+ end
259
+ end