github.com/m3db/m3@v1.5.0/src/dbnode/storage/bootstrap/bootstrapper/commitlog/source_test.go (about) 1 // Copyright (c) 2018 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 commitlog 22 23 import ( 24 "errors" 25 "testing" 26 "time" 27 28 "github.com/m3db/m3/src/cluster/shard" 29 "github.com/m3db/m3/src/dbnode/persist/fs" 30 "github.com/m3db/m3/src/dbnode/runtime" 31 "github.com/m3db/m3/src/dbnode/storage/bootstrap" 32 "github.com/m3db/m3/src/dbnode/storage/bootstrap/result" 33 "github.com/m3db/m3/src/dbnode/topology" 34 tu "github.com/m3db/m3/src/dbnode/topology/testutil" 35 "github.com/m3db/m3/src/x/instrument" 36 xtime "github.com/m3db/m3/src/x/time" 37 38 "github.com/stretchr/testify/require" 39 ) 40 41 var ( 42 testDefaultOpts = NewOptions(). 43 SetRuntimeOptionsManager(runtime.NewOptionsManager()) 44 notSelfID = "not-self" 45 ) 46 47 func TestAvailableData(t *testing.T) { 48 var ( 49 nsMetadata = testNsMetadata(t) 50 blockSize = 2 * time.Hour 51 numShards = uint32(4) 52 blockStart = xtime.Now().Truncate(blockSize) 53 shardTimeRangesToBootstrap = result.NewShardTimeRanges() 54 bootstrapRanges = xtime.NewRanges(xtime.Range{ 55 Start: blockStart, 56 End: blockStart.Add(blockSize), 57 }) 58 cacheOptions = bootstrap.NewCacheOptions(). 59 SetFilesystemOptions(fs.NewOptions()). 60 SetInstrumentOptions(instrument.NewOptions()) 61 ) 62 63 for i := 0; i < int(numShards); i++ { 64 shardTimeRangesToBootstrap.Set(uint32(i), bootstrapRanges) 65 } 66 67 testCases := []struct { 68 title string 69 topoState *topology.StateSnapshot 70 shardsTimeRangesToBootstrap result.ShardTimeRanges 71 expectedAvailableShardsTimeRanges result.ShardTimeRanges 72 expectedErr error 73 }{ 74 { 75 title: "Single node - Shard initializing", 76 topoState: tu.NewStateSnapshot(1, tu.HostShardStates{ 77 tu.SelfID: tu.ShardsRange(0, numShards, shard.Initializing), 78 }), 79 shardsTimeRangesToBootstrap: shardTimeRangesToBootstrap, 80 expectedAvailableShardsTimeRanges: result.NewShardTimeRanges(), 81 }, 82 { 83 title: "Single node - Shard unknown", 84 topoState: tu.NewStateSnapshot(1, tu.HostShardStates{ 85 tu.SelfID: tu.ShardsRange(0, numShards, shard.Unknown), 86 }), 87 shardsTimeRangesToBootstrap: shardTimeRangesToBootstrap, 88 expectedAvailableShardsTimeRanges: result.NewShardTimeRanges(), 89 expectedErr: errors.New("unknown shard state: Unknown"), 90 }, 91 { 92 title: "Single node - Shard leaving", 93 topoState: tu.NewStateSnapshot(1, tu.HostShardStates{ 94 tu.SelfID: tu.ShardsRange(0, numShards, shard.Leaving), 95 }), 96 shardsTimeRangesToBootstrap: shardTimeRangesToBootstrap, 97 expectedAvailableShardsTimeRanges: shardTimeRangesToBootstrap, 98 }, 99 { 100 title: "Single node - Shard available", 101 topoState: tu.NewStateSnapshot(1, tu.HostShardStates{ 102 tu.SelfID: tu.ShardsRange(0, numShards, shard.Available), 103 }), 104 shardsTimeRangesToBootstrap: shardTimeRangesToBootstrap, 105 expectedAvailableShardsTimeRanges: shardTimeRangesToBootstrap, 106 }, 107 { 108 title: "Multi node - Origin available", 109 topoState: tu.NewStateSnapshot(1, tu.HostShardStates{ 110 tu.SelfID: tu.ShardsRange(0, numShards, shard.Available), 111 notSelfID: tu.ShardsRange(0, numShards, shard.Initializing), 112 }), 113 shardsTimeRangesToBootstrap: shardTimeRangesToBootstrap, 114 expectedAvailableShardsTimeRanges: shardTimeRangesToBootstrap, 115 }, 116 { 117 title: "Multi node - Origin not available", 118 topoState: tu.NewStateSnapshot(1, tu.HostShardStates{ 119 tu.SelfID: tu.ShardsRange(0, numShards, shard.Initializing), 120 notSelfID: tu.ShardsRange(0, numShards, shard.Available), 121 }), 122 shardsTimeRangesToBootstrap: shardTimeRangesToBootstrap, 123 expectedAvailableShardsTimeRanges: result.NewShardTimeRanges(), 124 }, 125 } 126 127 for _, tc := range testCases { 128 t.Run(tc.title, func(t *testing.T) { 129 var shards []uint32 130 for shard := range tc.shardsTimeRangesToBootstrap.Iter() { 131 shards = append(shards, shard) 132 } 133 cache, sErr := bootstrap.NewCache(cacheOptions. 134 SetNamespaceDetails([]bootstrap.NamespaceDetails{ 135 { 136 Namespace: nsMetadata, 137 Shards: shards, 138 }, 139 })) 140 require.NoError(t, sErr) 141 142 var ( 143 src = newCommitLogSource(testDefaultOpts, fs.Inspection{}) 144 runOpts = testDefaultRunOpts.SetInitialTopologyState(tc.topoState) 145 dataRes, err = src.AvailableData(nsMetadata, tc.shardsTimeRangesToBootstrap, cache, runOpts) 146 ) 147 148 if tc.expectedErr != nil { 149 require.Equal(t, err, tc.expectedErr) 150 } else { 151 require.NoError(t, err) 152 require.Equal(t, tc.expectedAvailableShardsTimeRanges, dataRes) 153 } 154 155 indexRes, err := src.AvailableIndex(nsMetadata, tc.shardsTimeRangesToBootstrap, cache, runOpts) 156 if tc.expectedErr != nil { 157 require.Equal(t, err, tc.expectedErr) 158 } else { 159 require.NoError(t, err) 160 require.Equal(t, tc.expectedAvailableShardsTimeRanges, indexRes) 161 } 162 }) 163 } 164 }