real_data_tests 0.3.2 → 0.3.4
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 +4 -4
- data/CHANGELOG.md +24 -0
- data/lib/real_data_tests/configuration.rb +8 -0
- data/lib/real_data_tests/pg_dump_generator.rb +14 -7
- data/lib/real_data_tests/rspec_helper.rb +66 -4
- data/lib/real_data_tests/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a75133368f84b08bf44ad4f2ee73ed4eaf5636a7f19dbafdc5e6c47478055d8
|
4
|
+
data.tar.gz: 7693fa53c25af6c928ce61cb33e14667bf580fb18a32182452917932ca539bf2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 366de9d95f5d8582c83cebcb89e20af819a6516dc6a1a30e3e560b3ba6de5e300404a781a08fc6b1063b562dd2519ce83ce80a0976844dfd09e0ce94551641ca
|
7
|
+
data.tar.gz: be867e1b473e90ea4bcb9041704fe6e4edac3d4e371c283dda8ac6c32b2903cd2d5b81a326f4aaa6bcb36859c2125ec995d6d115b594441bb6f23b1cbc019e5b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,29 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.4] - 2025-01-14
|
4
|
+
### Added
|
5
|
+
- Alternative native SQL loading method for CI environments
|
6
|
+
- Added `load_real_test_data_native` method that doesn't rely on system commands
|
7
|
+
- Works in restricted environments like GitHub Actions
|
8
|
+
- Uses ActiveRecord's native connection for SQL execution
|
9
|
+
- Maintains same transaction and foreign key handling behavior
|
10
|
+
|
11
|
+
## [0.3.3] - 2025-01-14
|
12
|
+
### Fixed
|
13
|
+
- Improved circular dependency handling in PgDumpGenerator for self-referential associations
|
14
|
+
- Added robust checks for self-referential associations during topological sort
|
15
|
+
- Updated dependency graph building to properly exclude prevented circular dependencies
|
16
|
+
- Fixed model name handling in circular dependency error messages
|
17
|
+
- Improved error reporting for circular dependency detection
|
18
|
+
- Enhanced PresetConfiguration circular dependency prevention
|
19
|
+
- Added more reliable tracking of prevented reciprocal associations using Sets
|
20
|
+
- Improved handling of both class and string model names in prevention checks
|
21
|
+
- Better support for multiple prevented dependencies per model
|
22
|
+
- Updated record collection depth handling
|
23
|
+
- Fixed max depth enforcement for nested associations
|
24
|
+
- Added proper depth tracking for self-referential relationships
|
25
|
+
- Improved interaction between max depth and circular dependency prevention
|
26
|
+
|
3
27
|
## [0.3.2] - 2025-01-14
|
4
28
|
### Fixed
|
5
29
|
- Enhanced association statistics tracking in RecordCollector
|
@@ -87,6 +87,14 @@ module RealDataTests
|
|
87
87
|
@prevented_reciprocals << key
|
88
88
|
end
|
89
89
|
|
90
|
+
def max_self_ref_depth=(depth)
|
91
|
+
@max_self_ref_depth = depth
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_max_self_ref_depth(model)
|
95
|
+
@max_self_ref_depth
|
96
|
+
end
|
97
|
+
|
90
98
|
def has_circular_dependency?(klass, association_name)
|
91
99
|
key = if klass.is_a?(String)
|
92
100
|
"#{klass}:#{association_name}"
|
@@ -34,15 +34,19 @@ module RealDataTests
|
|
34
34
|
|
35
35
|
def build_dependency_graph(models)
|
36
36
|
models.each_with_object({}) do |model, deps|
|
37
|
-
#
|
38
|
-
# the true foreign key dependencies that affect insert order
|
37
|
+
# Get direct dependencies from belongs_to associations
|
39
38
|
direct_dependencies = model.reflect_on_all_associations(:belongs_to)
|
40
39
|
.reject(&:polymorphic?) # Skip polymorphic associations
|
40
|
+
.reject do |assoc|
|
41
|
+
# Skip self-referential associations that are configured to prevent circular deps
|
42
|
+
assoc.klass == model &&
|
43
|
+
RealDataTests.configuration.current_preset.prevent_reciprocal?(model, assoc.name)
|
44
|
+
end
|
41
45
|
.map(&:klass)
|
42
|
-
.select { |klass| models.include?(klass) }
|
46
|
+
.select { |klass| models.include?(klass) }
|
43
47
|
.uniq
|
44
48
|
|
45
|
-
#
|
49
|
+
# Handle HABTM associations
|
46
50
|
habtm_dependencies = model.reflect_on_all_associations(:has_and_belongs_to_many)
|
47
51
|
.map { |assoc| assoc.join_table_model }
|
48
52
|
.compact
|
@@ -69,9 +73,12 @@ module RealDataTests
|
|
69
73
|
return if visited.include?(model)
|
70
74
|
|
71
75
|
if temporary.include?(model)
|
72
|
-
#
|
73
|
-
|
74
|
-
|
76
|
+
# Only raise if this isn't a prevented self-reference
|
77
|
+
unless RealDataTests.configuration.current_preset.prevent_reciprocal?(model, model.model_name.singular)
|
78
|
+
cycle = detect_cycle(model, dependencies, temporary)
|
79
|
+
raise "Circular dependency detected: #{cycle.map(&:name).join(' -> ')}"
|
80
|
+
end
|
81
|
+
return
|
75
82
|
end
|
76
83
|
|
77
84
|
temporary.add(model)
|
@@ -3,16 +3,13 @@ module RealDataTests
|
|
3
3
|
def load_real_test_data(name)
|
4
4
|
dump_path = File.join(RealDataTests.configuration.dump_path, "#{name}.sql")
|
5
5
|
raise Error, "Test data file not found: #{dump_path}" unless File.exist?(dump_path)
|
6
|
-
|
7
6
|
ActiveRecord::Base.transaction do
|
8
7
|
# Disable foreign key checks
|
9
8
|
ActiveRecord::Base.connection.execute('SET session_replication_role = replica;')
|
10
|
-
|
11
9
|
begin
|
12
10
|
# Load the SQL dump quietly
|
13
11
|
result = system("psql #{connection_options} -q < #{dump_path}")
|
14
12
|
raise Error, "Failed to load test data: #{dump_path}" unless result
|
15
|
-
|
16
13
|
ensure
|
17
14
|
# Re-enable foreign key checks
|
18
15
|
ActiveRecord::Base.connection.execute('SET session_replication_role = DEFAULT;')
|
@@ -20,6 +17,40 @@ module RealDataTests
|
|
20
17
|
end
|
21
18
|
end
|
22
19
|
|
20
|
+
# New method that doesn't rely on system commands
|
21
|
+
def load_real_test_data_native(name)
|
22
|
+
dump_path = File.join(RealDataTests.configuration.dump_path, "#{name}.sql")
|
23
|
+
raise Error, "Test data file not found: #{dump_path}" unless File.exist?(dump_path)
|
24
|
+
|
25
|
+
ActiveRecord::Base.transaction do
|
26
|
+
connection = ActiveRecord::Base.connection
|
27
|
+
|
28
|
+
# Disable foreign key checks
|
29
|
+
connection.execute('SET session_replication_role = replica;')
|
30
|
+
|
31
|
+
begin
|
32
|
+
# Read the SQL file content
|
33
|
+
sql_content = File.read(dump_path)
|
34
|
+
|
35
|
+
# Split the file into individual statements
|
36
|
+
statements = split_sql_statements(sql_content)
|
37
|
+
|
38
|
+
# Execute each statement
|
39
|
+
statements.each do |statement|
|
40
|
+
next if statement.strip.empty?
|
41
|
+
begin
|
42
|
+
connection.execute(statement)
|
43
|
+
rescue ActiveRecord::StatementInvalid => e
|
44
|
+
raise Error, "Failed to execute SQL statement: #{e.message}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
ensure
|
48
|
+
# Re-enable foreign key checks
|
49
|
+
connection.execute('SET session_replication_role = DEFAULT;')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
23
54
|
private
|
24
55
|
|
25
56
|
def connection_options
|
@@ -28,7 +59,6 @@ module RealDataTests
|
|
28
59
|
else
|
29
60
|
ActiveRecord::Base.connection_config
|
30
61
|
end
|
31
|
-
|
32
62
|
options = []
|
33
63
|
options << "-h #{config[:host]}" if config[:host]
|
34
64
|
options << "-p #{config[:port]}" if config[:port]
|
@@ -37,5 +67,37 @@ module RealDataTests
|
|
37
67
|
options << "-q"
|
38
68
|
options.join(" ")
|
39
69
|
end
|
70
|
+
|
71
|
+
def split_sql_statements(sql)
|
72
|
+
statements = []
|
73
|
+
current_statement = ''
|
74
|
+
in_string = false
|
75
|
+
escaped = false
|
76
|
+
|
77
|
+
sql.each_char do |char|
|
78
|
+
case char
|
79
|
+
when '\\'
|
80
|
+
escaped = !escaped
|
81
|
+
when "'"
|
82
|
+
in_string = !in_string unless escaped
|
83
|
+
escaped = false
|
84
|
+
when ';'
|
85
|
+
if !in_string
|
86
|
+
statements << current_statement.strip
|
87
|
+
current_statement = ''
|
88
|
+
else
|
89
|
+
current_statement << char
|
90
|
+
end
|
91
|
+
else
|
92
|
+
escaped = false
|
93
|
+
current_statement << char
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Add the last statement if it doesn't end with a semicolon
|
98
|
+
statements << current_statement.strip if current_statement.strip.length > 0
|
99
|
+
|
100
|
+
statements
|
101
|
+
end
|
40
102
|
end
|
41
103
|
end
|