github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/namespace/convert_prop_test.go (about) 1 // Copyright (c) 2017 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 namespace_test 22 23 import ( 24 "fmt" 25 "github.com/stretchr/testify/require" 26 "math/rand" 27 "os" 28 "testing" 29 "time" 30 31 "github.com/m3db/m3/src/dbnode/namespace" 32 "github.com/m3db/m3/src/dbnode/retention" 33 "github.com/m3db/m3/src/x/ident" 34 35 "github.com/leanovate/gopter" 36 "github.com/leanovate/gopter/gen" 37 "github.com/leanovate/gopter/prop" 38 ) 39 40 const ( 41 testRandomSeeed int64 = 7823434 42 testMinSuccessfulTests = 1000 43 ) 44 45 func TestConvert(t *testing.T) { 46 parameters := gopter.DefaultTestParameters() 47 parameters.Rng.Seed(testRandomSeeed) // generate reproducible results 48 parameters.MinSuccessfulTests = testMinSuccessfulTests 49 parameters.MaxSize = 10 50 parameters.MinSize = 2 51 props := gopter.NewProperties(parameters) 52 53 props.Property("Conversion rooted at metadata is bijective", prop.ForAll( 54 func(nsMap namespace.Map) (bool, error) { 55 reg, err := namespace.ToProto(nsMap) 56 require.NoError(t, err) 57 cmd, err := namespace.FromProto(*reg) 58 if err != nil { 59 return false, err 60 } 61 return nsMap.Equal(cmd), nil 62 }, 63 genMap(), 64 )) 65 reporter := gopter.NewFormatedReporter(true, 160, os.Stdout) 66 if !props.Run(reporter) { 67 t.Errorf("failed with initial seed: %d", 0) // seed) 68 } 69 } 70 71 // map generator 72 func genMap() gopter.Gen { 73 return gen.SliceOf(genMetadata()).Map( 74 func(metadatas []namespace.Metadata) namespace.Map { 75 nsMap, err := namespace.NewMap(metadatas) 76 if err != nil { 77 panic(err.Error()) 78 } 79 return nsMap 80 }) 81 } 82 83 // metadata generator 84 func genMetadata() gopter.Gen { 85 return gopter.CombineGens( 86 gen.Identifier(), 87 gen.SliceOfN(7, gen.Bool()), 88 genRetention(), 89 ).Map(func(values []interface{}) namespace.Metadata { 90 var ( 91 id = values[0].(string) 92 bools = values[1].([]bool) 93 retention = values[2].(retention.Options) 94 ) 95 testSchemaReg, _ := namespace.LoadSchemaHistory(testSchemaOptions) 96 md, err := namespace.NewMetadata(ident.StringID(id), namespace.NewOptions(). 97 SetBootstrapEnabled(bools[0]). 98 SetCleanupEnabled(bools[1]). 99 SetFlushEnabled(bools[2]). 100 SetRepairEnabled(bools[3]). 101 SetWritesToCommitLog(bools[4]). 102 SetSnapshotEnabled(bools[5]). 103 SetSchemaHistory(testSchemaReg). 104 SetRetentionOptions(retention). 105 SetIndexOptions(namespace.NewIndexOptions(). 106 SetEnabled(bools[6]). 107 SetBlockSize(retention.BlockSize()))) 108 if err != nil { 109 panic(err.Error()) 110 } 111 return md 112 }) 113 } 114 115 func newRandomRetention(rng *rand.Rand) *generatedRetention { 116 var ( 117 blockSizeMins = maxInt(1, rng.Intn(60*12)) // 12 hours 118 retentionMins = maxInt(1, rng.Intn(40)) * blockSizeMins 119 bufferPastMins = maxInt(1, rng.Intn(blockSizeMins)) 120 bufferFutureMins = maxInt(1, rng.Intn(blockSizeMins)) 121 ) 122 123 return &generatedRetention{retention.NewOptions(). 124 SetRetentionPeriod(time.Duration(retentionMins) * time.Minute). 125 SetBlockSize(time.Duration(blockSizeMins) * time.Minute). 126 SetBufferPast(time.Duration(bufferPastMins) * time.Minute). 127 SetBufferFuture(time.Duration(bufferFutureMins) * time.Minute)} 128 } 129 130 // generator for retention options 131 func genRetention() gopter.Gen { 132 return func(genParams *gopter.GenParameters) *gopter.GenResult { 133 opts := newRandomRetention(genParams.Rng) 134 genResult := gopter.NewGenResult(opts, gopter.NoShrinker) 135 genResult.Sieve = func(v interface{}) bool { 136 return v.(retention.Options).Validate() == nil 137 } 138 return genResult 139 } 140 } 141 142 type generatedRetention struct { 143 retention.Options 144 } 145 146 func (ro *generatedRetention) String() string { 147 return fmt.Sprintf( 148 "[ retention-period = %v, block-size = %v, buffer-past = %v, buffer-future = %v ]", 149 ro.RetentionPeriod().String(), 150 ro.BlockSize().String(), 151 ro.BufferPast().String(), 152 ro.BufferFuture().String()) 153 } 154 155 func maxInt(x, y int) int { 156 if x > y { 157 return x 158 } 159 return y 160 }