nonnative 2.11.0 → 2.13.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
2
  SHA256:
3
- metadata.gz: 304dcea40b84eda206fe9964fe1479a54e0188f52f2a5300dbcf992101cab2b3
4
- data.tar.gz: a6adb1b816c424709ab337d1b845dd106ff5141ddb6f26bfe73318c4f51bed23
3
+ metadata.gz: 4bf1427ceb9bd3e1a93d7879934477938eb677a12f1687439e99d477ed32ddfa
4
+ data.tar.gz: c8db117445b7de2b9f16eec5fb36839aeeb6b0496f4e8077d9ce70852fe2b303
5
5
  SHA512:
6
- metadata.gz: a7d8afad5ad7ff9b550c67fe73a683da85ae1bcfa611e0b25b0d570f44ebd5beba47ab50287d58206a51d6d61722bf42ae893929d2c4a99d5ea53b2e033fae91
7
- data.tar.gz: 506907d924a16c49d583a91e78a7c6e17bb03e3e5d879f00f43e8d4313fb57957bf545538d2953d056ab0c3eecb94ff29ab9a1af22547c890c1a1e56e3f0335c
6
+ metadata.gz: a0c388775687f4f0832200cddf41def76228097216a80485554ed1874be54a66564946c3bdde65b3c78ce651c6664794c83d8b59e66c24e1719fb0c482295f08
7
+ data.tar.gz: 150f9db8f08b7ef7ea0697be96e1f4a4c779b3674d66283a7461b0f3037fc448baa3886d42f8984ddee47190ed3269d9c659badb7b333da859ce31e685c82a47
data/.circleci/config.yml CHANGED
@@ -3,7 +3,7 @@ version: 2.1
3
3
  jobs:
4
4
  build:
5
5
  docker:
6
- - image: alexfalkowski/ruby:2.4
6
+ - image: alexfalkowski/ruby:2.5
7
7
  working_directory: ~/nonnative
8
8
  steps:
9
9
  - checkout:
@@ -25,8 +25,8 @@ jobs:
25
25
  - vendor
26
26
  - run: make lint
27
27
  - run: make sec
28
- - run: COVERAGE_NAME="Features" make features
29
- - run: COVERAGE_NAME="Benchmarks" make benchmarks
28
+ - run: make features
29
+ - run: make benchmarks
30
30
  - store_test_results:
31
31
  path: test/reports
32
32
  - store_artifacts:
@@ -35,7 +35,7 @@ jobs:
35
35
  resource_class: arm.large
36
36
  sync:
37
37
  docker:
38
- - image: alexfalkowski/release:7.5
38
+ - image: alexfalkowski/release:7.6
39
39
  working_directory: ~/nonnative
40
40
  steps:
41
41
  - checkout:
@@ -46,7 +46,7 @@ jobs:
46
46
  resource_class: arm.large
47
47
  version:
48
48
  docker:
49
- - image: alexfalkowski/release:7.5
49
+ - image: alexfalkowski/release:7.6
50
50
  working_directory: ~/nonnative
51
51
  steps:
52
52
  - checkout:
@@ -58,7 +58,7 @@ jobs:
58
58
  resource_class: arm.large
59
59
  wait-all:
60
60
  docker:
61
- - image: alexfalkowski/ruby:2.4
61
+ - image: alexfalkowski/ruby:2.5
62
62
  steps:
63
63
  - run: echo "all applicable jobs finished"
64
64
  resource_class: arm.large
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nonnative (2.11.0)
4
+ nonnative (2.13.0)
5
5
  concurrent-ruby (>= 1, < 2)
6
6
  config (>= 5, < 6)
7
- cucumber (>= 7, < 11)
7
+ cucumber (>= 7, < 12)
8
8
  cucumber-cucumber-expressions (< 19)
9
9
  get_process_mem (>= 1, < 2)
10
10
  grpc (>= 1, < 2)
@@ -30,18 +30,18 @@ GEM
30
30
  config (5.6.1)
31
31
  deep_merge (~> 1.2, >= 1.2.1)
32
32
  ostruct
33
- cucumber (10.2.0)
33
+ cucumber (11.0.0)
34
34
  base64 (~> 0.2)
35
35
  builder (~> 3.2)
36
36
  cucumber-ci-environment (> 9, < 12)
37
- cucumber-core (> 15, < 17)
37
+ cucumber-core (>= 16.2.0, < 17)
38
38
  cucumber-cucumber-expressions (> 17, < 20)
39
- cucumber-html-formatter (> 21, < 23)
39
+ cucumber-html-formatter (> 21, < 24)
40
40
  diff-lcs (~> 1.5)
41
41
  logger (~> 1.6)
42
42
  mini_mime (~> 1.1)
43
43
  multi_test (~> 1.1)
44
- sys-uname (~> 1.3)
44
+ sys-uname (~> 1.5)
45
45
  cucumber-ci-environment (11.0.0)
46
46
  cucumber-core (16.2.0)
47
47
  cucumber-gherkin (> 36, < 40)
@@ -51,9 +51,9 @@ GEM
51
51
  bigdecimal
52
52
  cucumber-gherkin (39.0.0)
53
53
  cucumber-messages (>= 31, < 33)
54
- cucumber-html-formatter (22.3.0)
54
+ cucumber-html-formatter (23.1.0)
55
55
  cucumber-messages (> 23, < 33)
56
- cucumber-messages (32.2.0)
56
+ cucumber-messages (32.3.1)
57
57
  cucumber-tag-expressions (8.1.0)
58
58
  deep_merge (1.2.2)
59
59
  diff-lcs (1.6.2)
@@ -97,7 +97,7 @@ GEM
97
97
  netrc (0.11.0)
98
98
  nio4r (2.7.5)
99
99
  ostruct (0.6.3)
100
- parallel (1.28.0)
100
+ parallel (2.0.1)
101
101
  parser (3.3.11.1)
102
102
  ast (~> 2.4.1)
103
103
  racc
@@ -147,11 +147,11 @@ GEM
147
147
  rspec-support (3.13.7)
148
148
  rspec-wait (1.0.2)
149
149
  rspec (>= 3.4)
150
- rubocop (1.86.0)
150
+ rubocop (1.86.1)
151
151
  json (~> 2.3)
152
152
  language_server-protocol (~> 3.17.0.2)
153
153
  lint_roller (~> 1.1.0)
154
- parallel (~> 1.10)
154
+ parallel (>= 1.10)
155
155
  parser (>= 3.3.0.2)
156
156
  rainbow (>= 2.2.2, < 4.0)
157
157
  regexp_parser (>= 2.9.3, < 3.0)
@@ -3,8 +3,8 @@
3
3
  module Nonnative
4
4
  # Socket-pair variant used by the fault-injection proxy to simulate corrupted/incoherent traffic.
5
5
  #
6
- # When active, data written to the upstream socket is corrupted by shuffling the payload bytes
7
- # before forwarding.
6
+ # When active, client requests still pass through unchanged, but responses flowing back from the
7
+ # upstream socket are corrupted before they reach the client.
8
8
  #
9
9
  # This behavior is enabled by calling {Nonnative::FaultInjectionProxy#invalid_data}.
10
10
  #
@@ -12,16 +12,28 @@ module Nonnative
12
12
  # @see Nonnative::SocketPairFactory
13
13
  # @see Nonnative::SocketPair
14
14
  class InvalidDataSocketPair < SocketPair
15
- # Writes corrupted data to the socket by shuffling bytes.
15
+ LINE_DELIMITERS = ["\r\n", "\n", "\r"].freeze
16
+
17
+ # Track the accepted client socket so we can corrupt only the response path.
18
+ def connect(local_socket)
19
+ @local_socket = local_socket
20
+
21
+ super
22
+ ensure
23
+ @local_socket = nil
24
+ end
25
+
26
+ # Writes corrupted data to the socket by mutating payload bytes.
16
27
  #
17
- # The payload must always change, otherwise short or repetitive inputs such as "test" can
18
- # occasionally pass through unchanged and make fault-injection scenarios flaky.
28
+ # Client requests are forwarded unchanged so the upstream service can still parse them.
29
+ # Responses flowing back to the client are corrupted in-place, which keeps line-based clients
30
+ # from hanging while ensuring echoed data does not come back unchanged.
19
31
  #
20
32
  # @param socket [IO] the socket to write to
21
33
  # @param data [String] the original payload
22
34
  # @return [Integer] number of bytes written
23
35
  def write(socket, data)
24
- Nonnative.logger.info "shuffling socket data '#{socket.inspect}' for 'invalid_data' pair"
36
+ return super unless socket.equal?(@local_socket)
25
37
 
26
38
  super(socket, corrupt(data))
27
39
  end
@@ -29,40 +41,18 @@ module Nonnative
29
41
  private
30
42
 
31
43
  def corrupt(data)
32
- payload, delimiter = split_trailing_delimiter(data)
33
- return "\0#{delimiter}" if payload.empty?
34
-
35
- "#{corrupt_payload(payload)}#{delimiter}"
36
- end
37
-
38
- def split_trailing_delimiter(data)
39
- index = trailing_delimiter_start(data)
40
- payload = data.byteslice(0, index)
41
- delimiter = data.byteslice(index, data.bytesize - index) || ''
44
+ # Preserve a final line ending so line-oriented clients still finish their reads.
45
+ delimiter = LINE_DELIMITERS.find { |candidate| data.end_with?(candidate) } || ''
46
+ payload = data.delete_suffix(delimiter)
42
47
 
43
- [payload, delimiter]
44
- end
45
-
46
- def trailing_delimiter_start(data)
47
- index = data.bytesize
48
-
49
- while index.positive?
50
- byte = data.getbyte(index - 1)
51
- break unless [10, 13].include?(byte)
52
-
53
- index -= 1
54
- end
55
-
56
- index
57
- end
48
+ # A delimiter-only response still needs one byte we can corrupt without losing the terminator.
49
+ payload = "\0" if payload.empty?
58
50
 
59
- def corrupt_payload(payload)
60
- bytes = payload.bytes
61
- corrupted = bytes.shuffle
62
- return corrupted.pack('C*') unless corrupted == bytes
51
+ # Flip the first byte so the payload is definitely wrong without mangling the whole
52
+ # response structure and turning an invalid response into a timeout.
53
+ payload.setbyte(0, payload.getbyte(0).zero? ? 1 : 0)
63
54
 
64
- corrupted[0] = (corrupted[0] + 1) % 256
65
- corrupted.pack('C*')
55
+ "#{payload}#{delimiter}"
66
56
  end
67
57
  end
68
58
  end
@@ -4,5 +4,5 @@ module Nonnative
4
4
  # The current gem version.
5
5
  #
6
6
  # @return [String]
7
- VERSION = '2.11.0'
7
+ VERSION = '2.13.0'
8
8
  end
data/nonnative.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_dependency 'concurrent-ruby', '>= 1', '< 2'
28
28
  spec.add_dependency 'config', '>= 5', '< 6'
29
- spec.add_dependency 'cucumber', '>= 7', '< 11'
29
+ spec.add_dependency 'cucumber', '>= 7', '< 12'
30
30
  spec.add_dependency 'cucumber-cucumber-expressions', '< 19'
31
31
  spec.add_dependency 'get_process_mem', '>= 1', '< 2'
32
32
  spec.add_dependency 'grpc', '>= 1', '< 2'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nonnative
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.11.0
4
+ version: 2.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Falkowski
@@ -58,7 +58,7 @@ dependencies:
58
58
  version: '7'
59
59
  - - "<"
60
60
  - !ruby/object:Gem::Version
61
- version: '11'
61
+ version: '12'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
@@ -68,7 +68,7 @@ dependencies:
68
68
  version: '7'
69
69
  - - "<"
70
70
  - !ruby/object:Gem::Version
71
- version: '11'
71
+ version: '12'
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: cucumber-cucumber-expressions
74
74
  requirement: !ruby/object:Gem::Requirement