java_bin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/fixtures/json.dat ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "responseHeader":{
3
+ "status":0,
4
+ "QTime":0,
5
+ "params":{
6
+ "explainOther":"",
7
+ "fl":"*,score",
8
+ "indent":"on",
9
+ "start":"0",
10
+ "q":"software",
11
+ "hl.fl":"",
12
+ "qt":"standard",
13
+ "wt":"json",
14
+ "fq":"",
15
+ "version":"2.2",
16
+ "rows":"10"}},
17
+ "response":{"numFound":2,"start":0,"maxScore":0.6288448,"docs":[
18
+ {
19
+ "id":"UTF8TEST",
20
+ "name":"Test with some UTF-8 encoded characters",
21
+ "manu":"Apache Software Foundation",
22
+ "price":0.0,
23
+ "inStock":true,
24
+ "cat":[
25
+ "software",
26
+ "search"],
27
+ "features":[
28
+ "No accents here",
29
+ "This is an e acute: é",
30
+ "eaiou with circumflexes: êâîôû",
31
+ "eaiou with umlauts: ëäïöü",
32
+ "tag with escaped chars: <nicetag/>",
33
+ "escaped ampersand: Bonnie & Clyde"],
34
+ "score":0.6288448},
35
+ {
36
+ "id":"SOLR1000",
37
+ "name":"Solr, the Enterprise Search Server",
38
+ "manu":"Apache Software Foundation",
39
+ "price":0.0,
40
+ "popularity":10,
41
+ "inStock":true,
42
+ "incubationdate_dt":"2006-01-17T00:00:00Z",
43
+ "cat":[
44
+ "software",
45
+ "search"],
46
+ "features":[
47
+ "Advanced Full-Text Search Capabilities using Lucene",
48
+ "Optimized for High Volume Web Traffic",
49
+ "Standards Based Open Interfaces - XML and HTTP",
50
+ "Comprehensive HTML Administration Interfaces",
51
+ "Scalability - Efficient Replication to other Solr Search Servers",
52
+ "Flexible and Adaptable with XML configuration and Schema",
53
+ "Good unicode support: héllo (hello with an accent over the e)"],
54
+ "score":0.50307584}]
55
+ }}
data/fixtures/ruby.dat ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ 'responseHeader'=>{
3
+ 'status'=>0,
4
+ 'QTime'=>0,
5
+ 'params'=>{
6
+ 'explainOther'=>'',
7
+ 'fl'=>'*,score',
8
+ 'indent'=>'on',
9
+ 'start'=>'0',
10
+ 'q'=>'software',
11
+ 'hl.fl'=>'',
12
+ 'qt'=>'standard',
13
+ 'wt'=>'ruby',
14
+ 'fq'=>'',
15
+ 'version'=>'2.2',
16
+ 'rows'=>'10'}},
17
+ 'response'=>{'numFound'=>2,'start'=>0,'maxScore'=>0.6288448,'docs'=>[
18
+ {
19
+ 'id'=>'UTF8TEST',
20
+ 'name'=>'Test with some UTF-8 encoded characters',
21
+ 'manu'=>'Apache Software Foundation',
22
+ 'price'=>0.0,
23
+ 'inStock'=>true,
24
+ 'cat'=>[
25
+ 'software',
26
+ 'search'],
27
+ 'features'=>[
28
+ 'No accents here',
29
+ 'This is an e acute: é',
30
+ 'eaiou with circumflexes: êâîôû',
31
+ 'eaiou with umlauts: ëäïöü',
32
+ 'tag with escaped chars: <nicetag/>',
33
+ 'escaped ampersand: Bonnie & Clyde'],
34
+ 'score'=>0.6288448},
35
+ {
36
+ 'id'=>'SOLR1000',
37
+ 'name'=>'Solr, the Enterprise Search Server',
38
+ 'manu'=>'Apache Software Foundation',
39
+ 'price'=>0.0,
40
+ 'popularity'=>10,
41
+ 'inStock'=>true,
42
+ 'incubationdate_dt'=>'2006-01-17T00:00:00Z',
43
+ 'cat'=>[
44
+ 'software',
45
+ 'search'],
46
+ 'features'=>[
47
+ 'Advanced Full-Text Search Capabilities using Lucene',
48
+ 'Optimized for High Volume Web Traffic',
49
+ 'Standards Based Open Interfaces - XML and HTTP',
50
+ 'Comprehensive HTML Administration Interfaces',
51
+ 'Scalability - Efficient Replication to other Solr Search Servers',
52
+ 'Flexible and Adaptable with XML configuration and Schema',
53
+ 'Good unicode support: héllo (hello with an accent over the e)'],
54
+ 'score'=>0.50307584}]
55
+ }}
data/java_bin.gemspec ADDED
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{java_bin}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["kennyj"]
12
+ s.date = %q{2010-01-11}
13
+ s.description = %q{Solr JavaBin format implementation for Ruby.}
14
+ s.email = %q{kennyj@gmail.com}
15
+ s.extensions = ["ext/java_bin/ext/extconf.rb"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc",
19
+ "TODO"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "TODO",
28
+ "VERSION",
29
+ "ext/java_bin/ext/extconf.rb",
30
+ "ext/java_bin/ext/parser.c",
31
+ "ext/java_bin/ext/parser.h",
32
+ "fixtures/javabin.dat",
33
+ "fixtures/json.dat",
34
+ "fixtures/ruby.dat",
35
+ "java_bin.gemspec",
36
+ "lib/java_bin.rb",
37
+ "lib/java_bin/ext.rb",
38
+ "lib/java_bin/ext/.keep",
39
+ "lib/java_bin/pure.rb",
40
+ "lib/java_bin/pure/parser.rb",
41
+ "lib/java_bin/version.rb",
42
+ "test/helper.rb",
43
+ "test/test_java_bin_parser.rb",
44
+ "test/xxx_performance.rb"
45
+ ]
46
+ s.homepage = %q{http://github.com/kennyj/java_bin}
47
+ s.rdoc_options = ["--charset=UTF-8"]
48
+ s.require_paths = ["lib", "ext"]
49
+ s.rubygems_version = %q{1.3.5}
50
+ s.summary = %q{Solr JavaBin format implementation for Ruby.}
51
+ s.test_files = [
52
+ "test/xxx_performance.rb",
53
+ "test/test_java_bin_parser.rb",
54
+ "test/helper.rb"
55
+ ]
56
+
57
+ if s.respond_to? :specification_version then
58
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
59
+ s.specification_version = 3
60
+
61
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
62
+ else
63
+ end
64
+ else
65
+ end
66
+ end
67
+
File without changes
@@ -0,0 +1,9 @@
1
+ # vim:fileencoding=utf-8
2
+ module JavaBin
3
+ module Ext
4
+ require 'java_bin/ext/parser'
5
+ #require 'parser'
6
+ $DEBUG and warn "Using c extension for JavaBin."
7
+ ::JavaBin.parser = ::JavaBin::Ext::Parser
8
+ end
9
+ end
@@ -0,0 +1,219 @@
1
+ # vim:fileencoding=utf-8
2
+ module JavaBin
3
+ module Pure
4
+ NULL = 0
5
+ BOOL_TRUE = 1
6
+ BOOL_FALSE = 2
7
+ BYTE = 3
8
+ SHORT = 4
9
+ DOUBLE = 5
10
+ INT = 6
11
+ LONG = 7
12
+ FLOAT = 8
13
+ DATE = 9
14
+ MAP = 10
15
+ SOLRDOC = 11
16
+ SOLRDOCLST = 12
17
+ BYTEARR = 13
18
+ ITERATOR = 14
19
+ TERM = 15 #END = 15
20
+
21
+ #TAG_AND_LEN = (1 << 5)
22
+ STR = (1 << 5)
23
+ SINT = (2 << 5)
24
+ SLONG = (3 << 5)
25
+ ARR = (4 << 5)
26
+ ORDERED_MAP = (5 << 5)
27
+ NAMED_LST = (6 << 5)
28
+ EXTERN_STRING = (7 << 5)
29
+
30
+ # TODO 論理シフト
31
+ SHIFTED_STR = STR >> 5
32
+ SHIFTED_ARR = ARR >> 5
33
+ SHIFTED_EXTERN_STRING = EXTERN_STRING >> 5
34
+ SHIFTED_ORDERED_MAP = ORDERED_MAP >> 5
35
+ SHIFTED_NAMED_LST = NAMED_LST >> 5
36
+ SHIFTED_SINT = SINT >> 5
37
+ SHIFTED_SLONG = SLONG >> 5
38
+
39
+ VERSION = 1
40
+ TERM_OBJ = :term_obj
41
+
42
+ class Parser
43
+
44
+ attr_reader :tag_byte, :input, :current
45
+
46
+ def initialize
47
+ end
48
+
49
+ def parse(input)
50
+ array = input.bytes.to_a
51
+ check_version(array[0])
52
+ @input = array
53
+ @current = 1 # HINT VERSIONをとばす
54
+ @tag_byte = nil
55
+ read_val
56
+ end
57
+
58
+ private
59
+ def check_version(byte)
60
+ return true if VERSION == byte
61
+ raise "unsupported version #{byte}"
62
+ end
63
+
64
+ def getbyte
65
+ ret = @input[@current]
66
+ @current += 1
67
+ ret
68
+ end
69
+
70
+ def getbytes(size)
71
+ ret = @input[@current...(@current + size)]
72
+ @current += size
73
+ ret
74
+ end
75
+
76
+ def read_val
77
+ @tag_byte = getbyte
78
+ case (@tag_byte >> 5) # TODO 論理シフト
79
+ when SHIFTED_STR
80
+ return read_chars
81
+ when SHIFTED_ARR
82
+ size = read_size
83
+ array = Array.new(size)
84
+ size.times { |i| array[i] = read_val }
85
+ return array
86
+ when SHIFTED_EXTERN_STRING
87
+ size = read_size
88
+ if size == 0
89
+ str = read_val
90
+ @exts ||= []
91
+ @exts << str
92
+ return str
93
+ else
94
+ return @exts[size - 1].dup
95
+ end
96
+ when SHIFTED_ORDERED_MAP, SHIFTED_NAMED_LST
97
+ size = read_size
98
+ hash = {}
99
+ size.times do
100
+ k = read_val
101
+ v = read_val
102
+ hash[k] = v
103
+ end
104
+ return hash
105
+ when SHIFTED_SINT
106
+ return read_small_int
107
+ when SHIFTED_SLONG
108
+ return read_small_int
109
+ end
110
+
111
+ case @tag_byte
112
+ when NULL
113
+ return nil
114
+ when BOOL_TRUE
115
+ return true
116
+ when BOOL_FALSE
117
+ return false
118
+ when BYTE
119
+ return getbytes(1).pack("C*").unpack("c")[0]
120
+ when SHORT
121
+ return getbytes(2).reverse.pack("C*").unpack("s")[0]
122
+ when DOUBLE
123
+ return getbytes(8).pack("C*").unpack("G")[0]
124
+ when INT
125
+ return getbytes(4).reverse.pack("C*").unpack("i")[0]
126
+ when LONG
127
+ return getbytes(8).reverse.pack("C*").unpack("q")[0]
128
+ when FLOAT
129
+ return getbytes(4).pack("C*").unpack("g")[0]
130
+ when DATE
131
+ x = getbytes(8).reverse.pack("C*").unpack("q")[0]
132
+ return Time.at(x/1000)
133
+ when MAP
134
+ size = read_v_int
135
+ hash = {}
136
+ size.times do
137
+ k = read_val
138
+ v = read_val
139
+ hash[k] = v
140
+ end
141
+ return hash
142
+ when BYTEARR
143
+ size = read_v_int
144
+ return getbytes(size)
145
+ when ITERATOR
146
+ array = []
147
+ while true
148
+ i = read_val
149
+ break if i == TERM_OBJ
150
+ array << i
151
+ end
152
+ return array
153
+ when TERM
154
+ return TERM_OBJ
155
+ when SOLRDOC
156
+ return read_val
157
+ when SOLRDOCLST
158
+ result = {}
159
+ list = read_val
160
+ result['numFound'] = list[0]
161
+ result['start'] = list[1]
162
+ result['maxScore'] = list[2]
163
+ result['docs'] = read_val
164
+ return result
165
+ end
166
+ end
167
+
168
+ def read_v_int
169
+ byte = getbyte
170
+ result = byte & 0x7f
171
+ shift = 7
172
+ while (byte & 0x80) != 0
173
+ byte = getbyte
174
+ result |= ((byte & 0x7f) << shift)
175
+ shift += 7
176
+ end
177
+ result
178
+ end
179
+
180
+ def read_size
181
+ size = (@tag_byte & 0x1f)
182
+ size += read_v_int if (size == 0x1f)
183
+ size
184
+ end
185
+
186
+ def read_small_int
187
+ result = @tag_byte & 0x0F
188
+ result = ((read_v_int << 4) | result) if ((@tag_byte & 0x10) != 0)
189
+ result
190
+ end
191
+
192
+ def read_chars
193
+ size = read_size
194
+ str = ''
195
+ size.times {
196
+ # HINT. read utf-8 char
197
+ b = getbyte
198
+ if ((b & 0x80) == 0)
199
+ str << b
200
+ elsif ((b & 0xE0) == 0xC0)
201
+ #str << (((b & 0x1F) << 6) | (getbyte & 0x3F))
202
+ str << b
203
+ str << getbyte
204
+ else
205
+ #str << (((b & 0x0F) << 12) | ((getbyte & 0x3F) << 6) | (getbyte & 0x3F))
206
+ str << b
207
+ str << getbyte
208
+ str << getbyte
209
+ end
210
+ }
211
+ str.force_encoding('utf-8') if str.respond_to? :force_encoding
212
+ str
213
+ end
214
+
215
+ end
216
+
217
+ end
218
+ end
219
+
@@ -0,0 +1,8 @@
1
+ # vim:fileencoding=utf-8
2
+ module JavaBin
3
+ module Pure
4
+ require 'java_bin/pure/parser'
5
+ $DEBUG and warn "Using pure for JavaBin."
6
+ ::JavaBin.parser = ::JavaBin::Pure::Parser
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ # vim:fileencoding=utf-8
2
+ module JavaBin
3
+ # JavaBin version
4
+ VERSION = '0.1.0'
5
+ VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
6
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
7
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
8
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
9
+ end
10
+
data/lib/java_bin.rb ADDED
@@ -0,0 +1,17 @@
1
+ # vim:fileencoding=utf-8
2
+ module JavaBin
3
+ def self.parser=(value)
4
+ @parser = value
5
+ end
6
+ def self.parser
7
+ @parser
8
+ end
9
+
10
+ require 'java_bin/version'
11
+ begin
12
+ require 'java_bin/ext'
13
+ rescue LoadError => e
14
+ require 'java_bin/pure'
15
+ end
16
+
17
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ # vim:fileencoding=utf-8
2
+ require 'rubygems'
3
+ require 'test/unit'
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ require 'java_bin'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,240 @@
1
+ # vim:fileencoding=utf-8
2
+ require 'helper'
3
+
4
+ case ENV['JavaBin']
5
+ when 'pure'
6
+ then
7
+ require 'java_bin/pure'
8
+ else
9
+ require 'java_bin/ext'
10
+ end
11
+
12
+ class TestJavaBin < Test::Unit::TestCase
13
+
14
+ private
15
+ def write_v_int(i, output)
16
+ while ((i & ~0x7F) != 0)
17
+ output.putc(((i & 0x7f) | 0x80))
18
+ # i >>>= 7
19
+ i = (i >> 7) # TODO 論理シフト
20
+ end
21
+ output.putc(i)
22
+ end
23
+
24
+ def write_tag(tag, size, output)
25
+ if ((tag & 0xe0) != 0)
26
+ if (size < 0x1f)
27
+ output.putc(tag | size)
28
+ else
29
+ output.putc(tag | 0x1f)
30
+ write_v_int(size - 0x1f, output)
31
+ end
32
+ else
33
+ output.putc(tag)
34
+ write_v_int(size, output)
35
+ end
36
+ end
37
+
38
+ def elapsed_time(name, t, &block)
39
+ GC.start
40
+ s = Time.now
41
+ t.times {
42
+ block.call
43
+ }
44
+ e = Time.now
45
+ puts "#{name}#{t} times. elapsed time #{e - s}"
46
+ (e - s)
47
+ end
48
+
49
+ public
50
+ def setup
51
+ @parser = JavaBin.parser.new
52
+ end
53
+
54
+ def test_valid_version
55
+ assert @parser.parse([1, 1].pack("C*"))
56
+ end
57
+ def test_invalid_version
58
+ assert_raise(RuntimeError) { @parser.parse([2].pack("C*")) }
59
+ end
60
+
61
+ def test_javabin_dat
62
+ result = @parser.parse(open("fixtures/javabin.dat", "r:utf-8").read)
63
+ assert result['response']['docs'][0]['features'].include?('eaiou with umlauts: ëäïöü')
64
+ assert_equal result['response']['docs'][1]['incubationdate_dt'], Time.local(2006, 1, 17, 9, 0, 0)
65
+ assert_equal result['response']['docs'][1]['score'], 0.5030758380889893
66
+ end
67
+
68
+ TIMES = 5000
69
+ def test_javabin_parse_and_ruby_eval
70
+ jb = open("fixtures/javabin.dat", "r:utf-8").read
71
+ r = open("fixtures/ruby.dat", "r:utf-8").read
72
+ puts ""
73
+ r_et = elapsed_time("ruby eval parse. ", TIMES) { eval(r) }
74
+ jb_et = elapsed_time("javabin parse. ", TIMES) { @parser.parse(jb) }
75
+ assert (jb_et * 3) < r_et if @parser.is_a? JavaBin::Ext::Parser
76
+ end
77
+
78
+ def test_null
79
+ assert_nil @parser.parse([1, 0].pack("C*"))
80
+ end
81
+
82
+ def test_true
83
+ assert @parser.parse([1, 1].pack("C*"))
84
+ end
85
+
86
+ def test_false
87
+ assert !@parser.parse([1, 2].pack("C*"))
88
+ end
89
+
90
+ def test_byte
91
+ assert_equal 1, @parser.parse([1, 3, 0x01].pack("C*"))
92
+ assert_equal 127, @parser.parse([1, 3, 0x7f].pack("C*"))
93
+ assert_equal -1, @parser.parse([1, 3, 0xff].pack("C*"))
94
+ assert_equal -2, @parser.parse([1, 3, 0xfe].pack("C*"))
95
+ end
96
+
97
+ def test_short
98
+ assert_equal 1, @parser.parse([1, 4, 0x00, 0x01].pack("C*"))
99
+ assert_equal 32767, @parser.parse([1, 4, 0x7f, 0xff].pack("C*"))
100
+ assert_equal -1, @parser.parse([1, 4, 0xff, 0xff].pack("C*"))
101
+ assert_equal -2, @parser.parse([1, 4, 0xff, 0xfe].pack("C*"))
102
+ end
103
+
104
+ def test_double
105
+ assert_equal -1.0, @parser.parse([1, 5, -1.0].pack("C2G"))
106
+ end
107
+
108
+ def test_int
109
+ assert_equal 1, @parser.parse([1, 6, 0x00, 0x00, 0x00, 0x01].pack("C*"))
110
+ assert_equal 2147483647, @parser.parse([1, 6, 0x7f, 0xff, 0xff, 0xff].pack("C*"))
111
+ assert_equal -1, @parser.parse([1, 6, 0xff, 0xff, 0xff, 0xff].pack("C*"))
112
+ assert_equal -2, @parser.parse([1, 6, 0xff, 0xff, 0xff, 0xfe].pack("C*"))
113
+ end
114
+
115
+ def test_long
116
+ assert_equal 1, @parser.parse([1, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01].pack("C*"))
117
+ assert_equal 9223372036854775807 , @parser.parse([1, 7, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].pack("C*"))
118
+ assert_equal -1, @parser.parse([1, 7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].pack("C*"))
119
+ assert_equal -2, @parser.parse([1, 7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe].pack("C*"))
120
+ end
121
+
122
+ def test_float
123
+ assert_equal -1.0, @parser.parse([1, 8, -1.0].pack("C2g"))
124
+ end
125
+
126
+ def test_date
127
+ t = Time.now
128
+ x = (t.to_f * 1000).to_i
129
+ x = [x].pack("q").unpack("C*").reverse # TODO endian次第なので修正必要
130
+ assert_equal t.to_i, @parser.parse(([1, 9] + x).pack("C*")).to_i
131
+ end
132
+
133
+ def test_map
134
+ assert_equal({0 => 0, 1 => 1}, @parser.parse([1, 10, 2, 3, 0, 3, 0, 3, 1, 3, 1].pack("C*")))
135
+ end
136
+
137
+ def test_solrdoc
138
+ arr = [1, 11] + [(5 << 5) | 2] + [(1 << 5) | 1] + "a".unpack("C*") + [3, 8] + [(1 << 5) | 1] + "b".unpack("C*") + [3, 9]
139
+ assert_equal({"a" => 8, "b" => 9}, @parser.parse(arr.pack("C*")))
140
+ end
141
+
142
+ def test_solrdoclst
143
+ arr = [1, 12] + [(4 << 5) | 3, 3, 3, 3, 4, 3, 5] + [(4 << 5) | 0]
144
+ assert_equal({'numFound' => 3, 'start' => 4, 'maxScore' => 5, 'docs' => []}, @parser.parse(arr.pack("C*")))
145
+ end
146
+
147
+ def test_bytearr
148
+ array = [0, 1, 0xff]
149
+ assert_equal array, @parser.parse([1, 13, array.size, *array].pack("C*"))
150
+ end
151
+
152
+ def test_large_bytearr
153
+ array = [0,1,255] * 100
154
+ sio = StringIO.new
155
+ sio.putc 1 #VERSION
156
+ sio.putc 13 #JavaBin::BYTEARR
157
+ write_v_int(array.size, sio)
158
+ array.each { |e| sio.putc e }
159
+ sio.pos = 0
160
+ assert_equal array, @parser.parse(sio.read)
161
+ end
162
+
163
+ def test_iterator
164
+ assert_equal([0, 127, nil, true], @parser.parse([1, 14, 3, 0, 3, 127, 0, 1,15].pack("C*")))
165
+ end
166
+
167
+ # def test_term
168
+ # end
169
+
170
+ def test_string
171
+ assert_equal "あい", @parser.parse(([1, (1 << 5) | 2] + "あい".unpack("C*")).pack("C*"))
172
+ end
173
+
174
+ def test_long_string
175
+ str = "0123456789" * 100
176
+ sio = StringIO.new
177
+ sio.putc 1 #VERSION
178
+ write_tag(1 << 5, str.size, sio)
179
+ str.each_byte { |e| sio.putc e }
180
+ sio.pos = 0
181
+ assert_equal str, @parser.parse(sio.read)
182
+ end
183
+
184
+ def test_sint
185
+ assert_equal 8, @parser.parse([1, (2 << 5) | 8].pack("C*"))
186
+ # flunk("not implemented yet.")
187
+ end
188
+
189
+ def test_slong
190
+ assert_equal 8, @parser.parse([1, (3 << 5) | 8].pack("C*"))
191
+ # flunk("not implemented yet.")
192
+ end
193
+
194
+ def test_arr
195
+ assert_equal [3, 4], @parser.parse([1, (4 << 5) | 2, 3, 3, 3, 4].pack("C*"))
196
+ end
197
+
198
+ def test_large_arr
199
+ array = [0, 1, 2, 3, 4] * 100
200
+ sio = StringIO.new
201
+ sio.putc 1 #VERSION
202
+ write_tag(4 << 5, array.size, sio)
203
+ array.each { |e| sio.putc 3; sio.putc e }
204
+ sio.pos = 0
205
+ assert_equal array, @parser.parse(sio.read)
206
+ end
207
+
208
+ def test_ordered_map
209
+ arr = [1, (5 << 5) | 2] + [(1 << 5) | 1] + "a".unpack("C*") + [3, 8] + [(1 << 5) | 1] + "b".unpack("C*") + [3, 9]
210
+ assert_equal({"a" => 8, "b" => 9}, @parser.parse(arr.pack("C*")))
211
+ end
212
+
213
+ # def test_named_lst
214
+ # end
215
+
216
+ def test_extern_string
217
+ arr = [1, (5 << 5) | 2] +
218
+ [(1 << 5) | 1] + "a".unpack("C*") +
219
+ [(7 << 5) | 0] + [(1 << 5) | 3] + "あいa".unpack("C*") +
220
+ [(1 << 5) | 1] + "b".unpack("C*") +
221
+ [(7 << 5) | 1]
222
+ assert_equal({"a" => "あいa", "b" => "あいa"}, @parser.parse(arr.pack("C*")))
223
+ end
224
+
225
+ LARGE_SIZE = 1000
226
+ def test_long_large_amount_extern_string
227
+ sio = StringIO.new
228
+ sio.putc 1 #VERSION
229
+ write_tag(4 << 5, LARGE_SIZE, sio)
230
+ LARGE_SIZE.times { |i|
231
+ sio.putc((7 << 5) | 0)
232
+ sio.putc((1 << 5) | 1)
233
+ sio.putc("a")
234
+ write_tag((7 << 5), i, sio)
235
+ }
236
+ sio.pos = 0
237
+ assert_equal ['a'] * LARGE_SIZE, @parser.parse(sio.read)
238
+ end
239
+
240
+ end