packsnap 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +17 -0
  2. data/ChangeLog +29 -0
  3. data/README.rdoc +26 -0
  4. data/Rakefile +150 -0
  5. data/doclib/msgpack.rb +54 -0
  6. data/doclib/packsnap/buffer.rb +177 -0
  7. data/doclib/packsnap/error.rb +14 -0
  8. data/doclib/packsnap/packer.rb +131 -0
  9. data/doclib/packsnap/unpacker.rb +130 -0
  10. data/ext/packsnap/buffer.cc +684 -0
  11. data/ext/packsnap/buffer.hh +439 -0
  12. data/ext/packsnap/buffer_class.cc +490 -0
  13. data/ext/packsnap/buffer_class.hh +32 -0
  14. data/ext/packsnap/compat.h +128 -0
  15. data/ext/packsnap/extconf.rb +94 -0
  16. data/ext/packsnap/packer.cc +137 -0
  17. data/ext/packsnap/packer.h +334 -0
  18. data/ext/packsnap/packer_class.cc +288 -0
  19. data/ext/packsnap/packer_class.hh +32 -0
  20. data/ext/packsnap/packsnap.h +4 -0
  21. data/ext/packsnap/rbinit.cc +52 -0
  22. data/ext/packsnap/rmem.cc +110 -0
  23. data/ext/packsnap/rmem.h +100 -0
  24. data/ext/packsnap/sysdep.h +112 -0
  25. data/ext/packsnap/sysdep_endian.h +50 -0
  26. data/ext/packsnap/sysdep_types.h +46 -0
  27. data/ext/packsnap/unpacker.cc +654 -0
  28. data/ext/packsnap/unpacker.hh +108 -0
  29. data/ext/packsnap/unpacker_class.cc +392 -0
  30. data/ext/packsnap/unpacker_class.hh +32 -0
  31. data/lib/packsnap.rb +12 -0
  32. data/lib/packsnap/version.rb +3 -0
  33. data/packsnap.gemspec +23 -0
  34. data/spec/buffer_io_spec.rb +228 -0
  35. data/spec/buffer_spec.rb +572 -0
  36. data/spec/cases.json +1 -0
  37. data/spec/cases.msg +0 -0
  38. data/spec/cases_compact.msg +0 -0
  39. data/spec/cases_spec.rb +39 -0
  40. data/spec/format_spec.rb +225 -0
  41. data/spec/packer_spec.rb +127 -0
  42. data/spec/random_compat.rb +24 -0
  43. data/spec/spec_helper.rb +21 -0
  44. data/spec/unpacker_spec.rb +128 -0
  45. metadata +183 -0
@@ -0,0 +1,32 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2012 FURUHASHI Sadayuki
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ #ifndef MSGPACK_RUBY_UNPACKER_CLASS_H__
19
+ #define MSGPACK_RUBY_UNPACKER_CLASS_H__
20
+
21
+ #include "unpacker.hh"
22
+
23
+ extern VALUE cMessagePack_Unpacker;
24
+
25
+ extern "C"
26
+ void MessagePack_Unpacker_module_init(VALUE mMessagePack);
27
+
28
+ extern "C"
29
+ VALUE MessagePack_unpack(int argc, VALUE* argv);
30
+
31
+ #endif
32
+
@@ -0,0 +1,12 @@
1
+ require 'packsnap/version'
2
+
3
+ here = File.expand_path(File.dirname(__FILE__))
4
+
5
+ require 'rbconfig'
6
+ prebuilt = File.join(here, RUBY_PLATFORM, RbConfig::CONFIG['ruby_version'])
7
+ if File.directory?(prebuilt)
8
+ require File.join(prebuilt, "packsnap")
9
+ else
10
+ require File.join(here, '..', 'ext', 'packsnap', 'packsnap')
11
+ end
12
+
@@ -0,0 +1,3 @@
1
+ module Packsnap
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require 'packsnap/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "packsnap"
6
+ s.version = Packsnap::VERSION
7
+ s.summary = "MessagePack, a binary-based efficient data interchange format."
8
+ s.description = %q{MessagePack is a binary-based efficient object serialization library. It enables to exchange structured objects between many languages like JSON. But unlike JSON, it is very fast and small.}
9
+ s.author = "Burke Libbey"
10
+ s.email = "burke@libbey.me"
11
+ s.homepage = "https://github.com/burke/packsnap"
12
+ s.has_rdoc = false
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
15
+ s.require_paths = ["lib"]
16
+ s.extensions = ['ext/packsnap/extconf.rb']
17
+
18
+ s.add_development_dependency 'bundler', ['>= 1.0.0']
19
+ s.add_development_dependency 'rake', ['>= 0.8.7']
20
+ s.add_development_dependency 'rspec', ['>= 2.10.0']
21
+ s.add_development_dependency 'json', ['~> 1.7']
22
+ s.add_development_dependency 'yard', ['~> 0.8']
23
+ end
@@ -0,0 +1,228 @@
1
+ require 'spec_helper'
2
+ require 'random_compat'
3
+
4
+ require 'stringio'
5
+ if defined?(Encoding)
6
+ Encoding.default_external = 'ASCII-8BIT'
7
+ end
8
+
9
+ describe Buffer do
10
+ r = Random.new
11
+ random_seed = r.seed
12
+ puts "buffer_io random seed: 0x#{random_seed.to_s(16)}"
13
+
14
+ let :source do
15
+ ''
16
+ end
17
+
18
+ def set_source(s)
19
+ source.replace(s)
20
+ end
21
+
22
+ let :io do
23
+ StringIO.new(source.dup)
24
+ end
25
+
26
+ let :buffer do
27
+ Buffer.new(io)
28
+ end
29
+
30
+ it 'short feed and read all' do
31
+ set_source 'aa'
32
+ buffer.read.should == 'aa'
33
+ end
34
+
35
+ it 'short feed and read short' do
36
+ set_source 'aa'
37
+ buffer.read(1).should == 'a'
38
+ buffer.read(1).should == 'a'
39
+ buffer.read(1).should == nil
40
+ end
41
+
42
+ it 'long feed and read all' do
43
+ set_source ' '*(1024*1024)
44
+ s = buffer.read
45
+ s.size.should == source.size
46
+ s.should == source
47
+ end
48
+
49
+ it 'long feed and read mixed' do
50
+ set_source ' '*(1024*1024)
51
+ buffer.read(10).should == source.slice!(0, 10)
52
+ buffer.read(10).should == source.slice!(0, 10)
53
+ buffer.read(10).should == source.slice!(0, 10)
54
+ s = buffer.read
55
+ s.size.should == source.size
56
+ s.should == source
57
+ end
58
+
59
+ it 'eof' do
60
+ set_source ''
61
+ buffer.read.should == ''
62
+ end
63
+
64
+ it 'eof 2' do
65
+ set_source 'a'
66
+ buffer.read.should == 'a'
67
+ buffer.read.should == ''
68
+ end
69
+
70
+ it 'write short once and flush' do
71
+ buffer.write('aa')
72
+ buffer.flush
73
+ io.string.should == 'aa'
74
+ end
75
+
76
+ it 'write short twice and flush' do
77
+ buffer.write('a')
78
+ buffer.write('a')
79
+ buffer.flush
80
+ io.string.should == 'aa'
81
+ end
82
+
83
+ it 'write long once and flush' do
84
+ s = ' '*(1024*1024)
85
+ buffer.write s
86
+ buffer.flush
87
+ io.string.size.should == s.size
88
+ io.string.should == s
89
+ end
90
+
91
+ it 'write short multi and flush' do
92
+ s = ' '*(1024*1024)
93
+ 1024.times {
94
+ buffer.write ' '*1024
95
+ }
96
+ buffer.flush
97
+ io.string.size.should == s.size
98
+ io.string.should == s
99
+ end
100
+
101
+ it 'random read' do
102
+ r = Random.new(random_seed)
103
+
104
+ 50.times {
105
+ fragments = []
106
+
107
+ r.rand(4).times do
108
+ n = r.rand(1024*1400)
109
+ s = r.bytes(n)
110
+ fragments << s
111
+ end
112
+
113
+ io = StringIO.new(fragments.join)
114
+ b = Buffer.new(io)
115
+
116
+ fragments.each {|s|
117
+ x = b.read(s.size)
118
+ x.size.should == s.size
119
+ x.should == s
120
+ }
121
+ b.empty?.should == true
122
+ b.read.should == ''
123
+ }
124
+ end
125
+
126
+ it 'random read_all' do
127
+ r = Random.new(random_seed)
128
+
129
+ 50.times {
130
+ fragments = []
131
+ sx = r.bytes(0)
132
+
133
+ r.rand(4).times do
134
+ n = r.rand(1024*1400)
135
+ s = r.bytes(n)
136
+ fragments << s
137
+ end
138
+
139
+ io = StringIO.new(fragments.join)
140
+ b = Buffer.new(io)
141
+
142
+ fragments.each {|s|
143
+ x = b.read_all(s.size)
144
+ x.size.should == s.size
145
+ x.should == s
146
+ }
147
+ b.empty?.should == true
148
+ lambda {
149
+ b.read_all(1)
150
+ }.should raise_error(EOFError)
151
+ }
152
+ end
153
+
154
+ it 'random skip' do
155
+ r = Random.new(random_seed)
156
+
157
+ 50.times {
158
+ fragments = []
159
+
160
+ r.rand(4).times do
161
+ n = r.rand(1024*1400)
162
+ s = r.bytes(n)
163
+ fragments << s
164
+ end
165
+
166
+ io = StringIO.new(fragments.join)
167
+ b = Buffer.new(io)
168
+
169
+ fragments.each {|s|
170
+ b.skip(s.size).should == s.size
171
+ }
172
+ b.empty?.should == true
173
+ b.skip(1).should == 0
174
+ }
175
+ end
176
+
177
+ it 'random skip_all' do
178
+ r = Random.new(random_seed)
179
+
180
+ 50.times {
181
+ fragments = []
182
+
183
+ r.rand(4).times do
184
+ n = r.rand(1024*1400)
185
+ s = r.bytes(n)
186
+ fragments << s
187
+ end
188
+
189
+ io = StringIO.new(fragments.join)
190
+ b = Buffer.new(io)
191
+
192
+ fragments.each {|s|
193
+ lambda {
194
+ b.skip_all(s.size)
195
+ }.should_not raise_error(EOFError)
196
+ }
197
+ b.empty?.should == true
198
+ lambda {
199
+ b.skip_all(1)
200
+ }.should raise_error(EOFError)
201
+ }
202
+ end
203
+
204
+ it 'random write' do
205
+ r = Random.new(random_seed)
206
+
207
+ 50.times {
208
+ s = r.bytes(0)
209
+ io = StringIO.new
210
+ b = Buffer.new(io)
211
+
212
+ r.rand(4).times do
213
+ n = r.rand(1024*1400)
214
+ x = r.bytes(n)
215
+ s << x
216
+ b.write(x)
217
+ end
218
+
219
+ (io.string.size + b.size).should == s.size
220
+
221
+ b.flush
222
+
223
+ io.string.size.should == s.size
224
+ io.string.should == s
225
+ }
226
+ end
227
+ end
228
+
@@ -0,0 +1,572 @@
1
+ require 'spec_helper'
2
+ require 'random_compat'
3
+
4
+ describe Buffer do
5
+ STATIC_EXAMPLES = {}
6
+ STATIC_EXAMPLES[:empty01] = ''
7
+ STATIC_EXAMPLES[:empty02] = ''
8
+ STATIC_EXAMPLES[:copy01] = 'short'
9
+ STATIC_EXAMPLES[:copy02] = 'short'*2
10
+ STATIC_EXAMPLES[:ref01] = 'short'*128
11
+ STATIC_EXAMPLES[:ref02] = 'short'*128*2
12
+ STATIC_EXAMPLES[:ref03] = 'a'*((1024*1024+2)*2)
13
+ STATIC_EXAMPLES[:refcopy01] = 'short'*128
14
+ STATIC_EXAMPLES[:expand01] = 'short'*1024
15
+ STATIC_EXAMPLES[:expand02] = 'short'*(127+1024)
16
+ STATIC_EXAMPLES[:offset01] = 'ort'+'short'
17
+ STATIC_EXAMPLES[:offset02] = 'ort'+'short'*127
18
+ STATIC_EXAMPLES[:offset03] = 'ort'+'short'*(126+1024)
19
+
20
+ if ''.respond_to?(:force_encoding)
21
+ STATIC_EXAMPLES.each_value {|v| v.force_encoding('ASCII-8BIT') }
22
+ end
23
+ STATIC_EXAMPLES.each_value {|v| v.freeze }
24
+
25
+ r = Random.new
26
+ random_seed = r.seed
27
+ puts "buffer random seed: 0x#{random_seed.to_s(16)}"
28
+
29
+ let :random_cases_examples do
30
+ r = Random.new(random_seed)
31
+ cases = {}
32
+ examples = {}
33
+
34
+ 10.times do |i|
35
+ b = Buffer.new
36
+ s = r.bytes(0)
37
+ r.rand(3).times do
38
+ n = r.rand(1024*1400)
39
+ x = r.bytes(n)
40
+ s << x
41
+ b << x
42
+ end
43
+ r.rand(2).times do
44
+ n = r.rand(1024*1400)
45
+ b.read(n)
46
+ s.slice!(0, n)
47
+ end
48
+ key = :"random#{"%02d"%i}"
49
+ cases[key] = b
50
+ examples[key] = s
51
+ end
52
+
53
+ [cases, examples]
54
+ end
55
+
56
+ let :static_cases do
57
+ map = {}
58
+ map[:empty01] = empty01
59
+ map[:empty02] = empty02
60
+ map[:copy01] = copy01
61
+ map[:copy02] = copy02
62
+ map[:ref01] = ref01
63
+ map[:ref02] = ref02
64
+ map[:ref03] = ref03
65
+ map[:refcopy01] = refcopy01
66
+ map[:expand01] = expand01
67
+ map[:expand02] = expand02
68
+ map[:offset01] = offset01
69
+ map[:offset02] = offset02
70
+ map[:offset03] = offset03
71
+ map
72
+ end
73
+
74
+ let :static_examples do
75
+ STATIC_EXAMPLES
76
+ end
77
+
78
+ let :random_cases do
79
+ random_cases_examples[0]
80
+ end
81
+
82
+ let :random_examples do
83
+ random_cases_examples[1]
84
+ end
85
+
86
+ let :cases do
87
+ static_cases.merge(random_cases)
88
+ end
89
+
90
+ let :examples do
91
+ static_examples.merge(random_examples)
92
+ end
93
+
94
+ let :case_keys do
95
+ examples.keys
96
+ end
97
+
98
+ let :empty01 do
99
+ Buffer.new
100
+ end
101
+
102
+ let :empty02 do
103
+ b = Buffer.new
104
+ b << 'a'
105
+ b.read_all(1)
106
+ b
107
+ end
108
+
109
+ let :copy01 do
110
+ # one copy chunk
111
+ b = Buffer.new
112
+ b << 'short'
113
+ b
114
+ end
115
+
116
+ let :copy02 do
117
+ # one copy chunk
118
+ b = Buffer.new
119
+ b << 'short'
120
+ b << 'short'
121
+ b
122
+ end
123
+
124
+ let :expand02 do
125
+ # one copy chunk / expanded
126
+ b = Buffer.new
127
+ 1024.times do
128
+ b << 'short'
129
+ end
130
+ b
131
+ end
132
+
133
+ let :ref01 do
134
+ # one reference chunk
135
+ b = Buffer.new
136
+ b << 'short'*128
137
+ b.to_s
138
+ b
139
+ end
140
+
141
+ let :ref02 do
142
+ # two reference chunks
143
+ b = Buffer.new
144
+ b << 'short'*128
145
+ b.to_s
146
+ b << 'short'*128
147
+ b.to_a
148
+ b
149
+ end
150
+
151
+ let :ref03 do
152
+ # two reference chunks
153
+ b = Buffer.new
154
+ b << 'a'*(1024*1024+2)
155
+ b << 'a'*(1024*1024+2)
156
+ b
157
+ end
158
+
159
+ let :refcopy01 do
160
+ # one reference chunk + one copy chunk
161
+ b = Buffer.new
162
+ b << 'short'*127
163
+ b.to_s
164
+ b << 'short'
165
+ b
166
+ end
167
+
168
+ let :expand01 do
169
+ # one copy chunk / expanded
170
+ b = Buffer.new
171
+ 1024.times do
172
+ b << 'short'
173
+ end
174
+ b
175
+ end
176
+
177
+ let :expand02 do
178
+ # one reference chunk + one copy chunk / expanded
179
+ b = Buffer.new
180
+ b << 'short'*127
181
+ b.to_s
182
+ 1024.times do
183
+ b << 'short'
184
+ end
185
+ b
186
+ end
187
+
188
+ let :offset01 do
189
+ # one copy chunk / offset
190
+ b = Buffer.new
191
+ b << 'short'
192
+ b << 'short'
193
+ b.skip(2)
194
+ b
195
+ end
196
+
197
+ let :offset02 do
198
+ # one reference chunk / offset
199
+ b = Buffer.new
200
+ b << 'short'*127
201
+ b.to_s
202
+ b.skip(2)
203
+ b << 'short'
204
+ b
205
+ end
206
+
207
+ let :offset03 do
208
+ # one reference chunk / offset + one copy chunk / expanded
209
+ b = Buffer.new
210
+ b << 'short'*127
211
+ b.to_s
212
+ 1024.times do
213
+ b << 'short'
214
+ end
215
+ b.skip(2)
216
+ b
217
+ end
218
+
219
+ it 'empty?' do
220
+ empty01.empty?.should == true
221
+ empty02.empty?.should == true
222
+ end
223
+
224
+ it 'size' do
225
+ case_keys.each {|k|
226
+ cases[k].size.should == examples[k].size
227
+ }
228
+ end
229
+
230
+ it 'short write increments size' do
231
+ case_keys.each {|k|
232
+ sz = examples[k].size
233
+ 10.times do |i|
234
+ cases[k].write 'short'
235
+ sz += 'short'.size
236
+ cases[k].size.should == sz
237
+ end
238
+ }
239
+ end
240
+
241
+ it 'read with limit decrements size' do
242
+ case_keys.each {|k|
243
+ sz = examples[k].size
244
+ next if sz < 2
245
+
246
+ cases[k].read(1).should == examples[k][0,1]
247
+ sz -= 1
248
+ cases[k].size.should == sz
249
+
250
+ cases[k].read(1).should == examples[k][1,1]
251
+ sz -= 1
252
+ cases[k].size.should == sz
253
+ }
254
+ end
255
+
256
+ it 'read_all with limit decrements size' do
257
+ case_keys.each {|k|
258
+ sz = examples[k].size
259
+ next if sz < 2
260
+
261
+ cases[k].read_all(1).should == examples[k][0,1]
262
+ sz -= 1
263
+ cases[k].size.should == sz
264
+
265
+ cases[k].read_all(1).should == examples[k][1,1]
266
+ sz -= 1
267
+ cases[k].size.should == sz
268
+ }
269
+ end
270
+
271
+ it 'skip decrements size' do
272
+ case_keys.each {|k|
273
+ sz = examples[k].size
274
+ next if sz < 2
275
+
276
+ cases[k].skip(1).should == 1
277
+ sz -= 1
278
+ cases[k].size.should == sz
279
+
280
+ cases[k].skip(1).should == 1
281
+ sz -= 1
282
+ cases[k].size.should == sz
283
+ }
284
+ end
285
+
286
+ it 'skip_all decrements size' do
287
+ case_keys.each {|k|
288
+ sz = examples[k].size
289
+ next if sz < 2
290
+
291
+ cases[k].skip_all(1)
292
+ sz -= 1
293
+ cases[k].size.should == sz
294
+
295
+ cases[k].skip_all(1)
296
+ sz -= 1
297
+ cases[k].size.should == sz
298
+ }
299
+ end
300
+
301
+ it 'read_all against insufficient buffer raises EOFError and consumes nothing' do
302
+ case_keys.each {|k|
303
+ sz = examples[k].size
304
+ lambda {
305
+ cases[k].read_all(sz+1)
306
+ }.should raise_error(EOFError)
307
+ cases[k].size.should == sz
308
+ }
309
+ end
310
+
311
+ it 'skip_all against insufficient buffer raises EOFError and consumes nothing' do
312
+ case_keys.each {|k|
313
+ sz = examples[k].size
314
+ lambda {
315
+ cases[k].skip_all(sz+1)
316
+ }.should raise_error(EOFError)
317
+ cases[k].size.should == sz
318
+ }
319
+ end
320
+
321
+ it 'read against insufficient buffer consumes all buffer or return nil' do
322
+ case_keys.each {|k|
323
+ sz = examples[k].size
324
+ if sz == 0
325
+ cases[k].read(sz+1).should == nil
326
+ else
327
+ cases[k].read(sz+1).should == examples[k]
328
+ end
329
+ cases[k].size.should == 0
330
+ }
331
+ end
332
+
333
+ it 'skip against insufficient buffer consumes all buffer' do
334
+ case_keys.each {|k|
335
+ sz = examples[k].size
336
+ cases[k].skip(sz+1).should == examples[k].size
337
+ cases[k].size.should == 0
338
+ }
339
+ end
340
+
341
+ it 'read with no arguments consumes all buffer and returns string and do not return nil' do
342
+ case_keys.each {|k|
343
+ cases[k].read_all.should == examples[k]
344
+ cases[k].size.should == 0
345
+ }
346
+ end
347
+
348
+ it 'read_all with no arguments consumes all buffer and returns string' do
349
+ case_keys.each {|k|
350
+ cases[k].read_all.should == examples[k]
351
+ cases[k].size.should == 0
352
+ }
353
+ end
354
+
355
+ it 'to_s returns a string and consume nothing' do
356
+ case_keys.each {|k|
357
+ cases[k].to_s.should == examples[k]
358
+ cases[k].size.should == examples[k].size
359
+ }
360
+ end
361
+
362
+ it 'to_s and modify' do
363
+ case_keys.each {|k|
364
+ s = cases[k].to_s
365
+ s << 'x'
366
+ cases[k].to_s.should == examples[k]
367
+ }
368
+ end
369
+
370
+ it 'big write and modify reference' do
371
+ big2 = "a" * (1024*1024 + 2)
372
+
373
+ case_keys.each {|k|
374
+ big1 = "a" * (1024*1024 + 2)
375
+ cases[k].write(big1)
376
+ big1 << 'x'
377
+ cases[k].read.should == examples[k] + big2
378
+ }
379
+ end
380
+
381
+ it 'big write -> short write' do
382
+ biglen = 1024*1024 + 2
383
+ big1 = "a" * (1024*1024 + 2)
384
+
385
+ case_keys.each {|k|
386
+ sz = examples[k].size
387
+
388
+ cases[k].write big1
389
+ cases[k].size.should == sz + big1.size
390
+
391
+ cases[k].write("c")
392
+ cases[k].size.should == sz + big1.size + 1
393
+
394
+ cases[k].read_all.should == examples[k] + big1 + "c"
395
+ cases[k].size.should == 0
396
+ cases[k].empty?.should == true
397
+ }
398
+ end
399
+
400
+ it 'big write 2'do
401
+ big1 = "a" * (1024*1024 + 2)
402
+ big2 = "b" * (1024*1024 + 2)
403
+
404
+ case_keys.each {|k|
405
+ sz = examples[k].size
406
+
407
+ cases[k].write big1
408
+ cases[k].write big2
409
+ cases[k].size.should == sz + big1.size + big2.size
410
+
411
+ cases[k].read_all(sz + big1.size).should == examples[k] + big1
412
+ cases[k].size.should == big2.size
413
+
414
+ cases[k].read.should == big2
415
+ cases[k].size.should == 0
416
+ cases[k].empty?.should == true
417
+ }
418
+ end
419
+
420
+ it 'read 0' do
421
+ case_keys.each {|k|
422
+ cases[k].read(0).should == ''
423
+ cases[k].read.should == examples[k]
424
+ }
425
+ end
426
+
427
+ it 'skip 0' do
428
+ case_keys.each {|k|
429
+ cases[k].skip(0).should == 0
430
+ cases[k].read.should == examples[k]
431
+ }
432
+ end
433
+
434
+ it 'read_all 0' do
435
+ case_keys.each {|k|
436
+ cases[k].read_all(0).should == ''
437
+ cases[k].read_all.should == examples[k]
438
+ }
439
+ end
440
+
441
+ it 'skip_all 0' do
442
+ case_keys.each {|k|
443
+ cases[k].skip_all(0)
444
+ cases[k].read_all.should == examples[k]
445
+ }
446
+ end
447
+
448
+ it 'write_to' do
449
+ case_keys.each {|k|
450
+ sio = StringIO.new
451
+ cases[k].write_to(sio).should == examples[k].size
452
+ cases[k].size.should == 0
453
+ sio.string.should == examples[k]
454
+ }
455
+ end
456
+
457
+ it 'random read/write' do
458
+ r = Random.new(random_seed)
459
+ s = r.bytes(0)
460
+ b = Buffer.new
461
+
462
+ 10.times {
463
+ # write
464
+ r.rand(4).times do
465
+ n = r.rand(1024*1400)
466
+ x = r.bytes(n)
467
+ s << x
468
+ b.write(x)
469
+ end
470
+
471
+ # read
472
+ r.rand(3).times do
473
+ n = r.rand(1024*1400)
474
+ ex = s.slice!(0, n)
475
+ ex = nil if ex.empty?
476
+ x = b.read(n)
477
+ x.size == ex.size if x != nil
478
+ x.should == ex
479
+ b.size.should == s.size
480
+ end
481
+ }
482
+ end
483
+
484
+ it 'random read_all/write' do
485
+ r = Random.new(random_seed)
486
+ s = r.bytes(0)
487
+ b = Buffer.new
488
+
489
+ 10.times {
490
+ # write
491
+ r.rand(4).times do
492
+ n = r.rand(1024*1400)
493
+ x = r.bytes(n)
494
+ s << x
495
+ b.write(x)
496
+ end
497
+
498
+ # read_all
499
+ r.rand(3).times do
500
+ n = r.rand(1024*1400)
501
+ begin
502
+ x = b.read_all(n)
503
+ ex = s.slice!(0, n)
504
+ x.size == n
505
+ x.should == ex
506
+ b.size.should == s.size
507
+ rescue EOFError
508
+ b.size.should == s.size
509
+ b.read.should == s
510
+ s.clear
511
+ break
512
+ end
513
+ end
514
+ }
515
+ end
516
+
517
+ it 'random skip write' do
518
+ r = Random.new(random_seed)
519
+ s = r.bytes(0)
520
+ b = Buffer.new
521
+
522
+ 10.times {
523
+ # write
524
+ r.rand(4).times do
525
+ n = r.rand(1024*1400)
526
+ x = r.bytes(n)
527
+ s << x
528
+ b.write(x)
529
+ end
530
+
531
+ # skip
532
+ r.rand(3).times do
533
+ n = r.rand(1024*1400)
534
+ ex = s.slice!(0, n)
535
+ b.skip(n).should == ex.size
536
+ b.size.should == s.size
537
+ end
538
+ }
539
+ end
540
+
541
+ it 'random skip_all write' do
542
+ r = Random.new(random_seed)
543
+ s = r.bytes(0)
544
+ b = Buffer.new
545
+
546
+ 10.times {
547
+ # write
548
+ r.rand(4).times do
549
+ n = r.rand(1024*1400)
550
+ x = r.bytes(n)
551
+ s << x
552
+ b.write(x)
553
+ end
554
+
555
+ # skip_all
556
+ r.rand(3).times do
557
+ n = r.rand(1024*1400)
558
+ begin
559
+ b.skip_all(n)
560
+ ex = s.slice!(0, n)
561
+ b.size.should == s.size
562
+ ensure EOFError
563
+ b.size.should == s.size
564
+ b.read.should == s
565
+ s.clear
566
+ break
567
+ end
568
+ end
569
+ }
570
+ end
571
+ end
572
+