Skip to content

Commit e08cf1e

Browse files
committed
Refactor test, split into smaller subtests
1 parent 41d572e commit e08cf1e

File tree

2 files changed

+125
-98
lines changed

2 files changed

+125
-98
lines changed

internal/bitmapist/bitmapist_test.go

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"github.com/artyom/red"
1515
"github.com/artyom/resp"
16+
bolt "go.etcd.io/bbolt"
1617
)
1718

1819
func TestServer(t *testing.T) {
@@ -114,11 +115,7 @@ func checkResponse(t testing.TB, req string, respWanted interface{}, rd resp.Byt
114115
}
115116

116117
func newServer(t testing.TB) (fn clientConnFunc, cleanup func()) {
117-
td, err := os.MkdirTemp("", "bitmapist-test-")
118-
if err != nil {
119-
t.Fatal(err)
120-
return
121-
}
118+
td := t.TempDir()
122119
srv, err := New(filepath.Join(td, "temp.db"))
123120
if err != nil {
124121
os.RemoveAll(td)
@@ -127,6 +124,7 @@ func newServer(t testing.TB) (fn clientConnFunc, cleanup func()) {
127124
}
128125
redsrv := red.NewServer()
129126
srv.Register(redsrv)
127+
redsrv.Handle("flushall", srv.handleFlush)
130128
unixSocket := filepath.Join(td, "bitmapist.sock")
131129
ln, err := net.Listen("unix", unixSocket)
132130
if err != nil {
@@ -157,12 +155,7 @@ func newServer(t testing.TB) (fn clientConnFunc, cleanup func()) {
157155
type clientConnFunc func() net.Conn
158156

159157
func TestServerPersistence(t *testing.T) {
160-
td, err := os.MkdirTemp("", "bitmapist-test-")
161-
if err != nil {
162-
t.Fatal(err)
163-
return
164-
}
165-
defer os.RemoveAll(td)
158+
td := t.TempDir()
166159
newServerDirectory := func(t testing.TB) (fn clientConnFunc, cleanup func()) {
167160
srv, err := New(filepath.Join(td, "temp.db"))
168161
if err != nil {
@@ -212,3 +205,21 @@ func TestServerPersistence(t *testing.T) {
212205
defer conn.Close()
213206
checkResponse(t, "get foo", "\x01 ", rd, conn)
214207
}
208+
209+
func (s *Server) handleFlush(r red.Request) (any, error) { // should only be used in tests
210+
if len(r.Args) != 0 {
211+
return nil, red.ErrWrongArgs
212+
}
213+
s.mu.Lock()
214+
defer s.mu.Unlock()
215+
clear(s.keys)
216+
clear(s.cache)
217+
clear(s.rm)
218+
_ = s.db.Update(func(tx *bolt.Tx) error {
219+
for _, name := range [][]byte{bucketName, expiresBucket} {
220+
_ = tx.DeleteBucket(name)
221+
}
222+
return nil
223+
})
224+
return resp.OK, nil
225+
}

internal/bitmapist/compare_test.go

Lines changed: 103 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -26,106 +26,127 @@ func TestAgainstRedis(t *testing.T) {
2626
cfRedis, cleanupRedis := newRedisServer(t)
2727
defer cleanupRedis()
2828

29-
cmds := []string{
30-
"ping",
31-
"ping hello",
32-
"multi",
33-
"setbit foo 10 1",
34-
"setbit foo 7 1",
35-
"bitcount foo",
36-
"setbit bar 7 1",
37-
"setbit bar 6 1",
38-
"setbit bar 6 0",
39-
"bitcount bar",
40-
"exec",
41-
"get foo",
42-
"get bar",
43-
44-
"bitop not dst foo",
45-
"get dst",
46-
"bitcount dst",
47-
"getbit dst 5",
48-
49-
"bitop xor dst foo bar",
50-
"get dst",
51-
52-
"bitop or dst foo bar",
53-
"get dst",
54-
55-
"del foo bar",
56-
"setbit foo 10 1",
57-
"setbit foo 7 1",
58-
"setbit bar 10 1",
59-
60-
"bitop and dst foo bar",
61-
"get dst",
62-
"set dst \xff\x7f",
63-
"get dst",
64-
65-
"ttl nonexistent",
66-
"ttl dst",
67-
"expire dst 60",
68-
"ttl dst",
69-
70-
"setbit src_rename 1 1",
71-
"expire src_rename 60",
72-
"rename src_rename dst_rename",
73-
"ttl dst_rename",
74-
"getbit dst_rename 1",
75-
76-
"bitop and xxx_dst xxx_nonexistent xxx_nonexistent",
77-
"bitcount xxx_dst",
78-
"exists xxx_dst",
79-
"del xxx_dst",
80-
81-
"setbit xxx_somekey 256 1",
82-
"bitop and xxx_dst xxx_nonexistent xxx_somekey",
83-
"bitcount xxx_dst",
84-
85-
"quit",
29+
type testCase struct {
30+
name string
31+
commands []string
8632
}
87-
88-
resBitmapist, err := collectOutput(cmds, cf)
89-
if err != nil {
90-
t.Fatal(err)
91-
}
92-
resRedis, err := collectOutput(cmds, cfRedis)
93-
if err != nil {
94-
t.Fatal(err)
95-
}
96-
if !bytes.Equal(resBitmapist, resRedis) {
97-
if out, _ := diff(resBitmapist, resRedis); out != nil {
98-
t.Logf("diff -u:\n%s\n", out)
99-
}
100-
t.Fatal("bitmapist and redis output differ")
33+
for _, test := range []testCase{
34+
{name: "basic", commands: []string{
35+
"ping",
36+
"ping hello",
37+
"multi",
38+
"setbit foo 10 1",
39+
"setbit foo 7 1",
40+
"bitcount foo",
41+
"setbit bar 7 1",
42+
"setbit bar 6 1",
43+
"setbit bar 6 0",
44+
"bitcount bar",
45+
"exec",
46+
"get foo",
47+
"get bar",
48+
}},
49+
{name: "bitop xor", commands: []string{
50+
"setbit foo 10 1",
51+
"setbit foo 7 1",
52+
"setbit bar 7 1",
53+
"setbit bar 6 1",
54+
"setbit bar 6 0",
55+
"bitop xor dst foo bar",
56+
"get dst",
57+
}},
58+
{name: "bitop not", commands: []string{
59+
"setbit foo 10 1",
60+
"bitop not dst foo",
61+
"get dst",
62+
"bitcount dst",
63+
"getbit dst 5",
64+
}},
65+
{name: "bitop or", commands: []string{
66+
"setbit foo 10 1",
67+
"setbit bar 6 1",
68+
"bitop or dst foo bar",
69+
"get dst",
70+
}},
71+
{name: "bitop and", commands: []string{
72+
"setbit foo 10 1",
73+
"setbit foo 7 1",
74+
"setbit bar 10 1",
75+
"bitop and dst foo bar",
76+
"get dst",
77+
"set dst \xff\x7f",
78+
"get dst",
79+
}},
80+
{name: "ttl", commands: []string{
81+
"set dst \xff\x7f",
82+
"ttl nonexistent",
83+
"ttl dst",
84+
"expire dst 60",
85+
"ttl dst",
86+
}},
87+
{name: "rename", commands: []string{
88+
"setbit src_rename 1 1",
89+
"expire src_rename 60",
90+
"rename src_rename dst_rename",
91+
"ttl dst_rename",
92+
"getbit dst_rename 1",
93+
}},
94+
{name: "bitop and nonexistent", commands: []string{
95+
"bitop and xxx_dst xxx_nonexistent xxx_nonexistent",
96+
"bitcount xxx_dst",
97+
"exists xxx_dst",
98+
"del xxx_dst",
99+
"setbit xxx_somekey 256 1",
100+
"bitop and xxx_dst xxx_nonexistent xxx_somekey",
101+
"bitcount xxx_dst",
102+
}},
103+
} {
104+
t.Run(test.name, func(t *testing.T) {
105+
resBitmapist, err := flushAndCollectOutput(test.commands, cf)
106+
if err != nil {
107+
t.Fatal(err)
108+
}
109+
resRedis, err := flushAndCollectOutput(test.commands, cfRedis)
110+
if err != nil {
111+
t.Fatal(err)
112+
}
113+
if !bytes.Equal(resBitmapist, resRedis) {
114+
if out, _ := diff(t.TempDir(), resBitmapist, resRedis); out != nil {
115+
t.Logf("diff -u:\n%s\n", out)
116+
}
117+
t.Fatal("bitmapist and redis output differ")
118+
}
119+
})
101120
}
102121
}
103122

104-
func collectOutput(cmds []string, cf clientConnFunc) ([]byte, error) {
123+
func flushAndCollectOutput(cmds []string, cf clientConnFunc) ([]byte, error) {
105124
conn := cf()
106125
defer conn.Close()
107126
rd := bufio.NewReader(conn)
108127
buf := new(bytes.Buffer)
128+
if err := resp.Encode(conn, []string{"flushall"}); err != nil {
129+
return nil, fmt.Errorf("flushall: %w", err)
130+
}
131+
if _, err := resp.Decode(rd); err != nil {
132+
return nil, fmt.Errorf("flushall response: %w", err)
133+
}
109134
for _, cmd := range cmds {
110-
fmt.Fprintf(buf, "> %s\n", cmd)
135+
fmt.Fprintf(buf, "(client)> %s\n", cmd)
111136
if err := resp.Encode(conn, strings.Fields(cmd)); err != nil {
112137
return nil, err
113138
}
114139
response, err := resp.Decode(rd)
115140
if err != nil {
116141
return nil, err
117142
}
118-
fmt.Fprintf(buf, "< %#v\n", response)
143+
fmt.Fprintf(buf, "(server)> %#v\n", response)
119144
}
120145
return buf.Bytes(), nil
121146
}
122147

123148
func newRedisServer(t testing.TB) (fn clientConnFunc, cleanup func()) {
124-
td, err := os.MkdirTemp("", "bitmapist-test-")
125-
if err != nil {
126-
t.Fatal(err)
127-
return
128-
}
149+
td := t.TempDir()
129150
buf := bytes.NewBufferString(redisConf)
130151
unixSocket := filepath.Join(td, "redis.sock")
131152
fmt.Fprintf(buf, "\nunixsocket %s\n", unixSocket)
@@ -168,19 +189,14 @@ func newRedisServer(t testing.TB) (fn clientConnFunc, cleanup func()) {
168189
return fn, cleanup
169190
}
170191

171-
func diff(resBitmapist, resRedis []byte) ([]byte, error) {
172-
td, err := os.MkdirTemp("", "")
173-
if err != nil {
174-
return nil, err
175-
}
176-
defer os.RemoveAll(td)
177-
if err := os.WriteFile(filepath.Join(td, "bmpst.txt"), resBitmapist, 0644); err != nil {
192+
func diff(td string, resBitmapist, resRedis []byte) ([]byte, error) {
193+
if err := os.WriteFile(filepath.Join(td, "bitmapist-server.txt"), resBitmapist, 0644); err != nil {
178194
return nil, err
179195
}
180196
if err := os.WriteFile(filepath.Join(td, "redis.txt"), resRedis, 0644); err != nil {
181197
return nil, err
182198
}
183-
cmd := exec.Command("diff", "-u", "bmpst.txt", "redis.txt")
199+
cmd := exec.Command("diff", "-u", "bitmapist-server.txt", "redis.txt")
184200
cmd.Dir = td
185201
return cmd.CombinedOutput()
186202
}

0 commit comments

Comments
 (0)