bugsnag-maze-runner 7.22.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/bugsnag-print-load-paths +6 -0
- data/bin/download-logs +74 -0
- data/bin/maze-runner +174 -0
- data/bin/upload-app +56 -0
- data/lib/features/scripts/await-android-emulator.sh +11 -0
- data/lib/features/scripts/clear-android-app-data.sh +8 -0
- data/lib/features/scripts/force-stop-android-app.sh +8 -0
- data/lib/features/scripts/install-android-app.sh +15 -0
- data/lib/features/scripts/launch-android-app.sh +38 -0
- data/lib/features/scripts/launch-android-emulator.sh +15 -0
- data/lib/features/steps/android_steps.rb +51 -0
- data/lib/features/steps/app_automator_steps.rb +228 -0
- data/lib/features/steps/aws_sam_steps.rb +212 -0
- data/lib/features/steps/breadcrumb_steps.rb +80 -0
- data/lib/features/steps/browser_steps.rb +93 -0
- data/lib/features/steps/build_api_steps.rb +25 -0
- data/lib/features/steps/document_server_steps.rb +7 -0
- data/lib/features/steps/error_reporting_steps.rb +358 -0
- data/lib/features/steps/feature_flag_steps.rb +190 -0
- data/lib/features/steps/header_steps.rb +72 -0
- data/lib/features/steps/log_steps.rb +29 -0
- data/lib/features/steps/multipart_request_steps.rb +142 -0
- data/lib/features/steps/network_steps.rb +135 -0
- data/lib/features/steps/payload_steps.rb +257 -0
- data/lib/features/steps/proxy_steps.rb +34 -0
- data/lib/features/steps/query_parameter_steps.rb +31 -0
- data/lib/features/steps/request_assertion_steps.rb +186 -0
- data/lib/features/steps/runner_steps.rb +428 -0
- data/lib/features/steps/session_tracking_steps.rb +116 -0
- data/lib/features/steps/trace_steps.rb +206 -0
- data/lib/features/steps/value_steps.rb +119 -0
- data/lib/features/support/env.rb +7 -0
- data/lib/features/support/internal_hooks.rb +207 -0
- data/lib/maze/api/appium/file_manager.rb +29 -0
- data/lib/maze/appium_server.rb +112 -0
- data/lib/maze/assertions/request_set_assertions.rb +97 -0
- data/lib/maze/aws/sam.rb +112 -0
- data/lib/maze/aws_public_ip.rb +53 -0
- data/lib/maze/bugsnag_config.rb +42 -0
- data/lib/maze/checks/assert_check.rb +69 -0
- data/lib/maze/checks/noop_check.rb +34 -0
- data/lib/maze/client/appium/base_client.rb +131 -0
- data/lib/maze/client/appium/bb_client.rb +102 -0
- data/lib/maze/client/appium/bb_devices.rb +127 -0
- data/lib/maze/client/appium/bs_client.rb +91 -0
- data/lib/maze/client/appium/bs_devices.rb +141 -0
- data/lib/maze/client/appium/bs_legacy_client.rb +31 -0
- data/lib/maze/client/appium/local_client.rb +67 -0
- data/lib/maze/client/appium.rb +23 -0
- data/lib/maze/client/bb_api_client.rb +102 -0
- data/lib/maze/client/bb_client_utils.rb +181 -0
- data/lib/maze/client/bs_client_utils.rb +168 -0
- data/lib/maze/client/selenium/base_client.rb +15 -0
- data/lib/maze/client/selenium/bb_browsers.yml +188 -0
- data/lib/maze/client/selenium/bb_client.rb +38 -0
- data/lib/maze/client/selenium/bs_browsers.yml +257 -0
- data/lib/maze/client/selenium/bs_client.rb +89 -0
- data/lib/maze/client/selenium/local_client.rb +16 -0
- data/lib/maze/client/selenium.rb +16 -0
- data/lib/maze/compare.rb +161 -0
- data/lib/maze/configuration.rb +182 -0
- data/lib/maze/docker.rb +147 -0
- data/lib/maze/document_server.rb +46 -0
- data/lib/maze/driver/appium.rb +198 -0
- data/lib/maze/driver/browser.rb +124 -0
- data/lib/maze/errors.rb +52 -0
- data/lib/maze/generator.rb +55 -0
- data/lib/maze/helper.rb +122 -0
- data/lib/maze/hooks/appium_hooks.rb +55 -0
- data/lib/maze/hooks/browser_hooks.rb +15 -0
- data/lib/maze/hooks/command_hooks.rb +9 -0
- data/lib/maze/hooks/error_code_hook.rb +49 -0
- data/lib/maze/hooks/hooks.rb +61 -0
- data/lib/maze/http_request.rb +21 -0
- data/lib/maze/interactive_cli.rb +173 -0
- data/lib/maze/logger.rb +86 -0
- data/lib/maze/macos_utils.rb +14 -0
- data/lib/maze/maze_output.rb +88 -0
- data/lib/maze/network.rb +49 -0
- data/lib/maze/option/parser.rb +240 -0
- data/lib/maze/option/processor.rb +130 -0
- data/lib/maze/option/validator.rb +155 -0
- data/lib/maze/option.rb +62 -0
- data/lib/maze/plugins/bugsnag_reporting_plugin.rb +49 -0
- data/lib/maze/plugins/cucumber_report_plugin.rb +101 -0
- data/lib/maze/plugins/error_code_plugin.rb +21 -0
- data/lib/maze/plugins/global_retry_plugin.rb +38 -0
- data/lib/maze/proxy.rb +114 -0
- data/lib/maze/request_list.rb +87 -0
- data/lib/maze/request_repeater.rb +49 -0
- data/lib/maze/retry_handler.rb +67 -0
- data/lib/maze/runner.rb +149 -0
- data/lib/maze/schemas/OtelTraceSchema.json +390 -0
- data/lib/maze/schemas/trace_schema.rb +7 -0
- data/lib/maze/schemas/trace_validator.rb +98 -0
- data/lib/maze/server.rb +251 -0
- data/lib/maze/servlets/base_servlet.rb +27 -0
- data/lib/maze/servlets/command_servlet.rb +47 -0
- data/lib/maze/servlets/log_servlet.rb +64 -0
- data/lib/maze/servlets/reflective_servlet.rb +70 -0
- data/lib/maze/servlets/servlet.rb +199 -0
- data/lib/maze/servlets/temp.rb +0 -0
- data/lib/maze/servlets/trace_servlet.rb +13 -0
- data/lib/maze/store.rb +15 -0
- data/lib/maze/terminating_server.rb +129 -0
- data/lib/maze/timers.rb +51 -0
- data/lib/maze/wait.rb +35 -0
- data/lib/maze.rb +27 -0
- data/lib/utils/deep_merge.rb +17 -0
- data/lib/utils/selenium_money_patch.rb +17 -0
- metadata +451 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
module Maze
|
6
|
+
# Receives and terminates network connections without reading any data
|
7
|
+
class TerminatingServer
|
8
|
+
CONTINUE_RESPONSE = "HTTP/1.1 100 CONTINUE\n\r"
|
9
|
+
BAD_REQUEST_RESPONSE = "HTTP/1.1 400 BAD REQUEST\n\r"
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# Starts the socket accept loop in a separate thread
|
14
|
+
def start
|
15
|
+
# Only run a single server thread
|
16
|
+
return if running?
|
17
|
+
|
18
|
+
attempts = 0
|
19
|
+
loop do
|
20
|
+
|
21
|
+
@thread = Thread.new do
|
22
|
+
# Reset the received count
|
23
|
+
@received_requests = 0
|
24
|
+
|
25
|
+
Socket.tcp_server_loop(Maze.config.null_port) {|socket, _client_addrinfo|
|
26
|
+
$logger.info 'Terminating server received request'
|
27
|
+
@received_requests += 1
|
28
|
+
headers = receive_headers(socket)
|
29
|
+
|
30
|
+
body_length = headers['Content-Length']
|
31
|
+
receive_data(socket, body_length) unless body_length.nil?
|
32
|
+
|
33
|
+
end_connection(socket)
|
34
|
+
}
|
35
|
+
rescue StandardError => e
|
36
|
+
$logger.warn "Terminating server error: #{e.message}"
|
37
|
+
end
|
38
|
+
|
39
|
+
break if running?
|
40
|
+
|
41
|
+
# Bail out after 3 attempts
|
42
|
+
attempts += 1
|
43
|
+
raise 'Too many failed attempts to start terminating server' if attempts == 3
|
44
|
+
|
45
|
+
# Failed to start - sleep before retrying
|
46
|
+
$logger.info 'Retrying in 3 seconds'
|
47
|
+
sleep 1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# The maximum string length to be received before disconnecting
|
52
|
+
#
|
53
|
+
# @return [Integer] The string length, defaults to 1MB
|
54
|
+
def max_received_size
|
55
|
+
@max_received_size ||= 1048576
|
56
|
+
end
|
57
|
+
|
58
|
+
# Set the maximum string length to be received before disconnecting
|
59
|
+
#
|
60
|
+
# @param new_max_size [Integer] The new maximum size
|
61
|
+
def max_received_size=(new_max_size)
|
62
|
+
@max_received_size = new_max_size
|
63
|
+
end
|
64
|
+
|
65
|
+
# The response string sent to a connected client
|
66
|
+
#
|
67
|
+
# @return [String] The response string, defaults to "400/BAD REQUEST"
|
68
|
+
def response
|
69
|
+
@response ||= BAD_REQUEST_RESPONSE
|
70
|
+
end
|
71
|
+
|
72
|
+
# Set the response string to an arbitrary value
|
73
|
+
#
|
74
|
+
# @param new_response [String] The new response
|
75
|
+
def response=(new_response)
|
76
|
+
@response = new_response
|
77
|
+
end
|
78
|
+
|
79
|
+
# Resets the response string to "400/BAD REQUEST" and the read size to 1MB
|
80
|
+
def reset_elements
|
81
|
+
@response = BAD_REQUEST_RESPONSE
|
82
|
+
@max_received_size = 1048576
|
83
|
+
end
|
84
|
+
|
85
|
+
# Whether the server thread is running
|
86
|
+
#
|
87
|
+
# @return [Boolean] If the server is running
|
88
|
+
def running?
|
89
|
+
@thread&.alive?
|
90
|
+
end
|
91
|
+
|
92
|
+
# Outputs the amount of times the server has received a connection on the last run
|
93
|
+
def received_request_count
|
94
|
+
@received_requests ||= 0
|
95
|
+
end
|
96
|
+
|
97
|
+
# Stops the socket accept loop if alive
|
98
|
+
def stop
|
99
|
+
@thread&.kill if @thread&.alive?
|
100
|
+
@thread = nil
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def receive_headers(socket)
|
106
|
+
headers = {}
|
107
|
+
while (request = socket.gets) && (request.chomp.length > 0)
|
108
|
+
key, val = request.chomp.split(': ')
|
109
|
+
headers[key] = val
|
110
|
+
$logger.debug "Received #{headers.size} headers"
|
111
|
+
end
|
112
|
+
headers
|
113
|
+
end
|
114
|
+
|
115
|
+
def receive_data(socket, body_length)
|
116
|
+
read_length = body_length.to_i < max_received_size ? body_length.to_i : max_received_size
|
117
|
+
$logger.info "Reading #{read_length} bytes"
|
118
|
+
socket.read(read_length)
|
119
|
+
end
|
120
|
+
|
121
|
+
def end_connection(socket)
|
122
|
+
$logger.info "Responding with: #{response}"
|
123
|
+
# Unlikely to be used, but replicates pipeline response
|
124
|
+
socket.print response
|
125
|
+
socket.close
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/lib/maze/timers.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Maze
|
2
|
+
|
3
|
+
# A simple run/stop timer
|
4
|
+
class Timer
|
5
|
+
attr_accessor :total
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@total = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def time(&block)
|
12
|
+
start = Time.now
|
13
|
+
|
14
|
+
block.call
|
15
|
+
ensure
|
16
|
+
@total += Time.now - start
|
17
|
+
end
|
18
|
+
|
19
|
+
def reset
|
20
|
+
@total = 0
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Stores a collection of timers
|
25
|
+
class Timers
|
26
|
+
def initialize
|
27
|
+
@timers = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def add(name)
|
31
|
+
timer = Timer.new
|
32
|
+
@timers[name] = timer
|
33
|
+
timer
|
34
|
+
end
|
35
|
+
|
36
|
+
def get(name)
|
37
|
+
@timers[name]
|
38
|
+
end
|
39
|
+
|
40
|
+
def size
|
41
|
+
@timers.size
|
42
|
+
end
|
43
|
+
|
44
|
+
def report
|
45
|
+
$logger.info 'Timer totals:'
|
46
|
+
@timers.sort.each do |name, timer|
|
47
|
+
$logger.info " #{name}: #{timer.total}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/maze/wait.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maze
|
4
|
+
# Allows repeated attempts at something, until it is successful or the timeout
|
5
|
+
# is exceed
|
6
|
+
class Wait
|
7
|
+
# @param interval [Numeric] Optional. The time to sleep between attempts
|
8
|
+
# @param timeout [Numeric] The amount of time to spend on attempts before giving up
|
9
|
+
def initialize(interval: 0.1, timeout:)
|
10
|
+
raise "Interval must be greater than zero, got '#{interval}'" unless interval > 0
|
11
|
+
raise "Timeout (#{timeout}) must be greater than interval (#{interval})" unless timeout > interval
|
12
|
+
|
13
|
+
@interval = interval
|
14
|
+
@max_attempts = timeout / interval
|
15
|
+
end
|
16
|
+
|
17
|
+
# Wait until the given block succeeds (returns a truthy value) or the
|
18
|
+
# timeout is exceeded
|
19
|
+
#
|
20
|
+
# @return [Object] The last value returned by the block
|
21
|
+
def until(&block)
|
22
|
+
success = false
|
23
|
+
attempts = 0
|
24
|
+
|
25
|
+
until success || attempts >= @max_attempts do
|
26
|
+
attempts += 1
|
27
|
+
success = block.call
|
28
|
+
|
29
|
+
sleep @interval unless success
|
30
|
+
end
|
31
|
+
|
32
|
+
success
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/maze.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'maze/configuration'
|
4
|
+
require_relative 'maze/hooks/hooks'
|
5
|
+
require_relative 'maze/timers'
|
6
|
+
|
7
|
+
# Glues the various parts of MazeRunner together that need to be accessed globally,
|
8
|
+
# providing an alternative to the proliferation of global variables or singletons.
|
9
|
+
module Maze
|
10
|
+
VERSION = '7.22.1'
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address, :run_uuid
|
14
|
+
|
15
|
+
def config
|
16
|
+
@config ||= Maze::Configuration.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def hooks
|
20
|
+
@hooks ||= Maze::Hooks::Hooks.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def timers
|
24
|
+
@timers ||= Maze::Timers.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Hash
|
2
|
+
def deep_merge!(other_hash, &block)
|
3
|
+
merge!(other_hash) do |key, this_val, other_val|
|
4
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
5
|
+
this_val.deep_merge(other_val, &block)
|
6
|
+
elsif block_given?
|
7
|
+
block.call(key, this_val, other_val)
|
8
|
+
else
|
9
|
+
other_val
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def deep_merge(other_hash, &block)
|
15
|
+
dup.deep_merge!(other_hash, &block)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Log the full response so we see more than just the error code
|
2
|
+
module Selenium
|
3
|
+
module WebDriver
|
4
|
+
module Error
|
5
|
+
class ServerError < StandardError
|
6
|
+
def initialize(response)
|
7
|
+
if response.is_a? String
|
8
|
+
super(response)
|
9
|
+
else
|
10
|
+
$logger.error "Server response: #{response.inspect}"
|
11
|
+
super("status code #{response.code}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end # ServerError
|
15
|
+
end # Error
|
16
|
+
end # WebDriver
|
17
|
+
end # Selenium
|