github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/cmd/services/m3dbnode/main/common_test.go (about) 1 // +build big 2 // 3 // Copyright (c) 2017 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 main_test 24 25 import ( 26 "bytes" 27 "encoding/json" 28 "fmt" 29 "io/ioutil" 30 "os" 31 "strings" 32 "sync/atomic" 33 "testing" 34 "time" 35 36 "github.com/m3db/m3/src/cluster/shard" 37 "github.com/m3db/m3/src/dbnode/client" 38 "github.com/m3db/m3/src/dbnode/namespace" 39 "github.com/m3db/m3/src/dbnode/retention" 40 "github.com/m3db/m3/src/x/ident" 41 42 "github.com/gogo/protobuf/proto" 43 "github.com/stretchr/testify/assert" 44 "github.com/stretchr/testify/require" 45 ) 46 47 const ( 48 hostID = "m3dbtest01" 49 serviceName = "m3dbnode_test" 50 serviceEnv = "test" 51 serviceZone = "local" 52 namespaceID = "metrics" 53 lpURL = "http://0.0.0.0:2380" 54 lcURL = "http://0.0.0.0:2379" 55 apURL = "http://localhost:2380" 56 acURL = "http://localhost:2379" 57 etcdEndpoint = acURL 58 initialClusterHostID = hostID 59 initialClusterEndpoint = apURL 60 ) 61 62 var ( 63 // NB: access through nextServicePort 64 _servicePort uint32 = 9000 65 ) 66 67 func nextServicePort() uint32 { 68 return atomic.AddUint32(&_servicePort, 1000) 69 } 70 71 type cleanup func() 72 73 func tempFile(t *testing.T, name string) (*os.File, cleanup) { 74 fd, err := ioutil.TempFile("", name) 75 require.NoError(t, err) 76 77 fname := fd.Name() 78 return fd, func() { 79 assert.NoError(t, fd.Close()) 80 assert.NoError(t, os.Remove(fname)) 81 } 82 } 83 84 func tempFileTouch(t *testing.T, name string) (string, cleanup) { 85 fd, err := ioutil.TempFile("", name) 86 require.NoError(t, err) 87 88 fname := fd.Name() 89 require.NoError(t, fd.Close()) 90 return fname, func() { 91 assert.NoError(t, os.Remove(fname)) 92 } 93 } 94 95 func tempDir(t *testing.T, name string) (string, cleanup) { 96 dir, err := ioutil.TempDir("", name) 97 require.NoError(t, err) 98 return dir, func() { 99 assert.NoError(t, os.RemoveAll(dir)) 100 } 101 } 102 103 // yamlArray returns a JSON array which is valid YAML, hehe.. 104 func yamlArray(t *testing.T, values []string) string { 105 buff := bytes.NewBuffer(nil) 106 err := json.NewEncoder(buff).Encode(values) 107 require.NoError(t, err) 108 return strings.TrimSpace(buff.String()) 109 } 110 111 func endpoint(ip string, port uint32) string { 112 return fmt.Sprintf("%s:%d", ip, port) 113 } 114 115 func newNamespaceProtoValue(id string) (proto.Message, error) { 116 return newNamespaceWithIndexProtoValue(id, false) 117 } 118 119 func newNamespaceWithIndexProtoValue(id string, indexEnabled bool) (proto.Message, error) { 120 md, err := namespace.NewMetadata( 121 ident.StringID(id), 122 namespace.NewOptions(). 123 SetBootstrapEnabled(true). 124 SetCleanupEnabled(true). 125 SetFlushEnabled(true). 126 SetRepairEnabled(true). 127 SetWritesToCommitLog(true). 128 SetRetentionOptions( 129 retention.NewOptions(). 130 SetBlockSize(1*time.Hour). 131 SetRetentionPeriod(24*time.Hour)). 132 SetIndexOptions( 133 namespace.NewIndexOptions(). 134 SetBlockSize(6*time.Hour). 135 SetEnabled(indexEnabled))) 136 if err != nil { 137 return nil, err 138 } 139 nsMap, err := namespace.NewMap([]namespace.Metadata{md}) 140 if err != nil { 141 return nil, err 142 } 143 144 registry, err := namespace.ToProto(nsMap) 145 if err != nil { 146 return nil, err 147 } 148 149 return registry, nil 150 } 151 152 // waitUntilAllShardsAreAvailable continually polls the session checking to see if the topology.Map 153 // that the session is currently storing contains a non-zero number of host shard sets, and if so, 154 // makes sure that all their shard states are Available. 155 func waitUntilAllShardsAreAvailable(t *testing.T, session client.AdminSession) { 156 outer: 157 for { 158 time.Sleep(10 * time.Millisecond) 159 160 topoMap, err := session.TopologyMap() 161 require.NoError(t, err) 162 163 var ( 164 hostShardSets = topoMap.HostShardSets() 165 ) 166 167 if len(hostShardSets) == 0 { 168 // We haven't received an actual topology yet. 169 continue 170 } 171 172 for _, hostShardSet := range hostShardSets { 173 for _, hostShard := range hostShardSet.ShardSet().All() { 174 if hostShard.State() != shard.Available { 175 continue outer 176 } 177 } 178 } 179 180 break 181 } 182 }