-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathautoprepare_test.go
120 lines (102 loc) · 2.44 KB
/
autoprepare_test.go
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
package autoprepare
import (
"context"
"database/sql"
"fmt"
"math"
"math/rand"
"sync/atomic"
"testing"
_ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3"
)
func TestSqlStmtCache(t *testing.T) {
if *SqliteDSN == "" {
t.Skip("SQLite is disabled")
}
db, err := sql.Open("sqlite3", *SqliteDSN)
if err != nil {
panic(err)
}
defer db.Close()
_, err = db.Exec("CREATE TABLE tables (a INT, b TEXT)")
if err != nil {
panic(err)
}
dbsc, err := New(db)
if err != nil {
panic(err)
}
ctx := context.Background()
for i := 0; i < 100000; i++ {
res, err := dbsc.QueryContext(ctx, "SELECT * FROM tables")
if err != nil {
panic(err)
}
res.Close()
}
}
func TestSqlStmtCachePollute(t *testing.T) {
if *SqliteDSN == "" {
t.Skip("SQLite is disabled")
}
db, err := sql.Open("sqlite3", *SqliteDSN)
if err != nil {
panic(err)
}
defer db.Close()
_, err = db.Exec("CREATE TABLE tables (a INT, b TEXT)")
if err != nil {
panic(err)
}
dbsc, err := New(db)
if err != nil {
panic(err)
}
ctx := context.Background()
for i := 0; i < 500000; i++ {
var a int
if i%2 == 0 {
a = int(math.Abs(rand.NormFloat64()*float64(dbsc.maxPS))) + (i / 10000)
} else {
a = rand.Intn(1 << 20)
}
res, err := dbsc.QueryContext(ctx, fmt.Sprintf("SELECT * FROM tables WHERE a = %d", a))
if err != nil {
panic(err)
}
res.Close()
}
expstmt := make(map[string]struct{})
for i := uint32(0); i < dbsc.maxPS; i++ {
expstmt[fmt.Sprintf("SELECT * FROM tables WHERE a = %d", i+49)] = struct{}{}
}
dbsc.l.RLock()
defer dbsc.l.RUnlock()
psCount := uint32(0)
for _, s := range dbsc.stmt {
prepared := s.prepared()
if prepared {
psCount++
}
_, expected := expstmt[s.q]
if prepared && !expected {
t.Errorf("unexpected prepared statement %q", s.q)
} else if !prepared && expected {
t.Errorf("missing prepared statement %q", s.q)
}
}
if len(dbsc.stmt) > dbsc.maxStmt {
t.Errorf("too many statements: %d/%d", len(dbsc.stmt), dbsc.maxStmt)
}
psc := atomic.LoadUint32(&dbsc.psCount)
if psc > dbsc.maxPS {
t.Errorf("too many prepared statements: %d/%d", psc, dbsc.maxPS)
}
if psc != psCount {
t.Errorf("inconsistent number of prepared statements: count %d, in map %d", psc, psCount)
}
if psc < dbsc.maxPS {
t.Errorf("not enough prepared statements: %d/%d", psc, dbsc.maxPS)
}
}