go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/tsmon/flush_test.go (about) 1 // Copyright 2015 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tsmon 16 17 import ( 18 "context" 19 "testing" 20 "time" 21 22 "go.chromium.org/luci/common/clock" 23 "go.chromium.org/luci/common/clock/testclock" 24 "go.chromium.org/luci/common/tsmon/field" 25 "go.chromium.org/luci/common/tsmon/target" 26 "go.chromium.org/luci/common/tsmon/types" 27 28 . "github.com/smartystreets/goconvey/convey" 29 ) 30 31 func TestFlush(t *testing.T) { 32 t.Parallel() 33 34 defaultTarget := &target.Task{ServiceName: "test"} 35 36 Convey("With a testing State", t, func() { 37 c := WithState(context.Background(), NewState()) 38 39 Convey("Sends a metric", func() { 40 c, s, m := WithFakes(c) 41 s.Cells = []types.Cell{ 42 { 43 types.MetricInfo{ 44 Name: "foo", 45 Fields: []field.Field{}, 46 ValueType: types.StringType, 47 }, 48 types.MetricMetadata{}, 49 types.CellData{ 50 FieldVals: []any{}, 51 ResetTime: time.Unix(1234, 1000), 52 Value: "bar", 53 }, 54 }, 55 } 56 s.DT = defaultTarget 57 m.CS = 42 58 59 So(Flush(c), ShouldBeNil) 60 61 So(len(m.Cells), ShouldEqual, 1) 62 So(len(m.Cells[0]), ShouldEqual, 1) 63 So(m.Cells[0][0], ShouldResemble, types.Cell{ 64 types.MetricInfo{ 65 Name: "foo", 66 Fields: []field.Field{}, 67 ValueType: types.StringType, 68 }, 69 types.MetricMetadata{}, 70 types.CellData{ 71 FieldVals: []any{}, 72 ResetTime: time.Unix(1234, 1000), 73 Value: "bar", 74 }, 75 }) 76 }) 77 78 Convey("Splits up ChunkSize metrics", func() { 79 c, s, m := WithFakes(c) 80 s.Cells = make([]types.Cell, 43) 81 s.DT = defaultTarget 82 m.CS = 42 83 84 for i := 0; i < 43; i++ { 85 s.Cells[i] = types.Cell{ 86 types.MetricInfo{ 87 Name: "foo", 88 Fields: []field.Field{}, 89 ValueType: types.StringType, 90 }, 91 types.MetricMetadata{}, 92 types.CellData{ 93 FieldVals: []any{}, 94 ResetTime: time.Unix(1234, 1000), 95 Value: "bar", 96 }, 97 } 98 } 99 100 So(Flush(c), ShouldBeNil) 101 102 So(len(m.Cells), ShouldEqual, 2) 103 So(len(m.Cells[0]), ShouldEqual, 42) 104 So(len(m.Cells[1]), ShouldEqual, 1) 105 }) 106 107 Convey("Doesn't split metrics when ChunkSize is 0", func() { 108 c, s, m := WithFakes(c) 109 s.Cells = make([]types.Cell, 43) 110 s.DT = defaultTarget 111 m.CS = 0 112 113 for i := 0; i < 43; i++ { 114 s.Cells[i] = types.Cell{ 115 types.MetricInfo{ 116 Name: "foo", 117 Fields: []field.Field{}, 118 ValueType: types.StringType, 119 }, 120 types.MetricMetadata{}, 121 types.CellData{ 122 FieldVals: []any{}, 123 ResetTime: time.Unix(1234, 1000), 124 Value: "bar", 125 }, 126 } 127 } 128 129 So(Flush(c), ShouldBeNil) 130 131 So(len(m.Cells), ShouldEqual, 1) 132 So(len(m.Cells[0]), ShouldEqual, 43) 133 }) 134 135 Convey("No Monitor configured", func() { 136 c, _, _ := WithFakes(c) 137 state := GetState(c) 138 state.SetMonitor(nil) 139 140 So(Flush(c), ShouldNotBeNil) 141 }) 142 143 Convey("Auto flush works", func() { 144 start := time.Unix(1454561232, 0) 145 c, tc := testclock.UseTime(c, start) 146 tc.SetTimerCallback(func(d time.Duration, t clock.Timer) { 147 tc.Add(d) 148 }) 149 150 moments := make(chan int) 151 flusher := autoFlusher{ 152 flush: func(ctx context.Context) error { 153 select { 154 case <-ctx.Done(): 155 case moments <- int(clock.Now(ctx).Sub(start).Seconds()): 156 } 157 return nil 158 }, 159 } 160 161 flusher.start(c, time.Second) 162 163 // Each 'flush' gets blocked on sending into 'moments'. Once unblocked, it 164 // advances timer by 'interval' sec (1 sec in the test). 165 So(<-moments, ShouldEqual, 1) 166 So(<-moments, ShouldEqual, 2) 167 // and so on ... 168 169 // Doesn't timeout => works. 170 flusher.stop() 171 }) 172 }) 173 }