simmer 1.0.0.pre.alpha.3 → 1.0.0.pre.alpha.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/lib/simmer.rb +103 -9
- data/lib/simmer/configuration.rb +7 -17
- data/lib/simmer/database.rb +10 -0
- data/lib/simmer/{util → database}/fixture.rb +7 -3
- data/lib/simmer/{util → database}/fixture_set.rb +10 -4
- data/lib/simmer/externals/aws_file_system.rb +30 -23
- data/lib/simmer/externals/mysql_database.rb +17 -10
- data/lib/simmer/externals/spoon_client.rb +5 -19
- data/lib/simmer/runner.rb +2 -2
- data/lib/simmer/specification/act.rb +1 -6
- data/lib/simmer/specification/assert/assertions/table.rb +1 -6
- data/lib/simmer/spoon_mock.rb +35 -0
- data/lib/simmer/suite.rb +49 -43
- data/lib/simmer/{session → suite}/reporter.rb +1 -1
- data/lib/simmer/{session → suite}/result.rb +1 -1
- data/lib/simmer/util.rb +0 -1
- data/lib/simmer/util/evaluator.rb +4 -5
- data/lib/simmer/util/record.rb +2 -0
- data/lib/simmer/util/record_set.rb +5 -1
- data/lib/simmer/util/resolver.rb +2 -2
- data/lib/simmer/util/yaml_reader.rb +9 -12
- data/lib/simmer/version.rb +1 -1
- data/spec/config/simmer.yaml.ci +7 -0
- data/spec/db/database.sql +1 -0
- data/spec/db/tables.sql +20 -0
- data/spec/db_helper.rb +26 -0
- data/spec/fixtures/agent_fixtures.yaml +14 -0
- data/spec/fixtures/configuration.yaml +11 -0
- data/spec/fixtures/noc_list.csv +3 -0
- data/spec/fixtures/specifications/load_noc_list.yaml +30 -0
- data/spec/fixtures/yaml_reader/bar.yaml +2 -0
- data/spec/fixtures/yaml_reader/baz/baz.yaml +2 -0
- data/spec/fixtures/yaml_reader/foo.yaml +2 -0
- data/spec/simmer/configuration_spec.rb +46 -0
- data/spec/simmer/database/fixture_set_spec.rb +75 -0
- data/spec/simmer/database/fixture_spec.rb +57 -0
- data/spec/simmer/externals/aws_file_system_spec.rb +75 -0
- data/spec/simmer/externals/mysql_database_spec.rb +79 -0
- data/spec/simmer/externals/spoon_client_spec.rb +67 -0
- data/spec/simmer/specification/act/params_spec.rb +38 -0
- data/spec/simmer/specification/act_spec.rb +37 -0
- data/spec/simmer/specification/assert_spec.rb +27 -0
- data/spec/simmer/specification/stage_spec.rb +32 -0
- data/spec/simmer/specification_spec.rb +28 -0
- data/spec/simmer/util/evaluator_spec.rb +82 -0
- data/spec/simmer/util/record_set_spec.rb +41 -0
- data/spec/simmer/util/record_spec.rb +218 -0
- data/spec/simmer/util/yaml_reader_spec.rb +49 -0
- data/spec/spec_helper.rb +21 -0
- metadata +60 -8
- data/lib/simmer/externals/spoon_client/mock.rb +0 -39
- data/lib/simmer/session.rb +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1197e913b7b6a7b9a814fb2474aa9d89844af7c4efe872ae001116354a3b6cdb
|
4
|
+
data.tar.gz: 6e24db3887b3abb23489642547f64ce4c68af85493b06c54d0c9bc15c637cc44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e994e8d2f87598a9baa31211e5baeae2210c8dc8e5e8337579ea2417c835162b12c59dbbd5e84d34d5f969bbe5770dc02ec8017c3e45fb0a1af6572a07f5916
|
7
|
+
data.tar.gz: 4f15f5aadaff3d595969aee68ad8c0689f879b1f6c0fde5fc7febe0f4aeff0fa25cc04c0cfeaa263fcca9e3e33ea20598d8d586803e34db68fd58bbf1739eb19
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -2,6 +2,8 @@ env:
|
|
2
2
|
global:
|
3
3
|
- CC_TEST_REPORTER_ID=48c3a48cc3c203ac365190a30b3c0a9aae0d2c10c9a86735e654f23b8660bb02
|
4
4
|
language: ruby
|
5
|
+
services:
|
6
|
+
- mysql
|
5
7
|
rvm:
|
6
8
|
# Build on the latest stable of all supported Rubies (https://www.ruby-lang.org/en/downloads/):
|
7
9
|
- 2.4.6
|
@@ -13,6 +15,9 @@ before_script:
|
|
13
15
|
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
14
16
|
- chmod +x ./cc-test-reporter
|
15
17
|
- ./cc-test-reporter before-build
|
18
|
+
- cp spec/config/simmer.yaml.ci spec/config/simmer.yaml
|
19
|
+
- cat spec/db/database.sql | mysql
|
20
|
+
- cat spec/db/tables.sql | mysql
|
16
21
|
script:
|
17
22
|
- bundle exec rubocop
|
18
23
|
- bundle exec rspec spec --format documentation
|
data/lib/simmer.rb
CHANGED
@@ -30,25 +30,119 @@ Hash.include Simmer::CoreExt::Hash
|
|
30
30
|
require_relative 'simmer/util'
|
31
31
|
|
32
32
|
# Core code
|
33
|
+
require_relative 'simmer/configuration'
|
34
|
+
require_relative 'simmer/database'
|
35
|
+
require_relative 'simmer/externals'
|
36
|
+
require_relative 'simmer/runner'
|
37
|
+
require_relative 'simmer/specification'
|
38
|
+
require_relative 'simmer/spoon_mock'
|
33
39
|
require_relative 'simmer/suite'
|
34
40
|
|
35
41
|
# The main entry-point API for the library.
|
36
42
|
module Simmer
|
37
43
|
DEFAULT_CONFIG_PATH = File.join('config', 'simmer.yaml')
|
38
|
-
DEFAULT_RESULTS_DIR = 'results'
|
39
44
|
DEFAULT_SIMMER_DIR = 'simmer'
|
45
|
+
|
40
46
|
class << self
|
41
|
-
def run(
|
42
|
-
|
47
|
+
def run(
|
48
|
+
path,
|
49
|
+
config_path: DEFAULT_CONFIG_PATH,
|
50
|
+
out: $stdout,
|
51
|
+
simmer_dir: DEFAULT_SIMMER_DIR
|
52
|
+
)
|
53
|
+
# Get configuration
|
54
|
+
yaml_reader = Util::YamlReader.new
|
55
|
+
raw_config = yaml_reader.smash(config_path)
|
56
|
+
configuration = Configuration.new(raw_config, simmer_dir)
|
57
|
+
|
58
|
+
# Get fixtures
|
59
|
+
raw_fixtures = yaml_reader.smash(configuration.fixtures_dir)
|
60
|
+
fixtures = Database::FixtureSet.new(raw_fixtures)
|
61
|
+
|
62
|
+
# Get specifications to run
|
63
|
+
specs = make_specifications(path, configuration.tests_dir)
|
64
|
+
|
65
|
+
# Make main executable instances
|
66
|
+
runner = make_runner(configuration, out, fixtures)
|
67
|
+
suite = Suite.new(
|
68
|
+
config: configuration.config,
|
69
|
+
out: out,
|
70
|
+
results_dir: configuration.results_dir,
|
71
|
+
runner: runner
|
72
|
+
)
|
73
|
+
|
74
|
+
suite.run(specs)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def make_specifications(path, tests_dir)
|
80
|
+
path = path.to_s.empty? ? tests_dir : path
|
81
|
+
|
82
|
+
Util::YamlReader.new.read(path).map do |file|
|
83
|
+
config = (file.data || {}).merge(path: file.path)
|
84
|
+
|
85
|
+
Specification.make(config)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def make_runner(configuration, out, fixtures)
|
90
|
+
database = make_mysql_database(configuration, fixtures)
|
91
|
+
file_system = make_aws_file_system(configuration)
|
92
|
+
spoon_client = make_spoon_client(configuration)
|
93
|
+
|
94
|
+
Runner.new(
|
95
|
+
database: database,
|
96
|
+
file_system: file_system,
|
97
|
+
out: out,
|
98
|
+
spoon_client: spoon_client
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
def make_fixture_set(configuration)
|
103
|
+
config = Util::YamlReader.new.smash(configuration.fixtures_dir)
|
104
|
+
|
105
|
+
Database::FixtureSet.new(config)
|
106
|
+
end
|
107
|
+
|
108
|
+
def make_mysql_database(configuration, fixtures)
|
109
|
+
config = (configuration.mysql_database_config || {}).symbolize_keys
|
110
|
+
client = Mysql2::Client.new(config)
|
111
|
+
exclude_tables = config[:exclude_tables]
|
112
|
+
|
113
|
+
Externals::MysqlDatabase.new(client, exclude_tables, fixtures)
|
43
114
|
end
|
44
115
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
116
|
+
def make_aws_file_system(configuration)
|
117
|
+
config = (configuration.aws_file_system_config || {}).symbolize_keys
|
118
|
+
|
119
|
+
client = Aws::S3::Client.new(
|
120
|
+
access_key_id: config[:access_key_id],
|
121
|
+
secret_access_key: config[:secret_access_key],
|
122
|
+
region: config[:region]
|
123
|
+
)
|
124
|
+
|
125
|
+
Externals::AwsFileSystem.new(
|
126
|
+
client,
|
127
|
+
config[:bucket],
|
128
|
+
config[:encryption],
|
129
|
+
configuration.files_dir
|
51
130
|
)
|
52
131
|
end
|
132
|
+
|
133
|
+
def make_spoon_client(configuration)
|
134
|
+
config = (configuration.spoon_client_config || {}).symbolize_keys
|
135
|
+
|
136
|
+
spoon =
|
137
|
+
if config[:mock]
|
138
|
+
SpoonMock.new
|
139
|
+
elsif config[:mock_err]
|
140
|
+
SpoonMock.new(false)
|
141
|
+
else
|
142
|
+
Pdi::Spoon.new(dir: config[:dir])
|
143
|
+
end
|
144
|
+
|
145
|
+
Externals::SpoonClient.new(configuration.files_dir, spoon)
|
146
|
+
end
|
53
147
|
end
|
54
148
|
end
|
data/lib/simmer/configuration.rb
CHANGED
@@ -19,6 +19,7 @@ module Simmer
|
|
19
19
|
# Paths
|
20
20
|
FILES = 'files'
|
21
21
|
FIXTURES = 'fixtures'
|
22
|
+
RESULTS = 'results'
|
22
23
|
TESTS = 'specs'
|
23
24
|
|
24
25
|
private_constant :AWS_FILE_SYSTEM_KEY,
|
@@ -30,27 +31,19 @@ module Simmer
|
|
30
31
|
|
31
32
|
attr_reader :config
|
32
33
|
|
33
|
-
def initialize(
|
34
|
-
|
35
|
-
resolver: Objectable.resolver,
|
36
|
-
results_dir:,
|
37
|
-
simmer_dir:,
|
38
|
-
yaml_reader: Util::YamlReader.new
|
39
|
-
)
|
40
|
-
@config = yaml_reader.read(config_path)
|
34
|
+
def initialize(config, simmer_dir, resolver: Objectable.resolver)
|
35
|
+
@config = config || {}
|
41
36
|
@resolver = resolver
|
42
|
-
@results_dir = results_dir
|
43
37
|
@simmer_dir = simmer_dir
|
44
|
-
@yaml_reader = yaml_reader
|
45
38
|
|
46
39
|
freeze
|
47
40
|
end
|
48
41
|
|
49
|
-
def
|
42
|
+
def mysql_database_config
|
50
43
|
get(MYSQL_DATABASE_KEY) || {}
|
51
44
|
end
|
52
45
|
|
53
|
-
def
|
46
|
+
def aws_file_system_config
|
54
47
|
get(AWS_FILE_SYSTEM_KEY) || {}
|
55
48
|
end
|
56
49
|
|
@@ -70,16 +63,13 @@ module Simmer
|
|
70
63
|
File.join(simmer_dir, FILES)
|
71
64
|
end
|
72
65
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
Util::FixtureSet.new(config)
|
66
|
+
def results_dir
|
67
|
+
File.join(simmer_dir, RESULTS)
|
77
68
|
end
|
78
69
|
|
79
70
|
private
|
80
71
|
|
81
72
|
attr_reader :resolver,
|
82
|
-
:results_dir,
|
83
73
|
:simmer_dir,
|
84
74
|
:yaml_reader
|
85
75
|
|
@@ -0,0 +1,10 @@
|
|
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 'database/fixture_set'
|
@@ -8,7 +8,7 @@
|
|
8
8
|
#
|
9
9
|
|
10
10
|
module Simmer
|
11
|
-
module
|
11
|
+
module Database
|
12
12
|
# A fixture is a database record that can be inserted in the Stage phase of a specification
|
13
13
|
# execution.
|
14
14
|
class Fixture
|
@@ -24,9 +24,13 @@ module Simmer
|
|
24
24
|
@table = table.to_s
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
|
27
|
+
def ==(other)
|
28
|
+
other.instance_of?(self.class) &&
|
29
|
+
fields == other.fields &&
|
30
|
+
name == other.name &&
|
31
|
+
table == other.table
|
29
32
|
end
|
33
|
+
alias eql? ==
|
30
34
|
end
|
31
35
|
end
|
32
36
|
end
|
@@ -10,13 +10,11 @@
|
|
10
10
|
require_relative 'fixture'
|
11
11
|
|
12
12
|
module Simmer
|
13
|
-
module
|
13
|
+
module Database
|
14
14
|
# Hydrate a collection of Fixture instances from configuration.
|
15
15
|
class FixtureSet
|
16
16
|
def initialize(config = {})
|
17
|
-
@fixtures_by_name = config
|
18
|
-
memo[name.to_s] = Fixture.make((fixture_config || {}).merge('name' => name))
|
19
|
-
end
|
17
|
+
@fixtures_by_name = config_to_fixures_by_name(config)
|
20
18
|
|
21
19
|
freeze
|
22
20
|
end
|
@@ -36,6 +34,14 @@ module Simmer
|
|
36
34
|
private
|
37
35
|
|
38
36
|
attr_reader :fixtures_by_name
|
37
|
+
|
38
|
+
def config_to_fixures_by_name(config)
|
39
|
+
(config || {}).each_with_object({}) do |(name, fixture_config), memo|
|
40
|
+
full_config = (fixture_config || {}).merge(name: name)
|
41
|
+
|
42
|
+
memo[name.to_s] = Fixture.make(full_config)
|
43
|
+
end
|
44
|
+
end
|
39
45
|
end
|
40
46
|
end
|
41
47
|
end
|
@@ -15,26 +15,21 @@ module Simmer
|
|
15
15
|
|
16
16
|
private_constant :BUCKET_SUFFIX
|
17
17
|
|
18
|
-
def initialize(
|
19
|
-
|
18
|
+
def initialize(aws_s3_client, bucket, encryption, files_dir)
|
19
|
+
raise ArgumentError, 'aws_s3_client is required' unless aws_s3_client
|
20
|
+
raise ArgumentError, 'bucket is required' if bucket.to_s.empty?
|
20
21
|
|
21
|
-
|
22
|
-
access_key_id: config[:access_key_id],
|
23
|
-
secret_access_key: config[:secret_access_key],
|
24
|
-
region: config[:region]
|
25
|
-
)
|
26
|
-
|
27
|
-
bucket_name = config[:bucket].to_s
|
28
|
-
assert_bucket_name(bucket_name)
|
22
|
+
assert_bucket_name(bucket)
|
29
23
|
|
30
|
-
@
|
31
|
-
@
|
32
|
-
@
|
24
|
+
@aws_s3_client = aws_s3_client
|
25
|
+
@bucket = bucket.to_s
|
26
|
+
@encryption = encryption
|
27
|
+
@files_dir = files_dir
|
33
28
|
|
34
29
|
freeze
|
35
30
|
end
|
36
31
|
|
37
|
-
def write(specification)
|
32
|
+
def write!(specification)
|
38
33
|
files = specification.stage.files
|
39
34
|
|
40
35
|
files.each do |file|
|
@@ -46,24 +41,36 @@ module Simmer
|
|
46
41
|
files.length
|
47
42
|
end
|
48
43
|
|
49
|
-
def clean
|
50
|
-
|
51
|
-
|
44
|
+
def clean!
|
45
|
+
response = aws_s3_client.list_objects(bucket: bucket)
|
46
|
+
objects = response.contents
|
47
|
+
keys = objects.map(&:key)
|
48
|
+
delete_keys = keys.map { |key| { key: key } }
|
52
49
|
|
53
|
-
|
54
|
-
|
50
|
+
return 0 if objects.length.zero?
|
51
|
+
|
52
|
+
aws_s3_client.delete_objects(
|
53
|
+
bucket: bucket,
|
54
|
+
delete: {
|
55
|
+
objects: delete_keys
|
56
|
+
}
|
57
|
+
)
|
58
|
+
|
59
|
+
delete_keys.length
|
55
60
|
end
|
56
61
|
|
57
62
|
private
|
58
63
|
|
59
|
-
attr_reader :bucket, :encryption, :files_dir
|
64
|
+
attr_reader :aws_s3_client, :bucket, :encryption, :files_dir
|
60
65
|
|
61
66
|
def write_single(dest, src)
|
62
67
|
src = File.expand_path(src)
|
63
68
|
|
64
69
|
File.open(src, 'rb') do |file|
|
65
|
-
|
66
|
-
body: file,
|
70
|
+
aws_s3_client.put_object(
|
71
|
+
body: file.read,
|
72
|
+
bucket: bucket,
|
73
|
+
key: dest,
|
67
74
|
server_side_encryption: encryption
|
68
75
|
)
|
69
76
|
end
|
@@ -72,7 +79,7 @@ module Simmer
|
|
72
79
|
end
|
73
80
|
|
74
81
|
def assert_bucket_name(name)
|
75
|
-
return if name.end_with?(BUCKET_SUFFIX)
|
82
|
+
return if name.to_s.end_with?(BUCKET_SUFFIX)
|
76
83
|
|
77
84
|
raise ArgumentError, "bucket (#{name}) must end in #{BUCKET_SUFFIX}"
|
78
85
|
end
|
@@ -15,17 +15,14 @@ module Simmer
|
|
15
15
|
class MysqlDatabase
|
16
16
|
DATABASE_SUFFIX = 'test'
|
17
17
|
|
18
|
-
def initialize(
|
19
|
-
|
20
|
-
|
21
|
-
database = config[:database].to_s
|
22
|
-
assert_database_name(database)
|
23
|
-
|
24
|
-
@client = Mysql2::Client.new(config)
|
18
|
+
def initialize(client, exclude_tables, fixture_set)
|
19
|
+
@client = client
|
25
20
|
@fixture_set = fixture_set
|
26
|
-
exclude_tables = Array(
|
21
|
+
exclude_tables = Array(exclude_tables).map(&:to_s)
|
27
22
|
@table_names = retrieve_table_names - exclude_tables
|
28
23
|
|
24
|
+
assert_database_name(schema)
|
25
|
+
|
29
26
|
freeze
|
30
27
|
end
|
31
28
|
|
@@ -97,9 +94,19 @@ module Simmer
|
|
97
94
|
'SET @@foreign_key_checks = 1'
|
98
95
|
end
|
99
96
|
|
97
|
+
def schema
|
98
|
+
client.query_options[:database].to_s
|
99
|
+
end
|
100
|
+
|
100
101
|
def retrieve_table_names
|
101
|
-
|
102
|
-
|
102
|
+
escaped_schema = client.escape(schema)
|
103
|
+
|
104
|
+
sql = <<~SQL
|
105
|
+
SELECT TABLE_NAME
|
106
|
+
FROM INFORMATION_SCHEMA.TABLES
|
107
|
+
WHERE TABLE_SCHEMA = '#{escaped_schema}'
|
108
|
+
AND TABLE_TYPE = 'BASE TABLE'
|
109
|
+
SQL
|
103
110
|
|
104
111
|
client.query(sql).to_a.map { |v| v['TABLE_NAME'].to_s }
|
105
112
|
end
|
@@ -7,36 +7,22 @@
|
|
7
7
|
# LICENSE file in the root directory of this source tree.
|
8
8
|
#
|
9
9
|
|
10
|
-
require_relative 'spoon_client/mock'
|
11
10
|
require_relative 'spoon_client/result'
|
12
11
|
|
13
12
|
module Simmer
|
14
13
|
module Externals
|
15
14
|
# Wraps up Pdi::Spoon at a higher-level for Simmer to consume.
|
16
15
|
class SpoonClient
|
17
|
-
|
18
|
-
|
16
|
+
def initialize(files_dir, spoon)
|
17
|
+
raise ArgumentError, 'spoon is required' unless spoon
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
def initialize(config, files_dir)
|
23
|
-
@files_dir = files_dir
|
24
|
-
|
25
|
-
config = (config || {}).symbolize_keys
|
26
|
-
|
27
|
-
@spoon =
|
28
|
-
if config[MOCK_KEY]
|
29
|
-
Mock.new
|
30
|
-
elsif config[MOCK_ERR_KEY]
|
31
|
-
Mock.new(false)
|
32
|
-
else
|
33
|
-
Pdi::Spoon.new(dir: config[:dir])
|
34
|
-
end
|
19
|
+
@files_dir = files_dir.to_s
|
20
|
+
@spoon = spoon
|
35
21
|
|
36
22
|
freeze
|
37
23
|
end
|
38
24
|
|
39
|
-
def run(specification, config
|
25
|
+
def run(specification, config)
|
40
26
|
execution_result = nil
|
41
27
|
time_in_seconds = nil
|
42
28
|
|