fastlane-plugin-automated_test_emulator_run_xing 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +102 -0
- data/lib/fastlane/plugin/automated_test_emulator_run_xing.rb +13 -0
- data/lib/fastlane/plugin/automated_test_emulator_run_xing/actions/automated_test_emulator_run_xing_action.rb +493 -0
- data/lib/fastlane/plugin/automated_test_emulator_run_xing/factory/adb_controller_factory.rb +55 -0
- data/lib/fastlane/plugin/automated_test_emulator_run_xing/factory/avd_controller_factory.rb +129 -0
- data/lib/fastlane/plugin/automated_test_emulator_run_xing/provider/avd_setup_provider.rb +173 -0
- data/lib/fastlane/plugin/automated_test_emulator_run_xing/version.rb +5 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d8cd0f05420fa809c04b87544ca487705e10d733
|
4
|
+
data.tar.gz: 33ee66983a168007a6e057f1d8cbaa2075e13052
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5c2b067cff79db0c34b8b1a0418560977bcb73caa65dfb3dabeb7172247647a7fbe7d6cac7ca28a100ca363eb29b6e0e576f49e2cb6a709d0f580e38fca8d345
|
7
|
+
data.tar.gz: b6653040d8f95c5d68774e2af002a17f6bf59df5438e8c19680d719aca660af13134b606d9f296cac16e52856a06e394a41dba1c3eaf18ea1f47c21b9f1130a8
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Kamil Krzyk <krzyk.kamil@gmail.com>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# automated_test_emulator_run plugin
|
2
|
+
|
3
|
+
[![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-automated_test_emulator_run)
|
4
|
+
|
5
|
+
<b>(article is deprecated - covered plugin version < 1.3.2 which doesn't support Build-Tools ver. >= 25.0.2)</b>
|
6
|
+
<br>See [blog post related to this plugin](https://medium.com/azimolabs/managing-android-virtual-devices-during-test-session-98a403acffc2#.upcmonil1). You can learn there how to create basic setup for this plugin step by step.
|
7
|
+
|
8
|
+
## About automated_test_emulator_run
|
9
|
+
|
10
|
+
Starts any number of AVDs. AVDs are created and configured automatically according to user liking before instrumentation test process starts (started either via shell command or from gradle) and killed/deleted after test process finishes.
|
11
|
+
|
12
|
+
## Getting Started
|
13
|
+
|
14
|
+
This project is a [fastlane](https://github.com/fastlane/fastlane) plugin.
|
15
|
+
|
16
|
+
1. To get started with `fastlane-plugin-automated_test_emulator_run`, add it to your project by running:
|
17
|
+
|
18
|
+
```bash
|
19
|
+
fastlane add_plugin automated_test_emulator_run
|
20
|
+
```
|
21
|
+
2. Create your \*.JSON config file to create AVD launch plan according to schema below/provided example.
|
22
|
+
|
23
|
+
3. Wrap your test launch command with plugin and provide link to \*.JSON config.
|
24
|
+
|
25
|
+
## Example of Fastfile
|
26
|
+
|
27
|
+
Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
|
28
|
+
|
29
|
+
## JSON config
|
30
|
+
|
31
|
+
What is JSON config?
|
32
|
+
|
33
|
+
It is a core of this plugin. User can specify any number of AVD devices in JSON file. Each AVD can be configured separately. Plugin will read JSON file and create fresh, new, untouched AVDs on host - use them in tests - and then delete them after test process finishes.
|
34
|
+
|
35
|
+
JSON file scheme:
|
36
|
+
```
|
37
|
+
{
|
38
|
+
"avd_list":
|
39
|
+
[
|
40
|
+
{
|
41
|
+
"avd_name": "",
|
42
|
+
|
43
|
+
"create_avd_package": "",
|
44
|
+
"create_avd_device": "",
|
45
|
+
"create_avd_tag": "",
|
46
|
+
"create_avd_abi": "",
|
47
|
+
"create_avd_additional_options": "",
|
48
|
+
"create_avd_hardware_config_filepath": "",
|
49
|
+
|
50
|
+
"launch_avd_port": "",
|
51
|
+
"launch_avd_snapshot_filepath": "",
|
52
|
+
"launch_avd_launch_binary_name": "",
|
53
|
+
"launch_avd_additional_options": ""
|
54
|
+
}
|
55
|
+
]
|
56
|
+
}
|
57
|
+
```
|
58
|
+
|
59
|
+
Parameters:
|
60
|
+
<br>For official help refer to `avdmanager` binary file: `<sdk_root>/tools/bin/avdmanager create avd`
|
61
|
+
- `avd_name` - name of your AVD, avoid using spaces, this field is necessary
|
62
|
+
- `create_avd_package` - path to system image in example "system-images;android-23;google_apis;x86_64"
|
63
|
+
- `create_avd_device` - name of your device visible on `avdmanager list device` list
|
64
|
+
- `create_avd_tag` - the sys-img tag to use for the AVD. e.g. if you are using Google Apis then set it to "google_apis"
|
65
|
+
- `create_avd_abi` - abi for AVD e.g. "x86" or "x86_64" (https://developer.android.com/ndk/guides/abis.html)
|
66
|
+
- `create_avd_hardware_config_filepath` - path to config.ini file containing custom config for your AVD. After AVD is created this file will be copied into AVD location before it launches.
|
67
|
+
- `create_avd_additional_options` - if you think that you need something more you can just add your create parameters here (e.g. "--sdcard 128M", https://developer.android.com/studio/tools/help/android.html)
|
68
|
+
- `launch_avd_snapshot_filepath` - plugin might (if you set it) delete and re-create AVD before test start. That means all your permissions and settings will be lost on each emulator run. If you want to apply qemu image with saved AVD state you can put path to it in this field. It will be applied by using "-wipe-data -initdata <path to your file>"
|
69
|
+
- `launch_avd_launch_binary_name` - depending on your CPU architecture you need to choose binary file which should launch your AVD (e.g. "emulator", "emulator64-arm")
|
70
|
+
- `launch_avd_port` - port on which you wish your AVD should be launched, if you leave this field empty it will be assigned automatically
|
71
|
+
- `launch_avd_additional_options` - if you need more customization add your parameters here (e.g. "-gpu on -no-boot-anim -no-window", https://developer.android.com/studio/run/emulator-commandline.html)
|
72
|
+
|
73
|
+
Note:
|
74
|
+
- parameter `--path` is not supported, if you want to change directory to where your AVD are created edit your env variable ANDROID_SDK_HOME. Which is set to `~/.android/avd` by default.
|
75
|
+
|
76
|
+
Hints:
|
77
|
+
- <b> After change from `android` bin to `avdmanager` bin, default settings of AVD created from terminal has changed. No resolution is set. We highly recommend to use config.ini files which you can set to `create_avd_hardware_config_filepath` or specify resolution in `create_avd_additional_options`. </b>
|
78
|
+
- all fields need to be present in JSON, if you don't need any of the parameters just leave it empty
|
79
|
+
- pick even ports for your AVDs
|
80
|
+
- if you can't launch more than 2 AVDs be sure to check how much memory is your HAXM allowed to use (by default it is 2GB and that will allow you to launch around 2 AVDs) If you face any problems with freezing AVDs then be sure to reinstall your HAXM and allow it to use more of RAM (https://software.intel.com/en-us/android/articles/intel-hardware-accelerated-execution-manager)
|
81
|
+
- make sure you have all targets/abis installed on your PC if you want to use them (type in terminal: `android list targets`)
|
82
|
+
- we recommend adding `-gpu on` to your launching options for each device, it helps when working with many AVDs
|
83
|
+
|
84
|
+
Example:
|
85
|
+
|
86
|
+
[Example of complete JSON file can be found here.](fastlane/examples/AVD_setup.json)
|
87
|
+
|
88
|
+
## Issues and Feedback
|
89
|
+
|
90
|
+
For any other issues and feedback about this plugin, please submit it to this repository.
|
91
|
+
|
92
|
+
## Troubleshooting
|
93
|
+
|
94
|
+
If you have trouble using plugins, check out the [Plugins Troubleshooting](https://github.com/fastlane/fastlane/blob/master/fastlane/docs/PluginsTroubleshooting.md) doc in the main `fastlane` repo.
|
95
|
+
|
96
|
+
## Using `fastlane` Plugins
|
97
|
+
|
98
|
+
For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Plugins.md).
|
99
|
+
|
100
|
+
## About `fastlane`
|
101
|
+
|
102
|
+
`fastlane` is the easiest way to automate building and releasing your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'fastlane/plugin/automated_test_emulator_run_xing/version'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module AutomatedTestEmulatorRunXing
|
5
|
+
def self.all_classes
|
6
|
+
Dir[File.expand_path('**/{actions,factory,provider}/*.rb', File.dirname(__FILE__))]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Fastlane::AutomatedTestEmulatorRunXing.all_classes.each do |current|
|
12
|
+
require current
|
13
|
+
end
|
@@ -0,0 +1,493 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Fastlane
|
5
|
+
module Actions
|
6
|
+
|
7
|
+
class AutomatedTestEmulatorRunXingAction < Action
|
8
|
+
def self.run(params)
|
9
|
+
UI.message("The automated_test_emulator_run plugin is working!")
|
10
|
+
|
11
|
+
# Parse JSON with AVD launch confing to array of AVD_scheme objects
|
12
|
+
avd_schemes = Provider::AvdSchemeProvider.get_avd_schemes(params)
|
13
|
+
|
14
|
+
# ADB, AVD helper classes
|
15
|
+
adb_controller = Factory::AdbControllerFactory.get_adb_controller(params)
|
16
|
+
avd_controllers = []
|
17
|
+
|
18
|
+
# Create AVD_Controller class for each AVD_scheme
|
19
|
+
for i in 0...avd_schemes.length
|
20
|
+
avd_controller = Factory::AvdControllerFactory.get_avd_controller(params, avd_schemes[i])
|
21
|
+
avd_controllers << avd_controller
|
22
|
+
|
23
|
+
if params[:verbose]
|
24
|
+
# Checking for output files
|
25
|
+
if File.exists?(avd_controller.output_file.path)
|
26
|
+
UI.message([
|
27
|
+
"Successfully created tmp output file for AVD:",
|
28
|
+
avd_schemes[i].avd_name + ".",
|
29
|
+
"File: " + avd_controller.output_file.path].join(" ").green)
|
30
|
+
else
|
31
|
+
UI.message([
|
32
|
+
"Unable to create output file for AVD:",
|
33
|
+
avd_schemes[i].avd_name + ".",
|
34
|
+
"Output will be delegated to null and lost. Check your save/read permissions."].join(" ").red)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Reseting wait states
|
40
|
+
all_avd_launched = false
|
41
|
+
adb_launch_complete = false
|
42
|
+
param_launch_complete = false
|
43
|
+
|
44
|
+
while(!all_avd_launched)
|
45
|
+
# Preparation
|
46
|
+
UI.message("Configuring environment in order to launch emulators: ".yellow)
|
47
|
+
UI.message("Getting avaliable AVDs".yellow)
|
48
|
+
devices = Action.sh(adb_controller.command_get_avds)
|
49
|
+
|
50
|
+
for i in 0...avd_schemes.length
|
51
|
+
unless devices.match(avd_schemes[i].avd_name).nil?
|
52
|
+
UI.message(["AVD with name '", avd_schemes[i].avd_name, "' currently exists."].join("").yellow)
|
53
|
+
if params[:AVD_recreate_new]
|
54
|
+
# Delete existing AVDs
|
55
|
+
UI.message("AVD_create_new parameter set to true.".yellow)
|
56
|
+
UI.message(["Deleting existing AVD with name:", avd_schemes[i].avd_name].join(" ").yellow)
|
57
|
+
Action.sh(avd_controllers[i].command_delete_avd)
|
58
|
+
|
59
|
+
# Re-create AVD
|
60
|
+
UI.message(["Re-creating new AVD."].join(" ").yellow)
|
61
|
+
Action.sh(avd_controllers[i].command_create_avd)
|
62
|
+
else
|
63
|
+
# Use existing AVD
|
64
|
+
UI.message("AVD_recreate_new parameter set to false.".yellow)
|
65
|
+
UI.message("Using existing AVD for tests.".yellow)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
# Create AVD
|
69
|
+
UI.message(["AVD with name '", avd_schemes[i].avd_name, "' does not exist. Creating new AVD."].join("").yellow)
|
70
|
+
Action.sh(avd_controllers[i].command_create_avd)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Restart ADB
|
75
|
+
if params[:ADB_restart]
|
76
|
+
UI.message("Restarting adb".yellow)
|
77
|
+
Action.sh(adb_controller.command_stop)
|
78
|
+
Action.sh(adb_controller.command_start)
|
79
|
+
else
|
80
|
+
UI.message("ADB won't be restarted. 'ADB_restart' set to false.".yellow)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Applying custom configs (it's not done directly after create because 'cat' operation seems to fail overwrite)
|
84
|
+
for i in 0...avd_schemes.length
|
85
|
+
UI.message(["Attemting to apply custom config to ", avd_schemes[i].avd_name].join("").yellow)
|
86
|
+
if avd_controllers[i].command_apply_config_avd.eql? ""
|
87
|
+
UI.message(["No config file found for AVD '", avd_schemes[i].avd_name, "'. AVD won't have config.ini applied."].join("").yellow)
|
88
|
+
else
|
89
|
+
UI.message(["Config file found! Applying custom config to: ", avd_schemes[i].avd_name].join("").yellow)
|
90
|
+
Action.sh(avd_controllers[i].command_apply_config_avd)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Launching AVDs
|
95
|
+
UI.message("Launching all AVDs at the same time.".yellow)
|
96
|
+
for i in 0...avd_controllers.length
|
97
|
+
Process.fork do
|
98
|
+
Action.sh(avd_controllers[i].command_start_avd)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Wait for AVDs finish booting
|
103
|
+
UI.message("Waiting for AVDs to finish booting.".yellow)
|
104
|
+
UI.message("Performig wait for ADB boot".yellow)
|
105
|
+
adb_launch_complete = wait_for_emulator_boot_by_adb(adb_controller, avd_schemes, "#{params[:AVD_adb_launch_timeout]}")
|
106
|
+
|
107
|
+
# Wait for AVD params finish booting
|
108
|
+
if adb_launch_complete
|
109
|
+
UI.message("Wait for ADB boot completed with success".yellow)
|
110
|
+
|
111
|
+
if (params[:AVD_wait_for_bootcomplete] || params[:AVD_wait_for_boot_completed] || params[:AVD_wait_for_bootanim])
|
112
|
+
message = "Performing wait for params: "
|
113
|
+
|
114
|
+
if params[:AVD_wait_for_bootcomplete]
|
115
|
+
message += "'dev.bootcomplete', "
|
116
|
+
end
|
117
|
+
|
118
|
+
if params[:AVD_wait_for_boot_completed]
|
119
|
+
message += "'sys.boot_completed', "
|
120
|
+
end
|
121
|
+
|
122
|
+
if params[:AVD_wait_for_bootanim]
|
123
|
+
message += "'init.svc.bootanim', "
|
124
|
+
end
|
125
|
+
|
126
|
+
message = message[0...-2] + "."
|
127
|
+
UI.message(message.yellow)
|
128
|
+
|
129
|
+
param_launch_complete = wait_for_emulator_boot_by_params(params, adb_controller, avd_controllers, avd_schemes, "#{params[:AVD_param_launch_timeout]}")
|
130
|
+
else
|
131
|
+
UI.message("Wait for AVD launch params was turned off. Skipping...".yellow)
|
132
|
+
param_launch_complete = true
|
133
|
+
end
|
134
|
+
else
|
135
|
+
UI.message("Wait for ADB boot failed".yellow)
|
136
|
+
end
|
137
|
+
|
138
|
+
all_avd_launched = adb_launch_complete && param_launch_complete
|
139
|
+
|
140
|
+
# Deciding if AVD launch should be restarted
|
141
|
+
devices_output = Action.sh(adb_controller.command_get_devices)
|
142
|
+
|
143
|
+
devices = ""
|
144
|
+
devices_output.each_line do |line|
|
145
|
+
if line.include?("emulator-")
|
146
|
+
devices += line.sub(/\t/, " ")
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
if all_avd_launched
|
151
|
+
UI.message("AVDs Booted!".green)
|
152
|
+
else
|
153
|
+
for i in 0...avd_schemes.length
|
154
|
+
if params[:verbose]
|
155
|
+
# Display AVD output
|
156
|
+
if (File.exists?(avd_controllers[i].output_file.path))
|
157
|
+
UI.message(["Displaying log for AVD:", avd_schemes[i].avd_name].join(" ").red)
|
158
|
+
UI.message(avd_controllers[i].output_file.read.blue)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Killing devices
|
163
|
+
unless devices.match(["emulator-", avd_schemes[i].launch_avd_port].join("")).nil?
|
164
|
+
Action.sh(avd_controllers[i].command_kill_device)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Launching tests
|
171
|
+
shell_task = "#{params[:shell_task]}" unless params[:shell_task].nil?
|
172
|
+
gradle_task = "#{params[:gradle_task]}" unless params[:gradle_task].nil?
|
173
|
+
spoon_task = "#{params[:spoon_task]}" unless params[:spoon_task].nil?
|
174
|
+
|
175
|
+
UI.message("Starting tests".green)
|
176
|
+
begin
|
177
|
+
unless shell_task.nil?
|
178
|
+
UI.message("Using shell task.".green)
|
179
|
+
Action.sh(shell_task)
|
180
|
+
end
|
181
|
+
|
182
|
+
unless gradle_task.nil?
|
183
|
+
gradle = Helper::GradleHelper.new(gradle_path: Dir["./gradlew"].last)
|
184
|
+
|
185
|
+
UI.message("Using gradle task.".green)
|
186
|
+
gradle.trigger(task: params[:gradle_task], flags: params[:gradle_flags], serial: nil)
|
187
|
+
end
|
188
|
+
|
189
|
+
unless spoon_task.nil?
|
190
|
+
gradle = Helper::GradleHelper.new(gradle_path: Dir["./gradlew"].last)
|
191
|
+
|
192
|
+
UI.message("Using spoon task.".green)
|
193
|
+
ports = Array.new
|
194
|
+
spoon_devices = ""
|
195
|
+
for i in 0...avd_schemes.length
|
196
|
+
ports << avd_schemes[i].launch_avd_port
|
197
|
+
spoon_devices = spoon_devices + "-pSpoonDevice=emulator-" + avd_schemes[i].launch_avd_port + " "
|
198
|
+
end
|
199
|
+
|
200
|
+
gradle_flags = params[:gradle_flags]
|
201
|
+
gradle_flags = gradle_flags + spoon_devices
|
202
|
+
|
203
|
+
gradle.trigger(task: params[:gradle_task], flags: gradle_flags, serial: nil)
|
204
|
+
end
|
205
|
+
ensure
|
206
|
+
# Clean up
|
207
|
+
for i in 0...avd_schemes.length
|
208
|
+
# Kill all emulators
|
209
|
+
unless devices.match(["emulator-", avd_schemes[i].launch_avd_port].join("")).nil?
|
210
|
+
Action.sh(avd_controllers[i].command_kill_device)
|
211
|
+
end
|
212
|
+
|
213
|
+
if params[:verbose]
|
214
|
+
# Display AVD output
|
215
|
+
if (File.exists?(avd_controllers[i].output_file.path))
|
216
|
+
UI.message("Displaying log from AVD to console:".green)
|
217
|
+
UI.message(avd_controllers[i].output_file.read.blue)
|
218
|
+
|
219
|
+
UI.message("Removing temp file.".green)
|
220
|
+
avd_controllers[i].output_file.close
|
221
|
+
avd_controllers[i].output_file.unlink
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Delete AVDs
|
226
|
+
if params[:AVD_clean_after]
|
227
|
+
UI.message("AVD_clean_after param set to true. Deleting AVDs.".green)
|
228
|
+
Action.sh(avd_controllers[i].command_delete_avd)
|
229
|
+
else
|
230
|
+
UI.message("AVD_clean_after param set to false. Created AVDs won't be deleted.".green)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.wait_for_emulator_boot_by_adb(adb_controller, avd_schemes, timeout)
|
237
|
+
timeoutInSeconds= timeout.to_i
|
238
|
+
interval = 1000 * 10
|
239
|
+
startTime = Time.now
|
240
|
+
lastCheckTime = Time.now
|
241
|
+
launch_status_hash = Hash.new
|
242
|
+
device_visibility_hash = Hash.new
|
243
|
+
|
244
|
+
for i in 0...avd_schemes.length
|
245
|
+
device_name = ["emulator-", avd_schemes[i].launch_avd_port].join("")
|
246
|
+
launch_status_hash.store(device_name, false)
|
247
|
+
device_visibility_hash.store(device_name, false)
|
248
|
+
end
|
249
|
+
|
250
|
+
launch_status = false
|
251
|
+
loop do
|
252
|
+
currentTime = Time.now
|
253
|
+
if ((currentTime - lastCheckTime) * 1000) > interval
|
254
|
+
lastCheckTime = currentTime
|
255
|
+
devices_output = Action.sh(adb_controller.command_get_devices)
|
256
|
+
|
257
|
+
devices = ""
|
258
|
+
devices_output.each_line do |line|
|
259
|
+
if line.include?("emulator-")
|
260
|
+
devices += line.sub(/\t/, " ")
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Check if device is visible
|
265
|
+
all_devices_visible = true
|
266
|
+
device_visibility_hash.each do |name, is_visible|
|
267
|
+
unless (devices.match(name).nil? || is_visible)
|
268
|
+
device_visibility_hash[name] = true
|
269
|
+
end
|
270
|
+
all_devices_visible = false unless is_visible
|
271
|
+
end
|
272
|
+
|
273
|
+
# Check if device is booted
|
274
|
+
all_devices_booted = true
|
275
|
+
launch_status_hash.each do |name, is_booted|
|
276
|
+
unless (devices.match(name + " device").nil? || is_booted)
|
277
|
+
launch_status_hash[name] = true
|
278
|
+
end
|
279
|
+
all_devices_booted = false unless launch_status_hash[name]
|
280
|
+
end
|
281
|
+
|
282
|
+
# Quit if timeout reached
|
283
|
+
if ((currentTime - startTime) >= timeoutInSeconds)
|
284
|
+
UI.message(["AVD ADB loading took more than ", timeout, ". Attempting to re-launch."].join("").red)
|
285
|
+
launch_status = false
|
286
|
+
break
|
287
|
+
end
|
288
|
+
|
289
|
+
# Quit if all devices booted
|
290
|
+
if (all_devices_booted && all_devices_visible)
|
291
|
+
launch_status = true
|
292
|
+
break
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
return launch_status
|
297
|
+
end
|
298
|
+
|
299
|
+
def self.wait_for_emulator_boot_by_params(params, adb_controller, avd_controllers, avd_schemes, timeout)
|
300
|
+
timeout_in_seconds= timeout.to_i
|
301
|
+
interval = 1000 * 10
|
302
|
+
all_params_launched = false
|
303
|
+
start_time = last_scan_ended = Time.now
|
304
|
+
device_boot_statuses = Hash.new
|
305
|
+
|
306
|
+
loop do
|
307
|
+
current_time = Time.now
|
308
|
+
|
309
|
+
# Performing single scan over each device
|
310
|
+
if (((current_time - last_scan_ended) * 1000) >= interval || start_time == last_scan_ended)
|
311
|
+
for i in 0...avd_schemes.length
|
312
|
+
avd_schema = avd_schemes[i]
|
313
|
+
avd_controller = avd_controllers[i]
|
314
|
+
avd_param_boot_hash = Hash.new
|
315
|
+
avd_param_status_hash = Hash.new
|
316
|
+
avd_booted = false
|
317
|
+
|
318
|
+
# Retreiving device parameters according to config
|
319
|
+
if params[:AVD_wait_for_bootcomplete]
|
320
|
+
dev_bootcomplete, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "dev.bootcomplete"].join(" "))
|
321
|
+
avd_param_boot_hash.store("dev.bootcomplete", dev_bootcomplete.strip.eql?("1"))
|
322
|
+
avd_param_status_hash.store("dev.bootcomplete", dev_bootcomplete)
|
323
|
+
end
|
324
|
+
|
325
|
+
if params[:AVD_wait_for_boot_completed]
|
326
|
+
sys_boot_completed, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "sys.boot_completed"].join(" "))
|
327
|
+
avd_param_boot_hash.store("sys.boot_completed", sys_boot_completed.strip.eql?("1"))
|
328
|
+
avd_param_status_hash.store("sys.boot_completed", sys_boot_completed)
|
329
|
+
end
|
330
|
+
|
331
|
+
if params[:AVD_wait_for_bootanim]
|
332
|
+
bootanim, _stdeerr, _status = Open3.capture3([avd_controller.command_get_property, "init.svc.bootanim"].join(" "))
|
333
|
+
avd_param_boot_hash.store("init.svc.bootanim", bootanim.strip.eql?("stopped"))
|
334
|
+
avd_param_status_hash.store("init.svc.bootanim", bootanim)
|
335
|
+
end
|
336
|
+
|
337
|
+
# Checking for param statuses
|
338
|
+
avd_param_boot_hash.each do |name, is_booted|
|
339
|
+
if !is_booted
|
340
|
+
break
|
341
|
+
end
|
342
|
+
avd_booted = true
|
343
|
+
end
|
344
|
+
device_boot_statuses.store(avd_schema.avd_name, avd_booted)
|
345
|
+
|
346
|
+
# Plotting current wait results
|
347
|
+
device_log = "Device 'emulator-" + avd_schemes[i].launch_avd_port.to_s + "' launch status:"
|
348
|
+
UI.message(device_log.magenta)
|
349
|
+
avd_param_boot_hash.each do |name, is_booted|
|
350
|
+
device_log = "'" + name + "' - '" + avd_param_status_hash[name].strip + "' (launched: " + is_booted.to_s + ")"
|
351
|
+
UI.message(device_log.magenta)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
last_scan_ended = Time.now
|
355
|
+
end
|
356
|
+
|
357
|
+
# Checking if wait doesn't last too long
|
358
|
+
if (current_time - start_time) >= timeout_in_seconds
|
359
|
+
UI.message(["AVD param loading took more than ", timeout, ". Attempting to re-launch."].join("").red)
|
360
|
+
all_params_launched = false
|
361
|
+
break
|
362
|
+
end
|
363
|
+
|
364
|
+
# Finishing wait with success if all params are loaded for every device
|
365
|
+
device_boot_statuses.each do |name, is_booted|
|
366
|
+
if !is_booted
|
367
|
+
break
|
368
|
+
end
|
369
|
+
all_params_launched = true
|
370
|
+
end
|
371
|
+
if all_params_launched
|
372
|
+
break
|
373
|
+
end
|
374
|
+
end
|
375
|
+
return all_params_launched
|
376
|
+
end
|
377
|
+
|
378
|
+
def self.available_options
|
379
|
+
[
|
380
|
+
#paths
|
381
|
+
FastlaneCore::ConfigItem.new(key: :AVD_path,
|
382
|
+
env_name: "AVD_PATH",
|
383
|
+
description: "The path to your android AVD directory (root). ANDROID_SDK_HOME by default",
|
384
|
+
default_value: (ENV['ANDROID_SDK_HOME'].nil? or ENV['ANDROID_SDK_HOME'].eql?("")) ? "~/.android/avd" : ENV['ANDROID_SDK_HOME'],
|
385
|
+
is_string: true,
|
386
|
+
optional: true),
|
387
|
+
FastlaneCore::ConfigItem.new(key: :AVD_setup_path,
|
388
|
+
env_name: "AVD_SETUP_PATH",
|
389
|
+
description: "Location to AVD_setup.json file which contains info about how many AVD should be launched and their configs",
|
390
|
+
is_string: true,
|
391
|
+
optional: false),
|
392
|
+
FastlaneCore::ConfigItem.new(key: :SDK_path,
|
393
|
+
env_name: "SDK_PATH",
|
394
|
+
description: "The path to your android sdk directory (root). ANDROID_HOME by default",
|
395
|
+
default_value: ENV['ANDROID_HOME'],
|
396
|
+
is_string: true,
|
397
|
+
optional: true),
|
398
|
+
|
399
|
+
|
400
|
+
#launch config params
|
401
|
+
FastlaneCore::ConfigItem.new(key: :AVD_param_launch_timeout,
|
402
|
+
env_name: "AVD_PARAM_LAUNCH_TIMEOUT",
|
403
|
+
description: "Timeout in seconds. Even though ADB might find all devices you still might want to wait for animations to finish and system to boot. Default 60 seconds",
|
404
|
+
default_value: 60,
|
405
|
+
is_string: true,
|
406
|
+
optional: true),
|
407
|
+
FastlaneCore::ConfigItem.new(key: :AVD_adb_launch_timeout,
|
408
|
+
env_name: "AVD_ADB_LAUNCH_TIMEOUT",
|
409
|
+
description: "Timeout in seconds. Wait until ADB finds all devices specified in config and sets their value to 'device'. Default 240 seconds",
|
410
|
+
default_value: 240,
|
411
|
+
is_string: true,
|
412
|
+
optional: true),
|
413
|
+
FastlaneCore::ConfigItem.new(key: :AVD_recreate_new,
|
414
|
+
env_name: "AVD_RECREATE_NEW",
|
415
|
+
description: "Allow to decide if AVDs from AVD_setup.json (in case they already exist) should be deleted and created from scratch",
|
416
|
+
default_value: true,
|
417
|
+
is_string: false,
|
418
|
+
optional: true),
|
419
|
+
FastlaneCore::ConfigItem.new(key: :AVD_clean_after,
|
420
|
+
env_name: "AVD_CLEAN_AFTER",
|
421
|
+
description: "Allow to decide if AVDs should be deleted from PC after test session ends",
|
422
|
+
default_value: true,
|
423
|
+
is_string: false,
|
424
|
+
optional: true),
|
425
|
+
FastlaneCore::ConfigItem.new(key: :ADB_restart,
|
426
|
+
env_name: "ADB_RESTART",
|
427
|
+
description: "Allows to switch adb restarting on/off",
|
428
|
+
default_value: true,
|
429
|
+
is_string: false,
|
430
|
+
optional: true),
|
431
|
+
FastlaneCore::ConfigItem.new(key: :AVD_wait_for_bootcomplete,
|
432
|
+
env_name: "AVD_BOOTCOMPLETE_WAIT",
|
433
|
+
description: "Allows to switch wait for 'dev.bootcomplete' AVD launch param on/off",
|
434
|
+
default_value: true,
|
435
|
+
is_string: false,
|
436
|
+
optional: true),
|
437
|
+
FastlaneCore::ConfigItem.new(key: :AVD_wait_for_boot_completed,
|
438
|
+
env_name: "AVD_BOOT_COMPLETED_WAIT",
|
439
|
+
description: "Allows to switch wait for 'sys.boot_completed' AVD launch param on/off",
|
440
|
+
default_value: true,
|
441
|
+
is_string: false,
|
442
|
+
optional: true),
|
443
|
+
FastlaneCore::ConfigItem.new(key: :AVD_wait_for_bootanim,
|
444
|
+
env_name: "ABD_BOOTANIM_WAIT",
|
445
|
+
description: "Allows to switch wait for 'init.svc.bootanim' AVD launch param on/off",
|
446
|
+
default_value: true,
|
447
|
+
is_string: false,
|
448
|
+
optional: true),
|
449
|
+
|
450
|
+
#launch commands
|
451
|
+
FastlaneCore::ConfigItem.new(key: :shell_task,
|
452
|
+
env_name: "SHELL_TASK",
|
453
|
+
description: "The shell command you want to execute",
|
454
|
+
conflicting_options: [:gradle_task],
|
455
|
+
is_string: true,
|
456
|
+
optional: true),
|
457
|
+
FastlaneCore::ConfigItem.new(key: :gradle_task,
|
458
|
+
env_name: "GRADLE_TASK",
|
459
|
+
description: "The gradle task you want to execute",
|
460
|
+
conflicting_options: [:shell_command],
|
461
|
+
is_string: true,
|
462
|
+
optional: true),
|
463
|
+
FastlaneCore::ConfigItem.new(key: :gradle_flags,
|
464
|
+
env_name: "GRADLE_FLAGS",
|
465
|
+
description: "All parameter flags you want to pass to the gradle command, e.g. `--exitcode --xml file.xml`",
|
466
|
+
conflicting_options: [:shell_command],
|
467
|
+
optional: true,
|
468
|
+
is_string: true),
|
469
|
+
|
470
|
+
#mode
|
471
|
+
FastlaneCore::ConfigItem.new(key: :verbose,
|
472
|
+
env_name: "AVD_VERBOSE",
|
473
|
+
description: "Allows to turn on/off mode verbose which displays output of AVDs",
|
474
|
+
default_value: false,
|
475
|
+
is_string: false,
|
476
|
+
optional: true),
|
477
|
+
]
|
478
|
+
end
|
479
|
+
|
480
|
+
def self.description
|
481
|
+
"Starts AVD, based on AVD_setup.json file, before test launch and kills it after testing is done."
|
482
|
+
end
|
483
|
+
|
484
|
+
def self.authors
|
485
|
+
["F1sherKK"]
|
486
|
+
end
|
487
|
+
|
488
|
+
def self.is_supported?(platform)
|
489
|
+
platform == :android
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Factory
|
3
|
+
|
4
|
+
class ADB_Controller
|
5
|
+
attr_accessor :command_stop, :command_start, :command_get_devices, :command_wait_for_device, :command_get_avds
|
6
|
+
end
|
7
|
+
|
8
|
+
class AdbControllerFactory
|
9
|
+
|
10
|
+
def self.get_adb_controller(params)
|
11
|
+
UI.message(["Preparing commands for Android ADB"].join(" ").yellow)
|
12
|
+
|
13
|
+
# Get paths
|
14
|
+
path_sdk = "#{params[:SDK_path]}"
|
15
|
+
path_avdmanager_binary = path_sdk + "/tools/bin/avdmanager"
|
16
|
+
path_adb = path_sdk + "/platform-tools/adb"
|
17
|
+
|
18
|
+
# ADB shell command parts
|
19
|
+
sh_stop_adb = "kill-server"
|
20
|
+
sh_start_adb = "start-server"
|
21
|
+
sh_devices_adb = "devices"
|
22
|
+
sh_wait_for_device_adb = "wait-for-device"
|
23
|
+
sh_list_avd_adb = "list avd"
|
24
|
+
|
25
|
+
# Assemble ADB controller
|
26
|
+
adb_controller = ADB_Controller.new
|
27
|
+
adb_controller.command_stop = [
|
28
|
+
path_adb,
|
29
|
+
sh_stop_adb
|
30
|
+
].join(" ")
|
31
|
+
|
32
|
+
adb_controller.command_start = [
|
33
|
+
path_adb,
|
34
|
+
sh_start_adb
|
35
|
+
].join(" ")
|
36
|
+
|
37
|
+
adb_controller.command_get_devices = [
|
38
|
+
path_adb,
|
39
|
+
sh_devices_adb
|
40
|
+
].join(" ")
|
41
|
+
|
42
|
+
adb_controller.command_wait_for_device = [
|
43
|
+
path_adb,
|
44
|
+
sh_wait_for_device_adb
|
45
|
+
].join(" ")
|
46
|
+
|
47
|
+
adb_controller.command_get_avds = [
|
48
|
+
path_avdmanager_binary,
|
49
|
+
sh_list_avd_adb].join(" ").chomp
|
50
|
+
|
51
|
+
return adb_controller
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
module Factory
|
5
|
+
|
6
|
+
class AVD_Controller
|
7
|
+
attr_accessor :command_create_avd, :command_start_avd, :command_delete_avd, :command_apply_config_avd, :command_get_property, :command_kill_device,
|
8
|
+
:output_file
|
9
|
+
|
10
|
+
def self.create_output_file(params)
|
11
|
+
output_file = Tempfile.new('emulator_output', '#{params[:AVD_path]}')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class AvdControllerFactory
|
16
|
+
|
17
|
+
def self.get_avd_controller(params, avd_scheme)
|
18
|
+
UI.message(["Preparing parameters and commands for emulator:", avd_scheme.avd_name].join(" ").yellow)
|
19
|
+
|
20
|
+
# Get paths
|
21
|
+
path_sdk = "#{params[:SDK_path]}"
|
22
|
+
path_avdmanager_binary = path_sdk + "/tools/bin/avdmanager"
|
23
|
+
path_adb = path_sdk + "/platform-tools/adb"
|
24
|
+
path_avd = "#{params[:AVD_path]}"
|
25
|
+
|
26
|
+
# Create AVD shell command parts
|
27
|
+
sh_create_answer_no = "echo \"no\" |"
|
28
|
+
sh_create_avd = "create avd"
|
29
|
+
sh_create_avd_name = ["--name \"", avd_scheme.avd_name, "\""].join("")
|
30
|
+
sh_create_avd_package = ["--package \"", avd_scheme.create_avd_package, "\""].join("")
|
31
|
+
|
32
|
+
if avd_scheme.create_avd_device.eql? ""
|
33
|
+
sh_create_avd_device = ""
|
34
|
+
else
|
35
|
+
sh_create_avd_device = ["--device \"", avd_scheme.create_avd_device, "\""].join("")
|
36
|
+
end
|
37
|
+
|
38
|
+
if avd_scheme.create_avd_abi.eql? ""
|
39
|
+
sh_create_avd_abi = ""
|
40
|
+
else
|
41
|
+
sh_create_avd_abi = ["--abi ", avd_scheme.create_avd_abi].join("")
|
42
|
+
end
|
43
|
+
|
44
|
+
if avd_scheme.create_avd_tag.eql? ""
|
45
|
+
sh_create_avd_tag = ""
|
46
|
+
else
|
47
|
+
sh_create_avd_tag = ["--tag ", avd_scheme.create_avd_tag].join("")
|
48
|
+
end
|
49
|
+
|
50
|
+
sh_create_avd_additional_options = avd_scheme.create_avd_additional_options
|
51
|
+
sh_create_config_loc = "#{path_avd}/#{avd_scheme.avd_name}.avd/config.ini"
|
52
|
+
|
53
|
+
# Launch AVD shell command parts
|
54
|
+
sh_launch_emulator_binary = [path_sdk, "/emulator/", avd_scheme.launch_avd_launch_binary_name].join("")
|
55
|
+
sh_launch_avd_name = ["-avd ", avd_scheme.avd_name].join("")
|
56
|
+
sh_launch_avd_additional_options = avd_scheme.launch_avd_additional_options
|
57
|
+
sh_launch_avd_port = ["-port", avd_scheme.launch_avd_port].join(" ")
|
58
|
+
|
59
|
+
if avd_scheme.launch_avd_snapshot_filepath.eql? ""
|
60
|
+
sh_launch_avd_snapshot = ""
|
61
|
+
else
|
62
|
+
sh_launch_avd_snapshot = ["-wipe-data -initdata ", avd_scheme.launch_avd_snapshot_filepath].join("")
|
63
|
+
end
|
64
|
+
|
65
|
+
# Re-create AVD shell command parts
|
66
|
+
sh_delete_avd = ["delete avd -n ", avd_scheme.avd_name].join("")
|
67
|
+
|
68
|
+
# ADB related shell command parts
|
69
|
+
sh_specific_device = "-s"
|
70
|
+
sh_device_name_adb = ["emulator-", avd_scheme.launch_avd_port].join("")
|
71
|
+
sh_get_property = "shell getprop"
|
72
|
+
sh_kill_device = "emu kill"
|
73
|
+
|
74
|
+
# Assemble AVD controller
|
75
|
+
avd_controller = AVD_Controller.new
|
76
|
+
avd_controller.command_create_avd = [
|
77
|
+
sh_create_answer_no,
|
78
|
+
path_avdmanager_binary,
|
79
|
+
sh_create_avd,
|
80
|
+
sh_create_avd_name,
|
81
|
+
sh_create_avd_package,
|
82
|
+
sh_create_avd_device,
|
83
|
+
sh_create_avd_tag,
|
84
|
+
sh_create_avd_abi,
|
85
|
+
sh_create_avd_additional_options].join(" ")
|
86
|
+
|
87
|
+
avd_controller.output_file = Tempfile.new('emulator_output')
|
88
|
+
avd_output = File.exists?(avd_controller.output_file) ? ["&>", avd_controller.output_file.path, "&"].join("") : "&>/dev/null &"
|
89
|
+
|
90
|
+
avd_controller.command_start_avd = [
|
91
|
+
sh_launch_emulator_binary,
|
92
|
+
sh_launch_avd_port,
|
93
|
+
sh_launch_avd_name,
|
94
|
+
sh_launch_avd_snapshot,
|
95
|
+
sh_launch_avd_additional_options,
|
96
|
+
avd_output].join(" ")
|
97
|
+
|
98
|
+
avd_controller.command_delete_avd = [
|
99
|
+
path_avdmanager_binary,
|
100
|
+
sh_delete_avd].join(" ")
|
101
|
+
|
102
|
+
if path_avd.nil? || (avd_scheme.create_avd_hardware_config_filepath.eql? "")
|
103
|
+
avd_controller.command_apply_config_avd = ""
|
104
|
+
else
|
105
|
+
avd_controller.command_apply_config_avd = [
|
106
|
+
"cat",
|
107
|
+
avd_scheme.create_avd_hardware_config_filepath,
|
108
|
+
">",
|
109
|
+
sh_create_config_loc].join(" ")
|
110
|
+
end
|
111
|
+
|
112
|
+
avd_controller.command_get_property = [
|
113
|
+
path_adb,
|
114
|
+
sh_specific_device,
|
115
|
+
sh_device_name_adb,
|
116
|
+
sh_get_property].join(" ")
|
117
|
+
|
118
|
+
avd_controller.command_kill_device = [
|
119
|
+
path_adb,
|
120
|
+
sh_specific_device,
|
121
|
+
sh_device_name_adb,
|
122
|
+
sh_kill_device,
|
123
|
+
"&>/dev/null"].join(" ")
|
124
|
+
|
125
|
+
return avd_controller
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Provider
|
3
|
+
|
4
|
+
class AVD_scheme
|
5
|
+
attr_accessor :avd_name, :create_avd_package, :create_avd_device, :create_avd_tag, :create_avd_abi, :create_avd_hardware_config_filepath, :create_avd_additional_options,
|
6
|
+
:launch_avd_port, :launch_avd_launch_binary_name, :launch_avd_additional_options, :launch_avd_snapshot_filepath
|
7
|
+
end
|
8
|
+
|
9
|
+
class AvdSchemeProvider
|
10
|
+
|
11
|
+
def self.get_avd_schemes(params)
|
12
|
+
|
13
|
+
# Read JSON into string variable
|
14
|
+
avd_setup_json = read_avd_setup(params)
|
15
|
+
if avd_setup_json.nil?
|
16
|
+
throw_error("Unable to read AVD_setup.json. Check JSON file structure or file path.")
|
17
|
+
end
|
18
|
+
|
19
|
+
# Read JSON into Hash
|
20
|
+
avd_setup = JSON.parse(avd_setup_json)
|
21
|
+
avd_hash_list = avd_setup['avd_list']
|
22
|
+
|
23
|
+
# Create AVD_scheme objects and fill them with data
|
24
|
+
avd_scheme_list = []
|
25
|
+
for i in 0...avd_hash_list.length
|
26
|
+
avd_hash = avd_hash_list[i]
|
27
|
+
|
28
|
+
avd_scheme = AVD_scheme.new
|
29
|
+
avd_scheme.avd_name = avd_hash['avd_name']
|
30
|
+
|
31
|
+
avd_scheme.create_avd_package = avd_hash['create_avd_package']
|
32
|
+
avd_scheme.create_avd_device = avd_hash['create_avd_device']
|
33
|
+
avd_scheme.create_avd_tag = avd_hash['create_avd_tag']
|
34
|
+
avd_scheme.create_avd_abi = avd_hash['create_avd_abi']
|
35
|
+
avd_scheme.create_avd_hardware_config_filepath = avd_hash['create_avd_hardware_config_filepath']
|
36
|
+
|
37
|
+
avd_scheme.launch_avd_port = avd_hash['launch_avd_port']
|
38
|
+
avd_scheme.launch_avd_launch_binary_name = avd_hash['launch_avd_launch_binary_name']
|
39
|
+
avd_scheme.launch_avd_additional_options = avd_hash['launch_avd_additional_options']
|
40
|
+
avd_scheme.launch_avd_snapshot_filepath = avd_hash['launch_avd_snapshot_filepath']
|
41
|
+
|
42
|
+
errors = check_avd_fields(avd_scheme)
|
43
|
+
unless errors.empty?
|
44
|
+
error_log = "Error! Fields not found in JSON: \n"
|
45
|
+
errors.each { |error| error_log += error + "\n" }
|
46
|
+
throw_error(error_log)
|
47
|
+
end
|
48
|
+
|
49
|
+
avd_scheme_list << avd_scheme
|
50
|
+
end
|
51
|
+
|
52
|
+
# Prepare list of open ports for AVD_schemes without ports set in JSON
|
53
|
+
avaliable_ports = get_unused_even_tcp_ports(5556, 5586, avd_scheme_list)
|
54
|
+
|
55
|
+
# Fill empty AVD_schemes with open ports
|
56
|
+
for i in 0...avd_scheme_list.length
|
57
|
+
avd_scheme = avd_scheme_list[i]
|
58
|
+
if avd_scheme.launch_avd_port.eql? ""
|
59
|
+
avd_scheme.launch_avd_port = avaliable_ports[0]
|
60
|
+
$Ports << avd_scheme.launch_avd_port
|
61
|
+
avaliable_ports.delete(avaliable_ports[0])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
return avd_scheme_list
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.get_unused_even_tcp_ports(min_port, max_port, avd_scheme_list)
|
69
|
+
if min_port % 2 != 0
|
70
|
+
min_port += 1
|
71
|
+
end
|
72
|
+
|
73
|
+
if max_port % 2 != 0
|
74
|
+
max_port += 1
|
75
|
+
end
|
76
|
+
|
77
|
+
avaliable_ports = []
|
78
|
+
reserved_ports = []
|
79
|
+
|
80
|
+
# Gather ports requested in JSON config
|
81
|
+
for i in 0...avd_scheme_list.length
|
82
|
+
avd_scheme = avd_scheme_list[i]
|
83
|
+
unless avd_scheme.launch_avd_port.eql? ""
|
84
|
+
reserved_ports << avd_scheme.launch_avd_port
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Find next open port which wasn't reserved in JSON config
|
89
|
+
port = min_port
|
90
|
+
for i in 0...avd_scheme_list.length
|
91
|
+
|
92
|
+
while port < max_port do
|
93
|
+
if !system("lsof -i:#{port}", out: '/dev/null')
|
94
|
+
|
95
|
+
is_port_reserved = false
|
96
|
+
for j in 0...reserved_ports.length
|
97
|
+
if reserved_ports[j].eql?(port.to_s)
|
98
|
+
is_port_reserved = true
|
99
|
+
break
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
if is_port_reserved
|
104
|
+
port = port + 2
|
105
|
+
break
|
106
|
+
end
|
107
|
+
|
108
|
+
avaliable_ports << port
|
109
|
+
port = port + 2
|
110
|
+
break
|
111
|
+
else
|
112
|
+
port = port + 2
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
return avaliable_ports
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.read_avd_setup(params)
|
121
|
+
if File.exists?(File.expand_path("#{params[:AVD_setup_path]}"))
|
122
|
+
file = File.open(File.expand_path("#{params[:AVD_setup_path]}"), "rb")
|
123
|
+
json = file.read
|
124
|
+
file.close
|
125
|
+
return json
|
126
|
+
else
|
127
|
+
return nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.check_avd_fields(avd_scheme)
|
132
|
+
errors = []
|
133
|
+
|
134
|
+
if avd_scheme.avd_name.nil?
|
135
|
+
errors.push("avd_name not found")
|
136
|
+
end
|
137
|
+
if avd_scheme.create_avd_package.nil?
|
138
|
+
errors.push("create_avd_package not found")
|
139
|
+
end
|
140
|
+
if avd_scheme.create_avd_device.nil?
|
141
|
+
errors.push("create_avd_device not found")
|
142
|
+
end
|
143
|
+
if avd_scheme.create_avd_tag.nil?
|
144
|
+
errors.push("create_avd_tag not found")
|
145
|
+
end
|
146
|
+
if avd_scheme.create_avd_abi.nil?
|
147
|
+
errors.push("create_avd_abi not found")
|
148
|
+
end
|
149
|
+
if avd_scheme.create_avd_hardware_config_filepath.nil?
|
150
|
+
errors.push("create_avd_hardware_config_filepath not found")
|
151
|
+
end
|
152
|
+
if avd_scheme.launch_avd_snapshot_filepath.nil?
|
153
|
+
errors.push("launch_avd_snapshot_filepath not found")
|
154
|
+
end
|
155
|
+
if avd_scheme.launch_avd_launch_binary_name.nil?
|
156
|
+
errors.push("launch_avd_launch_binary_name not found")
|
157
|
+
end
|
158
|
+
if avd_scheme.launch_avd_port.nil?
|
159
|
+
errors.push("launch_avd_port not found")
|
160
|
+
end
|
161
|
+
if avd_scheme.launch_avd_additional_options.nil?
|
162
|
+
errors.push("launch_avd_additional_options not found")
|
163
|
+
end
|
164
|
+
return errors
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.throw_error(message)
|
168
|
+
UI.message("Error: ".red + message.red)
|
169
|
+
raise Exception, "Lane was stopped by plugin"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fastlane-plugin-automated_test_emulator_run_xing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Hartwich
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-09-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: fastlane
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.98.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.98.0
|
97
|
+
description:
|
98
|
+
email: hartwich.daniel@gmail.com
|
99
|
+
executables: []
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- LICENSE
|
104
|
+
- README.md
|
105
|
+
- lib/fastlane/plugin/automated_test_emulator_run_xing.rb
|
106
|
+
- lib/fastlane/plugin/automated_test_emulator_run_xing/actions/automated_test_emulator_run_xing_action.rb
|
107
|
+
- lib/fastlane/plugin/automated_test_emulator_run_xing/factory/adb_controller_factory.rb
|
108
|
+
- lib/fastlane/plugin/automated_test_emulator_run_xing/factory/avd_controller_factory.rb
|
109
|
+
- lib/fastlane/plugin/automated_test_emulator_run_xing/provider/avd_setup_provider.rb
|
110
|
+
- lib/fastlane/plugin/automated_test_emulator_run_xing/version.rb
|
111
|
+
homepage: https://github.com/dhartwich1991/fastlane-plugin-automated-test-emulator-run
|
112
|
+
licenses:
|
113
|
+
- MIT
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.5.1
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: Starts n AVDs based on JSON file config. AVDs are created and configured
|
135
|
+
according to user liking before instrumentation test process (started either via
|
136
|
+
shell command or gradle) and killed/deleted after test process finishes.
|
137
|
+
test_files: []
|