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  }