nonnative 3.2.1 → 3.6.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: 522cec08aee3855943f6ef6ba38bec3d85acd00aeeb2d6640a6869cf55014518
4
- data.tar.gz: ebebc8d342a2111f8fb8538c0bf5b615c549b61127761c3e2ada47397294b47c
3
+ metadata.gz: 0fb25075ea94da70b097c6b60e7a47fea1a73b7e80d4903f32b2a2d00675b50e
4
+ data.tar.gz: 33c1c4310fa48a1a8dacf792d9ce6af73f9a406f67185f61fb292f07d06d2345
5
5
  SHA512:
6
- metadata.gz: e4df243398b167fb955324fe12894f8bb5ecaf4ec612f8c55ad73e6cf95d6e04868ad1ee2ff64c1fbbc68322ea96dc953a0329b01f609a31b5409fb38542f09a
7
- data.tar.gz: 419ca92810588c41e281cd4d77e49651bee8c412d7285689f196c176473364f1562eabbe1944a121e238e79c9cfb0de6335bbcde05b6e068478c45db4414cef2
6
+ metadata.gz: c1c7e788eacbf1ed02100d4fc954f3ab7781c17a4e8c46c8ca8764becea615d54c6dee3be60404901228b37397533a809873c3ae27a157ac53463ff048ce8d50
7
+ data.tar.gz: fc73665d0141f943beca8dd9d43adbee088a214d1d31dad757fed1502df707f8ae599f10f4d5b3eb0b0c7e8c7db4b43b860cdd655e90d49c194320148df65439
data/.circleci/config.yml CHANGED
@@ -1,15 +1,33 @@
1
1
  version: 2.1
2
2
 
3
+ commands:
4
+ sync-submodules:
5
+ steps:
6
+ - run: git submodule sync
7
+ - run: git submodule update --init
8
+ checkout-submodules:
9
+ steps:
10
+ - checkout:
11
+ method: blobless
12
+ - sync-submodules
13
+
14
+ executors:
15
+ ruby:
16
+ docker:
17
+ - image: alexfalkowski/ruby:3.17
18
+ release:
19
+ docker:
20
+ - image: alexfalkowski/release:8.18
21
+ alpine:
22
+ docker:
23
+ - image: alpine:latest
24
+
3
25
  jobs:
4
26
  build:
5
- docker:
6
- - image: alexfalkowski/ruby:3.14
27
+ executor: ruby
7
28
  working_directory: ~/nonnative
8
29
  steps:
9
- - checkout:
10
- method: blobless
11
- - run: git submodule sync
12
- - run: git submodule update --init
30
+ - checkout-submodules
13
31
  - run: make source-key
14
32
  - restore_cache:
15
33
  name: restore deps
@@ -34,34 +52,25 @@ jobs:
34
52
  - run: make codecov-upload
35
53
  resource_class: arm.large
36
54
  sync:
37
- docker:
38
- - image: alexfalkowski/release:8.15
55
+ executor: release
39
56
  working_directory: ~/nonnative
40
57
  steps:
41
- - checkout:
42
- method: blobless
43
- - run: git submodule sync
44
- - run: git submodule update --init
58
+ - checkout-submodules
45
59
  - run: make sync push
46
60
  resource_class: arm.large
47
61
  version:
48
- docker:
49
- - image: alexfalkowski/release:8.15
62
+ executor: release
50
63
  working_directory: ~/nonnative
51
64
  steps:
52
- - checkout:
53
- method: blobless
54
- - run: git submodule sync
55
- - run: git submodule update --init
65
+ - checkout-submodules
56
66
  - run: version
57
67
  - run: package
58
68
  resource_class: arm.large
59
69
  wait-all:
60
- docker:
61
- - image: alexfalkowski/ruby:3.14
70
+ executor: alpine
71
+ resource_class: small
62
72
  steps:
63
73
  - run: echo "all applicable jobs finished"
64
- resource_class: arm.large
65
74
 
66
75
  workflows:
67
76
  nonnative:
data/.gitignore CHANGED
@@ -1,9 +1,18 @@
1
1
  /.bundle/
2
+ .crush/
3
+ .ruby-lsp/
4
+ .source-key
2
5
  /.yardoc
3
6
  /_yardoc/
4
7
  /doc/
5
8
  /pkg/
9
+ ISSUES.md
10
+ TESTS.md
11
+ DOCS.md
12
+ FEATURES.md
13
+ PROJECTS.md
14
+ RELIABILITY.md
6
15
  test/reports/*
16
+ !test/reports/.keep
7
17
  /tmp/
8
- vendor
9
- ISSUES.md
18
+ vendor/
data/AGENTS.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # AGENTS.md
2
2
 
3
- ## Shared skills
3
+ ## Shared guidance
4
4
 
5
- This repository uses the shared skills from `bin/skills/`. Read
6
- `bin/AGENTS.md` for the canonical shared skill list and use the smallest
7
- matching skill for the task.
5
+ Use `bin/AGENTS.md` for shared skills and cross-repository defaults.
8
6
 
9
7
  `nonnative` is a Ruby gem for end-to-end testing systems implemented in other
10
8
  languages. It starts processes, in-process servers, and proxy-only services,
@@ -18,18 +16,16 @@ of dependencies.
18
16
  - Generated gRPC test stubs: `test/grpc/**/*`
19
17
  - Test protos: `test/nonnative/v1/*.proto`
20
18
  - Build wiring: root `Makefile` includes `bin/build/make/*.mak`
21
- - Required submodule: `bin/` from `git@github.com:alexfalkowski/bin.git`; missing SSH/submodule setup breaks `make`
19
+ - Required submodule: `bin/`; missing submodule setup breaks `make`
22
20
  - Install deps: `make dep`
23
21
  - Lint: `make lint`
22
+ - Security checks: `make sec`
24
23
  - Features: `make features`
25
24
  - Benchmarks only: `make benchmarks`
26
25
  - Cleanup: `make clean-dep`, `make clean-reports`
27
26
 
28
27
  ## Intentional Design Choices
29
28
 
30
- - Root `make` compatibility is GNU Make 4+/`gmake` oriented through the shared
31
- `bin/build/make/*.mak` fragments. Do not flag GNU Make 3.81 parsing failures
32
- as code issues unless the task is explicitly about supporting GNU Make 3.81.
33
29
  - The configured HTTP proxy feature intentionally uses the external
34
30
  `www.afalkowski.com` host through `features/support/http_proxy_server.rb`.
35
31
  Do not flag this external dependency as a code issue unless the task is
@@ -54,6 +50,10 @@ of dependencies.
54
50
  test proto changes. Do not flag the absence of an automatic generated-stub
55
51
  freshness check as a test gap unless the task is explicitly about changing
56
52
  test proto generation or generated-file validation.
53
+ - Generated gRPC test stubs may carry manual require-path adjustments after
54
+ generation. Do not treat `make -C test stale` as a required validation target
55
+ unless the task is explicitly about changing test proto generation; verify
56
+ the generated Ruby loads before accepting generator-only rewrites.
57
57
  - Buf linting for the test-only proto module is intentionally not part of the
58
58
  required local validation surface. Do not flag missing root-level validation
59
59
  for `test/buf.yaml` as a test gap unless the task is explicitly about test
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nonnative (3.2.1)
4
+ nonnative (3.6.0)
5
5
  concurrent-ruby (>= 1, < 2)
6
6
  config (>= 5, < 6)
7
7
  cucumber (>= 7, < 12)
@@ -26,7 +26,7 @@ GEM
26
26
  benchmark-trend (0.4.0)
27
27
  bigdecimal (4.1.2)
28
28
  builder (3.3.0)
29
- concurrent-ruby (1.3.6)
29
+ concurrent-ruby (1.3.7)
30
30
  config (5.6.1)
31
31
  deep_merge (~> 1.2, >= 1.2.1)
32
32
  ostruct
@@ -64,24 +64,24 @@ GEM
64
64
  get_process_mem (1.0.0)
65
65
  bigdecimal (>= 2.0)
66
66
  ffi (~> 1.0)
67
- google-protobuf (4.35.0-x86_64-darwin)
67
+ google-protobuf (4.35.1-x86_64-darwin)
68
68
  bigdecimal
69
69
  rake (~> 13.3)
70
- google-protobuf (4.35.0-x86_64-linux-gnu)
70
+ google-protobuf (4.35.1-x86_64-linux-gnu)
71
71
  bigdecimal
72
72
  rake (~> 13.3)
73
73
  googleapis-common-protos-types (1.23.0)
74
74
  google-protobuf (~> 4.26)
75
- grpc (1.81.0-x86_64-darwin)
75
+ grpc (1.81.1-x86_64-darwin)
76
76
  google-protobuf (>= 3.25, < 5.0)
77
77
  googleapis-common-protos-types (~> 1.0)
78
- grpc (1.81.0-x86_64-linux-gnu)
78
+ grpc (1.81.1-x86_64-linux-gnu)
79
79
  google-protobuf (>= 3.25, < 5.0)
80
80
  googleapis-common-protos-types (~> 1.0)
81
81
  http-accept (1.7.0)
82
82
  http-cookie (1.1.6)
83
83
  domain_name (~> 0.5)
84
- json (2.19.8)
84
+ json (2.20.0)
85
85
  language_server-protocol (3.17.0.5)
86
86
  lint_roller (1.1.0)
87
87
  logger (1.7.0)
@@ -114,7 +114,7 @@ GEM
114
114
  rack (>= 3.0.0)
115
115
  rainbow (3.1.1)
116
116
  rake (13.4.2)
117
- rbs (4.0.2)
117
+ rbs (4.0.3)
118
118
  logger
119
119
  prism (>= 1.6.0)
120
120
  tsort
@@ -146,7 +146,7 @@ GEM
146
146
  rspec-support (3.13.7)
147
147
  rspec-wait (1.0.2)
148
148
  rspec (>= 3.4)
149
- rubocop (1.87.0)
149
+ rubocop (1.88.0)
150
150
  json (~> 2.3)
151
151
  language_server-protocol (~> 3.17.0.2)
152
152
  lint_roller (~> 1.1.0)
@@ -169,7 +169,7 @@ GEM
169
169
  docile (~> 1.1)
170
170
  simplecov-html (~> 0.11)
171
171
  simplecov_json_formatter (~> 0.1)
172
- simplecov-cobertura (3.1.0)
172
+ simplecov-cobertura (3.2.0)
173
173
  rexml
174
174
  simplecov (~> 0.19)
175
175
  simplecov-html (0.13.2)
data/README.md CHANGED
@@ -62,7 +62,7 @@ Common runner fields:
62
62
 
63
63
  Process/server fields:
64
64
  - `ports`: client-facing ports. These are also used for readiness/shutdown port checks.
65
- - `timeout`: max time (seconds) for readiness/shutdown port checks.
65
+ - `timeout`: max time (seconds) for readiness/shutdown port checks. Defaults to `1.0`.
66
66
  - `wait`: small sleep (seconds) between lifecycle steps.
67
67
  - `log`: per-runner log file used by process output redirection or server implementations.
68
68
 
@@ -164,7 +164,7 @@ Nonnative.configure do |config|
164
164
 
165
165
  config.process do |p|
166
166
  p.name = 'start_1'
167
- p.command = -> { ['features/support/bin/start', '12_321'] }
167
+ p.command = -> { ['bin/start-test-service', '12_321'] }
168
168
  p.timeout = 5
169
169
  p.wait = 0.1
170
170
  p.ports = [12_321]
@@ -177,7 +177,7 @@ Nonnative.configure do |config|
177
177
 
178
178
  config.process do |p|
179
179
  p.name = 'start_2'
180
- p.command = -> { ['features/support/bin/start', '12_322'] }
180
+ p.command = -> { ['bin/start-test-service', '12_322'] }
181
181
  p.timeout = 0.5
182
182
  p.wait = 0.1
183
183
  p.ports = [12_322]
@@ -197,7 +197,7 @@ processes:
197
197
  -
198
198
  name: start_1
199
199
  command:
200
- - features/support/bin/start
200
+ - bin/start-test-service
201
201
  - "12_321"
202
202
  timeout: 5
203
203
  wait: 1
@@ -210,7 +210,7 @@ processes:
210
210
  -
211
211
  name: start_2
212
212
  command:
213
- - features/support/bin/start
213
+ - bin/start-test-service
214
214
  - "12_322"
215
215
  timeout: 5
216
216
  wait: 1
@@ -474,6 +474,8 @@ end
474
474
 
475
475
  Define your server:
476
476
 
477
+ Assume the gRPC service base class and response types below come from your generated gRPC stubs.
478
+
477
479
  ```ruby
478
480
  module Nonnative
479
481
  module Features
@@ -530,6 +532,9 @@ servers:
530
532
  log: grpc_server_1.log
531
533
  ```
532
534
 
535
+ The `grpc` gem uses a global logger, so per-server gRPC log files are not independent. The first
536
+ initialized gRPC server sets the logger used by later gRPC servers in the same Ruby process.
537
+
533
538
  Then load the file with:
534
539
 
535
540
  ```ruby
@@ -42,13 +42,25 @@ module Nonnative
42
42
  end
43
43
 
44
44
  # @return [String, nil] logical system name (used for observability endpoints)
45
+ attr_accessor :name
46
+
45
47
  # @return [String, nil] configuration version
48
+ attr_accessor :version
49
+
46
50
  # @return [String, nil] base URL for observability queries (for example `"http://127.0.0.1:8080"`)
51
+ attr_accessor :url
52
+
47
53
  # @return [String, nil] path to the Nonnative log file
54
+ attr_accessor :log
55
+
48
56
  # @return [Array<Nonnative::ConfigurationProcess>] configured processes
57
+ attr_accessor :processes
58
+
49
59
  # @return [Array<Nonnative::ConfigurationServer>] configured in-process servers
60
+ attr_accessor :servers
61
+
50
62
  # @return [Array<Nonnative::ConfigurationService>] configured services (proxy-only)
51
- attr_accessor :name, :version, :url, :log, :processes, :servers, :services
63
+ attr_accessor :services
52
64
 
53
65
  # Loads a configuration file and appends its runners to this instance.
54
66
  #
@@ -179,7 +191,8 @@ module Nonnative
179
191
 
180
192
  def runner_attributes(runner, loaded)
181
193
  runner.name = loaded.name
182
- runner.timeout = loaded.timeout
194
+ timeout = loaded.timeout
195
+ runner.timeout = timeout unless timeout.nil?
183
196
  runner.wait = loaded.wait if loaded.wait
184
197
  runner.host = loaded.host if loaded.host
185
198
  assign_ports(runner, loaded)
@@ -19,7 +19,7 @@ module Nonnative
19
19
  # @return [String, nil] signal name to use for stopping (defaults to `"INT"` when not set)
20
20
  attr_accessor :signal
21
21
 
22
- # @return [Numeric] readiness timeout (seconds) used when waiting for ports to open/close
22
+ # @return [Numeric] readiness timeout (seconds) used when waiting for ports to open/close (defaults to `1.0`)
23
23
  attr_accessor :timeout
24
24
 
25
25
  # @return [String] log file path to append process stdout/stderr to
@@ -27,5 +27,17 @@ module Nonnative
27
27
 
28
28
  # @return [Hash, nil] environment variables to pass to the spawned process
29
29
  attr_accessor :environment
30
+
31
+ # Creates a process configuration with bounded lifecycle defaults.
32
+ #
33
+ # Defaults:
34
+ # - `timeout`: `1.0`
35
+ #
36
+ # @return [void]
37
+ def initialize
38
+ super
39
+
40
+ self.timeout = DEFAULT_TIMEOUT
41
+ end
30
42
  end
31
43
  end
@@ -15,12 +15,21 @@ module Nonnative
15
15
  # @see Nonnative.proxies
16
16
  class ConfigurationProxy
17
17
  # @return [String] proxy kind name (for example `"none"` or `"fault_injection"`)
18
+ attr_accessor :kind
19
+
18
20
  # @return [String] upstream host used by proxy implementations (defaults to `"127.0.0.1"`)
21
+ attr_accessor :host
22
+
19
23
  # @return [Integer] upstream port used by proxy implementations (defaults to `0`)
24
+ attr_accessor :port
25
+
20
26
  # @return [String, nil] path to proxy log file (implementation-dependent)
27
+ attr_accessor :log
28
+
21
29
  # @return [Numeric] wait interval (seconds) after proxy state changes (defaults to `0.1`)
30
+ attr_accessor :wait
31
+
22
32
  # @return [Hash] proxy implementation options (implementation-dependent)
23
- attr_accessor :kind, :host, :port, :log, :wait
24
33
  attr_reader :options
25
34
 
26
35
  # Creates a proxy configuration with defaults.
@@ -12,11 +12,17 @@ module Nonnative
12
12
  # @see Nonnative::ConfigurationServer
13
13
  # @see Nonnative::ConfigurationService
14
14
  class ConfigurationRunner
15
+ # Default bounded readiness/shutdown timeout for process and server runners.
16
+ DEFAULT_TIMEOUT = 1.0
17
+
15
18
  # @return [String, nil] runner name used for lookup (for example via `pool.process_by_name`)
19
+ attr_accessor :name
20
+
16
21
  # @return [String] host to bind/connect to (defaults to `"127.0.0.1"`)
17
- # @return [Array<Integer>] ports to bind/connect to
22
+ attr_accessor :host
23
+
18
24
  # @return [Numeric] wait interval (seconds) used by runners between lifecycle steps
19
- attr_accessor :name, :host, :wait
25
+ attr_accessor :wait
20
26
 
21
27
  # @return [Array<Integer>] client-facing ports used for readiness/shutdown checks
22
28
  attr_reader :ports
@@ -11,9 +11,25 @@ module Nonnative
11
11
  # @see Nonnative::Configuration
12
12
  # @see Nonnative::Server
13
13
  class ConfigurationServer < ConfigurationRunner
14
- # @return [Class] a class that implements `#initialize(service)`, and lifecycle hooks expected by {Nonnative::Server}
15
- # @return [Numeric] readiness timeout (seconds) used when waiting for ports to open/close
14
+ # @return [Class] a class that implements `#initialize(service)` and the hooks expected by {Nonnative::Server}
15
+ attr_accessor :klass
16
+
17
+ # @return [Numeric] readiness timeout (seconds) used when waiting for ports to open/close (defaults to `1.0`)
18
+ attr_accessor :timeout
19
+
16
20
  # @return [String] log file path used by server implementations (for example Puma/gRPC log files)
17
- attr_accessor :klass, :timeout, :log
21
+ attr_accessor :log
22
+
23
+ # Creates a server configuration with bounded lifecycle defaults.
24
+ #
25
+ # Defaults:
26
+ # - `timeout`: `1.0`
27
+ #
28
+ # @return [void]
29
+ def initialize
30
+ super
31
+
32
+ self.timeout = DEFAULT_TIMEOUT
33
+ end
18
34
  end
19
35
  end
@@ -8,6 +8,26 @@ module Nonnative
8
8
  # Requiring `nonnative` outside a running Cucumber environment should not fail, but when Cucumber
9
9
  # does finish booting its support-code registry this installer still needs to register the hooks
10
10
  # and step definitions defined here.
11
+ #
12
+ # Supported hooks:
13
+ # - `@startup`: start before scenario, stop after scenario
14
+ # - `@manual`: stop after scenario; use `When I start the system` to start manually
15
+ # - `@clear`: clear memoized Nonnative state before scenario
16
+ # - `@reset`: reset proxies after scenario
17
+ #
18
+ # Installed step definitions:
19
+ # - `Given I set the proxy for service {string} to {string}`
20
+ # - `Then I should reset the proxy for service {string}`
21
+ # - `When I start the system`
22
+ # - `When I attempt to start the system`
23
+ # - `When I attempt to stop the system`
24
+ # - `Then I should see {string} as unhealthy`
25
+ # - `Then I should see {string} as healthy`
26
+ # - `Then the process {string} should consume less than {string} of memory`
27
+ # - `Then starting the system should raise an error`
28
+ # - `Then stopping the system should raise an error`
29
+ # - `Then I should see a log entry of {string} for process {string}`
30
+ # - `Then I should see a log entry of {string} in the file {string}`
11
31
  module Cucumber
12
32
  module LanguageHook
13
33
  def rb_language=(value)
@@ -11,7 +11,7 @@ module Nonnative
11
11
  #
12
12
  # - {#close_all}: close connections immediately on accept
13
13
  # - {#delay}: delay reads by a configured duration (default: 2 seconds)
14
- # - {#invalid_data}: corrupt outbound data by shuffling characters
14
+ # - {#invalid_data}: forward requests unchanged and mutate upstream responses before they reach clients
15
15
  # - {#reset}: return to healthy pass-through behavior
16
16
  #
17
17
  # State changes terminate any active connections so new connections observe the new behavior.
@@ -107,7 +107,7 @@ module Nonnative
107
107
  apply_state :delay
108
108
  end
109
109
 
110
- # Corrupts forwarded data by shuffling characters.
110
+ # Mutates upstream responses while forwarding client requests unchanged.
111
111
  #
112
112
  # @return [void]
113
113
  def invalid_data
@@ -23,6 +23,14 @@ module Nonnative
23
23
  #
24
24
  # Supported HTTP verbs: GET, POST, PUT, PATCH, DELETE.
25
25
  class HTTPProxy < Sinatra::Application
26
+ NON_FORWARDABLE_HEADERS = %w[
27
+ Host
28
+ Accept-Encoding
29
+ Version
30
+ Proxy-Authenticate
31
+ Proxy-Authorization
32
+ ].freeze
33
+
26
34
  # Extracts request headers from the Rack environment and normalizes them to standard HTTP names.
27
35
  #
28
36
  # Certain hop-by-hop or proxy-specific headers are removed.
@@ -36,7 +44,7 @@ module Nonnative
36
44
  result[normalized_header_name(header)] = value
37
45
  end
38
46
 
39
- headers.except('Host', 'Accept-Encoding', 'Version')
47
+ headers.except(*NON_FORWARDABLE_HEADERS)
40
48
  end
41
49
 
42
50
  # Builds the upstream URL for the given request.
@@ -9,14 +9,20 @@ module Nonnative
9
9
  # The server is started and stopped by {Nonnative::Server} via {#perform_start} / {#perform_stop}.
10
10
  #
11
11
  # @example Running a Sinatra app
12
- # app = Sinatra.new do
13
- # get('/hello') { 'Hello World!' }
12
+ # class HelloHTTPServer < Nonnative::HTTPServer
13
+ # def initialize(service)
14
+ # app = Sinatra.new do
15
+ # get('/hello') { 'Hello World!' }
16
+ # end
17
+ #
18
+ # super(app, service)
19
+ # end
14
20
  # end
15
21
  #
16
22
  # Nonnative.configure do |config|
17
23
  # config.server do |s|
18
24
  # s.name = 'http'
19
- # s.klass = ->(service) { Nonnative::HTTPServer.new(app, service) }
25
+ # s.klass = HelloHTTPServer
20
26
  # s.timeout = 2
21
27
  # s.host = '127.0.0.1'
22
28
  # s.ports = [4567]
@@ -24,7 +30,7 @@ module Nonnative
24
30
  # end
25
31
  # end
26
32
  #
27
- # Note: In YAML configuration you typically set `class` to a concrete subclass that calls `super(app, service)`.
33
+ # YAML configuration uses the same concrete subclass name in its `class` field.
28
34
  #
29
35
  # @see Nonnative::Server
30
36
  class HTTPServer < Nonnative::Server
@@ -33,7 +39,8 @@ module Nonnative
33
39
  # @param app [#call] a Rack-compatible application (e.g. Sinatra/Rack app)
34
40
  # @param service [Nonnative::ConfigurationServer] server configuration
35
41
  def initialize(app, service)
36
- log = File.open(service.log, 'a')
42
+ # Keep the log IO so the server lifecycle can release Puma's file handle on stop.
43
+ @log = File.open(service.log, 'a')
37
44
  options = {
38
45
  log_writer: Puma::LogWriter.new(log, log),
39
46
  force_shutdown_after: service.timeout
@@ -60,10 +67,16 @@ module Nonnative
60
67
  # @return [void]
61
68
  def perform_stop
62
69
  server.graceful_shutdown
70
+ ensure
71
+ close_log
63
72
  end
64
73
 
65
74
  private
66
75
 
67
- attr_reader :server
76
+ attr_reader :server, :log
77
+
78
+ def close_log
79
+ log.close unless log.closed?
80
+ end
68
81
  end
69
82
  end
@@ -49,6 +49,7 @@ module Nonnative
49
49
  if process_exists?
50
50
  process_kill
51
51
  stopped = wait_stop != false
52
+ force_stop unless stopped
52
53
  end
53
54
 
54
55
  [pid, stopped]
@@ -82,6 +83,13 @@ module Nonnative
82
83
  ::Process.kill(signal, pid)
83
84
  end
84
85
 
86
+ def force_stop
87
+ ::Process.kill('KILL', pid)
88
+ wait_stop
89
+ rescue Errno::ESRCH, Errno::ECHILD
90
+ true
91
+ end
92
+
85
93
  def process_spawn
86
94
  environment = service.environment.to_h
87
95
  environment = environment.transform_keys(&:to_s).transform_values(&:to_s)
@@ -6,11 +6,14 @@ module Nonnative
6
6
  # A proxy is responsible for interposing behavior between a client and a target service.
7
7
  # Runtime services create a proxy instance via {Nonnative::ProxyFactory} based on `service.proxy.kind`.
8
8
  #
9
+ # Service configuration `host` and `port` are the client-facing endpoint. Concrete proxy methods are
10
+ # implementation-specific; for example {Nonnative::FaultInjectionProxy#host} and
11
+ # {Nonnative::FaultInjectionProxy#port} return the upstream target behind the proxy.
12
+ #
9
13
  # Concrete proxies typically implement these public methods:
10
14
  # - `start`: begin proxying (bind/listen, start threads, etc)
11
15
  # - `stop`: stop proxying and release resources
12
16
  # - `reset`: return proxy behavior to a healthy/default state
13
- # - `host` / `port`: endpoint clients should connect to when the proxy is enabled
14
17
  #
15
18
  # @see Nonnative::ProxyFactory
16
19
  # @see Nonnative::NoProxy
@@ -4,5 +4,5 @@ module Nonnative
4
4
  # The current gem version.
5
5
  #
6
6
  # @return [String]
7
- VERSION = '3.2.1'
7
+ VERSION = '3.6.0'
8
8
  end
data/lib/nonnative.rb CHANGED
@@ -36,10 +36,10 @@
36
36
  # # run tests...
37
37
  # Nonnative.stop
38
38
  #
39
- # == Notes
39
+ # == Cucumber integration
40
40
  #
41
- # This file also requires integration helpers used by acceptance tests. If you require `nonnative` outside a
42
- # Cucumber runtime, loading `nonnative/cucumber` may not be desirable for your environment.
41
+ # Requiring `nonnative` loads the lazy Cucumber integration. It is safe outside a booted Cucumber
42
+ # runtime; hooks and step definitions are installed once Cucumber's Ruby DSL is ready.
43
43
  #
44
44
  require 'socket'
45
45
  require 'timeout'
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: 3.2.1
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Falkowski