Skip to content

Commit 063264e

Browse files
authored
test(contrib/drivers/mysql): add Lock/Omit/Cache/Batch tests (gogf#4706)
## Summary - Add Lock/LockUpdate/LockShared tests - Add OmitNil/OmitEmpty/OmitNilData tests - Add Cache mechanism tests - Add Batch operation tests **Test coverage added:** ~34 test functions across 4 files Ref gogf#4689 ## Test plan ```bash cd contrib/drivers/mysql go test -v -run "TestModel_Lock|TestModel_Omit|TestModel_Cache|TestModel_Batch" ```
1 parent 02abc51 commit 063264e

4 files changed

Lines changed: 1263 additions & 0 deletions

File tree

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
2+
//
3+
// This Source Code Form is subject to the terms of the MIT License.
4+
// If a copy of the MIT was not distributed with this file,
5+
// You can obtain one at https://github.com/gogf/gf.
6+
7+
package mysql_test
8+
9+
import (
10+
"context"
11+
"fmt"
12+
"testing"
13+
14+
"github.com/gogf/gf/v2/database/gdb"
15+
"github.com/gogf/gf/v2/frame/g"
16+
"github.com/gogf/gf/v2/test/gtest"
17+
)
18+
19+
// Test_Model_Batch_Insert tests batch insert with different batch sizes
20+
func Test_Model_Batch_Insert(t *testing.T) {
21+
table := createTable()
22+
defer dropTable(table)
23+
24+
gtest.C(t, func(t *gtest.T) {
25+
// Prepare data for batch insert
26+
data := g.Slice{}
27+
for i := 1; i <= 10; i++ {
28+
data = append(data, g.Map{
29+
"id": i,
30+
"passport": fmt.Sprintf("batch_user_%d", i),
31+
"password": fmt.Sprintf("batch_pass_%d", i),
32+
"nickname": fmt.Sprintf("batch_name_%d", i),
33+
})
34+
}
35+
36+
// Batch insert with batch size 3
37+
result, err := db.Model(table).Batch(3).Data(data).Insert()
38+
t.AssertNil(err)
39+
n, _ := result.RowsAffected()
40+
t.Assert(n, 10)
41+
42+
// Verify all records were inserted
43+
count, err := db.Model(table).Count()
44+
t.AssertNil(err)
45+
t.Assert(count, 10)
46+
47+
// Verify specific records
48+
one, err := db.Model(table).Where("id", 1).One()
49+
t.AssertNil(err)
50+
t.Assert(one["passport"], "batch_user_1")
51+
52+
one, err = db.Model(table).Where("id", 10).One()
53+
t.AssertNil(err)
54+
t.Assert(one["passport"], "batch_user_10")
55+
})
56+
}
57+
58+
// Test_Model_Batch_Replace tests batch replace operation
59+
func Test_Model_Batch_Replace(t *testing.T) {
60+
table := createTable()
61+
defer dropTable(table)
62+
63+
gtest.C(t, func(t *gtest.T) {
64+
// Initial insert
65+
data := g.Slice{}
66+
for i := 1; i <= 5; i++ {
67+
data = append(data, g.Map{
68+
"id": i,
69+
"passport": fmt.Sprintf("original_%d", i),
70+
})
71+
}
72+
_, err := db.Model(table).Data(data).Insert()
73+
t.AssertNil(err)
74+
75+
// Batch replace with overlapping ids
76+
replaceData := g.Slice{}
77+
for i := 3; i <= 8; i++ {
78+
replaceData = append(replaceData, g.Map{
79+
"id": i,
80+
"passport": fmt.Sprintf("replaced_%d", i),
81+
"nickname": fmt.Sprintf("new_name_%d", i),
82+
})
83+
}
84+
result, err := db.Model(table).Batch(2).Data(replaceData).Replace()
85+
t.AssertNil(err)
86+
n, _ := result.RowsAffected()
87+
t.AssertGT(n, 0)
88+
89+
// Verify replaced records
90+
one, err := db.Model(table).Where("id", 3).One()
91+
t.AssertNil(err)
92+
t.Assert(one["passport"], "replaced_3")
93+
t.Assert(one["nickname"], "new_name_3")
94+
95+
// Verify new records
96+
one, err = db.Model(table).Where("id", 8).One()
97+
t.AssertNil(err)
98+
t.Assert(one["passport"], "replaced_8")
99+
100+
// Verify total count
101+
count, err := db.Model(table).Count()
102+
t.AssertNil(err)
103+
t.Assert(count, 8) // ids 1-8
104+
})
105+
}
106+
107+
// Test_Model_Batch_Save tests batch save operation
108+
func Test_Model_Batch_Save(t *testing.T) {
109+
table := createTable()
110+
defer dropTable(table)
111+
112+
gtest.C(t, func(t *gtest.T) {
113+
// Initial data
114+
data := g.Slice{}
115+
for i := 1; i <= 5; i++ {
116+
data = append(data, g.Map{
117+
"id": i,
118+
"passport": fmt.Sprintf("save_user_%d", i),
119+
})
120+
}
121+
_, err := db.Model(table).Data(data).Insert()
122+
t.AssertNil(err)
123+
124+
// Batch save with overlapping and new ids
125+
saveData := g.Slice{}
126+
for i := 3; i <= 8; i++ {
127+
saveData = append(saveData, g.Map{
128+
"id": i,
129+
"passport": fmt.Sprintf("saved_%d", i),
130+
"nickname": fmt.Sprintf("save_name_%d", i),
131+
})
132+
}
133+
result, err := db.Model(table).Batch(3).Data(saveData).Save()
134+
t.AssertNil(err)
135+
n, _ := result.RowsAffected()
136+
t.AssertGT(n, 0)
137+
138+
// Verify updated records
139+
one, err := db.Model(table).Where("id", 3).One()
140+
t.AssertNil(err)
141+
t.Assert(one["passport"], "saved_3")
142+
143+
// Verify inserted records
144+
one, err = db.Model(table).Where("id", 8).One()
145+
t.AssertNil(err)
146+
t.Assert(one["passport"], "saved_8")
147+
148+
// Verify total count
149+
count, err := db.Model(table).Count()
150+
t.AssertNil(err)
151+
t.Assert(count, 8)
152+
})
153+
}
154+
155+
// Test_Model_Batch_LargeBatch tests batch operation with large dataset
156+
func Test_Model_Batch_LargeBatch(t *testing.T) {
157+
table := createTable()
158+
defer dropTable(table)
159+
160+
gtest.C(t, func(t *gtest.T) {
161+
// Prepare 1000+ records
162+
data := g.Slice{}
163+
totalRecords := 1500
164+
for i := 1; i <= totalRecords; i++ {
165+
data = append(data, g.Map{
166+
"id": i,
167+
"passport": fmt.Sprintf("large_user_%d", i),
168+
"nickname": fmt.Sprintf("large_name_%d", i),
169+
})
170+
}
171+
172+
// Batch insert with batch size 100
173+
result, err := db.Model(table).Batch(100).Data(data).Insert()
174+
t.AssertNil(err)
175+
n, _ := result.RowsAffected()
176+
t.Assert(n, totalRecords)
177+
178+
// Verify count
179+
count, err := db.Model(table).Count()
180+
t.AssertNil(err)
181+
t.Assert(count, totalRecords)
182+
183+
// Verify first and last records
184+
one, err := db.Model(table).Where("id", 1).One()
185+
t.AssertNil(err)
186+
t.Assert(one["passport"], "large_user_1")
187+
188+
one, err = db.Model(table).Where("id", totalRecords).One()
189+
t.AssertNil(err)
190+
t.Assert(one["passport"], fmt.Sprintf("large_user_%d", totalRecords))
191+
})
192+
}
193+
194+
// Test_Model_Batch_EmptyBatch tests batch operation with empty data
195+
func Test_Model_Batch_EmptyBatch(t *testing.T) {
196+
table := createTable()
197+
defer dropTable(table)
198+
199+
gtest.C(t, func(t *gtest.T) {
200+
// Empty slice
201+
data := g.Slice{}
202+
203+
// Batch insert with empty data should return error
204+
_, err := db.Model(table).Batch(10).Data(data).Insert()
205+
t.AssertNE(err, nil)
206+
t.AssertIN(err.Error(), "data list cannot be empty")
207+
208+
// Verify no records inserted
209+
count, err := db.Model(table).Count()
210+
t.AssertNil(err)
211+
t.Assert(count, 0)
212+
})
213+
}
214+
215+
// Test_Model_Batch_SingleRecord tests batch operation with single record
216+
func Test_Model_Batch_SingleRecord(t *testing.T) {
217+
table := createTable()
218+
defer dropTable(table)
219+
220+
gtest.C(t, func(t *gtest.T) {
221+
// Single record batch insert
222+
data := g.Slice{
223+
g.Map{
224+
"id": 1,
225+
"passport": "single_user",
226+
"nickname": "single_name",
227+
},
228+
}
229+
230+
result, err := db.Model(table).Batch(10).Data(data).Insert()
231+
t.AssertNil(err)
232+
n, _ := result.RowsAffected()
233+
t.Assert(n, 1)
234+
235+
// Verify the record
236+
one, err := db.Model(table).Where("id", 1).One()
237+
t.AssertNil(err)
238+
t.Assert(one["passport"], "single_user")
239+
t.Assert(one["nickname"], "single_name")
240+
})
241+
}
242+
243+
// Test_Model_Batch_VsBatch tests performance comparison between different batch sizes
244+
func Test_Model_Batch_VsBatch(t *testing.T) {
245+
table := createTable()
246+
defer dropTable(table)
247+
248+
gtest.C(t, func(t *gtest.T) {
249+
// Prepare data
250+
data := g.Slice{}
251+
for i := 1; i <= 100; i++ {
252+
data = append(data, g.Map{
253+
"id": i,
254+
"passport": fmt.Sprintf("perf_user_%d", i),
255+
})
256+
}
257+
258+
// Test with batch size 1
259+
result, err := db.Model(table).Batch(1).Data(data).Insert()
260+
t.AssertNil(err)
261+
n, _ := result.RowsAffected()
262+
t.Assert(n, 100)
263+
264+
// Clean up
265+
_, err = db.Model(table).Where("1=1").Delete()
266+
t.AssertNil(err)
267+
268+
// Test with batch size 10
269+
result, err = db.Model(table).Batch(10).Data(data).Insert()
270+
t.AssertNil(err)
271+
n, _ = result.RowsAffected()
272+
t.Assert(n, 100)
273+
274+
// Clean up
275+
_, err = db.Model(table).Where("1=1").Delete()
276+
t.AssertNil(err)
277+
278+
// Test with batch size 50
279+
result, err = db.Model(table).Batch(50).Data(data).Insert()
280+
t.AssertNil(err)
281+
n, _ = result.RowsAffected()
282+
t.Assert(n, 100)
283+
284+
// All batch sizes should produce same result
285+
count, err := db.Model(table).Count()
286+
t.AssertNil(err)
287+
t.Assert(count, 100)
288+
})
289+
}
290+
291+
// Test_Model_Batch_WithTransaction tests batch operation within transaction
292+
func Test_Model_Batch_WithTransaction(t *testing.T) {
293+
table := createTable()
294+
defer dropTable(table)
295+
296+
gtest.C(t, func(t *gtest.T) {
297+
data := g.Slice{}
298+
for i := 1; i <= 50; i++ {
299+
data = append(data, g.Map{
300+
"id": i,
301+
"passport": fmt.Sprintf("tx_batch_%d", i),
302+
})
303+
}
304+
305+
// Test commit
306+
err := db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
307+
result, err := tx.Model(table).Batch(10).Data(data).Insert()
308+
t.AssertNil(err)
309+
n, _ := result.RowsAffected()
310+
t.Assert(n, 50)
311+
return nil
312+
})
313+
t.AssertNil(err)
314+
315+
// Verify commit
316+
count, err := db.Model(table).Count()
317+
t.AssertNil(err)
318+
t.Assert(count, 50)
319+
320+
// Clean up
321+
_, err = db.Model(table).Where("1=1").Delete()
322+
t.AssertNil(err)
323+
324+
// Test rollback
325+
err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
326+
_, err := tx.Model(table).Batch(10).Data(data).Insert()
327+
t.AssertNil(err)
328+
return fmt.Errorf("rollback test")
329+
})
330+
t.AssertNE(err, nil)
331+
332+
// Verify rollback - no records should exist
333+
count, err = db.Model(table).Count()
334+
t.AssertNil(err)
335+
t.Assert(count, 0)
336+
})
337+
}

0 commit comments

Comments
 (0)