stf-client 0.3.0.rc10 → 0.3.0
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.
- checksums.yaml +5 -5
- data/lib/di.rb +5 -0
- data/lib/stf/client.rb +5 -0
- data/lib/stf/interactor/add_adb_public_key.rb +20 -0
- data/lib/stf/interactor/start_debug_session_interactor.rb +62 -24
- data/lib/stf/interactor/stop_all_debug_sessions_interactor.rb +2 -7
- data/lib/stf/model/device.rb +27 -1
- data/lib/stf/model/device_list.rb +29 -8
- data/lib/stf/version.rb +1 -1
- data/lib/stf/view/cli.rb +18 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1e9c7988df5dfcedbb4dcdbf9806393cbccbc52a
|
4
|
+
data.tar.gz: 7edad8804eb4b5dba79f1f72d4beb3987886d7ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31ae93d7103a8646ea1bf546d0e5e8b0031f22fb97795497f6e168d7e3cb65f9efcab778ede8519fbd387574d313b94a86df0b6ad0ee072b2c550191f4679ef5
|
7
|
+
data.tar.gz: a1be4ebb8e2a8cdc6d4ea6cb1c4c721c815c303a9d8eef8e80724e0f38810ba8f7e027880785681962fb3d661ff24451f965c4a486ca9ab5bca5acf85f170426
|
data/lib/di.rb
CHANGED
@@ -9,6 +9,7 @@ require 'stf/interactor/stop_all_debug_sessions_interactor'
|
|
9
9
|
require 'stf/interactor/remove_all_user_devices_interactor'
|
10
10
|
require 'stf/interactor/get_keys_interactor'
|
11
11
|
require 'stf/interactor/get_values_interactor'
|
12
|
+
require 'stf/interactor/add_adb_public_key'
|
12
13
|
require 'stf/validate/uri_validator'
|
13
14
|
|
14
15
|
class DI
|
@@ -64,6 +65,10 @@ class DI
|
|
64
65
|
c.register(:uri_validator,
|
65
66
|
-> {Stf::URIValidator.new},
|
66
67
|
memoize: true)
|
68
|
+
|
69
|
+
c.register(:add_adb_public_key_interactor,
|
70
|
+
-> {Stf::AddAdbPublicKeyInteractor.new},
|
71
|
+
memoize: true)
|
67
72
|
end
|
68
73
|
|
69
74
|
def [](what)
|
data/lib/stf/client.rb
CHANGED
@@ -54,6 +54,11 @@ module Stf
|
|
54
54
|
return response.success
|
55
55
|
end
|
56
56
|
|
57
|
+
def add_adb_public_key(adb_public_key)
|
58
|
+
response = execute '/api/v1/user/adbPublicKeys', Net::HTTP::Post, { publickey: adb_public_key }.to_json
|
59
|
+
return response.success
|
60
|
+
end
|
61
|
+
|
57
62
|
private
|
58
63
|
|
59
64
|
def execute(relative_url, type, body='')
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'di'
|
2
|
+
|
3
|
+
require 'stf/client'
|
4
|
+
require 'stf/log/log'
|
5
|
+
|
6
|
+
module Stf
|
7
|
+
class AddAdbPublicKeyInteractor
|
8
|
+
include Log
|
9
|
+
|
10
|
+
def execute(adb_public_key_location)
|
11
|
+
public_key = File.open(adb_public_key_location, 'rb', &:read)
|
12
|
+
success = DI[:stf].add_adb_public_key public_key
|
13
|
+
if success
|
14
|
+
logger.info "adb public key from '#{adb_public_key_location}' has been added"
|
15
|
+
elsif logger.error "Can't add public key from '#{adb_public_key_location}'"
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -17,18 +17,23 @@ module Stf
|
|
17
17
|
max_n = opts[:n].to_i > 0 ? opts[:n].to_i : 1
|
18
18
|
start_timeout = opts[:starttime].to_i > 0 ? opts[:starttime].to_i : 120
|
19
19
|
session = opts[:worktime].to_i > 0 ? opts[:session].to_i : 10800
|
20
|
-
min_n = opts[:min].to_s.empty? ? (max_n + 1) / 2 : opts[:min].to_i
|
20
|
+
min_n = opts[:min].to_s.empty? ? (max_n + 1) / 2 : [opts[:min].to_i, max_n].min
|
21
|
+
healthcheck = opts[:health]
|
22
|
+
force_filter = opts[:forcefilter]
|
21
23
|
|
22
24
|
DI[:demonizer].kill unless opts[:nokill]
|
23
25
|
|
24
|
-
if filter
|
25
|
-
DI[:stop_all_debug_sessions_interactor].execute(exceptFilter: filter)
|
26
|
-
end
|
27
|
-
|
28
26
|
wanted = nodaemon_flag ? max_n : min_n
|
29
27
|
|
30
28
|
begin
|
31
|
-
connect_loop(all_flag
|
29
|
+
connect_loop(all_flag: all_flag,
|
30
|
+
wanted: wanted,
|
31
|
+
filter: filter,
|
32
|
+
force_filter: force_filter,
|
33
|
+
healthcheck: healthcheck,
|
34
|
+
delay: 5,
|
35
|
+
timeout: start_timeout)
|
36
|
+
|
32
37
|
rescue SignalException => e
|
33
38
|
logger.info "Caught signal \"#{e.message}\""
|
34
39
|
DI[:stop_all_debug_sessions_interactor].execute
|
@@ -46,12 +51,14 @@ module Stf
|
|
46
51
|
|
47
52
|
# will be daemon here
|
48
53
|
DI[:demonizer].run do
|
49
|
-
connect_loop(all_flag,
|
50
|
-
max_n,
|
51
|
-
filter,
|
52
|
-
|
53
|
-
|
54
|
-
|
54
|
+
connect_loop(all_flag: all_flag,
|
55
|
+
wanted: max_n,
|
56
|
+
filter: filter,
|
57
|
+
force_filter: force_filter,
|
58
|
+
healthcheck: healthcheck,
|
59
|
+
daemon_mode: true,
|
60
|
+
delay: 30,
|
61
|
+
timeout: session)
|
55
62
|
|
56
63
|
DI[:stop_all_debug_sessions_interactor].execute(byFilter: filter, nokill: true)
|
57
64
|
end
|
@@ -59,29 +66,39 @@ module Stf
|
|
59
66
|
return true
|
60
67
|
end
|
61
68
|
|
62
|
-
def connect_loop(all_flag
|
69
|
+
def connect_loop(all_flag: false,
|
70
|
+
wanted: 1,
|
71
|
+
|
72
|
+
filter: nil,
|
73
|
+
force_filter: false,
|
74
|
+
healthcheck: nil,
|
75
|
+
|
76
|
+
daemon_mode: false,
|
77
|
+
delay: 5,
|
78
|
+
timeout: 120)
|
63
79
|
finish_time = Time.now + timeout
|
64
80
|
one_time_mode = !daemon_mode
|
65
81
|
|
66
82
|
while true do
|
67
|
-
cleanup_disconnected_devices(filter)
|
83
|
+
cleanup_disconnected_devices(filter, force_filter, healthcheck)
|
68
84
|
|
69
85
|
if one_time_mode && Time.now > finish_time
|
70
86
|
raise "Connect loop timeout reached"
|
71
87
|
end
|
72
88
|
|
73
89
|
all_devices = DeviceList.new(DI[:stf].get_devices)
|
74
|
-
stf_devices = all_devices.
|
75
|
-
stf_devices = stf_devices.
|
90
|
+
stf_devices = all_devices.select_ready_to_connect
|
91
|
+
stf_devices = stf_devices.by_filter(filter) if filter
|
92
|
+
stf_devices = stf_devices.select_healthy_for_connect(healthcheck) if healthcheck
|
76
93
|
|
77
94
|
if all_flag
|
78
95
|
to_connect = stf_devices.size
|
79
96
|
else
|
80
|
-
connected = devices & all_devices.
|
97
|
+
connected = devices & all_devices.as_connect_url_list
|
81
98
|
to_connect = wanted - connected.size
|
82
99
|
end
|
83
100
|
|
84
|
-
return if one_time_mode && to_connect
|
101
|
+
return if one_time_mode && to_connect <= 0
|
85
102
|
|
86
103
|
if to_connect > 0
|
87
104
|
if stf_devices.empty?
|
@@ -99,17 +116,38 @@ module Stf
|
|
99
116
|
|
100
117
|
def count_connected_devices(filter)
|
101
118
|
stf_devices = DeviceList.new(DI[:stf].get_user_devices)
|
102
|
-
stf_devices = stf_devices.
|
103
|
-
connected = devices & stf_devices.
|
119
|
+
stf_devices = stf_devices.by_filter(filter) if filter
|
120
|
+
connected = devices & stf_devices.as_connect_url_list
|
104
121
|
connected.size
|
105
122
|
end
|
106
123
|
|
107
|
-
def cleanup_disconnected_devices(filter)
|
124
|
+
def cleanup_disconnected_devices(filter, force_filter, healthcheck)
|
125
|
+
to_disconnect = []
|
108
126
|
stf_devices = DeviceList.new(DI[:stf].get_user_devices)
|
109
|
-
stf_devices = stf_devices.byFilter(filter) if filter
|
110
|
-
connected = stf_devices.asConnectUrlList - devices
|
111
127
|
|
112
|
-
|
128
|
+
if filter && force_filter
|
129
|
+
disconnect_because_filter = stf_devices.except_filter(filter).as_connect_url_list
|
130
|
+
unless disconnect_because_filter.empty?
|
131
|
+
logger.info 'will be disconnected by filter: ' + disconnect_because_filter.join(',')
|
132
|
+
to_disconnect += disconnect_because_filter
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
if healthcheck
|
137
|
+
disconnect_by_health = stf_devices.select_not_healthy(healthcheck).as_connect_url_list
|
138
|
+
unless disconnect_by_health.empty?
|
139
|
+
logger.info 'will be disconnected by health check: ' + disconnect_by_health.join(',')
|
140
|
+
to_disconnect += disconnect_by_health
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
dead_persons = stf_devices.as_connect_url_list - devices
|
145
|
+
unless dead_persons.empty?
|
146
|
+
logger.info 'will be disconnected because not present locally: ' + dead_persons.join(',')
|
147
|
+
to_disconnect += dead_persons
|
148
|
+
end
|
149
|
+
|
150
|
+
to_disconnect.reject {|url| url.to_s.empty?}.uniq.each do |url|
|
113
151
|
logger.info 'Cleanup the device ' + url.to_s
|
114
152
|
DI[:stop_debug_session_interactor].execute(url)
|
115
153
|
end
|
@@ -12,19 +12,14 @@ module Stf
|
|
12
12
|
include ADB
|
13
13
|
|
14
14
|
# byFilter:
|
15
|
-
# exceptFilter:
|
16
15
|
def execute(options = {})
|
17
16
|
DI[:demonizer].kill unless options[:nokill]
|
18
17
|
|
19
18
|
stf_devices = DeviceList.new(DI[:stf].get_user_devices)
|
20
19
|
|
21
|
-
stf_devices = stf_devices.
|
22
|
-
stf_devices = stf_devices.exceptFilter options[:exceptFilter] if options[:exceptFilter]
|
20
|
+
stf_devices = stf_devices.by_filter options[:byFilter] if options[:byFilter]
|
23
21
|
|
24
|
-
|
25
|
-
remote_devices = stf_devices.asConnectUrlList
|
26
|
-
|
27
|
-
pending_disconnect = connected_devices & remote_devices
|
22
|
+
pending_disconnect = stf_devices.as_connect_url_list
|
28
23
|
|
29
24
|
pending_disconnect.each {|d| DI[:stop_debug_session_interactor].execute d}
|
30
25
|
end
|
data/lib/stf/model/device.rb
CHANGED
@@ -8,7 +8,33 @@ module Stf
|
|
8
8
|
getKeysNextLevel('', self)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
# more pessimistic decision
|
12
|
+
def healthy_for_connect?(pattern)
|
13
|
+
return true if pattern.nil?
|
14
|
+
health = healthy?(pattern)
|
15
|
+
ppp = pattern.split(',')
|
16
|
+
ppp.each do |p|
|
17
|
+
health &&= getValue('battery.temp').to_i < 30 if ['t', 'temp', 'temperature'].include? p
|
18
|
+
health &&= getValue('battery.level').to_f > 30.0 if ['b', 'batt', 'battery'].include? p
|
19
|
+
end
|
20
|
+
health
|
21
|
+
end
|
22
|
+
|
23
|
+
def healthy?(pattern)
|
24
|
+
return true if pattern.nil?
|
25
|
+
ppp = pattern.split(',')
|
26
|
+
health = true
|
27
|
+
ppp.each do |p|
|
28
|
+
health &&= getValue('battery.temp').to_i < 32 if ['t', 'temp', 'temperature'].include? p
|
29
|
+
health &&= getValue('battery.level').to_f > 20.0 if ['b', 'batt', 'battery'].include? p
|
30
|
+
health &&= getValue('network.connected') if ['n', 'net', 'network'].include? p
|
31
|
+
health &&= getValue('network.type') == 'VPN' if ['vpn'].include? p
|
32
|
+
health &&= getValue('network.type') == 'WIFI' if ['wifi'].include? p
|
33
|
+
end
|
34
|
+
health
|
35
|
+
end
|
36
|
+
|
37
|
+
def checkFilter?(filter)
|
12
38
|
return true if filter.nil?
|
13
39
|
key, value = filter.split(':', 2)
|
14
40
|
getValue(key) == value
|
@@ -11,15 +11,28 @@ module Stf
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
filter ? select {|d| d.checkFilter(filter)} :
|
14
|
+
def by_filter(filter)
|
15
|
+
filter ? select {|d| d.checkFilter?(filter)} : []
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
filter ? reject {|d| d.checkFilter(filter)} : this
|
18
|
+
def except_filter(filter)
|
19
|
+
filter ? reject {|d| d.checkFilter?(filter)} : this
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def select_healthy(pattern)
|
23
|
+
pattern ? select { |d| d.healthy?(pattern) } : this
|
24
|
+
end
|
25
|
+
|
26
|
+
# more pessimistic than healthy()
|
27
|
+
def select_healthy_for_connect(pattern)
|
28
|
+
pattern ? select { |d| d.healthy_for_connect?(pattern) } : this
|
29
|
+
end
|
30
|
+
|
31
|
+
def select_not_healthy(pattern)
|
32
|
+
pattern ? reject { |d| d.healthy?(pattern) } : []
|
33
|
+
end
|
34
|
+
|
35
|
+
def select_ready_to_connect
|
23
36
|
# https://github.com/openstf/stf/blob/93d9d7fe859bb7ca71669f375d841d94fa47d751/lib/wire/wire.proto#L170
|
24
37
|
# enum DeviceStatus {
|
25
38
|
# OFFLINE = 1;
|
@@ -28,11 +41,19 @@ module Stf
|
|
28
41
|
# CONNECTING = 4;
|
29
42
|
# AUTHORIZING = 5;
|
30
43
|
# }
|
31
|
-
|
44
|
+
#
|
45
|
+
# https://github.com/openstf/stf/blob/93d9d7fe859bb7ca71669f375d841d94fa47d751/res/app/components/stf/device/enhance-device/enhance-device-service.js
|
46
|
+
select {|d|
|
47
|
+
d.present == true &&
|
48
|
+
d.status == 3 &&
|
49
|
+
d.ready == true &&
|
50
|
+
d.using == false &&
|
51
|
+
d.owner.nil?
|
52
|
+
}
|
32
53
|
end
|
33
54
|
|
34
|
-
def
|
35
|
-
@devices.map {|d| d.remoteConnectUrl}
|
55
|
+
def as_connect_url_list
|
56
|
+
@devices.map {|d| d.remoteConnectUrl}.reject { |c| c.nil? || c.empty? }
|
36
57
|
end
|
37
58
|
|
38
59
|
def select
|
data/lib/stf/version.rb
CHANGED
data/lib/stf/view/cli.rb
CHANGED
@@ -7,7 +7,7 @@ module Stf
|
|
7
7
|
|
8
8
|
extend self
|
9
9
|
|
10
|
-
program_desc
|
10
|
+
program_desc "Smartphone Test Lab client (version #{Stf::VERSION})"
|
11
11
|
|
12
12
|
desc 'Be verbose'
|
13
13
|
switch [:v, :verbose]
|
@@ -50,6 +50,10 @@ module Stf
|
|
50
50
|
c.flag [:min]
|
51
51
|
c.desc 'Filter key:value for devices'
|
52
52
|
c.flag [:f, :filter]
|
53
|
+
c.desc 'Force filter check for connected devices'
|
54
|
+
c.switch [:forcefilter, :ff]
|
55
|
+
c.desc 'Check selected health parameters, could be any of the: battery,temperature,network,vpn,wifi'
|
56
|
+
c.flag [:health]
|
53
57
|
c.desc 'Maximum session duration in seconds, 10800 (3h) by default'
|
54
58
|
c.flag [:session]
|
55
59
|
c.desc 'Maximum time to connect minimal quantity of devices in seconds, 120 (2m) by default'
|
@@ -98,6 +102,19 @@ module Stf
|
|
98
102
|
c.action {DI[:remove_all_user_devices_interactor].execute}
|
99
103
|
end
|
100
104
|
|
105
|
+
desc 'Add adb public key into STF'
|
106
|
+
command :trustme do |c|
|
107
|
+
c.desc 'Location of adb public key'
|
108
|
+
c.flag [:k, :adb_public_key_location]
|
109
|
+
c.default_value '~/.android/adbkey.pub'
|
110
|
+
|
111
|
+
c.action do |_, options, _|
|
112
|
+
filename = File.expand_path(options[:adb_public_key_location])
|
113
|
+
exit_now!("File does not exist: '#{options[:adb_public_key_location]}'") unless File.exist? filename
|
114
|
+
DI[:add_adb_public_key_interactor].execute(options[:adb_public_key_location])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
101
118
|
exit run(ARGV)
|
102
119
|
end
|
103
120
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stf-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.0
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Malinskiy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gli
|
@@ -199,6 +199,7 @@ files:
|
|
199
199
|
- lib/di.rb
|
200
200
|
- lib/stf.rb
|
201
201
|
- lib/stf/client.rb
|
202
|
+
- lib/stf/interactor/add_adb_public_key.rb
|
202
203
|
- lib/stf/interactor/get_keys_interactor.rb
|
203
204
|
- lib/stf/interactor/get_values_interactor.rb
|
204
205
|
- lib/stf/interactor/remove_all_user_devices_interactor.rb
|
@@ -229,12 +230,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
229
230
|
version: '0'
|
230
231
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
231
232
|
requirements:
|
232
|
-
- - "
|
233
|
+
- - ">="
|
233
234
|
- !ruby/object:Gem::Version
|
234
|
-
version:
|
235
|
+
version: '0'
|
235
236
|
requirements: []
|
236
237
|
rubyforge_project:
|
237
|
-
rubygems_version: 2.
|
238
|
+
rubygems_version: 2.6.13
|
238
239
|
signing_key:
|
239
240
|
specification_version: 4
|
240
241
|
summary: Request devices from Smartphone Test Farm for adb connection
|