simmer 1.0.0.pre.alpha.2
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 +7 -0
- data/.editorconfig +8 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +25 -0
- data/.ruby-version +1 -0
- data/.travis.yml +25 -0
- data/CHANGELOG.md +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -0
- data/Guardfile +16 -0
- data/LICENSE +7 -0
- data/README.md +5 -0
- data/Rakefile +17 -0
- data/bin/console +18 -0
- data/bin/simmer +11 -0
- data/lib/simmer.rb +50 -0
- data/lib/simmer/configuration.rb +90 -0
- data/lib/simmer/core_ext/hash.rb +21 -0
- data/lib/simmer/externals.rb +12 -0
- data/lib/simmer/externals/aws_file_system.rb +81 -0
- data/lib/simmer/externals/mysql_database.rb +114 -0
- data/lib/simmer/externals/mysql_database/sql_fixture.rb +43 -0
- data/lib/simmer/externals/spoon_client.rb +77 -0
- data/lib/simmer/externals/spoon_client/mock.rb +39 -0
- data/lib/simmer/externals/spoon_client/result.rb +48 -0
- data/lib/simmer/judge.rb +38 -0
- data/lib/simmer/judge/result.rb +34 -0
- data/lib/simmer/runner.rb +125 -0
- data/lib/simmer/runner/result.rb +52 -0
- data/lib/simmer/session.rb +79 -0
- data/lib/simmer/session/reporter.rb +100 -0
- data/lib/simmer/session/result.rb +45 -0
- data/lib/simmer/specification.rb +34 -0
- data/lib/simmer/specification/act.rb +48 -0
- data/lib/simmer/specification/act/params.rb +55 -0
- data/lib/simmer/specification/assert.rb +27 -0
- data/lib/simmer/specification/assert/assertions.rb +27 -0
- data/lib/simmer/specification/assert/assertions/bad_output_assertion.rb +34 -0
- data/lib/simmer/specification/assert/assertions/bad_table_assertion.rb +38 -0
- data/lib/simmer/specification/assert/assertions/output.rb +37 -0
- data/lib/simmer/specification/assert/assertions/table.rb +47 -0
- data/lib/simmer/specification/stage.rb +28 -0
- data/lib/simmer/specification/stage/input_file.rb +33 -0
- data/lib/simmer/suite.rb +73 -0
- data/lib/simmer/util.rb +13 -0
- data/lib/simmer/util/evaluator.rb +32 -0
- data/lib/simmer/util/fixture.rb +32 -0
- data/lib/simmer/util/fixture_set.rb +41 -0
- data/lib/simmer/util/record.rb +54 -0
- data/lib/simmer/util/record_set.rb +51 -0
- data/lib/simmer/util/resolver.rb +28 -0
- data/lib/simmer/util/yaml_reader.rb +61 -0
- data/lib/simmer/version.rb +12 -0
- data/simmer.gemspec +38 -0
- data/spec/simmer/core_ext/hash_spec.rb +16 -0
- data/spec/spec_helper.rb +22 -0
- metadata +284 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Simmer
|
11
|
+
class Runner
|
12
|
+
# Return object from a Runner#run call.
|
13
|
+
class Result
|
14
|
+
extend Forwardable
|
15
|
+
|
16
|
+
attr_reader :id, :judge_result, :specification, :spoon_client_result
|
17
|
+
|
18
|
+
def_delegators :spoon_client_result, :time_in_seconds
|
19
|
+
|
20
|
+
def_delegators :specification, :name
|
21
|
+
|
22
|
+
def initialize(id, judge_result, specification, spoon_client_result)
|
23
|
+
@id = id.to_s
|
24
|
+
@judge_result = judge_result
|
25
|
+
@specification = specification
|
26
|
+
@spoon_client_result = spoon_client_result
|
27
|
+
|
28
|
+
freeze
|
29
|
+
end
|
30
|
+
|
31
|
+
def pass?
|
32
|
+
judge_result&.pass? && spoon_client_result&.pass?
|
33
|
+
end
|
34
|
+
|
35
|
+
def fail?
|
36
|
+
!pass?
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_h
|
40
|
+
{
|
41
|
+
'name' => specification.name,
|
42
|
+
'id' => id,
|
43
|
+
'path' => specification.path,
|
44
|
+
'time_in_seconds' => time_in_seconds,
|
45
|
+
'pass' => pass?,
|
46
|
+
'spoon_client_result' => spoon_client_result.to_h,
|
47
|
+
'judge_result' => judge_result.to_h
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'session/reporter'
|
11
|
+
require_relative 'session/result'
|
12
|
+
|
13
|
+
module Simmer
|
14
|
+
# Runs a collection of specifications and then writes down the results to disk.
|
15
|
+
class Session
|
16
|
+
def initialize(
|
17
|
+
config:,
|
18
|
+
out:,
|
19
|
+
resolver: Objectable.resolver,
|
20
|
+
results_dir:,
|
21
|
+
runner:
|
22
|
+
)
|
23
|
+
@config = config || {}
|
24
|
+
@out = out
|
25
|
+
@resolver = resolver
|
26
|
+
@results_dir = results_dir
|
27
|
+
@runner = runner
|
28
|
+
|
29
|
+
freeze
|
30
|
+
end
|
31
|
+
|
32
|
+
def run(specifications)
|
33
|
+
runner_results = run_all_specs(specifications)
|
34
|
+
|
35
|
+
Result.new(runner_results).tap do |result|
|
36
|
+
if result.pass?
|
37
|
+
out.puts('Suite ended successfully')
|
38
|
+
else
|
39
|
+
out.puts('Suite ended but was not successful')
|
40
|
+
end
|
41
|
+
|
42
|
+
Reporter.new(result).write!(results_dir)
|
43
|
+
|
44
|
+
out.puts("Results can be viewed at #{results_dir}")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
attr_reader :config, :out, :results_dir, :resolver, :runner
|
51
|
+
|
52
|
+
def run_all_specs(specifications)
|
53
|
+
out.puts('Simmer suite started')
|
54
|
+
|
55
|
+
count = specifications.length
|
56
|
+
|
57
|
+
out.puts("Running #{count} specification(s)")
|
58
|
+
print_line
|
59
|
+
|
60
|
+
specifications.map.with_index(1) do |specification, index|
|
61
|
+
run_single_spec(specification, index, count)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def run_single_spec(specification, index, count)
|
66
|
+
id = SecureRandom.uuid
|
67
|
+
|
68
|
+
out.puts("Test #{index} of #{count}: #{id}")
|
69
|
+
|
70
|
+
runner.run(specification, id: id, config: config).tap do
|
71
|
+
print_line
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def print_line
|
76
|
+
out.puts('-' * 60)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Simmer
|
11
|
+
class Session
|
12
|
+
# Understands how to write a SessionResult instance to disk.
|
13
|
+
class Reporter
|
14
|
+
DATA_FILE = 'data.yaml'
|
15
|
+
PDI_OUT_FILE = 'pdi_out.txt'
|
16
|
+
PDI_ERR_FILE = 'pdi_err.txt'
|
17
|
+
|
18
|
+
def initialize(session_result)
|
19
|
+
raise ArgumentError, 'session_result is required' unless session_result
|
20
|
+
|
21
|
+
@session_result = session_result
|
22
|
+
|
23
|
+
freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
def write!(dir)
|
27
|
+
dir = setup_directory(dir)
|
28
|
+
|
29
|
+
IO.write(data_path(dir), session_result.to_h.to_yaml)
|
30
|
+
|
31
|
+
pdi_out_file = File.open(pdi_out_path(dir), 'w')
|
32
|
+
pdi_err_file = File.open(pdi_err_path(dir), 'w')
|
33
|
+
|
34
|
+
write_part(session_result.runner_results, pdi_out_file, pdi_err_file)
|
35
|
+
|
36
|
+
pdi_out_file.close
|
37
|
+
pdi_err_file.close
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_h
|
43
|
+
{
|
44
|
+
'pass' => pass?,
|
45
|
+
'time_in_seconds' => time_in_seconds,
|
46
|
+
'runner_results' => runner_results.map(&:to_h)
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
attr_reader :session_result
|
53
|
+
|
54
|
+
def data_path(dir)
|
55
|
+
File.join(dir, DATA_FILE)
|
56
|
+
end
|
57
|
+
|
58
|
+
def pdi_out_path(dir)
|
59
|
+
File.join(dir, PDI_OUT_FILE)
|
60
|
+
end
|
61
|
+
|
62
|
+
def pdi_err_path(dir)
|
63
|
+
File.join(dir, PDI_ERR_FILE)
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_directory(dir)
|
67
|
+
File.expand_path(dir).tap do |expanded_dir|
|
68
|
+
FileUtils.mkdir_p(expanded_dir)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def write_part(runner_results, pdi_out_file, pdi_err_file)
|
73
|
+
runner_results.each do |runner_result|
|
74
|
+
name = runner_result.name
|
75
|
+
runner_id = runner_result.id
|
76
|
+
out_contents = runner_result.spoon_client_result.execution_result.out
|
77
|
+
err_contents = runner_result.spoon_client_result.execution_result.err
|
78
|
+
|
79
|
+
write_block(pdi_out_file, name, runner_id, out_contents)
|
80
|
+
write_block(pdi_err_file, name, runner_id, err_contents)
|
81
|
+
end
|
82
|
+
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def write_block(file, name, runner_id, contents)
|
87
|
+
hyphens = '-' * 80
|
88
|
+
|
89
|
+
file.write("#{hyphens}\n")
|
90
|
+
file.write("Name: #{name}\n")
|
91
|
+
file.write("Runner ID: #{runner_id}\n")
|
92
|
+
file.write("#{hyphens}\n")
|
93
|
+
file.write("#{contents}\n")
|
94
|
+
file.write("\n")
|
95
|
+
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Simmer
|
11
|
+
class Session
|
12
|
+
# The return object for a Session#run call.
|
13
|
+
class Result
|
14
|
+
attr_reader :runner_results
|
15
|
+
|
16
|
+
def initialize(runner_results = [])
|
17
|
+
@runner_results = Array(runner_results)
|
18
|
+
|
19
|
+
freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def pass?
|
23
|
+
!fail?
|
24
|
+
end
|
25
|
+
|
26
|
+
def fail?
|
27
|
+
runner_results.any?(&:fail?)
|
28
|
+
end
|
29
|
+
|
30
|
+
def time_in_seconds
|
31
|
+
runner_results.inject(0.0) do |memo, runner_result|
|
32
|
+
memo + runner_result.time_in_seconds
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_h
|
37
|
+
{
|
38
|
+
'pass' => pass?,
|
39
|
+
'time_in_seconds' => time_in_seconds,
|
40
|
+
'runner_results' => runner_results.map(&:to_h)
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'specification/act'
|
11
|
+
require_relative 'specification/assert'
|
12
|
+
require_relative 'specification/stage'
|
13
|
+
|
14
|
+
module Simmer
|
15
|
+
# Describes a specification at the highest of levels.
|
16
|
+
class Specification
|
17
|
+
acts_as_hashable
|
18
|
+
|
19
|
+
attr_reader :act, :assert, :name, :path, :stage
|
20
|
+
|
21
|
+
def initialize(act: {}, assert: {}, name:, path:, stage: {})
|
22
|
+
raise ArgumentError, 'name is required' if name.to_s.empty?
|
23
|
+
raise ArgumentError, 'path is required' if path.to_s.empty?
|
24
|
+
|
25
|
+
@act = Act.make(act)
|
26
|
+
@assert = Assert.make(assert)
|
27
|
+
@name = name.to_s
|
28
|
+
@path = path.to_s
|
29
|
+
@stage = Stage.make(stage)
|
30
|
+
|
31
|
+
freeze
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'act/params'
|
11
|
+
|
12
|
+
module Simmer
|
13
|
+
class Specification
|
14
|
+
# Describes everything necessary to execute Pdi::Spoon.
|
15
|
+
class Act
|
16
|
+
extend Forwardable
|
17
|
+
acts_as_hashable
|
18
|
+
|
19
|
+
module Type
|
20
|
+
JOB = :job
|
21
|
+
TRANSFORMATION = :transformation
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :repository, :name, :type, :params
|
25
|
+
|
26
|
+
def_delegator :params, :compile, :compiled_params
|
27
|
+
|
28
|
+
def initialize(repository:, name:, type:, params: {})
|
29
|
+
assert_presence(repository, 'repository')
|
30
|
+
assert_presence(name, 'name')
|
31
|
+
assert_presence(type, 'type')
|
32
|
+
|
33
|
+
@repository = repository.to_s
|
34
|
+
@name = name.to_s
|
35
|
+
@type = Type.const_get(type.to_s.to_s.upcase.to_sym)
|
36
|
+
@params = Params.make(params)
|
37
|
+
|
38
|
+
freeze
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def assert_presence(value, name)
|
44
|
+
raise ArgumentError, "#{name} is required" if value.to_s.empty?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Simmer
|
11
|
+
class Specification
|
12
|
+
class Act
|
13
|
+
# Understands how to compile a list of files and key value pairs for Pdi::Spoon
|
14
|
+
# consumption.
|
15
|
+
class Params
|
16
|
+
acts_as_hashable
|
17
|
+
|
18
|
+
attr_reader :files, :keys
|
19
|
+
|
20
|
+
def initialize(files: {}, keys: {})
|
21
|
+
@files = files || {}
|
22
|
+
@keys = keys || {}
|
23
|
+
@evaluator = Util::Evaluator.new
|
24
|
+
|
25
|
+
freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
def compile(files_path, config = {})
|
29
|
+
compiled_file_params(files_path, config).merge(compiled_key_params(config))
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :evaluator
|
35
|
+
|
36
|
+
def compiled_file_params(files_path, config)
|
37
|
+
files.map do |key, value|
|
38
|
+
evaluated_value = evaluator.evaluate(value, config)
|
39
|
+
expanded_value = File.expand_path(File.join(files_path, evaluated_value))
|
40
|
+
|
41
|
+
[key, expanded_value]
|
42
|
+
end.to_h
|
43
|
+
end
|
44
|
+
|
45
|
+
def compiled_key_params(config)
|
46
|
+
keys.map do |key, value|
|
47
|
+
evaluated_value = evaluator.evaluate(value, config)
|
48
|
+
|
49
|
+
[key, evaluated_value]
|
50
|
+
end.to_h
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2020-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'assert/assertions'
|
11
|
+
|
12
|
+
module Simmer
|
13
|
+
class Specification
|
14
|
+
# Describes what should be expected after a Pdi::Spoon execution.
|
15
|
+
class Assert
|
16
|
+
acts_as_hashable
|
17
|
+
|
18
|
+
attr_reader :assertions
|
19
|
+
|
20
|
+
def initialize(assertions: [])
|
21
|
+
@assertions = Assertions.array(assertions)
|
22
|
+
|
23
|
+
freeze
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|