github.com/m3db/m3@v1.5.0/src/cluster/kv/mem/store_test.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package mem 22 23 import ( 24 "sync" 25 "testing" 26 27 "github.com/m3db/m3/src/cluster/generated/proto/kvtest" 28 "github.com/m3db/m3/src/cluster/kv" 29 30 "github.com/stretchr/testify/require" 31 ) 32 33 func TestValue(t *testing.T) { 34 v1 := NewValue(1, &kvtest.Foo{ 35 Msg: "1", 36 }) 37 38 v2 := NewValue(2, &kvtest.Foo{ 39 Msg: "2", 40 }) 41 42 require.True(t, v2.IsNewer(v1)) 43 } 44 45 func TestStore(t *testing.T) { 46 s := NewStore() 47 48 // Should start without a value 49 val, err := s.Get("foo") 50 require.Equal(t, kv.ErrNotFound, err) 51 require.Nil(t, val) 52 53 // Should be able to set to non-existent value 54 version, err := s.SetIfNotExists("foo", &kvtest.Foo{ 55 Msg: "first", 56 }) 57 require.NoError(t, err) 58 require.Equal(t, 1, version) 59 60 // And have that value stored 61 val, err = s.Get("foo") 62 require.NoError(t, err) 63 require.NotNil(t, val) 64 require.Equal(t, 1, val.Version()) 65 66 var read kvtest.Foo 67 require.NoError(t, val.Unmarshal(&read)) 68 require.Equal(t, "first", read.Msg) 69 70 // Should not be able to SetIfNotExists to that value again 71 _, err = s.SetIfNotExists("foo", &kvtest.Foo{ 72 Msg: "update", 73 }) 74 require.Equal(t, kv.ErrAlreadyExists, err) 75 76 read.Reset() 77 val, err = s.Get("foo") 78 require.NoError(t, err) 79 require.NotNil(t, val) 80 require.Equal(t, 1, val.Version()) 81 require.NoError(t, val.Unmarshal(&read)) 82 require.Equal(t, "first", read.Msg) 83 84 // Should be able to Set unconditionally and get a new version 85 version2, err := s.Set("foo", &kvtest.Foo{ 86 Msg: "update", 87 }) 88 require.NoError(t, err) 89 require.Equal(t, 2, version2) 90 91 read.Reset() 92 val, err = s.Get("foo") 93 require.NoError(t, err) 94 require.Equal(t, 2, val.Version()) 95 require.NoError(t, val.Unmarshal(&read)) 96 require.Equal(t, "update", read.Msg) 97 98 // Should not be able to set at an old version 99 _, err = s.CheckAndSet("foo", version, &kvtest.Foo{ 100 Msg: "update2", 101 }) 102 require.Equal(t, kv.ErrVersionMismatch, err) 103 104 read.Reset() 105 val, err = s.Get("foo") 106 require.NoError(t, err) 107 require.NotNil(t, val) 108 require.Equal(t, 2, val.Version()) 109 require.NoError(t, val.Unmarshal(&read)) 110 require.Equal(t, "update", read.Msg) 111 112 // Should be able to set at the specific version 113 version3, err := s.CheckAndSet("foo", val.Version(), &kvtest.Foo{ 114 Msg: "update3", 115 }) 116 require.NoError(t, err) 117 require.Equal(t, 3, version3) 118 119 read.Reset() 120 val, err = s.Get("foo") 121 require.NoError(t, err) 122 require.NotNil(t, val) 123 require.Equal(t, 3, val.Version()) 124 require.NoError(t, val.Unmarshal(&read)) 125 require.Equal(t, "update3", read.Msg) 126 } 127 128 func TestStoreWatch(t *testing.T) { 129 s := NewStore() 130 131 fooWatch1, err := s.Watch("foo") 132 require.NoError(t, err) 133 require.NotNil(t, fooWatch1) 134 require.Nil(t, fooWatch1.Get()) 135 136 version, err := s.SetIfNotExists("foo", &kvtest.Foo{ 137 Msg: "first", 138 }) 139 require.NoError(t, err) 140 require.Equal(t, 1, version) 141 142 <-fooWatch1.C() 143 var foo kvtest.Foo 144 require.NoError(t, fooWatch1.Get().Unmarshal(&foo)) 145 require.Equal(t, "first", foo.Msg) 146 147 fooWatch2, err := s.Watch("foo") 148 require.NoError(t, err) 149 <-fooWatch2.C() 150 require.NoError(t, fooWatch2.Get().Unmarshal(&foo)) 151 require.Equal(t, "first", foo.Msg) 152 153 var wg sync.WaitGroup 154 wg.Add(2) 155 156 go func() { 157 defer wg.Done() 158 <-fooWatch1.C() 159 var foo kvtest.Foo 160 require.NoError(t, fooWatch1.Get().Unmarshal(&foo)) 161 require.Equal(t, "second", foo.Msg) 162 }() 163 164 go func() { 165 defer wg.Done() 166 <-fooWatch2.C() 167 var foo kvtest.Foo 168 require.NoError(t, fooWatch2.Get().Unmarshal(&foo)) 169 require.Equal(t, "second", foo.Msg) 170 }() 171 172 version, err = s.Set("foo", &kvtest.Foo{ 173 Msg: "second", 174 }) 175 require.NoError(t, err) 176 require.Equal(t, 2, version) 177 wg.Wait() 178 179 fooWatch1.Close() 180 version, err = s.Set("foo", &kvtest.Foo{ 181 Msg: "third", 182 }) 183 require.NoError(t, err) 184 require.Equal(t, 3, version) 185 require.NoError(t, fooWatch2.Get().Unmarshal(&foo)) 186 require.Equal(t, "third", foo.Msg) 187 } 188 189 func TestFakeStoreErrors(t *testing.T) { 190 s := NewStore() 191 192 _, err := s.Set("foo", nil) 193 require.Error(t, err) 194 195 _, err = s.SetIfNotExists("foo", nil) 196 require.Error(t, err) 197 198 _, err = s.CheckAndSet("foo", 1, nil) 199 require.Error(t, err) 200 201 _, err = s.History("foo", -5, 0) 202 require.Error(t, err) 203 204 _, err = s.History("foo", 0, 10) 205 require.Error(t, err) 206 207 _, err = s.History("foo", 20, 10) 208 require.Error(t, err) 209 } 210 211 func TestHistory(t *testing.T) { 212 s := NewStore() 213 214 for i := 1; i <= 10; i++ { 215 _, err := s.Set("foo", &kvtest.Foo{ 216 Msg: "bar1", 217 }) 218 require.NoError(t, err) 219 } 220 221 vals, err := s.History("foo", 3, 7) 222 require.NoError(t, err) 223 require.Equal(t, 4, len(vals)) 224 for i := 0; i < len(vals); i++ { 225 require.Equal(t, i+3, vals[i].Version()) 226 } 227 228 vals, err = s.History("foo", 3, 3) 229 require.NoError(t, err) 230 require.Equal(t, 0, len(vals)) 231 232 vals, err = s.History("foo", 13, 17) 233 require.NoError(t, err) 234 require.Equal(t, 0, len(vals)) 235 } 236 237 func TestDelete(t *testing.T) { 238 s := NewStore() 239 240 _, err := s.Delete("foo") 241 require.Error(t, err) 242 require.Equal(t, kv.ErrNotFound, err) 243 244 s.Set("foo", &kvtest.Foo{ 245 Msg: "bar1", 246 }) 247 248 w, err := s.Watch("foo") 249 require.NoError(t, err) 250 251 <-w.C() 252 require.Equal(t, 1, w.Get().Version()) 253 254 s.Set("foo", &kvtest.Foo{ 255 Msg: "bar2", 256 }) 257 <-w.C() 258 v := w.Get() 259 require.Equal(t, 2, v.Version()) 260 val, err := s.Delete("foo") 261 require.NoError(t, err) 262 require.Equal(t, 2, val.Version()) 263 264 var read kvtest.Foo 265 require.NoError(t, val.Unmarshal(&read)) 266 require.Equal(t, "bar2", read.Msg) 267 268 <-w.C() 269 require.Nil(t, w.Get()) 270 271 _, err = s.Get("foo") 272 require.Error(t, err) 273 require.Equal(t, kv.ErrNotFound, err) 274 275 s.Set("foo", &kvtest.Foo{ 276 Msg: "after_delete_bar1", 277 }) 278 279 <-w.C() 280 newValue := w.Get() 281 require.Equal(t, 1, newValue.Version()) 282 require.True(t, newValue.IsNewer(v)) 283 } 284 285 func TestTxn(t *testing.T) { 286 store := NewStore() 287 288 r, err := store.Commit( 289 []kv.Condition{ 290 kv.NewCondition(). 291 SetCompareType(kv.CompareEqual). 292 SetTargetType(kv.TargetVersion). 293 SetKey("foo"). 294 SetValue(0), 295 kv.NewCondition(). 296 SetCompareType(kv.CompareEqual). 297 SetTargetType(kv.TargetVersion). 298 SetKey("key"). 299 SetValue(0), 300 }, 301 []kv.Op{ 302 kv.NewSetOp("key", &kvtest.Foo{Msg: "1"}), 303 kv.NewSetOp("foo", &kvtest.Foo{Msg: "1"}), 304 }, 305 ) 306 require.NoError(t, err) 307 require.Equal(t, 2, len(r.Responses())) 308 require.Equal(t, "key", r.Responses()[0].Key()) 309 require.Equal(t, kv.OpSet, r.Responses()[0].Type()) 310 require.Equal(t, 1, r.Responses()[0].Value()) 311 require.Equal(t, "foo", r.Responses()[1].Key()) 312 require.Equal(t, kv.OpSet, r.Responses()[1].Type()) 313 require.Equal(t, 1, r.Responses()[1].Value()) 314 315 _, err = store.Commit( 316 []kv.Condition{ 317 kv.NewCondition(). 318 SetCompareType(kv.CompareEqual). 319 SetTargetType(kv.TargetVersion). 320 SetKey("foo"). 321 SetValue(1), 322 kv.NewCondition(). 323 SetCompareType(kv.CompareEqual). 324 SetTargetType(kv.TargetVersion). 325 SetKey("key"). 326 SetValue(0), 327 }, 328 []kv.Op{ 329 kv.NewSetOp("key", &kvtest.Foo{Msg: "1"}), 330 kv.NewSetOp("foo", &kvtest.Foo{Msg: "1"}), 331 }, 332 ) 333 require.Error(t, err) 334 require.Equal(t, kv.ErrConditionCheckFailed, err) 335 }