Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 1 | package fs_test |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 2 | |
| 3 | import ( |
| 4 | "fmt" |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 5 | "io/ioutil" |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 6 | "os" |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 7 | "reflect" |
| 8 | "testing" |
| 9 | |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 10 | "veyron.io/veyron/veyron/services/mgmt/lib/fs" |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 11 | _ "veyron.io/veyron/veyron/services/mgmt/profile" |
| 12 | "veyron.io/veyron/veyron2/naming" |
| 13 | "veyron.io/veyron/veyron2/services/mgmt/application" |
| 14 | "veyron.io/veyron/veyron2/verror" |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 15 | ) |
| 16 | |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 17 | func tempFile(t *testing.T) string { |
| 18 | tmpfile, err := ioutil.TempFile("", "simplestore-test-") |
| 19 | if err != nil { |
| 20 | t.Fatalf("ioutil.TempFile() failed: %v", err) |
| 21 | } |
| 22 | defer tmpfile.Close() |
| 23 | return tmpfile.Name() |
| 24 | } |
| 25 | |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 26 | func TestNewMemstore(t *testing.T) { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 27 | memstore, err := fs.NewMemstore("") |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 28 | |
| 29 | if err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 30 | t.Fatalf("fs.NewMemstore() failed: %v", err) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 31 | } |
| 32 | |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 33 | if _, err = os.Stat(memstore.PersistedFile()); err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 34 | t.Fatalf("Stat(%v) failed: %v", memstore.PersistedFile(), err) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 35 | } |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 36 | os.Remove(memstore.PersistedFile()) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 37 | } |
| 38 | |
| 39 | func TestNewNamedMemstore(t *testing.T) { |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 40 | path := tempFile(t) |
| 41 | defer os.Remove(path) |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 42 | memstore, err := fs.NewMemstore(path) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 43 | if err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 44 | t.Fatalf("fs.NewMemstore() failed: %v", err) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 45 | } |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 46 | |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 47 | if _, err = os.Stat(memstore.PersistedFile()); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 48 | t.Fatalf("Stat(%v) failed: %v", path, err) |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | // Verify that all of the listed paths Exists(). |
| 53 | // Caller is responsible for setting up any transaction state necessary. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 54 | func allPathsExist(ts *fs.Memstore, paths []string) error { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 55 | for _, p := range paths { |
| 56 | exists, err := ts.BindObject(p).Exists(nil) |
| 57 | if err != nil { |
| 58 | return fmt.Errorf("Exists(%s) expected to succeed but failed: %v", p, err) |
| 59 | } |
| 60 | if !exists { |
| 61 | return fmt.Errorf("Exists(%s) expected to be true but is false", p) |
| 62 | } |
| 63 | } |
| 64 | return nil |
| 65 | } |
| 66 | |
| 67 | // Verify that all of the listed paths !Exists(). |
| 68 | // Caller is responsible for setting up any transaction state necessary. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 69 | func allPathsDontExist(ts *fs.Memstore, paths []string) error { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 70 | for _, p := range paths { |
| 71 | exists, err := ts.BindObject(p).Exists(nil) |
| 72 | if err != nil { |
| 73 | return fmt.Errorf("Exists(%s) expected to succeed but failed: %v", p, err) |
| 74 | } |
| 75 | if exists { |
| 76 | return fmt.Errorf("Exists(%s) expected to be false but is true", p) |
| 77 | } |
| 78 | } |
| 79 | return nil |
| 80 | } |
| 81 | |
| 82 | type PathValue struct { |
| 83 | Path string |
| 84 | Expected interface{} |
| 85 | } |
| 86 | |
| 87 | // getEquals tests that every provided path is equal to the specified value. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 88 | func allPathsEqual(ts *fs.Memstore, pvs []PathValue) error { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 89 | for _, p := range pvs { |
| 90 | v, err := ts.BindObject(p.Path).Get(nil) |
| 91 | if err != nil { |
| 92 | return fmt.Errorf("Get(%s) expected to succeed but failed", p, err) |
| 93 | } |
| 94 | if !reflect.DeepEqual(p.Expected, v.Value) { |
| 95 | return fmt.Errorf("Unexpected non-equality for %s: got %v, expected %v", p.Path, v.Value, p.Expected) |
| 96 | } |
| 97 | } |
| 98 | return nil |
| 99 | } |
| 100 | |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 101 | func TestSerializeDeserialize(t *testing.T) { |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 102 | path := tempFile(t) |
| 103 | defer os.Remove(path) |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 104 | memstoreOriginal, err := fs.NewMemstore(path) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 105 | if err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 106 | t.Fatalf("fs.NewMemstore() failed: %v", err) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 107 | } |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 108 | |
| 109 | // Create example data. |
| 110 | envelope := application.Envelope{ |
| 111 | Args: []string{"--help"}, |
| 112 | Env: []string{"DEBUG=1"}, |
| 113 | Binary: "/veyron/name/of/binary", |
| 114 | } |
| 115 | secondEnvelope := application.Envelope{ |
| 116 | Args: []string{"--save"}, |
| 117 | Env: []string{"VEYRON=42"}, |
| 118 | Binary: "/veyron/name/of/binary/is/memstored", |
| 119 | } |
| 120 | |
| 121 | // TRANSACTION BEGIN |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 122 | // Insert a value into the fs.Memstore at /test/a |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 123 | memstoreOriginal.Lock() |
| 124 | tname, err := memstoreOriginal.BindTransactionRoot("ignored").CreateTransaction(nil) |
| 125 | if err != nil { |
| 126 | t.Fatalf("CreateTransaction() failed: %v", err) |
| 127 | } |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 128 | if _, err := memstoreOriginal.BindObject(fs.TP("/test/a")).Put(nil, envelope); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 129 | t.Fatalf("Put() failed: %v", err) |
| 130 | } |
| 131 | |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 132 | if err := allPathsExist(memstoreOriginal, []string{fs.TP("/test/a"), fs.TP("/test")}); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 133 | t.Fatalf("%v", err) |
| 134 | } |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 135 | if err := allPathsEqual(memstoreOriginal, []PathValue{{fs.TP("/test/a"), envelope}}); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 136 | t.Fatalf("%v", err) |
| 137 | } |
| 138 | |
| 139 | if err := memstoreOriginal.BindTransaction(tname).Commit(nil); err != nil { |
| 140 | t.Fatalf("Commit() failed: %v", err) |
| 141 | } |
| 142 | memstoreOriginal.Unlock() |
| 143 | // TRANSACTION END |
| 144 | |
| 145 | // Validate persisted state. |
| 146 | if err := allPathsExist(memstoreOriginal, []string{"/test/a", "/test"}); err != nil { |
| 147 | t.Fatalf("%v", err) |
| 148 | } |
| 149 | if err := allPathsEqual(memstoreOriginal, []PathValue{{"/test/a", envelope}}); err != nil { |
| 150 | t.Fatalf("%v", err) |
| 151 | } |
| 152 | |
| 153 | // TRANSACTION BEGIN Write a value to /test/b as well. |
| 154 | memstoreOriginal.Lock() |
| 155 | tname, err = memstoreOriginal.BindTransactionRoot("also ignored").CreateTransaction(nil) |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 156 | bindingTnameTestB := memstoreOriginal.BindObject(fs.TP("/test/b")) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 157 | if _, err := bindingTnameTestB.Put(nil, envelope); err != nil { |
| 158 | t.Fatalf("Put() failed: %v", err) |
| 159 | } |
| 160 | |
| 161 | // Validate persisted state during transaction |
| 162 | if err := allPathsExist(memstoreOriginal, []string{"/test/a", "/test"}); err != nil { |
| 163 | t.Fatalf("%v", err) |
| 164 | } |
| 165 | if err := allPathsEqual(memstoreOriginal, []PathValue{{"/test/a", envelope}}); err != nil { |
| 166 | t.Fatalf("%v", err) |
| 167 | } |
| 168 | // Validate pending state during transaction |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 169 | if err := allPathsExist(memstoreOriginal, []string{fs.TP("/test/a"), fs.TP("/test"), fs.TP("/test/b")}); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 170 | t.Fatalf("%v", err) |
| 171 | } |
| 172 | if err := allPathsEqual(memstoreOriginal, []PathValue{ |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 173 | {fs.TP("/test/a"), envelope}, |
| 174 | {fs.TP("/test/b"), envelope}}); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 175 | t.Fatalf("%v", err) |
| 176 | } |
| 177 | |
| 178 | // Commit the <tname>/test/b to /test/b |
| 179 | if err := memstoreOriginal.Commit(nil); err != nil { |
| 180 | t.Fatalf("Commit() failed: %v", err) |
| 181 | } |
| 182 | memstoreOriginal.Unlock() |
| 183 | // TODO(rjkroege): Consider ensuring that Get() on <tname>/test/b should now fail. |
| 184 | // TRANSACTION END |
| 185 | |
| 186 | // Validate persisted state after transaction |
| 187 | if err := allPathsExist(memstoreOriginal, []string{"/test/a", "/test", "/test/b"}); err != nil { |
| 188 | t.Fatalf("%v", err) |
| 189 | } |
| 190 | if err := allPathsEqual(memstoreOriginal, []PathValue{ |
| 191 | {"/test/a", envelope}, |
| 192 | {"/test/b", envelope}}); err != nil { |
| 193 | t.Fatalf("%v", err) |
| 194 | } |
| 195 | |
| 196 | // TRANSACTION BEGIN (to be abandonned) |
| 197 | memstoreOriginal.Lock() |
| 198 | tname, err = memstoreOriginal.BindTransactionRoot("").CreateTransaction(nil) |
| 199 | |
| 200 | // Exists is true before doing anything. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 201 | if err := allPathsExist(memstoreOriginal, []string{fs.TP("/test")}); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 202 | t.Fatalf("%v", err) |
| 203 | } |
| 204 | |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 205 | if _, err := memstoreOriginal.BindObject(fs.TP("/test/b")).Put(nil, secondEnvelope); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 206 | t.Fatalf("Put() failed: %v", err) |
| 207 | } |
| 208 | |
| 209 | // Validate persisted state during transaction |
| 210 | if err := allPathsExist(memstoreOriginal, []string{ |
| 211 | "/test/a", |
| 212 | "/test/b", |
| 213 | "/test", |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 214 | fs.TP("/test"), |
| 215 | fs.TP("/test/a"), |
| 216 | fs.TP("/test/b"), |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 217 | }); err != nil { |
| 218 | t.Fatalf("%v", err) |
| 219 | } |
| 220 | if err := allPathsEqual(memstoreOriginal, []PathValue{ |
| 221 | {"/test/a", envelope}, |
| 222 | {"/test/b", envelope}, |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 223 | {fs.TP("/test/b"), secondEnvelope}, |
| 224 | {fs.TP("/test/a"), envelope}, |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 225 | }); err != nil { |
| 226 | t.Fatalf("%v", err) |
| 227 | } |
| 228 | |
| 229 | // Pending Remove() of /test |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 230 | if err := memstoreOriginal.BindObject(fs.TP("/test")).Remove(nil); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 231 | t.Fatalf("Remove() failed: %v", err) |
| 232 | } |
| 233 | |
| 234 | // Verify that all paths are successfully removed from the in-progress transaction. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 235 | if err := allPathsDontExist(memstoreOriginal, []string{fs.TP("/test/a"), fs.TP("/test"), fs.TP("/test/b")}); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 236 | t.Fatalf("%v", err) |
| 237 | } |
| 238 | // But all paths remain in the persisted version. |
| 239 | if err := allPathsExist(memstoreOriginal, []string{"/test/a", "/test", "/test/b"}); err != nil { |
| 240 | t.Fatalf("%v", err) |
| 241 | } |
| 242 | if err := allPathsEqual(memstoreOriginal, []PathValue{ |
| 243 | {"/test/a", envelope}, |
| 244 | {"/test/b", envelope}, |
| 245 | }); err != nil { |
| 246 | t.Fatalf("%v", err) |
| 247 | } |
| 248 | |
| 249 | // At which point, Get() on the transaction won't find anything. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 250 | if _, err := memstoreOriginal.BindObject(fs.TP("/test/a")).Get(nil); !verror.Is(err, verror.NoExist) { |
Tilak Sharma | 492e8e9 | 2014-09-18 10:58:14 -0700 | [diff] [blame] | 251 | t.Fatalf("Get() should have failed: got %v, expected %v", err, verror.NoExistf("path %s not in Memstore", tname+"/test/a")) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | // Attempting to Remove() it over again will fail. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 255 | if err := memstoreOriginal.BindObject(fs.TP("/test/a")).Remove(nil); !verror.Is(err, verror.NoExist) { |
Tilak Sharma | 492e8e9 | 2014-09-18 10:58:14 -0700 | [diff] [blame] | 256 | t.Fatalf("Remove() should have failed: got %v, expected %v", err, verror.NoExistf("path %s not in Memstore", tname+"/test/a")) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | // Attempting to Remove() a non-existing path will fail. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 260 | if err := memstoreOriginal.BindObject(fs.TP("/foo")).Remove(nil); !verror.Is(err, verror.NoExist) { |
Tilak Sharma | 492e8e9 | 2014-09-18 10:58:14 -0700 | [diff] [blame] | 261 | t.Fatalf("Remove() should have failed: got %v, expected %v", err, verror.NoExistf("path %s not in Memstore", tname+"/foo")) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 262 | } |
| 263 | |
| 264 | // Exists() a non-existing path will fail. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 265 | if present, _ := memstoreOriginal.BindObject(fs.TP("/foo")).Exists(nil); present { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 266 | t.Fatalf("Exists() should have failed for non-existing path %s", tname+"/foo") |
| 267 | } |
| 268 | |
| 269 | // Abort the transaction without committing it. |
| 270 | memstoreOriginal.Abort(nil) |
| 271 | memstoreOriginal.Unlock() |
| 272 | // TRANSACTION END (ABORTED) |
| 273 | |
| 274 | // Validate that persisted state after abandonned transaction has not changed. |
| 275 | if err := allPathsExist(memstoreOriginal, []string{"/test/a", "/test", "/test/b"}); err != nil { |
| 276 | t.Fatalf("%v", err) |
| 277 | } |
| 278 | if err := allPathsEqual(memstoreOriginal, []PathValue{ |
| 279 | {"/test/a", envelope}, |
| 280 | {"/test/b", envelope}}); err != nil { |
| 281 | t.Fatalf("%v", err) |
| 282 | } |
| 283 | |
| 284 | // Validate that Get will fail on a non-existent path. |
Tilak Sharma | 492e8e9 | 2014-09-18 10:58:14 -0700 | [diff] [blame] | 285 | if _, err := memstoreOriginal.BindObject("/test/c").Get(nil); !verror.Is(err, verror.NoExist) { |
| 286 | t.Fatalf("Get() should have failed: got %v, expected %v", err, verror.NoExistf("path %s not in Memstore", tname+"/test/c")) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 287 | } |
| 288 | |
| 289 | // Verify that the previous Commit() operations have persisted to |
| 290 | // disk by creating a new Memstore from the contents on disk. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 291 | memstoreCopy, err := fs.NewMemstore(path) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 292 | if err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 293 | t.Fatalf("fs.NewMemstore() failed: %v", err) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 294 | } |
| 295 | // Verify that memstoreCopy is an exact copy of memstoreOriginal. |
| 296 | if err := allPathsExist(memstoreCopy, []string{"/test/a", "/test", "/test/b"}); err != nil { |
| 297 | t.Fatalf("%v", err) |
| 298 | } |
| 299 | if err := allPathsEqual(memstoreCopy, []PathValue{ |
| 300 | {"/test/a", envelope}, |
| 301 | {"/test/b", envelope}}); err != nil { |
| 302 | t.Fatalf("%v", err) |
| 303 | } |
| 304 | |
| 305 | // TRANSACTION BEGIN |
| 306 | memstoreCopy.Lock() |
| 307 | tname, err = memstoreCopy.BindTransactionRoot("also ignored").CreateTransaction(nil) |
| 308 | |
| 309 | // Add a pending object c to test that pending objects are deleted. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 310 | if _, err := memstoreCopy.BindObject(fs.TP("/test/c")).Put(nil, secondEnvelope); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 311 | t.Fatalf("Put() failed: %v", err) |
| 312 | } |
| 313 | if err := allPathsExist(memstoreCopy, []string{ |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 314 | fs.TP("/test/a"), |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 315 | "/test/a", |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 316 | fs.TP("/test"), |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 317 | "/test", |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 318 | fs.TP("/test/b"), |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 319 | "/test/b", |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 320 | fs.TP("/test/c"), |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 321 | }); err != nil { |
| 322 | t.Fatalf("%v", err) |
| 323 | } |
| 324 | if err := allPathsEqual(memstoreCopy, []PathValue{ |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 325 | {fs.TP("/test/a"), envelope}, |
| 326 | {fs.TP("/test/b"), envelope}, |
| 327 | {fs.TP("/test/c"), secondEnvelope}, |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 328 | {"/test/a", envelope}, |
| 329 | {"/test/b", envelope}, |
| 330 | }); err != nil { |
| 331 | t.Fatalf("%v", err) |
| 332 | } |
| 333 | |
| 334 | // Remove /test/a /test/b /test/c /test |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 335 | if err := memstoreCopy.BindObject(fs.TP("/test")).Remove(nil); err != nil { |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 336 | t.Fatalf("Remove() failed: %v", err) |
| 337 | } |
| 338 | // Verify that all paths are successfully removed from the in-progress transaction. |
| 339 | if err := allPathsDontExist(memstoreCopy, []string{ |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 340 | fs.TP("/test/a"), |
| 341 | fs.TP("/test"), |
| 342 | fs.TP("/test/b"), |
| 343 | fs.TP("/test/c"), |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 344 | }); err != nil { |
| 345 | t.Fatalf("%v", err) |
| 346 | } |
| 347 | if err := allPathsExist(memstoreCopy, []string{ |
| 348 | "/test/a", |
| 349 | "/test", |
| 350 | "/test/b", |
| 351 | }); err != nil { |
| 352 | t.Fatalf("%v", err) |
| 353 | } |
| 354 | // Commit the change. |
| 355 | if err = memstoreCopy.Commit(nil); err != nil { |
| 356 | t.Fatalf("Commit() failed: %v", err) |
| 357 | } |
| 358 | memstoreCopy.Unlock() |
| 359 | // TRANSACTION END |
| 360 | |
| 361 | // Create a new Memstore from file to see if Remove operates are |
| 362 | // persisted. |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 363 | memstoreRemovedCopy, err := fs.NewMemstore(path) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 364 | if err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 365 | t.Fatalf("fs.NewMemstore() failed for removed copy: %v", err) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 366 | } |
| 367 | if err := allPathsDontExist(memstoreRemovedCopy, []string{ |
| 368 | "/test/a", |
| 369 | "/test", |
| 370 | "/test/b", |
| 371 | "/test/c", |
| 372 | }); err != nil { |
| 373 | t.Fatalf("%v", err) |
| 374 | } |
| 375 | } |
| 376 | |
| 377 | func TestOperationsNeedValidBinding(t *testing.T) { |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 378 | path := tempFile(t) |
| 379 | defer os.Remove(path) |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 380 | memstoreOriginal, err := fs.NewMemstore(path) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 381 | if err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 382 | t.Fatalf("fs.NewMemstore() failed: %v", err) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 383 | } |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 384 | |
| 385 | // Create example data. |
| 386 | envelope := application.Envelope{ |
| 387 | Args: []string{"--help"}, |
| 388 | Env: []string{"DEBUG=1"}, |
| 389 | Binary: "/veyron/name/of/binary", |
| 390 | } |
| 391 | |
| 392 | // TRANSACTION BEGIN |
| 393 | // Attempt inserting a value at /test/a. |
| 394 | memstoreOriginal.Lock() |
| 395 | tname, err := memstoreOriginal.BindTransactionRoot("").CreateTransaction(nil) |
| 396 | if err != nil { |
| 397 | t.Fatalf("CreateTransaction() failed: %v", err) |
| 398 | } |
| 399 | |
| 400 | if err := memstoreOriginal.BindTransaction(tname).Commit(nil); err != nil { |
| 401 | t.Fatalf("Commit() failed: %v", err) |
| 402 | } |
| 403 | memstoreOriginal.Unlock() |
| 404 | // TRANSACTION END |
| 405 | |
| 406 | // Put outside ot a transaction should fail. |
| 407 | bindingTnameTestA := memstoreOriginal.BindObject(naming.Join("fooey", "/test/a")) |
| 408 | if _, err := bindingTnameTestA.Put(nil, envelope); !verror.Is(err, verror.BadProtocol) { |
| 409 | t.Fatalf("Put() failed: got %v, expected %v", err, verror.BadProtocolf("Put() without a transactional binding")) |
| 410 | } |
| 411 | |
| 412 | // Remove outside of a transaction should fail |
| 413 | if err := bindingTnameTestA.Remove(nil); !verror.Is(err, verror.BadProtocol) { |
| 414 | t.Fatalf("Put() failed: got %v, expected %v", err, verror.BadProtocolf("Remove() without a transactional binding")) |
| 415 | } |
| 416 | |
| 417 | // Commit outside of a transaction should fail |
| 418 | if err := memstoreOriginal.BindTransaction(tname).Commit(nil); !verror.Is(err, verror.BadProtocol) { |
| 419 | t.Fatalf("Commit() failed: got %v, expected %v", err, verror.BadProtocolf("illegal attempt to commit previously committed or abandonned transaction")) |
| 420 | } |
| 421 | |
| 422 | // Attempt inserting a value at /test/b |
| 423 | memstoreOriginal.Lock() |
| 424 | tname, err = memstoreOriginal.BindTransactionRoot("").CreateTransaction(nil) |
| 425 | if err != nil { |
| 426 | t.Fatalf("CreateTransaction() failed: %v", err) |
| 427 | } |
| 428 | |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 429 | bindingTnameTestB := memstoreOriginal.BindObject(fs.TP("/test/b")) |
Robert Kroeger | d9c3488 | 2014-08-22 11:16:38 -0700 | [diff] [blame] | 430 | if _, err := bindingTnameTestB.Put(nil, envelope); err != nil { |
| 431 | t.Fatalf("Put() failed: %v", err) |
| 432 | } |
| 433 | // Abandon transaction. |
| 434 | memstoreOriginal.Unlock() |
| 435 | |
| 436 | // Remove should definitely fail on an abndonned transaction. |
| 437 | if err := bindingTnameTestB.Remove(nil); !verror.Is(err, verror.BadProtocol) { |
| 438 | t.Fatalf("Remove() failed: got %v, expected %v", err, verror.Internalf("Remove() without a transactional binding")) |
| 439 | } |
| 440 | } |
Robert Kroeger | 5fec5cf | 2014-10-08 17:19:50 -0700 | [diff] [blame] | 441 | |
| 442 | func TestOpenEmptyMemstore(t *testing.T) { |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 443 | path := tempFile(t) |
Robert Kroeger | 5fec5cf | 2014-10-08 17:19:50 -0700 | [diff] [blame] | 444 | defer os.Remove(path) |
| 445 | |
| 446 | // Create a brand new memstore persisted to namedms. This will |
| 447 | // have the side-effect of creating an empty backing file. |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 448 | if _, err := fs.NewMemstore(path); err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 449 | t.Fatalf("fs.NewMemstore() failed: %v", err) |
Robert Kroeger | 5fec5cf | 2014-10-08 17:19:50 -0700 | [diff] [blame] | 450 | } |
| 451 | |
| 452 | // Create another memstore that will attempt to deserialize the empty |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 453 | // backing file. |
Robin Thellend | 4081a30 | 2014-12-08 17:38:56 -0800 | [diff] [blame] | 454 | if _, err := fs.NewMemstore(path); err != nil { |
Robert Kroeger | f903fe2 | 2014-10-20 14:37:28 -0700 | [diff] [blame] | 455 | t.Fatalf("fs.NewMemstore() failed: %v", err) |
Robert Kroeger | 5fec5cf | 2014-10-08 17:19:50 -0700 | [diff] [blame] | 456 | } |
| 457 | } |
Robin Thellend | 0155a37 | 2014-11-11 17:30:11 -0800 | [diff] [blame] | 458 | |
| 459 | func TestChildren(t *testing.T) { |
| 460 | memstore, err := fs.NewMemstore("") |
| 461 | if err != nil { |
| 462 | t.Fatalf("fs.NewMemstore() failed: %v", err) |
| 463 | } |
| 464 | defer os.Remove(memstore.PersistedFile()) |
| 465 | |
| 466 | // Create example data. |
| 467 | envelope := application.Envelope{ |
| 468 | Args: []string{"--help"}, |
| 469 | Env: []string{"DEBUG=1"}, |
| 470 | Binary: "/veyron/name/of/binary", |
| 471 | } |
| 472 | |
| 473 | // TRANSACTION BEGIN |
| 474 | memstore.Lock() |
| 475 | tname, err := memstore.BindTransactionRoot("ignored").CreateTransaction(nil) |
| 476 | if err != nil { |
| 477 | t.Fatalf("CreateTransaction() failed: %v", err) |
| 478 | } |
| 479 | // Insert a few values |
| 480 | names := []string{"/test/a", "/test/b", "/test/a/x", "/test/a/y", "/test/b/fooooo/bar"} |
| 481 | for _, n := range names { |
| 482 | if _, err := memstore.BindObject(fs.TP(n)).Put(nil, envelope); err != nil { |
| 483 | t.Fatalf("Put() failed: %v", err) |
| 484 | } |
| 485 | } |
| 486 | if err := memstore.BindTransaction(tname).Commit(nil); err != nil { |
| 487 | t.Fatalf("Commit() failed: %v", err) |
| 488 | } |
| 489 | memstore.Unlock() |
| 490 | // TRANSACTION END |
| 491 | |
| 492 | memstore.Lock() |
| 493 | testcases := []struct { |
| 494 | name string |
| 495 | children []string |
| 496 | }{ |
| 497 | {"/", []string{"test"}}, |
| 498 | {"/test", []string{"a", "b"}}, |
| 499 | {"/test/a", []string{"x", "y"}}, |
| 500 | {"/test/b", []string{"fooooo"}}, |
| 501 | {"/test/b/fooooo", []string{"bar"}}, |
| 502 | {"/test/a/x", []string{}}, |
| 503 | {"/test/a/y", []string{}}, |
| 504 | } |
| 505 | for _, tc := range testcases { |
| 506 | children, err := memstore.BindObject(tc.name).Children() |
| 507 | if err != nil { |
| 508 | t.Errorf("unexpected error for %q: %v", tc.name, err) |
| 509 | continue |
| 510 | } |
| 511 | if !reflect.DeepEqual(children, tc.children) { |
| 512 | t.Errorf("unexpected result for %q: got %q, expected %q", tc.name, children, tc.children) |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | for _, notthere := range []string{"/doesnt-exist", "/tes"} { |
| 517 | if _, err := memstore.BindObject(notthere).Children(); err == nil { |
| 518 | t.Errorf("unexpected success for: %q", notthere) |
| 519 | } |
| 520 | } |
| 521 | memstore.Unlock() |
| 522 | } |