ruby_apk 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
+