| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- // Copyright 2015 CoreOS, Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package etcdserver
- import (
- "io"
- "reflect"
- "sync"
- "testing"
- "github.com/coreos/etcd/Godeps/_workspace/src/github.com/jonboulle/clockwork"
- "github.com/coreos/etcd/pkg/testutil"
- "github.com/coreos/etcd/raft"
- "github.com/coreos/etcd/raft/raftpb"
- dstorage "github.com/coreos/etcd/storage"
- "github.com/coreos/etcd/storage/storagepb"
- )
- func TestSnapshotStoreCreateSnap(t *testing.T) {
- snap := raftpb.Snapshot{
- Metadata: raftpb.SnapshotMetadata{Index: 1},
- }
- ss := newSnapshotStore("", &nopKV{})
- fakeClock := clockwork.NewFakeClock()
- ss.clock = fakeClock
- go func() {
- <-ss.reqsnapc
- ss.raftsnapc <- snap
- }()
- // create snapshot
- ss.createSnap()
- if !reflect.DeepEqual(ss.snap.raft(), snap) {
- t.Errorf("raftsnap = %+v, want %+v", ss.snap.raft(), snap)
- }
- // unused snapshot is cleared after clearUnusedSnapshotInterval
- fakeClock.BlockUntil(1)
- fakeClock.Advance(clearUnusedSnapshotInterval)
- testutil.WaitSchedule()
- ss.mu.Lock()
- if ss.snap != nil {
- t.Errorf("snap = %+v, want %+v", ss.snap, nil)
- }
- ss.mu.Unlock()
- }
- func TestSnapshotStoreGetSnap(t *testing.T) {
- snap := raftpb.Snapshot{
- Metadata: raftpb.SnapshotMetadata{Index: 1},
- }
- ss := newSnapshotStore("", &nopKV{})
- fakeClock := clockwork.NewFakeClock()
- ss.clock = fakeClock
- ss.tr = &nopTransporter{}
- go func() {
- <-ss.reqsnapc
- ss.raftsnapc <- snap
- }()
- // get snap when no snapshot stored
- _, err := ss.getSnap()
- if err != raft.ErrSnapshotTemporarilyUnavailable {
- t.Fatalf("getSnap error = %v, want %v", err, raft.ErrSnapshotTemporarilyUnavailable)
- }
- // wait for asynchronous snapshot creation to finish
- testutil.WaitSchedule()
- // get the created snapshot
- s, err := ss.getSnap()
- if err != nil {
- t.Fatalf("getSnap error = %v, want nil", err)
- }
- if !reflect.DeepEqual(s.raft(), snap) {
- t.Errorf("raftsnap = %+v, want %+v", s.raft(), snap)
- }
- if !ss.inUse {
- t.Errorf("inUse = %v, want true", ss.inUse)
- }
- // get snap when snapshot stored has been in use
- _, err = ss.getSnap()
- if err != raft.ErrSnapshotTemporarilyUnavailable {
- t.Fatalf("getSnap error = %v, want %v", err, raft.ErrSnapshotTemporarilyUnavailable)
- }
- // clean up
- fakeClock.Advance(clearUnusedSnapshotInterval)
- }
- func TestSnapshotStoreClearUsedSnap(t *testing.T) {
- s := &fakeSnapshot{}
- var once sync.Once
- once.Do(func() {})
- ss := &snapshotStore{
- snap: newSnapshot(raftpb.Snapshot{}, s),
- inUse: true,
- createOnce: once,
- }
- ss.clearUsedSnap()
- // wait for underlying KV snapshot closed
- testutil.WaitSchedule()
- s.mu.Lock()
- if !s.closed {
- t.Errorf("snapshot closed = %v, want true", s.closed)
- }
- s.mu.Unlock()
- if ss.snap != nil {
- t.Errorf("snapshot = %v, want nil", ss.snap)
- }
- if ss.inUse {
- t.Errorf("isUse = %v, want false", ss.inUse)
- }
- // test createOnce is reset
- if ss.createOnce == once {
- t.Errorf("createOnce fails to reset")
- }
- }
- func TestSnapshotStoreCloseSnapBefore(t *testing.T) {
- snapIndex := uint64(5)
- tests := []struct {
- index uint64
- wok bool
- }{
- {snapIndex - 2, false},
- {snapIndex - 1, false},
- {snapIndex, true},
- }
- for i, tt := range tests {
- rs := raftpb.Snapshot{
- Metadata: raftpb.SnapshotMetadata{Index: 5},
- }
- s := &fakeSnapshot{}
- ss := &snapshotStore{
- snap: newSnapshot(rs, s),
- }
- ok := ss.closeSnapBefore(tt.index)
- if ok != tt.wok {
- t.Errorf("#%d: closeSnapBefore = %v, want %v", i, ok, tt.wok)
- }
- if ok {
- // wait for underlying KV snapshot closed
- testutil.WaitSchedule()
- s.mu.Lock()
- if !s.closed {
- t.Errorf("#%d: snapshot closed = %v, want true", i, s.closed)
- }
- s.mu.Unlock()
- }
- }
- }
- type nopKV struct{}
- func (kv *nopKV) Rev() int64 { return 0 }
- func (kv *nopKV) Range(key, end []byte, limit, rangeRev int64) (kvs []storagepb.KeyValue, rev int64, err error) {
- return nil, 0, nil
- }
- func (kv *nopKV) Put(key, value []byte) (rev int64) { return 0 }
- func (kv *nopKV) DeleteRange(key, end []byte) (n, rev int64) { return 0, 0 }
- func (kv *nopKV) TxnBegin() int64 { return 0 }
- func (kv *nopKV) TxnEnd(txnID int64) error { return nil }
- func (kv *nopKV) TxnRange(txnID int64, key, end []byte, limit, rangeRev int64) (kvs []storagepb.KeyValue, rev int64, err error) {
- return nil, 0, nil
- }
- func (kv *nopKV) TxnPut(txnID int64, key, value []byte) (rev int64, err error) { return 0, nil }
- func (kv *nopKV) TxnDeleteRange(txnID int64, key, end []byte) (n, rev int64, err error) {
- return 0, 0, nil
- }
- func (kv *nopKV) Compact(rev int64) error { return nil }
- func (kv *nopKV) Hash() (uint32, error) { return 0, nil }
- func (kv *nopKV) Snapshot() dstorage.Snapshot { return &fakeSnapshot{} }
- func (kv *nopKV) Restore() error { return nil }
- func (kv *nopKV) Close() error { return nil }
- type fakeSnapshot struct {
- mu sync.Mutex
- closed bool
- }
- func (s *fakeSnapshot) Size() int64 { return 0 }
- func (s *fakeSnapshot) WriteTo(w io.Writer) (int64, error) { return 0, nil }
- func (s *fakeSnapshot) Close() error {
- s.mu.Lock()
- s.closed = true
- s.mu.Unlock()
- return nil
- }
|