bugsnag-maze-runner 8.2.0 → 8.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eac01df378fac543e5aa19a4999e4a2e403de8e7df9860b6463e27899f2f2f0d
4
- data.tar.gz: c59e92d444b2da617bb0ec06c5fdc4355687129b7cc01cd56e5900a48c2fbe2c
3
+ metadata.gz: 02b1bd719cc437d684670a164059b1db11b6b86e10de81348e1027b74b1a138d
4
+ data.tar.gz: f5341e638425082222c5ca8462e4e98cce7a00a084351a91e746ebb07fc0d23e
5
5
  SHA512:
6
- metadata.gz: a7d5e5079dc431e2c33d57f63ce3242cc0eaf12f81de1b043b843598ba15beb6d0610f21fbc2955502c6f35125781c1889b5a92963560e5dfc14d01f230bda90
7
- data.tar.gz: 8551f7d971779b47ec6e65ba0a6402bcbf9110e4b9232b4851c2b37aab1793a89879c1e3946e86c87abea478465ec43a28306f6f1daf42ff5c043415e4b297e9
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
- When('I wait for {int} span(s)') do |span_count|
7
- assert_received_spans span_count, Maze::Server.list_for('traces')
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 assert_received_spans(span_count, list)
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 >= span_count }
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 #{span_count} spans but received #{received_count} within the #{timeout}s timeout.
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(span_count, :<=, received_count, "#{received_count} spans received")
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
@@ -161,7 +161,7 @@ android_6:
161
161
 
162
162
  android_7:
163
163
  browserName: "Android Browser"
164
- device: "Samsung Galaxy S8 Plus"
164
+ device: "Samsung Galaxy S8"
165
165
  os: "android"
166
166
  osVersion: "7.0"
167
167
  realMobile: true
@@ -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 body [Hash] The body of the trace to validate
19
- def initialize(body)
20
- @body = body
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
- regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.spanId', '^[A-Fa-f0-9]{16}$')
30
- regex_comparison('resourceSpans.0.scopeSpans.0.spans.0.traceId', '^[A-Fa-f0-9]{32}$')
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)
@@ -49,7 +49,7 @@ module Maze
49
49
 
50
50
  if validator_class
51
51
  validators = list.all.map do |request|
52
- validator = validator_class.new(request[:body])
52
+ validator = validator_class.new(request)
53
53
  validator.validate
54
54
  validator
55
55
  end
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.2.0'
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.2.0
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-07-19 00:00:00.000000000 Z
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: []