brazenhead 0.1

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.
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'