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