github.com/mrgossett/heapster@v0.18.2/store/daystore/day_store_test.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 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 daystore 16 17 import ( 18 "testing" 19 "time" 20 21 "github.com/stretchr/testify/assert" 22 23 statstore "k8s.io/heapster/store/statstore" 24 ) 25 26 // TestPutError tests the error flow of Put 27 func TestPutError(t *testing.T) { 28 assert := assert.New(t) 29 now := time.Now().Truncate(time.Minute) 30 31 ds := NewDayStore(10, time.Minute) 32 33 // Put a normal Point 34 assert.NoError(ds.Put(statstore.TimePoint{ 35 Timestamp: now, 36 Value: uint64(100), 37 })) 38 39 // Put a Point in the past 40 assert.Error(ds.Put(statstore.TimePoint{ 41 Timestamp: now.Add(-time.Minute), 42 Value: uint64(100), 43 })) 44 } 45 46 // TestNewDayStore tests the validity of the NewDayStore constructor. 47 func TestNewDayStore(t *testing.T) { 48 assert := assert.New(t) 49 50 // Invocation with a resolution of 1 minute 51 ds := NewDayStore(10, time.Minute) 52 assert.Equal(ds.Hour.MaxSize(), time.Hour) 53 54 // Invocation with a resolution of 6 minutes 55 ds = NewDayStore(10, 6*time.Minute) 56 assert.Equal(ds.Hour.MaxSize(), time.Hour) 57 58 // Invocation with a resolution of 1 Hour 59 ds = NewDayStore(10, time.Hour) 60 assert.Equal(ds.Hour.MaxSize(), time.Hour) 61 62 // Invocation with a resolution of 11 minutes. 63 // The window should be 66 minutes in that case 64 ds = NewDayStore(10, 11*time.Minute) 65 target := time.Time{}.Add(time.Hour).Add(6 * time.Minute).Sub(time.Time{}) 66 assert.Equal(ds.Hour.MaxSize(), target) 67 } 68 69 // TestDayStore tests all methods of a DayStore. 70 func TestDayStore(t *testing.T) { 71 ds := NewDayStore(100, time.Minute) 72 assert := assert.New(t) 73 now := time.Now().Truncate(time.Minute) 74 75 // Invocations with nothing in the dayStore 76 avg, err := ds.Average() 77 assert.Error(err) 78 assert.Equal(avg, 0) 79 80 max, err := ds.Max() 81 assert.Error(err) 82 assert.Equal(max, 0) 83 84 nf, err := ds.NinetyFifth() 85 assert.Error(err) 86 assert.Equal(nf, 0) 87 88 // Put in 1 hour of data 89 assert.NoError(ds.Put(statstore.TimePoint{ 90 Timestamp: now, 91 Value: uint64(100), 92 })) 93 assert.NoError(ds.Put(statstore.TimePoint{ 94 Timestamp: now.Add(30 * time.Minute), 95 Value: uint64(200), 96 })) 97 98 // No data has been flushed to the window, the Average, Max and NinetyFifth should be - 99 // equal to that of the Hour StatStore 100 avg, err = ds.Average() 101 assert.NoError(err) 102 avgHr, err := ds.Hour.Average() 103 assert.NoError(err) 104 assert.Equal(avg, avgHr) 105 106 // The max is in the last hour 107 max, err = ds.Max() 108 assert.NoError(err) 109 maxHr, err := ds.Hour.Max() 110 assert.NoError(err) 111 assert.Equal(max, maxHr) 112 113 // The Ninetyfifth percentile does not take the last hour into account 114 nf, err = ds.NinetyFifth() 115 assert.NoError(err) 116 nfHr, err := ds.Hour.Percentile(0.95) 117 assert.NoError(err) 118 assert.Equal(nf, nfHr) 119 120 // Put in 11 more hours of data. 121 for i := 1; i <= 6; i++ { 122 assert.NoError(ds.Put(statstore.TimePoint{ 123 Timestamp: now.Add(time.Duration(i) * time.Hour), 124 Value: uint64((2*i + 1) * 100), 125 })) 126 assert.NoError(ds.Put(statstore.TimePoint{ 127 Timestamp: now.Add(time.Duration(i) * time.Hour).Add(30 * time.Minute), 128 Value: uint64((2 * (i + 1)) * 100), 129 })) 130 } 131 132 for i := 1; i <= 5; i++ { 133 assert.NoError(ds.Put(statstore.TimePoint{ 134 Timestamp: now.Add(time.Duration(i+6) * time.Hour), 135 Value: uint64((2*i - 1) * 100), 136 })) 137 assert.NoError(ds.Put(statstore.TimePoint{ 138 Timestamp: now.Add(time.Duration(i+6) * time.Hour).Add(30 * time.Minute), 139 Value: uint64((2 * i) * 100), 140 })) 141 } 142 143 // 13th Hour 144 assert.NoError(ds.Put(statstore.TimePoint{ 145 Timestamp: now.Add(12 * time.Hour), 146 Value: uint64(1100), 147 })) 148 assert.NoError(ds.Put(statstore.TimePoint{ 149 Timestamp: now.Add(12 * time.Hour).Add(30 * time.Minute), 150 Value: uint64(1500), 151 })) 152 // flush the second value of the 13th hour 153 assert.NoError(ds.Put(statstore.TimePoint{ 154 Timestamp: now.Add(12 * time.Hour).Add(32 * time.Minute), 155 Value: uint64(100), 156 })) 157 158 // Half-Day Invocations. 159 // 12 Hours have been flushed to the DayStore 160 // The current hour has two values flushed 161 162 // The average is expected to be the average of the first 12 hours. 163 avg, err = ds.Average() 164 assert.NoError(err) 165 assert.Equal(avg, uint64(666)) 166 167 // The max is in the last hour 168 max, err = ds.Max() 169 assert.NoError(err) 170 assert.Equal(max, uint64(1500)) 171 172 // The Ninetyfifth percentile does not take the last hour into account 173 nf, err = ds.NinetyFifth() 174 assert.NoError(err) 175 assert.Equal(nf, uint64(1400)) 176 177 // Assert validity of the cache by performing the same checks 178 avg, err = ds.Average() 179 assert.NoError(err) 180 assert.Equal(avg, uint64(666)) 181 max, err = ds.Max() 182 assert.NoError(err) 183 assert.Equal(max, uint64(1500)) 184 nf, err = ds.NinetyFifth() 185 assert.NoError(err) 186 assert.Equal(nf, uint64(1400)) 187 188 // Put in 12 more hours of data, at half-hour intervals. 189 for i := 1; i <= 7; i++ { 190 assert.NoError(ds.Put(statstore.TimePoint{ 191 Timestamp: now.Add(time.Duration(i+12) * time.Hour), 192 Value: uint64((2*i - 1) * 100), 193 })) 194 assert.NoError(ds.Put(statstore.TimePoint{ 195 Timestamp: now.Add(time.Duration(i+12) * time.Hour).Add(30 * time.Minute), 196 Value: uint64((2 * i) * 100), 197 })) 198 } 199 for i := 1; i <= 3; i++ { 200 assert.NoError(ds.Put(statstore.TimePoint{ 201 Timestamp: now.Add(time.Duration(i+19) * time.Hour), 202 Value: uint64((2*i - 1) * 100), 203 })) 204 assert.NoError(ds.Put(statstore.TimePoint{ 205 Timestamp: now.Add(time.Duration(i+19) * time.Hour).Add(30 * time.Minute), 206 Value: uint64((2 * i) * 100), 207 })) 208 } 209 210 assert.NoError(ds.Put(statstore.TimePoint{ 211 Timestamp: now.Add(23 * time.Hour), 212 Value: uint64(21000), 213 })) 214 assert.NoError(ds.Put(statstore.TimePoint{ 215 Timestamp: now.Add(23 * time.Hour).Add(30 * time.Minute), 216 Value: uint64(700), 217 })) 218 219 // 25th hour stored, current last hour of the DayStore 220 assert.NoError(ds.Put(statstore.TimePoint{ 221 Timestamp: now.Add(24 * time.Hour), 222 Value: uint64(900), 223 })) 224 assert.NoError(ds.Put(statstore.TimePoint{ 225 Timestamp: now.Add(24 * time.Hour).Add(30 * time.Minute), 226 Value: uint64(1000), 227 })) 228 229 // 26th hour 230 assert.NoError(ds.Put(statstore.TimePoint{ 231 Timestamp: now.Add(25 * time.Hour), 232 Value: uint64(100), 233 })) 234 assert.NoError(ds.Put(statstore.TimePoint{ 235 Timestamp: now.Add(25 * time.Hour).Add(30 * time.Minute), 236 Value: uint64(100), 237 })) 238 239 // Full-Day Invocations. 240 // The DayStore has rewinded by one hour already 241 avg, err = ds.Average() 242 assert.NoError(err) 243 assert.Equal(avg, uint64(1108)) 244 245 max, err = ds.Max() 246 assert.NoError(err) 247 assert.Equal(max, uint64(21000)) 248 249 nf, err = ds.NinetyFifth() 250 assert.NoError(err) 251 assert.Equal(nf, uint64(21000)) 252 253 // Rewind once more. 254 assert.NoError(ds.Put(statstore.TimePoint{ 255 Timestamp: now.Add(26 * time.Hour), 256 Value: uint64(5000), 257 })) 258 assert.NoError(ds.Put(statstore.TimePoint{ 259 Timestamp: now.Add(26 * time.Hour).Add(30 * time.Minute), 260 Value: uint64(5000), 261 })) 262 263 // Invocations after second rewind 264 // Drop in average because of the 26th hour having a value of 100 265 nf, err = ds.NinetyFifth() 266 assert.NoError(err) 267 assert.Equal(nf, uint64(21000)) 268 269 max, err = ds.Max() 270 assert.NoError(err) 271 assert.Equal(max, uint64(21000)) 272 273 avg, err = ds.Average() 274 assert.NoError(err) 275 assert.Equal(avg, uint64(1097)) 276 277 // Assert validity of the cache 278 avg, err = ds.Average() 279 assert.NoError(err) 280 assert.Equal(avg, uint64(1097)) 281 282 max, err = ds.Max() 283 assert.NoError(err) 284 assert.Equal(max, uint64(21000)) 285 286 nf, err = ds.NinetyFifth() 287 assert.NoError(err) 288 assert.Equal(nf, uint64(21000)) 289 290 // Get Invocation, a full hour should be available plus the lastPut 291 res := ds.Hour.Get(time.Time{}, time.Time{}) 292 assert.Len(res, 61) 293 }