1package raft
2
3import (
4	"bytes"
5	"io"
6	"reflect"
7	"testing"
8)
9
10func TestInmemSnapshotStoreImpl(t *testing.T) {
11	var impl interface{} = &InmemSnapshotStore{}
12	if _, ok := impl.(SnapshotStore); !ok {
13		t.Fatalf("InmemSnapshotStore not a SnapshotStore")
14	}
15}
16
17func TestInmemSnapshotSinkImpl(t *testing.T) {
18	var impl interface{} = &InmemSnapshotSink{}
19	if _, ok := impl.(SnapshotSink); !ok {
20		t.Fatalf("InmemSnapshotSink not a SnapshotSink")
21	}
22}
23
24func TestInmemSS_CreateSnapshot(t *testing.T) {
25	snap := NewInmemSnapshotStore()
26
27	// Check no snapshots
28	snaps, err := snap.List()
29	if err != nil {
30		t.Fatalf("err: %v", err)
31	}
32	if len(snaps) != 0 {
33		t.Fatalf("did not expect any snapshots: %v", snaps)
34	}
35
36	// Create a new sink
37	var configuration Configuration
38	configuration.Servers = append(configuration.Servers, Server{
39		Suffrage: Voter,
40		ID:       ServerID("my id"),
41		Address:  ServerAddress("over here"),
42	})
43	_, trans := NewInmemTransport(NewInmemAddr())
44	sink, err := snap.Create(SnapshotVersionMax, 10, 3, configuration, 2, trans)
45	if err != nil {
46		t.Fatalf("err: %v", err)
47	}
48
49	// The sink is not done, should not be in a list!
50	snaps, err = snap.List()
51	if err != nil {
52		t.Fatalf("err: %v", err)
53	}
54	if len(snaps) != 1 {
55		t.Fatalf("should always be 1 snapshot: %v", snaps)
56	}
57
58	// Write to the sink
59	_, err = sink.Write([]byte("first\n"))
60	if err != nil {
61		t.Fatalf("err: %v", err)
62	}
63	_, err = sink.Write([]byte("second\n"))
64	if err != nil {
65		t.Fatalf("err: %v", err)
66	}
67
68	// Done!
69	err = sink.Close()
70	if err != nil {
71		t.Fatalf("err: %v", err)
72	}
73
74	// Should have a snapshot!
75	snaps, err = snap.List()
76	if err != nil {
77		t.Fatalf("err: %v", err)
78	}
79	if len(snaps) != 1 {
80		t.Fatalf("expect a snapshots: %v", snaps)
81	}
82
83	// Check the latest
84	latest := snaps[0]
85	if latest.Index != 10 {
86		t.Fatalf("bad snapshot: %v", *latest)
87	}
88	if latest.Term != 3 {
89		t.Fatalf("bad snapshot: %v", *latest)
90	}
91	if !reflect.DeepEqual(latest.Configuration, configuration) {
92		t.Fatalf("bad snapshot: %v", *latest)
93	}
94	if latest.ConfigurationIndex != 2 {
95		t.Fatalf("bad snapshot: %v", *latest)
96	}
97	if latest.Size != 13 {
98		t.Fatalf("bad snapshot: %v", *latest)
99	}
100
101	// Read the snapshot
102	_, r, err := snap.Open(latest.ID)
103	if err != nil {
104		t.Fatalf("err: %v", err)
105	}
106
107	// Read out everything
108	var buf bytes.Buffer
109	if _, err := io.Copy(&buf, r); err != nil {
110		t.Fatalf("err: %v", err)
111	}
112	if err := r.Close(); err != nil {
113		t.Fatalf("err: %v", err)
114	}
115
116	// Ensure a match
117	if bytes.Compare(buf.Bytes(), []byte("first\nsecond\n")) != 0 {
118		t.Fatalf("content mismatch")
119	}
120}
121
122func TestInmemSS_OpenSnapshotTwice(t *testing.T) {
123	snap := NewInmemSnapshotStore()
124
125	// Create a new sink
126	var configuration Configuration
127	configuration.Servers = append(configuration.Servers, Server{
128		Suffrage: Voter,
129		ID:       ServerID("my id"),
130		Address:  ServerAddress("over here"),
131	})
132	_, trans := NewInmemTransport(NewInmemAddr())
133	sink, err := snap.Create(SnapshotVersionMax, 10, 3, configuration, 2, trans)
134	if err != nil {
135		t.Fatalf("err: %v", err)
136	}
137
138	// Write to the sink
139	_, err = sink.Write([]byte("data\n"))
140	if err != nil {
141		t.Fatalf("err: %v", err)
142	}
143	err = sink.Close()
144	if err != nil {
145		t.Fatalf("err: %v", err)
146	}
147
148	// Read the snapshot a first time
149	_, r, err := snap.Open(sink.ID())
150	if err != nil {
151		t.Fatalf("err: %v", err)
152	}
153
154	// Read out everything
155	var buf1 bytes.Buffer
156	if _, err = io.Copy(&buf1, r); err != nil {
157		t.Fatalf("err: %v", err)
158	}
159	if err = r.Close(); err != nil {
160		t.Fatalf("err: %v", err)
161	}
162
163	// Ensure a match
164	if bytes.Compare(buf1.Bytes(), []byte("data\n")) != 0 {
165		t.Fatalf("content mismatch")
166	}
167
168	// Read the snapshot a second time.
169	_, r, err = snap.Open(sink.ID())
170	if err != nil {
171		t.Fatalf("err: %v", err)
172	}
173
174	// Read out everything again
175	var buf2 bytes.Buffer
176	if _, err := io.Copy(&buf2, r); err != nil {
177		t.Fatalf("err: %v", err)
178	}
179	if err := r.Close(); err != nil {
180		t.Fatalf("err: %v", err)
181	}
182
183	// Ensure it's still the same content
184	if bytes.Compare(buf2.Bytes(), []byte("data\n")) != 0 {
185		t.Fatalf("content mismatch")
186	}
187}
188