nonnative 1.19.0 → 1.24.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: d50a3cb35c875fa077d8ca3bd756e11d10deaffec26a90b142dc8e70a690ba97
4
- data.tar.gz: 8396fbee42d4d138ca270a39cf916f701a3874aa55c62312f05bc613de39b1ed
3
+ metadata.gz: 39dfda3ff344a41e06816d7f7cbc152a53d8b5bc98090113e1c79109ea2faf95
4
+ data.tar.gz: b1fbf5078dfa16d8fb89fc0699af0bebdc2a47473b455d71f3b7cd7bab390b8c
5
5
  SHA512:
6
- metadata.gz: f7b04f930d6743048cbb33bf5e7cdcfc915aee45ce1f788ec392fe100edab8a2a39e714fe6bb51a8bfd376d51c00c15870a3a3d5f79bd7449ce1ffaefbeea628
7
- data.tar.gz: 35df2beddc2ef0c9aae2c5f4c5c4f4e0a3ea013af03571a01024aa0cf329804f0867bd59d8087ec04c91eef10a53150a2a251998cf4fa4a1d07a4f66812f6328
6
+ metadata.gz: a797cf86fe77a38f9ebb5fa78f0dd20f24ce9e91f5666ae0c264ce1a37c9e91bba4ff19389da82c5de6fa48099d0187b6789fa1abb296383a8a186280b3b8ab0
7
+ data.tar.gz: 7a559c54037a22f2b01c995787cac36a076b5afbd8c68a3f1c72ed9f50f4543ff73d060514ea747c4db6964348d568d0a38c222476a33fa8886919e10b8ca093
@@ -6,10 +6,10 @@ Layout/LineLength:
6
6
  Max: 120
7
7
 
8
8
  Metrics/MethodLength:
9
- Max: 15
9
+ Max: 20
10
10
 
11
11
  Metrics/BlockLength:
12
- Max: 50
12
+ Max: 70
13
13
 
14
14
  Metrics/AbcSize:
15
15
  Max: 20
@@ -58,3 +58,12 @@ Style/RedundantRegexpEscape:
58
58
 
59
59
  Style/RedundantFetchBlock:
60
60
  Enabled: true
61
+
62
+ Style/AccessorGrouping:
63
+ Enabled: true
64
+
65
+ Style/BisectedAttrAccessor:
66
+ Enabled: true
67
+
68
+ Style/RedundantAssignment:
69
+ Enabled: true
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nonnative (1.19.0)
5
- cucumber (~> 3.1, >= 3.1.2)
6
- grpc (~> 1.28)
4
+ nonnative (1.24.0)
5
+ concurrent-ruby (~> 1.0, >= 1.0.5)
6
+ cucumber (>= 4, < 5)
7
+ grpc (>= 1, < 2)
7
8
  puma (~> 4.3, >= 4.3.3)
8
9
  rest-client (~> 2.1)
9
10
  rspec-benchmark (~> 0.6.0)
@@ -13,54 +14,64 @@ PATH
13
14
  GEM
14
15
  remote: https://rubygems.org/
15
16
  specs:
16
- amatch (0.4.0)
17
- mize
18
- tins (~> 1.0)
17
+ activesupport (6.0.3.2)
18
+ concurrent-ruby (~> 1.0, >= 1.0.2)
19
+ i18n (>= 0.7, < 2)
20
+ minitest (~> 5.1)
21
+ tzinfo (~> 1.1)
22
+ zeitwerk (~> 2.2, >= 2.2.2)
19
23
  ast (2.4.1)
20
24
  backport (1.1.2)
21
- backports (3.18.1)
22
25
  benchmark (0.1.0)
23
26
  benchmark-malloc (0.2.0)
24
27
  benchmark-perf (0.6.0)
25
28
  benchmark-trend (0.4.0)
26
29
  builder (3.2.4)
27
- chutney (2.0.3.1)
28
- amatch (~> 0.4.0)
29
- gherkin (~> 5.1.0)
30
- i18n (~> 1.8.2)
31
- pastel (~> 0.7)
32
- tty-pie (~> 0.3)
33
30
  concurrent-ruby (1.1.6)
34
- cucumber (3.2.0)
35
- builder (>= 2.1.2)
36
- cucumber-core (~> 3.2.0)
37
- cucumber-expressions (~> 6.0.1)
38
- cucumber-wire (~> 0.0.1)
39
- diff-lcs (~> 1.3)
40
- gherkin (~> 5.1.0)
41
- multi_json (>= 1.7.5, < 2.0)
42
- multi_test (>= 0.1.2)
43
- cucumber-core (3.2.1)
44
- backports (>= 3.8.0)
45
- cucumber-tag_expressions (~> 1.1.0)
46
- gherkin (~> 5.0)
47
- cucumber-expressions (6.0.1)
48
- cucumber-tag_expressions (1.1.1)
49
- cucumber-wire (0.0.1)
50
- diff-lcs (1.4.4)
31
+ cucumber (4.1.0)
32
+ builder (~> 3.2, >= 3.2.3)
33
+ cucumber-core (~> 7.1, >= 7.1.0)
34
+ cucumber-create-meta (~> 1.0.0, >= 1.0.0)
35
+ cucumber-cucumber-expressions (~> 10.1, >= 10.1.0)
36
+ cucumber-gherkin (~> 14.0, >= 14.0.1)
37
+ cucumber-html-formatter (~> 7.0, >= 7.0.0)
38
+ cucumber-messages (~> 12.2, >= 12.2.0)
39
+ cucumber-wire (~> 3.1, >= 3.1.0)
40
+ diff-lcs (~> 1.3, >= 1.3, < 1.4)
41
+ multi_test (~> 0.1, >= 0.1.2)
42
+ sys-uname (~> 1.0, >= 1.0.2)
43
+ cucumber-core (7.1.0)
44
+ cucumber-gherkin (~> 14.0, >= 14.0.1)
45
+ cucumber-messages (~> 12.2, >= 12.2.0)
46
+ cucumber-tag-expressions (~> 2.0, >= 2.0.4)
47
+ cucumber-create-meta (1.0.0)
48
+ cucumber-messages (~> 12.2, >= 12.2.0)
49
+ sys-uname (~> 1.2, >= 1.2.1)
50
+ cucumber-cucumber-expressions (10.2.1)
51
+ cucumber-gherkin (14.0.1)
52
+ cucumber-messages (~> 12.2, >= 12.2.0)
53
+ cucumber-html-formatter (7.0.0)
54
+ cucumber-messages (~> 12.2, >= 12.2.0)
55
+ cucumber-messages (12.2.0)
56
+ protobuf-cucumber (~> 3.10, >= 3.10.8)
57
+ cucumber-tag-expressions (2.0.4)
58
+ cucumber-wire (3.1.0)
59
+ cucumber-core (~> 7.1, >= 7.1.0)
60
+ cucumber-cucumber-expressions (~> 10.1, >= 10.1.0)
61
+ cucumber-messages (~> 12.2, >= 12.2.0)
62
+ diff-lcs (1.3)
51
63
  docile (1.3.2)
52
64
  domain_name (0.5.20190701)
53
65
  unf (>= 0.0.5, < 1.0.0)
54
66
  e2mmap (0.1.0)
55
- equatable (0.6.1)
56
- gherkin (5.1.0)
67
+ ffi (1.13.1)
57
68
  google-protobuf (3.12.2)
58
69
  googleapis-common-protos-types (1.0.5)
59
70
  google-protobuf (~> 3.11)
60
- grpc (1.28.0)
61
- google-protobuf (~> 3.11)
71
+ grpc (1.30.1)
72
+ google-protobuf (~> 3.12)
62
73
  googleapis-common-protos-types (~> 1.0)
63
- grpc-tools (1.28.0)
74
+ grpc-tools (1.30.1)
64
75
  http-accept (1.7.0)
65
76
  http-cookie (1.0.3)
66
77
  domain_name (~> 0.5)
@@ -69,28 +80,27 @@ GEM
69
80
  jaro_winkler (1.5.4)
70
81
  json (2.3.0)
71
82
  maruku (0.7.3)
83
+ middleware (0.1.0)
72
84
  mime-types (3.3.1)
73
85
  mime-types-data (~> 3.2015)
74
86
  mime-types-data (3.2020.0512)
75
87
  mini_portile2 (2.4.0)
76
- mize (0.4.0)
77
- protocol (~> 2.0)
78
- multi_json (1.14.1)
88
+ minitest (5.14.1)
79
89
  multi_test (0.1.2)
80
90
  mustermann (1.1.1)
81
91
  ruby2_keywords (~> 0.0.1)
82
92
  netrc (0.11.0)
83
93
  nio4r (2.5.2)
84
- nokogiri (1.10.9)
94
+ nokogiri (1.10.10)
85
95
  mini_portile2 (~> 2.4.0)
86
96
  parallel (1.19.2)
87
97
  parser (2.7.1.4)
88
98
  ast (~> 2.4.1)
89
- pastel (0.7.4)
90
- equatable (~> 0.6)
91
- tty-color (~> 0.5)
92
- protocol (2.0.0)
93
- ruby_parser (~> 3.0)
99
+ protobuf-cucumber (3.10.8)
100
+ activesupport (>= 3.2)
101
+ middleware
102
+ thor
103
+ thread_safe
94
104
  puma (4.3.5)
95
105
  nio4r (~> 2.0)
96
106
  rack (2.2.3)
@@ -125,22 +135,19 @@ GEM
125
135
  diff-lcs (>= 1.2.0, < 2.0)
126
136
  rspec-support (~> 3.9.0)
127
137
  rspec-support (3.9.3)
128
- rubocop (0.86.0)
138
+ rubocop (0.87.1)
129
139
  parallel (~> 1.10)
130
- parser (>= 2.7.0.1)
140
+ parser (>= 2.7.1.1)
131
141
  rainbow (>= 2.2.2, < 4.0)
132
142
  regexp_parser (>= 1.7)
133
143
  rexml
134
- rubocop-ast (>= 0.0.3, < 1.0)
144
+ rubocop-ast (>= 0.1.0, < 1.0)
135
145
  ruby-progressbar (~> 1.7)
136
146
  unicode-display_width (>= 1.4.0, < 2.0)
137
147
  rubocop-ast (0.1.0)
138
148
  parser (>= 2.7.0.1)
139
149
  ruby-progressbar (1.10.1)
140
150
  ruby2_keywords (0.0.2)
141
- ruby_parser (3.14.2)
142
- sexp_processor (~> 4.9)
143
- sexp_processor (4.15.0)
144
151
  simplecov (0.17.1)
145
152
  docile (~> 1.1)
146
153
  json (>= 1.8, < 3)
@@ -165,34 +172,31 @@ GEM
165
172
  thor (~> 1.0)
166
173
  tilt (~> 2.0)
167
174
  yard (~> 0.9, >= 0.9.24)
168
- sync (0.5.0)
175
+ sys-uname (1.2.1)
176
+ ffi (>= 1.0.0)
169
177
  thor (1.0.1)
178
+ thread_safe (0.3.6)
170
179
  tilt (2.0.10)
171
- tins (1.25.0)
172
- sync
173
- tty-color (0.5.1)
174
- tty-cursor (0.7.1)
175
- tty-pie (0.3.0)
176
- pastel (~> 0.7.3)
177
- tty-cursor (~> 0.7)
180
+ tzinfo (1.2.7)
181
+ thread_safe (~> 0.1)
178
182
  unf (0.1.4)
179
183
  unf_ext
180
184
  unf_ext (0.0.7.7)
181
185
  unicode-display_width (1.7.0)
182
186
  yard (0.9.25)
187
+ zeitwerk (2.3.1)
183
188
 
184
189
  PLATFORMS
185
190
  ruby
186
191
 
187
192
  DEPENDENCIES
188
193
  bundler (~> 2.1, >= 2.1.4)
189
- chutney (~> 2.0, >= 2.0.3.1)
190
- grpc-tools (~> 1.28)
194
+ grpc-tools (>= 1, < 2)
191
195
  nonnative!
192
196
  rake (~> 13.0, >= 13.0.1)
193
- rubocop (~> 0.86.0)
197
+ rubocop (~> 0.87.1)
194
198
  simplecov (~> 0.17.1)
195
- solargraph (~> 0.39.7)
199
+ solargraph (~> 0.39.11)
196
200
 
197
201
  BUNDLED WITH
198
202
  2.1.4
data/Makefile CHANGED
@@ -11,7 +11,6 @@ features: clean
11
11
 
12
12
  analysis:
13
13
  bundle exec rubocop
14
- bundle exec chutney
15
14
 
16
15
  cleanup-analysis:
17
16
  bundle exec rubocop -a
data/README.md CHANGED
@@ -297,8 +297,8 @@ Nonnative.load_configuration('configuration.yml')
297
297
  #### Proxies
298
298
 
299
299
  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
- - none (this is the default)
301
- - chaos
300
+ - `none` (this is the default)
301
+ - `chaos`
302
302
 
303
303
  Setup it up programmatically:
304
304
 
@@ -309,8 +309,13 @@ Nonnative.configure do |config|
309
309
  config.strategy = :manual
310
310
 
311
311
  config.server do |d|
312
- d.proxy.type = 'chaos'
313
- d.proxy.port = 20_000
312
+ d.proxy = {
313
+ type: 'chaos',
314
+ port: 20_000,
315
+ options: {
316
+ delay: 5
317
+ }
318
+ }
314
319
  end
315
320
  end
316
321
  ```
@@ -325,4 +330,23 @@ servers:
325
330
  proxy:
326
331
  type: chaos
327
332
  port: 20000
333
+ options:
334
+ delay: 5
335
+ ```
336
+
337
+ ##### Fault Injection
338
+
339
+ The `chaos` proxy allows you to simulate failures by injecting them. We currently support the following:
340
+ - `close_all` - Closes the socket as soon as it connects.
341
+ - `delay` - This delays the communication between the connection. Default is 2 secs can be configured through options.
342
+ - `invalid_data` - This takes the input and rearranges it to produce invalid data.
343
+
344
+ Setup it up programmatically:
345
+
346
+ ```ruby
347
+ name = 'name of server in configuration'
348
+ server = Nonnative.pool.server_by_name(name)
349
+
350
+ server.proxy.close_all # To use close_all.
351
+ server.proxy.reset # To reset it back to a good state.
328
352
  ```
@@ -10,6 +10,7 @@ require 'sinatra'
10
10
  require 'rest-client'
11
11
  require 'puma'
12
12
  require 'puma/server'
13
+ require 'concurrent'
13
14
 
14
15
  require 'nonnative/version'
15
16
  require 'nonnative/error'
@@ -34,11 +35,16 @@ require 'nonnative/proxy_factory'
34
35
  require 'nonnative/proxy'
35
36
  require 'nonnative/no_proxy'
36
37
  require 'nonnative/chaos_proxy'
37
-
38
- Thread.abort_on_exception = true
38
+ require 'nonnative/socket_pair'
39
+ require 'nonnative/close_all_socket_pair'
40
+ require 'nonnative/delay_socket_pair'
41
+ require 'nonnative/invalid_data_socket_pair'
42
+ require 'nonnative/socket_pair_factory'
39
43
 
40
44
  module Nonnative
41
45
  class << self
46
+ attr_reader :pool
47
+
42
48
  def load_configuration(path)
43
49
  @configuration ||= Nonnative::Configuration.load_file(path) # rubocop:disable Naming/MemoizedInstanceVariableName
44
50
  end
@@ -2,6 +2,14 @@
2
2
 
3
3
  module Nonnative
4
4
  class ChaosProxy < Nonnative::Proxy
5
+ def initialize(service)
6
+ @connections = Concurrent::Hash.new
7
+ @mutex = Mutex.new
8
+ @state = :none
9
+
10
+ super service
11
+ end
12
+
5
13
  def start
6
14
  @tcp_server = ::TCPServer.new('0.0.0.0', service.port)
7
15
  @thread = Thread.new { perform_start }
@@ -12,55 +20,47 @@ module Nonnative
12
20
  tcp_server.close
13
21
  end
14
22
 
23
+ def close_all
24
+ apply_state :close_all
25
+ end
26
+
27
+ def delay
28
+ apply_state :delay
29
+ end
30
+
31
+ def invalid_data
32
+ apply_state :invalid_data
33
+ end
34
+
35
+ def reset
36
+ apply_state :none
37
+ end
38
+
15
39
  def port
16
40
  service.proxy.port
17
41
  end
18
42
 
19
43
  private
20
44
 
21
- attr_reader :tcp_server, :thread
45
+ attr_reader :tcp_server, :thread, :connections, :mutex, :state
22
46
 
23
47
  def perform_start
24
48
  loop do
25
- Thread.start(tcp_server.accept) { |local_socket| connect(local_socket) }
49
+ thread = Thread.start(tcp_server.accept) do |local_socket|
50
+ SocketPairFactory.create(read_state, service.proxy).connect(local_socket)
51
+ connections.delete(Thread.current.object_id)
52
+ end
53
+ thread.report_on_exception = false
54
+ connections[thread.object_id] = thread
26
55
  end
27
56
  end
28
57
 
29
- def connect(local_socket)
30
- remote_socket = create_remote_socket
31
- return unless remote_socket
32
-
33
- loop do
34
- ready = select([local_socket, remote_socket], nil, nil)
35
-
36
- break if write(ready, local_socket, remote_socket)
37
- break if write(ready, remote_socket, local_socket)
38
- end
39
- rescue Errno::ECONNRESET
40
- # Just ignore it.
41
- ensure
42
- local_socket.close
43
- remote_socket&.close
44
- end
45
-
46
- def create_remote_socket
47
- timeout.perform do
48
- ::TCPSocket.new('0.0.0.0', port)
49
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
50
- sleep 0.01
51
- retry
52
- end
58
+ def apply_state(state)
59
+ mutex.synchronize { @state = state }
53
60
  end
54
61
 
55
- def write(ready, socket1, socket2)
56
- if ready[0].include?(socket1)
57
- data = socket1.recv(1024)
58
- return true if data.empty?
59
-
60
- socket2.write(data)
61
- end
62
-
63
- false
62
+ def read_state
63
+ mutex.synchronize { state }
64
64
  end
65
65
  end
66
66
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class CloseAllSocketPair < SocketPair
5
+ def connect(local_socket)
6
+ local_socket.close
7
+ end
8
+ end
9
+ end
@@ -42,8 +42,11 @@ module Nonnative
42
42
  proxy = fd['proxy']
43
43
 
44
44
  if proxy
45
- s.proxy.type = proxy['type']
46
- s.proxy.port = proxy['port']
45
+ s.proxy = {
46
+ type: proxy['type'],
47
+ port: proxy['port'],
48
+ options: proxy['options']
49
+ }
47
50
  end
48
51
  end
49
52
  end
@@ -56,9 +59,7 @@ module Nonnative
56
59
  self.servers = []
57
60
  end
58
61
 
59
- attr_accessor :strategy
60
- attr_accessor :processes
61
- attr_accessor :servers
62
+ attr_accessor :strategy, :processes, :servers
62
63
 
63
64
  def process
64
65
  process = Nonnative::ConfigurationProcess.new
@@ -2,11 +2,6 @@
2
2
 
3
3
  module Nonnative
4
4
  class ConfigurationProcess
5
- attr_accessor :name
6
- attr_accessor :command
7
- attr_accessor :timeout
8
- attr_accessor :port
9
- attr_accessor :file
10
- attr_accessor :signal
5
+ attr_accessor :name, :command, :timeout, :port, :file, :signal
11
6
  end
12
7
  end
@@ -2,12 +2,12 @@
2
2
 
3
3
  module Nonnative
4
4
  class ConfigurationProxy
5
- attr_accessor :type
6
- attr_accessor :port
5
+ attr_accessor :type, :port, :options
7
6
 
8
7
  def initialize
9
8
  self.type = 'none'
10
9
  self.port = 0
10
+ self.options = {}
11
11
  end
12
12
  end
13
13
  end
@@ -2,14 +2,17 @@
2
2
 
3
3
  module Nonnative
4
4
  class ConfigurationServer
5
- attr_accessor :name
6
- attr_accessor :klass
7
- attr_accessor :timeout
8
- attr_accessor :port
9
- attr_accessor :proxy
5
+ attr_accessor :name, :klass, :timeout, :port
6
+ attr_reader :proxy
10
7
 
11
8
  def initialize
12
- self.proxy = Nonnative::ConfigurationProxy.new
9
+ @proxy = Nonnative::ConfigurationProxy.new
10
+ end
11
+
12
+ def proxy=(value)
13
+ proxy.type = value[:type]
14
+ proxy.port = value[:port]
15
+ proxy.options = value[:options]
13
16
  end
14
17
  end
15
18
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class DelaySocketPair < SocketPair
5
+ def read(socket)
6
+ duration = proxy.options.dig(:delay) || 2
7
+ sleep duration
8
+
9
+ super socket
10
+ end
11
+ end
12
+ end
@@ -8,31 +8,33 @@ module Nonnative
8
8
 
9
9
  protected
10
10
 
11
- def get(pathname, headers = {})
11
+ def get(pathname, headers = {}, timeout = 60)
12
12
  with_exception do
13
13
  uri = URI.join(host, pathname)
14
- RestClient.get(uri.to_s, headers)
14
+ RestClient::Request.execute(method: :get, url: uri.to_s, headers: headers, timeout: timeout)
15
15
  end
16
16
  end
17
17
 
18
- def post(pathname, payload, headers = {})
18
+ def post(pathname, payload, headers = {}, timeout = 60)
19
19
  with_exception do
20
20
  uri = URI.join(host, pathname)
21
- RestClient.post(uri.to_s, payload.to_json, headers)
21
+ RestClient::Request.execute(method: :post, url: uri.to_s, payload: payload.to_json, headers: headers,
22
+ timeout: timeout)
22
23
  end
23
24
  end
24
25
 
25
- def delete(pathname, headers = {})
26
+ def delete(pathname, headers = {}, timeout = 60)
26
27
  with_exception do
27
28
  uri = URI.join(host, pathname)
28
- RestClient.delete(uri.to_s, headers)
29
+ RestClient::Request.execute(method: :delete, url: uri.to_s, headers: headers, timeout: timeout)
29
30
  end
30
31
  end
31
32
 
32
- def put(pathname, payload, headers = {})
33
+ def put(pathname, payload, headers = {}, timeout = 60)
33
34
  with_exception do
34
35
  uri = URI.join(host, pathname)
35
- RestClient.put(uri.to_s, payload.to_json, headers)
36
+ RestClient::Request.execute(method: :put, url: uri.to_s, payload: payload.to_json, headers: headers,
37
+ timeout: timeout)
36
38
  end
37
39
  end
38
40
 
@@ -42,6 +44,8 @@ module Nonnative
42
44
 
43
45
  def with_exception
44
46
  yield
47
+ rescue RestClient::Exceptions::ReadTimeout => e
48
+ raise e
45
49
  rescue RestClient::ExceptionWithResponse => e
46
50
  e.response
47
51
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class InvalidDataSocketPair < SocketPair
5
+ def write(socket, data)
6
+ data = data.chars.shuffle.join
7
+
8
+ super socket, data
9
+ end
10
+ end
11
+ end
@@ -14,6 +14,11 @@ module Nonnative
14
14
  [processes, servers].each { |t| process(t, :stop, :closed?, &block) }
15
15
  end
16
16
 
17
+ def server_by_name(name)
18
+ index = configuration.servers.find_index { |s| s.name == name }
19
+ servers[index].first
20
+ end
21
+
17
22
  private
18
23
 
19
24
  attr_reader :configuration
@@ -4,11 +4,10 @@ module Nonnative
4
4
  class Proxy
5
5
  def initialize(service)
6
6
  @service = service
7
- @timeout = Nonnative::Timeout.new(service.timeout)
8
7
  end
9
8
 
10
9
  protected
11
10
 
12
- attr_reader :service, :timeout
11
+ attr_reader :service
13
12
  end
14
13
  end
@@ -2,8 +2,9 @@
2
2
 
3
3
  module Nonnative
4
4
  class Server < Nonnative::Service
5
+ attr_reader :proxy
6
+
5
7
  def initialize(service)
6
- @id = SecureRandom.hex(5)
7
8
  @proxy = Nonnative::ProxyFactory.create(service)
8
9
 
9
10
  super service
@@ -17,7 +18,7 @@ module Nonnative
17
18
  wait_start
18
19
  end
19
20
 
20
- id
21
+ object_id
21
22
  end
22
23
 
23
24
  def stop
@@ -30,15 +31,11 @@ module Nonnative
30
31
  wait_stop
31
32
  end
32
33
 
33
- id
34
+ object_id
34
35
  end
35
36
 
36
- protected
37
-
38
- attr_reader :id
39
-
40
37
  private
41
38
 
42
- attr_reader :proxy, :thread
39
+ attr_reader :thread
43
40
  end
44
41
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class SocketPair
5
+ def initialize(proxy)
6
+ @proxy = proxy
7
+ end
8
+
9
+ def connect(local_socket)
10
+ remote_socket = create_remote_socket
11
+
12
+ loop do
13
+ ready = select([local_socket, remote_socket], nil, nil)
14
+
15
+ break if pipe(ready, local_socket, remote_socket)
16
+ break if pipe(ready, remote_socket, local_socket)
17
+ end
18
+ ensure
19
+ local_socket.close
20
+ remote_socket&.close
21
+ end
22
+
23
+ protected
24
+
25
+ attr_reader :proxy
26
+
27
+ def create_remote_socket
28
+ ::TCPSocket.new('0.0.0.0', proxy.port)
29
+ end
30
+
31
+ def pipe(ready, socket1, socket2)
32
+ if ready[0].include?(socket1)
33
+ data = read(socket1)
34
+ return true if data.empty?
35
+
36
+ write socket2, data
37
+ end
38
+
39
+ false
40
+ end
41
+
42
+ def read(socket)
43
+ socket.recv(1024)
44
+ end
45
+
46
+ def write(socket, data)
47
+ socket.write(data)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class SocketPairFactory
5
+ class << self
6
+ def create(type, port)
7
+ case type
8
+ when :close_all
9
+ CloseAllSocketPair.new(port)
10
+ when :delay
11
+ DelaySocketPair.new(port)
12
+ when :invalid_data
13
+ InvalidDataSocketPair.new(port)
14
+ else
15
+ SocketPair.new(port)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- VERSION = '1.19.0'
4
+ VERSION = '1.24.0'
5
5
  end
@@ -24,8 +24,9 @@ Gem::Specification.new do |spec|
24
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ['lib']
26
26
 
27
- spec.add_dependency 'cucumber', '~> 3.1', '>= 3.1.2'
28
- spec.add_dependency 'grpc', '~> 1.28'
27
+ spec.add_dependency 'concurrent-ruby', '~> 1.0', '>= 1.0.5'
28
+ spec.add_dependency 'cucumber', ['>= 4', '< 5']
29
+ spec.add_dependency 'grpc', ['>= 1', '< 2']
29
30
  spec.add_dependency 'puma', '~> 4.3', '>= 4.3.3'
30
31
  spec.add_dependency 'rest-client', '~> 2.1'
31
32
  spec.add_dependency 'rspec-benchmark', '~> 0.6.0'
@@ -33,10 +34,9 @@ Gem::Specification.new do |spec|
33
34
  spec.add_dependency 'sinatra', '~> 2.0', '>= 2.0.8.1'
34
35
 
35
36
  spec.add_development_dependency 'bundler', '~> 2.1', '>= 2.1.4'
36
- spec.add_development_dependency 'chutney', '~> 2.0', '>= 2.0.3.1'
37
- spec.add_development_dependency 'grpc-tools', '~> 1.28'
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.86.0'
39
+ spec.add_development_dependency 'rubocop', '~> 0.87.1'
40
40
  spec.add_development_dependency 'simplecov', '~> 0.17.1'
41
- spec.add_development_dependency 'solargraph', '~> 0.39.7'
41
+ spec.add_development_dependency 'solargraph', '~> 0.39.11'
42
42
  end
metadata CHANGED
@@ -1,49 +1,75 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nonnative
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.19.0
4
+ version: 1.24.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-07-05 00:00:00.000000000 Z
11
+ date: 2020-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: cucumber
14
+ name: concurrent-ruby
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.1'
19
+ version: '1.0'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 3.1.2
22
+ version: 1.0.5
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '3.1'
29
+ version: '1.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.5
33
+ - !ruby/object:Gem::Dependency
34
+ name: cucumber
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '4'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '5'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
30
47
  - - ">="
31
48
  - !ruby/object:Gem::Version
32
- version: 3.1.2
49
+ version: '4'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '5'
33
53
  - !ruby/object:Gem::Dependency
34
54
  name: grpc
35
55
  requirement: !ruby/object:Gem::Requirement
36
56
  requirements:
37
- - - "~>"
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '1'
60
+ - - "<"
38
61
  - !ruby/object:Gem::Version
39
- version: '1.28'
62
+ version: '2'
40
63
  type: :runtime
41
64
  prerelease: false
42
65
  version_requirements: !ruby/object:Gem::Requirement
43
66
  requirements:
44
- - - "~>"
67
+ - - ">="
45
68
  - !ruby/object:Gem::Version
46
- version: '1.28'
69
+ version: '1'
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '2'
47
73
  - !ruby/object:Gem::Dependency
48
74
  name: puma
49
75
  requirement: !ruby/object:Gem::Requirement
@@ -153,39 +179,25 @@ dependencies:
153
179
  - !ruby/object:Gem::Version
154
180
  version: 2.1.4
155
181
  - !ruby/object:Gem::Dependency
156
- name: chutney
182
+ name: grpc-tools
157
183
  requirement: !ruby/object:Gem::Requirement
158
184
  requirements:
159
- - - "~>"
160
- - !ruby/object:Gem::Version
161
- version: '2.0'
162
185
  - - ">="
163
186
  - !ruby/object:Gem::Version
164
- version: 2.0.3.1
187
+ version: '1'
188
+ - - "<"
189
+ - !ruby/object:Gem::Version
190
+ version: '2'
165
191
  type: :development
166
192
  prerelease: false
167
193
  version_requirements: !ruby/object:Gem::Requirement
168
194
  requirements:
169
- - - "~>"
170
- - !ruby/object:Gem::Version
171
- version: '2.0'
172
195
  - - ">="
173
196
  - !ruby/object:Gem::Version
174
- version: 2.0.3.1
175
- - !ruby/object:Gem::Dependency
176
- name: grpc-tools
177
- requirement: !ruby/object:Gem::Requirement
178
- requirements:
179
- - - "~>"
180
- - !ruby/object:Gem::Version
181
- version: '1.28'
182
- type: :development
183
- prerelease: false
184
- version_requirements: !ruby/object:Gem::Requirement
185
- requirements:
186
- - - "~>"
197
+ version: '1'
198
+ - - "<"
187
199
  - !ruby/object:Gem::Version
188
- version: '1.28'
200
+ version: '2'
189
201
  - !ruby/object:Gem::Dependency
190
202
  name: rake
191
203
  requirement: !ruby/object:Gem::Requirement
@@ -212,14 +224,14 @@ dependencies:
212
224
  requirements:
213
225
  - - "~>"
214
226
  - !ruby/object:Gem::Version
215
- version: 0.86.0
227
+ version: 0.87.1
216
228
  type: :development
217
229
  prerelease: false
218
230
  version_requirements: !ruby/object:Gem::Requirement
219
231
  requirements:
220
232
  - - "~>"
221
233
  - !ruby/object:Gem::Version
222
- version: 0.86.0
234
+ version: 0.87.1
223
235
  - !ruby/object:Gem::Dependency
224
236
  name: simplecov
225
237
  requirement: !ruby/object:Gem::Requirement
@@ -240,14 +252,14 @@ dependencies:
240
252
  requirements:
241
253
  - - "~>"
242
254
  - !ruby/object:Gem::Version
243
- version: 0.39.7
255
+ version: 0.39.11
244
256
  type: :development
245
257
  prerelease: false
246
258
  version_requirements: !ruby/object:Gem::Requirement
247
259
  requirements:
248
260
  - - "~>"
249
261
  - !ruby/object:Gem::Version
250
- version: 0.39.7
262
+ version: 0.39.11
251
263
  description: Allows you to keep using the power of ruby to test other systems
252
264
  email:
253
265
  - alexrfalkowski@gmail.com
@@ -272,15 +284,18 @@ files:
272
284
  - lib/nonnative.rb
273
285
  - lib/nonnative/before.rb
274
286
  - lib/nonnative/chaos_proxy.rb
287
+ - lib/nonnative/close_all_socket_pair.rb
275
288
  - lib/nonnative/command.rb
276
289
  - lib/nonnative/configuration.rb
277
290
  - lib/nonnative/configuration_process.rb
278
291
  - lib/nonnative/configuration_proxy.rb
279
292
  - lib/nonnative/configuration_server.rb
293
+ - lib/nonnative/delay_socket_pair.rb
280
294
  - lib/nonnative/error.rb
281
295
  - lib/nonnative/grpc_server.rb
282
296
  - lib/nonnative/http_client.rb
283
297
  - lib/nonnative/http_server.rb
298
+ - lib/nonnative/invalid_data_socket_pair.rb
284
299
  - lib/nonnative/manual.rb
285
300
  - lib/nonnative/no_proxy.rb
286
301
  - lib/nonnative/observability.rb
@@ -290,6 +305,8 @@ files:
290
305
  - lib/nonnative/proxy_factory.rb
291
306
  - lib/nonnative/server.rb
292
307
  - lib/nonnative/service.rb
308
+ - lib/nonnative/socket_pair.rb
309
+ - lib/nonnative/socket_pair_factory.rb
293
310
  - lib/nonnative/start_error.rb
294
311
  - lib/nonnative/startup.rb
295
312
  - lib/nonnative/stop_error.rb
@@ -301,7 +318,7 @@ homepage: https://github.com/alexfalkowski/nonnative
301
318
  licenses:
302
319
  - Unlicense
303
320
  metadata: {}
304
- post_install_message:
321
+ post_install_message:
305
322
  rdoc_options: []
306
323
  require_paths:
307
324
  - lib
@@ -316,8 +333,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
316
333
  - !ruby/object:Gem::Version
317
334
  version: '0'
318
335
  requirements: []
319
- rubygems_version: 3.0.3
320
- signing_key:
336
+ rubygems_version: 3.0.8
337
+ signing_key:
321
338
  specification_version: 4
322
339
  summary: Allows you to keep using the power of ruby to test other systems
323
340
  test_files: []