-
Notifications
You must be signed in to change notification settings - Fork 159
Expand file tree
/
Copy pathEnd2EndTest.php
More file actions
166 lines (146 loc) · 6.79 KB
/
End2EndTest.php
File metadata and controls
166 lines (146 loc) · 6.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
use Illuminate\Database\Capsule\Manager as Capsule;
/**
* End-to-End Test for DBDiff
*
* This test compares the SQL generated by DBDiff against pre-recorded expected files.
* It uses two temporary databases (diff1 and diff2) to perform the comparison.
*/
class End2EndTest extends PHPUnit\Framework\TestCase
{
// Database connection configuration
private $host;
private $port = 3306;
private $user = "root";
private $pass = "rootpass";
private $db1 = "diff1";
private $db2 = "diff2";
// Filenames for migration output and expectation baselines
private $migration_actual = 'migration_actual';
private $migration_expected = 'migration_expected';
// Database connection and metadata
private $db;
private $databaseMajor;
/**
* Set up the test environment.
* Note: We use setUp() instead of __construct() for PHPUnit 11 compatibility.
*/
protected function setUp(): void
{
// 1. Identify Database Host
// We use DB_HOST environment variable (provided by Docker) or fallback to 'db'
$this->host = getenv('DB_HOST') ?: ($_ENV['DB_HOST'] ?? ($_SERVER['DB_HOST'] ?? 'db'));
$debug = getenv('DBDIFF_DEBUG') === 'true';
if ($debug) {
echo "\nDEBUG: DB_HOST environment variable: " . (getenv('DB_HOST') ?: 'NOT_SET');
echo "\nDEBUG: Using database host: " . $this->host;
echo "\nDEBUG: Full connection string will be: mysql:host=" . $this->host . ";port=" . $this->port . "\n";
}
// 2. Establish Database Connection with Retry Logic
// This ensures tests don't fail if the MySQL container is still warming up
$maxRetries = 3;
$retryDelay = 2;
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
try {
$this->db = new PDO("mysql:host=$this->host;port=$this->port", $this->user, $this->pass);
if ($debug) {
echo "\nSuccessfully connected to database on attempt $attempt\n";
}
break;
} catch (PDOException $e) {
if ($debug) {
echo "\nConnection attempt $attempt failed: " . $e->getMessage();
}
if ($attempt === $maxRetries) {
if ($debug) {
echo "\nFailed to connect after $maxRetries attempts. Please check if MySQL is running.\n";
}
$this->fail("Failed to connect to database after $maxRetries attempts: " . $e->getMessage());
}
if ($debug) {
echo "\nRetrying in $retryDelay seconds...\n";
}
sleep($retryDelay);
}
}
// 3. Detect Database Version
// SQL generated by MySQL can vary slightly by version. We append the major version
// to the expectation filename (e.g., migration_expected_8) for byte-for-byte matching.
$databaseVersion = explode(".", $this->db->getAttribute(PDO::ATTR_SERVER_VERSION));
$this->databaseMajor = $databaseVersion[0];
$this->migration_expected = $this->migration_expected . "_" . $this->databaseMajor;
$this->migration_actual = $this->migration_actual . "_" . $this->databaseMajor;
if ($debug) {
echo "\nDatabase server major version is: " . $this->databaseMajor . "\n";
}
// 4. Reset Test Databases
// Ensure we start with a clean slate for every test execution
$this->db->exec("DROP DATABASE IF EXISTS `$this->db1`;");
$this->db->exec("DROP DATABASE IF EXISTS `$this->db2`;");
$this->db->exec("CREATE DATABASE `$this->db1`;");
$this->db->exec("CREATE DATABASE `$this->db2`;");
// 5. Initialize Database Fixtures
// Apply the pre-defined SQL structures to our test databases
$this->db->query("use `$this->db1`");
$this->db->exec(file_get_contents('tests/end2end/db1-up.sql'));
$this->db->query("use `$this->db2`");
$this->db->exec(file_get_contents('tests/end2end/db2-up.sql'));
}
/**
* Main test runner
*/
public function testAll()
{
// Prepare CLI arguments as if they were passed via terminal
$GLOBALS['argv'] = [
"",
"--server1=$this->user:$this->pass@$this->host:$this->port",
"--template=templates/simple-db-migrate.tmpl",
"--type=all",
"--include=all",
"--nocomments",
"--output=./tests/end2end/$this->migration_actual",
"server1.$this->db1:server1.$this->db2"
];
// Run DBDiff and capture output
// We use try-finally to ensure the output buffer is ALWAYS closed,
// preventing 'Risky Test' warnings in PHPUnit.
ob_start();
try {
$dbdiff = new DBDiff\DBDiff;
$dbdiff->run();
} finally {
ob_end_clean();
}
$migration_actual_content = file_get_contents("./tests/end2end/$this->migration_actual");
$migration_expected_path = "./tests/end2end/$this->migration_expected";
// Record Mode Logic
// If DBDIFF_RECORD_MODE is true, we update the gold standard file instead of asserting.
// This is useful when the environment or deterministic sorting order changes.
if (($_ENV['DBDIFF_RECORD_MODE'] ?? 'false') === 'true') {
file_put_contents($migration_expected_path, $migration_actual_content);
echo "\n📝 Recorded NEW deterministic expected output for Legacy End2EndTest (MySQL $this->databaseMajor)\n";
$this->addToAssertionCount(1);
} else {
if (!file_exists($migration_expected_path)) {
$this->fail("Expected output file not found: $migration_expected_path. Run with DBDIFF_RECORD_MODE=true to create it.");
}
$migration_expected_content = trim(file_get_contents($migration_expected_path));
// Assert that the generated SQL exactly matches our deterministic baseline
$this->assertEquals($migration_expected_content, trim($migration_actual_content));
}
}
/**
* Clean up after tests
*/
protected function tearDown(): void
{
// Remove temporary databases
$this->db->exec("DROP DATABASE IF EXISTS `$this->db1`;");
$this->db->exec("DROP DATABASE IF EXISTS `$this->db2`;");
// Remove temporary output file
if (file_exists("./tests/end2end/$this->migration_actual")) {
unlink("./tests/end2end/$this->migration_actual");
}
}
}