brazenhead 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/driver/AndroidManifest.xml +21 -0
  2. data/driver/brazenhead-release-unsigned.apk +0 -0
  3. data/features/brazenhead.feature +35 -0
  4. data/features/exception.feature +6 -0
  5. data/features/robotium.feature +31 -0
  6. data/features/step_definitions/brazenhead_steps.rb +52 -0
  7. data/features/step_definitions/exception_steps.rb +13 -0
  8. data/features/step_definitions/robotium_steps.rb +62 -0
  9. data/features/support/ApiDemos.apk +0 -0
  10. data/features/support/debug.keystore +0 -0
  11. data/features/support/env.rb +30 -0
  12. data/lib/brazenhead/android.rb +37 -0
  13. data/lib/brazenhead/builder.rb +92 -0
  14. data/lib/brazenhead/call_accumulator.rb +28 -0
  15. data/lib/brazenhead/core_ext/string.rb +7 -0
  16. data/lib/brazenhead/device.rb +35 -0
  17. data/lib/brazenhead/manifest_info.rb +51 -0
  18. data/lib/brazenhead/package.rb +36 -0
  19. data/lib/brazenhead/process.rb +35 -0
  20. data/lib/brazenhead/request.rb +40 -0
  21. data/lib/brazenhead/server.rb +54 -0
  22. data/lib/brazenhead/signer.rb +66 -0
  23. data/lib/brazenhead/version.rb +3 -0
  24. data/lib/brazenhead.rb +42 -0
  25. data/spec/lib/brazenhead/android_spec.rb +35 -0
  26. data/spec/lib/brazenhead/builder_spec.rb +108 -0
  27. data/spec/lib/brazenhead/call_accumulator_spec.rb +11 -0
  28. data/spec/lib/brazenhead/device_spec.rb +27 -0
  29. data/spec/lib/brazenhead/manifest_info_spec.rb +61 -0
  30. data/spec/lib/brazenhead/package_spec.rb +30 -0
  31. data/spec/lib/brazenhead/process_spec.rb +64 -0
  32. data/spec/lib/brazenhead/request_spec.rb +51 -0
  33. data/spec/lib/brazenhead/server_spec.rb +75 -0
  34. data/spec/lib/brazenhead/signer_spec.rb +35 -0
  35. data/spec/lib/brazenhead_spec.rb +34 -0
  36. data/spec/spec_helper.rb +18 -0
  37. metadata +176 -0
@@ -0,0 +1,66 @@
1
+ require 'brazenhead/android'
2
+ require 'brazenhead/process'
3
+
4
+ module Brazenhead
5
+ module Signer
6
+ include Brazenhead::Android
7
+
8
+ def sign(apk, keystore)
9
+ @keystore = keystore
10
+ jarsign(apk)
11
+ verify(apk)
12
+ process.run(*zipalign(apk), *signed(apk))
13
+ end
14
+
15
+ private
16
+ def process
17
+ @process ||= Brazenhead::Process.new
18
+ end
19
+
20
+ def jarsign(apk)
21
+ process.run(*jar_command, *keypasses, *the_key, apk, key_alias)
22
+ end
23
+
24
+ def jar_command
25
+ "jarsigner -sigalg MD5withRSA -digestalg SHA1".split
26
+ end
27
+
28
+ def verify(apk)
29
+ process.run(*"jarsigner -verify".split, apk)
30
+ error_signing(apk) unless process.last_stdout.include? "jar verified"
31
+ end
32
+
33
+ def zipalign(apk)
34
+ "zipalign -v 4".split << apk
35
+ end
36
+
37
+ def signed(apk)
38
+ File.join dir(apk), new_name(apk)
39
+ end
40
+
41
+ def dir(apk)
42
+ File.dirname(apk)
43
+ end
44
+
45
+ def new_name(apk)
46
+ File.basename(apk, '.apk') << '-signed.apk'
47
+ end
48
+
49
+ def keypasses
50
+ "-storepass #{@keystore[:password]} -keypass #{@keystore[:keystore_password]}".split
51
+ end
52
+
53
+ def the_key
54
+ ["-keystore", File.expand_path(@keystore[:path])]
55
+ end
56
+
57
+ def key_alias
58
+ @keystore[:alias]
59
+ end
60
+
61
+ def error_signing(apk)
62
+ raise Exception, "error signing #{apk} (#{process.last_stdout})"
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,3 @@
1
+ module Brazenhead
2
+ VERSION = "0.1"
3
+ end
data/lib/brazenhead.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'brazenhead/version'
2
+ require 'brazenhead/device'
3
+ require 'brazenhead/request'
4
+ require 'brazenhead/call_accumulator'
5
+ require 'brazenhead/core_ext/string'
6
+
7
+ module Brazenhead
8
+ def method_missing(method, *args)
9
+ call_method_on_driver(method.to_s.to_java_call, args)
10
+ end
11
+
12
+ def chain_calls(&block)
13
+ accumulator.clear
14
+ block.call accumulator
15
+ @last_response = device.send(accumulator.message)
16
+ @last_response
17
+ end
18
+
19
+ def last_response
20
+ @last_response
21
+ end
22
+
23
+ private
24
+
25
+ def call_method_on_driver(method, args)
26
+ message = request.build(method, args)
27
+ @last_response = device.send(message)
28
+ @last_response
29
+ end
30
+
31
+ def device
32
+ @device ||= Brazenhead::Device.new
33
+ end
34
+
35
+ def request
36
+ @request ||= Brazenhead::Request.new
37
+ end
38
+
39
+ def accumulator
40
+ @accumulator ||= Brazenhead::CallAccumulator.new
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ require 'brazenhead/android'
2
+
3
+ class AndroidTest
4
+ include Brazenhead::Android
5
+ end
6
+
7
+ describe Brazenhead::Android do
8
+ let(:android) { AndroidTest.new }
9
+
10
+ context "resolving android paths" do
11
+
12
+ before(:each) do
13
+ ENV.stub(:[]).with('ANDROID_HOME').and_return('/path/to/android')
14
+ File.stub(:exists?).and_return(true)
15
+ end
16
+
17
+ it "should be able to locate the android jar" do
18
+ ENV.stub(:[]).with('ANDROID_HOME').and_return('/path/to/android')
19
+ android.path_to(8).should eq '/path/to/android/platforms/android-8/android.jar'
20
+ end
21
+
22
+ it "should raise an error if the path is not found" do
23
+ File.should_receive(:exists?).and_return(false)
24
+ api = 8
25
+ lambda { android.path_to(api) }.should raise_error (message="the path to android-#{api} was not found")
26
+ end
27
+ end
28
+
29
+ context "locating the keystore" do
30
+ it "should be able to locate the path to the default keystore" do
31
+ File.stub(:expand_path).with("~/.android/debug.keystore").and_return("/some/expanded/.android/debug.keystore")
32
+ android.default_keystore[:path].should eq "/some/expanded/.android/debug.keystore"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,108 @@
1
+ require 'brazenhead/builder'
2
+
3
+ describe Brazenhead::Builder do
4
+ let(:apk) { 'some_apk.apk' }
5
+ let(:activity) { 'SomeActivityToStart' }
6
+ let(:server) { Brazenhead::Builder.new }
7
+ let(:manifest_info) { double('manifest-info').as_null_object }
8
+ let(:tmpdir) { '/some/tmp/dir' }
9
+ let(:driver_apk) { 'brazenhead-release-unsigned.apk' }
10
+ let(:keystore) { {:path => 'default.keystore'} }
11
+
12
+ before(:each) do
13
+ File.stub(:exists?).and_return(true)
14
+ Dir.stub(:mktmpdir).and_yield(tmpdir)
15
+ FileUtils.stub(:copy_file)
16
+ File.stub(:read).and_return('')
17
+ File.stub(:write)
18
+ server.stub(:update_manifest)
19
+ server.stub(:sign)
20
+ server.stub(:install)
21
+ Brazenhead::ManifestInfo.stub(:new).with(apk).and_return(manifest_info)
22
+ end
23
+
24
+ context "building the test server" do
25
+ context "validating the arguments" do
26
+ it "should require that the package exists" do
27
+ File.should_receive(:exists?).and_return(false)
28
+ lambda { server.build_for('some_package.apk', keystore) }.should raise_error(message="Invalid package path: some_package.apk")
29
+ end
30
+ end
31
+
32
+ context "setting up the test server sandbox" do
33
+ let(:base_gem_dir) { '/base/gem' }
34
+ let(:base_test_apk) { "#{base_gem_dir}/driver/#{driver_apk}" }
35
+ let(:manifest) { 'AndroidManifest.xml' }
36
+ let(:base_manifest) { "#{base_gem_dir}/driver/#{manifest}" }
37
+
38
+ before(:each) do
39
+ File.stub(:expand_path).with("~/.android/debug.keystore").and_return("expanded/.android/debug.keystore")
40
+ File.stub(:expand_path).with("../../../", anything()).and_return(base_gem_dir)
41
+ end
42
+
43
+ it "should use a temporary directory" do
44
+ Dir.should_receive(:mktmpdir)
45
+ server.build_for(apk, keystore)
46
+ end
47
+
48
+ it "should copy the unsigned release package into the directory" do
49
+ FileUtils.should_receive(:copy_file).with(base_test_apk, File.join(tmpdir, driver_apk))
50
+ server.build_for(apk, keystore)
51
+ end
52
+
53
+ it "should copy the manifest into the directory" do
54
+ FileUtils.should_receive(:copy_file).with(base_manifest, File.join(tmpdir, manifest))
55
+ server.build_for(apk, keystore)
56
+ end
57
+ end
58
+
59
+ context "updating the manifest" do
60
+ it "should load the contents of the existing manifest" do
61
+ File.should_receive(:read).with("#{tmpdir}/AndroidManifest.xml")
62
+ server.build_for(apk, keystore)
63
+ end
64
+
65
+ it "should replace the target package" do
66
+ the_target_package = "the.target.package"
67
+ File.should_receive(:read).and_return("android:targetPackage=\"it.does.not.matter\"")
68
+ manifest_info.should_receive(:package).and_return(the_target_package)
69
+ File.should_receive(:write).with("#{tmpdir}/AndroidManifest.xml", "android:targetPackage=\"#{the_target_package}\"")
70
+
71
+ server.build_for(apk, keystore)
72
+ end
73
+
74
+ it "should package the modified manifest back into the test package" do
75
+ manifest_info.should_receive(:target_sdk).and_return(10)
76
+ server.should_receive(:update_manifest).with("#{tmpdir}/#{driver_apk}", "#{tmpdir}/AndroidManifest.xml", 10)
77
+ server.build_for(apk, keystore)
78
+ end
79
+
80
+ end
81
+
82
+ context "signing the test server" do
83
+ it "should use the provided keystore to sign the package" do
84
+ server.should_receive(:sign).with("#{tmpdir}/#{driver_apk}", {:path => 'another keystore'})
85
+ server.build_for(apk, :path => 'another keystore')
86
+ end
87
+ end
88
+
89
+ context "installing the test server" do
90
+ it "should reinstall the test server to the device" do
91
+ server.should_receive(:install).with("#{tmpdir}/#{driver_apk}", "-r", {}, 90)
92
+ server.build_for(apk, keystore)
93
+ end
94
+
95
+ it "should reinstall the target package to the device" do
96
+ server.should_receive(:install).with(apk, "-r", {}, 90)
97
+ server.build_for(apk, keystore)
98
+ end
99
+
100
+ end
101
+ end
102
+
103
+ context "sending back informationa about the server" do
104
+ it "should send back information about the target package" do
105
+ server.build_for(apk, keystore).should_be manifest_info
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brazenhead::CallAccumulator do
4
+ let(:accumulator) { Brazenhead::CallAccumulator.new }
5
+
6
+ it "should accumulate a series of calls and build the message" do
7
+ accumulator.first_call
8
+ accumulator.second_call
9
+ accumulator.message.should == "commands=[{\"name\":\"firstCall\"},{\"name\":\"secondCall\"}]"
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brazenhead::Device do
4
+ let(:device) { Brazenhead::Device.new }
5
+ let(:http_mock) { double("http_mock") }
6
+
7
+ before(:each) do
8
+ Net::HTTP.stub(:new).and_return(http_mock)
9
+ end
10
+
11
+ it "should retry the http call if it fails the first time" do
12
+ http_mock.should_receive(:post).and_raise("error")
13
+ http_mock.should_receive(:post).with('/', "blah")
14
+ device.send "blah"
15
+ end
16
+
17
+ it "should retry the http call a maximum of 20 times" do
18
+ device.should_receive(:sleep).exactly(20).times
19
+ http_mock.should_receive(:post).exactly(20).times.and_raise("error")
20
+ expect { device.send "blah" }.to raise_error
21
+ end
22
+
23
+ it "should be able to stop the server" do
24
+ http_mock.should_receive(:post).with('/kill', '')
25
+ device.stop
26
+ end
27
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brazenhead::ManifestInfo do
4
+ let(:process) { double('brazenhead-process').as_null_object }
5
+ let(:manifest_info) { Brazenhead::ManifestInfo.new 'some_apk.apk' }
6
+
7
+ before(:each) do
8
+ Brazenhead::Process.stub(:new).and_return(process)
9
+ end
10
+
11
+ it "should grab the minimum sdk" do
12
+ process.should_receive(:last_stdout).and_return("
13
+ E: uses-sdk (line=39)
14
+ A: android:minSdkVersion(0x0101020c)=(type 0x10)0x0f
15
+ A: android:targetSdkVersion(0x01010270)=(type 0x10)0xe")
16
+
17
+ manifest_info.min_sdk.should eq 15
18
+ end
19
+
20
+ it "should load the manifest the first time it needs it" do
21
+ process.should_receive(:run).with('aapt', 'dump', 'xmltree', 'some_apk.apk', 'AndroidManifest.xml')
22
+ manifest_info.min_sdk
23
+ end
24
+
25
+ it "should default the minimum sdk to 1" do
26
+ process.should_receive(:last_stdout).and_return("
27
+ E: uses-sdk (line=39)
28
+ A: android:notTheminSdkVersion(0x0101020c)=(type 0x10)0x0f
29
+ A: android:targetSdkVersion(0x01010270)=(type 0x10)0xe")
30
+
31
+ manifest_info.min_sdk.should eq 1
32
+ end
33
+
34
+ it "should grab the maximum sdk" do
35
+ process.should_receive(:last_stdout).and_return("
36
+ E: uses-sdk (line=39)
37
+ A: android:minSdkVersion(0x0101020c)=(type 0x10)0x0f
38
+ A: android:maxSdkVersion(0x0101020c)=(type 0x10)0x0a")
39
+
40
+ manifest_info.max_sdk.should eq 10
41
+ end
42
+
43
+ it "should grab the target sdk" do
44
+ process.should_receive(:last_stdout).and_return("
45
+ E: uses-sdk (line=39)
46
+ A: android:notTheminSdkVersion(0x0101020c)=(type 0x10)0x0f
47
+ A: android:targetSdkVersion(0x01010270)=(type 0x10)0xe")
48
+
49
+ manifest_info.target_sdk.should eq 14
50
+ end
51
+
52
+ it "should grab the default package" do
53
+ process.should_receive(:last_stdout).and_return("
54
+ N: android=http://schemas.android.com/apk/res/android
55
+ E: manifest (line=22)
56
+ A: package=\"com.example.android.apis\" (Raw: \"com.example.android.apis\")")
57
+
58
+ manifest_info.package.should eq 'com.example.android.apis'
59
+ end
60
+
61
+ end
@@ -0,0 +1,30 @@
1
+ require 'brazenhead/package'
2
+
3
+ class PackageTest
4
+ include Brazenhead::Package
5
+ end
6
+
7
+ describe Brazenhead::Package do
8
+ let(:package) { PackageTest.new }
9
+ let(:process) { double('brazenhead-process').as_null_object }
10
+ let(:android) { double('brazenhead-android') }
11
+ let(:apk) { '/path/to/some_apk.apk' }
12
+
13
+ before(:each) do
14
+ Brazenhead::Process.stub(:new).and_return(process)
15
+ end
16
+
17
+ context "updating a manifest" do
18
+ let(:manifest) { '/path/to/AndroidManifest.xml' }
19
+ let(:android_jar) { '/path/to/android.jar' }
20
+
21
+ it "should update the manifest" do
22
+ package.stub(:path_to).and_return(android_jar)
23
+ process.should_receive(:run).with('aapt', 'p', '-u', '-f', '-F', apk, '-M', manifest, '-I', android_jar)
24
+
25
+ package.update_manifest(apk, manifest)
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brazenhead::Process do
4
+ let(:stdout) { double(:name => 'stdout').as_null_object }
5
+ let(:stderr) { double(:name => 'stderr').as_null_object }
6
+ let(:running_process) { double('process').as_null_object }
7
+ let(:process) { Brazenhead::Process.new }
8
+
9
+ before(:each) do
10
+ Time.stub(:now) { 'this:time' }
11
+ Tempfile.stub(:new).and_return(stdout,stderr)
12
+
13
+ running_process.stub_chain(:io, :stdout).and_return(stdout)
14
+ running_process.stub_chain(:io, :stdout=)
15
+ running_process.stub_chain(:io, :stderr).and_return(stderr)
16
+ running_process.stub_chain(:io, :stderr=)
17
+
18
+ ChildProcess.stub(:build) { running_process }
19
+ end
20
+
21
+ it "should run the command with arguments" do
22
+ ChildProcess.should_receive(:build).with('command', 'some', 'argument')
23
+ running_process.should_receive(:start)
24
+ process.run('command', 'some', 'argument')
25
+ end
26
+
27
+ it "should wait for the command to complete" do
28
+ running_process.should_receive(:wait)
29
+ process.run('anything')
30
+ end
31
+
32
+ it "should redirect stdout and stderr" do
33
+ Tempfile.should_receive(:new).with('brazenhead-proc-out-this_time')
34
+ Tempfile.should_receive(:new).with('brazenhead-proc-err-this_time')
35
+ process.run('anything')
36
+ end
37
+
38
+ it "should capture stdout and stderr" do
39
+ running_process.io.should_receive(:stdout=).with(stdout)
40
+ running_process.io.should_receive(:stderr=).with(stderr)
41
+ process.run('anything')
42
+ end
43
+
44
+ it "should preserve the last stdout and stderr" do
45
+ [stdout, stderr].each do |iostream|
46
+ iostream.should_receive(:rewind)
47
+ iostream.should_receive(:read).and_return("last #{iostream.name}")
48
+ end
49
+
50
+ process.run('anything')
51
+
52
+ process.last_stdout.should eq 'last stdout'
53
+ process.last_stderr.should eq 'last stderr'
54
+ end
55
+
56
+ it "should clean up stdout and stderr temporary files" do
57
+ [stdout, stderr].each do |iostream|
58
+ iostream.should_receive(:close)
59
+ iostream.should_receive(:unlink)
60
+ end
61
+ process.run('anything')
62
+ end
63
+
64
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+
4
+ describe Brazenhead::Request do
5
+ let(:request) { Brazenhead::Request.new }
6
+
7
+ def json_message(message)
8
+ JSON.parse(message[9..-1])[0]
9
+ end
10
+
11
+ it "should place the method name in the json file" do
12
+ message = request.build('call_me', [])
13
+ json_message(message)['name'].should == 'call_me'
14
+ end
15
+
16
+ it "should place an argument in the json file" do
17
+ message = request.build('call_me', ['the_argument'])
18
+ json_message(message)['arguments'].should == ['the_argument']
19
+ end
20
+
21
+ it "should place multiple arguments in the json file" do
22
+ message = request.build('call_me', ['first', 'second'])
23
+ json_message(message)['arguments'].should == ['first', 'second']
24
+ end
25
+
26
+ it "should use the target when one is provided" do
27
+ message = request.build('call_me', [{:target => 'Robotium'}])
28
+ json_message(message)['target'].should == 'Robotium'
29
+ end
30
+
31
+ it "should grab the target from the final parameter" do
32
+ message = request.build('call_me', ['the_argument', {:target => 'Robotium'}])
33
+ json_message(message)['target'].should == 'Robotium'
34
+ end
35
+
36
+ it "should use a variable when one is provided" do
37
+ message = request.build('call_me', [{:variable => '@@var@@'}])
38
+ json_message(message)['variable'].should == "@@var@@"
39
+ end
40
+
41
+ it "should grab the variable from the final parameter" do
42
+ message = request.build('call_me', ['the_argument', {:variable => '@@var@@'}])
43
+ json_message(message)['variable'].should == '@@var@@'
44
+ end
45
+
46
+ it "should find both the target and variable in the final hash parameter" do
47
+ message = request.build('call_me', ['the_argument', {:target => 'Robotium', :variable => '@@var@@'}])
48
+ json_message(message)['variable'].should == '@@var@@'
49
+ json_message(message)['target'].should == 'Robotium'
50
+ end
51
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe Brazenhead::Server do
4
+ let(:server) { Brazenhead::Server.new(apk) }
5
+ let(:builder) { double('brazenhead-builder').as_null_object }
6
+ let(:manifest) { double('manifest-info') }
7
+ let(:apk) { 'someapk.apk' }
8
+ let(:activity) { 'SomeActivity' }
9
+ let(:default_keystore) { server.default_keystore }
10
+
11
+ before(:each) do
12
+ Brazenhead::Builder.stub(:new).and_return(builder)
13
+ builder.stub(:build_for).with(apk, anything()).and_return(manifest)
14
+ server.stub(:shell)
15
+ server.stub(:forward)
16
+ server.stub(:instrument)
17
+ manifest.stub(:package).and_return('com.example')
18
+ end
19
+
20
+ context "installing the server for the first time" do
21
+ it "should install the server" do
22
+ server.start(activity)
23
+ end
24
+
25
+ it "should only install it the first time" do
26
+ builder.should_receive(:build_for).once.and_return(manifest)
27
+ server.start(activity)
28
+ server.start(activity)
29
+ end
30
+
31
+ it "should use the default keystore if none is provided" do
32
+ builder.should_receive(:build_for).with(apk, server.default_keystore)
33
+ server.start(activity)
34
+ end
35
+
36
+ it "should use the provided keystore if it is given" do
37
+ other_keystore = {:path => 'other_keystore'}
38
+ builder.should_receive(:build_for).with(apk, other_keystore)
39
+ other_server = Brazenhead::Server.new(apk, other_keystore)
40
+ other_server.stub(:shell)
41
+ other_server.stub(:forward)
42
+ other_server.stub(:instrument)
43
+ other_server.start(activity)
44
+ end
45
+
46
+ it "should setup the proper port forwarding" do
47
+ server.should_receive(:forward).with("tcp:7777", "tcp:54767")
48
+ server.start(activity)
49
+ end
50
+ end
51
+
52
+ context "instrumenting the application" do
53
+ let(:runner) { 'com.leandog.brazenhead/com.leandog.brazenhead.BrazenheadInstrumentation' }
54
+
55
+ it "should use the package from the target manifest" do
56
+ manifest.should_receive(:package)
57
+ server.start(activity)
58
+ end
59
+
60
+ it "should start instrumenting" do
61
+ expected = {:packageName => 'com.example', :fullLauncherName => 'com.example.SomeActivity', :class => 'com.leandog.brazenhead.TheTest'}
62
+ server.should_receive(:instrument).with(runner, expected)
63
+ server.start(activity)
64
+ end
65
+
66
+ it "should be able to stop instrumenting" do
67
+ device = double('brazenhead-device')
68
+ Brazenhead::Device.should_receive(:new).and_return(device)
69
+ device.should_receive(:stop)
70
+ server.stop
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,35 @@
1
+ class SignerTest
2
+ include Brazenhead::Signer
3
+ end
4
+
5
+ describe Brazenhead::Signer do
6
+ let(:signer) { SignerTest.new }
7
+ let(:process) { double('brazenhead-process').as_null_object }
8
+ let(:keypath) { '/path/to/debug.keystore' }
9
+
10
+ before(:each) do
11
+ Brazenhead::Process.stub(:new).and_return(process)
12
+ process.stub(:last_stdout).and_return("jar verified")
13
+ signer.stub(:default_key_path).and_return(keypath)
14
+ end
15
+
16
+ it "should give back the default keystore information" do
17
+ expected = {:path => '/path/to/debug.keystore', :alias => 'androiddebugkey', :password => 'android', :keystore_password => 'android'}
18
+ signer.default_keystore.should eq expected
19
+ end
20
+
21
+ it "should be able to sign a package" do
22
+ expanded_keypath = "/expanded/#{keypath}"
23
+ File.should_receive(:expand_path).with(keypath).and_return(expanded_keypath)
24
+ process.should_receive(:run).with('jarsigner', '-sigalg', 'MD5withRSA', '-digestalg', 'SHA1', '-storepass', 'android', '-keypass', 'android', '-keystore', expanded_keypath, '/some_apk.apk', 'androiddebugkey')
25
+ process.should_receive(:run).with('zipalign', '-v', '4', '/some_apk.apk', '/some_apk-signed.apk')
26
+ signer.sign('/some_apk.apk', signer.default_keystore)
27
+ end
28
+
29
+ it "should raise if signing fails to verify" do
30
+ process.should_receive(:run).with(*"jarsigner -verify /some_apk.apk".split)
31
+ process.stub(:last_stdout).and_return("something went wrong")
32
+ lambda { signer.sign('/some_apk.apk', signer.default_keystore) }.should raise_error(message="error signing /some_apk.apk (something went wrong)")
33
+ end
34
+
35
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ class Driver
4
+ include Brazenhead
5
+ end
6
+
7
+ describe Brazenhead do
8
+
9
+ let(:driver) { Driver.new }
10
+ let(:http_mock) { double("http_mock") }
11
+
12
+ context "when calling a method directly on the module" do
13
+ before(:each) do
14
+ Net::HTTP.stub(:new).and_return(http_mock)
15
+ end
16
+
17
+ it "should convert method name to camel case with first letter lowercase" do
18
+ driver.should_receive(:call_method_on_driver).with("fooBar", [])
19
+ driver.foo_bar
20
+ end
21
+
22
+ it "should make an http call passing the method name as the name" do
23
+ Net::HTTP.should_receive(:new).and_return(http_mock)
24
+ http_mock.should_receive(:post).with('/', "commands=[{\"name\":\"fooBar\"}]")
25
+ driver.foo_bar
26
+ end
27
+
28
+ it "should make the result of the call available for inspection" do
29
+ http_mock.should_receive(:post).with('/', "commands=[{\"name\":\"fooBar\"}]").and_return("Success")
30
+ result = driver.foo_bar
31
+ driver.last_response.should == result
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ if ENV['coverage']
6
+ raise "simplecov only works on Ruby 1.9" unless RUBY_VERSION =~ /^1\.9/
7
+
8
+ require 'simplecov'
9
+ SimpleCov.start { add_filter "spec/" }
10
+ end
11
+
12
+ require 'rspec'
13
+ require 'brazenhead'
14
+ require 'brazenhead/manifest_info'
15
+ require 'brazenhead/server'
16
+ require 'net/http'
17
+ require 'childprocess'
18
+ require 'tempfile'