simmer 1.0.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +8 -0
  3. data/.gitignore +6 -0
  4. data/.rubocop.yml +25 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +25 -0
  7. data/CHANGELOG.md +1 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +5 -0
  10. data/Guardfile +16 -0
  11. data/LICENSE +7 -0
  12. data/README.md +5 -0
  13. data/Rakefile +17 -0
  14. data/bin/console +18 -0
  15. data/bin/simmer +11 -0
  16. data/lib/simmer.rb +50 -0
  17. data/lib/simmer/configuration.rb +90 -0
  18. data/lib/simmer/core_ext/hash.rb +21 -0
  19. data/lib/simmer/externals.rb +12 -0
  20. data/lib/simmer/externals/aws_file_system.rb +79 -0
  21. data/lib/simmer/externals/mysql_database.rb +114 -0
  22. data/lib/simmer/externals/mysql_database/sql_fixture.rb +43 -0
  23. data/lib/simmer/externals/spoon_client.rb +77 -0
  24. data/lib/simmer/externals/spoon_client/mock.rb +39 -0
  25. data/lib/simmer/externals/spoon_client/result.rb +48 -0
  26. data/lib/simmer/judge.rb +38 -0
  27. data/lib/simmer/judge/result.rb +34 -0
  28. data/lib/simmer/runner.rb +125 -0
  29. data/lib/simmer/runner/result.rb +52 -0
  30. data/lib/simmer/session.rb +79 -0
  31. data/lib/simmer/session/reporter.rb +86 -0
  32. data/lib/simmer/session/result.rb +45 -0
  33. data/lib/simmer/specification.rb +34 -0
  34. data/lib/simmer/specification/act.rb +48 -0
  35. data/lib/simmer/specification/act/params.rb +55 -0
  36. data/lib/simmer/specification/assert.rb +27 -0
  37. data/lib/simmer/specification/assert/assertions.rb +27 -0
  38. data/lib/simmer/specification/assert/assertions/bad_output_assertion.rb +34 -0
  39. data/lib/simmer/specification/assert/assertions/bad_table_assertion.rb +38 -0
  40. data/lib/simmer/specification/assert/assertions/output.rb +37 -0
  41. data/lib/simmer/specification/assert/assertions/table.rb +47 -0
  42. data/lib/simmer/specification/stage.rb +28 -0
  43. data/lib/simmer/specification/stage/input_file.rb +33 -0
  44. data/lib/simmer/suite.rb +73 -0
  45. data/lib/simmer/util.rb +13 -0
  46. data/lib/simmer/util/evaluator.rb +32 -0
  47. data/lib/simmer/util/fixture.rb +32 -0
  48. data/lib/simmer/util/fixture_set.rb +41 -0
  49. data/lib/simmer/util/record.rb +54 -0
  50. data/lib/simmer/util/record_set.rb +51 -0
  51. data/lib/simmer/util/resolver.rb +28 -0
  52. data/lib/simmer/util/yaml_reader.rb +60 -0
  53. data/lib/simmer/version.rb +12 -0
  54. data/simmer.gemspec +38 -0
  55. data/spec/simmer/core_ext/hash_spec.rb +16 -0
  56. data/spec/spec_helper.rb +22 -0
  57. metadata +285 -0
@@ -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
+ module Simmer
11
+ class Specification
12
+ class Assert
13
+ class Assertions
14
+ # Describes when the output does not meet expectations.
15
+ class BadOutputAssertion
16
+ attr_reader :expected_value
17
+
18
+ def initialize(expected_value)
19
+ @expected_value = expected_value
20
+
21
+ freeze
22
+ end
23
+
24
+ def to_h
25
+ {
26
+ 'type' => 'output',
27
+ 'expected_value' => expected_value
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,38 @@
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 Assert
13
+ class Assertions
14
+ # Describes when a database table does not meet expectations.
15
+ class BadTableAssertion
16
+ attr_reader :name, :expected_record_set, :actual_record_set
17
+
18
+ def initialize(name, expected_record_set, actual_record_set)
19
+ @name = name
20
+ @expected_record_set = expected_record_set
21
+ @actual_record_set = actual_record_set
22
+
23
+ freeze
24
+ end
25
+
26
+ def to_h
27
+ {
28
+ 'type' => 'table',
29
+ 'name' => name,
30
+ 'expected_record_set' => expected_record_set.to_h,
31
+ 'actual_record_set' => actual_record_set.to_h
32
+ }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,37 @@
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 'bad_output_assertion'
11
+
12
+ module Simmer
13
+ class Specification
14
+ class Assert
15
+ class Assertions
16
+ # Describes an expected state of the output (log).
17
+ class Output
18
+ acts_as_hashable
19
+
20
+ attr_reader :value
21
+
22
+ def initialize(value:)
23
+ @value = value.to_s
24
+
25
+ freeze
26
+ end
27
+
28
+ def assert(_database, output)
29
+ return nil if output.to_s.include?(value)
30
+
31
+ BadOutputAssertion.new(value)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,47 @@
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 'bad_table_assertion'
11
+
12
+ module Simmer
13
+ class Specification
14
+ class Assert
15
+ class Assertions
16
+ # Describes an expected state of a database table.
17
+ class Table
18
+ acts_as_hashable
19
+
20
+ attr_reader :name, :record_set
21
+
22
+ def initialize(name:, records: [])
23
+ @name = name.to_s
24
+ @record_set = Util::RecordSet.new(records)
25
+
26
+ freeze
27
+ end
28
+
29
+ def assert(database, _output)
30
+ actual_records = database.records(name, keys)
31
+ actual_record_set = Util::RecordSet.new(actual_records)
32
+
33
+ return nil if actual_record_set == record_set
34
+
35
+ BadTableAssertion.new(name, record_set, actual_record_set)
36
+ end
37
+
38
+ private
39
+
40
+ def keys
41
+ record_set.keys
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,28 @@
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 'stage/input_file'
11
+
12
+ module Simmer
13
+ class Specification
14
+ # Describes the state necessary to exist before Spoon can be executed successfully.
15
+ class Stage
16
+ acts_as_hashable
17
+
18
+ attr_reader :files, :fixtures
19
+
20
+ def initialize(files: [], fixtures: [])
21
+ @files = InputFile.array(files)
22
+ @fixtures = Array(fixtures).map(&:to_s)
23
+
24
+ freeze
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,33 @@
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 Stage
13
+ # Describes a file needing to be staged for a specification to execute properly.
14
+ # It understands where the file exists in the local repository and where to transfer it
15
+ # to.
16
+ class InputFile
17
+ acts_as_hashable
18
+
19
+ attr_reader :dest, :src
20
+
21
+ def initialize(dest:, src:)
22
+ raise ArgumentError, 'dest is required' if dest.to_s.empty?
23
+ raise ArgumentError, 'src is required' if src.to_s.empty?
24
+
25
+ @dest = dest.to_s
26
+ @src = src.to_s
27
+
28
+ freeze
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,73 @@
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 'configuration'
11
+ require_relative 'externals'
12
+ require_relative 'runner'
13
+ require_relative 'session'
14
+ require_relative 'specification'
15
+
16
+ # Entrypoint to the library
17
+ module Simmer
18
+ # The main object entrypoint that brings the entire codebase together.
19
+ class Suite
20
+ attr_reader :configuration, :session
21
+
22
+ def initialize(out:, config_path:, results_dir:, spec_dir:)
23
+ @configuration = Configuration.new(
24
+ config_path: config_path,
25
+ results_dir: results_dir,
26
+ spec_dir: spec_dir
27
+ )
28
+
29
+ runner = Runner.new(
30
+ database: database,
31
+ file_system: file_system,
32
+ out: out,
33
+ spoon_client: spoon_client
34
+ )
35
+
36
+ @session = Session.new(
37
+ config: configuration.config,
38
+ out: out,
39
+ results_dir: results_dir,
40
+ runner: runner
41
+ )
42
+
43
+ freeze
44
+ end
45
+
46
+ def run(path)
47
+ session.run(specifications(path))
48
+ end
49
+
50
+ private
51
+
52
+ def specifications(path)
53
+ path = path.to_s.empty? ? configuration.tests_dir : path
54
+
55
+ Util::YamlReader.new.all(path).map do |file, config|
56
+ config = (config || {}).merge(path: file)
57
+ Specification.make(config)
58
+ end
59
+ end
60
+
61
+ def database
62
+ Externals::MysqlDatabase.new(configuration.database_config, configuration.fixture_set)
63
+ end
64
+
65
+ def file_system
66
+ Externals::AwsFileSystem.new(configuration.file_system_config, configuration.files_dir)
67
+ end
68
+
69
+ def spoon_client
70
+ Externals::SpoonClient.new(configuration.spoon_client_config, configuration.files_dir)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,13 @@
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 'util/evaluator'
11
+ require_relative 'util/fixture_set'
12
+ require_relative 'util/record_set'
13
+ require_relative 'util/yaml_reader'
@@ -0,0 +1,32 @@
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 'resolver'
11
+
12
+ module Simmer
13
+ module Util
14
+ # Text template renderer. It knows how to take a string and object as an input and
15
+ # output a compiled string.
16
+ class Evaluator
17
+ def initialize
18
+ @resolver = Objectable.resolver
19
+
20
+ freeze
21
+ end
22
+
23
+ def evaluate(string, input = {})
24
+ Stringento.evaluate(string, input, resolver: Resolver.new)
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :resolver
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
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
+ module Util
12
+ # A fixture is a database record that can be inserted in the Stage phase of a specification
13
+ # execution.
14
+ class Fixture
15
+ acts_as_hashable
16
+
17
+ attr_reader :fields,
18
+ :name,
19
+ :table
20
+
21
+ def initialize(fields: {}, name:, table:)
22
+ @fields = fields || {}
23
+ @name = name.to_s
24
+ @table = table.to_s
25
+ end
26
+
27
+ def to_s
28
+ "#{name} (#{table}) #{fields}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,41 @@
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 'fixture'
11
+
12
+ module Simmer
13
+ module Util
14
+ # Hydrate a collection of Fixture instances from configuration.
15
+ class FixtureSet
16
+ def initialize(config = {})
17
+ @fixtures_by_name = config.each_with_object({}) do |(name, fixture_config), memo|
18
+ memo[name.to_s] = Fixture.make((fixture_config || {}).merge('name' => name))
19
+ end
20
+
21
+ freeze
22
+ end
23
+
24
+ def get!(name)
25
+ key = name.to_s
26
+
27
+ raise ArgumentError, "fixture not found: #{name}" unless fixtures_by_name.key?(key)
28
+
29
+ fixtures_by_name[key]
30
+ end
31
+
32
+ def all
33
+ fixtures_by_name.values
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :fixtures_by_name
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,54 @@
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
+ module Util
12
+ # A less strict comparable hash data structure. It does not depend on key type, value type,
13
+ # and key ordering.
14
+ class Record
15
+ extend Forwardable
16
+
17
+ attr_reader :data
18
+
19
+ def_delegators :data, :to_h
20
+
21
+ def initialize(data = {})
22
+ @data = sorted_string_hash(data)
23
+ end
24
+
25
+ def <=>(other)
26
+ data <=> other.data
27
+ end
28
+
29
+ def ==(other)
30
+ other.instance_of?(self.class) && data == other.data
31
+ end
32
+ alias eql? ==
33
+
34
+ def keys
35
+ data.map(&:first)
36
+ end
37
+
38
+ private
39
+
40
+ def sorted_string_hash(hash)
41
+ (hash || {}).map do |k, v|
42
+ key = k.to_s
43
+ value = convert(v)
44
+
45
+ [key, value]
46
+ end.sort
47
+ end
48
+
49
+ def convert(value)
50
+ value.is_a?(BigDecimal) ? value.to_s('F') : value.to_s
51
+ end
52
+ end
53
+ end
54
+ end