github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/storage/database_bootstrapped_test.go (about) 1 // Copyright (c) 2019 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package storage 22 23 import ( 24 "testing" 25 "time" 26 27 xtest "github.com/m3db/m3/src/x/test" 28 xtime "github.com/m3db/m3/src/x/time" 29 "github.com/stretchr/testify/assert" 30 ) 31 32 func TestDatabaseIsBootstrappedAndDurable(t *testing.T) { 33 ctrl := xtest.NewController(t) 34 defer ctrl.Finish() 35 36 var ( 37 validIsBootstrapped = true 38 validShardSetAssignedAt = xtime.Now() 39 validLastBootstrapCompletionTime = validShardSetAssignedAt.Add(time.Second) 40 validLastSuccessfulSnapshotStartTime = validLastBootstrapCompletionTime.Add(time.Second) 41 zeroTime xtime.UnixNano 42 ) 43 testCases := []struct { 44 title string 45 isBootstrapped bool 46 lastBootstrapCompletionTime xtime.UnixNano 47 lastSuccessfulSnapshotStartTime xtime.UnixNano 48 shardSetAssignedAt xtime.UnixNano 49 expectedResult bool 50 }{ 51 { 52 title: "False is not bootstrapped", 53 isBootstrapped: false, 54 lastBootstrapCompletionTime: validLastBootstrapCompletionTime, 55 lastSuccessfulSnapshotStartTime: validLastSuccessfulSnapshotStartTime, 56 shardSetAssignedAt: validShardSetAssignedAt, 57 expectedResult: false, 58 }, 59 { 60 title: "False if no last bootstrap completion time", 61 isBootstrapped: validIsBootstrapped, 62 lastBootstrapCompletionTime: zeroTime, 63 lastSuccessfulSnapshotStartTime: validLastSuccessfulSnapshotStartTime, 64 shardSetAssignedAt: validShardSetAssignedAt, 65 expectedResult: false, 66 }, 67 { 68 title: "False if no last successful snapshot start time", 69 isBootstrapped: validIsBootstrapped, 70 lastBootstrapCompletionTime: validLastBootstrapCompletionTime, 71 lastSuccessfulSnapshotStartTime: zeroTime, 72 shardSetAssignedAt: validShardSetAssignedAt, 73 expectedResult: false, 74 }, 75 { 76 title: "False if last snapshot start is not after last bootstrap completion time", 77 isBootstrapped: validIsBootstrapped, 78 lastBootstrapCompletionTime: validLastBootstrapCompletionTime, 79 lastSuccessfulSnapshotStartTime: validLastBootstrapCompletionTime, 80 shardSetAssignedAt: validShardSetAssignedAt, 81 expectedResult: false, 82 }, 83 { 84 title: "False if last bootstrap completion time is not after shardset assigned at time", 85 isBootstrapped: validIsBootstrapped, 86 lastBootstrapCompletionTime: validLastBootstrapCompletionTime, 87 lastSuccessfulSnapshotStartTime: validLastBootstrapCompletionTime, 88 shardSetAssignedAt: validLastBootstrapCompletionTime, 89 expectedResult: false, 90 }, 91 { 92 title: "False if last bootstrap completion time is not after/equal shardset assigned at time", 93 isBootstrapped: validIsBootstrapped, 94 lastBootstrapCompletionTime: validLastBootstrapCompletionTime, 95 lastSuccessfulSnapshotStartTime: validLastSuccessfulSnapshotStartTime, 96 shardSetAssignedAt: validLastBootstrapCompletionTime + xtime.UnixNano(xtime.Second), 97 expectedResult: false, 98 }, 99 { 100 title: "True if all conditions are met", 101 isBootstrapped: validIsBootstrapped, 102 lastBootstrapCompletionTime: validLastBootstrapCompletionTime, 103 lastSuccessfulSnapshotStartTime: validLastSuccessfulSnapshotStartTime, 104 shardSetAssignedAt: validShardSetAssignedAt, 105 expectedResult: true, 106 }, 107 } 108 109 for _, tc := range testCases { 110 t.Run(tc.title, func(t *testing.T) { 111 d, mapCh, _ := defaultTestDatabase(t, ctrl, Bootstrapped) 112 defer func() { 113 close(mapCh) 114 }() 115 116 mediator := NewMockdatabaseMediator(ctrl) 117 d.mediator = mediator 118 d.lastReceivedNewShards = tc.shardSetAssignedAt.ToTime() 119 120 mediator.EXPECT().IsBootstrapped().Return(tc.isBootstrapped) 121 if !tc.isBootstrapped { 122 assert.Equal(t, tc.expectedResult, d.IsBootstrappedAndDurable()) 123 // Early return because other mock calls will not get called. 124 return 125 } 126 127 if tc.lastBootstrapCompletionTime == 0 { 128 mediator.EXPECT().LastBootstrapCompletionTime().Return(zeroTime, false) 129 assert.Equal(t, tc.expectedResult, d.IsBootstrappedAndDurable()) 130 // Early return because other mock calls will not get called. 131 return 132 } 133 134 mediator.EXPECT().LastBootstrapCompletionTime().Return(tc.lastBootstrapCompletionTime, true) 135 136 if tc.lastSuccessfulSnapshotStartTime == 0 { 137 mediator.EXPECT().LastSuccessfulSnapshotStartTime().Return(zeroTime, false) 138 assert.Equal(t, tc.expectedResult, d.IsBootstrappedAndDurable()) 139 // Early return because other mock calls will not get called. 140 return 141 } 142 143 mediator.EXPECT().LastSuccessfulSnapshotStartTime().Return(tc.lastSuccessfulSnapshotStartTime, true) 144 145 assert.Equal(t, tc.expectedResult, d.IsBootstrappedAndDurable()) 146 }) 147 } 148 }