nonnative 0.8.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e8928eb7a827f2a160e04c23364ee50004d1ee643b9fc1b46b4bdd17ef882388
4
- data.tar.gz: efc2aef3d031abe3edabef19c48db62a400506f4431af16cc55c21e3d49b47d8
3
+ metadata.gz: 9c10339b1e71b31706b70b61c1107c2e1cfef46da91852f3d973065da3ab150c
4
+ data.tar.gz: '0619ca746648a935a9b3904a5cc33f40bc324d1a66db289ed98466ed2207aa38'
5
5
  SHA512:
6
- metadata.gz: 70d457b4ab3b4c7427ce93155bc26da56e0a32c90a2568ad738aa53b1a871bde52f363b01f48fc4194c5908c3ea76e7f6cc74845de8a9860f3b41986e01b709d
7
- data.tar.gz: 88a31eea446d14d0e9271501aa5997832e023235ff0b6f282d237c9796c01732993e961c46c0bed7f281be31f926554ac72a755393b99ce36fcb047d10b49e6d
6
+ metadata.gz: dfb30c7fd56bd14dc6d4fb8bddc1770a1afee0feeb79e99992510464401fff9953415433b9b139bb2725a264d6749e9d6eaeb868b7d0f29a7d20656e871eabf8
7
+ data.tar.gz: d0fd3db73e4b91c419bae57cb76c0d1a10e7d7a17310c16dad6fb82e49eefab87a533ca32c6cfa7cb44ca505742a33c4b83e0bde024d9dcba3457578a6f295c4
data/.circleci/config.yml CHANGED
@@ -20,3 +20,6 @@ jobs:
20
20
  - vendor/bundle
21
21
  - run: make features
22
22
  - run: make analysis
23
+ - run: make audit
24
+ - store_artifacts:
25
+ path: features/logs
data/.gitignore CHANGED
@@ -8,4 +8,4 @@
8
8
  /tmp/
9
9
  vendor
10
10
  coverage
11
- logs
11
+ features/logs/*.log
data/.rubocop.yml CHANGED
@@ -2,7 +2,7 @@ AllCops:
2
2
  TargetRubyVersion: 2.6
3
3
  DisplayCopNames: true
4
4
 
5
- Metrics/LineLength:
5
+ Layout/LineLength:
6
6
  Max: 120
7
7
 
8
8
  Style/Documentation:
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.6.3
1
+ ruby-2.6.5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nonnative (0.8.0)
4
+ nonnative (1.0.0)
5
5
  cucumber
6
6
  rspec-expectations
7
7
  semantic_logger
@@ -10,10 +10,15 @@ GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
12
  ast (2.4.0)
13
- backport (1.1.2)
14
- backports (3.15.0)
15
- builder (3.2.3)
16
- concurrent-ruby (1.1.5)
13
+ backports (3.16.1)
14
+ benchmark-malloc (0.1.0)
15
+ benchmark-perf (0.5.0)
16
+ benchmark-trend (0.3.0)
17
+ builder (3.2.4)
18
+ bundler-audit (0.6.1)
19
+ bundler (>= 1.2.0, < 3)
20
+ thor (~> 0.18)
21
+ concurrent-ruby (1.1.6)
17
22
  cucumber (3.1.2)
18
23
  builder (>= 2.1.2)
19
24
  cucumber-core (~> 3.2.0)
@@ -33,67 +38,62 @@ GEM
33
38
  diff-lcs (1.3)
34
39
  docile (1.3.2)
35
40
  gherkin (5.1.0)
36
- htmlentities (4.3.4)
37
- jaro_winkler (1.5.3)
38
- json (2.2.0)
39
- mini_portile2 (2.4.0)
40
- multi_json (1.13.1)
41
+ jaro_winkler (1.5.4)
42
+ multi_json (1.14.1)
41
43
  multi_test (0.1.2)
42
- nokogiri (1.10.4)
43
- mini_portile2 (~> 2.4.0)
44
- parallel (1.17.0)
45
- parser (2.6.4.0)
44
+ parallel (1.19.1)
45
+ parser (2.7.0.2)
46
46
  ast (~> 2.4.0)
47
47
  rainbow (3.0.0)
48
- rake (12.3.3)
49
- reverse_markdown (1.2.0)
50
- nokogiri
51
- rspec-expectations (3.8.4)
48
+ rake (13.0.1)
49
+ rexml (3.2.4)
50
+ rspec (3.9.0)
51
+ rspec-core (~> 3.9.0)
52
+ rspec-expectations (~> 3.9.0)
53
+ rspec-mocks (~> 3.9.0)
54
+ rspec-benchmark (0.5.1)
55
+ benchmark-malloc (~> 0.1.0)
56
+ benchmark-perf (~> 0.5.0)
57
+ benchmark-trend (~> 0.3.0)
58
+ rspec (>= 3.0.0, < 4.0.0)
59
+ rspec-core (3.9.1)
60
+ rspec-support (~> 3.9.1)
61
+ rspec-expectations (3.9.0)
52
62
  diff-lcs (>= 1.2.0, < 2.0)
53
- rspec-support (~> 3.8.0)
54
- rspec-support (3.8.2)
55
- rubocop (0.74.0)
63
+ rspec-support (~> 3.9.0)
64
+ rspec-mocks (3.9.1)
65
+ diff-lcs (>= 1.2.0, < 2.0)
66
+ rspec-support (~> 3.9.0)
67
+ rspec-support (3.9.2)
68
+ rubocop (0.80.0)
56
69
  jaro_winkler (~> 1.5.1)
57
70
  parallel (~> 1.10)
58
- parser (>= 2.6)
71
+ parser (>= 2.7.0.1)
59
72
  rainbow (>= 2.2.2, < 4.0)
73
+ rexml
60
74
  ruby-progressbar (~> 1.7)
61
75
  unicode-display_width (>= 1.4.0, < 1.7)
62
76
  ruby-progressbar (1.10.1)
63
- semantic_logger (4.5.0)
77
+ semantic_logger (4.6.0)
64
78
  concurrent-ruby (~> 1.0)
65
- simplecov (0.17.0)
79
+ simplecov (0.18.2)
66
80
  docile (~> 1.1)
67
- json (>= 1.8, < 3)
68
- simplecov-html (~> 0.10.0)
69
- simplecov-html (0.10.2)
70
- solargraph (0.37.2)
71
- backport (~> 1.1)
72
- bundler (>= 1.17.2)
73
- htmlentities (~> 4.3, >= 4.3.4)
74
- jaro_winkler (~> 1.5)
75
- nokogiri (~> 1.9, >= 1.9.1)
76
- parser (~> 2.3)
77
- reverse_markdown (~> 1.0, >= 1.0.5)
78
- rubocop (~> 0.52)
79
- thor (~> 0.19, >= 0.19.4)
80
- tilt (~> 2.0)
81
- yard (~> 0.9)
81
+ simplecov-html (~> 0.11)
82
+ simplecov-html (0.12.0)
82
83
  thor (0.20.3)
83
- tilt (2.0.9)
84
- unicode-display_width (1.6.0)
85
- yard (0.9.20)
84
+ unicode-display_width (1.6.1)
86
85
 
87
86
  PLATFORMS
88
87
  ruby
89
88
 
90
89
  DEPENDENCIES
91
90
  bundler
91
+ bundler-audit
92
92
  nonnative!
93
93
  rake
94
+ rspec-benchmark
94
95
  rubocop
95
96
  simplecov
96
- solargraph
97
97
 
98
98
  BUNDLED WITH
99
- 1.17.2
99
+ 2.1.4
data/Makefile CHANGED
@@ -3,8 +3,21 @@
3
3
  dependencies:
4
4
  bin/setup
5
5
 
6
+ outdated-dependencies:
7
+ bundle outdated --only-explicit
8
+
6
9
  features:
7
- bundle exec cucumber
10
+ bundle exec cucumber $(feature)
8
11
 
9
12
  analysis:
10
13
  bundle exec rubocop
14
+
15
+ audit:
16
+ bundle exec bundle-audit update
17
+ bundle exec bundle-audit
18
+
19
+ cleanup-analysis:
20
+ bundle exec rubocop -a
21
+
22
+ cleanup-logs:
23
+ rm -rf features/logs/*.log
data/README.md CHANGED
@@ -10,7 +10,7 @@ Well so do I. The issue is that most languages the cucumber implementation is no
10
10
 
11
11
  So why not test the way you want and build the microservice how you want. These kind of tests will make sure your application is tested properly by going end-to-end.
12
12
 
13
- The way it works is it spawns the process you configure and waits for it to start. Then you communicate with your microservice however you like (TCP, HTTP, gRPC, etc)
13
+ The way it works is it spawns the processes you configure and waits for it to start. Then you communicate with your microservice however you like (TCP, HTTP, gRPC, etc)
14
14
 
15
15
  ## Installation
16
16
 
@@ -38,14 +38,52 @@ Configure nonnative with the following:
38
38
  - The file you want STDOUT to be logged to.
39
39
  - The strategy (Startup will start the process once and before will hook into cucumbers Before and After).
40
40
 
41
+ ### Ruby
42
+
41
43
  ```ruby
42
44
  require 'nonnative'
43
45
 
44
46
  Nonnative.configure do |config|
45
- config.process = 'features/support/bin/start'
46
- config.timeout = 0.5
47
- config.port = 12_321
48
- config.file = 'logs/output'
49
- config.strategy = :startup or :before
47
+ config.strategy = :startup or :before or :manual
48
+
49
+ config.definition do |d|
50
+ d.process = 'features/support/bin/start 12_321'
51
+ d.timeout = 0.5
52
+ d.port = 12_321
53
+ d.file = 'features/logs/12_321.log'
54
+ end
55
+
56
+ config.definition do |d|
57
+ d.process = 'features/support/bin/start 12_322'
58
+ d.timeout = 0.5
59
+ d.port = 12_322
60
+ d.file = 'features/logs/12_322.log'
61
+ end
50
62
  end
51
63
  ```
64
+
65
+ ### YAML
66
+
67
+ ```yaml
68
+ version: 1.0
69
+ strategy: manual
70
+ definitions:
71
+ -
72
+ process: features/support/bin/start 12_321
73
+ timeout: 5
74
+ port: 12321
75
+ file: features/logs/12_321.log
76
+ -
77
+ process: features/support/bin/start 12_322
78
+ timeout: 5
79
+ port: 12322
80
+ file: features/logs/12_322.log
81
+ ```
82
+
83
+ Then load the file with
84
+
85
+ ```ruby
86
+ require 'nonnative'
87
+
88
+ Nonnative.load_configuration('configuration.yml')
89
+ ```
data/bin/setup CHANGED
@@ -4,5 +4,6 @@ IFS=$'\n\t'
4
4
  set -vx
5
5
 
6
6
  gem install bundler
7
- bundle check --path vendor/bundle || bundle install --path vendor/bundle
8
- bundle clean
7
+ bundle config set path 'vendor/bundle'
8
+ bundle check || bundle install
9
+ bundle clean --force
@@ -2,14 +2,44 @@
2
2
 
3
3
  module Nonnative
4
4
  class Configuration
5
+ class << self
6
+ def load_file(path)
7
+ file = YAML.load_file(path)
8
+
9
+ new.tap do |c|
10
+ c.strategy = file['strategy']
11
+
12
+ definitions(file, c)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def definitions(file, config)
19
+ file['definitions'].each do |fd|
20
+ config.definition do |d|
21
+ d.process = fd['process']
22
+ d.timeout = fd['timeout']
23
+ d.port = fd['port']
24
+ d.file = fd['file']
25
+ end
26
+ end
27
+ end
28
+ end
29
+
5
30
  def initialize
6
31
  self.strategy = :before
32
+ self.definitions = []
7
33
  end
8
34
 
9
- attr_accessor :process
10
- attr_accessor :timeout
11
- attr_accessor :port
12
- attr_accessor :file
13
35
  attr_accessor :strategy
36
+ attr_accessor :definitions
37
+
38
+ def definition
39
+ definition = Nonnative::Definition.new
40
+ yield definition
41
+
42
+ definitions << definition
43
+ end
14
44
  end
15
45
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Definition
5
+ attr_accessor :process
6
+ attr_accessor :timeout
7
+ attr_accessor :port
8
+ attr_accessor :file
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Do nothing as it's manual
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class Port
5
+ def initialize(definition)
6
+ @definition = definition
7
+ end
8
+
9
+ def open?
10
+ timeout do
11
+ open_socket
12
+ true
13
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
14
+ sleep_interval
15
+ retry
16
+ end
17
+ end
18
+
19
+ def closed?
20
+ timeout do
21
+ open_socket
22
+ raise Nonnative::Error
23
+ rescue Nonnative::Error
24
+ sleep_interval
25
+ retry
26
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ECONNRESET
27
+ true
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :definition
34
+
35
+ def timeout
36
+ Timeout.timeout(definition.timeout) do
37
+ yield
38
+ end
39
+ rescue Timeout::Error
40
+ false
41
+ end
42
+
43
+ def open_socket
44
+ TCPSocket.new('127.0.0.1', definition.port).close
45
+ end
46
+
47
+ def sleep_interval
48
+ sleep 0.01
49
+ end
50
+ end
51
+ end
@@ -2,65 +2,31 @@
2
2
 
3
3
  module Nonnative
4
4
  class Process
5
- def initialize(configuration)
6
- @configuration = configuration
5
+ def initialize(definition)
6
+ @definition = definition
7
+ @started = false
7
8
  end
8
9
 
9
10
  def start
10
- @pid = if configuration.file
11
- spawn(configuration.process, %i[out err] => [configuration.file, 'a'])
12
- else
13
- spawn(configuration.process)
14
- end
11
+ unless started
12
+ @pid = spawn(definition.process, %i[out err] => [definition.file, 'a'])
13
+ @started = true
14
+ end
15
15
 
16
- [port_open?, pid]
16
+ pid
17
17
  end
18
18
 
19
19
  def stop
20
- ::Process.kill('SIGINT', pid)
21
- [port_closed?, pid]
22
- end
23
-
24
- private
25
-
26
- attr_reader :configuration, :pid
27
-
28
- def port_open?
29
- timeout do
30
- open_socket
31
- true
32
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
33
- sleep_interval
34
- retry
35
- end
36
- end
20
+ raise Nonnative::Error, "Can't stop a process that has not started" unless started
37
21
 
38
- def port_closed?
39
- timeout do
40
- open_socket
41
- raise Nonnative::Error
42
- rescue Nonnative::Error
43
- sleep_interval
44
- retry
45
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
46
- true
47
- end
48
- end
22
+ ::Process.kill('SIGINT', pid)
23
+ @started = false
49
24
 
50
- def timeout
51
- Timeout.timeout(configuration.timeout) do
52
- yield
53
- end
54
- rescue Timeout::Error
55
- false
25
+ pid
56
26
  end
57
27
 
58
- def open_socket
59
- TCPSocket.new('127.0.0.1', configuration.port).close
60
- end
28
+ private
61
29
 
62
- def sleep_interval
63
- sleep 0.01
64
- end
30
+ attr_reader :definition, :pid, :started
65
31
  end
66
32
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Nonnative
4
+ class ProcessPool
5
+ def initialize(configuration)
6
+ @configuration = configuration
7
+ end
8
+
9
+ def start(&block)
10
+ prs = processes.map { |p, _| p.start }
11
+ pos = processes.map { |_, p| Thread.new { p.open? } }.map(&:value)
12
+
13
+ yield_results(prs, pos, &block)
14
+ end
15
+
16
+ def stop(&block)
17
+ prs = processes.map { |p, _| p.stop }
18
+ pos = processes.map { |_, p| Thread.new { p.closed? } }.map(&:value)
19
+
20
+ yield_results(prs, pos, &block)
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :configuration
26
+
27
+ def processes
28
+ @processes ||= configuration.definitions.map { |d| [Nonnative::Process.new(d), Nonnative::Port.new(d)] }
29
+ end
30
+
31
+ def yield_results(prs, pos)
32
+ prs.zip(pos).each do |pid, result|
33
+ yield pid, result
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- VERSION = '0.8.0'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/nonnative.rb CHANGED
@@ -6,7 +6,10 @@ require 'timeout'
6
6
  require 'nonnative/version'
7
7
  require 'nonnative/error'
8
8
  require 'nonnative/configuration'
9
+ require 'nonnative/definition'
9
10
  require 'nonnative/process'
11
+ require 'nonnative/process_pool'
12
+ require 'nonnative/port'
10
13
  require 'nonnative/logger'
11
14
 
12
15
  module Nonnative
@@ -15,6 +18,10 @@ module Nonnative
15
18
  @logger ||= Nonnative::Logger.create
16
19
  end
17
20
 
21
+ def load_configuration(path)
22
+ @configuration ||= Nonnative::Configuration.load_file(path) # rubocop:disable Naming/MemoizedInstanceVariableName
23
+ end
24
+
18
25
  def configuration
19
26
  @configuration ||= Nonnative::Configuration.new
20
27
  end
@@ -26,18 +33,17 @@ module Nonnative
26
33
  end
27
34
 
28
35
  def start
29
- @process ||= Nonnative::Process.new(configuration)
30
- result, pid = @process.start
31
- return if result
36
+ @process_pool ||= Nonnative::ProcessPool.new(configuration)
32
37
 
33
- logger.error('Process has started though did respond in time', pid: pid)
38
+ @process_pool.start do |pid, result|
39
+ logger.error('Process has started though did respond in time', pid: pid) unless result
40
+ end
34
41
  end
35
42
 
36
43
  def stop
37
- result, pid = @process.stop
38
- return if result
39
-
40
- logger.error('Process has stopped though did respond in time', pid: pid)
44
+ @process_pool.stop do |pid, result|
45
+ logger.error('Process has stopped though did respond in time', pid: pid) unless result
46
+ end
41
47
  end
42
48
  end
43
49
  end
data/nonnative.gemspec CHANGED
@@ -29,8 +29,9 @@ Gem::Specification.new do |spec|
29
29
  spec.add_dependency 'semantic_logger'
30
30
 
31
31
  spec.add_development_dependency 'bundler'
32
+ spec.add_development_dependency 'bundler-audit'
32
33
  spec.add_development_dependency 'rake'
34
+ spec.add_development_dependency 'rspec-benchmark'
33
35
  spec.add_development_dependency 'rubocop'
34
36
  spec.add_development_dependency 'simplecov'
35
- spec.add_development_dependency 'solargraph'
36
37
  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: 0.8.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Falkowski
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-31 00:00:00.000000000 Z
11
+ date: 2020-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler-audit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -81,7 +95,7 @@ dependencies:
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
- name: rubocop
98
+ name: rspec-benchmark
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - ">="
@@ -95,7 +109,7 @@ dependencies:
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
- name: simplecov
112
+ name: rubocop
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - ">="
@@ -109,7 +123,7 @@ dependencies:
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
- name: solargraph
126
+ name: simplecov
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - ">="
@@ -145,9 +159,13 @@ files:
145
159
  - lib/nonnative.rb
146
160
  - lib/nonnative/before.rb
147
161
  - lib/nonnative/configuration.rb
162
+ - lib/nonnative/definition.rb
148
163
  - lib/nonnative/error.rb
149
164
  - lib/nonnative/logger.rb
165
+ - lib/nonnative/manual.rb
166
+ - lib/nonnative/port.rb
150
167
  - lib/nonnative/process.rb
168
+ - lib/nonnative/process_pool.rb
151
169
  - lib/nonnative/startup.rb
152
170
  - lib/nonnative/version.rb
153
171
  - nonnative.gemspec