github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/x/instrument/build_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 instrument 22 23 import ( 24 "bytes" 25 "encoding/json" 26 "errors" 27 "fmt" 28 "log" 29 "os" 30 "strings" 31 "testing" 32 "time" 33 34 "github.com/fortytw2/leaktest" 35 "github.com/stretchr/testify/assert" 36 "github.com/stretchr/testify/require" 37 "github.com/uber-go/tally" 38 ) 39 40 const ( 41 testReportInterval = 10 * time.Millisecond 42 ) 43 44 func newTestOptions() Options { 45 testScope := tally.NewTestScope("", nil) 46 return NewOptions(). 47 SetMetricsScope(testScope). 48 SetReportInterval(testReportInterval) 49 } 50 51 func TestStartStop(t *testing.T) { 52 defer leaktest.Check(t)() 53 54 rep := NewBuildReporter(newTestOptions()) 55 require.NoError(t, rep.Start()) 56 require.NoError(t, rep.Stop()) 57 } 58 59 func TestStartStart(t *testing.T) { 60 defer leaktest.Check(t)() 61 62 rep := NewBuildReporter(newTestOptions()) 63 defer rep.Stop() 64 require.NoError(t, rep.Start()) 65 require.Error(t, rep.Start()) 66 } 67 68 func TestStopWithoutStart(t *testing.T) { 69 defer leaktest.Check(t)() 70 71 rep := NewBuildReporter(newTestOptions()) 72 require.Error(t, rep.Stop()) 73 } 74 75 func TestMultipleStop(t *testing.T) { 76 defer leaktest.Check(t)() 77 78 rep := NewBuildReporter(newTestOptions()) 79 require.NoError(t, rep.Start()) 80 go rep.Stop() 81 go rep.Stop() 82 } 83 84 func TestVersionReported(t *testing.T) { 85 defer leaktest.Check(t)() 86 87 opts := newTestOptions() 88 rep := NewBuildReporter(opts) 89 require.NoError(t, rep.Start()) 90 91 testScope := opts.MetricsScope().(tally.TestScope) 92 notFound := true 93 for notFound { 94 snapshot := testScope.Snapshot().Gauges() 95 for key := range snapshot { 96 if strings.Contains(key, buildInfoMetricName) { 97 notFound = false 98 break 99 } 100 } 101 } 102 103 require.NoError(t, rep.Stop()) 104 } 105 106 func TestAgeReported(t *testing.T) { 107 defer leaktest.Check(t)() 108 109 opts := newTestOptions() 110 rep := NewBuildReporter(opts) 111 require.NoError(t, rep.Start()) 112 113 testScope := opts.MetricsScope().(tally.TestScope) 114 notFound := true 115 for notFound { 116 snapshot := testScope.Snapshot().Gauges() 117 for key := range snapshot { 118 if strings.Contains(key, buildAgeMetricName) { 119 notFound = false 120 break 121 } 122 } 123 } 124 125 require.NoError(t, rep.Stop()) 126 } 127 128 func TestAgeReportedIsCorrect(t *testing.T) { 129 defer leaktest.Check(t)() 130 131 BuildTimeUnix = fmt.Sprintf("%d", time.Now().Add(-24*time.Hour).Unix()) 132 opts := newTestOptions() 133 rep := NewBuildReporter(opts) 134 require.NoError(t, rep.Start()) 135 136 testScope := opts.MetricsScope().(tally.TestScope) 137 notFound := true 138 age := float64(0.0) 139 for notFound { 140 snapshot := testScope.Snapshot().Gauges() 141 for key, value := range snapshot { 142 if strings.Contains(key, buildAgeMetricName) { 143 age = value.Value() 144 notFound = false 145 break 146 } 147 } 148 } 149 150 dayInNanos := float64(24 * time.Hour / time.Nanosecond) 151 require.True(t, age >= dayInNanos) 152 153 require.NoError(t, rep.Stop()) 154 } 155 156 func TestBuildReporterFailsForWrongAge(t *testing.T) { 157 defer leaktest.Check(t)() 158 159 BuildTimeUnix = fmt.Sprintf("-%d", time.Now().Unix()) 160 opts := newTestOptions() 161 rep := NewBuildReporter(opts) 162 require.Error(t, rep.Start()) 163 } 164 165 func TestLogBuildInfoJSONReturnsValidJSON(t *testing.T) { 166 defer leaktest.Check(t)() 167 var buf bytes.Buffer 168 log.SetOutput(&buf) 169 defer func() { 170 log.SetOutput(os.Stderr) 171 }() 172 err := LogBuildInfoWithLoggerJSON(log.Default(), json.Marshal) 173 assert.Nil(t, err) 174 var js json.RawMessage 175 176 // json Unmarshal returns error if the message is invalid json 177 assert.Nil(t, json.Unmarshal(buf.Bytes(), &js)) 178 } 179 180 func TestLogBuildInfoJSONHandlesErrorGracefully(t *testing.T) { 181 defer leaktest.Check(t)() 182 err := LogBuildInfoWithLoggerJSON(log.Default(), func(interface{}) ([]byte, error) { 183 return nil, errors.New("test error") 184 }) 185 assert.Equal(t, err.Error(), "test error") 186 }