github.com/m3db/m3@v1.5.0/src/cmd/tools/dtest/util/seed/generator_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 seed 22 23 import ( 24 "fmt" 25 "io/ioutil" 26 "os" 27 "path" 28 "path/filepath" 29 "sort" 30 "strconv" 31 "strings" 32 "testing" 33 "time" 34 35 "github.com/m3db/m3/src/dbnode/integration/generate" 36 "github.com/m3db/m3/src/dbnode/namespace" 37 "github.com/m3db/m3/src/x/ident" 38 "github.com/m3db/m3/src/x/instrument" 39 xtest "github.com/m3db/m3/src/x/test" 40 xtime "github.com/m3db/m3/src/x/time" 41 42 "github.com/golang/mock/gomock" 43 "github.com/stretchr/testify/require" 44 ) 45 46 func TestGenerator(t *testing.T) { 47 dir, err := ioutil.TempDir("", "test-single-conf") 48 require.NoError(t, err) 49 defer os.RemoveAll(dir) 50 51 gOpts := generate.NewOptions(). 52 SetFilePathPrefix(dir). 53 SetRetentionPeriod(2 * time.Hour). 54 SetBlockSize(time.Hour). 55 SetWriteEmptyShards(false) 56 57 rawLogger := xtest.NewLogger(t) 58 iopts := instrument.NewOptions().SetLogger(rawLogger) 59 60 opts := NewOptions(). 61 SetInstrumentOptions(iopts). 62 SetGenerateOptions(gOpts). 63 SetNumIDs(10). 64 SetMaxNumPointsPerID(10). 65 SetMinNumPointsPerID(2) 66 67 generator := NewGenerator(opts) 68 69 ctrl := gomock.NewController(t) 70 defer ctrl.Finish() 71 72 shard := uint32(123) 73 require.NoError(t, generator.Generate(namespace.Context{ID: ident.StringID("testmetrics")}, shard)) 74 75 te := newFileInfoExtractor() 76 require.NoError(t, filepath.Walk(dir, te.visit)) 77 shards := te.sortedShards() 78 require.Equal(t, 1, len(shards)) 79 require.Equal(t, uint32(123), shards[0]) 80 times := te.sortedTimes() 81 require.Equal(t, 2, len(times)) 82 } 83 84 type fileInfoExtractor struct { 85 shards map[uint32]struct{} 86 times map[int64]struct{} 87 } 88 89 func newFileInfoExtractor() *fileInfoExtractor { 90 return &fileInfoExtractor{ 91 shards: make(map[uint32]struct{}), 92 times: make(map[int64]struct{}), 93 } 94 } 95 96 func (t *fileInfoExtractor) sortedShards() []uint32 { 97 shards := make([]uint32, 0, len(t.shards)) 98 for i := range t.shards { 99 shards = append(shards, i) 100 } 101 sort.Sort(uint32arr(shards)) 102 return shards 103 } 104 105 func (t *fileInfoExtractor) sortedTimes() []time.Time { 106 times := make([]int64, 0, len(t.times)) 107 for i := range t.times { 108 times = append(times, i) 109 } 110 sort.Sort(int64arr(times)) 111 112 timets := make([]time.Time, 0, len(t.times)) 113 for _, ts := range times { 114 timets = append(timets, xtime.FromNanoseconds(ts)) 115 } 116 return timets 117 } 118 119 func (t *fileInfoExtractor) visit(fPath string, f os.FileInfo, err error) error { 120 if f.IsDir() { 121 return nil 122 } 123 shardDir := path.Base(path.Dir(fPath)) 124 shardNum, err := strconv.ParseUint(shardDir, 10, 32) 125 if err != nil { 126 return err 127 } 128 t.shards[uint32(shardNum)] = struct{}{} 129 130 name := f.Name() 131 nameSplit := strings.Split(name, "-") 132 if len(nameSplit) < 2 { 133 return fmt.Errorf("unable to parse time from %v", name) 134 } 135 136 num, parseErr := strconv.ParseInt(nameSplit[1], 10, 64) 137 if parseErr != nil { 138 return err 139 } 140 t.times[num] = struct{}{} 141 return nil 142 } 143 144 type uint32arr []uint32 145 146 func (a uint32arr) Len() int { return len(a) } 147 func (a uint32arr) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 148 func (a uint32arr) Less(i, j int) bool { return a[i] < a[j] } 149 150 type int64arr []int64 151 152 func (a int64arr) Len() int { return len(a) } 153 func (a int64arr) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 154 func (a int64arr) Less(i, j int) bool { return a[i] < a[j] }