github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/integration/peers_bootstrap_select_best_test.go (about) 1 // +build integration 2 3 // Copyright (c) 2016 Uber Technologies, Inc. 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a copy 6 // of this software and associated documentation files (the "Software"), to deal 7 // in the Software without restriction, including without limitation the rights 8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 // copies of the Software, and to permit persons to whom the Software is 10 // furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 // THE SOFTWARE. 22 23 package integration 24 25 import ( 26 "testing" 27 "time" 28 29 "github.com/m3db/m3/src/dbnode/integration/generate" 30 "github.com/m3db/m3/src/dbnode/namespace" 31 "github.com/m3db/m3/src/dbnode/retention" 32 xtest "github.com/m3db/m3/src/x/test" 33 xtime "github.com/m3db/m3/src/x/time" 34 35 "github.com/stretchr/testify/require" 36 ) 37 38 func TestPeersBootstrapSelectBest(t *testing.T) { 39 if testing.Short() { 40 t.SkipNow() 41 } 42 43 // Test setups 44 log := xtest.NewLogger(t) 45 retentionOpts := retention.NewOptions(). 46 SetRetentionPeriod(20 * time.Hour). 47 SetBlockSize(2 * time.Hour). 48 SetBufferPast(10 * time.Minute). 49 SetBufferFuture(2 * time.Minute) 50 namesp, err := namespace.NewMetadata(testNamespaces[0], namespace.NewOptions().SetRetentionOptions(retentionOpts)) 51 require.NoError(t, err) 52 opts := NewTestOptions(t). 53 SetNamespaces([]namespace.Metadata{namesp}). 54 // Use TChannel clients for writing / reading because we want to target individual nodes at a time 55 // and not write/read all nodes in the cluster. 56 SetUseTChannelClientForWriting(true). 57 SetUseTChannelClientForReading(true) 58 59 setupOpts := []BootstrappableTestSetupOptions{ 60 {DisablePeersBootstrapper: true}, 61 {DisablePeersBootstrapper: true}, 62 { 63 DisableCommitLogBootstrapper: true, 64 DisablePeersBootstrapper: false, 65 }, 66 } 67 setups, closeFn := NewDefaultBootstrappableTestSetups(t, opts, setupOpts) 68 defer closeFn() 69 70 // Write test data alternating missing data for left/right nodes 71 now := setups[0].NowFn()() 72 blockSize := retentionOpts.BlockSize() 73 // Make sure we have multiple blocks of data for multiple series to exercise 74 // the grouping and aggregating logic in the client peer bootstrapping process 75 seriesMaps := generate.BlocksByStart([]generate.BlockConfig{ 76 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-4 * blockSize)}, 77 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-3 * blockSize)}, 78 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-2 * blockSize)}, 79 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now.Add(-blockSize)}, 80 {IDs: []string{"foo", "baz"}, NumPoints: 90, Start: now}, 81 }) 82 left := make(map[xtime.UnixNano]generate.SeriesBlock) 83 right := make(map[xtime.UnixNano]generate.SeriesBlock) 84 shouldMissData := false 85 appendSeries := func(target map[xtime.UnixNano]generate.SeriesBlock, start time.Time, s generate.Series) { 86 startNano := xtime.ToUnixNano(start) 87 if shouldMissData { 88 var dataWithMissing []generate.TestValue 89 for i := range s.Data { 90 if i%2 != 0 { 91 continue 92 } 93 dataWithMissing = append(dataWithMissing, s.Data[i]) 94 } 95 target[startNano] = append(target[startNano], generate.Series{ID: s.ID, Data: dataWithMissing}) 96 } else { 97 target[startNano] = append(target[startNano], s) 98 } 99 shouldMissData = !shouldMissData 100 } 101 for start, data := range seriesMaps { 102 for _, series := range data { 103 appendSeries(left, start.ToTime(), series) 104 appendSeries(right, start.ToTime(), series) 105 } 106 } 107 require.NoError(t, writeTestDataToDisk(namesp, setups[0], left, 0)) 108 require.NoError(t, writeTestDataToDisk(namesp, setups[1], right, 0)) 109 110 // Start the first two servers with filesystem bootstrappers 111 setups[:2].parallel(func(s TestSetup) { 112 require.NoError(t, s.StartServer()) 113 }) 114 115 // Start the last server with peers and filesystem bootstrappers 116 require.NoError(t, setups[2].StartServer()) 117 log.Debug("servers are now up") 118 119 // Stop the servers 120 defer func() { 121 setups.parallel(func(s TestSetup) { 122 require.NoError(t, s.StopServer()) 123 }) 124 log.Debug("servers are now down") 125 }() 126 127 // Verify in-memory data match what we expect 128 verifySeriesMaps(t, setups[0], namesp.ID(), left) 129 verifySeriesMaps(t, setups[1], namesp.ID(), right) 130 verifySeriesMaps(t, setups[2], namesp.ID(), seriesMaps) 131 }