github.com/m3db/m3@v1.5.0/src/m3em/integration/common.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 integration 22 23 import ( 24 "bytes" 25 "encoding/binary" 26 "fmt" 27 "io/ioutil" 28 "math/rand" 29 "os" 30 "path" 31 "testing" 32 "time" 33 34 "github.com/m3db/m3/src/m3em/agent" 35 36 "github.com/stretchr/testify/require" 37 ) 38 39 const ( 40 rngSeed = int64(123456789) 41 defaultUniqueBytes = int64(1024 * 8) 42 ) 43 44 type testProgram []byte 45 46 var ( 47 // nolint: varcheck 48 shortLivedTestProgram = testProgram([]byte(`#!/usr/bin/env bash 49 if [ "$#" -ne 2 ]; then 50 echo "Args: $@" >&2 51 echo "Illegal number of arguments" >&2 52 exit 1 53 fi 54 echo -ne "testing random output"`)) 55 56 // nolint: varcheck 57 longRunningTestProgram = testProgram([]byte(`#!/usr/bin/env bash 58 echo -ne "testing random output" 59 while true; do sleep 1; done 60 echo -ne "should never get this"`)) 61 ) 62 63 func newTempFile(t *testing.T, dir string, content []byte) *os.File { 64 tmpfile, err := ioutil.TempFile(dir, "example") 65 require.NoError(t, err) 66 n, err := tmpfile.Write(content) 67 require.NoError(t, err) 68 require.Equal(t, len(content), n) 69 require.NoError(t, tmpfile.Close()) 70 return tmpfile 71 } 72 73 func newTestScript(t *testing.T, dir string, scriptNum int, script testProgram) string { 74 file, err := ioutil.TempFile(dir, fmt.Sprintf("testscript%d.sh", scriptNum)) 75 require.NoError(t, err) 76 name := file.Name() 77 require.NoError(t, file.Chmod(0755)) 78 scriptContents := []byte(script) 79 numWritten, err := file.Write(scriptContents) 80 require.NoError(t, err) 81 require.Equal(t, len(scriptContents), numWritten) 82 require.NoError(t, file.Close()) 83 return name 84 } 85 86 func newLargeTempFile(t *testing.T, dir string, numBytes int64) *os.File { 87 if numBytes%defaultUniqueBytes != 0 { 88 require.FailNow(t, "numBytes must be divisble by %d", defaultUniqueBytes) 89 } 90 byteStream := newRandByteStream(t, defaultUniqueBytes) 91 numIters := numBytes / defaultUniqueBytes 92 tmpfile, err := ioutil.TempFile(dir, "example-large-file") 93 require.NoError(t, err) 94 for i := int64(0); i < numIters; i++ { 95 n, err := tmpfile.Write(byteStream) 96 require.NoError(t, err) 97 require.Equal(t, len(byteStream), n) 98 } 99 require.NoError(t, tmpfile.Close()) 100 return tmpfile 101 } 102 103 func newTempDir(t *testing.T) string { 104 path, err := ioutil.TempDir("", "integration-test") 105 require.NoError(t, err) 106 return path 107 } 108 109 func newSubDir(t *testing.T, dir, subdir string) string { 110 newPath := path.Join(dir, subdir) 111 err := os.Mkdir(newPath, os.FileMode(0755)) 112 require.NoError(t, err) 113 return newPath 114 } 115 116 func newRandByteStream(t *testing.T, numBytes int64) []byte { 117 if mod8 := numBytes % int64(8); mod8 != 0 { 118 require.FailNow(t, "numBytes must be divisible by 8") 119 } 120 var ( 121 buff = bytes.NewBuffer(nil) 122 num = numBytes / 8 123 r = rand.New(rand.NewSource(rngSeed)) 124 ) 125 for i := int64(0); i < num; i++ { 126 n := r.Int63() 127 err := binary.Write(buff, binary.LittleEndian, n) 128 require.NoError(t, err) 129 } 130 return buff.Bytes() 131 } 132 133 // returns true if agent finished, false otherwise 134 func waitUntilAgentFinished(a agent.Agent, timeout time.Duration) bool { 135 start := time.Now() 136 seenRunning := false 137 stopped := false 138 for !stopped { 139 now := time.Now() 140 if now.Sub(start) > timeout { 141 return stopped 142 } 143 running := a.Running() 144 seenRunning = seenRunning || running 145 stopped = seenRunning && !running 146 time.Sleep(10 * time.Millisecond) 147 } 148 return stopped 149 } 150 151 func testExecGenFn(binary string, config string) (string, []string) { 152 return binary, []string{"-f", config} 153 }