...

Source file src/go.etcd.io/etcd/raft/v3/tracker/progress_test.go

Documentation: go.etcd.io/etcd/raft/v3/tracker

     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 tracker
    16  
    17  import (
    18  	"testing"
    19  )
    20  
    21  func TestProgressString(t *testing.T) {
    22  	ins := NewInflights(1)
    23  	ins.Add(123)
    24  	pr := &Progress{
    25  		Match:           1,
    26  		Next:            2,
    27  		State:           StateSnapshot,
    28  		PendingSnapshot: 123,
    29  		RecentActive:    false,
    30  		ProbeSent:       true,
    31  		IsLearner:       true,
    32  		Inflights:       ins,
    33  	}
    34  	const exp = `StateSnapshot match=1 next=2 learner paused pendingSnap=123 inactive inflight=1[full]`
    35  	if act := pr.String(); act != exp {
    36  		t.Errorf("exp: %s\nact: %s", exp, act)
    37  	}
    38  }
    39  
    40  func TestProgressIsPaused(t *testing.T) {
    41  	tests := []struct {
    42  		state  StateType
    43  		paused bool
    44  
    45  		w bool
    46  	}{
    47  		{StateProbe, false, false},
    48  		{StateProbe, true, true},
    49  		{StateReplicate, false, false},
    50  		{StateReplicate, true, false},
    51  		{StateSnapshot, false, true},
    52  		{StateSnapshot, true, true},
    53  	}
    54  	for i, tt := range tests {
    55  		p := &Progress{
    56  			State:     tt.state,
    57  			ProbeSent: tt.paused,
    58  			Inflights: NewInflights(256),
    59  		}
    60  		if g := p.IsPaused(); g != tt.w {
    61  			t.Errorf("#%d: paused= %t, want %t", i, g, tt.w)
    62  		}
    63  	}
    64  }
    65  
    66  // TestProgressResume ensures that MaybeUpdate and MaybeDecrTo will reset
    67  // ProbeSent.
    68  func TestProgressResume(t *testing.T) {
    69  	p := &Progress{
    70  		Next:      2,
    71  		ProbeSent: true,
    72  	}
    73  	p.MaybeDecrTo(1, 1)
    74  	if p.ProbeSent {
    75  		t.Errorf("paused= %v, want false", p.ProbeSent)
    76  	}
    77  	p.ProbeSent = true
    78  	p.MaybeUpdate(2)
    79  	if p.ProbeSent {
    80  		t.Errorf("paused= %v, want false", p.ProbeSent)
    81  	}
    82  }
    83  
    84  func TestProgressBecomeProbe(t *testing.T) {
    85  	match := uint64(1)
    86  	tests := []struct {
    87  		p     *Progress
    88  		wnext uint64
    89  	}{
    90  		{
    91  			&Progress{State: StateReplicate, Match: match, Next: 5, Inflights: NewInflights(256)},
    92  			2,
    93  		},
    94  		{
    95  			// snapshot finish
    96  			&Progress{State: StateSnapshot, Match: match, Next: 5, PendingSnapshot: 10, Inflights: NewInflights(256)},
    97  			11,
    98  		},
    99  		{
   100  			// snapshot failure
   101  			&Progress{State: StateSnapshot, Match: match, Next: 5, PendingSnapshot: 0, Inflights: NewInflights(256)},
   102  			2,
   103  		},
   104  	}
   105  	for i, tt := range tests {
   106  		tt.p.BecomeProbe()
   107  		if tt.p.State != StateProbe {
   108  			t.Errorf("#%d: state = %s, want %s", i, tt.p.State, StateProbe)
   109  		}
   110  		if tt.p.Match != match {
   111  			t.Errorf("#%d: match = %d, want %d", i, tt.p.Match, match)
   112  		}
   113  		if tt.p.Next != tt.wnext {
   114  			t.Errorf("#%d: next = %d, want %d", i, tt.p.Next, tt.wnext)
   115  		}
   116  	}
   117  }
   118  
   119  func TestProgressBecomeReplicate(t *testing.T) {
   120  	p := &Progress{State: StateProbe, Match: 1, Next: 5, Inflights: NewInflights(256)}
   121  	p.BecomeReplicate()
   122  
   123  	if p.State != StateReplicate {
   124  		t.Errorf("state = %s, want %s", p.State, StateReplicate)
   125  	}
   126  	if p.Match != 1 {
   127  		t.Errorf("match = %d, want 1", p.Match)
   128  	}
   129  	if w := p.Match + 1; p.Next != w {
   130  		t.Errorf("next = %d, want %d", p.Next, w)
   131  	}
   132  }
   133  
   134  func TestProgressBecomeSnapshot(t *testing.T) {
   135  	p := &Progress{State: StateProbe, Match: 1, Next: 5, Inflights: NewInflights(256)}
   136  	p.BecomeSnapshot(10)
   137  
   138  	if p.State != StateSnapshot {
   139  		t.Errorf("state = %s, want %s", p.State, StateSnapshot)
   140  	}
   141  	if p.Match != 1 {
   142  		t.Errorf("match = %d, want 1", p.Match)
   143  	}
   144  	if p.PendingSnapshot != 10 {
   145  		t.Errorf("pendingSnapshot = %d, want 10", p.PendingSnapshot)
   146  	}
   147  }
   148  
   149  func TestProgressUpdate(t *testing.T) {
   150  	prevM, prevN := uint64(3), uint64(5)
   151  	tests := []struct {
   152  		update uint64
   153  
   154  		wm  uint64
   155  		wn  uint64
   156  		wok bool
   157  	}{
   158  		{prevM - 1, prevM, prevN, false},        // do not decrease match, next
   159  		{prevM, prevM, prevN, false},            // do not decrease next
   160  		{prevM + 1, prevM + 1, prevN, true},     // increase match, do not decrease next
   161  		{prevM + 2, prevM + 2, prevN + 1, true}, // increase match, next
   162  	}
   163  	for i, tt := range tests {
   164  		p := &Progress{
   165  			Match: prevM,
   166  			Next:  prevN,
   167  		}
   168  		ok := p.MaybeUpdate(tt.update)
   169  		if ok != tt.wok {
   170  			t.Errorf("#%d: ok= %v, want %v", i, ok, tt.wok)
   171  		}
   172  		if p.Match != tt.wm {
   173  			t.Errorf("#%d: match= %d, want %d", i, p.Match, tt.wm)
   174  		}
   175  		if p.Next != tt.wn {
   176  			t.Errorf("#%d: next= %d, want %d", i, p.Next, tt.wn)
   177  		}
   178  	}
   179  }
   180  
   181  func TestProgressMaybeDecr(t *testing.T) {
   182  	tests := []struct {
   183  		state    StateType
   184  		m        uint64
   185  		n        uint64
   186  		rejected uint64
   187  		last     uint64
   188  
   189  		w  bool
   190  		wn uint64
   191  	}{
   192  		{
   193  			// state replicate and rejected is not greater than match
   194  			StateReplicate, 5, 10, 5, 5, false, 10,
   195  		},
   196  		{
   197  			// state replicate and rejected is not greater than match
   198  			StateReplicate, 5, 10, 4, 4, false, 10,
   199  		},
   200  		{
   201  			// state replicate and rejected is greater than match
   202  			// directly decrease to match+1
   203  			StateReplicate, 5, 10, 9, 9, true, 6,
   204  		},
   205  		{
   206  			// next-1 != rejected is always false
   207  			StateProbe, 0, 0, 0, 0, false, 0,
   208  		},
   209  		{
   210  			// next-1 != rejected is always false
   211  			StateProbe, 0, 10, 5, 5, false, 10,
   212  		},
   213  		{
   214  			// next>1 = decremented by 1
   215  			StateProbe, 0, 10, 9, 9, true, 9,
   216  		},
   217  		{
   218  			// next>1 = decremented by 1
   219  			StateProbe, 0, 2, 1, 1, true, 1,
   220  		},
   221  		{
   222  			// next<=1 = reset to 1
   223  			StateProbe, 0, 1, 0, 0, true, 1,
   224  		},
   225  		{
   226  			// decrease to min(rejected, last+1)
   227  			StateProbe, 0, 10, 9, 2, true, 3,
   228  		},
   229  		{
   230  			// rejected < 1, reset to 1
   231  			StateProbe, 0, 10, 9, 0, true, 1,
   232  		},
   233  	}
   234  	for i, tt := range tests {
   235  		p := &Progress{
   236  			State: tt.state,
   237  			Match: tt.m,
   238  			Next:  tt.n,
   239  		}
   240  		if g := p.MaybeDecrTo(tt.rejected, tt.last); g != tt.w {
   241  			t.Errorf("#%d: maybeDecrTo= %t, want %t", i, g, tt.w)
   242  		}
   243  		if gm := p.Match; gm != tt.m {
   244  			t.Errorf("#%d: match= %d, want %d", i, gm, tt.m)
   245  		}
   246  		if gn := p.Next; gn != tt.wn {
   247  			t.Errorf("#%d: next= %d, want %d", i, gn, tt.wn)
   248  		}
   249  	}
   250  }
   251  

View as plain text