Skip to content

Commit 6f412de

Browse files
committed
add CompareAndSwap (cas) tests
Signed-off-by: Brad Fitzpatrick <brad@danga.com>
1 parent 553e0d5 commit 6f412de

2 files changed

Lines changed: 25 additions & 6 deletions

File tree

memcache/fakeserver_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (c *testConn) reply(msg string) bool {
7171
}
7272

7373
var (
74-
writeRx = regexp.MustCompile(`^(set|add|replace|append|prepend|cas) (\S+) (\d+) (\d+) (\d+)( \S+)?( noreply)?\r\n`)
74+
writeRx = regexp.MustCompile(`^(set|add|replace|append|prepend|cas) (\S+) (\d+) (\d+) (\d+)(?: (\S+))?( noreply)?\r\n`)
7575
deleteRx = regexp.MustCompile(`^delete (\S+)( noreply)?\r\n`)
7676
incrDecrRx = regexp.MustCompile(`^(incr|decr) (\S+) (\d+)( noreply)?\r\n`)
7777
touchRx = regexp.MustCompile(`^touch (\S+) (\d+)( noreply)?\r\n`)
@@ -148,7 +148,6 @@ func (c *testConn) handleRequestLine(line string) bool {
148148
exptimeVal, _ := strconv.ParseInt(exptimeStr, 10, 64)
149149
itemLen, _ := strconv.ParseInt(lenStr, 10, 32)
150150
//log.Printf("got %q flags=%q exp=%d %d len=%d cas=%q noreply=%q", verb, key, flags, exptimeVal, itemLen, casUniq, noReply)
151-
_ = casUniq // TODO
152151
if c.s.m == nil {
153152
c.s.m = make(map[string]serverItem)
154153
}
@@ -200,7 +199,11 @@ func (c *testConn) handleRequestLine(line string) bool {
200199
if !ok {
201200
reply("NOT_FOUND")
202201
}
203-
return false
202+
if casUniq != fmt.Sprint(was.casUniq) {
203+
return reply("EXISTS")
204+
}
205+
c.s.m[key] = newItem
206+
return reply("STORED")
204207
case "append":
205208
if !ok {
206209
return reply("NOT_STORED")

memcache/memcache_test.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,36 @@ func testWithClient(t *testing.T, c *Client) {
9999
mustSet := mustSetF(t, c)
100100

101101
// Set
102-
foo := &Item{Key: "foo", Value: []byte("fooval"), Flags: 123}
102+
foo := &Item{Key: "foo", Value: []byte("fooval-fromset"), Flags: 123}
103103
err := c.Set(foo)
104104
checkErr(err, "first set(foo): %v", err)
105105
err = c.Set(foo)
106106
checkErr(err, "second set(foo): %v", err)
107107

108-
// Get
108+
// CompareAndSwap
109109
it, err := c.Get("foo")
110110
checkErr(err, "get(foo): %v", err)
111+
if string(it.Value) != "fooval-fromset" {
112+
t.Errorf("get(foo) Value = %q, want fooval-romset", it.Value)
113+
}
114+
it0, err := c.Get("foo") // another get, to fail our CAS later
115+
checkErr(err, "get(foo): %v", err)
116+
it.Value = []byte("fooval")
117+
err = c.CompareAndSwap(it)
118+
checkErr(err, "cas(foo): %v", err)
119+
it0.Value = []byte("should-fail")
120+
if err := c.CompareAndSwap(it0); err != ErrCASConflict {
121+
t.Fatalf("cas(foo) error = %v; want ErrCASConflict", err)
122+
}
123+
124+
// Get
125+
it, err = c.Get("foo")
126+
checkErr(err, "get(foo): %v", err)
111127
if it.Key != "foo" {
112128
t.Errorf("get(foo) Key = %q, want foo", it.Key)
113129
}
114130
if string(it.Value) != "fooval" {
115-
t.Errorf("get(foo) Value = %q, want fooval", string(it.Value))
131+
t.Errorf("get(foo) Value = %q, want fooval", it.Value)
116132
}
117133
if it.Flags != 123 {
118134
t.Errorf("get(foo) Flags = %v, want 123", it.Flags)

0 commit comments

Comments
 (0)