Skip to content

Commit f459411

Browse files
committed
Add extra tests for issue 1462 fix
These extra tests should help to avoid a regression for what issue 1462 reported.
1 parent 0174447 commit f459411

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

internal/dumper/loader_test.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dumper
22

33
import (
44
"context"
5+
"os"
56
"testing"
67

78
qt "github.com/frankban/quicktest"
@@ -47,3 +48,186 @@ func TestLoader(t *testing.T) {
4748
err = loader.Run(context.Background())
4849
c.Assert(err, qt.IsNil)
4950
}
51+
52+
func TestRestoreTableSchema_WithComments(t *testing.T) {
53+
tests := []struct {
54+
name string
55+
schemaContent string
56+
setupQueries []string
57+
description string
58+
}{
59+
{
60+
name: "schema with line comments at end",
61+
schemaContent: `CREATE TABLE example_table (
62+
id INT PRIMARY KEY
63+
);
64+
-- This is a comment
65+
-- This is another comment`,
66+
setupQueries: []string{
67+
"CREATE TABLE example_table (\n id INT PRIMARY KEY\n)",
68+
},
69+
description: "Should execute CREATE TABLE and skip trailing comments",
70+
},
71+
{
72+
name: "schema with ALTER TABLE after comments",
73+
schemaContent: `CREATE TABLE example_table (
74+
id INT PRIMARY KEY,
75+
name VARCHAR(100)
76+
);
77+
-- This is a comment
78+
-- This is another comment
79+
ALTER TABLE example_table
80+
ADD INDEX idx_name (name);`,
81+
setupQueries: []string{
82+
"CREATE TABLE example_table (\n id INT PRIMARY KEY,\n name VARCHAR(100)\n)",
83+
},
84+
description: "Should execute CREATE TABLE and ALTER TABLE, skipping comments in between",
85+
},
86+
{
87+
name: "schema with block comments",
88+
schemaContent: `/* This is a block comment */
89+
CREATE TABLE example_table (
90+
id INT PRIMARY KEY
91+
);`,
92+
setupQueries: []string{
93+
"CREATE TABLE example_table (\n id INT PRIMARY KEY\n)",
94+
},
95+
description: "Should skip block comments and execute CREATE TABLE",
96+
},
97+
{
98+
name: "schema with interspersed comments",
99+
schemaContent: `CREATE TABLE example_table (
100+
id INT PRIMARY KEY
101+
);
102+
-- Comment between statements
103+
ALTER TABLE example_table ADD COLUMN name VARCHAR(100);
104+
-- Another comment
105+
ALTER TABLE example_table ADD INDEX idx_id (id);`,
106+
setupQueries: []string{
107+
"CREATE TABLE example_table (\n id INT PRIMARY KEY\n)",
108+
},
109+
description: "Should execute all SQL statements and skip all comment lines",
110+
},
111+
}
112+
113+
for _, tt := range tests {
114+
t.Run(tt.name, func(t *testing.T) {
115+
c := qt.New(t)
116+
117+
log := xlog.NewStdLog(xlog.Level(xlog.ERROR))
118+
fakedbs := driver.NewTestHandler(log)
119+
server, err := driver.MockMysqlServer(log, fakedbs)
120+
c.Assert(err, qt.IsNil)
121+
defer server.Close()
122+
123+
address := server.Addr()
124+
125+
// Set up mock expectations
126+
fakedbs.AddQueryPattern("use .*", &sqltypes.Result{})
127+
fakedbs.AddQueryPattern("set foreign_key_checks=.*", &sqltypes.Result{})
128+
fakedbs.AddQueryPattern("drop table .*", &sqltypes.Result{})
129+
fakedbs.AddQueryPattern("alter table .*", &sqltypes.Result{})
130+
131+
// Add expected queries - if these aren't executed, the test will fail
132+
for _, query := range tt.setupQueries {
133+
fakedbs.AddQuery(query, &sqltypes.Result{})
134+
}
135+
136+
// Create test schema file
137+
tempDir := c.TempDir()
138+
schemaFile := tempDir + "/testdb.test_table-schema.sql"
139+
err = os.WriteFile(schemaFile, []byte(tt.schemaContent), 0644)
140+
c.Assert(err, qt.IsNil)
141+
142+
// Create loader
143+
cfg := &Config{
144+
Database: "testdb",
145+
Outdir: tempDir,
146+
User: "mock",
147+
Password: "mock",
148+
Threads: 1,
149+
Address: address,
150+
IntervalMs: 500,
151+
OverwriteTables: true,
152+
ShowDetails: false,
153+
Debug: false,
154+
}
155+
loader, err := NewLoader(cfg)
156+
c.Assert(err, qt.IsNil)
157+
158+
// Create connection pool
159+
pool, err := NewPool(loader.log, cfg.Threads, cfg.Address, cfg.User, cfg.Password, cfg.SessionVars, "")
160+
c.Assert(err, qt.IsNil)
161+
defer pool.Close()
162+
163+
conn := pool.Get()
164+
defer pool.Put(conn)
165+
166+
// Execute restoreTableSchema - should not return error if all expected queries are executed
167+
err = loader.restoreTableSchema(cfg.OverwriteTables, []string{schemaFile}, conn)
168+
c.Assert(err, qt.IsNil, qt.Commentf("%s: failed to restore table schema", tt.description))
169+
})
170+
}
171+
}
172+
173+
func TestRestoreTableSchema_DropTableCalledOnce(t *testing.T) {
174+
c := qt.New(t)
175+
176+
log := xlog.NewStdLog(xlog.Level(xlog.ERROR))
177+
fakedbs := driver.NewTestHandler(log)
178+
server, err := driver.MockMysqlServer(log, fakedbs)
179+
c.Assert(err, qt.IsNil)
180+
defer server.Close()
181+
182+
address := server.Addr()
183+
184+
// Set up mock expectations
185+
fakedbs.AddQueryPattern("use .*", &sqltypes.Result{})
186+
fakedbs.AddQueryPattern("set foreign_key_checks=.*", &sqltypes.Result{})
187+
188+
// Add DROP TABLE query only once - if it's called twice, the second call will fail
189+
// because there's no matching handler for it
190+
fakedbs.AddQuery("DROP TABLE IF EXISTS `testdb`.`test_table`", &sqltypes.Result{})
191+
fakedbs.AddQuery("CREATE TABLE test_table (\n id INT PRIMARY KEY\n)", &sqltypes.Result{})
192+
193+
// Create test schema file with comments at the end (the original bug scenario)
194+
tempDir := c.TempDir()
195+
schemaFile := tempDir + "/testdb.test_table-schema.sql"
196+
schemaContent := `CREATE TABLE test_table (
197+
id INT PRIMARY KEY
198+
);
199+
-- This is a comment
200+
-- This is another comment`
201+
err = os.WriteFile(schemaFile, []byte(schemaContent), 0644)
202+
c.Assert(err, qt.IsNil)
203+
204+
// Create loader
205+
cfg := &Config{
206+
Database: "testdb",
207+
Outdir: tempDir,
208+
User: "mock",
209+
Password: "mock",
210+
Threads: 1,
211+
Address: address,
212+
IntervalMs: 500,
213+
OverwriteTables: true,
214+
ShowDetails: false,
215+
Debug: false,
216+
}
217+
loader, err := NewLoader(cfg)
218+
c.Assert(err, qt.IsNil)
219+
220+
// Create connection pool
221+
pool, err := NewPool(loader.log, cfg.Threads, cfg.Address, cfg.User, cfg.Password, cfg.SessionVars, "")
222+
c.Assert(err, qt.IsNil)
223+
defer pool.Close()
224+
225+
conn := pool.Get()
226+
defer pool.Put(conn)
227+
228+
// Execute restoreTableSchema
229+
// If DROP TABLE is called more than once, the test will fail because there's
230+
// only one handler registered for it
231+
err = loader.restoreTableSchema(cfg.OverwriteTables, []string{schemaFile}, conn)
232+
c.Assert(err, qt.IsNil, qt.Commentf("DROP TABLE should be called exactly once. If called multiple times, this test will fail."))
233+
}

0 commit comments

Comments
 (0)