bugsnag-maze-runner 8.2.0 → 8.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 +4 -4
- data/lib/features/steps/deprecated_steps.rb +8 -0
- data/lib/features/steps/request_assertion_steps.rb +12 -1
- data/lib/features/steps/trace_steps.rb +35 -6
- data/lib/features/support/internal_hooks.rb +11 -1
- data/lib/maze/client/appium/bs_devices.rb +0 -1
- data/lib/maze/client/selenium/bs_browsers.yml +1 -1
- data/lib/maze/schemas/trace_validator.rb +55 -5
- data/lib/maze/schemas/validator.rb +1 -1
- data/lib/maze.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02b1bd719cc437d684670a164059b1db11b6b86e10de81348e1027b74b1a138d
|
4
|
+
data.tar.gz: f5341e638425082222c5ca8462e4e98cce7a00a084351a91e746ebb07fc0d23e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 683441571c5eb37acffc60787acaa1f697b9e20fe5af95ebb45abe52682ac0507b2ee1f4b55bc28ea0de7eb7587c5f829ee12bcde75482a818cee3be34cbafe5
|
7
|
+
data.tar.gz: 8832b0b1684e380449cc3aac2fecf6b2ae47195761a07ac6d1fdc469e6bd176ab89a068726e259dd63f3137af80d57b2542120c8e41b779afe211e75ac4c1470
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# @!group Deprecated steps
|
2
|
+
|
3
|
+
# Waits for a given number of spans to be received, which may be spread across one or more trace requests.
|
4
|
+
#
|
5
|
+
# @step_input span_count [Integer] The number of spans to wait for
|
6
|
+
When('I wait for {int} span(s)') do |span_count|
|
7
|
+
assert_received_spans Maze::Server.list_for('traces'), span_count
|
8
|
+
end
|
@@ -8,7 +8,7 @@ require_relative '../../maze/wait'
|
|
8
8
|
|
9
9
|
# @!group Request assertion steps
|
10
10
|
|
11
|
-
def assert_received_requests(request_count, list, list_name, precise = true)
|
11
|
+
def assert_received_requests(request_count, list, list_name, precise = true, maximum = nil)
|
12
12
|
timeout = Maze.config.receive_requests_wait
|
13
13
|
# Interval set to 0.5s to make it more likely to detect erroneous extra requests,
|
14
14
|
# without impacting overall speed too much
|
@@ -45,6 +45,7 @@ def assert_received_requests(request_count, list, list_name, precise = true)
|
|
45
45
|
Maze.check.equal(request_count, list.size_remaining, "#{list.size_remaining} #{list_name} received")
|
46
46
|
else
|
47
47
|
Maze.check.operator(request_count, :<=, list.size_remaining, "#{list.size_remaining} #{list_name} received")
|
48
|
+
Maze.check.operator(maximum, :>=, list.size_remaining, "#{list.size_remaining} #{list_name} received") unless maximum.nil?
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
@@ -102,6 +103,16 @@ Then('I have received at least {int} {request_type}') do |min_received, request_
|
|
102
103
|
Maze.check.operator(list.size_remaining, :>=, min_received, "Actually received #{list.size_remaining} #{request_type} requests")
|
103
104
|
end
|
104
105
|
|
106
|
+
# Verify that an amount of requests within a range have been received
|
107
|
+
#
|
108
|
+
# @step_input min_received [Integer] The minimum amount of requests required to pass
|
109
|
+
# @step_input max_received [Integer] The maximum amount of requests before failure
|
110
|
+
# @step_input request_type [String] The type of request (error, session, build, etc)
|
111
|
+
Then('I wait to receive between {int} and {int} {request_type}') do |min_received, max_received, request_type|
|
112
|
+
list = Maze::Server.list_for(request_type)
|
113
|
+
assert_received_requests min_received, list, request_type, false, max_received
|
114
|
+
end
|
115
|
+
|
105
116
|
# Assert that the test Server hasn't received any requests - of a specific, or any, type.
|
106
117
|
#
|
107
118
|
# @step_input request_type [String] The type of request ('error', 'session', 'trace', sampling request', etc)
|
@@ -3,8 +3,25 @@
|
|
3
3
|
# Waits for a given number of spans to be received, which may be spread across one or more trace requests.
|
4
4
|
#
|
5
5
|
# @step_input span_count [Integer] The number of spans to wait for
|
6
|
-
|
7
|
-
|
6
|
+
Then('I wait to receive {int} span(s)') do |span_count|
|
7
|
+
assert_received_span_count Maze::Server.list_for('traces'), span_count
|
8
|
+
end
|
9
|
+
|
10
|
+
# Waits for a minimum number of spans to be received, which may be spread across one or more trace requests.
|
11
|
+
# If more spans than requested are received, this step will still pass.
|
12
|
+
#
|
13
|
+
# @step_input span_min [Integer] The minimum number of spans to wait for
|
14
|
+
Then('I wait to receive at least {int} span(s)') do |span_min|
|
15
|
+
assert_received_minimum_span_count Maze::Server.list_for('traces'), span_min
|
16
|
+
end
|
17
|
+
|
18
|
+
# Waits for a minimum number of spans to be received, which may be spread across one or more trace requests.
|
19
|
+
# If more spans than the maximum requested number of spans are received, this step will fail.
|
20
|
+
#
|
21
|
+
# @step_input span_min [Integer] The minimum number of spans to wait for
|
22
|
+
# @step_input span_max [Integer] The maximum number of spans to receive before failure
|
23
|
+
Then('I wait to receive between {int} and {int} span(s)') do |span_min, span_max|
|
24
|
+
assert_received_ranged_span_count Maze::Server.list_for('traces'), span_min, span_max
|
8
25
|
end
|
9
26
|
|
10
27
|
Then('I should have received no spans') do
|
@@ -227,16 +244,28 @@ def attribute_value_matches?(attribute_value, expected_type, expected_value)
|
|
227
244
|
end
|
228
245
|
end
|
229
246
|
|
230
|
-
def
|
247
|
+
def assert_received_span_count(list, count)
|
248
|
+
assert_received_spans(list, count, count)
|
249
|
+
end
|
250
|
+
|
251
|
+
def assert_received_minimum_span_count(list, minimum)
|
252
|
+
assert_received_spans(list, minimum)
|
253
|
+
end
|
254
|
+
|
255
|
+
def assert_received_ranged_span_count(list, minimum, maximum)
|
256
|
+
assert_received_spans(list, minimum, maximum)
|
257
|
+
end
|
258
|
+
|
259
|
+
def assert_received_spans(list, min_received, max_received = nil)
|
231
260
|
timeout = Maze.config.receive_requests_wait
|
232
261
|
wait = Maze::Wait.new(timeout: timeout)
|
233
262
|
|
234
|
-
received = wait.until { spans_from_request_list(list).size >=
|
263
|
+
received = wait.until { spans_from_request_list(list).size >= min_received }
|
235
264
|
received_count = spans_from_request_list(list).size
|
236
265
|
|
237
266
|
unless received
|
238
267
|
raise Test::Unit::AssertionFailedError.new <<-MESSAGE
|
239
|
-
Expected #{
|
268
|
+
Expected #{min_received} spans but received #{received_count} within the #{timeout}s timeout.
|
240
269
|
This could indicate that:
|
241
270
|
- Bugsnag crashed with a fatal error.
|
242
271
|
- Bugsnag did not make the requests that it should have done.
|
@@ -246,7 +275,7 @@ def assert_received_spans(span_count, list)
|
|
246
275
|
MESSAGE
|
247
276
|
end
|
248
277
|
|
249
|
-
Maze.check.operator(
|
278
|
+
Maze.check.operator(max_received, :>=, received_count, "#{received_count} spans received") if max_received
|
250
279
|
|
251
280
|
Maze::Schemas::Validator.verify_against_schema(list, 'trace')
|
252
281
|
Maze::Schemas::Validator.validate_payload_elements(list, 'trace')
|
@@ -30,12 +30,14 @@ BeforeAll do
|
|
30
30
|
end
|
31
31
|
$logger.info "Running in #{Maze.mode.to_s} mode"
|
32
32
|
|
33
|
-
# Clear out maze_output folder
|
33
|
+
# Clear out maze_output folder and zip
|
34
34
|
maze_output = Dir.glob(File.join(Dir.pwd, 'maze_output', '*'))
|
35
35
|
if Maze.config.file_log && !maze_output.empty?
|
36
36
|
maze_output.each { |path| $logger.info "Clearing contents of #{path}" }
|
37
37
|
FileUtils.rm_rf(maze_output)
|
38
38
|
end
|
39
|
+
maze_output_zip = Dir.glob(File.join(Dir.pwd, 'maze_output.zip'))
|
40
|
+
FileUtils.rm_rf(maze_output_zip)
|
39
41
|
|
40
42
|
# Record the local server starting time
|
41
43
|
Maze.start_time = Time.now.strftime('%Y-%m-%d %H:%M:%S')
|
@@ -222,6 +224,14 @@ end
|
|
222
224
|
|
223
225
|
# After all tests
|
224
226
|
AfterAll do
|
227
|
+
maze_output = File.join(Dir.pwd, 'maze_output')
|
228
|
+
maze_output_zip = File.join(Dir.pwd, 'maze_output.zip')
|
229
|
+
# zip a folder with files and subfolders
|
230
|
+
Zip::File.open(maze_output_zip, Zip::File::CREATE) do |zipfile|
|
231
|
+
Dir["#{maze_output}/**/**"].each do |file|
|
232
|
+
zipfile.add(file.sub(Dir.pwd + '/', ''), file)
|
233
|
+
end
|
234
|
+
end
|
225
235
|
|
226
236
|
metrics = Maze::MetricsProcessor.new(Maze::Server.metrics)
|
227
237
|
metrics.process
|
@@ -108,7 +108,6 @@ module Maze
|
|
108
108
|
add_android 'Samsung Galaxy A8', '7.1', hash # ANDROID_7_1_SAMSUNG_GALAXY_A8
|
109
109
|
add_android 'Samsung Galaxy Note 8', '7.1', hash # ANDROID_7_1_SAMSUNG_GALAXY_NOTE_8
|
110
110
|
add_android 'Samsung Galaxy S8', '7.0', hash # ANDROID_7_0_SAMSUNG_GALAXY_S8
|
111
|
-
add_android 'Samsung Galaxy S8 Plus', '7.0', hash # ANDROID_7_0_SAMSUNG_GALAXY_S8_PLUS
|
112
111
|
|
113
112
|
# Specific iOS devices
|
114
113
|
add_ios 'iPhone 14 Plus', '16.0', hash # IOS_16_0_IPHONE_14_PLUS
|
@@ -5,6 +5,11 @@ require_relative '../helper'
|
|
5
5
|
module Maze
|
6
6
|
module Schemas
|
7
7
|
|
8
|
+
HEX_STRING_16 = '^[A-Fa-f0-9]{16}$'
|
9
|
+
HEX_STRING_32 = '^[A-Fa-f0-9]{32}$'
|
10
|
+
SAMPLING_HEADER_ENTRY = '((1(.0)?|0(\.[0-9]+)?):[0-9]+)'
|
11
|
+
SAMPLING_HEADER = "^#{SAMPLING_HEADER_ENTRY}(;#{SAMPLING_HEADER_ENTRY})*$"
|
12
|
+
|
8
13
|
# Contains a set of pre-defined validations for ensuring traces are correct
|
9
14
|
class TraceValidator
|
10
15
|
|
@@ -15,9 +20,10 @@ module Maze
|
|
15
20
|
|
16
21
|
# Creates the validator
|
17
22
|
#
|
18
|
-
# @param
|
19
|
-
def initialize(
|
20
|
-
@
|
23
|
+
# @param request [Hash] The trace request to validate
|
24
|
+
def initialize(request)
|
25
|
+
@headers = request[:request].header
|
26
|
+
@body = request[:body]
|
21
27
|
@success = nil
|
22
28
|
@errors = []
|
23
29
|
end
|
@@ -26,8 +32,9 @@ module Maze
|
|
26
32
|
def validate
|
27
33
|
@success = true
|
28
34
|
|
29
|
-
|
30
|
-
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.
|
35
|
+
validate_headers
|
36
|
+
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.spanId', HEX_STRING_16)
|
37
|
+
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.traceId', HEX_STRING_32)
|
31
38
|
element_int_in_range('resourceSpans.0.scopeSpans.0.spans.0.kind', 0..5)
|
32
39
|
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.startTimeUnixNano', '^[0-9]+$')
|
33
40
|
regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.endTimeUnixNano', '^[0-9]+$')
|
@@ -40,6 +47,49 @@ module Maze
|
|
40
47
|
)
|
41
48
|
end
|
42
49
|
|
50
|
+
def validate_header(name)
|
51
|
+
value = @headers[name]
|
52
|
+
if value.nil? || value.size > 1
|
53
|
+
@errors << "Expected exactly one value for header #{name}, received #{value || 'nil'}"
|
54
|
+
else
|
55
|
+
yield value[0]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Checks that the required headers are present and correct
|
60
|
+
def validate_headers
|
61
|
+
# API key
|
62
|
+
validate_header('bugsnag-api-key') do |api_key|
|
63
|
+
expected = Regexp.new(HEX_STRING_32)
|
64
|
+
unless expected.match(api_key)
|
65
|
+
@success = false
|
66
|
+
@errors << "bugsnag-api-key header was expected to match the regex '#{HEX_STRING_32}', but was '#{api_key}'"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Bugsnag-Sent-at
|
71
|
+
validate_header('bugsnag-sent-at') do |date|
|
72
|
+
begin
|
73
|
+
Date.iso8601(date)
|
74
|
+
rescue Date::Error
|
75
|
+
@success = false
|
76
|
+
@errors << "bugsnag-sent-at header was expected to be an IOS 8601 date, but was '#{date}'"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Bugsnag-Span-Sampling
|
81
|
+
# of the format x:y where x is a decimal between 0 and 1 (inclusive) and y is the number of spans in the batch (if possible at this stage - we could weaken this if necessary)
|
82
|
+
validate_header('bugsnag-span-sampling') do |sampling|
|
83
|
+
begin
|
84
|
+
expected = Regexp.new(SAMPLING_HEADER)
|
85
|
+
unless expected.match(sampling)
|
86
|
+
@success = false
|
87
|
+
@errors << "bugsnag-span-sampling header was expected to match the regex '#{SAMPLING_HEADER}', but was '#{sampling}'"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
43
93
|
def regex_comparison(path, regex)
|
44
94
|
element_value = Maze::Helper.read_key_path(@body, path)
|
45
95
|
expected = Regexp.new(regex)
|
data/lib/maze.rb
CHANGED
@@ -7,7 +7,7 @@ require_relative 'maze/timers'
|
|
7
7
|
# Glues the various parts of MazeRunner together that need to be accessed globally,
|
8
8
|
# providing an alternative to the proliferation of global variables or singletons.
|
9
9
|
module Maze
|
10
|
-
VERSION = '8.
|
10
|
+
VERSION = '8.3.0'
|
11
11
|
|
12
12
|
class << self
|
13
13
|
attr_accessor :check, :driver, :internal_hooks, :mode, :start_time, :dynamic_retry, :public_address,
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bugsnag-maze-runner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.
|
4
|
+
version: 8.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Kirkland
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -347,6 +347,7 @@ files:
|
|
347
347
|
- lib/features/steps/breadcrumb_steps.rb
|
348
348
|
- lib/features/steps/browser_steps.rb
|
349
349
|
- lib/features/steps/build_api_steps.rb
|
350
|
+
- lib/features/steps/deprecated_steps.rb
|
350
351
|
- lib/features/steps/document_server_steps.rb
|
351
352
|
- lib/features/steps/error_reporting_steps.rb
|
352
353
|
- lib/features/steps/feature_flag_steps.rb
|
@@ -446,11 +447,11 @@ files:
|
|
446
447
|
- lib/maze/wait.rb
|
447
448
|
- lib/utils/deep_merge.rb
|
448
449
|
- lib/utils/selenium_money_patch.rb
|
449
|
-
homepage:
|
450
|
+
homepage:
|
450
451
|
licenses:
|
451
452
|
- MIT
|
452
453
|
metadata: {}
|
453
|
-
post_install_message:
|
454
|
+
post_install_message:
|
454
455
|
rdoc_options: []
|
455
456
|
require_paths:
|
456
457
|
- lib
|
@@ -466,7 +467,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
466
467
|
version: '0'
|
467
468
|
requirements: []
|
468
469
|
rubygems_version: 3.1.6
|
469
|
-
signing_key:
|
470
|
+
signing_key:
|
470
471
|
specification_version: 4
|
471
472
|
summary: Bugsnag API request validation harness
|
472
473
|
test_files: []
|