nonnative 2.1.0 → 2.8.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/.circleci/config.yml +5 -4
- data/AGENTS.md +86 -202
- data/Gemfile.lock +21 -20
- data/README.md +21 -12
- data/lib/nonnative/configuration.rb +11 -10
- data/lib/nonnative/configuration_proxy.rb +13 -1
- data/lib/nonnative/cucumber.rb +199 -103
- data/lib/nonnative/http_proxy_server.rb +36 -9
- data/lib/nonnative/pool.rb +114 -23
- data/lib/nonnative/process.rb +2 -1
- data/lib/nonnative/version.rb +1 -1
- data/lib/nonnative.rb +59 -15
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b7370ea5a582e82e738d71cbffc4a3ad847e8050165b02d33f1c18301212ace2
|
|
4
|
+
data.tar.gz: d3c139dd5cb598c013196f8362b38929783910e38fd4c45227e0093e28626eb8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 171e964df36ea5434a138fa0f01bfede21b7ad4b7708246b395e22eb3b373c9dda61299d72a663a759cd200572432d4ee7787f50de224808fd8a01c32315aa4e
|
|
7
|
+
data.tar.gz: 780c202b553579a078bdbcc0370d3d8641ea2c7a6268c7ab53182db970f1a299b8853fa8cf5ed6fd59ccd15bb46d63826c2adc5ef69bb010b661e4aba10a6971
|
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.
|
|
6
|
+
- image: alexfalkowski/ruby:2.4
|
|
7
7
|
working_directory: ~/nonnative
|
|
8
8
|
steps:
|
|
9
9
|
- checkout:
|
|
@@ -24,6 +24,7 @@ jobs:
|
|
|
24
24
|
paths:
|
|
25
25
|
- vendor
|
|
26
26
|
- run: make lint
|
|
27
|
+
- run: make sec
|
|
27
28
|
- run: make features
|
|
28
29
|
- store_test_results:
|
|
29
30
|
path: test/reports
|
|
@@ -33,7 +34,7 @@ jobs:
|
|
|
33
34
|
resource_class: arm.large
|
|
34
35
|
sync:
|
|
35
36
|
docker:
|
|
36
|
-
- image: alexfalkowski/release:7.
|
|
37
|
+
- image: alexfalkowski/release:7.5
|
|
37
38
|
working_directory: ~/nonnative
|
|
38
39
|
steps:
|
|
39
40
|
- checkout:
|
|
@@ -44,7 +45,7 @@ jobs:
|
|
|
44
45
|
resource_class: arm.large
|
|
45
46
|
version:
|
|
46
47
|
docker:
|
|
47
|
-
- image: alexfalkowski/release:7.
|
|
48
|
+
- image: alexfalkowski/release:7.5
|
|
48
49
|
working_directory: ~/nonnative
|
|
49
50
|
steps:
|
|
50
51
|
- checkout:
|
|
@@ -56,7 +57,7 @@ jobs:
|
|
|
56
57
|
resource_class: arm.large
|
|
57
58
|
wait-all:
|
|
58
59
|
docker:
|
|
59
|
-
- image: alexfalkowski/ruby:2.
|
|
60
|
+
- image: alexfalkowski/ruby:2.4
|
|
60
61
|
steps:
|
|
61
62
|
- run: echo "all applicable jobs finished"
|
|
62
63
|
resource_class: arm.large
|
data/AGENTS.md
CHANGED
|
@@ -1,248 +1,132 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This repo is the `nonnative` Ruby gem: a Ruby-first harness for end-to-end testing of systems implemented in other languages by starting processes/servers/services, waiting on TCP port readiness, and optionally putting fault-injection proxies in front of them.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Quick map
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- Library code: `lib/nonnative/**/*.rb`
|
|
8
|
+
- Acceptance tests: `features/**/*.feature`, `features/support/**/*.rb`, `features/step_definitions/**/*.rb`
|
|
9
|
+
- Generated gRPC Ruby stubs for tests: `test/grpc/**/*`
|
|
10
|
+
- Test proto files: `test/nonnative/v1/*.proto`
|
|
11
|
+
- Build wiring: root `Makefile` includes `bin/build/make/*.mak`
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
- Added/expanded RDoc for the module entry point (`Nonnative`) and core configuration/error types.
|
|
11
|
-
- Goal: document *public APIs only* (gem consumers), not internal/private helpers.
|
|
12
|
-
- **README accuracy pass started**:
|
|
13
|
-
- Fixed incorrect examples around **services**:
|
|
14
|
-
- Programmatic example incorrectly used `p.port` inside a `config.service do |s| ... end` block; corrected to `s.host`/`s.port`.
|
|
15
|
-
- YAML example incorrectly used `processes:` for services; corrected to `services:`.
|
|
16
|
-
- Removed/avoided implying non-existent config fields (e.g. there is no top-level `config.wait`; `wait` is per-runner).
|
|
13
|
+
## Key repo dependency
|
|
17
14
|
|
|
18
|
-
|
|
15
|
+
This repo depends on the `bin/` git submodule.
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
- `.gitmodules` points to `git@github.com:alexfalkowski/bin.git`
|
|
18
|
+
- CI runs `git submodule sync && git submodule update --init`
|
|
19
|
+
- If `bin/` is missing or you do not have SSH access, `make` targets will fail
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
- **Acceptance tests**: `features/**/*.feature` + `features/support/**/*.rb` + `features/step_definitions/**/*.rb` (Cucumber)
|
|
24
|
-
- **Generated gRPC Ruby stubs for tests**: `test/grpc/**/*` (excluded from RuboCop)
|
|
25
|
-
- **Proto definitions for test fixtures**: `test/nonnative/v1/*.proto`
|
|
26
|
-
- **Build system**: `Makefile` includes make fragments from the `bin/` submodule (`bin/build/make/*.mak`).
|
|
21
|
+
## Core commands
|
|
27
22
|
|
|
28
|
-
|
|
23
|
+
- Install deps: `make dep`
|
|
24
|
+
- Lint: `make lint`
|
|
25
|
+
- Run features: `make features`
|
|
26
|
+
- Run benchmarks only: `make benchmarks`
|
|
27
|
+
- Clean deps: `make clean-dep`
|
|
28
|
+
- Clean reports: `make clean-reports`
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
## Runtime model
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
- CI runs `git submodule sync && git submodule update --init` before running `make` targets (`.circleci/config.yml`).
|
|
32
|
+
Public entry point is `lib/nonnative.rb`.
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
Main module API:
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
- `configure`
|
|
37
|
+
- `start`
|
|
38
|
+
- `stop`
|
|
39
|
+
- `clear`
|
|
40
|
+
- `reset`
|
|
41
|
+
- `pool`
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
git submodule sync
|
|
41
|
-
git submodule update --init
|
|
42
|
-
```
|
|
43
|
+
Configuration lives in `Nonnative::Configuration` and is built either:
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
- programmatically with `config.process`, `config.server`, `config.service`
|
|
46
|
+
- from YAML with `config.load_file(...)`
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
Runtime runners:
|
|
47
49
|
|
|
48
|
-
- `
|
|
50
|
+
- `Nonnative::Process`: manages an OS process
|
|
51
|
+
- `Nonnative::Server`: manages an in-process Ruby server thread
|
|
52
|
+
- `Nonnative::Service`: manages only proxy lifecycle for an externally managed dependency
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
`Nonnative::Pool` starts services first, then servers/processes, and stops in the reverse direction.
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
Readiness and shutdown checks are TCP-only via `Nonnative::Port#open?` and `#closed?`.
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
make dep
|
|
56
|
-
```
|
|
58
|
+
## Cucumber integration
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
Cucumber integration lives in `lib/nonnative/cucumber.rb`.
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
Supported tags:
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
- `@startup`: start before scenario, stop after scenario
|
|
65
|
+
- `@manual`: scenario starts manually, stop after scenario
|
|
66
|
+
- `@clear`: call `Nonnative.clear` before scenario
|
|
67
|
+
- `@reset`: reset proxies after scenario
|
|
65
68
|
|
|
66
|
-
|
|
69
|
+
`Nonnative.clear` now clears:
|
|
67
70
|
|
|
68
|
-
-
|
|
69
|
-
-
|
|
71
|
+
- configuration
|
|
72
|
+
- logger
|
|
73
|
+
- observability client
|
|
74
|
+
- pool
|
|
70
75
|
|
|
71
|
-
|
|
76
|
+
`require 'nonnative'` still loads the Cucumber integration, but hook/step registration is lazy, so plain `require 'nonnative'` is safe outside a booted Cucumber runtime.
|
|
72
77
|
|
|
73
|
-
|
|
74
|
-
make fix-lint
|
|
75
|
-
# or
|
|
76
|
-
make format
|
|
77
|
-
```
|
|
78
|
+
For “start once per test run”, use `require 'nonnative/startup'`.
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
## Proxy wiring
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
make features
|
|
83
|
-
```
|
|
82
|
+
This is the easiest thing to get wrong.
|
|
84
83
|
|
|
85
|
-
|
|
84
|
+
- Runner `host` / `port` are the client-facing endpoint and the values used by readiness/shutdown checks
|
|
85
|
+
- For `fault_injection`, nested `proxy.host` / `proxy.port` are the upstream target behind the proxy
|
|
86
|
+
- Clients should connect to the runner `host` / `port` when a proxy is enabled
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
- Cucumber profile `report` is defined in `.config/cucumber.yml` and writes:
|
|
89
|
-
- JUnit XML to `test/reports`
|
|
90
|
-
- HTML report to `test/reports/index.html`
|
|
88
|
+
Available proxy kinds:
|
|
91
89
|
|
|
92
|
-
|
|
90
|
+
- `none`
|
|
91
|
+
- `fault_injection`
|
|
93
92
|
|
|
94
|
-
|
|
95
|
-
make benchmarks
|
|
96
|
-
```
|
|
93
|
+
Fault injection states:
|
|
97
94
|
|
|
98
|
-
|
|
95
|
+
- `none`
|
|
96
|
+
- `close_all`
|
|
97
|
+
- `delay`
|
|
98
|
+
- `invalid_data`
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
## Config gotchas
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
- Services must be declared under `services:` in YAML, not `processes:`
|
|
103
|
+
- There is no top-level `config.wait`; `wait` is per runner
|
|
104
|
+
- Service configs use `config.service do |s| ... end`, so use `s.host` / `s.port`
|
|
105
|
+
- Proxy examples need both sides of the split:
|
|
106
|
+
- runner `host` / `port` = proxy endpoint
|
|
107
|
+
- nested `proxy.host` / `proxy.port` = upstream target
|
|
103
108
|
|
|
104
|
-
|
|
109
|
+
## Test fixtures worth knowing
|
|
105
110
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
111
|
+
- Local process fixture: `features/support/bin/start`
|
|
112
|
+
- HTTP fixtures: `features/support/http_server.rb`, `features/support/http_proxy_server.rb`
|
|
113
|
+
- TCP fixture: `features/support/tcp_server.rb`
|
|
114
|
+
- gRPC fixtures: `features/support/grpc_server.rb`, plus generated stubs under `test/grpc/`
|
|
109
115
|
|
|
110
|
-
|
|
116
|
+
## Important limitations / gotchas
|
|
111
117
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
make
|
|
115
|
-
|
|
118
|
+
- Ruby version is constrained by `nonnative.gemspec` to `>= 3.4.0` and `< 4.0.0`
|
|
119
|
+
- The `grpc` Ruby library uses a global logger; per-server gRPC loggers are not really supported
|
|
120
|
+
- `make` depends on the `bin/` submodule being present
|
|
121
|
+
- Local Ruby/Bundler mismatches can break native extensions on macOS
|
|
122
|
+
- Coverage output and Cucumber reports are written under `test/reports`
|
|
123
|
+
- Port checks can be flaky if tests reuse ports unexpectedly
|
|
116
124
|
|
|
117
|
-
##
|
|
118
|
-
|
|
119
|
-
### Cucumber hooks and tags
|
|
120
|
-
|
|
121
|
-
Cucumber integration lives in `lib/nonnative/cucumber.rb`:
|
|
122
|
-
|
|
123
|
-
- `@startup`: starts and stops Nonnative around each scenario.
|
|
124
|
-
- `@manual`: only stops after scenario (start is expected to be triggered manually in steps).
|
|
125
|
-
- `@clear`: calls `Nonnative.clear` before scenario.
|
|
126
|
-
- `@reset`: resets proxies after scenario.
|
|
127
|
-
|
|
128
|
-
The “start once per test run” strategy is implemented by requiring `nonnative/startup`:
|
|
129
|
-
|
|
130
|
-
- `lib/nonnative/startup.rb` calls `Nonnative.start` and registers an `at_exit` stop.
|
|
131
|
-
|
|
132
|
-
### README gotchas that matter in practice
|
|
133
|
-
|
|
134
|
-
- **Service vs process YAML keys**:
|
|
135
|
-
- Services must be declared under `services:` in YAML (not `processes:`). Code reads `cfg.services` and maps them to `Nonnative::ConfigurationService`.
|
|
136
|
-
- **No top-level `wait`**:
|
|
137
|
-
- `wait` is defined on runner configurations (`ConfigurationRunner#wait`) and is per process/server/service.
|
|
138
|
-
- **Proxy wiring is easy to misunderstand**:
|
|
139
|
-
- When a proxy kind like `fault_injection` is enabled, the proxy binds to `service.proxy.host`/`service.proxy.port`.
|
|
140
|
-
- Readiness checks and traffic should typically target the **proxy host/port**, not the underlying service host/port.
|
|
141
|
-
|
|
142
|
-
### Feature support code
|
|
143
|
-
|
|
144
|
-
`features/support/` contains small servers/clients used by cucumber scenarios (HTTP/TCP/gRPC). Example:
|
|
145
|
-
|
|
146
|
-
- `features/support/http_server.rb` defines a Sinatra app for `/hello` and health endpoints.
|
|
147
|
-
|
|
148
|
-
### Process fixture
|
|
149
|
-
|
|
150
|
-
Scenarios start a local process via `features/support/bin/start` (referenced in step definitions and YAML configs like `features/configs/processes.yml`).
|
|
151
|
-
|
|
152
|
-
## Library architecture (high level)
|
|
153
|
-
|
|
154
|
-
### Entry point and global state
|
|
155
|
-
|
|
156
|
-
- `lib/nonnative.rb` defines the `Nonnative` module singleton API:
|
|
157
|
-
- `configure { |config| ... }`
|
|
158
|
-
- `start` / `stop`
|
|
159
|
-
- `clear`, `reset`
|
|
160
|
-
- `pool` is created on `start` (`Nonnative::Pool.new(configuration)`).
|
|
161
|
-
|
|
162
|
-
### Configuration objects
|
|
163
|
-
|
|
164
|
-
- `Nonnative::Configuration` (`lib/nonnative/configuration.rb`) holds arrays of:
|
|
165
|
-
- `processes` (`Nonnative::ConfigurationProcess`)
|
|
166
|
-
- `servers` (`Nonnative::ConfigurationServer`)
|
|
167
|
-
- `services` (`Nonnative::ConfigurationService`)
|
|
168
|
-
|
|
169
|
-
It can be populated either:
|
|
170
|
-
|
|
171
|
-
- programmatically via `config.process { ... }`, `config.server { ... }`, `config.service { ... }`
|
|
172
|
-
- via YAML using `config.load_file(path)` which calls `Config.load_files(...)` (the `config` gem)
|
|
173
|
-
|
|
174
|
-
Proxies are configured via `ConfigurationProxy` (`lib/nonnative/configuration_proxy.rb`) and attached to runners as a hash.
|
|
175
|
-
|
|
176
|
-
### Runners and lifecycle
|
|
177
|
-
|
|
178
|
-
There are three runtime “runner” types, all subclassing `Runner` (`lib/nonnative/runner.rb`):
|
|
179
|
-
|
|
180
|
-
- `Nonnative::Process` (`lib/nonnative/process.rb`): `spawn(...)` + `Process.kill` / `waitpid2`.
|
|
181
|
-
- `Nonnative::Server` (`lib/nonnative/server.rb`): `Thread.new { perform_start }` + `perform_stop`.
|
|
182
|
-
- `Nonnative::Service` (`lib/nonnative/service.rb`): no process management; proxy only.
|
|
183
|
-
|
|
184
|
-
`Nonnative::Pool` (`lib/nonnative/pool.rb`) owns collections of runners and orchestrates start/stop:
|
|
185
|
-
|
|
186
|
-
- starts **services first**, then servers/processes
|
|
187
|
-
- stops **processes/servers first**, then services
|
|
188
|
-
- readiness is determined via `Nonnative::Port#open?` / `#closed?` (`lib/nonnative/port.rb`) which repeatedly tries `TCPSocket.new(host, port)` inside a timeout.
|
|
189
|
-
|
|
190
|
-
### Proxies
|
|
191
|
-
|
|
192
|
-
Proxy selection is keyed by `kind`:
|
|
193
|
-
|
|
194
|
-
- mapping: `Nonnative.proxies` in `lib/nonnative.rb`
|
|
195
|
-
- default proxy config values: `ConfigurationProxy#initialize` sets kind `none`, host `0.0.0.0`, wait `0.1`, etc.
|
|
196
|
-
|
|
197
|
-
Implemented proxies:
|
|
198
|
-
|
|
199
|
-
- `Nonnative::NoProxy` (`lib/nonnative/no_proxy.rb`)
|
|
200
|
-
- `Nonnative::FaultInjectionProxy` (`lib/nonnative/fault_injection_proxy.rb`)
|
|
201
|
-
- states: `:none`, `:close_all`, `:delay`, `:invalid_data`
|
|
202
|
-
- delegates behavior to socket-pair classes via `SocketPairFactory` (`lib/nonnative/socket_pair_factory.rb`).
|
|
203
|
-
|
|
204
|
-
### Go executable helper
|
|
205
|
-
|
|
206
|
-
There is a helper for building a Go *test binary* command line with optional profiling/trace/coverage flags:
|
|
207
|
-
|
|
208
|
-
- `Nonnative.go_executable` in `lib/nonnative.rb`
|
|
209
|
-
- `Nonnative::GoCommand` in `lib/nonnative/go_command.rb`
|
|
210
|
-
|
|
211
|
-
This is used when YAML process config has a `go:` section (see `Configuration#command` in `lib/nonnative/configuration.rb`).
|
|
212
|
-
|
|
213
|
-
## Style and conventions
|
|
214
|
-
|
|
215
|
-
- Ruby style is enforced by RuboCop (`.rubocop.yml`):
|
|
216
|
-
- Target Ruby 3.4
|
|
217
|
-
- Line length 150
|
|
218
|
-
- `Style/Documentation` disabled
|
|
219
|
-
- `.editorconfig`:
|
|
220
|
-
- `indent_size = 2` for most files
|
|
221
|
-
- **Makefiles use tabs**
|
|
222
|
-
- Many Ruby files use `# frozen_string_literal: true`.
|
|
223
|
-
|
|
224
|
-
## CI notes
|
|
225
|
-
|
|
226
|
-
CircleCI runs (see `.circleci/config.yml`):
|
|
227
|
-
|
|
228
|
-
- `make source-key` (defined in `bin/build/make/git.mak`) to generate `.source-key` used for caching
|
|
229
|
-
- `make dep`, `make clean-dep`
|
|
230
|
-
- `make lint`, `make features`
|
|
231
|
-
- uploads `test/reports` artifacts
|
|
232
|
-
|
|
233
|
-
## Common gotchas
|
|
234
|
-
|
|
235
|
-
- **Submodule required**: root `Makefile` only includes `bin/...` make fragments; without `bin/` present/updated, `make` won’t work.
|
|
236
|
-
- **SSH-only submodule URL**: `.gitmodules` uses `git@github.com:...`; CI or local environments without SSH keys will fail to init the submodule.
|
|
237
|
-
- **Local Ruby/Bundler mismatch can break native extensions**: on macOS, `make lint`/`bundle exec ...` may fail if the Ruby used to install gems differs from the Ruby used to run them (example error seen: `prism.bundle` missing `libruby.3.4.dylib`).
|
|
238
|
-
- **Requiring `nonnative` loads Cucumber DSL**: `lib/nonnative.rb` requires `lib/nonnative/cucumber.rb`, which calls `World(...)`. Outside a Cucumber runtime this can raise (example error seen: `Cucumber::Glue::Dsl.build_rb_world_factory`).
|
|
239
|
-
- **Reports directory**: Cucumber report profile writes into `test/reports/` and the repo keeps a `test/reports/.keep` file.
|
|
240
|
-
- **Port checks can be flaky if ports are reused**: readiness is purely `TCPSocket`-based (`lib/nonnative/port.rb`), so ensure test fixtures bind expected ports.
|
|
241
|
-
|
|
242
|
-
## Where to look first when changing behavior
|
|
125
|
+
## Where to look first
|
|
243
126
|
|
|
244
127
|
- Lifecycle orchestration: `lib/nonnative.rb`, `lib/nonnative/pool.rb`
|
|
245
128
|
- Readiness / timeouts: `lib/nonnative/port.rb`, `lib/nonnative/timeout.rb`
|
|
246
|
-
- Process
|
|
129
|
+
- Process lifecycle: `lib/nonnative/process.rb`
|
|
247
130
|
- Proxies / fault injection: `lib/nonnative/fault_injection_proxy.rb`, `lib/nonnative/socket_pair_factory.rb`
|
|
248
131
|
- Cucumber integration: `lib/nonnative/cucumber.rb`, `lib/nonnative/startup.rb`, `features/support/env.rb`
|
|
132
|
+
- Config loading: `lib/nonnative/configuration.rb`, `lib/nonnative/configuration_runner.rb`, `lib/nonnative/configuration_proxy.rb`
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
nonnative (2.
|
|
4
|
+
nonnative (2.8.0)
|
|
5
5
|
concurrent-ruby (>= 1, < 2)
|
|
6
6
|
config (>= 5, < 6)
|
|
7
7
|
cucumber (>= 7, < 11)
|
|
@@ -24,7 +24,7 @@ GEM
|
|
|
24
24
|
benchmark-malloc (0.2.0)
|
|
25
25
|
benchmark-perf (0.6.0)
|
|
26
26
|
benchmark-trend (0.4.0)
|
|
27
|
-
bigdecimal (4.
|
|
27
|
+
bigdecimal (4.1.1)
|
|
28
28
|
builder (3.3.0)
|
|
29
29
|
concurrent-ruby (1.3.6)
|
|
30
30
|
config (5.6.1)
|
|
@@ -47,7 +47,7 @@ GEM
|
|
|
47
47
|
cucumber-gherkin (> 36, < 40)
|
|
48
48
|
cucumber-messages (> 31, < 33)
|
|
49
49
|
cucumber-tag-expressions (> 6, < 9)
|
|
50
|
-
cucumber-cucumber-expressions (18.0
|
|
50
|
+
cucumber-cucumber-expressions (18.1.0)
|
|
51
51
|
bigdecimal
|
|
52
52
|
cucumber-gherkin (39.0.0)
|
|
53
53
|
cucumber-messages (>= 31, < 33)
|
|
@@ -59,29 +59,29 @@ GEM
|
|
|
59
59
|
diff-lcs (1.6.2)
|
|
60
60
|
docile (1.4.1)
|
|
61
61
|
domain_name (0.6.20240107)
|
|
62
|
-
ffi (1.17.
|
|
63
|
-
ffi (1.17.
|
|
62
|
+
ffi (1.17.4-x86_64-darwin)
|
|
63
|
+
ffi (1.17.4-x86_64-linux-gnu)
|
|
64
64
|
get_process_mem (1.0.0)
|
|
65
65
|
bigdecimal (>= 2.0)
|
|
66
66
|
ffi (~> 1.0)
|
|
67
|
-
google-protobuf (4.34.
|
|
67
|
+
google-protobuf (4.34.1-x86_64-darwin)
|
|
68
68
|
bigdecimal
|
|
69
69
|
rake (~> 13.3)
|
|
70
|
-
google-protobuf (4.34.
|
|
70
|
+
google-protobuf (4.34.1-x86_64-linux-gnu)
|
|
71
71
|
bigdecimal
|
|
72
72
|
rake (~> 13.3)
|
|
73
73
|
googleapis-common-protos-types (1.22.0)
|
|
74
74
|
google-protobuf (~> 4.26)
|
|
75
|
-
grpc (1.
|
|
75
|
+
grpc (1.80.0-x86_64-darwin)
|
|
76
76
|
google-protobuf (>= 3.25, < 5.0)
|
|
77
77
|
googleapis-common-protos-types (~> 1.0)
|
|
78
|
-
grpc (1.
|
|
78
|
+
grpc (1.80.0-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
|
-
http-cookie (1.1.
|
|
82
|
+
http-cookie (1.1.4)
|
|
83
83
|
domain_name (~> 0.5)
|
|
84
|
-
json (2.19.
|
|
84
|
+
json (2.19.3)
|
|
85
85
|
language_server-protocol (3.17.0.5)
|
|
86
86
|
lint_roller (1.1.0)
|
|
87
87
|
logger (1.7.0)
|
|
@@ -89,7 +89,7 @@ GEM
|
|
|
89
89
|
mime-types (3.7.0)
|
|
90
90
|
logger
|
|
91
91
|
mime-types-data (~> 3.2025, >= 3.2025.0507)
|
|
92
|
-
mime-types-data (3.2026.
|
|
92
|
+
mime-types-data (3.2026.0407)
|
|
93
93
|
mini_mime (1.1.5)
|
|
94
94
|
multi_test (1.1.0)
|
|
95
95
|
mustermann (3.0.4)
|
|
@@ -97,28 +97,29 @@ GEM
|
|
|
97
97
|
netrc (0.11.0)
|
|
98
98
|
nio4r (2.7.5)
|
|
99
99
|
ostruct (0.6.3)
|
|
100
|
-
parallel (1.
|
|
101
|
-
parser (3.3.
|
|
100
|
+
parallel (1.28.0)
|
|
101
|
+
parser (3.3.11.1)
|
|
102
102
|
ast (~> 2.4.1)
|
|
103
103
|
racc
|
|
104
104
|
prism (1.9.0)
|
|
105
105
|
puma (7.2.0)
|
|
106
106
|
nio4r (~> 2.0)
|
|
107
107
|
racc (1.8.1)
|
|
108
|
-
rack (3.2.
|
|
108
|
+
rack (3.2.6)
|
|
109
109
|
rack-protection (4.2.1)
|
|
110
110
|
base64 (>= 0.1.0)
|
|
111
111
|
logger (>= 1.6.0)
|
|
112
112
|
rack (>= 3.0.0, < 4)
|
|
113
|
-
rack-session (2.1.
|
|
113
|
+
rack-session (2.1.2)
|
|
114
114
|
base64 (>= 0.1.0)
|
|
115
115
|
rack (>= 3.0.0)
|
|
116
116
|
rainbow (3.1.1)
|
|
117
117
|
rake (13.3.1)
|
|
118
|
-
rbs (
|
|
118
|
+
rbs (4.0.2)
|
|
119
119
|
logger
|
|
120
|
+
prism (>= 1.6.0)
|
|
120
121
|
tsort
|
|
121
|
-
regexp_parser (2.
|
|
122
|
+
regexp_parser (2.12.0)
|
|
122
123
|
rest-client (2.1.0)
|
|
123
124
|
http-accept (>= 1.7.0, < 2.0)
|
|
124
125
|
http-cookie (>= 1.0.2, < 2.0)
|
|
@@ -160,7 +161,7 @@ GEM
|
|
|
160
161
|
rubocop-ast (1.49.1)
|
|
161
162
|
parser (>= 3.3.7.2)
|
|
162
163
|
prism (~> 1.7)
|
|
163
|
-
ruby-lsp (0.26.
|
|
164
|
+
ruby-lsp (0.26.9)
|
|
164
165
|
language_server-protocol (~> 3.17.0)
|
|
165
166
|
prism (>= 1.2, < 2.0)
|
|
166
167
|
rbs (>= 3, < 5)
|
|
@@ -182,7 +183,7 @@ GEM
|
|
|
182
183
|
rack-protection (= 4.2.1)
|
|
183
184
|
rack-session (>= 2.0.0, < 3)
|
|
184
185
|
tilt (~> 2.0)
|
|
185
|
-
sys-uname (1.5.
|
|
186
|
+
sys-uname (1.5.1)
|
|
186
187
|
ffi (~> 1.1)
|
|
187
188
|
memoist3 (~> 1.0.0)
|
|
188
189
|
tilt (2.7.0)
|
data/README.md
CHANGED
|
@@ -51,17 +51,21 @@ High-level configuration fields:
|
|
|
51
51
|
Runner fields (process/server/service):
|
|
52
52
|
- `timeout`: max time (seconds) for readiness/shutdown port checks.
|
|
53
53
|
- `wait`: small sleep (seconds) between lifecycle steps.
|
|
54
|
-
- `host`/`port`: address used for port checks
|
|
54
|
+
- `host`/`port`: client-facing address used for readiness/shutdown port checks. When a `fault_injection` proxy is enabled, this is the endpoint your tests/clients should hit.
|
|
55
55
|
- `log`: per-runner log file (used by process output redirection or server implementations).
|
|
56
56
|
|
|
57
|
+
For `fault_injection`, the nested `proxy.host`/`proxy.port` describe the upstream target behind the proxy. In-process server implementations typically bind there via `proxy.host` / `proxy.port`.
|
|
58
|
+
|
|
57
59
|
### Lifecycle strategies (Cucumber integration)
|
|
58
60
|
|
|
59
61
|
Nonnative ships Cucumber hooks (when loaded) that support these tags/strategies:
|
|
60
62
|
- `@startup`: start before scenario; stop after scenario
|
|
61
63
|
- `@manual`: stop after scenario (start is expected to be triggered manually in steps)
|
|
62
|
-
- `@clear`: clears memoized configuration and pool before scenario
|
|
64
|
+
- `@clear`: clears memoized configuration, logger, observability client, and pool before scenario
|
|
63
65
|
- `@reset`: resets proxies after scenario
|
|
64
66
|
|
|
67
|
+
Requiring `nonnative` is enough; the Cucumber hooks and step definitions are installed lazily once Cucumber’s Ruby DSL is ready.
|
|
68
|
+
|
|
65
69
|
If you want “start once per test run”, require:
|
|
66
70
|
|
|
67
71
|
```ruby
|
|
@@ -516,9 +520,11 @@ We allow different proxies to be configured. These proxies can be used to simula
|
|
|
516
520
|
- `none` (this is the default)
|
|
517
521
|
- `fault_injection`
|
|
518
522
|
|
|
523
|
+
For `fault_injection`, keep the runner `host`/`port` as the client-facing endpoint and use nested `proxy.host`/`proxy.port` for the upstream target behind the proxy.
|
|
524
|
+
|
|
519
525
|
##### Proxies Processes
|
|
520
526
|
|
|
521
|
-
|
|
527
|
+
Add this to an existing process configuration:
|
|
522
528
|
|
|
523
529
|
```ruby
|
|
524
530
|
require 'nonnative'
|
|
@@ -543,7 +549,7 @@ Nonnative.configure do |config|
|
|
|
543
549
|
end
|
|
544
550
|
```
|
|
545
551
|
|
|
546
|
-
|
|
552
|
+
YAML fragment:
|
|
547
553
|
|
|
548
554
|
```yaml
|
|
549
555
|
version: "1.0"
|
|
@@ -563,7 +569,7 @@ processes:
|
|
|
563
569
|
|
|
564
570
|
##### Proxies Servers
|
|
565
571
|
|
|
566
|
-
|
|
572
|
+
Add this to an existing server configuration:
|
|
567
573
|
|
|
568
574
|
```ruby
|
|
569
575
|
require 'nonnative'
|
|
@@ -588,7 +594,7 @@ Nonnative.configure do |config|
|
|
|
588
594
|
end
|
|
589
595
|
```
|
|
590
596
|
|
|
591
|
-
|
|
597
|
+
YAML fragment:
|
|
592
598
|
|
|
593
599
|
```yaml
|
|
594
600
|
version: "1.0"
|
|
@@ -608,7 +614,7 @@ servers:
|
|
|
608
614
|
|
|
609
615
|
##### Proxies Services
|
|
610
616
|
|
|
611
|
-
|
|
617
|
+
Add this to an existing service configuration:
|
|
612
618
|
|
|
613
619
|
```ruby
|
|
614
620
|
require 'nonnative'
|
|
@@ -622,12 +628,12 @@ Nonnative.configure do |config|
|
|
|
622
628
|
config.service do |s|
|
|
623
629
|
s.name = 'redis'
|
|
624
630
|
s.host = '127.0.0.1'
|
|
625
|
-
s.port =
|
|
631
|
+
s.port = 16_379
|
|
626
632
|
|
|
627
633
|
s.proxy = {
|
|
628
634
|
kind: 'fault_injection',
|
|
629
635
|
host: '127.0.0.1',
|
|
630
|
-
port:
|
|
636
|
+
port: 6379,
|
|
631
637
|
log: 'proxy_server.log',
|
|
632
638
|
wait: 1,
|
|
633
639
|
options: {
|
|
@@ -638,19 +644,22 @@ Nonnative.configure do |config|
|
|
|
638
644
|
end
|
|
639
645
|
```
|
|
640
646
|
|
|
641
|
-
|
|
647
|
+
YAML fragment:
|
|
642
648
|
|
|
643
649
|
```yaml
|
|
644
650
|
version: "1.0"
|
|
645
651
|
name: test
|
|
646
652
|
url: http://localhost:4567
|
|
647
653
|
log: nonnative.log
|
|
648
|
-
wait: 1
|
|
649
654
|
services:
|
|
650
655
|
-
|
|
656
|
+
name: redis
|
|
657
|
+
host: 127.0.0.1
|
|
658
|
+
port: 16379
|
|
651
659
|
proxy:
|
|
652
660
|
kind: fault_injection
|
|
653
|
-
|
|
661
|
+
host: 127.0.0.1
|
|
662
|
+
port: 6379
|
|
654
663
|
log: proxy_server.log
|
|
655
664
|
wait: 1
|
|
656
665
|
options:
|
|
@@ -124,14 +124,10 @@ module Nonnative
|
|
|
124
124
|
processes = cfg.processes || []
|
|
125
125
|
processes.each do |fd|
|
|
126
126
|
process do |d|
|
|
127
|
-
d.name = fd.name
|
|
128
127
|
d.command = command(fd)
|
|
129
|
-
d.timeout = fd.timeout
|
|
130
|
-
d.wait = fd.wait if fd.wait
|
|
131
|
-
d.port = fd.port
|
|
132
|
-
d.log = fd.log
|
|
133
128
|
d.signal = fd.signal
|
|
134
129
|
d.environment = fd.environment
|
|
130
|
+
runner_attributes(d, fd)
|
|
135
131
|
|
|
136
132
|
proxy d, fd.proxy
|
|
137
133
|
end
|
|
@@ -154,12 +150,8 @@ module Nonnative
|
|
|
154
150
|
servers = cfg.servers || []
|
|
155
151
|
servers.each do |fd|
|
|
156
152
|
server do |s|
|
|
157
|
-
s.name = fd.name
|
|
158
153
|
s.klass = Object.const_get(fd.class)
|
|
159
|
-
s
|
|
160
|
-
s.wait = fd.wait if fd.wait
|
|
161
|
-
s.port = fd.port
|
|
162
|
-
s.log = fd.log
|
|
154
|
+
runner_attributes(s, fd)
|
|
163
155
|
|
|
164
156
|
proxy s, fd.proxy
|
|
165
157
|
end
|
|
@@ -179,6 +171,15 @@ module Nonnative
|
|
|
179
171
|
end
|
|
180
172
|
end
|
|
181
173
|
|
|
174
|
+
def runner_attributes(runner, loaded)
|
|
175
|
+
runner.name = loaded.name
|
|
176
|
+
runner.timeout = loaded.timeout
|
|
177
|
+
runner.wait = loaded.wait if loaded.wait
|
|
178
|
+
runner.host = loaded.host if loaded.host
|
|
179
|
+
runner.port = loaded.port
|
|
180
|
+
runner.log = loaded.log if loaded.respond_to?(:log)
|
|
181
|
+
end
|
|
182
|
+
|
|
182
183
|
def proxy(runner, proxy)
|
|
183
184
|
return unless proxy
|
|
184
185
|
|