automate-standard-baseline 0.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.
- data/bin/abs-stop +101 -0
- data/bin/automate-standard-baseline +283 -0
- data/lib/helpers.rb +226 -0
- data/lib/manifest_extractor.jar +0 -0
- data/lib/operations.rb +238 -0
- metadata +62 -0
data/bin/abs-stop
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
5
|
+
require 'helpers'
|
6
|
+
require 'logger'
|
7
|
+
require 'yaml'
|
8
|
+
require 'sys/proctable'
|
9
|
+
require 'optparse'
|
10
|
+
|
11
|
+
include Sys
|
12
|
+
|
13
|
+
END {
|
14
|
+
|
15
|
+
options = opt_parse(ARGV)
|
16
|
+
|
17
|
+
pid_file = '.pid'
|
18
|
+
|
19
|
+
unless File.exists?(pid_file)
|
20
|
+
log("pid file doesn't exist!")
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
pid_content = YAML.load_file(pid_file)
|
25
|
+
options.each do |k, v|
|
26
|
+
str_key = k.to_s
|
27
|
+
|
28
|
+
str_key = 'main' if str_key == 'all'
|
29
|
+
str_key = v if str_key == 'serial'
|
30
|
+
|
31
|
+
log "Stopping '#{str_key}' processes"
|
32
|
+
|
33
|
+
pids = pid_content.delete(str_key)
|
34
|
+
do_stop(pids)
|
35
|
+
end
|
36
|
+
|
37
|
+
if not pid_content.empty? and options[:all].nil?
|
38
|
+
IO.write(pid_file, pid_content.to_yaml)
|
39
|
+
else
|
40
|
+
File.delete(pid_file)
|
41
|
+
end
|
42
|
+
|
43
|
+
} # end of END
|
44
|
+
|
45
|
+
def opt_parse(args)
|
46
|
+
|
47
|
+
options = {}
|
48
|
+
|
49
|
+
opts = OptionParser.new do |opt|
|
50
|
+
opt.banner = "Usage: stop [options]"
|
51
|
+
opt.separator ""
|
52
|
+
|
53
|
+
opt.on("-a", "--all", "Stop all processes [default]") do |v|
|
54
|
+
options[:all] = v
|
55
|
+
end
|
56
|
+
|
57
|
+
opt.on("-l", "--logcat", "Stop logcat processes") do |v|
|
58
|
+
options[:logcat] = v
|
59
|
+
end
|
60
|
+
|
61
|
+
opt.on("-t", "--tcpdump", "Stop tcpdump processes") do |v|
|
62
|
+
options[:tcpdump] = v
|
63
|
+
end
|
64
|
+
|
65
|
+
opt.on("-s", "--serial [SERIAL_NUMBER]", "Stop all processes related the specified device serial number") do |v|
|
66
|
+
options[:serial] = v
|
67
|
+
end
|
68
|
+
|
69
|
+
opt.separator ""
|
70
|
+
opt.on_tail("-h", "--help", "Show this message") do
|
71
|
+
puts opt
|
72
|
+
exit
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
opts.parse!(args)
|
77
|
+
# stop all processes by default
|
78
|
+
options[:all] = true if options.length == 0
|
79
|
+
|
80
|
+
options
|
81
|
+
end
|
82
|
+
|
83
|
+
def do_stop(pids)
|
84
|
+
return if pids.nil?
|
85
|
+
|
86
|
+
log "Stopping #{pids.to_s}"
|
87
|
+
to_kill = pids
|
88
|
+
|
89
|
+
# find the sub-processes of these pids
|
90
|
+
ProcTable.ps do |proc|
|
91
|
+
to_kill << proc.pid if to_kill.include?(proc.ppid)
|
92
|
+
end
|
93
|
+
log "Processes will be killed (including sub-processes): #{to_kill}"
|
94
|
+
|
95
|
+
to_kill.each do |pid|
|
96
|
+
Process.kill("KILL", pid) rescue nil # in case of the process doesn't exist.
|
97
|
+
end
|
98
|
+
log "Done!"
|
99
|
+
end
|
100
|
+
|
101
|
+
|
@@ -0,0 +1,283 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
|
4
|
+
require 'operations'
|
5
|
+
require 'helpers'
|
6
|
+
require 'logger'
|
7
|
+
require 'optparse'
|
8
|
+
require 'ostruct'
|
9
|
+
require "securerandom"
|
10
|
+
require 'sys/proctable'
|
11
|
+
|
12
|
+
include Sys
|
13
|
+
|
14
|
+
include Seven::ASB::Operations
|
15
|
+
|
16
|
+
|
17
|
+
$pid_file = '.pid'
|
18
|
+
|
19
|
+
# For now we hard code the timeout value in case of the
|
20
|
+
# program run more than 24 hours
|
21
|
+
$time_out = 24 * 60 * 60
|
22
|
+
|
23
|
+
##-------------------------------------------------------------
|
24
|
+
## define methods
|
25
|
+
##-----------------
|
26
|
+
def opt_parse(args)
|
27
|
+
# The options specified on the command line will be collected in *options*.
|
28
|
+
# We set default values here.
|
29
|
+
options = {}
|
30
|
+
|
31
|
+
mandatory = [:oc_path,:reinstall,:duration]
|
32
|
+
mutual_exclusion = [:oc_path,:reinstall,:duration]
|
33
|
+
|
34
|
+
# set default values
|
35
|
+
options[:enable_logcat] = true
|
36
|
+
options[:enable_tcpdump] = true
|
37
|
+
|
38
|
+
options[:enable_monitor] = false
|
39
|
+
options[:verbose] = true
|
40
|
+
|
41
|
+
opts = OptionParser.new do |opts|
|
42
|
+
opts.banner = "Usage: run [options]"
|
43
|
+
|
44
|
+
opts.separator ""
|
45
|
+
opts.separator "Specific options:"
|
46
|
+
|
47
|
+
# Mandatory argument.
|
48
|
+
opts.on("-l", "--[no-]logcat", "record logcat logs") do |v|
|
49
|
+
options[:enable_logcat] = v
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on("-t", "--[no-]tcpdump", "record tcpdump or not") do |v|
|
53
|
+
options[:enable_tcpdump] = v
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
opts.on("-o", "--oc_path oc_path",
|
58
|
+
"specify oc client path(local file path or http url)") do |oc_path|
|
59
|
+
options[:oc_path] = oc_path
|
60
|
+
options[:reinstall] = true if options[:reinstall].nil? # only when user doesn't use -n
|
61
|
+
# if user uses -n and -o together, only -n will take effect.
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on("-n", "--no-reinstall", "Whether to re-install OC client or not") do
|
65
|
+
options[:reinstall] = false
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
opts.on("-d [TIME_TO_TEST]", "test duration time") do |v|
|
70
|
+
v = v.strip
|
71
|
+
seconds = 0
|
72
|
+
|
73
|
+
case v
|
74
|
+
when /^(\d+)\s*(hours|hour|hrs|h|hr)?$/
|
75
|
+
seconds = $1.to_i * 60 * 60
|
76
|
+
when /^(\d+)\s*(minute|minutes|m|ms)?$/
|
77
|
+
seconds = $1.to_i * 60
|
78
|
+
when /^(\d+)\s*(seconds|second|s)?$/
|
79
|
+
seconds = $1.to_i
|
80
|
+
else
|
81
|
+
raise %Q{ The time value "#{v}" is not acceptable. }
|
82
|
+
end
|
83
|
+
options[:duration] = seconds
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
opts.parse!(args)
|
89
|
+
missing = mandatory.select{ |param| options[param].nil? }
|
90
|
+
if missing.select{|i| mutual_exclusion.include?(i)} == mutual_exclusion
|
91
|
+
puts "One of #{mutual_exclusion.join(', ')} must be specified!"
|
92
|
+
puts opts
|
93
|
+
exit
|
94
|
+
end
|
95
|
+
|
96
|
+
missing.delete_if{|i| mutual_exclusion.include?(i)}
|
97
|
+
unless missing.empty?
|
98
|
+
puts "Missing options: #{missing.join(', ')}"
|
99
|
+
puts opts
|
100
|
+
exit
|
101
|
+
end
|
102
|
+
|
103
|
+
options
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
def trap_signals
|
108
|
+
Signal.trap("INT") do
|
109
|
+
logger.info "Terminating..."
|
110
|
+
to_kill = [Process.pid]
|
111
|
+
ProcTable.ps do |proc|
|
112
|
+
to_kill << proc.pid if to_kill.include?(proc.ppid)
|
113
|
+
end
|
114
|
+
logger.info "Processes will be killed (including sub-processes): #{to_kill}"
|
115
|
+
to_kill.each do |pid|
|
116
|
+
Process.kill("KILL", pid) rescue nil # in case of the process doesn't exist.
|
117
|
+
end
|
118
|
+
# process logcat
|
119
|
+
# process execution status (if there is)
|
120
|
+
delete_pid_file($pid_file)
|
121
|
+
exit 1
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def check_if_old_process_killed(pid_f)
|
126
|
+
if File.exists?(pid_f)
|
127
|
+
tmp_pid = YAML.load_file(pid_f)
|
128
|
+
tmp_pid.each do |k, v|
|
129
|
+
if v and not v.empty?
|
130
|
+
logger.warn "Have you killed the old process properly?"
|
131
|
+
exit -1
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
File.delete(pid_f)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def delete_pid_file(pid_f)
|
140
|
+
if File.exists?(pid_f)
|
141
|
+
File.delete(pid_f)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def archive_logs(devices)
|
146
|
+
# if there is any existing tcpdump files on devices' sdcard, pull them
|
147
|
+
# out and archive them. In case of the program crashed or ubs exit
|
148
|
+
# abnormally, we'd better do this check.
|
149
|
+
# All /sdcard/*.pcap will be pulled to logs and then removed.
|
150
|
+
|
151
|
+
logger.info "Check existing tcpdump...."
|
152
|
+
pull_out_tcpdump(devices)
|
153
|
+
logger.info "tcpdump checking done."
|
154
|
+
|
155
|
+
if Dir.exists?('logs')
|
156
|
+
# Archive the logs
|
157
|
+
archive_name = "#{Time.now.strftime('%Y%m_%d%H%M%S')}.tar.gz"
|
158
|
+
logger.info "archiving existing logs to #{archive_name}"
|
159
|
+
logger.info `tar --gzip --remove-files -cvf #{archive_name} logs`
|
160
|
+
|
161
|
+
# Move the log to archived dir
|
162
|
+
archived = 'archived'
|
163
|
+
Dir.mkdir(archived) unless Dir.exists?(archived)
|
164
|
+
`mv #{archive_name} #{archived}/`
|
165
|
+
end
|
166
|
+
|
167
|
+
Dir.mkdir('logs') unless Dir.exists?('logs')
|
168
|
+
end
|
169
|
+
|
170
|
+
## operation steps ---start test ...
|
171
|
+
|
172
|
+
trap_signals()
|
173
|
+
|
174
|
+
option = opt_parse(ARGV)
|
175
|
+
|
176
|
+
logger.info "#{option}"
|
177
|
+
|
178
|
+
check_if_old_process_killed($pid_file)
|
179
|
+
|
180
|
+
devices = get_available_devices
|
181
|
+
raise "No device connected!" if devices.length == 0
|
182
|
+
|
183
|
+
|
184
|
+
archive_logs(devices)
|
185
|
+
|
186
|
+
if not option[:reinstall]
|
187
|
+
# pull OC out from one of the devices.
|
188
|
+
# If one of them doesn't have OC installed, just exit!
|
189
|
+
logger.info "Pull OC out from device."
|
190
|
+
|
191
|
+
apk_path = nil
|
192
|
+
devices.each do |serial|
|
193
|
+
begin
|
194
|
+
apk_path = pull_out_apk(serial, 'com.seven.asimov', 'tmp/oc.apk') # com.igatr10.to
|
195
|
+
rescue
|
196
|
+
raise %Q{Device "#{serial}" doesn't install OC, You cannot run this program without OC installed!}
|
197
|
+
end
|
198
|
+
end
|
199
|
+
option[:oc_path] = apk_path
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
all_pids = {}
|
204
|
+
logcat_pids = []
|
205
|
+
tcpdump_pids = []
|
206
|
+
|
207
|
+
for i in 0...devices.length
|
208
|
+
pids = []
|
209
|
+
|
210
|
+
# install oc at first
|
211
|
+
logger.info "start to install oc for device '#{devices[i]}'"
|
212
|
+
|
213
|
+
#set environment
|
214
|
+
set_env(devices[i],i)
|
215
|
+
|
216
|
+
|
217
|
+
install_or_dump_oc_client(option[:oc_path],option[:reinstall])
|
218
|
+
reset_data()
|
219
|
+
|
220
|
+
if option[:enable_logcat]
|
221
|
+
logcat_pid = spawn("#{adb_cmd} -s #{devices[i]} logcat -v time", [:out, :err]=>["logs/logcat-device-#{devices[i]}.log", 'w'])
|
222
|
+
logcat_pids << logcat_pid
|
223
|
+
pids << logcat_pid
|
224
|
+
end
|
225
|
+
|
226
|
+
if option[:enable_tcpdump]
|
227
|
+
tcpdump_pid = spawn("#{adb_cmd} -s #{devices[i]} shell su -c tcpdump -s 0 -i any -w /sdcard/#{Time.now.strftime('%Y%m%d%H%M%S')}.pcap",
|
228
|
+
[:out, :err]=>["logs/tcpdump-device-#{devices[i]}.log", 'w'])
|
229
|
+
tcpdump_pids << tcpdump_pid
|
230
|
+
pids << tcpdump_pid
|
231
|
+
end
|
232
|
+
|
233
|
+
all_pids.store(devices[i], pids)
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
# persist the pids
|
240
|
+
all_pids.store("main", [Process.pid])
|
241
|
+
#all_pids.store("ubs", ubs_pids)
|
242
|
+
if option[:enable_logcat]
|
243
|
+
all_pids.store("logcat", logcat_pids)
|
244
|
+
end
|
245
|
+
|
246
|
+
if option[:enable_tcpdump]
|
247
|
+
all_pids.store('tcpdump', tcpdump_pids)
|
248
|
+
end
|
249
|
+
logger.info "subprocesses' pids: #{all_pids}"
|
250
|
+
IO.write('.pid', all_pids.to_yaml)
|
251
|
+
|
252
|
+
# Wait for all sub-processes to finish
|
253
|
+
du=option[:duration]
|
254
|
+
|
255
|
+
|
256
|
+
if nil==du||du==0
|
257
|
+
logger.info "use default time out: 24 hours"
|
258
|
+
else
|
259
|
+
$time_out= Integer(du)
|
260
|
+
end
|
261
|
+
|
262
|
+
begin Timeout.timeout($time_out) do
|
263
|
+
Process.waitall
|
264
|
+
end
|
265
|
+
rescue Timeout::Error
|
266
|
+
logger.info 'Test duartion has over, pull tcpdump.'
|
267
|
+
|
268
|
+
pull_out_tcpdump(devices)
|
269
|
+
delete_pid_file($pid_file)
|
270
|
+
|
271
|
+
logger.info "Kill all sub_processes"
|
272
|
+
# find the sub-processes of these pids
|
273
|
+
to_kill = [Process.pid]
|
274
|
+
ProcTable.ps do |proc|
|
275
|
+
to_kill << proc.pid if to_kill.include?(proc.ppid)
|
276
|
+
end
|
277
|
+
logger.info "Processes will be killed (including sub-processes): #{to_kill}"
|
278
|
+
to_kill.each do |pid|
|
279
|
+
Process.kill("KILL", pid) rescue nil # in case of the process doesn't exist.
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
|
data/lib/helpers.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require "securerandom"
|
3
|
+
require 'rexml/document'
|
4
|
+
require 'rexml/xpath'
|
5
|
+
require 'tempfile'
|
6
|
+
require "uri"
|
7
|
+
require "net/http"
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
include REXML
|
11
|
+
|
12
|
+
def default_timeout_val
|
13
|
+
300
|
14
|
+
end
|
15
|
+
|
16
|
+
def logger
|
17
|
+
@logger ||= Logger.new(STDOUT)
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_env(device_id,id)
|
21
|
+
ENV["ADB_DEVICE_ARG"]="#{device_id}"
|
22
|
+
ENV["ADB_DEVICE_INDEX"]="#{id}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def log(message)
|
26
|
+
logger.info message
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def pull_out_apk(device_serial, package_name, to_path = nil)
|
31
|
+
out_path = File.expand_path(to_path) if to_path
|
32
|
+
out_path ||= File.expand_path("#{package_name}.apk")
|
33
|
+
|
34
|
+
if File.exists?(out_path)
|
35
|
+
new_name = "#{out_path}.#{Time.now.strftime('%Y%m%d%H%M%S%s%S')}"
|
36
|
+
puts %Q{rename #{out_path} to #{new_name} since it already exists.}
|
37
|
+
File.rename(out_path, new_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
for num in ['2', '1', '3']
|
41
|
+
begin
|
42
|
+
cmd = %Q{ #{adb_cmd(device_serial)} pull /data/app/#{package_name}-#{num}.apk #{out_path} }
|
43
|
+
exec_command(cmd, 120)
|
44
|
+
rescue
|
45
|
+
end
|
46
|
+
|
47
|
+
if File.exists?(out_path)
|
48
|
+
break
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
raise %Q{Failed to pull out the package "#{}"} unless File.exists?(out_path)
|
53
|
+
out_path
|
54
|
+
end
|
55
|
+
|
56
|
+
def mkdirs(path)
|
57
|
+
if(!File.directory?(path))
|
58
|
+
if(!mkdirs(File.dirname(path)))
|
59
|
+
return false;
|
60
|
+
end
|
61
|
+
Dir.mkdir(path)
|
62
|
+
end
|
63
|
+
|
64
|
+
return true
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def get_available_devices
|
69
|
+
# grep the connected devices
|
70
|
+
cmd = "#{adb_cmd} devices | ruby -nae 'puts $F[0] if $F[1] =~ /device/'"
|
71
|
+
devices = exec_command(cmd, 10).output
|
72
|
+
devices = devices.split /\s+/
|
73
|
+
|
74
|
+
if devices.length > 0
|
75
|
+
logger.info {
|
76
|
+
msg = "\nAvailable devices\n"
|
77
|
+
for i in 0...devices.length
|
78
|
+
msg += "#{devices[i]}\n"
|
79
|
+
end
|
80
|
+
|
81
|
+
msg
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
devices
|
86
|
+
end
|
87
|
+
|
88
|
+
# pull out all /sdcard/*.pcap to logs/
|
89
|
+
def pull_out_tcpdump(devices)
|
90
|
+
dest_dir = "/sdcard/"
|
91
|
+
devices.each do |d|
|
92
|
+
cmd = "#{adb_cmd(d)} shell su -c ls #{dest_dir} | grep pcap"
|
93
|
+
tcpdump_files = exec_command(cmd, 10).output.strip
|
94
|
+
tcpdump_files.each_line do |f|
|
95
|
+
Dir.mkdir('logs') unless Dir.exists?('logs')
|
96
|
+
|
97
|
+
cmd = "#{adb_cmd(d)} pull #{File.join(dest_dir, f)} logs/#{d}_#{f}"
|
98
|
+
logger.info(cmd)
|
99
|
+
exec_command(cmd, 120)
|
100
|
+
cmd = "#{adb_cmd(d)} shell su -c rm #{File.join(dest_dir, f)}"
|
101
|
+
logger.info(cmd)
|
102
|
+
exec_command(cmd, 10)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def download_file(url, saved_path = nil)
|
109
|
+
uri = URI.parse(url)
|
110
|
+
path = (!uri.query or uri.query.blank?) ? uri.path : uri.path+"?"+uri.query
|
111
|
+
unless saved_path
|
112
|
+
saved_path = "oc_apks/#{uri.path[uri.path.rindex("/") + 1, uri.path.length]}"
|
113
|
+
end
|
114
|
+
saved_path = File.expand_path(saved_path)
|
115
|
+
puts "Download file by url #{url}; saved_path: #{saved_path}"
|
116
|
+
f = File.new(saved_path, "wb")
|
117
|
+
begin
|
118
|
+
print "Downloading\n"
|
119
|
+
i = 0
|
120
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
121
|
+
http.request_get(path) do |resp|
|
122
|
+
resp.read_body do |segment|
|
123
|
+
f.write(segment)
|
124
|
+
i = i + 1
|
125
|
+
if (i % 80 == 0)
|
126
|
+
print "\n"
|
127
|
+
else
|
128
|
+
print "."
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
ensure
|
134
|
+
f.close()
|
135
|
+
end
|
136
|
+
print "\n"
|
137
|
+
return saved_path
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
def package_name(app)
|
142
|
+
require 'rexml/document'
|
143
|
+
require 'rexml/xpath'
|
144
|
+
|
145
|
+
manifest = Document.new(manifest(app))
|
146
|
+
manifest.root.attributes['package']
|
147
|
+
end
|
148
|
+
|
149
|
+
def manifest(app)
|
150
|
+
cmd = %Q{java -jar "#{File.dirname(__FILE__)}/manifest_extractor.jar" "#{app}"}
|
151
|
+
puts "exec #{cmd}"
|
152
|
+
exec_command(cmd, default_timeout_val).output
|
153
|
+
end
|
154
|
+
|
155
|
+
class ExecResult
|
156
|
+
attr_accessor :output, :is_success, :status_code
|
157
|
+
|
158
|
+
def initialize(output, is_success, status_code)
|
159
|
+
@output = output
|
160
|
+
@is_success = is_success
|
161
|
+
@status_code = status_code
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
## Add timeout mechanism here to avoid external command executing the whole
|
166
|
+
## program.
|
167
|
+
def exec_command(cmd, time_out = nil)
|
168
|
+
rd, wr = IO.pipe
|
169
|
+
pid = spawn(cmd, [:out, :err] => wr)
|
170
|
+
|
171
|
+
begin
|
172
|
+
unless time_out
|
173
|
+
Process.waitpid(pid)
|
174
|
+
status_code = $?.exitstatus
|
175
|
+
else
|
176
|
+
begin
|
177
|
+
Timeout.timeout(time_out) do
|
178
|
+
Process.waitpid(pid)
|
179
|
+
status_code = $?.exitstatus
|
180
|
+
end
|
181
|
+
rescue Timeout::Error => e
|
182
|
+
puts 'Timeout::Error'
|
183
|
+
puts "kill"
|
184
|
+
Process.kill("KILL", pid) rescue nil
|
185
|
+
status_code = -99999
|
186
|
+
|
187
|
+
backtrace = e.backtrace || []
|
188
|
+
new_error = Timeout::Error.new("Failed to execute command #{cmd} due to it spent too much time than expected time: #{time_out}s")
|
189
|
+
new_error.set_backtrace(backtrace + [e.message])
|
190
|
+
|
191
|
+
raise new_error
|
192
|
+
end
|
193
|
+
end
|
194
|
+
ensure
|
195
|
+
wr.close
|
196
|
+
output = rd.read
|
197
|
+
rd.close
|
198
|
+
end
|
199
|
+
|
200
|
+
ExecResult.new(output, status_code == 0, status_code)
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
def is_windows?
|
206
|
+
require 'rbconfig'
|
207
|
+
(RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
208
|
+
end
|
209
|
+
|
210
|
+
def adb_cmd(device_serial = nil)
|
211
|
+
if is_windows?
|
212
|
+
%Q("#{ENV["ANDROID_HOME"]}\\platform-tools\\adb.exe" #{_device_args(device_serial)})
|
213
|
+
else
|
214
|
+
%Q("#{ENV["ANDROID_HOME"]}/platform-tools/adb" #{_device_args(device_serial)})
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def _device_args(device_serial = nil)
|
219
|
+
if ENV["ADB_DEVICE_ARG"]
|
220
|
+
"-s #{ENV["ADB_DEVICE_ARG"]}"
|
221
|
+
elsif device_serial
|
222
|
+
" -s #{device_serial} "
|
223
|
+
else
|
224
|
+
""
|
225
|
+
end
|
226
|
+
end
|
Binary file
|
data/lib/operations.rb
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'timeout'
|
5
|
+
require 'retriable'
|
6
|
+
require 'yaml'
|
7
|
+
require 'uri'
|
8
|
+
require File.join(File.dirname(__FILE__), "helpers")
|
9
|
+
|
10
|
+
|
11
|
+
module Seven module ASB
|
12
|
+
|
13
|
+
OC_GA_PROCESSES = ['occ', 'ochttpd', 'ocdnsd', 'ocshttpd', 'octcpd']
|
14
|
+
|
15
|
+
module Operations
|
16
|
+
|
17
|
+
@@default_device = nil
|
18
|
+
|
19
|
+
@@default_time_out = 300 # 5 minutes
|
20
|
+
|
21
|
+
def default_device
|
22
|
+
unless @@default_device
|
23
|
+
puts "create a default device"
|
24
|
+
@@default_device = Device.new(self, ENV['ADB_DEVICE_ARG'],ENV['ADB_DEVICE_INDEX'])
|
25
|
+
end
|
26
|
+
@@default_device
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def install_or_dump_oc_client(path, reinstall = true)
|
31
|
+
|
32
|
+
|
33
|
+
if reinstall
|
34
|
+
uri = URI.parse(path)
|
35
|
+
if uri.scheme == 'http' or uri.scheme == 'https'
|
36
|
+
install_and_start_oc_client_by_url(path)
|
37
|
+
else
|
38
|
+
install_and_start_oc_client(path)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
#log "Only dump the OC info but not re-install OC client."
|
42
|
+
#oc_info = dump_oc_info(path, "logs/device-#{ENV['ADB_DEVICE_ARG']}-oc-info.yml")
|
43
|
+
#log "OC Info: #{oc_info}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def reset_data()
|
48
|
+
# install the oc client apk
|
49
|
+
default_device.device_reset_data()
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def install_and_start_oc_client_by_url(url, saved_path = nil)
|
54
|
+
default_device.reinstall_oc_client_by_url(url, saved_path)
|
55
|
+
end
|
56
|
+
|
57
|
+
def install_and_start_oc_client(oc_apk_path)
|
58
|
+
default_device.reinstall_oc_client(oc_apk_path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def uninstall_oc_client(package_name)
|
62
|
+
default_device.uninstall_oc_client(package_name)
|
63
|
+
end
|
64
|
+
|
65
|
+
def start_oc_client()
|
66
|
+
default_device.start_oc_client()
|
67
|
+
end
|
68
|
+
|
69
|
+
def stop_oc_client(package_name)
|
70
|
+
default_device.stop_oc_client(package_name)
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
###
|
76
|
+
|
77
|
+
class Device
|
78
|
+
|
79
|
+
def make_default_device
|
80
|
+
@cucumber_world.default_device = self
|
81
|
+
end
|
82
|
+
|
83
|
+
def initialize(cucumber_world, serial, index)
|
84
|
+
@cucumber_world = cucumber_world
|
85
|
+
@serial = serial
|
86
|
+
@index = index
|
87
|
+
log "ADB_DEVICE_INDEX; #{ENV['ADB_DEVICE_INDEX']}"
|
88
|
+
if @index
|
89
|
+
@index = Integer(@index) * 100
|
90
|
+
else
|
91
|
+
@index = 0
|
92
|
+
end
|
93
|
+
log "device_index; #{@index}"
|
94
|
+
@apps = Hash.new
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def uninstall_oc_client(package_name)
|
100
|
+
# uninstall the oc client apk
|
101
|
+
log "Uninstall oc client"
|
102
|
+
cmd = "#{adb_command} uninstall #{package_name}"
|
103
|
+
log cmd
|
104
|
+
result = exec_command(cmd, @@default_time_out)
|
105
|
+
log result.is_success
|
106
|
+
|
107
|
+
stop_oc_client(package_name)
|
108
|
+
|
109
|
+
# remove /data/misc/openchannel
|
110
|
+
cmd = "#{adb_command} shell su -c rm -r /data/misc/openchannel"
|
111
|
+
log cmd
|
112
|
+
result = exec_command(cmd, @@default_time_out)
|
113
|
+
log result.is_success
|
114
|
+
|
115
|
+
cmd = "#{adb_command} shell su -c rm -r /sdcard/OpenChannel"
|
116
|
+
log cmd
|
117
|
+
result = exec_command(cmd, @@default_time_out)
|
118
|
+
log result.is_success
|
119
|
+
|
120
|
+
log "Uninstall oc client finished"
|
121
|
+
end
|
122
|
+
|
123
|
+
def start_oc_client()
|
124
|
+
log "Starting oc client...."
|
125
|
+
cmd = "#{adb_command} shell am startservice -a com.seven.asimov.ocengine.OCENGINESERVICE"
|
126
|
+
log cmd
|
127
|
+
result = exec_command(cmd, @@default_time_out)
|
128
|
+
raise "Can not start oc by am startservice" unless result.is_success
|
129
|
+
|
130
|
+
# check if oc is running
|
131
|
+
retriable :tries => 60, :interval => 30 do
|
132
|
+
cmd = "#{adb_command} shell su -c ps"
|
133
|
+
log cmd
|
134
|
+
result = exec_command(cmd, @@default_time_out)
|
135
|
+
for oc_process in OC_GA_PROCESSES
|
136
|
+
raise "OC client is not running" unless result.output.include?(oc_process)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# check iptables is modified
|
141
|
+
retriable :tries => 60, :interval => 30 do
|
142
|
+
cmd = "#{adb_command} shell su -c iptables -t nat -nvL"
|
143
|
+
log cmd
|
144
|
+
result = exec_command(cmd, @@default_time_out)
|
145
|
+
raise "iptables is not modified" unless result.output.include?('redir ports 18080')
|
146
|
+
end
|
147
|
+
puts "oc client is started."
|
148
|
+
end
|
149
|
+
|
150
|
+
def stop_oc_client(package_name)
|
151
|
+
log "Stopping oc client...."
|
152
|
+
cmd = "#{adb_command} shell am force-stop #{package_name}"
|
153
|
+
log cmd
|
154
|
+
result = exec_command(cmd, @@default_time_out)
|
155
|
+
log result.is_success
|
156
|
+
raise "Can not stop oc by am force-stop" unless result.is_success
|
157
|
+
|
158
|
+
# kill oc client processes
|
159
|
+
for oc_process in OC_GA_PROCESSES
|
160
|
+
cmd = "#{adb_command} shell su -c cat /data/misc/openchannel/pids/#{oc_process}"
|
161
|
+
log cmd
|
162
|
+
result = exec_command(cmd, @@default_time_out).output.strip
|
163
|
+
log result
|
164
|
+
cmd = "#{adb_command} shell su -c kill -9 #{result}"
|
165
|
+
log cmd
|
166
|
+
result = exec_command(cmd, @@default_time_out)
|
167
|
+
log result.is_success
|
168
|
+
end
|
169
|
+
|
170
|
+
# flush iptables
|
171
|
+
cmd = "#{adb_command} shell su -c iptables -t nat -F"
|
172
|
+
log cmd
|
173
|
+
result = exec_command(cmd, @@default_time_out)
|
174
|
+
log result.is_success
|
175
|
+
end
|
176
|
+
|
177
|
+
def install_and_start_oc_client(oc_apk_path)
|
178
|
+
# install the oc client apk
|
179
|
+
log "Install oc client"
|
180
|
+
cmd = "#{adb_command} install -r #{oc_apk_path}"
|
181
|
+
log cmd
|
182
|
+
result = exec_command(cmd, @@default_time_out)
|
183
|
+
raise "Can not install oc client" unless result.is_success
|
184
|
+
start_oc_client()
|
185
|
+
|
186
|
+
#oc_info = dump_oc_info(oc_apk_path, "logs/device-#{ENV['ADB_DEVICE_ARG']}-oc-info.yml")
|
187
|
+
#log "oc_info: #{oc_info}"
|
188
|
+
log "Install and start oc client finished."
|
189
|
+
end
|
190
|
+
|
191
|
+
def device_reset_data()
|
192
|
+
# install the oc client apk
|
193
|
+
log "Reset Data Usage/Mobile data (off/on)"
|
194
|
+
cmd = "#{adb_command} shell svc data disable && #{adb_command} shell svc data enable"
|
195
|
+
log cmd
|
196
|
+
result = exec_command(cmd, @@default_time_out)
|
197
|
+
raise "Can not reset data" unless result.is_success
|
198
|
+
|
199
|
+
log "Reset data usage done."
|
200
|
+
end
|
201
|
+
|
202
|
+
def reinstall_oc_client(oc_apk_path)
|
203
|
+
oc_pkg_name = package_name(oc_apk_path)
|
204
|
+
uninstall_oc_client(oc_pkg_name)
|
205
|
+
install_and_start_oc_client(oc_apk_path)
|
206
|
+
end
|
207
|
+
|
208
|
+
def reinstall_oc_client_by_url(url, saved_path = nil)
|
209
|
+
if saved_path
|
210
|
+
saved_path = File.expand_path(saved_path)
|
211
|
+
end
|
212
|
+
saved_path = download_file(url, saved_path)
|
213
|
+
reinstall_oc_client(saved_path)
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
def adb_command
|
218
|
+
if is_windows?
|
219
|
+
%Q("#{ENV["ANDROID_HOME"]}\\platform-tools\\adb.exe" #{device_args})
|
220
|
+
else
|
221
|
+
%Q("#{ENV["ANDROID_HOME"]}/platform-tools/adb" #{device_args})
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def device_args
|
226
|
+
if @serial
|
227
|
+
"-s #{@serial}"
|
228
|
+
else
|
229
|
+
""
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
end end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: automate-standard-baseline
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Richard Fu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &15690080 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *15690080
|
25
|
+
description: auomated standard baseline test
|
26
|
+
email: rfu@seven.com
|
27
|
+
executables:
|
28
|
+
- automate-standard-baseline
|
29
|
+
- abs-stop
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/manifest_extractor.jar
|
34
|
+
- lib/operations.rb
|
35
|
+
- lib/helpers.rb
|
36
|
+
- bin/automate-standard-baseline
|
37
|
+
- bin/abs-stop
|
38
|
+
homepage: http://rubygems.org/gems/automate-standard-baseline
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.8.11
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: automate-standard-baseline
|
62
|
+
test_files: []
|