ruboto 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/COPYING +19 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +21 -0
  4. data/README.md +293 -0
  5. data/Rakefile +114 -0
  6. data/assets/Rakefile +386 -0
  7. data/assets/res/drawable-hdpi/icon.png +0 -0
  8. data/assets/res/drawable-ldpi/icon.png +0 -0
  9. data/assets/res/drawable-mdpi/icon.png +0 -0
  10. data/assets/res/layout/get_ruboto_core.xml +25 -0
  11. data/assets/samples/sample_activity.rb +21 -0
  12. data/assets/samples/sample_activity_test.rb +21 -0
  13. data/assets/samples/sample_broadcast_receiver.rb +6 -0
  14. data/assets/samples/sample_broadcast_receiver_test.rb +1 -0
  15. data/assets/samples/sample_service.rb +14 -0
  16. data/assets/samples/sample_service_test.rb +1 -0
  17. data/assets/src/InheritingActivity.java +195 -0
  18. data/assets/src/InheritingBroadcastReceiver.java +27 -0
  19. data/assets/src/InheritingClass.java +19 -0
  20. data/assets/src/InheritingService.java +9 -0
  21. data/assets/src/RubotoActivity.java +111 -0
  22. data/assets/src/RubotoBroadcastReceiver.java +51 -0
  23. data/assets/src/RubotoService.java +61 -0
  24. data/assets/src/org/ruboto/RubotoDialog.java +11 -0
  25. data/assets/src/org/ruboto/Script.java +545 -0
  26. data/assets/src/org/ruboto/test/ActivityTest.java +63 -0
  27. data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +124 -0
  28. data/assets/src/ruboto.rb +621 -0
  29. data/assets/test/assets/scripts/test_helper.rb +13 -0
  30. data/bin/ruboto +5 -0
  31. data/lib/java_class_gen/InheritingClass.java.erb +10 -0
  32. data/lib/java_class_gen/android_api.xml +1 -0
  33. data/lib/ruboto.rb +16 -0
  34. data/lib/ruboto/api.rb +21 -0
  35. data/lib/ruboto/commands/base.rb +392 -0
  36. data/lib/ruboto/core_ext/array.rb +6 -0
  37. data/lib/ruboto/core_ext/object.rb +10 -0
  38. data/lib/ruboto/util/asset_copier.rb +27 -0
  39. data/lib/ruboto/util/build.rb +201 -0
  40. data/lib/ruboto/util/code_formatting.rb +22 -0
  41. data/lib/ruboto/util/log_action.rb +20 -0
  42. data/lib/ruboto/util/main_fix.rb +13 -0
  43. data/lib/ruboto/util/objectspace.rb +8 -0
  44. data/lib/ruboto/util/scan_in_api.rb +40 -0
  45. data/lib/ruboto/util/update.rb +420 -0
  46. data/lib/ruboto/util/verify.rb +87 -0
  47. data/lib/ruboto/util/xml_element.rb +200 -0
  48. data/lib/ruboto/version.rb +3 -0
  49. data/test/activity/image_button_activity.rb +21 -0
  50. data/test/activity/image_button_activity_test.rb +21 -0
  51. data/test/activity/image_button_and_button_activity.rb +24 -0
  52. data/test/activity/image_button_and_button_activity_test.rb +27 -0
  53. data/test/activity/option_menu_activity.rb +21 -0
  54. data/test/activity/option_menu_activity_test.rb +20 -0
  55. data/test/activity/stack_activity.rb +21 -0
  56. data/test/activity/stack_activity_test.rb +23 -0
  57. data/test/app_test_methods.rb +41 -0
  58. data/test/minimal_app_test.rb +23 -0
  59. data/test/rake_test.rb +40 -0
  60. data/test/ruboto_gen_test.rb +32 -0
  61. data/test/ruboto_gen_with_psych_test.rb +16 -0
  62. data/test/ruboto_update_test.rb +5 -0
  63. data/test/ruboto_update_with_psych_test.rb +18 -0
  64. data/test/service_test.rb +49 -0
  65. data/test/test_helper.rb +177 -0
  66. data/test/update_test_methods.rb +33 -0
  67. metadata +157 -0
@@ -0,0 +1,23 @@
1
+ activity org.ruboto.test_app.StackActivity
2
+
3
+ setup do |activity|
4
+ start = Time.now
5
+ loop do
6
+ @text_view = activity.findViewById(42)
7
+ break if @text_view || (Time.now - start > 60)
8
+ sleep 1
9
+ end
10
+ assert @text_view
11
+ end
12
+
13
+ test('stack depth') do |activity|
14
+ os_offset = {13 => 1}[android.os.Build::VERSION::SDK_INT].to_i
15
+ jruby_offset = {
16
+ '1.5.6' => [-2, -5, -6, -8],
17
+ }[org.jruby.runtime.Constants::VERSION] || [0,0,0,0]
18
+ version_message ="ANDROID: #{android.os.Build::VERSION::SDK_INT}, JRuby: #{org.jruby.runtime.Constants::VERSION}"
19
+ assert_equal 44 + os_offset + jruby_offset[0], activity.find_view_by_id(42).text.to_i, version_message
20
+ assert_equal 68 + os_offset + jruby_offset[1], activity.find_view_by_id(43).text.to_i, version_message
21
+ assert_equal 77 + os_offset + jruby_offset[2], activity.find_view_by_id(44).text.to_i, version_message
22
+ assert_equal 96 + os_offset + jruby_offset[3], activity.find_view_by_id(45).text.to_i, version_message
23
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+
3
+ module AppTestMethods
4
+ include RubotoTest
5
+
6
+ def test_activity_tests
7
+ if not ON_JRUBY_JARS_1_5_6
8
+ assert_code 'YamlLoads', "with_large_stack{require 'yaml'}"
9
+ else
10
+ puts "Skipping YAML tests on jruby-jars-1.5.6"
11
+ end
12
+
13
+ assert_code 'ReadSourceFile', "File.read(__FILE__)"
14
+ assert_code 'DirListsFilesInApk', 'Dir["#{File.dirname(__FILE__)}/*"].each{|f| raise "File #{f.inspect} not found" unless File.exists?(f)}'
15
+
16
+ Dir[File.expand_path('activity/*_test.rb', File.dirname(__FILE__))].each do |test_src|
17
+ snake_name = test_src.chomp('_test.rb')
18
+ activity_name = File.basename(snake_name).split('_').map { |s| "#{s[0..0].upcase}#{s[1..-1]}" }.join
19
+ Dir.chdir APP_DIR do
20
+ system "#{RUBOTO_CMD} gen class Activity --name #{activity_name}"
21
+ FileUtils.cp "#{snake_name}.rb", "src/"
22
+ FileUtils.cp test_src, "test/assets/scripts/"
23
+ end
24
+ end
25
+ run_app_tests
26
+ end
27
+
28
+ private
29
+
30
+ def assert_code(activity_name, code)
31
+ snake_name = activity_name.scan(/[A-Z]+[a-z]+/).map { |s| s.downcase }.join('_')
32
+ filename = "src/#{snake_name}_activity.rb"
33
+ Dir.chdir APP_DIR do
34
+ system "#{RUBOTO_CMD} gen class Activity --name #{activity_name}Activity"
35
+ s = File.read(filename)
36
+ s.gsub!(/(require 'ruboto')/, "\\1\n#{code}")
37
+ File.open(filename, 'w') { |f| f << s }
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+ require 'bigdecimal'
3
+
4
+ class MinimalAppTest < Test::Unit::TestCase
5
+ def setup
6
+ generate_app :excluded_stdlibs => %w{ant cgi digest dl drb ffi irb net optparse racc rbconfig rdoc rexml rinda rss rubygems runit shell soap test uri webrick win32 wsdl xmlrpc xsd}
7
+ end
8
+
9
+ def teardown
10
+ cleanup_app
11
+ end
12
+
13
+ def test_minimal_apk_is_less_than_3_mb
14
+ apk_size = BigDecimal(File.size("#{APP_DIR}/bin/RubotoTestApp-debug.apk").to_s) / (1024 * 1024)
15
+ limit = 3.0
16
+ assert apk_size < limit, "APK was larger than #{'%.1f' % limit}MB: #{'%.1f' % apk_size.ceil(1)}MB"
17
+ end
18
+
19
+ def test_minimal_apk_succeeds_tests
20
+ run_app_tests
21
+ end
22
+
23
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+
3
+ class RakeTest < Test::Unit::TestCase
4
+ def setup
5
+ generate_app
6
+ end
7
+
8
+ def teardown
9
+ cleanup_app
10
+ end
11
+
12
+ if ANDROID_OS == 'android-7'
13
+ puts "Skipping sdcard test since files on sdcard are not removed on android-7 on app uninstall"
14
+ else
15
+ def test_that_update_scripts_task_copies_files_to_sdcard_and_are_read_by_activity
16
+ Dir.chdir APP_DIR do
17
+ activity_filename = "src/ruboto_test_app_activity.rb"
18
+ s = File.read(activity_filename)
19
+ s.gsub!(/What hath Matz wrought\?/, "This text was changed by script!")
20
+ File.open(activity_filename, 'w') { |f| f << s }
21
+
22
+ test_filename = "test/assets/scripts/ruboto_test_app_activity_test.rb"
23
+ s2 = File.read(test_filename)
24
+ s2.gsub!(/What hath Matz wrought\?/, "This text was changed by script!")
25
+ File.open(test_filename, 'w') { |f| f << s2 }
26
+
27
+ apk_timestamp = File.ctime("bin/#{APP_NAME}-debug.apk")
28
+ system 'rake test:quick'
29
+ assert_equal 0, $?
30
+
31
+ # FIXME(uwe): Uncomment this when we can build the test package without building the main package
32
+ # assert_equal apk_timestamp, File.ctime("bin/#{APP_NAME}-debug.apk"), 'APK should not have been rebuilt'
33
+ # FIXME end
34
+
35
+ assert `adb shell ls -d /sdcard/Android/data/#{PACKAGE}/files/scripts`.chomp =~ %r{^/sdcard/Android/data/#{PACKAGE}/files/scripts$}
36
+ end
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+ require 'test/app_test_methods'
3
+
4
+ class RubotoGenTest < Test::Unit::TestCase
5
+ include AppTestMethods
6
+
7
+ def setup
8
+ generate_app
9
+ end
10
+
11
+ def teardown
12
+ cleanup_app
13
+ end
14
+
15
+ def test_icons_are_updated
16
+ Dir.chdir APP_DIR do
17
+ assert_equal 4032, File.size('res/drawable-hdpi/icon.png')
18
+ end
19
+ end
20
+
21
+ def test_gen_class_activity_with_lowercase_should_fail
22
+ Dir.chdir APP_DIR do
23
+ system "#{RUBOTO_CMD} gen class activity --name VeryNewActivity"
24
+ assert_equal 1, $?.exitstatus
25
+ assert !File.exists?('src/org/ruboto/test_app/VeryNewActivity.java')
26
+ assert !File.exists?('src/very_new_activity.rb')
27
+ assert !File.exists?('test/assets/scripts/very_new_activity_test.rb')
28
+ assert File.read('AndroidManifest.xml') !~ /VeryNewActivity/
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path("ruboto_gen_test", File.dirname(__FILE__))
2
+
3
+ if not RubotoTest::ON_JRUBY_JARS_1_5_6
4
+ class RubotoGenWithPsychTest < RubotoGenTest
5
+ def setup
6
+ generate_app :with_psych => true
7
+ end
8
+
9
+ def test_psych_jar_exists
10
+ assert File.exists?("#{APP_DIR}/libs/psych.jar"), "Failed to generate psych jar"
11
+ end
12
+
13
+ end
14
+ else
15
+ puts "Skipping Psych tests on jruby-jars-1.5.6"
16
+ end
@@ -0,0 +1,5 @@
1
+ require File.expand_path("update_test_methods", File.dirname(__FILE__))
2
+
3
+ class RubotoUpdateTest < Test::Unit::TestCase
4
+ include UpdateTestMethods
5
+ end
@@ -0,0 +1,18 @@
1
+ require File.expand_path("update_test_methods", File.dirname(__FILE__))
2
+
3
+ if not RubotoTest::ON_JRUBY_JARS_1_5_6
4
+ class RubotoUpdateWithPsychTest < Test::Unit::TestCase
5
+ include UpdateTestMethods
6
+
7
+ def setup
8
+ super(true)
9
+ end
10
+
11
+ def test_psych_jar_exists
12
+ assert File.exists?("#{APP_DIR}/libs/psych.jar"), "Failed to generate psych jar"
13
+ end
14
+
15
+ end
16
+ else
17
+ puts "Skipping Psych tests on jruby-jars-1.5.6"
18
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+ require 'fileutils'
3
+
4
+ class ServiceTest < Test::Unit::TestCase
5
+ SRC_DIR ="#{APP_DIR}/src"
6
+
7
+ def setup
8
+ generate_app
9
+ end
10
+
11
+ def teardown
12
+ cleanup_app
13
+ end
14
+
15
+ def test_service_startup
16
+ Dir.chdir APP_DIR do
17
+ system "#{RUBOTO_CMD} gen class Service --name RubotoTestService"
18
+ service_filename = "#{SRC_DIR}/ruboto_test_service.rb"
19
+ assert File.exists? service_filename
20
+ File.open(service_filename, 'w'){|f| f << <<EOF}
21
+ require 'ruboto'
22
+
23
+ $service.handle_create do
24
+ Thread.start do
25
+ loop do
26
+ sleep 1
27
+ puts "\#{self.class} running..."
28
+ end
29
+ end
30
+ puts "\#{self.class} started."
31
+ android.app.Service::START_STICKY
32
+ end
33
+
34
+ $service.handle_start_command do
35
+ android.app.Service::START_STICKY
36
+ end
37
+ EOF
38
+
39
+ activity_filename = "#{SRC_DIR}/ruboto_test_app_activity.rb"
40
+ s = File.read(activity_filename)
41
+ s.gsub!(/^(end)$/, "
42
+ startService(android.content.Intent.new($activity.application_context, $package.RubotoTestService.java_class))
43
+ \\1\n")
44
+ File.open(activity_filename, 'w') { |f| f << s }
45
+ end
46
+ run_app_tests
47
+ end
48
+
49
+ end
@@ -0,0 +1,177 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'fileutils'
4
+ require 'yaml'
5
+
6
+ module RubotoTest
7
+ PROJECT_DIR = File.expand_path('..', File.dirname(__FILE__))
8
+ $LOAD_PATH << PROJECT_DIR
9
+
10
+ # FIXME(uwe): Simplify when we stop supporting rubygems < 1.8.0
11
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.8.0')
12
+ gem_spec = Gem::Specification.find_by_path 'jruby-jars'
13
+ else
14
+ gem_spec = Gem.searcher.find('jruby-jars')
15
+ end
16
+ # FIXME end
17
+
18
+ raise StandardError.new("Can't find Gem specification jruby-jars.") unless gem_spec
19
+ JRUBY_JARS_VERSION = gem_spec.version
20
+
21
+ # FIXME(uwe): Remove when we stop supporting JRuby 1.5.6
22
+ ON_JRUBY_JARS_1_5_6 = JRUBY_JARS_VERSION == Gem::Version.new('1.5.6')
23
+
24
+ PACKAGE = 'org.ruboto.test_app'
25
+ APP_NAME = 'RubotoTestApp'
26
+ TMP_DIR = File.join PROJECT_DIR, 'tmp'
27
+ APP_DIR = File.join TMP_DIR, APP_NAME
28
+ ANDROID_TARGET = ENV['ANDROID_TARGET'] || 'android-7'
29
+
30
+ VERSION_TO_API_LEVEL = {
31
+ '2.1' => 'android-7', '2.1-update1' => 'android-7', '2.2' => 'android-8',
32
+ '2.3' => 'android-9', '2.3.1' => 'android-9', '2.3.2' => 'android-9',
33
+ '2.3.3' => 'android-10', '2.3.4' => 'android-10',
34
+ '3.0' => 'android-11', '3.1' => 'android-12', '3.2' => 'android-13',
35
+ '4.0.1' => 'android-14', '4.0.3' => 'android-15',
36
+ }
37
+
38
+ def self.version_from_device
39
+ puts "Reading OS version from device/emulator"
40
+ system "adb wait-for-device"
41
+ start = Time.now
42
+ IO.popen('adb bugreport').each_line do |line|
43
+ if line =~ /sdk-eng (.*?) .*? .*? test-keys/
44
+ version = $1
45
+ api_level = VERSION_TO_API_LEVEL[version]
46
+ raise "Unknown version: #{version}" if api_level.nil?
47
+ puts "Getting version from device/emulator took #{(Time.now - start).to_i}s"
48
+ return api_level
49
+ end
50
+ if line =~ /\[ro\.build\.version\.sdk\]: \[(\d+)\]/
51
+ return $1
52
+ end
53
+ end
54
+ raise "Unable to read device/emulator apilevel"
55
+ end
56
+
57
+ ANDROID_OS = ENV['ANDROID_OS'] || version_from_device
58
+ RUBOTO_CMD = "ruby -rubygems -I #{PROJECT_DIR}/lib #{PROJECT_DIR}/bin/ruboto"
59
+
60
+ puts "ANDROID_OS: #{ANDROID_OS}"
61
+ end
62
+
63
+ class Test::Unit::TestCase
64
+ include RubotoTest
65
+ alias old_run run
66
+
67
+ def run(*args, &block)
68
+ mark_test_start("#{self.class.name}\##{method_name}")
69
+ old_run(*args, &block)
70
+ mark_test_end("#{self.class.name}\##{method_name}")
71
+ end
72
+
73
+ def mark_test_start(test_name)
74
+ @start_time = Time.now
75
+ log
76
+ log '=' * 80
77
+ log "Starting test #{test_name} at #{@start_time.strftime('%Y-%m-%d %H:%M:%S')}:"
78
+ log
79
+ end
80
+
81
+ def mark_test_end(test_name)
82
+ log
83
+ log "Ended test #{test_name}: #{passed? ? 'PASSED' : 'FAILED'} after #{(Time.now - @start_time).to_i}s"
84
+ log '=' * 80
85
+ log
86
+ end
87
+
88
+ def log(message = '')
89
+ puts message
90
+ system "adb shell log -t 'RUBOTO TEST' '#{message}'"
91
+ end
92
+
93
+ def generate_app(options = {})
94
+ with_psych = options.delete(:with_psych) || false
95
+ update = options.delete(:update) || false
96
+ excluded_stdlibs = options.delete(:excluded_stdlibs)
97
+ raise "Unknown options: #{options.inspect}" unless options.empty?
98
+ Dir.mkdir TMP_DIR unless File.exists? TMP_DIR
99
+
100
+ if with_psych || excluded_stdlibs
101
+ system 'rake platform:uninstall'
102
+ else
103
+ system 'rake platform:install'
104
+ end
105
+ if $? != 0
106
+ FileUtils.rm_rf 'tmp/RubotoCore'
107
+ fail 'Error (un)installing RubotoCore'
108
+ end
109
+
110
+ FileUtils.rm_rf APP_DIR if File.exists? APP_DIR
111
+ template_dir = "#{APP_DIR}_template_#{$$}#{'_with_psych' if with_psych}#{'_updated' if update}#{"_without_#{excluded_stdlibs.join('_')}" if excluded_stdlibs}"
112
+ if File.exists?(template_dir)
113
+ puts "Copying app from template #{template_dir}"
114
+ FileUtils.cp_r template_dir, APP_DIR, :preserve => true
115
+ else
116
+ if update
117
+ Dir.chdir TMP_DIR do
118
+ system "tar xzf #{PROJECT_DIR}/examples/RubotoTestApp_0.1.0_jruby_1.6.3.dev.tgz"
119
+ end
120
+ if ENV['ANDROID_HOME']
121
+ android_home = ENV['ANDROID_HOME']
122
+ else
123
+ android_home = File.dirname(File.dirname(`which adb`))
124
+ end
125
+ Dir.chdir APP_DIR do
126
+ File.open('local.properties', 'w') { |f| f.puts "sdk.dir=#{android_home}" }
127
+ File.open('test/local.properties', 'w') { |f| f.puts "sdk.dir=#{android_home}" }
128
+ FileUtils.touch "libs/psych.jar" if with_psych
129
+ exclude_stdlibs(excluded_stdlibs) if excluded_stdlibs
130
+ system "#{RUBOTO_CMD} update app"
131
+ assert_equal 0, $?, "update app failed with return code #$?"
132
+ end
133
+ else
134
+ puts "Generating app #{APP_DIR}"
135
+ system "#{RUBOTO_CMD} gen app --package #{PACKAGE} --path #{APP_DIR} --name #{APP_NAME} --target #{ANDROID_TARGET} #{'--with-psych' if with_psych}"
136
+ if $? != 0
137
+ FileUtils.rm_rf APP_DIR
138
+ raise "gen app failed with return code #$?"
139
+ end
140
+ if excluded_stdlibs
141
+ Dir.chdir APP_DIR do
142
+ exclude_stdlibs(excluded_stdlibs)
143
+ system "#{RUBOTO_CMD} update jruby --force"
144
+ raise "update jruby failed with return code #$?" if $? != 0
145
+ end
146
+ end
147
+ end
148
+ Dir.chdir APP_DIR do
149
+ system 'rake debug'
150
+ assert_equal 0, $?
151
+ end
152
+ puts "Storing app as template #{template_dir}"
153
+ FileUtils.cp_r APP_DIR, template_dir, :preserve => true
154
+ end
155
+ end
156
+
157
+ def cleanup_app
158
+ # FileUtils.rm_rf APP_DIR if File.exists? APP_DIR
159
+ end
160
+
161
+ def run_app_tests
162
+ if ['android-7', 'android-8'].include? ANDROID_OS
163
+ puts "Skipping instrumentation tests on #{ANDROID_OS} since they don't work."
164
+ else
165
+ Dir.chdir APP_DIR do
166
+ system 'rake test:quick'
167
+ assert_equal 0, $?, "tests failed with return code #$?"
168
+ end
169
+ end
170
+ end
171
+
172
+ def exclude_stdlibs(excluded_stdlibs)
173
+ puts "Adding ruboto.yml: #{excluded_stdlibs.join(' ')}"
174
+ File.open('ruboto.yml', 'w') { |f| f << YAML.dump({:excluded_stdlibs => excluded_stdlibs}) }
175
+ end
176
+
177
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path("test_helper", File.dirname(__FILE__))
2
+ require 'test/app_test_methods'
3
+
4
+ module UpdateTestMethods
5
+ include RubotoTest
6
+ include AppTestMethods
7
+
8
+ def setup(with_psych = false)
9
+ generate_app(:with_psych => with_psych, :update => true)
10
+ end
11
+
12
+ def teardown
13
+ cleanup_app
14
+ end
15
+
16
+ def test_properties_and_ant_file_has_no_duplicates
17
+ Dir.chdir APP_DIR do
18
+ # FIXME(uwe): Cleanup when we stop support Android SDK <= 13
19
+ prop_file = %w{test/ant.properties test/build.properties}.find{|f| File.exists?(f)}
20
+ # FIXME end
21
+
22
+ assert File.readlines(prop_file).grep(/\w/).uniq!.nil?, "Duplicate lines in #{prop_file}"
23
+ assert_equal 1, File.readlines('test/build.xml').grep(/<macrodef name="run-tests-helper">/).size, 'Duplicate macro in build.xml'
24
+ end
25
+ end
26
+
27
+ def test_icons_are_untouched
28
+ Dir.chdir APP_DIR do
29
+ assert_equal 4100, File.size('res/drawable-hdpi/icon.png')
30
+ end
31
+ end
32
+
33
+ end