@@ -18,6 +18,66 @@ import (
1818 "github.com/stretchr/testify/require"
1919)
2020
21+ func TestTouchXattrWithCas (t * testing.T ) {
22+ ctx := t .Context ()
23+ ensureNoLeakedFeeds (t )
24+ coll := makeTestBucket (t ).DefaultDataStore (ctx ).(* Collection )
25+
26+ const docID = "doc1"
27+ bodyBytes := []byte (`{"hello":"world"}` )
28+ xattrsInput := map [string ][]byte {
29+ syncXattrName : []byte (`{"existing":"value"}` ),
30+ }
31+ originalCas , err := coll .WriteWithXattrs (ctx , docID , 0 , 0 , bodyBytes , xattrsInput , nil , nil )
32+ require .NoError (t , err )
33+
34+ // Stale CAS should fail.
35+ _ , err = coll .TouchXattrWithCas (ctx , docID , syncXattrName , "name" , "db1" , originalCas + 1 )
36+ require .ErrorAs (t , err , & sgbucket.CasMismatchErr {})
37+
38+ // Correct CAS succeeds and bumps CAS.
39+ newCas , err := coll .TouchXattrWithCas (ctx , docID , syncXattrName , "name" , "db1" , originalCas )
40+ require .NoError (t , err )
41+ require .NotEqual (t , originalCas , newCas )
42+
43+ // Verify the xattr property is now visible and the existing properties were preserved.
44+ gotBody , gotXattrs , getCas , err := coll .GetWithXattrs (ctx , docID , []string {syncXattrName })
45+ require .NoError (t , err )
46+ require .Equal (t , newCas , getCas )
47+ require .Equal (t , bodyBytes , gotBody )
48+ var xattr map [string ]string
49+ require .NoError (t , json .Unmarshal (gotXattrs [syncXattrName ], & xattr ))
50+ require .Equal (t , "db1" , xattr ["name" ])
51+ require .Equal (t , "value" , xattr ["existing" ])
52+
53+ // The old CAS is now stale.
54+ _ , err = coll .TouchXattrWithCas (ctx , docID , syncXattrName , "name" , "db2" , originalCas )
55+ require .ErrorAs (t , err , & sgbucket.CasMismatchErr {})
56+ }
57+
58+ // TestTouchXattrWithCasCreatesXattr verifies that TouchXattrWithCas can populate an xattr on a doc
59+ // that does not yet have one.
60+ func TestTouchXattrWithCasCreatesXattr (t * testing.T ) {
61+ ctx := t .Context ()
62+ ensureNoLeakedFeeds (t )
63+ coll := makeTestBucket (t ).DefaultDataStore (ctx ).(* Collection )
64+
65+ const docID = "doc1"
66+ require .NoError (t , coll .SetRaw (ctx , docID , 0 , nil , []byte (`{"a":1}` )))
67+ _ , cas , err := coll .GetRaw (ctx , docID )
68+ require .NoError (t , err )
69+
70+ newCas , err := coll .TouchXattrWithCas (ctx , docID , syncXattrName , "name" , "db1" , cas )
71+ require .NoError (t , err )
72+ require .NotEqual (t , cas , newCas )
73+
74+ _ , gotXattrs , _ , err := coll .GetWithXattrs (ctx , docID , []string {syncXattrName })
75+ require .NoError (t , err )
76+ var xattr map [string ]string
77+ require .NoError (t , json .Unmarshal (gotXattrs [syncXattrName ], & xattr ))
78+ require .Equal (t , "db1" , xattr ["name" ])
79+ }
80+
2181func TestSetXattrs (t * testing.T ) {
2282 ctx := t .Context ()
2383 ensureNoLeakedFeeds (t )
0 commit comments