ruby_apk 0.4.0

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.
data/spec/apk_spec.rb ADDED
@@ -0,0 +1,268 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'tempfile'
3
+ require 'zip/zip'
4
+ require 'digest/sha1'
5
+ require 'digest/sha2'
6
+ require 'digest/md5'
7
+
8
+ class TempApk
9
+ attr_reader :path
10
+ def initialize
11
+ @tmp = Tempfile.open('apk_spec')
12
+ @path = @tmp.path
13
+ @tmp.close! # delete file
14
+ append("AndroidManifest.xml", "hogehoge")
15
+ append("resources.arsc", "hogehoge")
16
+ end
17
+ def destroy!
18
+ File.unlink(@path) if File.exist? @path
19
+ end
20
+ def append(entry_name, data)
21
+ Zip::ZipFile.open(@path, Zip::ZipFile::CREATE) { |zip|
22
+ zip.get_output_stream(entry_name) {|f| f.write data }
23
+ }
24
+ end
25
+ def remove(entry_name)
26
+ Zip::ZipFile.open(@path, Zip::ZipFile::CREATE) { |zip|
27
+ zip.remove(entry_name)
28
+ }
29
+ end
30
+ end
31
+
32
+ describe Android::Apk do
33
+ before do
34
+ $stderr.reopen('/dev/null','w')
35
+ end
36
+ let(:tmp_apk) { TempApk.new }
37
+ let(:tmp_path) { tmp_apk.path }
38
+ let(:apk) { Android::Apk.new(tmp_path) }
39
+ subject { apk }
40
+
41
+ after do
42
+ tmp_apk.destroy!
43
+ end
44
+
45
+ describe "#initialize" do
46
+ let(:path) { tmp_path }
47
+ subject { Android::Apk.new(path) }
48
+ context "with not exist path" do
49
+ let(:path) { "not exist path" }
50
+ it { expect{ subject }.to raise_error Android::NotFoundError }
51
+ end
52
+ context "with not zip file path" do
53
+ let(:path) { __FILE__ } # not zip file
54
+ it { expect{ subject }.to raise_error Android::NotApkFileError }
55
+ end
56
+ context "with zip(and non apk) file" do
57
+ before do
58
+ tmp_apk.append('hoge.txt', 'hogehoge')
59
+ tmp_apk.remove('AndroidManifest.xml')
60
+ end
61
+ it { expect{ subject }.to raise_error Android::NotApkFileError }
62
+ end
63
+ context "with zip includes AndroidManifest.xml" do
64
+ it { should be_a_instance_of Android::Apk }
65
+ end
66
+ end
67
+
68
+ describe "#path" do
69
+ subject { apk.path }
70
+ it "should equals initialized path" do
71
+ should == tmp_path
72
+ end
73
+ end
74
+
75
+ describe "#manifest" do
76
+ subject { apk.manifest }
77
+
78
+ context "when Manifest parse is succeeded." do
79
+ let(:mock_mani) { mock(Android::Manifest) }
80
+
81
+ before do
82
+ end
83
+ it "should return manifest object" do
84
+ Android::Manifest.should_receive(:new).and_return(mock_mani)
85
+ subject.should == mock_mani
86
+ end
87
+ end
88
+
89
+ context "when Manifest parse is failed" do
90
+ it 'should return nil' do
91
+ Android::Manifest.should_receive(:new).and_raise(Android::AXMLParser::ReadError)
92
+ subject.should be_nil
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "#dex" do
98
+ let(:mock_dex) { mock(Android::Dex) }
99
+ subject { apk.dex }
100
+ context "when there is no dex file" do
101
+ it { should be_nil }
102
+ end
103
+ context "when invalid dex file" do
104
+ before do
105
+ tmp_apk.append("classes.dex", "invalid dex")
106
+ end
107
+ it { should be_nil }
108
+ end
109
+ context "with mock classes.dex file" do
110
+ before do
111
+ tmp_apk.append("classes.dex", "mock data")
112
+ end
113
+ it "should return mock value" do
114
+ Android::Dex.should_receive(:new).with("mock data").and_return(mock_dex)
115
+ subject.should == mock_dex
116
+ end
117
+ end
118
+ context "with real classes.dex file" do
119
+ before do
120
+ dex_path = File.expand_path(File.dirname(__FILE__) + '/data/sample_classes.dex')
121
+ tmp_apk.append("classes.dex", File.open(dex_path, "rb") {|f| f.read })
122
+ end
123
+ it { should be_instance_of Android::Dex }
124
+ end
125
+ end
126
+
127
+ its(:bindata) { should be_instance_of String }
128
+ describe '#bindata' do
129
+ specify 'encoding should be ASCII-8BIT' do
130
+ subject.bindata.encoding.should eq Encoding::ASCII_8BIT
131
+ end
132
+ end
133
+
134
+ describe '#resource' do
135
+ let(:mock_rsc) { mock(Android::Resource) }
136
+ subject { apk.resource }
137
+ it "should return manifest object" do
138
+ Android::Resource.should_receive(:new).and_return(mock_rsc)
139
+ subject.should == mock_rsc
140
+ end
141
+ end
142
+
143
+ describe "#size" do
144
+ subject { apk.size }
145
+ it "should return apk file size" do
146
+ should == File.size(tmp_path)
147
+ end
148
+ end
149
+
150
+ describe "#digest" do
151
+ let(:data) { File.open(tmp_apk.path, 'rb'){|f| f.read } }
152
+ subject { apk.digest(type) }
153
+ context "when type is sha1" do
154
+ let(:type) { :sha1 }
155
+ it "should return sha1 digest" do
156
+ should eq Digest::SHA1.hexdigest(data)
157
+ end
158
+ end
159
+ context "when type is sha256" do
160
+ let(:type) { :sha256 }
161
+ it "should return sha256 digest" do
162
+ should == Digest::SHA256.hexdigest(data)
163
+ end
164
+ end
165
+ context "when type is md5" do
166
+ let(:type) { :md5 }
167
+ it "should return md5 digest" do
168
+ should == Digest::MD5.hexdigest(data)
169
+ end
170
+ end
171
+ context "when type is unkown symbol" do
172
+ let(:type) { :unknown }
173
+ it do
174
+ expect { subject }.to raise_error(ArgumentError)
175
+ end
176
+ end
177
+ context "when type is not symbol(String: 'sha1')" do
178
+ let(:type) { 'sha1' }
179
+ it { expect { subject }.to raise_error(ArgumentError) }
180
+ end
181
+ end
182
+
183
+ describe '#time' do
184
+ subject { apk.time }
185
+ it { should be_kind_of Time }
186
+ end
187
+
188
+ describe "#each_file" do
189
+ before do
190
+ tmp_apk.append("hoge.txt", "aaaaaaa")
191
+ end
192
+ it { expect { |b| apk.each_file(&b) }.to yield_successive_args(Array, Array, Array) }
193
+ let(:each_file_result ) {
194
+ result = []
195
+ apk.each_file do |name, data|
196
+ result << [name, data]
197
+ end
198
+ result
199
+ }
200
+
201
+ it "should invoke block with all file" do
202
+ each_file_result.should have(3).items
203
+ each_file_result.should include(['AndroidManifest.xml', 'hogehoge'])
204
+ each_file_result.should include(['hoge.txt','aaaaaaa'])
205
+ end
206
+ end
207
+
208
+ describe '#file' do
209
+ let(:data) { 'aaaaaaaaaaaaaaaaaaaaaaaaaaa' }
210
+ let(:path) { 'hoge.txt' }
211
+ subject { apk.file(path) }
212
+
213
+ before do
214
+ tmp_apk.append('hoge.txt', data)
215
+ end
216
+ context 'assigns exist path' do
217
+ it 'should equal file data' do
218
+ should eq data
219
+ end
220
+ end
221
+ context 'assigns not exist path' do
222
+ let(:path) { 'not_exist_path.txt' }
223
+ it { expect { subject }.to raise_error(Android::NotFoundError) }
224
+ end
225
+ end
226
+
227
+ describe '#each_entry' do
228
+ before do
229
+ tmp_apk.append("hoge.txt", "aaaaaaa")
230
+ end
231
+ it { expect { |b| apk.each_entry(&b) }.to yield_successive_args(Zip::ZipEntry, Zip::ZipEntry, Zip::ZipEntry) }
232
+ end
233
+
234
+ describe '#entry' do
235
+ subject { apk.entry(entry_name) }
236
+ context 'assigns exist entry' do
237
+ let(:entry_name) { 'AndroidManifest.xml' }
238
+ it { should be_instance_of Zip::ZipEntry }
239
+ end
240
+ context 'assigns not exist entry name' do
241
+ let(:entry_name) { 'not_exist_path' }
242
+ it { expect{ subject }.to raise_error(Android::NotFoundError) }
243
+ end
244
+ end
245
+
246
+ describe "#find" do
247
+ before do
248
+ tmp_apk.append("hoge.txt", "aaaaaaa")
249
+ end
250
+ it "should return matched array" do
251
+ array = apk.find do |name, data|
252
+ name == "hoge.txt"
253
+ end
254
+ array.should be_instance_of Array
255
+ array.should have(1).item
256
+ array[0] == "hoge.txt" # returns filename
257
+ end
258
+ context "when no entry is matched" do
259
+ it "should return emtpy array" do
260
+ array = apk.find do |name, dota|
261
+ false # nothing matched
262
+ end
263
+ array.should be_instance_of Array
264
+ array.should be_empty
265
+ end
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
+
4
+ describe Android::AXMLParser do
5
+ let(:bin_xml_path){ File.expand_path(File.dirname(__FILE__) + '/data/sample_AndroidManifest.xml') }
6
+ let(:bin_xml){ File.open(bin_xml_path, 'rb') {|f| f.read } }
7
+ let(:axmlparser){ Android::AXMLParser.new(bin_xml) }
8
+
9
+ describe "#parse" do
10
+
11
+ subject { axmlparser.parse }
12
+ context 'with sample_AndroidManifest.xml' do
13
+ it { should be_instance_of(REXML::Document) }
14
+ specify 'root element should be <manifest> element' do
15
+ subject.root.name.should eq 'manifest'
16
+ end
17
+ specify 'should have 2 <uses-permission> elements' do
18
+ subject.get_elements('/manifest/uses-permission').should have(2).items
19
+ end
20
+ end
21
+
22
+ context 'with nil data as binary xml' do
23
+ let(:bin_xml) { nil }
24
+ specify { expect{ subject }.to raise_error }
25
+ end
26
+
27
+ end
28
+
29
+ describe "#strings" do
30
+ context 'with sample_AndroidManifest.xml' do
31
+ subject { axmlparser.strings }
32
+ before do
33
+ axmlparser.parse
34
+ end
35
+ it { should be_instance_of(Array) }
36
+
37
+ # ugh!! the below test cases depend on sample_AndroidManifest.xml
38
+ it { should have(26).items} # in sample manifest.
39
+ it { should include("versionCode") }
40
+ it { should include("versionName") }
41
+ it { should include("minSdkVersion") }
42
+ it { should include("package") }
43
+ it { should include("manifest") }
44
+ end
45
+ end
46
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Android::Dex::AccessFlag do
4
+ let(:flag) { 0x01 }
5
+ subject { Android::Dex::AccessFlag.new(flag) }
6
+ its(:flag) { should eq flag }
7
+ end
8
+
9
+ describe Android::Dex::ClassAccessFlag do
10
+ let(:accessor) { Android::Dex::ClassAccessFlag.new(flags) }
11
+
12
+ subject { accessor.to_s }
13
+ context 'flags are 0x19(public static final)' do
14
+ let(:flags) { 0x19 }
15
+ it { should eq 'public static final' }
16
+ end
17
+ context 'flags are 0xc0(volatile transient)' do
18
+ let(:flags) { 0xc0 }
19
+ it { should eq 'volatile transient' }
20
+ end
21
+ context 'flags are 0x22(private synchronized)' do
22
+ let(:flags) { 0x22 }
23
+ it { should eq 'private synchronized' }
24
+ end
25
+ end
26
+
27
+ describe Android::Dex::MethodAccessFlag do
28
+ let(:accessor) { Android::Dex::MethodAccessFlag.new(flags) }
29
+ subject { accessor.to_s }
30
+ context 'flags are 0x19(public static final)' do
31
+ let(:flags) { 0x19 }
32
+ it { should eq 'public static final' }
33
+ end
34
+ context 'flags are 0xc0(bridge varargs)' do
35
+ let(:flags) { 0xc0 }
36
+ it { should eq 'bridge varargs' }
37
+ end
38
+ context 'flags are 0x22(private synchronized)' do
39
+ let(:flags) { 0x22 }
40
+ it { should eq 'private synchronized' }
41
+ end
42
+ end
@@ -0,0 +1,103 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Android::Dex do
4
+ describe Android::Dex::DexObject::Header do
5
+ let(:header_sample) {
6
+ "\x64\x65\x78\x0A\x30\x33\x35\x00\x3F\x14\x98\x2C\x25\x77\x9B\x8D" +
7
+ "\x7C\xF0\x0B\xFA\x4D\x7B\x03\xAD\x4C\x15\xBC\x31\x4F\xD3\x4B\x71" +
8
+ "\x58\x18\x00\x00\x70\x00\x00\x00\x78\x56\x34\x12\x00\x00\x00\x00" +
9
+ "\x00\x00\x00\x00\x88\x17\x00\x00\x7A\x00\x00\x00\x70\x00\x00\x00" +
10
+ "\x23\x00\x00\x00\x58\x02\x00\x00\x0E\x00\x00\x00\xE4\x02\x00\x00" +
11
+ "\x10\x00\x00\x00\x8C\x03\x00\x00\x2C\x00\x00\x00\x0C\x04\x00\x00" +
12
+ "\x0A\x00\x00\x00\x6C\x05\x00\x00\xAC\x11\x00\x00\xAC\x06\x00\x00"
13
+ }
14
+ let(:header) { Android::Dex::DexObject::Header.new(header_sample) }
15
+ describe "#symbols" do
16
+ subject { header.symbols }
17
+ it { should be_kind_of(Array) }
18
+ it { should have(23).items }
19
+ it { should include(:magic) }
20
+ it { should include(:checksum) }
21
+ it { should include(:signature) }
22
+ it { should include(:file_size) }
23
+ it { should include(:header_size) }
24
+ it { should include(:endian_tag) }
25
+ it { should include(:link_size) }
26
+ it { should include(:link_off) }
27
+ it { should include(:map_off) }
28
+ it { should include(:string_ids_size) }
29
+ it { should include(:string_ids_off) }
30
+ it { should include(:type_ids_size) }
31
+ it { should include(:type_ids_off) }
32
+ it { should include(:proto_ids_size) }
33
+ it { should include(:proto_ids_off) }
34
+ it { should include(:field_ids_size) }
35
+ it { should include(:field_ids_off) }
36
+ it { should include(:method_ids_size) }
37
+ it { should include(:method_ids_off) }
38
+ it { should include(:class_defs_size) }
39
+ it { should include(:class_defs_off) }
40
+ it { should include(:data_size) }
41
+ it { should include(:data_off) }
42
+ end
43
+
44
+ describe "#[]" do
45
+ subject { header }
46
+ it ':magic should be "dex\n035\0"' do
47
+ subject[:magic].should == "dex\n035\0"
48
+ end
49
+ it ":checksum should be 748164159(this value depends on sample_classes.dex)" do
50
+ subject[:checksum].should == 748164159
51
+ end
52
+ it ":signature should be 20byte string" do
53
+ subject[:signature].should be_kind_of String
54
+ subject[:signature].length == 20
55
+ end
56
+ it ":file_size should be classes.dex file size" do
57
+ subject[:file_size].should == 6232
58
+ end
59
+ it ":header_size should be 0x70" do
60
+ subject[:header_size].should == 0x70
61
+ end
62
+ it "should have integer params" do
63
+ subject[:header_size].should == 0x70
64
+ end
65
+ context "with int symbols" do
66
+ before do
67
+ @params = [
68
+ :link_size,
69
+ :link_off,
70
+ :map_off,
71
+ :string_ids_size,
72
+ :string_ids_off,
73
+ :type_ids_size,
74
+ :type_ids_off,
75
+ :proto_ids_size,
76
+ :proto_ids_off,
77
+ :field_ids_size,
78
+ :field_ids_off,
79
+ :method_ids_size,
80
+ :method_ids_off,
81
+ :class_defs_size,
82
+ :class_defs_off,
83
+ :data_size,
84
+ :data_off,
85
+ ]
86
+ end
87
+ it "should have integer value" do
88
+ @params.each do |sym|
89
+ subject[sym].should be_kind_of Integer
90
+ end
91
+ end
92
+ end
93
+ context "with unkown params" do
94
+ it { subject[:unkown].should be_nil }
95
+ end
96
+ end
97
+
98
+ describe "#inspect" do
99
+ subject { header.inspect }
100
+ it { should match(/\A<Android::Dex::DexObject::Header.*>\Z/m) }
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,121 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ shared_context 'with sample_classes.dex', with: :sample_dex do
4
+ let(:dex_path){ File.expand_path(File.dirname(__FILE__) + '/../data/sample_classes.dex') }
5
+ let(:dex_bin){ File.open(dex_path, 'rb') {|f| f.read } }
6
+ let(:dex){ Android::Dex.new(dex_bin) }
7
+ let(:last_class) { dex.classes.last }
8
+ end
9
+ describe Android::Dex::ClassInfo do
10
+ include_context 'with sample_classes.dex'
11
+ context 'about the last class in Dex#classes with sample_classes.dex' do
12
+ let(:last_class) { dex.classes.last }
13
+ its(:name){ should eq 'Lexample/app/sample/SampleCode;' }
14
+ its(:access_flags){ should be_instance_of Android::Dex::ClassAccessFlag }
15
+ its(:super_class){ should eq 'Ljava/lang/Object;' }
16
+ its(:class_data){ should be_instance_of Android::Dex::DexObject::ClassDataItem }
17
+ its(:class_def){ should be_instance_of Android::Dex::DexObject::ClassDefItem }
18
+ its(:definition) { should eq 'public class Lexample/app/sample/SampleCode; extends Ljava/lang/Object;' }
19
+
20
+ subject { last_class }
21
+ describe '#static_fields' do
22
+ subject { last_class.static_fields }
23
+ it { should have(1).item }
24
+ specify { subject[0].should be_instance_of Android::Dex::FieldInfo }
25
+ end
26
+ describe '#instance_fields' do
27
+ subject { last_class.instance_fields }
28
+ it { should have(1).item }
29
+ specify { subject[0].should be_instance_of Android::Dex::FieldInfo }
30
+ end
31
+ describe '#direct_methods' do
32
+ subject { last_class.direct_methods }
33
+ it { should have(3).items }
34
+ specify { subject[0].should be_instance_of Android::Dex::MethodInfo }
35
+ end
36
+ describe '#virtual_methods' do
37
+ subject { last_class.virtual_methods }
38
+ it { should have(18).items }
39
+ specify { subject[0].should be_instance_of Android::Dex::MethodInfo }
40
+ end
41
+ end
42
+ context 'when class_data_item is nil' do
43
+ let(:mock_cls_def) {
44
+ s = double(Android::Dex::DexObject::ClassDefItem)
45
+ s.stub(:'[]').with(anything()).and_return(0)
46
+ s.stub(:class_data_item).and_return(nil)
47
+ s
48
+ }
49
+ let(:class_info) { Android::Dex::ClassInfo.new(mock_cls_def, nil) }
50
+ describe '#static_fields' do
51
+ subject { class_info.static_fields }
52
+ it { should be_kind_of Array }
53
+ it { should be_empty }
54
+ end
55
+ describe '#instance_fields' do
56
+ subject { class_info.instance_fields }
57
+ it { should be_kind_of Array }
58
+ it { should be_empty }
59
+ end
60
+ describe '#direct_methods' do
61
+ subject { class_info.direct_methods }
62
+ it { should be_kind_of Array }
63
+ it { should be_empty }
64
+ end
65
+ describe '#virtual_methods' do
66
+ subject { class_info.virtual_methods }
67
+ it { should be_kind_of Array }
68
+ it { should be_empty }
69
+ end
70
+ end
71
+ end
72
+
73
+ describe Android::Dex::FieldInfo do
74
+ include_context 'with sample_classes.dex'
75
+ context 'about the first static field of the last class with sample_classes.dex'do
76
+ let(:first_static_field) { last_class.static_fields.first }
77
+ subject { first_static_field }
78
+ its(:name) { should eq 'TAG' }
79
+ its(:type) { should eq 'Ljava/lang/String;' }
80
+ describe '#access_flags' do
81
+ subject { first_static_field.access_flags }
82
+ it { should be_instance_of Android::Dex::ClassAccessFlag }
83
+ specify { subject.to_s.should eq 'private static final' }
84
+ end
85
+ describe '#definition' do
86
+ subject { first_static_field.definition }
87
+ it { should eq 'private static final Ljava/lang/String; TAG' }
88
+ end
89
+ end
90
+ end
91
+
92
+ describe Android::Dex::MethodInfo do
93
+ include_context 'with sample_classes.dex'
94
+ context 'about the first direct method of the last class' do
95
+ let(:first_direct_method) { last_class.direct_methods.first }
96
+ subject { first_direct_method }
97
+ its(:name) { should eq '<init>' }
98
+ end
99
+ context 'about the first virtual method of the last class' do
100
+ let(:first_virtual_method) { last_class.virtual_methods.first }
101
+ subject { first_virtual_method }
102
+ its(:name) { should eq 'processDoWhile' }
103
+ its(:code_item) { should be_instance_of Android::Dex::DexObject::CodeItem }
104
+ describe '#parameters' do
105
+ subject { first_virtual_method.parameters }
106
+ it { should have(1).item }
107
+ it { should include('int') }
108
+ end
109
+ end
110
+ context 'about the 12th virtual method(processTryCatch) of the last class' do
111
+ let(:a_virtual_method) { last_class.virtual_methods[12]}
112
+ subject { a_virtual_method }
113
+ its(:name) { should eq 'processTryCatch' }
114
+ describe '#code_item' do
115
+ subject { a_virtual_method.code_item }
116
+ it { should be_instance_of Android::Dex::DexObject::CodeItem }
117
+ its(:debug_info_item) { should be_instance_of Android::Dex::DexObject::DebugInfoItem }
118
+ end
119
+ end
120
+ end
121
+
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Android::Dex do
4
+
5
+ describe ".uleb128" do
6
+ # @see http://en.wikipedia.org/wiki/LEB128
7
+ it "[0x00] should be 0" do
8
+ Android::Dex.uleb128("\x00").should == [0,1]
9
+ end
10
+ it "[0x01] should be 1" do
11
+ Android::Dex.uleb128("\x01").should == [1,1]
12
+ end
13
+ it "[0x7f] should be 127" do
14
+ Android::Dex.uleb128("\x7f").should == [127,1]
15
+ end
16
+ it "[0x80,0x7f] should be 16256" do
17
+ Android::Dex.uleb128("\x80\x7f").should == [16256,2]
18
+ end
19
+ it "[0xe5,0x8e,0x26] should be 624485" do
20
+ Android::Dex.uleb128("\xe5\x8e\x26").should == [624485,3]
21
+ end
22
+ end
23
+
24
+ describe ".uleb128p1" do
25
+ it "[0x00] should be -1" do
26
+ Android::Dex.uleb128p1("\x00").should == [-1,1]
27
+ end
28
+ it "[0x01] should be 0" do
29
+ Android::Dex.uleb128p1("\x01").should == [0,1]
30
+ end
31
+ it "[0x7f] should be 126" do
32
+ Android::Dex.uleb128p1("\x7f").should == [126,1]
33
+ end
34
+ it "[0x80,0x7f] should be 16255" do
35
+ Android::Dex.uleb128p1("\x80\x7f").should == [16255,2]
36
+ end
37
+ it "[0xe5,0x8e,0x26] should be 624485" do
38
+ Android::Dex.uleb128("\xe5\x8e\x26").should == [624485,3]
39
+ end
40
+ end
41
+ describe '.sleb128' do
42
+ it "[0x00] should be 0" do
43
+ Android::Dex.sleb128("\x00").should == [0,1]
44
+ end
45
+ it "[0x01] should be 1" do
46
+ Android::Dex.sleb128("\x01").should == [1,1]
47
+ end
48
+ it "[0x7f] should be -1" do
49
+ Android::Dex.sleb128("\x7f").should == [-1,1]
50
+ end
51
+ it "[0x80,0x7f] should be 127" do
52
+ Android::Dex.sleb128("\x80\x7f").should == [-128,2]
53
+ end
54
+ end
55
+ end
56
+