go.etcd.io/etcd@v3.3.27+incompatible/raft/storage_test.go (about)

     1  // Copyright 2015 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package raft
    16  
    17  import (
    18  	"math"
    19  	"reflect"
    20  	"testing"
    21  
    22  	pb "github.com/coreos/etcd/raft/raftpb"
    23  )
    24  
    25  func TestStorageTerm(t *testing.T) {
    26  	ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
    27  	tests := []struct {
    28  		i uint64
    29  
    30  		werr   error
    31  		wterm  uint64
    32  		wpanic bool
    33  	}{
    34  		{2, ErrCompacted, 0, false},
    35  		{3, nil, 3, false},
    36  		{4, nil, 4, false},
    37  		{5, nil, 5, false},
    38  		{6, ErrUnavailable, 0, false},
    39  	}
    40  
    41  	for i, tt := range tests {
    42  		s := &MemoryStorage{ents: ents}
    43  
    44  		func() {
    45  			defer func() {
    46  				if r := recover(); r != nil {
    47  					if !tt.wpanic {
    48  						t.Errorf("%d: panic = %v, want %v", i, true, tt.wpanic)
    49  					}
    50  				}
    51  			}()
    52  
    53  			term, err := s.Term(tt.i)
    54  			if err != tt.werr {
    55  				t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
    56  			}
    57  			if term != tt.wterm {
    58  				t.Errorf("#%d: term = %d, want %d", i, term, tt.wterm)
    59  			}
    60  		}()
    61  	}
    62  }
    63  
    64  func TestStorageEntries(t *testing.T) {
    65  	ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 6}}
    66  	tests := []struct {
    67  		lo, hi, maxsize uint64
    68  
    69  		werr     error
    70  		wentries []pb.Entry
    71  	}{
    72  		{2, 6, math.MaxUint64, ErrCompacted, nil},
    73  		{3, 4, math.MaxUint64, ErrCompacted, nil},
    74  		{4, 5, math.MaxUint64, nil, []pb.Entry{{Index: 4, Term: 4}}},
    75  		{4, 6, math.MaxUint64, nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}},
    76  		{4, 7, math.MaxUint64, nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 6}}},
    77  		// even if maxsize is zero, the first entry should be returned
    78  		{4, 7, 0, nil, []pb.Entry{{Index: 4, Term: 4}}},
    79  		// limit to 2
    80  		{4, 7, uint64(ents[1].Size() + ents[2].Size()), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}},
    81  		// limit to 2
    82  		{4, 7, uint64(ents[1].Size() + ents[2].Size() + ents[3].Size()/2), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}},
    83  		{4, 7, uint64(ents[1].Size() + ents[2].Size() + ents[3].Size() - 1), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}}},
    84  		// all
    85  		{4, 7, uint64(ents[1].Size() + ents[2].Size() + ents[3].Size()), nil, []pb.Entry{{Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 6}}},
    86  	}
    87  
    88  	for i, tt := range tests {
    89  		s := &MemoryStorage{ents: ents}
    90  		entries, err := s.Entries(tt.lo, tt.hi, tt.maxsize)
    91  		if err != tt.werr {
    92  			t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
    93  		}
    94  		if !reflect.DeepEqual(entries, tt.wentries) {
    95  			t.Errorf("#%d: entries = %v, want %v", i, entries, tt.wentries)
    96  		}
    97  	}
    98  }
    99  
   100  func TestStorageLastIndex(t *testing.T) {
   101  	ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
   102  	s := &MemoryStorage{ents: ents}
   103  
   104  	last, err := s.LastIndex()
   105  	if err != nil {
   106  		t.Errorf("err = %v, want nil", err)
   107  	}
   108  	if last != 5 {
   109  		t.Errorf("term = %d, want %d", last, 5)
   110  	}
   111  
   112  	s.Append([]pb.Entry{{Index: 6, Term: 5}})
   113  	last, err = s.LastIndex()
   114  	if err != nil {
   115  		t.Errorf("err = %v, want nil", err)
   116  	}
   117  	if last != 6 {
   118  		t.Errorf("last = %d, want %d", last, 5)
   119  	}
   120  }
   121  
   122  func TestStorageFirstIndex(t *testing.T) {
   123  	ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
   124  	s := &MemoryStorage{ents: ents}
   125  
   126  	first, err := s.FirstIndex()
   127  	if err != nil {
   128  		t.Errorf("err = %v, want nil", err)
   129  	}
   130  	if first != 4 {
   131  		t.Errorf("first = %d, want %d", first, 4)
   132  	}
   133  
   134  	s.Compact(4)
   135  	first, err = s.FirstIndex()
   136  	if err != nil {
   137  		t.Errorf("err = %v, want nil", err)
   138  	}
   139  	if first != 5 {
   140  		t.Errorf("first = %d, want %d", first, 5)
   141  	}
   142  }
   143  
   144  func TestStorageCompact(t *testing.T) {
   145  	ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
   146  	tests := []struct {
   147  		i uint64
   148  
   149  		werr   error
   150  		windex uint64
   151  		wterm  uint64
   152  		wlen   int
   153  	}{
   154  		{2, ErrCompacted, 3, 3, 3},
   155  		{3, ErrCompacted, 3, 3, 3},
   156  		{4, nil, 4, 4, 2},
   157  		{5, nil, 5, 5, 1},
   158  	}
   159  
   160  	for i, tt := range tests {
   161  		s := &MemoryStorage{ents: ents}
   162  		err := s.Compact(tt.i)
   163  		if err != tt.werr {
   164  			t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
   165  		}
   166  		if s.ents[0].Index != tt.windex {
   167  			t.Errorf("#%d: index = %d, want %d", i, s.ents[0].Index, tt.windex)
   168  		}
   169  		if s.ents[0].Term != tt.wterm {
   170  			t.Errorf("#%d: term = %d, want %d", i, s.ents[0].Term, tt.wterm)
   171  		}
   172  		if len(s.ents) != tt.wlen {
   173  			t.Errorf("#%d: len = %d, want %d", i, len(s.ents), tt.wlen)
   174  		}
   175  	}
   176  }
   177  
   178  func TestStorageCreateSnapshot(t *testing.T) {
   179  	ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
   180  	cs := &pb.ConfState{Nodes: []uint64{1, 2, 3}}
   181  	data := []byte("data")
   182  
   183  	tests := []struct {
   184  		i uint64
   185  
   186  		werr  error
   187  		wsnap pb.Snapshot
   188  	}{
   189  		{4, nil, pb.Snapshot{Data: data, Metadata: pb.SnapshotMetadata{Index: 4, Term: 4, ConfState: *cs}}},
   190  		{5, nil, pb.Snapshot{Data: data, Metadata: pb.SnapshotMetadata{Index: 5, Term: 5, ConfState: *cs}}},
   191  	}
   192  
   193  	for i, tt := range tests {
   194  		s := &MemoryStorage{ents: ents}
   195  		snap, err := s.CreateSnapshot(tt.i, cs, data)
   196  		if err != tt.werr {
   197  			t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
   198  		}
   199  		if !reflect.DeepEqual(snap, tt.wsnap) {
   200  			t.Errorf("#%d: snap = %+v, want %+v", i, snap, tt.wsnap)
   201  		}
   202  	}
   203  }
   204  
   205  func TestStorageAppend(t *testing.T) {
   206  	ents := []pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}}
   207  	tests := []struct {
   208  		entries []pb.Entry
   209  
   210  		werr     error
   211  		wentries []pb.Entry
   212  	}{
   213  		{
   214  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}},
   215  			nil,
   216  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}},
   217  		},
   218  		{
   219  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 6}, {Index: 5, Term: 6}},
   220  			nil,
   221  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 6}, {Index: 5, Term: 6}},
   222  		},
   223  		{
   224  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}},
   225  			nil,
   226  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}},
   227  		},
   228  		// truncate incoming entries, truncate the existing entries and append
   229  		{
   230  			[]pb.Entry{{Index: 2, Term: 3}, {Index: 3, Term: 3}, {Index: 4, Term: 5}},
   231  			nil,
   232  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 5}},
   233  		},
   234  		// truncate the existing entries and append
   235  		{
   236  			[]pb.Entry{{Index: 4, Term: 5}},
   237  			nil,
   238  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 5}},
   239  		},
   240  		// direct append
   241  		{
   242  			[]pb.Entry{{Index: 6, Term: 5}},
   243  			nil,
   244  			[]pb.Entry{{Index: 3, Term: 3}, {Index: 4, Term: 4}, {Index: 5, Term: 5}, {Index: 6, Term: 5}},
   245  		},
   246  	}
   247  
   248  	for i, tt := range tests {
   249  		s := &MemoryStorage{ents: ents}
   250  		err := s.Append(tt.entries)
   251  		if err != tt.werr {
   252  			t.Errorf("#%d: err = %v, want %v", i, err, tt.werr)
   253  		}
   254  		if !reflect.DeepEqual(s.ents, tt.wentries) {
   255  			t.Errorf("#%d: entries = %v, want %v", i, s.ents, tt.wentries)
   256  		}
   257  	}
   258  }
   259  
   260  func TestStorageApplySnapshot(t *testing.T) {
   261  	cs := &pb.ConfState{Nodes: []uint64{1, 2, 3}}
   262  	data := []byte("data")
   263  
   264  	tests := []pb.Snapshot{{Data: data, Metadata: pb.SnapshotMetadata{Index: 4, Term: 4, ConfState: *cs}},
   265  		{Data: data, Metadata: pb.SnapshotMetadata{Index: 3, Term: 3, ConfState: *cs}},
   266  	}
   267  
   268  	s := NewMemoryStorage()
   269  
   270  	//Apply Snapshot successful
   271  	i := 0
   272  	tt := tests[i]
   273  	err := s.ApplySnapshot(tt)
   274  	if err != nil {
   275  		t.Errorf("#%d: err = %v, want %v", i, err, nil)
   276  	}
   277  
   278  	//Apply Snapshot fails due to ErrSnapOutOfDate
   279  	i = 1
   280  	tt = tests[i]
   281  	err = s.ApplySnapshot(tt)
   282  	if err != ErrSnapOutOfDate {
   283  		t.Errorf("#%d: err = %v, want %v", i, err, ErrSnapOutOfDate)
   284  	}
   285  }