/
test_helper.rb
309 lines (271 loc) · 10.6 KB
/
test_helper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
lib = File.dirname(File.dirname(__FILE__)) + '/lib'
$:.unshift(lib) unless $:.include?(lib)
require 'test/unit'
require 'rubygems'
require 'fileutils'
require 'yaml'
require 'ruboto/sdk_versions'
module RubotoTest
include Ruboto::SdkVersions
PROJECT_DIR = File.expand_path('..', File.dirname(__FILE__))
$LOAD_PATH << PROJECT_DIR
GEM_PATH = File.join PROJECT_DIR, 'tmp', 'gems'
FileUtils.mkdir_p GEM_PATH
ENV['GEM_HOME'] = GEM_PATH
ENV['GEM_PATH'] = GEM_PATH
ENV['PATH'] = "#{GEM_PATH}/bin:#{ENV['PATH']}"
Gem.paths = GEM_PATH
Gem.refresh
`gem query -i -n bundler`
system 'gem install bundler --no-ri --no-rdoc' unless $? == 0
`bundle check`
system 'bundle --system' unless $? == 0
lib_path = File.expand_path('lib', File.dirname(File.dirname(__FILE__)))
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
require 'ruboto'
require 'ruboto/version'
PACKAGE = 'org.ruboto.test_app'
APP_NAME = 'RubotoTestApp'
TMP_DIR = File.join PROJECT_DIR, 'tmp'
APP_DIR = File.join TMP_DIR, APP_NAME
ANDROID_TARGET = (ENV['ANDROID_TARGET'] && ENV['ANDROID_TARGET'].slice(/\d+/).to_i) || MINIMUM_SUPPORTED_SDK_LEVEL
VERSION_TO_API_LEVEL = {
'2.1' => 'android-7', '2.1-update1' => 'android-7', '2.2' => 'android-8',
'2.3' => 'android-9', '2.3.1' => 'android-9', '2.3.2' => 'android-9',
'2.3.3' => 'android-10', '2.3.4' => 'android-10',
'3.0' => 'android-11', '3.1' => 'android-12', '3.2' => 'android-13',
'4.0.1' => 'android-14', '4.0.3' => 'android-15', '4.0.4' => 'android-15',
'4.1' => 'android-16', '4.1.1' => 'android-16'
}
def self.version_from_device
puts "Reading OS version from device/emulator"
system "adb wait-for-device"
IO.popen('adb bugreport').each_line do |line|
if line =~ /sdk-eng (.*?) .*? .*? test-keys/
version = $1
api_level = VERSION_TO_API_LEVEL[version]
raise "Unknown version: #{version}" if api_level.nil?
return api_level
end
if line =~ /\[ro\.build\.version\.sdk\]: \[(\d+)\]/
return $1
end
end
raise "Unable to read device/emulator apilevel"
end
def self.install_jruby_jars_gem
jars_version_from_env = ENV['JRUBY_JARS_VERSION'] unless RUBOTO_PLATFORM == 'CURRENT'
version_requirement = "-#{jars_version_from_env}" if jars_version_from_env
`gem query -i -n jruby-jars#{version_requirement}`
system "gem install jruby-jars#{version_requirement} --no-ri --no-rdoc" unless $? == 0
raise "install of jruby-jars failed with return code #$?" unless $? == 0
if jars_version_from_env
exclusion_clause = %Q{-v "!=#{jars_version_from_env}"}
`gem query -i -n jruby-jars #{exclusion_clause}`
if $? == 0
system %Q{gem uninstall jruby-jars --all #{exclusion_clause}}
raise "Uninstall of jruby-jars failed with return code #$?" unless $? == 0
end
end
Gem.refresh
end
def install_jruby_jars_gem
RubotoTest::install_jruby_jars_gem
end
def uninstall_jruby_jars_gem
`gem query --no-installed -n jruby-jars`
system 'gem uninstall jruby-jars --all' if $? != 0
assert_equal 0, $?, "uninstall of jruby-jars failed with return code #$?"
end
def install_ruboto_gem(version)
version_requirement = "-v #{version}"
`gem query -i -n ^ruboto$ #{version_requirement}`
system "gem install ruboto #{version_requirement} --no-ri --no-rdoc" unless $? == 0
raise "install of ruboto #{version} failed with return code #$?" unless $? == 0
end
puts RUBY_DESCRIPTION
ANDROID_OS = (ENV['ANDROID_OS'] || version_from_device).slice(/\d+/).to_i
puts "ANDROID_OS: #{ANDROID_OS}"
puts "ANDROID_TARGET: #{ANDROID_TARGET}"
RUBOTO_CMD = "ruby -rubygems -I #{PROJECT_DIR}/lib #{PROJECT_DIR}/bin/ruboto"
puts "ANDROID_HOME: #{ANDROID_HOME}"
puts "ANDROID_SDK_TOOLS_REVISION: #{ANDROID_TOOLS_REVISION}"
RUBOTO_PLATFORM = ENV['RUBOTO_PLATFORM'] || 'CURRENT'
puts "RUBOTO_PLATFORM: #{RUBOTO_PLATFORM}"
install_jruby_jars_gem
if RUBOTO_PLATFORM == 'CURRENT'
JRUBY_JARS_VERSION = Gem::Version.new('1.7.0.dev')
else
# FIXME(uwe): Simplify when we stop supporting rubygems < 1.8.0
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.8.0')
gem_spec = Gem::Specification.find_by_path 'jruby-jars'
else
gem_spec = Gem.searcher.find('jruby-jars')
end
# EMXIF
raise StandardError.new("Can't find Gem specification jruby-jars.") unless gem_spec
JRUBY_JARS_VERSION = gem_spec.version
end
puts "JRUBY_JARS_VERSION: #{JRUBY_JARS_VERSION}"
end
class Test::Unit::TestCase
include RubotoTest
extend RubotoTest
alias old_run run
def run(*args, &block)
mark_test_start("#{self.class.name}\##{respond_to?(:method_name) ? method_name : __name__}")
old_run(*args, &block)
mark_test_end("#{self.class.name}\##{respond_to?(:method_name) ? method_name : __name__}")
end
def mark_test_start(test_name)
@start_time = Time.now
log
log '=' * 80
log "Starting test #{test_name} at #{@start_time.strftime('%Y-%m-%d %H:%M:%S')}:"
log
end
def mark_test_end(test_name)
log
duration = (Time.now - @start_time).to_i
log "Ended test #{test_name}: #{passed? ? 'PASSED' : 'FAILED'} after #{duration / 60}:#{'%02d' % (duration % 60)}"
log '=' * 80
log
end
def log(message = '')
puts message
`adb shell log -t 'RUBOTO TEST' '#{message}'`
end
def generate_app(options = {})
example = options.delete(:example) || false
update = options.delete(:update) || false
excluded_stdlibs = options.delete(:excluded_stdlibs)
standalone = options.delete(:standalone) || !!excluded_stdlibs || ENV['RUBOTO_PLATFORM'] == 'STANDALONE'
bundle = options.delete(:bundle)
raise "Unknown options: #{options.inspect}" unless options.empty?
Dir.mkdir TMP_DIR unless File.exists? TMP_DIR
FileUtils.rm_rf APP_DIR if File.exists? APP_DIR
template_dir = "#{APP_DIR}_template_#{$$}"
template_dir << "_example_#{example}" if example
template_dir << '_updated' if update
template_dir << '_standalone' if standalone
template_dir << "_without_#{excluded_stdlibs.map { |ed| ed.gsub(/[.\/]/, '_') }.join('_')}" if excluded_stdlibs
if File.exists?(template_dir)
puts "Copying app from template #{template_dir}"
FileUtils.cp_r template_dir, APP_DIR, :preserve => true
else
install_jruby_jars_gem
if example
Dir.chdir TMP_DIR do
system "tar xzf #{PROJECT_DIR}/examples/#{APP_NAME}_#{example}.tgz"
end
Dir.chdir APP_DIR do
File.open('local.properties', 'w') { |f| f.puts "sdk.dir=#{ANDROID_HOME}" }
File.open('test/local.properties', 'w') { |f| f.puts "sdk.dir=#{ANDROID_HOME}" }
if standalone
exclude_stdlibs(excluded_stdlibs) if excluded_stdlibs
FileUtils.touch 'libs/jruby-core-x.x.x.jar'
FileUtils.touch 'libs/jruby-stdlib-x.x.x.jar'
else
FileUtils.rm(Dir['libs/{jruby-*.jar,dx.jar}'])
end
update_app if update
end
else
uninstall_jruby_jars_gem unless standalone
puts "Generating app #{APP_DIR}"
system "#{RUBOTO_CMD} gen app --package #{PACKAGE} --path #{APP_DIR} --name #{APP_NAME} --target android-#{ANDROID_TARGET}"
if $? != 0
FileUtils.rm_rf APP_DIR
raise "gen app failed with return code #$?"
end
Dir.chdir APP_DIR do
write_gemfile(bundle) if bundle
if standalone
exclude_stdlibs(excluded_stdlibs) if excluded_stdlibs
system "#{RUBOTO_CMD} gen jruby"
raise "update jruby failed with return code #$?" if $? != 0
end
end
end
# FIXME(uwe): Installation with dx.jar fails on Android < 4.0.3 due to complex interface structure
# Fixme(uwe): Remove when solved
#if standalone && ANDROID_OS < 15
# Dir.chdir APP_DIR do
# puts "Removing dx.jar for android-#{ANDROID_OS}"
# FileUtils.rm(Dir['libs/dx.jar'])
# end
#end
# EMXIF
unless example && !update
Dir.chdir APP_DIR do
system 'rake debug'
assert_equal 0, $?
end
end
puts "Storing app as template #{template_dir}"
FileUtils.cp_r APP_DIR, template_dir, :preserve => true
end
end
def update_app
system "#{RUBOTO_CMD} update app"
assert_equal 0, $?, "update app failed with return code #$?"
end
def cleanup_app
# FileUtils.rm_rf APP_DIR if File.exists? APP_DIR
end
def run_app_tests
if [7, 8].include? ANDROID_OS
puts "Skipping instrumentation tests on #{ANDROID_OS} since they don't work."
return
end
check_platform_installation
Dir.chdir APP_DIR do
# FIXME(uwe): Simplify when we stop supporting JRuby < 1.7.0 which causes the ArrayIndexOutOfBoundsException
# FIXME(uwe): Simplify if we find a cause for the system crashes.
# system 'rake test:quick' # This line should replace all those below.
retries = 0
loop do
output = `rake test:quick`
puts output
break if $? == 0
retries += 1
# FIXME(uwe): The cause of the system crash is unnown. We should investigate.
if output =~ /INSTRUMENTATION_ABORTED: System has crashed./
puts "System crash detected."
elsif (RUBOTO_PLATFORM == 'CURRENT' || JRUBY_JARS_VERSION < Gem::Version.new('1.7.0')) &&
output =~ /INSTRUMENTATION_RESULT: longMsg=java.lang.ArrayIndexOutOfBoundsException/
puts "Known ArrayIndexOutOfBoundsException failure detected. Retrying (#{retries})."
else
break
end
break if retries >= 3
puts "Retrying (#{retries})."
end
# EMXIF
assert_equal 0, $?, "tests failed with return code #$?"
end
end
def check_platform_installation
if RUBOTO_PLATFORM == 'STANDALONE'
system 'rake platform:uninstall'
elsif RUBOTO_PLATFORM == 'CURRENT'
system "rake platform:current platform:install"
elsif RUBOTO_PLATFORM == 'FROM_GEM'
system "rake platform:debug platform:install"
else
fail "Unknown Ruboto platform: #{RUBOTO_PLATFORM.inspect}"
end
if $? != 0
FileUtils.rm_rf 'tmp/RubotoCore'
fail 'Error (un)installing RubotoCore'
end
end
def exclude_stdlibs(excluded_stdlibs)
puts "Adding ruboto.yml: #{excluded_stdlibs.join(' ')}"
File.open('ruboto.yml', 'w') { |f| f << YAML.dump({:excluded_stdlibs => excluded_stdlibs}) }
end
def write_gemfile(bundle)
puts "Adding Gemfile.apk: #{[*bundle].join(' ')}"
File.open('Gemfile.apk', 'w') { |f| f << "source :rubygems\n\ngem 'sqldroid'\n" }
end
end