nonnative 1.24.0 → 1.29.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 +1 -1
- data/.rubocop.yml +19 -1
- data/.ruby-version +1 -1
- data/Gemfile.lock +16 -16
- data/README.md +93 -34
- data/lib/nonnative.rb +4 -2
- data/lib/nonnative/command.rb +1 -1
- data/lib/nonnative/configuration.rb +12 -5
- data/lib/nonnative/configuration_process.rb +1 -1
- data/lib/nonnative/configuration_proxy.rb +1 -1
- data/lib/nonnative/configuration_server.rb +2 -1
- data/lib/nonnative/{chaos_proxy.rb → fault_injection_proxy.rb} +16 -4
- data/lib/nonnative/go_command.rb +40 -0
- data/lib/nonnative/grpc_server.rb +5 -0
- data/lib/nonnative/http_server.rb +3 -1
- data/lib/nonnative/pool.rb +0 -2
- data/lib/nonnative/proxy_factory.rb +8 -7
- data/lib/nonnative/socket_pair.rb +5 -2
- data/lib/nonnative/socket_pair_factory.rb +13 -11
- data/lib/nonnative/strategy.rb +28 -0
- data/lib/nonnative/version.rb +1 -1
- data/nonnative.gemspec +1 -1
- metadata +11 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 38e0bc3edd8186e46c09f6ced347428e59c84d2fd1fa3621b43d750e6869df24
|
|
4
|
+
data.tar.gz: bce006f5c6c8efec4ee05eed6e596a387362efd533d39a76730d4c418da3ca96
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de9987b642545511b4b4357b1b74670ba2f82d15c13b6df442ea6ef8954ac1f4225d2fdd8029395a085491dace93f827bae0fa85256a6c7c8fed90681e252b72
|
|
7
|
+
data.tar.gz: aecc4f783443ecfc13dc8a93329e16fbf0677f09dff875bf878316e64c468e19abf3d93f08a8e246de56c33c2c103a14653b07b9048e1be2cde2458e69ca7752
|
data/.circleci/config.yml
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -9,7 +9,7 @@ Metrics/MethodLength:
|
|
|
9
9
|
Max: 20
|
|
10
10
|
|
|
11
11
|
Metrics/BlockLength:
|
|
12
|
-
Max:
|
|
12
|
+
Max: 80
|
|
13
13
|
|
|
14
14
|
Metrics/AbcSize:
|
|
15
15
|
Max: 20
|
|
@@ -67,3 +67,21 @@ Style/BisectedAttrAccessor:
|
|
|
67
67
|
|
|
68
68
|
Style/RedundantAssignment:
|
|
69
69
|
Enabled: true
|
|
70
|
+
|
|
71
|
+
Lint/DuplicateElsifCondition:
|
|
72
|
+
Enabled: true
|
|
73
|
+
|
|
74
|
+
Style/ArrayCoercion:
|
|
75
|
+
Enabled: true
|
|
76
|
+
|
|
77
|
+
Style/CaseLikeIf:
|
|
78
|
+
Enabled: true
|
|
79
|
+
|
|
80
|
+
Style/HashAsLastArrayItem:
|
|
81
|
+
Enabled: true
|
|
82
|
+
|
|
83
|
+
Style/HashLikeCase:
|
|
84
|
+
Enabled: true
|
|
85
|
+
|
|
86
|
+
Style/RedundantFileExtensionInRequire:
|
|
87
|
+
Enabled: true
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby-2.
|
|
1
|
+
ruby-2.7.1
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
nonnative (1.
|
|
4
|
+
nonnative (1.29.0)
|
|
5
5
|
concurrent-ruby (~> 1.0, >= 1.0.5)
|
|
6
6
|
cucumber (>= 4, < 5)
|
|
7
7
|
grpc (>= 1, < 2)
|
|
@@ -47,12 +47,12 @@ GEM
|
|
|
47
47
|
cucumber-create-meta (1.0.0)
|
|
48
48
|
cucumber-messages (~> 12.2, >= 12.2.0)
|
|
49
49
|
sys-uname (~> 1.2, >= 1.2.1)
|
|
50
|
-
cucumber-cucumber-expressions (10.2.
|
|
51
|
-
cucumber-gherkin (14.0
|
|
52
|
-
cucumber-messages (~> 12.
|
|
53
|
-
cucumber-html-formatter (7.
|
|
54
|
-
cucumber-messages (~> 12.
|
|
55
|
-
cucumber-messages (12.
|
|
50
|
+
cucumber-cucumber-expressions (10.2.2)
|
|
51
|
+
cucumber-gherkin (14.2.0)
|
|
52
|
+
cucumber-messages (~> 12.4, >= 12.4.0)
|
|
53
|
+
cucumber-html-formatter (7.2.0)
|
|
54
|
+
cucumber-messages (~> 12.4, >= 12.4.0)
|
|
55
|
+
cucumber-messages (12.4.0)
|
|
56
56
|
protobuf-cucumber (~> 3.10, >= 3.10.8)
|
|
57
57
|
cucumber-tag-expressions (2.0.4)
|
|
58
58
|
cucumber-wire (3.1.0)
|
|
@@ -65,17 +65,17 @@ GEM
|
|
|
65
65
|
unf (>= 0.0.5, < 1.0.0)
|
|
66
66
|
e2mmap (0.1.0)
|
|
67
67
|
ffi (1.13.1)
|
|
68
|
-
google-protobuf (3.12.
|
|
68
|
+
google-protobuf (3.12.4)
|
|
69
69
|
googleapis-common-protos-types (1.0.5)
|
|
70
70
|
google-protobuf (~> 3.11)
|
|
71
|
-
grpc (1.30.
|
|
71
|
+
grpc (1.30.2)
|
|
72
72
|
google-protobuf (~> 3.12)
|
|
73
73
|
googleapis-common-protos-types (~> 1.0)
|
|
74
|
-
grpc-tools (1.30.
|
|
74
|
+
grpc-tools (1.30.2)
|
|
75
75
|
http-accept (1.7.0)
|
|
76
76
|
http-cookie (1.0.3)
|
|
77
77
|
domain_name (~> 0.5)
|
|
78
|
-
i18n (1.8.
|
|
78
|
+
i18n (1.8.5)
|
|
79
79
|
concurrent-ruby (~> 1.0)
|
|
80
80
|
jaro_winkler (1.5.4)
|
|
81
81
|
json (2.3.0)
|
|
@@ -135,7 +135,7 @@ GEM
|
|
|
135
135
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
136
136
|
rspec-support (~> 3.9.0)
|
|
137
137
|
rspec-support (3.9.3)
|
|
138
|
-
rubocop (0.
|
|
138
|
+
rubocop (0.88.0)
|
|
139
139
|
parallel (~> 1.10)
|
|
140
140
|
parser (>= 2.7.1.1)
|
|
141
141
|
rainbow (>= 2.2.2, < 4.0)
|
|
@@ -144,7 +144,7 @@ GEM
|
|
|
144
144
|
rubocop-ast (>= 0.1.0, < 1.0)
|
|
145
145
|
ruby-progressbar (~> 1.7)
|
|
146
146
|
unicode-display_width (>= 1.4.0, < 2.0)
|
|
147
|
-
rubocop-ast (0.
|
|
147
|
+
rubocop-ast (0.2.0)
|
|
148
148
|
parser (>= 2.7.0.1)
|
|
149
149
|
ruby-progressbar (1.10.1)
|
|
150
150
|
ruby2_keywords (0.0.2)
|
|
@@ -158,7 +158,7 @@ GEM
|
|
|
158
158
|
rack (~> 2.0)
|
|
159
159
|
rack-protection (= 2.0.8.1)
|
|
160
160
|
tilt (~> 2.0)
|
|
161
|
-
solargraph (0.39.
|
|
161
|
+
solargraph (0.39.12)
|
|
162
162
|
backport (~> 1.1)
|
|
163
163
|
benchmark
|
|
164
164
|
bundler (>= 1.17.2)
|
|
@@ -184,7 +184,7 @@ GEM
|
|
|
184
184
|
unf_ext (0.0.7.7)
|
|
185
185
|
unicode-display_width (1.7.0)
|
|
186
186
|
yard (0.9.25)
|
|
187
|
-
zeitwerk (2.
|
|
187
|
+
zeitwerk (2.4.0)
|
|
188
188
|
|
|
189
189
|
PLATFORMS
|
|
190
190
|
ruby
|
|
@@ -194,7 +194,7 @@ DEPENDENCIES
|
|
|
194
194
|
grpc-tools (>= 1, < 2)
|
|
195
195
|
nonnative!
|
|
196
196
|
rake (~> 13.0, >= 13.0.1)
|
|
197
|
-
rubocop (~> 0.
|
|
197
|
+
rubocop (~> 0.88)
|
|
198
198
|
simplecov (~> 0.17.1)
|
|
199
199
|
solargraph (~> 0.39.11)
|
|
200
200
|
|
data/README.md
CHANGED
|
@@ -37,10 +37,19 @@ Configure nonnative with the following:
|
|
|
37
37
|
- A timeout value.
|
|
38
38
|
- Port to verify.
|
|
39
39
|
- The class for servers.
|
|
40
|
-
- The
|
|
40
|
+
- The log for servers/processes
|
|
41
41
|
- The strategy for processes/servers.
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
|
|
43
|
+
### Strategy
|
|
44
|
+
|
|
45
|
+
The strategy can be one of the following values:
|
|
46
|
+
- startup - will start the process once.
|
|
47
|
+
- before - will hook into cucumbers Before and After.
|
|
48
|
+
- manual - do this manually
|
|
49
|
+
|
|
50
|
+
This can be overridden by the following environment variables:
|
|
51
|
+
- NONNATIVE_STRATEGY - Set this to override what is set in the config.
|
|
52
|
+
- NONNATIVE_TIMEOUT - Set this (in seconds, e.g 5) to override what is set in the config.
|
|
44
53
|
|
|
45
54
|
### Processes
|
|
46
55
|
|
|
@@ -50,14 +59,14 @@ Setup it up programmatically:
|
|
|
50
59
|
require 'nonnative'
|
|
51
60
|
|
|
52
61
|
Nonnative.configure do |config|
|
|
53
|
-
config.strategy = :startup
|
|
62
|
+
config.strategy = :startup
|
|
54
63
|
|
|
55
64
|
config.process do |d|
|
|
56
65
|
d.name = 'start_1'
|
|
57
66
|
d.command = 'features/support/bin/start 12_321'
|
|
58
|
-
d.timeout =
|
|
67
|
+
d.timeout = config.strategy.timeout
|
|
59
68
|
d.port = 12_321
|
|
60
|
-
d.
|
|
69
|
+
d.log = 'features/logs/12_321.log'
|
|
61
70
|
d.signal = 'INT' # Possible values are described in Signal.list.keys
|
|
62
71
|
end
|
|
63
72
|
|
|
@@ -66,7 +75,7 @@ Nonnative.configure do |config|
|
|
|
66
75
|
d.command = 'features/support/bin/start 12_322'
|
|
67
76
|
d.timeout = 0.5
|
|
68
77
|
d.port = 12_322
|
|
69
|
-
d.
|
|
78
|
+
d.log = 'features/logs/12_322.log'
|
|
70
79
|
end
|
|
71
80
|
end
|
|
72
81
|
```
|
|
@@ -82,14 +91,14 @@ processes:
|
|
|
82
91
|
command: features/support/bin/start 12_321
|
|
83
92
|
timeout: 5
|
|
84
93
|
port: 12321
|
|
85
|
-
|
|
94
|
+
log: features/logs/12_321.log
|
|
86
95
|
signal: INT # Possible values are described in Signal.list.keys
|
|
87
96
|
-
|
|
88
97
|
name: start_2
|
|
89
98
|
command: features/support/bin/start 12_322
|
|
90
99
|
timeout: 5
|
|
91
100
|
port: 12322
|
|
92
|
-
|
|
101
|
+
log: features/logs/12_322.log
|
|
93
102
|
```
|
|
94
103
|
|
|
95
104
|
Then load the file with
|
|
@@ -133,18 +142,20 @@ require 'nonnative'
|
|
|
133
142
|
Nonnative.configure do |config|
|
|
134
143
|
config.strategy = :manual
|
|
135
144
|
|
|
136
|
-
config.server do |
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
config.server do |s|
|
|
146
|
+
s.name = 'server_1'
|
|
147
|
+
s.klass = Nonnative::EchoServer
|
|
148
|
+
s.timeout = 1
|
|
149
|
+
s.port = 12_323
|
|
150
|
+
s.log = 'features/logs/server_1.log'
|
|
141
151
|
end
|
|
142
152
|
|
|
143
|
-
config.server do |
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
153
|
+
config.server do |s|
|
|
154
|
+
s.name = 'server_2'
|
|
155
|
+
s.klass = Nonnative::EchoServer
|
|
156
|
+
s.timeout = 1
|
|
157
|
+
s.port = 12_324
|
|
158
|
+
s.log = 'features/logs/server_2.log'
|
|
148
159
|
end
|
|
149
160
|
end
|
|
150
161
|
```
|
|
@@ -160,11 +171,13 @@ servers:
|
|
|
160
171
|
klass: Nonnative::EchoServer
|
|
161
172
|
timeout: 1
|
|
162
173
|
port: 12323
|
|
174
|
+
log: features/logs/server_1.log
|
|
163
175
|
-
|
|
164
176
|
name: server_2
|
|
165
177
|
klass: Nonnative::EchoServer
|
|
166
178
|
timeout: 1
|
|
167
179
|
port: 12324
|
|
180
|
+
log: features/logs/server_2.log
|
|
168
181
|
```
|
|
169
182
|
|
|
170
183
|
Then load the file with:
|
|
@@ -182,7 +195,11 @@ Define your server:
|
|
|
182
195
|
```ruby
|
|
183
196
|
module Nonnative
|
|
184
197
|
module Features
|
|
185
|
-
class Application < Sinatra::
|
|
198
|
+
class Application < Sinatra::Application
|
|
199
|
+
configure do
|
|
200
|
+
set :server_settings, log_requests: true
|
|
201
|
+
end
|
|
202
|
+
|
|
186
203
|
get '/hello' do
|
|
187
204
|
'Hello World!'
|
|
188
205
|
end
|
|
@@ -205,11 +222,12 @@ require 'nonnative'
|
|
|
205
222
|
Nonnative.configure do |config|
|
|
206
223
|
config.strategy = :manual
|
|
207
224
|
|
|
208
|
-
config.server do |
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
225
|
+
config.server do |s|
|
|
226
|
+
s.name = 'http_server_1'
|
|
227
|
+
s.klass = Nonnative::Features::HTTPServer
|
|
228
|
+
s.timeout = 1
|
|
229
|
+
s.port = 4567
|
|
230
|
+
s.log = 'features/logs/http_server_1.log'
|
|
213
231
|
end
|
|
214
232
|
end
|
|
215
233
|
```
|
|
@@ -225,6 +243,7 @@ servers:
|
|
|
225
243
|
klass: Nonnative::Features::HTTPServer
|
|
226
244
|
timeout: 1
|
|
227
245
|
port: 4567
|
|
246
|
+
log: features/logs/http_server_1.log
|
|
228
247
|
```
|
|
229
248
|
|
|
230
249
|
Then load the file with:
|
|
@@ -265,11 +284,12 @@ require 'nonnative'
|
|
|
265
284
|
Nonnative.configure do |config|
|
|
266
285
|
config.strategy = :manual
|
|
267
286
|
|
|
268
|
-
config.server do |
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
287
|
+
config.server do |s|
|
|
288
|
+
s.name = 'grpc_server_1'
|
|
289
|
+
s.klass = Nonnative::Features::GRPCServer
|
|
290
|
+
s.timeout = 1
|
|
291
|
+
s.port = 9002
|
|
292
|
+
s.log = 'features/logs/grpc_server_1.log'
|
|
273
293
|
end
|
|
274
294
|
end
|
|
275
295
|
```
|
|
@@ -285,6 +305,7 @@ servers:
|
|
|
285
305
|
klass: Nonnative::Features::GRPCServer
|
|
286
306
|
timeout: 1
|
|
287
307
|
port: 9002
|
|
308
|
+
log: features/logs/grpc_server_1.log
|
|
288
309
|
```
|
|
289
310
|
|
|
290
311
|
Then load the file with:
|
|
@@ -298,7 +319,7 @@ Nonnative.load_configuration('configuration.yml')
|
|
|
298
319
|
|
|
299
320
|
We allow different proxies to be configured. These proxies can be used to simulate all kind of situations. The proxies that can be configured are:
|
|
300
321
|
- `none` (this is the default)
|
|
301
|
-
- `
|
|
322
|
+
- `fault_injection`
|
|
302
323
|
|
|
303
324
|
Setup it up programmatically:
|
|
304
325
|
|
|
@@ -310,8 +331,9 @@ Nonnative.configure do |config|
|
|
|
310
331
|
|
|
311
332
|
config.server do |d|
|
|
312
333
|
d.proxy = {
|
|
313
|
-
type: '
|
|
334
|
+
type: 'fault_injection',
|
|
314
335
|
port: 20_000,
|
|
336
|
+
log: 'features/logs/proxy_server.log',
|
|
315
337
|
options: {
|
|
316
338
|
delay: 5
|
|
317
339
|
}
|
|
@@ -328,15 +350,16 @@ strategy: manual
|
|
|
328
350
|
servers:
|
|
329
351
|
-
|
|
330
352
|
proxy:
|
|
331
|
-
type:
|
|
353
|
+
type: fault_injection
|
|
332
354
|
port: 20000
|
|
355
|
+
log: features/logs/proxy_server.log
|
|
333
356
|
options:
|
|
334
357
|
delay: 5
|
|
335
358
|
```
|
|
336
359
|
|
|
337
360
|
##### Fault Injection
|
|
338
361
|
|
|
339
|
-
The `
|
|
362
|
+
The `fault_injection` proxy allows you to simulate failures by injecting them. We currently support the following:
|
|
340
363
|
- `close_all` - Closes the socket as soon as it connects.
|
|
341
364
|
- `delay` - This delays the communication between the connection. Default is 2 secs can be configured through options.
|
|
342
365
|
- `invalid_data` - This takes the input and rearranges it to produce invalid data.
|
|
@@ -350,3 +373,39 @@ server = Nonnative.pool.server_by_name(name)
|
|
|
350
373
|
server.proxy.close_all # To use close_all.
|
|
351
374
|
server.proxy.reset # To reset it back to a good state.
|
|
352
375
|
```
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
### Go
|
|
379
|
+
|
|
380
|
+
As we love using go as a language for services we have added support to start binaries with defined parameters. This expects that you build your services in the format of `command sub_command --params`
|
|
381
|
+
|
|
382
|
+
To get this to work you will need to create a `main_test.go` file with these contents:
|
|
383
|
+
|
|
384
|
+
```go
|
|
385
|
+
// +build features
|
|
386
|
+
|
|
387
|
+
package main
|
|
388
|
+
|
|
389
|
+
import (
|
|
390
|
+
"testing"
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
// TestFeatures is a hack that allows us to figure out what the coverage is during
|
|
394
|
+
// integration tests. I would not recommend that you use a binary built using
|
|
395
|
+
// this hack outside of a test suite.
|
|
396
|
+
func TestFeatures(t *testing.T) {
|
|
397
|
+
main()
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Then to compile this binary you will need to do the following:
|
|
402
|
+
|
|
403
|
+
```sh
|
|
404
|
+
go test -mod vendor -c -tags features -covermode=count -o your_binary -coverpkg=./... github.com/your_location
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Then to get an executable you do the following:
|
|
408
|
+
|
|
409
|
+
```ruby
|
|
410
|
+
Nonnative::GoCommand.new('your_binary', 'reports').executable('sub_command', '--config config.yaml')
|
|
411
|
+
```
|
data/lib/nonnative.rb
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require 'socket'
|
|
4
4
|
require 'timeout'
|
|
5
|
-
require 'thwait'
|
|
6
5
|
require 'yaml'
|
|
6
|
+
require 'open3'
|
|
7
7
|
|
|
8
8
|
require 'grpc'
|
|
9
9
|
require 'sinatra'
|
|
@@ -34,12 +34,14 @@ require 'nonnative/observability'
|
|
|
34
34
|
require 'nonnative/proxy_factory'
|
|
35
35
|
require 'nonnative/proxy'
|
|
36
36
|
require 'nonnative/no_proxy'
|
|
37
|
-
require 'nonnative/
|
|
37
|
+
require 'nonnative/fault_injection_proxy'
|
|
38
38
|
require 'nonnative/socket_pair'
|
|
39
39
|
require 'nonnative/close_all_socket_pair'
|
|
40
40
|
require 'nonnative/delay_socket_pair'
|
|
41
41
|
require 'nonnative/invalid_data_socket_pair'
|
|
42
42
|
require 'nonnative/socket_pair_factory'
|
|
43
|
+
require 'nonnative/strategy'
|
|
44
|
+
require 'nonnative/go_command'
|
|
43
45
|
|
|
44
46
|
module Nonnative
|
|
45
47
|
class << self
|
data/lib/nonnative/command.rb
CHANGED
|
@@ -24,7 +24,7 @@ module Nonnative
|
|
|
24
24
|
d.command = fd['command']
|
|
25
25
|
d.timeout = fd['timeout']
|
|
26
26
|
d.port = fd['port']
|
|
27
|
-
d.
|
|
27
|
+
d.log = fd['log']
|
|
28
28
|
d.signal = fd['signal']
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -38,6 +38,7 @@ module Nonnative
|
|
|
38
38
|
s.klass = Object.const_get(fd['klass'])
|
|
39
39
|
s.timeout = fd['timeout']
|
|
40
40
|
s.port = fd['port']
|
|
41
|
+
s.log = fd['log']
|
|
41
42
|
|
|
42
43
|
proxy = fd['proxy']
|
|
43
44
|
|
|
@@ -45,6 +46,7 @@ module Nonnative
|
|
|
45
46
|
s.proxy = {
|
|
46
47
|
type: proxy['type'],
|
|
47
48
|
port: proxy['port'],
|
|
49
|
+
log: proxy['log'],
|
|
48
50
|
options: proxy['options']
|
|
49
51
|
}
|
|
50
52
|
end
|
|
@@ -54,12 +56,17 @@ module Nonnative
|
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
def initialize
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
@strategy = Strategy.new
|
|
60
|
+
@processes = []
|
|
61
|
+
@servers = []
|
|
60
62
|
end
|
|
61
63
|
|
|
62
|
-
attr_accessor :
|
|
64
|
+
attr_accessor :processes, :servers
|
|
65
|
+
attr_reader :strategy
|
|
66
|
+
|
|
67
|
+
def strategy=(value)
|
|
68
|
+
@strategy = Strategy.new(value)
|
|
69
|
+
end
|
|
63
70
|
|
|
64
71
|
def process
|
|
65
72
|
process = Nonnative::ConfigurationProcess.new
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Nonnative
|
|
4
4
|
class ConfigurationServer
|
|
5
|
-
attr_accessor :name, :klass, :timeout, :port
|
|
5
|
+
attr_accessor :name, :klass, :timeout, :port, :log
|
|
6
6
|
attr_reader :proxy
|
|
7
7
|
|
|
8
8
|
def initialize
|
|
@@ -12,6 +12,7 @@ module Nonnative
|
|
|
12
12
|
def proxy=(value)
|
|
13
13
|
proxy.type = value[:type]
|
|
14
14
|
proxy.port = value[:port]
|
|
15
|
+
proxy.log = value[:log]
|
|
15
16
|
proxy.options = value[:options]
|
|
16
17
|
end
|
|
17
18
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Nonnative
|
|
4
|
-
class
|
|
4
|
+
class FaultInjectionProxy < Nonnative::Proxy
|
|
5
5
|
def initialize(service)
|
|
6
6
|
@connections = Concurrent::Hash.new
|
|
7
|
+
@logger = Logger.new(service.proxy.log)
|
|
7
8
|
@mutex = Mutex.new
|
|
8
9
|
@state = :none
|
|
9
10
|
|
|
@@ -42,19 +43,30 @@ module Nonnative
|
|
|
42
43
|
|
|
43
44
|
private
|
|
44
45
|
|
|
45
|
-
attr_reader :tcp_server, :thread, :connections, :mutex, :state
|
|
46
|
+
attr_reader :tcp_server, :thread, :connections, :mutex, :state, :logger
|
|
46
47
|
|
|
47
48
|
def perform_start
|
|
48
49
|
loop do
|
|
49
50
|
thread = Thread.start(tcp_server.accept) do |local_socket|
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
id = Thread.current.object_id
|
|
52
|
+
|
|
53
|
+
logger.info "started connection for #{id} with socket #{local_socket.inspect}"
|
|
54
|
+
|
|
55
|
+
connect local_socket
|
|
56
|
+
connections.delete(id)
|
|
57
|
+
|
|
58
|
+
logger.info "finished connection for #{id} with socket #{local_socket.inspect}"
|
|
52
59
|
end
|
|
60
|
+
|
|
53
61
|
thread.report_on_exception = false
|
|
54
62
|
connections[thread.object_id] = thread
|
|
55
63
|
end
|
|
56
64
|
end
|
|
57
65
|
|
|
66
|
+
def connect(local_socket)
|
|
67
|
+
SocketPairFactory.create(read_state, service.proxy, logger).connect(local_socket)
|
|
68
|
+
end
|
|
69
|
+
|
|
58
70
|
def apply_state(state)
|
|
59
71
|
mutex.synchronize { @state = state }
|
|
60
72
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Nonnative
|
|
4
|
+
class GoCommand
|
|
5
|
+
def initialize(main, output)
|
|
6
|
+
@main = main
|
|
7
|
+
@output = output
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def executable(cmd, *params)
|
|
11
|
+
params = params.join(' ')
|
|
12
|
+
"#{main} #{flags(cmd, params).join(' ')} #{cmd} #{params}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def execute(cmd, *params)
|
|
16
|
+
Open3.popen3(executable(cmd, params)) do |_stdin, stdout, stderr, wait_thr|
|
|
17
|
+
return stdout.read, stderr.read, wait_thr.value
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
attr_reader :main, :output
|
|
24
|
+
|
|
25
|
+
def flags(cmd, params)
|
|
26
|
+
m = File.basename(main, File.extname(main))
|
|
27
|
+
p = params.gsub(/\W/, '')
|
|
28
|
+
path = "#{output}/#{m}-#{cmd}-#{p}"
|
|
29
|
+
|
|
30
|
+
[
|
|
31
|
+
"-test.cpuprofile=#{path}-cpu.prof",
|
|
32
|
+
"-test.memprofile=#{path}-mem.prof",
|
|
33
|
+
"-test.blockprofile=#{path}-block.prof",
|
|
34
|
+
"-test.mutexprofile=#{path}-mutex.prof",
|
|
35
|
+
"-test.coverprofile=#{path}.cov",
|
|
36
|
+
"-test.trace=#{path}-trace.out"
|
|
37
|
+
]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -6,6 +6,11 @@ module Nonnative
|
|
|
6
6
|
@server = GRPC::RpcServer.new
|
|
7
7
|
server.handle(svc)
|
|
8
8
|
|
|
9
|
+
# Unfortunately gRPC has only one logger so the first server wins.
|
|
10
|
+
GRPC.define_singleton_method(:logger) do
|
|
11
|
+
@logger ||= Logger.new(service.log)
|
|
12
|
+
end
|
|
13
|
+
|
|
9
14
|
super service
|
|
10
15
|
end
|
|
11
16
|
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
module Nonnative
|
|
4
4
|
class HTTPServer < Nonnative::Server
|
|
5
5
|
def initialize(service)
|
|
6
|
-
|
|
6
|
+
log = File.open(service.log, 'a')
|
|
7
|
+
events = Puma::Events.new(log, log)
|
|
8
|
+
@server = Puma::Server.new(app, events)
|
|
7
9
|
|
|
8
10
|
super service
|
|
9
11
|
end
|
data/lib/nonnative/pool.rb
CHANGED
|
@@ -4,13 +4,14 @@ module Nonnative
|
|
|
4
4
|
class ProxyFactory
|
|
5
5
|
class << self
|
|
6
6
|
def create(service)
|
|
7
|
-
case service.proxy.type
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
proxy = case service.proxy.type
|
|
8
|
+
when 'fault_injection'
|
|
9
|
+
FaultInjectionProxy
|
|
10
|
+
else
|
|
11
|
+
NoProxy
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
proxy.new(service)
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
end
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Nonnative
|
|
4
4
|
class SocketPair
|
|
5
|
-
def initialize(proxy)
|
|
5
|
+
def initialize(proxy, logger)
|
|
6
6
|
@proxy = proxy
|
|
7
|
+
@logger = logger
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
def connect(local_socket)
|
|
@@ -15,6 +16,8 @@ module Nonnative
|
|
|
15
16
|
break if pipe(ready, local_socket, remote_socket)
|
|
16
17
|
break if pipe(ready, remote_socket, local_socket)
|
|
17
18
|
end
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
logger.error e
|
|
18
21
|
ensure
|
|
19
22
|
local_socket.close
|
|
20
23
|
remote_socket&.close
|
|
@@ -22,7 +25,7 @@ module Nonnative
|
|
|
22
25
|
|
|
23
26
|
protected
|
|
24
27
|
|
|
25
|
-
attr_reader :proxy
|
|
28
|
+
attr_reader :proxy, :logger
|
|
26
29
|
|
|
27
30
|
def create_remote_socket
|
|
28
31
|
::TCPSocket.new('0.0.0.0', proxy.port)
|
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
module Nonnative
|
|
4
4
|
class SocketPairFactory
|
|
5
5
|
class << self
|
|
6
|
-
def create(type,
|
|
7
|
-
case type
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
def create(type, proxy, logger)
|
|
7
|
+
pair = case type
|
|
8
|
+
when :close_all
|
|
9
|
+
CloseAllSocketPair
|
|
10
|
+
when :delay
|
|
11
|
+
DelaySocketPair
|
|
12
|
+
when :invalid_data
|
|
13
|
+
InvalidDataSocketPair
|
|
14
|
+
else
|
|
15
|
+
SocketPair
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
pair.new(proxy, logger)
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Nonnative
|
|
4
|
+
class Strategy
|
|
5
|
+
def initialize(strategy = 'before', timeout = 5)
|
|
6
|
+
@strategy = strategy
|
|
7
|
+
@timeout = timeout
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def timeout
|
|
11
|
+
(env_timeout || @timeout).to_i
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_s
|
|
15
|
+
(env_strategy || @strategy).to_s
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def env_strategy
|
|
21
|
+
@env_strategy ||= ENV['NONNATIVE_STRATEGY']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def env_timeout
|
|
25
|
+
@env_timeout ||= ENV['NONNATIVE_TIMEOUT']
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/nonnative/version.rb
CHANGED
data/nonnative.gemspec
CHANGED
|
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
|
|
|
36
36
|
spec.add_development_dependency 'bundler', '~> 2.1', '>= 2.1.4'
|
|
37
37
|
spec.add_development_dependency 'grpc-tools', ['>= 1', '< 2']
|
|
38
38
|
spec.add_development_dependency 'rake', '~> 13.0', '>= 13.0.1'
|
|
39
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
|
39
|
+
spec.add_development_dependency 'rubocop', '~> 0.88'
|
|
40
40
|
spec.add_development_dependency 'simplecov', '~> 0.17.1'
|
|
41
41
|
spec.add_development_dependency 'solargraph', '~> 0.39.11'
|
|
42
42
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nonnative
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.29.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex Falkowski
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-08-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: concurrent-ruby
|
|
@@ -224,14 +224,14 @@ dependencies:
|
|
|
224
224
|
requirements:
|
|
225
225
|
- - "~>"
|
|
226
226
|
- !ruby/object:Gem::Version
|
|
227
|
-
version: 0.
|
|
227
|
+
version: '0.88'
|
|
228
228
|
type: :development
|
|
229
229
|
prerelease: false
|
|
230
230
|
version_requirements: !ruby/object:Gem::Requirement
|
|
231
231
|
requirements:
|
|
232
232
|
- - "~>"
|
|
233
233
|
- !ruby/object:Gem::Version
|
|
234
|
-
version: 0.
|
|
234
|
+
version: '0.88'
|
|
235
235
|
- !ruby/object:Gem::Dependency
|
|
236
236
|
name: simplecov
|
|
237
237
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -283,7 +283,6 @@ files:
|
|
|
283
283
|
- bin/setup
|
|
284
284
|
- lib/nonnative.rb
|
|
285
285
|
- lib/nonnative/before.rb
|
|
286
|
-
- lib/nonnative/chaos_proxy.rb
|
|
287
286
|
- lib/nonnative/close_all_socket_pair.rb
|
|
288
287
|
- lib/nonnative/command.rb
|
|
289
288
|
- lib/nonnative/configuration.rb
|
|
@@ -292,6 +291,8 @@ files:
|
|
|
292
291
|
- lib/nonnative/configuration_server.rb
|
|
293
292
|
- lib/nonnative/delay_socket_pair.rb
|
|
294
293
|
- lib/nonnative/error.rb
|
|
294
|
+
- lib/nonnative/fault_injection_proxy.rb
|
|
295
|
+
- lib/nonnative/go_command.rb
|
|
295
296
|
- lib/nonnative/grpc_server.rb
|
|
296
297
|
- lib/nonnative/http_client.rb
|
|
297
298
|
- lib/nonnative/http_server.rb
|
|
@@ -310,6 +311,7 @@ files:
|
|
|
310
311
|
- lib/nonnative/start_error.rb
|
|
311
312
|
- lib/nonnative/startup.rb
|
|
312
313
|
- lib/nonnative/stop_error.rb
|
|
314
|
+
- lib/nonnative/strategy.rb
|
|
313
315
|
- lib/nonnative/timeout.rb
|
|
314
316
|
- lib/nonnative/version.rb
|
|
315
317
|
- nonnative.gemspec
|
|
@@ -318,7 +320,7 @@ homepage: https://github.com/alexfalkowski/nonnative
|
|
|
318
320
|
licenses:
|
|
319
321
|
- Unlicense
|
|
320
322
|
metadata: {}
|
|
321
|
-
post_install_message:
|
|
323
|
+
post_install_message:
|
|
322
324
|
rdoc_options: []
|
|
323
325
|
require_paths:
|
|
324
326
|
- lib
|
|
@@ -333,8 +335,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
333
335
|
- !ruby/object:Gem::Version
|
|
334
336
|
version: '0'
|
|
335
337
|
requirements: []
|
|
336
|
-
rubygems_version: 3.
|
|
337
|
-
signing_key:
|
|
338
|
+
rubygems_version: 3.1.2
|
|
339
|
+
signing_key:
|
|
338
340
|
specification_version: 4
|
|
339
341
|
summary: Allows you to keep using the power of ruby to test other systems
|
|
340
342
|
test_files: []
|