1package api 2 3import ( 4 "bytes" 5 "strings" 6 "testing" 7) 8 9func TestAPI_Snapshot(t *testing.T) { 10 t.Parallel() 11 c, s := makeClient(t) 12 defer s.Stop() 13 14 s.WaitForSerfCheck(t) 15 // Place an initial key into the store. 16 kv := c.KV() 17 key := &KVPair{Key: testKey(), Value: []byte("hello")} 18 if _, err := kv.Put(key, nil); err != nil { 19 t.Fatalf("err: %v", err) 20 } 21 22 // Make sure it reads back. 23 pair, _, err := kv.Get(key.Key, nil) 24 if err != nil { 25 t.Fatalf("err: %v", err) 26 } 27 if pair == nil { 28 t.Fatalf("expected value: %#v", pair) 29 } 30 if !bytes.Equal(pair.Value, []byte("hello")) { 31 t.Fatalf("unexpected value: %#v", pair) 32 } 33 34 // Take a snapshot. 35 snapshot := c.Snapshot() 36 snap, qm, err := snapshot.Save(nil) 37 if err != nil { 38 t.Fatalf("err: %v", err) 39 } 40 defer snap.Close() 41 42 // Sanity check th query metadata. 43 if qm.LastIndex == 0 || !qm.KnownLeader || 44 qm.RequestTime == 0 { 45 t.Fatalf("bad: %v", qm) 46 } 47 48 // Overwrite the key's value. 49 key.Value = []byte("goodbye") 50 if _, err := kv.Put(key, nil); err != nil { 51 t.Fatalf("err: %v", err) 52 } 53 54 // Read the key back and look for the new value. 55 pair, _, err = kv.Get(key.Key, nil) 56 if err != nil { 57 t.Fatalf("err: %v", err) 58 } 59 if pair == nil { 60 t.Fatalf("expected value: %#v", pair) 61 } 62 if !bytes.Equal(pair.Value, []byte("goodbye")) { 63 t.Fatalf("unexpected value: %#v", pair) 64 } 65 66 // Restore the snapshot. 67 if err := snapshot.Restore(nil, snap); err != nil { 68 t.Fatalf("err: %v", err) 69 } 70 71 // Read the key back and look for the original value. 72 pair, _, err = kv.Get(key.Key, nil) 73 if err != nil { 74 t.Fatalf("err: %v", err) 75 } 76 if pair == nil { 77 t.Fatalf("expected value: %#v", pair) 78 } 79 if !bytes.Equal(pair.Value, []byte("hello")) { 80 t.Fatalf("unexpected value: %#v", pair) 81 } 82} 83 84func TestAPI_Snapshot_Options(t *testing.T) { 85 t.Parallel() 86 c, s := makeACLClient(t) 87 defer s.Stop() 88 89 // Try to take a snapshot with a bad token. 90 snapshot := c.Snapshot() 91 _, _, err := snapshot.Save(&QueryOptions{Token: "anonymous"}) 92 if err == nil || !strings.Contains(err.Error(), "Permission denied") { 93 t.Fatalf("err: %v", err) 94 } 95 96 // Now try an unknown DC. 97 _, _, err = snapshot.Save(&QueryOptions{Datacenter: "nope"}) 98 if err == nil || !strings.Contains(err.Error(), "No path to datacenter") { 99 t.Fatalf("err: %v", err) 100 } 101 102 // This should work with a valid token. 103 snap, _, err := snapshot.Save(&QueryOptions{Token: "root"}) 104 if err != nil { 105 t.Fatalf("err: %v", err) 106 } 107 defer snap.Close() 108 109 // This should work with a stale snapshot. This doesn't have good feedback 110 // that the stale option was sent, but it makes sure nothing bad happens. 111 snap, _, err = snapshot.Save(&QueryOptions{Token: "root", AllowStale: true}) 112 if err != nil { 113 t.Fatalf("err: %v", err) 114 } 115 defer snap.Close() 116 117 // Try to restore a snapshot with a bad token. 118 null := bytes.NewReader([]byte("")) 119 err = snapshot.Restore(&WriteOptions{Token: "anonymous"}, null) 120 if err == nil || !strings.Contains(err.Error(), "Permission denied") { 121 t.Fatalf("err: %v", err) 122 } 123 124 // Now try an unknown DC. 125 null = bytes.NewReader([]byte("")) 126 err = snapshot.Restore(&WriteOptions{Datacenter: "nope"}, null) 127 if err == nil || !strings.Contains(err.Error(), "No path to datacenter") { 128 t.Fatalf("err: %v", err) 129 } 130 131 // This should work. 132 if err := snapshot.Restore(&WriteOptions{Token: "root"}, snap); err != nil { 133 t.Fatalf("err: %v", err) 134 } 135} 136