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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: c249656e07f06e0277ef3bcb2cf2a7ab407b6147207d2e564e89eb8714b7520f
4
- data.tar.gz: 13bfab11bd241d2c6b0af14ba559ea242ef2a8e203ba3f6ffa3e1bd7dc7f54a3
2
+ SHA1:
3
+ metadata.gz: 1e9c7988df5dfcedbb4dcdbf9806393cbccbc52a
4
+ data.tar.gz: 7edad8804eb4b5dba79f1f72d4beb3987886d7ff
5
5
  SHA512:
6
- metadata.gz: d8929c2e8b8e406b8196e130766be14fde6c91a505ab3ea626a64aa332fd8f4739967700d2771f8abe1509a6d3fd01d5ad7a21411665259c97ebd5e316cba8ae
7
- data.tar.gz: ae9311e60e7402761a1287d560b3093d09e4511d790989c1b13fd1c6c9f4e4d05117b7d2b1ab5d7131eb26e8a3681d4872e6cb68a1c420eec88bd8f0b5d1ed40
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)
@@ -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, wanted, filter, false, 5, start_timeout)
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
- true,
53
- 30,
54
- session)
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, wanted, filter, daemon_mode, delay, timeout)
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.filterReadyToConnect
75
- stf_devices = stf_devices.byFilter(filter) if filter
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.asConnectUrlList
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 == 0
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.byFilter(filter) if filter
103
- connected = devices & stf_devices.asConnectUrlList
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
- connected.reject {|url| url.to_s.empty?}.each do |url|
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.byFilter options[:byFilter] if options[:byFilter]
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
- connected_devices = devices()
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
@@ -8,7 +8,33 @@ module Stf
8
8
  getKeysNextLevel('', self)
9
9
  end
10
10
 
11
- def checkFilter(filter)
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 byFilter(filter)
15
- filter ? select {|d| d.checkFilter(filter)} : Array.new
14
+ def by_filter(filter)
15
+ filter ? select {|d| d.checkFilter?(filter)} : []
16
16
  end
17
17
 
18
- def exceptFilter(filter)
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 filterReadyToConnect
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
- select {|d| d.ready == true && d.present == true && d.usage.nil? && d.status == 3 }
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 asConnectUrlList
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
@@ -1,3 +1,3 @@
1
1
  module Stf
2
- VERSION = '0.3.0.rc10'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -7,7 +7,7 @@ module Stf
7
7
 
8
8
  extend self
9
9
 
10
- program_desc 'Smartphone Test Lab client'
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.rc10
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: 2018-10-31 00:00:00.000000000 Z
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: 1.3.1
235
+ version: '0'
235
236
  requirements: []
236
237
  rubyforge_project:
237
- rubygems_version: 2.7.7
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