mysql_expectations 1.0.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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NGI4NWUzN2QwNTI4M2VlNjllMjY0ZTJjNTM3OWJlNmU4OWJmZTIwZg==
5
+ data.tar.gz: !binary |-
6
+ OTc2Y2Y2OWY5ZTQzOTg1ZDIxOTk0MDcyNmRiZDZlZGM0NDkxYWQ4Yg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZTJhYjNiYmVhOGYzZmVmM2Y3YWE4OTIyYWNhN2MxNjQ1MjI0YWU1NDllMDMx
10
+ MjU1YjM4NmZkNzA1MGJmOGFkNDIzMWE1NTUyZWIxZDk0ZTdjODAxZGU3NGI0
11
+ ZDU5NjRiNTY1MjM5MDIyZDgwM2I4ZmEzYWVhMTVjMmY4OWQyOTc=
12
+ data.tar.gz: !binary |-
13
+ MjcwMTUxYzVjYmE0ODViZmFjMDhmYmU4YWE2ZTQ1ZGIyNjE3N2YxZDNlYmQ1
14
+ MmIzZGY0NjE0YzZmMzBiOTRiMTliYTgyNThkZGQ2YmY0OWI2ODkzN2NkMDlj
15
+ N2MyYTk4Zjg4NzU5MmJhMTNhMjE5Mzg1NWMxYWNiMDZjNzEzNzI=
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ # Monkey patch Array to have #to_sentence.
7
+ # #to_sentence converts the array to a delimited string.
8
+ # you pick the delimiter, you pick the coordinating
9
+ # conjunction, you pick serial delimiter or not.
10
+ #
11
+ # Serial delimiter (or serial comma in the case the
12
+ # delimiter is a comma), means to include the comma
13
+ # between the last two items in the list.
14
+ #
15
+ module ArrayRefinements
16
+ refine Array do
17
+ def quote_elements(quote_with)
18
+ map { |e| "#{quote_with}#{e}#{quote_with}" }
19
+ end
20
+
21
+ def delimited_conjunction(conjunction, delimiter, serial_delimiter)
22
+ delimited_conjunction = conjunction
23
+ delimited_conjunction += ' ' unless conjunction.empty?
24
+ if serial_delimiter
25
+ delimited_conjunction = delimiter + delimited_conjunction
26
+ else
27
+ delimited_conjunction = ' ' + delimited_conjunction
28
+ end
29
+ delimited_conjunction
30
+ end
31
+
32
+ def to_sentence(
33
+ quote_with: "'", delimiter: ', ', conjunction: 'and',
34
+ serial_delimiter: true
35
+ )
36
+ return '' if self.empty?
37
+ words = quote_elements(quote_with)
38
+ return words[0] if words.size == 1
39
+ return "#{words[0]} #{conjunction} #{words[1]}" if words.size == 2
40
+ delimited_conjunction = delimited_conjunction(
41
+ conjunction, delimiter, serial_delimiter)
42
+ [words[0...-1].join(delimiter), words.last].join(delimited_conjunction)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ require 'mysql_expectations/table'
6
+
7
+ module MySQLExpectations
8
+ # Allows assertions on a database
9
+ #
10
+ class Database
11
+ attr_reader
12
+
13
+ def initialize(database_element)
14
+ @database_element = database_element
15
+ end
16
+
17
+ def name
18
+ @database_element.attributes['name']
19
+ end
20
+
21
+ def table?(name)
22
+ query = "table_structure[@name='#{name}']"
23
+ !@database_element.elements[query].nil?
24
+ end
25
+
26
+ alias_method :has_table?, :table?
27
+
28
+ def table(name)
29
+ query = "table_structure[@name='#{name}']"
30
+ table_element = @database_element.elements[query]
31
+ Table.new table_element if table_element
32
+ end
33
+
34
+ def tables
35
+ query = 'table_structure'
36
+ tables = []
37
+ @database_element.elements.each(query) do |table_element|
38
+ tables << Table.new(table_element)
39
+ end
40
+ tables
41
+ end
42
+
43
+ def method_missing(method, *arguments, &block)
44
+ if arguments.empty? && block.nil?
45
+ table_name = method.to_s
46
+ return table(table_name) if table?(table_name)
47
+ end
48
+ super
49
+ end
50
+
51
+ def respond_to_missing?(method, *)
52
+ table?(method.to_s) || super
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ # Allows assertions on a database
7
+ #
8
+ class Field
9
+ def initialize(field_element)
10
+ @field_element = field_element
11
+ end
12
+
13
+ def name
14
+ @field_element.attributes['Field']
15
+ end
16
+
17
+ def definition?(expected_options)
18
+ expected_options.each do |expected_key, expected_value|
19
+ value = @field_element.attributes[expected_key]
20
+ return false if value.nil? || value != expected_value
21
+ end
22
+ true
23
+ end
24
+
25
+ alias_method :has_definition?, :definition?
26
+
27
+ def type
28
+ @field_element.attributes['Type']
29
+ end
30
+
31
+ def type?(expected_type)
32
+ expected_type == type
33
+ end
34
+
35
+ alias_method :has_type?, :type?
36
+
37
+ def nullable?
38
+ @field_element.attributes['Null'] == 'YES'
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,106 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ require 'mysql_expectations/key_field'
6
+
7
+ module MySQLExpectations
8
+ # An table key has a name and a sequence of index fields.
9
+ #
10
+ class Key
11
+ attr_reader :name, :unique, :fields
12
+
13
+ UNIQUE = true
14
+ NON_UNIQUE = false
15
+
16
+ def initialize(name, unique = nil, fields)
17
+ @name = name
18
+ @unique = unique
19
+ @fields = []
20
+ fields.each do |field|
21
+ field = KeyField.new(field) unless field.instance_of?(KeyField)
22
+ @fields << field
23
+ end
24
+ end
25
+
26
+ def ==(other)
27
+ name == other.name && unique == other.unique && fields == other.fields
28
+ end
29
+
30
+ def to_s
31
+ result = "{ '#{name}', #{uniqueness_to_s}, ["
32
+ fields.each_with_index do |field, index|
33
+ result << ', ' if index > 0
34
+ result << field.to_s
35
+ end
36
+ result << '] }'
37
+ result
38
+ end
39
+
40
+ def uniqueness_to_s
41
+ return 'nil' if unique.nil?
42
+ return 'UNIQUE' if unique == true
43
+ return 'NON_UNIQUE' if unique == false
44
+ end
45
+
46
+ def self.key?(table_element, key_name)
47
+ result = table_element.elements["key[@Key_name='#{key_name}']"]
48
+ !result.nil?
49
+ end
50
+
51
+ def self.load_key(table_element, key_name)
52
+ if key?(table_element, key_name)
53
+ key_fields = load_key_fields(table_element, key_name)
54
+ unique = load_uniqueness(table_element, key_name)
55
+ return Key.new(key_name, unique, key_fields)
56
+ end
57
+ nil
58
+ end
59
+
60
+ def self.load_all_keys(table_element)
61
+ keys = {}
62
+ table_element.elements.each('key') do |e|
63
+ key_name = e.attributes['Key_name']
64
+ unless keys.key? key_name
65
+ keys[key_name] = load_key(table_element, key_name)
66
+ end
67
+ end
68
+ keys.values
69
+ end
70
+
71
+ def self.find_key_element(table_element, index_name, field_index)
72
+ query = "key[@Key_name='#{index_name}' and " \
73
+ "@Seq_in_index='#{field_index + 1}']"
74
+ table_element.elements[query]
75
+ end
76
+
77
+ def self.collation_from_s(collation)
78
+ return KeyField::ORDER_DESC if collation == 'D'
79
+ KeyField::ORDER_ASC
80
+ end
81
+
82
+ def self.load_key_field(key_element)
83
+ name = key_element.attributes['Column_name']
84
+ collation = key_element.attributes['Collation']
85
+ collation = collation_from_s(collation)
86
+ length = key_element.attributes['Length']
87
+ KeyField.new(name, collation, length)
88
+ end
89
+
90
+ def self.load_uniqueness(table_element, key_name)
91
+ key_element = find_key_element(table_element, key_name, 0)
92
+ return nil if key_element.nil?
93
+ (key_element.attributes['Non_unique'] == '0')
94
+ end
95
+
96
+ def self.load_key_fields(table_element, key_name)
97
+ key_fields = []
98
+ (0..1000).each do |field_index|
99
+ key_element = find_key_element(table_element, key_name, field_index)
100
+ break if key_element.nil?
101
+ key_fields << load_key_field(key_element)
102
+ end
103
+ key_fields
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,59 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ # An index field has a field name, length, and order (aka order)
7
+ #
8
+ class KeyField
9
+ attr_reader :name, :length, :order
10
+
11
+ ORDER_ASC = :asc
12
+ ORDER_DESC = :desc
13
+
14
+ VALID_ORDERINGS = [ORDER_ASC, ORDER_DESC]
15
+
16
+ def initialize(name, order = nil, length = nil)
17
+ @name = name
18
+ @order = validate_order(order)
19
+ @length = validate_length(length)
20
+ end
21
+
22
+ def ==(other)
23
+ other.name == @name && other.length == @length && other.order == @order
24
+ end
25
+
26
+ def to_s
27
+ "{ '#{name}', #{order_to_s}, #{length_to_s} }"
28
+ end
29
+
30
+ private
31
+
32
+ def order_to_s
33
+ return 'ASC' if order == ORDER_ASC
34
+ return 'DESC' if order == ORDER_DESC
35
+ 'nil'
36
+ end
37
+
38
+ def length_to_s
39
+ length.to_s unless length.nil?
40
+ 'nil'
41
+ end
42
+
43
+ def validate_length(length)
44
+ return nil if length.nil?
45
+ begin
46
+ length = Integer(length)
47
+ rescue ArgumentError
48
+ raise ArgumentError, 'length must be an integer or convertable to an integer'
49
+ end
50
+ length
51
+ end
52
+
53
+ def validate_order(order)
54
+ return nil if order.nil?
55
+ return order if VALID_ORDERINGS.include? order
56
+ fail ArgumentError, 'Order must be either KeyField::ORDER_ASC or KeyField::ORDER_DESC'
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ module Matchers
7
+ # A matcher that checks a table's collation
8
+ #
9
+ class DatabaseHaveTable
10
+ attr_reader :expected_table, :database
11
+
12
+ def initialize(expected_table)
13
+ @expected_table = expected_table
14
+ @table = nil
15
+ end
16
+
17
+ def matches?(database)
18
+ @database = database
19
+ database.table?(expected_table)
20
+ end
21
+
22
+ def description
23
+ "have table '#{expected_table}'"
24
+ end
25
+
26
+ def failure_message
27
+ "expected '#{database.name}' database to have table " \
28
+ "'#{expected_table}'"
29
+ end
30
+
31
+ def failure_message_when_negated
32
+ "expected '#{database.name}' database not to have table " \
33
+ "'#{expected_table}'"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,68 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ require 'mysql_expectations/array_refinements'
6
+
7
+ module MySQLExpectations
8
+ module Matchers
9
+ # A matcher that checks what tables are in a database
10
+ #
11
+ class DatabaseOnlyHaveTables
12
+ using ArrayRefinements
13
+
14
+ attr_reader :database, :expected_table_names, :actual_table_names
15
+
16
+ def initialize(*expected_table_names)
17
+ @expected_table_names = expected_table_names.flatten
18
+ @database = nil
19
+ end
20
+
21
+ def liquibase_tables
22
+ %w(DATABASECHANGELOG DATABASECHANGELOGLOCK)
23
+ end
24
+
25
+ def actual_table_names
26
+ database.tables.map(&:name) - liquibase_tables
27
+ end
28
+
29
+ def matches?(database)
30
+ @database = database
31
+ actual_table_names.sort == expected_table_names.sort
32
+ end
33
+
34
+ def description
35
+ "only have tables #{expected_table_names.to_sentence}"
36
+ end
37
+
38
+ def additional_tables_message
39
+ message = ''
40
+ unless (actual_table_names - expected_table_names).empty?
41
+ message << ' but had additional tables: '
42
+ message <<
43
+ (actual_table_names - expected_table_names).to_sentence
44
+ end
45
+ message
46
+ end
47
+
48
+ def missing_tables_message
49
+ message = ''
50
+ unless (expected_table_names - actual_table_names).empty?
51
+ message << ' but was missing tables: '
52
+ message <<
53
+ (expected_table_names - actual_table_names).to_sentence
54
+ end
55
+ message
56
+ end
57
+
58
+ def failure_message
59
+ message = "expected '#{database.name}' "
60
+ message << 'database to only have tables '
61
+ message << expected_table_names.to_sentence
62
+ message << additional_tables_message
63
+ message << missing_tables_message
64
+ message
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ module Matchers
7
+ # A matcher that checks a table's collation
8
+ #
9
+ class TableHaveCollation
10
+ attr_reader :expected_collation, :table
11
+
12
+ def initialize(expected_collation)
13
+ @expected_collation = expected_collation
14
+ @table = nil
15
+ end
16
+
17
+ def actual_collation
18
+ table.collation
19
+ end
20
+
21
+ def matches?(table)
22
+ @table = table
23
+ actual_collation == expected_collation
24
+ end
25
+
26
+ def description
27
+ "have collation '#{expected_collation}'"
28
+ end
29
+
30
+ def failure_message
31
+ "expected '#{table.name}' table to have collation " \
32
+ "'#{expected_collation}' but it was '#{table.collation}'"
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ module Matchers
7
+ # A matcher that check a table's engine type
8
+ #
9
+ class HaveEngineType
10
+ attr_reader :expected_engine_type, :table
11
+
12
+ def initialize(expected_engine_type)
13
+ @expected_engine_type = expected_engine_type
14
+ @table = nil
15
+ end
16
+
17
+ def actual_engine_type
18
+ table.engine_type
19
+ end
20
+
21
+ def matches?(table)
22
+ @table = table
23
+ actual_engine_type == expected_engine_type
24
+ end
25
+
26
+ def description
27
+ "have engine type '#{expected_engine_type}'"
28
+ end
29
+
30
+ def failure_message
31
+ "expected '#{table.name}' table engine type to be " \
32
+ "'#{expected_engine_type}' " \
33
+ "but it was '#{actual_engine_type}'"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,107 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ module Matchers
7
+ # A matcher that checks if a MySQLDumpExpectations::Table has a field.
8
+ # Optionally, checks the field type and nullability
9
+ #
10
+ class HaveField
11
+ attr_reader :expected_field_name, :expected_type
12
+ attr_reader :expected_nullable, :table
13
+
14
+ def initialize(expected_field_name)
15
+ @expected_field_name = expected_field_name
16
+ @expected_type = nil
17
+ @expected_nullable = nil
18
+ @table = nil
19
+ end
20
+
21
+ def field_match?
22
+ table.field?(expected_field_name)
23
+ end
24
+
25
+ def actual_type
26
+ table.field(expected_field_name).type
27
+ end
28
+
29
+ def type_match?
30
+ if field_match? && !expected_type.nil?
31
+ return actual_type == expected_type
32
+ end
33
+ true
34
+ end
35
+
36
+ def actual_nullable
37
+ table.field(expected_field_name).nullable?
38
+ end
39
+
40
+ def nullable_match?
41
+ if field_match? && !expected_nullable.nil?
42
+ return actual_nullable == expected_nullable
43
+ end
44
+ true
45
+ end
46
+
47
+ def matches?(table)
48
+ @table = table
49
+ field_match? && type_match? && nullable_match?
50
+ end
51
+
52
+ def description
53
+ description = "have field '#{expected_field_name}'"
54
+ description << " of type '#{expected_type}'" if expected_type
55
+ description << ' that is nullable' if expected_nullable == true
56
+ description << ' that is not nullable' if expected_nullable == false
57
+ description
58
+ end
59
+
60
+ def field_error(negated: false)
61
+ "expected '#{table.name}' table" \
62
+ " #{negated ? 'not ' : ''}to "\
63
+ "have field '#{expected_field_name}'."
64
+ end
65
+
66
+ def type_error
67
+ "expected '#{table.name}.#{expected_field_name}' field " \
68
+ "to be of type '#{expected_type}' but it was '#{actual_type}'"
69
+ end
70
+
71
+ def nullable_error
72
+ message = "expected '#{table.name}.#{expected_field_name}' field "
73
+ message << 'to be '
74
+ message << 'not ' unless expected_nullable
75
+ message << 'nullable but it was '
76
+ message << 'not ' unless actual_nullable
77
+ message << 'nullable.'
78
+ message
79
+ end
80
+
81
+ def failure_message
82
+ return field_error unless field_match?
83
+ return type_error unless type_match?
84
+ return nullable_error unless nullable_match?
85
+ end
86
+
87
+ def failure_message_when_negated
88
+ field_error(negated: true)
89
+ end
90
+
91
+ def of_type(expected_type)
92
+ @expected_type = expected_type
93
+ self
94
+ end
95
+
96
+ def that_is_nullable
97
+ @expected_nullable = true
98
+ self
99
+ end
100
+
101
+ def that_is_not_nullable
102
+ @expected_nullable = false
103
+ self
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ module Matchers
7
+ # A matcher that checks if a MySQLDumpExpectations::Table has a field.
8
+ # Optionally, checks the field type and nullability
9
+ #
10
+ class HaveKey
11
+ attr_reader :expected_key, :table
12
+
13
+ def initialize(expected_key)
14
+ @expected_key = expected_key
15
+ @table = nil
16
+ end
17
+
18
+ def matches?(table)
19
+ @table = table
20
+ @table.key?(expected_key.name) &&
21
+ @table.key(expected_key.name) == expected_key
22
+ end
23
+
24
+ def description
25
+ description = "have key #{expected_key}"
26
+ description
27
+ end
28
+
29
+ def current_keys(keys)
30
+ result = ''
31
+ keys.each_with_index do |key, index|
32
+ result << key.to_s
33
+ result << ",\n" unless index == keys.size - 1
34
+ end
35
+ result
36
+ end
37
+
38
+ def failure_message
39
+ result = "expected '#{table.name}' table to " \
40
+ "have key #{expected_key}"
41
+ keys = table.keys
42
+ if keys.empty?
43
+ result << ' but it has no keys.'
44
+ else
45
+ result << " but it has keys:\n"
46
+ result << current_keys(keys)
47
+ end
48
+ result
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,50 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ require 'mysql_expectations/matchers/database_have_table'
6
+ require 'mysql_expectations/matchers/database_only_have_tables'
7
+ require 'mysql_expectations/matchers/table_have_collation'
8
+ require 'mysql_expectations/matchers/table_have_engine_type'
9
+ require 'mysql_expectations/matchers/table_have_field'
10
+ require 'mysql_expectations/matchers/table_have_key'
11
+
12
+ # rubocop:disable Style/PredicateName
13
+
14
+ module MySQLExpectations
15
+ # Allows assertions on a database
16
+ #
17
+ module Matchers
18
+ ####################
19
+ # Database Matchers
20
+ ####################
21
+
22
+ def have_table(expected_table_name)
23
+ DatabaseHaveTable.new(expected_table_name)
24
+ end
25
+
26
+ def only_have_tables(*expected_table_names)
27
+ DatabaseOnlyHaveTables.new(*expected_table_names)
28
+ end
29
+
30
+ ####################
31
+ # Table Matchers
32
+ ####################
33
+
34
+ def have_collation(expected_collation)
35
+ TableHaveCollation.new(expected_collation)
36
+ end
37
+
38
+ def have_engine_type(expected_engine_type)
39
+ HaveEngineType.new(expected_engine_type)
40
+ end
41
+
42
+ def have_field(expected_field_name)
43
+ HaveField.new(expected_field_name)
44
+ end
45
+
46
+ def have_key(expected_key)
47
+ HaveKey.new(expected_key)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ require 'rexml/document'
6
+ require 'mysql_expectations/database'
7
+
8
+ module MySQLExpectations
9
+ # The database_structure_file should be an XML file resulting from the
10
+ # mysqldump command:
11
+ #
12
+ # mysqldump --xml --no-data --all-databases \
13
+ # --host=#{env.host} --port=#{env.port} \
14
+ # --user=#{env.username}
15
+ #
16
+ class MySQL
17
+ def initialize(source)
18
+ @doc = REXML::Document.new(source)
19
+ end
20
+
21
+ def database?(name)
22
+ query = "mysqldump/database[@name='#{name}']"
23
+ !@doc.elements[query].nil?
24
+ end
25
+
26
+ alias_method :has_database?, :database?
27
+
28
+ def database(name)
29
+ query = "mysqldump/database[@name='#{name}']"
30
+ database_element = @doc.elements[query]
31
+ Database.new database_element if database_element
32
+ end
33
+
34
+ def databases
35
+ query = 'mysqldump/database'
36
+ databases = []
37
+ @doc.elements.each(query) do |database_element|
38
+ databases << Database.new(database_element)
39
+ end
40
+ databases
41
+ end
42
+
43
+ def method_missing(method_sym, *arguments, &block)
44
+ if arguments.empty? && block.nil?
45
+ database_name = method_sym.to_s
46
+ return database(database_name) if database?(database_name)
47
+ end
48
+ super
49
+ end
50
+
51
+ def respond_to_missing?(method, *)
52
+ database?(method.to_s) || super
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,102 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ require 'mysql_expectations/field'
6
+ require 'mysql_expectations/key'
7
+
8
+ module MySQLExpectations
9
+ # Allows assertions on a table
10
+ #
11
+ class Table
12
+ def initialize(table_element)
13
+ @table_element = table_element
14
+ end
15
+
16
+ def name
17
+ @table_element.attributes['name']
18
+ end
19
+
20
+ def field?(expected_field)
21
+ query = "field[@Field='#{expected_field}']"
22
+ !@table_element.elements[query].nil?
23
+ end
24
+
25
+ alias_method :has_field?, :field?
26
+
27
+ def field(name)
28
+ query = "field[@Field='#{name}']"
29
+ field_element = @table_element.elements[query]
30
+ Field.new field_element if field_element
31
+ end
32
+
33
+ def fields
34
+ query = 'field'
35
+ fields = []
36
+ @table_element.elements.each(query) do |field_element|
37
+ fields << Field.new(field_element)
38
+ end
39
+ fields
40
+ end
41
+
42
+ def option?(expected_options)
43
+ options = @table_element.elements['options']
44
+ expected_options.each do |expected_key, expected_value|
45
+ value = options.attributes[expected_key]
46
+ return false if value.nil? || value != expected_value
47
+ end
48
+ end
49
+
50
+ alias_method :has_option?, :option?
51
+
52
+ def engine_type
53
+ options = @table_element.elements['options']
54
+ options.attributes['Engine'] if options
55
+ end
56
+
57
+ def engine_type?(expected_engine_type)
58
+ engine_type == expected_engine_type
59
+ end
60
+
61
+ alias_method :has_engine_type?, :engine_type?
62
+
63
+ def collation
64
+ options = @table_element.elements['options']
65
+ options.attributes['Collation'] if options
66
+ end
67
+
68
+ def collation?(expected_collation)
69
+ collation == expected_collation
70
+ end
71
+
72
+ alias_method :has_collation?, :collation?
73
+
74
+ def key?(key_name)
75
+ Key.key?(@table_element, key_name)
76
+ end
77
+
78
+ def primary_key?
79
+ key?('PRIMARY')
80
+ end
81
+
82
+ def key(key_name)
83
+ Key.load_key(@table_element, key_name)
84
+ end
85
+
86
+ def keys
87
+ Key.load_all_keys(@table_element)
88
+ end
89
+
90
+ def method_missing(method, *arguments, &block)
91
+ if arguments.empty? && block.nil?
92
+ name = method.to_s
93
+ return field(name) if field?(name)
94
+ end
95
+ super
96
+ end
97
+
98
+ def respond_to_missing?(method, *)
99
+ field?(method.to_s) || super
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,10 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ module MySQLExpectations
6
+ # This module holds the gem version number used in the gemspec
7
+ module Version
8
+ VERSION = '1.0.0'
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ # Copyright (c) 2015 Yahoo Inc.
2
+ # Copyrights licensed under the New BSD License.
3
+ # See the accompanying LICENSE file for terms.
4
+
5
+ require 'mysql_expectations/array_refinements'
6
+ require 'mysql_expectations/mysql'
7
+ require 'mysql_expectations/database'
8
+ require 'mysql_expectations/table'
9
+ require 'mysql_expectations/field'
10
+ require 'mysql_expectations/key'
11
+ require 'mysql_expectations/key_field'
12
+ require 'mysql_expectations/matchers'
13
+ require 'mysql_expectations/version'
14
+
15
+ require 'rspec'
16
+
17
+ RSpec.configure do |config|
18
+ config.include MySQLExpectations::Matchers
19
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mysql_expectations
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - James Couball
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mustache
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-collection_matchers
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: cucumber
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: aruba
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: relish
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '10.4'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: '10.4'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: coveralls
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: ! " The mysql_expectations gem allows you to make RSpec expectations\n
154
+ \ on the schemas and data in a MySQL database enabling test first\n development
155
+ and more confident Continuous Delivery.\n"
156
+ email: couballj@yahoo-inc.com
157
+ executables: []
158
+ extensions: []
159
+ extra_rdoc_files: []
160
+ files:
161
+ - lib/mysql_expectations.rb
162
+ - lib/mysql_expectations/array_refinements.rb
163
+ - lib/mysql_expectations/database.rb
164
+ - lib/mysql_expectations/field.rb
165
+ - lib/mysql_expectations/key.rb
166
+ - lib/mysql_expectations/key_field.rb
167
+ - lib/mysql_expectations/matchers.rb
168
+ - lib/mysql_expectations/matchers/database_have_table.rb
169
+ - lib/mysql_expectations/matchers/database_only_have_tables.rb
170
+ - lib/mysql_expectations/matchers/table_have_collation.rb
171
+ - lib/mysql_expectations/matchers/table_have_engine_type.rb
172
+ - lib/mysql_expectations/matchers/table_have_field.rb
173
+ - lib/mysql_expectations/matchers/table_have_key.rb
174
+ - lib/mysql_expectations/mysql.rb
175
+ - lib/mysql_expectations/table.rb
176
+ - lib/mysql_expectations/version.rb
177
+ homepage: https://github.com/yahoo/mysql_expectations
178
+ licenses:
179
+ - BSD-3-Clause
180
+ metadata: {}
181
+ post_install_message:
182
+ rdoc_options: []
183
+ require_paths:
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ required_rubygems_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ! '>='
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ requirements: []
196
+ rubyforge_project:
197
+ rubygems_version: 2.4.5
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: RSpec matchers for MySQL schemas and data
201
+ test_files: []