github.com/mrgossett/heapster@v0.18.2/store/statstore/stat_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  package statstore
    15  
    16  import (
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/stretchr/testify/assert"
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  // TestLast tests all flows of the Last method.
    25  func TestLast(t *testing.T) {
    26  	// epsilon: 10, resolution: 1 minute, total: 1 hour, no percentiles
    27  	store := NewStatStore(10, time.Minute, 60, []float64{})
    28  	assert := assert.New(t)
    29  	now := time.Now().Truncate(time.Minute)
    30  
    31  	// Invocation with nothing in the StatStore - no result
    32  	last, max, err := store.Last()
    33  	assert.Error(err)
    34  	assert.Equal(last, TimePoint{})
    35  	assert.Equal(max, uint64(0))
    36  
    37  	// Put 5 Points in the same minute. Average: 10029, Max: 50000
    38  	assert.NoError(store.Put(TimePoint{
    39  		Timestamp: now,
    40  		Value:     uint64(55),
    41  	}))
    42  	assert.NoError(store.Put(TimePoint{
    43  		Timestamp: now.Add(time.Second),
    44  		Value:     uint64(1),
    45  	}))
    46  	assert.NoError(store.Put(TimePoint{
    47  		Timestamp: now,
    48  		Value:     uint64(12),
    49  	}))
    50  	assert.NoError(store.Put(TimePoint{
    51  		Timestamp: now.Add(1 * time.Second),
    52  		Value:     uint64(77),
    53  	}))
    54  	assert.NoError(store.Put(TimePoint{
    55  		Timestamp: now.Add(1 * time.Second),
    56  		Value:     uint64(50000),
    57  	}))
    58  
    59  	// Put one point in a previous minute, should be ignored.
    60  	assert.Error(store.Put(TimePoint{
    61  		Timestamp: now.Add(-2 * time.Minute),
    62  		Value:     uint64(100000),
    63  	}))
    64  
    65  	last, max, err = store.Last()
    66  	assert.NoError(err)
    67  	assert.Equal(last.Timestamp, now)
    68  	assert.Equal(last.Value, uint64(10029))
    69  	assert.Equal(max, uint64(50000))
    70  
    71  	// Put one value from the next minute
    72  	assert.NoError(store.Put(TimePoint{
    73  		Timestamp: now.Add(time.Minute),
    74  		Value:     uint64(92),
    75  	}))
    76  
    77  	// Invocation where Last is a "fake" point added because of a missed resolution.
    78  	last, max, err = store.Last()
    79  	assert.NoError(err)
    80  	assert.Equal(last.Timestamp, now.Add(time.Minute))
    81  	assert.Equal(last.Value, uint64(92))
    82  	assert.Equal(max, uint64(92))
    83  
    84  	// Put one value from two more minutes later
    85  	assert.NoError(store.Put(TimePoint{
    86  		Timestamp: now.Add(3 * time.Minute),
    87  		Value:     uint64(10000),
    88  	}))
    89  
    90  	last, max, err = store.Last()
    91  	assert.NoError(err)
    92  	assert.Equal(last.Timestamp, now.Add(3*time.Minute))
    93  	assert.Equal(last.Value, uint64(10000))
    94  	assert.Equal(max, uint64(10000))
    95  }
    96  
    97  // TestMax tests all flows of the Max method.
    98  func TestMax(t *testing.T) {
    99  	// epsilon: 50, resolution: 1 minute, total: 5 minutes, no percentiles
   100  	store := NewStatStore(50, time.Minute, 5, []float64{})
   101  	assert := assert.New(t)
   102  	now := time.Now().Truncate(time.Minute)
   103  
   104  	// Invocation with nothing in the StatStore - no result
   105  	max, err := store.Max()
   106  	assert.Error(err)
   107  	assert.Equal(max, uint64(0))
   108  
   109  	// Put 3 Points in the same minute.  Max: 88
   110  	assert.NoError(store.Put(TimePoint{
   111  		Timestamp: now,
   112  		Value:     uint64(55),
   113  	}))
   114  	assert.NoError(store.Put(TimePoint{
   115  		Timestamp: now.Add(time.Second),
   116  		Value:     uint64(88),
   117  	}))
   118  	assert.NoError(store.Put(TimePoint{
   119  		Timestamp: now,
   120  		Value:     uint64(21),
   121  	}))
   122  
   123  	// Invocation with elements only in lastPut
   124  	max, err = store.Max()
   125  	assert.Error(err)
   126  	assert.Equal(max, uint64(0))
   127  
   128  	// Put 1 Point in the next minute.
   129  	assert.NoError(store.Put(TimePoint{
   130  		Timestamp: now.Add(time.Minute),
   131  		Value:     uint64(199),
   132  	}))
   133  
   134  	// Invocation where the previous minute is now accessible
   135  	max, err = store.Max()
   136  	assert.NoError(err)
   137  	assert.Equal(max, uint64(199))
   138  
   139  	// Put 1 Point in the next minute.
   140  	assert.NoError(store.Put(TimePoint{
   141  		Timestamp: now.Add(2 * time.Minute),
   142  		Value:     uint64(22),
   143  	}))
   144  
   145  	// Put one point in a previous minute, should be ignored.
   146  	assert.Error(store.Put(TimePoint{
   147  		Timestamp: now,
   148  		Value:     uint64(100000),
   149  	}))
   150  
   151  	// Put one point in the next minute, same bucket as before.
   152  	assert.NoError(store.Put(TimePoint{
   153  		Timestamp: now.Add(2 * time.Minute),
   154  		Value:     uint64(40),
   155  	}))
   156  
   157  	// Put one point in the next minute.
   158  	// Even though the max is greater, this minute is currently in lastPut,
   159  	// so it is excluded from the max.
   160  	assert.NoError(store.Put(TimePoint{
   161  		Timestamp: now.Add(3 * time.Minute),
   162  		Value:     uint64(511),
   163  	}))
   164  
   165  	// Invocation with three minutes in three different buckets
   166  	max, err = store.Max()
   167  	assert.NoError(err)
   168  	assert.Equal(max, uint64(511))
   169  
   170  	// Put one value from the next minute
   171  	assert.NoError(store.Put(TimePoint{
   172  		Timestamp: now.Add(4 * time.Minute),
   173  		Value:     uint64(550),
   174  	}))
   175  
   176  	// Invocation with four minutes
   177  	max, err = store.Max()
   178  	assert.NoError(err)
   179  	assert.Equal(max, uint64(550))
   180  
   181  	// Call again to assert validity of the cache
   182  	max, err = store.Max()
   183  	assert.NoError(err)
   184  	assert.Equal(max, uint64(550))
   185  }
   186  
   187  // TestGet tests all flows of the Get method.
   188  // Seven resolutions are stored in total, causing two rewinds.
   189  func TestGet(t *testing.T) {
   190  	// epsilon: 100, resolution: 1 minute, total: 5 minutes, no percentiles
   191  	store := NewStatStore(100, time.Minute, 5, []float64{})
   192  	assert := assert.New(t)
   193  	require := require.New(t)
   194  	now := time.Now().Truncate(time.Minute)
   195  	zeroTime := time.Time{}
   196  
   197  	// Invocation with nothing in the StatStore - empty result
   198  	res := store.Get(zeroTime, zeroTime)
   199  	assert.Len(res, 0)
   200  
   201  	// Put 3 Points in the same minute.  Average: 150, Max: 190
   202  	assert.NoError(store.Put(TimePoint{
   203  		Timestamp: now,
   204  		Value:     uint64(120),
   205  	}))
   206  	assert.NoError(store.Put(TimePoint{
   207  		Timestamp: now,
   208  		Value:     uint64(190),
   209  	}))
   210  	assert.NoError(store.Put(TimePoint{
   211  		Timestamp: now.Add(time.Second),
   212  		Value:     uint64(140),
   213  	}))
   214  
   215  	// Put 1 Point in the next minute.
   216  	assert.NoError(store.Put(TimePoint{
   217  		Timestamp: now.Add(time.Minute),
   218  		Value:     uint64(599),
   219  	}))
   220  
   221  	// Invocation with one element in the StatStore
   222  	res = store.Get(zeroTime, zeroTime)
   223  	require.Len(res, 2)
   224  	assert.Equal(res[0], TimePoint{
   225  		Timestamp: now.Add(time.Minute),
   226  		Value:     uint64(599),
   227  	})
   228  	assert.Equal(res[1], TimePoint{
   229  		Timestamp: now,
   230  		Value:     uint64(200),
   231  	})
   232  	// Put 1 Point in the next minute.
   233  	assert.NoError(store.Put(TimePoint{
   234  		Timestamp: now.Add(2 * time.Minute),
   235  		Value:     uint64(22),
   236  	}))
   237  
   238  	// Put one point in a previous minute, should be ignored.
   239  	assert.Error(store.Put(TimePoint{
   240  		Timestamp: now,
   241  		Value:     uint64(100000),
   242  	}))
   243  
   244  	// Invocation with two elements in the StatStore
   245  	res = store.Get(zeroTime, zeroTime)
   246  	require.Len(res, 3)
   247  	assert.Equal(res[0], TimePoint{
   248  		Timestamp: now.Add(2 * time.Minute),
   249  		Value:     uint64(22),
   250  	})
   251  	assert.Equal(res[1], TimePoint{
   252  		Timestamp: now.Add(time.Minute),
   253  		Value:     uint64(600),
   254  	})
   255  	assert.Equal(res[2], TimePoint{
   256  		Timestamp: now,
   257  		Value:     uint64(200),
   258  	})
   259  
   260  	// Put one point in the next minute, same bucket as before.
   261  	assert.NoError(store.Put(TimePoint{
   262  		Timestamp: now.Add(2 * time.Minute),
   263  		Value:     uint64(110),
   264  	}))
   265  
   266  	// Put one point in the next minute.
   267  	assert.NoError(store.Put(TimePoint{
   268  		Timestamp: now.Add(3 * time.Minute),
   269  		Value:     uint64(511),
   270  	}))
   271  
   272  	// Invocation with three elements in the StatStore
   273  	res = store.Get(zeroTime, zeroTime)
   274  	require.Len(res, 4)
   275  	assert.Equal(res[0], TimePoint{
   276  		Timestamp: now.Add(3 * time.Minute),
   277  		Value:     uint64(511),
   278  	})
   279  	assert.Equal(res[1], TimePoint{
   280  		Timestamp: now.Add(2 * time.Minute),
   281  		Value:     uint64(100),
   282  	})
   283  	assert.Equal(res[2], TimePoint{
   284  		Timestamp: now.Add(time.Minute),
   285  		Value:     uint64(600),
   286  	})
   287  	assert.Equal(res[3], TimePoint{
   288  		Timestamp: now,
   289  		Value:     uint64(200),
   290  	})
   291  
   292  	// Put one value from the next minute. Same bucket as the previous minute
   293  	assert.NoError(store.Put(TimePoint{
   294  		Timestamp: now.Add(4 * time.Minute),
   295  		Value:     uint64(540),
   296  	}))
   297  
   298  	// Put one value from the next minute. Same bucket as the previous minute
   299  	assert.NoError(store.Put(TimePoint{
   300  		Timestamp: now.Add(5 * time.Minute),
   301  		Value:     uint64(550),
   302  	}))
   303  
   304  	// Invocation with a full StatStore and a multi-resolution bucket
   305  	res = store.Get(zeroTime, zeroTime)
   306  	require.Len(res, 6)
   307  	assert.Equal(res[0], TimePoint{
   308  		Timestamp: now.Add(5 * time.Minute),
   309  		Value:     uint64(550),
   310  	})
   311  	assert.Equal(res[1], TimePoint{
   312  		Timestamp: now.Add(4 * time.Minute),
   313  		Value:     uint64(600),
   314  	})
   315  	assert.Equal(res[2], TimePoint{
   316  		Timestamp: now.Add(3 * time.Minute),
   317  		Value:     uint64(600),
   318  	})
   319  	assert.Equal(res[3], TimePoint{
   320  		Timestamp: now.Add(2 * time.Minute),
   321  		Value:     uint64(100),
   322  	})
   323  	assert.Equal(res[4], TimePoint{
   324  		Timestamp: now.Add(time.Minute),
   325  		Value:     uint64(600),
   326  	})
   327  	assert.Equal(res[5], TimePoint{
   328  		Timestamp: now,
   329  		Value:     uint64(200),
   330  	})
   331  
   332  	// Put one value from the next minute. Different bucket than the previous minute
   333  	// This Put should cause a rewind for the first minute that was stored
   334  	assert.NoError(store.Put(TimePoint{
   335  		Timestamp: now.Add(6 * time.Minute),
   336  		Value:     uint64(750),
   337  	}))
   338  
   339  	// Invocation after one rewind
   340  	res = store.Get(zeroTime, zeroTime)
   341  	require.Len(res, 6)
   342  	assert.Equal(res[0], TimePoint{
   343  		Timestamp: now.Add(6 * time.Minute),
   344  		Value:     uint64(750),
   345  	})
   346  	assert.Equal(res[1], TimePoint{
   347  		Timestamp: now.Add(5 * time.Minute),
   348  		Value:     uint64(600),
   349  	})
   350  	assert.Equal(res[2], TimePoint{
   351  		Timestamp: now.Add(4 * time.Minute),
   352  		Value:     uint64(600),
   353  	})
   354  	assert.Equal(res[3], TimePoint{
   355  		Timestamp: now.Add(3 * time.Minute),
   356  		Value:     uint64(600),
   357  	})
   358  	assert.Equal(res[4], TimePoint{
   359  		Timestamp: now.Add(2 * time.Minute),
   360  		Value:     uint64(100),
   361  	})
   362  	assert.Equal(res[5], TimePoint{
   363  		Timestamp: now.Add(time.Minute),
   364  		Value:     uint64(600),
   365  	})
   366  
   367  	// Cause one more rewind
   368  	assert.NoError(store.Put(TimePoint{
   369  		Timestamp: now.Add(7 * time.Minute),
   370  		Value:     uint64(998),
   371  	}))
   372  
   373  	// Invocation after second rewind
   374  	res = store.Get(zeroTime, zeroTime)
   375  	require.Len(res, 6)
   376  	assert.Equal(res[0], TimePoint{
   377  		Timestamp: now.Add(7 * time.Minute),
   378  		Value:     uint64(998),
   379  	})
   380  	assert.Equal(res[1], TimePoint{
   381  		Timestamp: now.Add(6 * time.Minute),
   382  		Value:     uint64(800),
   383  	})
   384  	assert.Equal(res[2], TimePoint{
   385  		Timestamp: now.Add(5 * time.Minute),
   386  		Value:     uint64(600),
   387  	})
   388  	assert.Equal(res[3], TimePoint{
   389  		Timestamp: now.Add(4 * time.Minute),
   390  		Value:     uint64(600),
   391  	})
   392  	assert.Equal(res[4], TimePoint{
   393  		Timestamp: now.Add(3 * time.Minute),
   394  		Value:     uint64(600),
   395  	})
   396  	assert.Equal(res[5], TimePoint{
   397  		Timestamp: now.Add(2 * time.Minute),
   398  		Value:     uint64(100),
   399  	})
   400  
   401  	// Invocation with start after end
   402  	res = store.Get(now.Add(10*time.Minute), now)
   403  	assert.Len(res, 0)
   404  
   405  	// Invocation with mid-length start-end range
   406  	res = store.Get(now.Add(3*time.Minute), now.Add(5*time.Minute))
   407  	assert.Len(res, 3)
   408  	assert.Equal(res[0], TimePoint{
   409  		Timestamp: now.Add(5 * time.Minute),
   410  		Value:     uint64(600),
   411  	})
   412  	assert.Equal(res[1], TimePoint{
   413  		Timestamp: now.Add(4 * time.Minute),
   414  		Value:     uint64(600),
   415  	})
   416  	assert.Equal(res[2], TimePoint{
   417  		Timestamp: now.Add(3 * time.Minute),
   418  		Value:     uint64(600),
   419  	})
   420  
   421  	// Invocation with full-length start-end range.
   422  	// The first TimePoint is ignored, as it is equal to start
   423  	res = store.Get(now.Add(2*time.Minute), now.Add(6*time.Minute))
   424  	assert.Len(res, 4)
   425  	assert.Equal(res[0], TimePoint{
   426  		Timestamp: now.Add(6 * time.Minute),
   427  		Value:     uint64(800),
   428  	})
   429  	assert.Equal(res[1], TimePoint{
   430  		Timestamp: now.Add(5 * time.Minute),
   431  		Value:     uint64(600),
   432  	})
   433  	assert.Equal(res[2], TimePoint{
   434  		Timestamp: now.Add(4 * time.Minute),
   435  		Value:     uint64(600),
   436  	})
   437  	assert.Equal(res[3], TimePoint{
   438  		Timestamp: now.Add(3 * time.Minute),
   439  		Value:     uint64(600),
   440  	})
   441  
   442  	// Invocation with start-end range outside of the scope of values.
   443  	res = store.Get(now.Add(-2*time.Minute), now.Add(time.Minute))
   444  	assert.Len(res, 0)
   445  
   446  	// Put one value from 10 minutes since the last Put.
   447  	// This Put should force the entire StatStore to be filled with 1000.
   448  	assert.NoError(store.Put(TimePoint{
   449  		Timestamp: now.Add(25 * time.Minute),
   450  		Value:     uint64(1500),
   451  	}))
   452  
   453  	// Invocation after a future Put. Everything in between is placed in the last bucket
   454  	res = store.Get(zeroTime, zeroTime)
   455  	require.Len(res, 6)
   456  	assert.Equal(res[0], TimePoint{
   457  		Timestamp: now.Add(25 * time.Minute),
   458  		Value:     uint64(1500),
   459  	})
   460  	assert.Equal(res[1], TimePoint{
   461  		Timestamp: now.Add(24 * time.Minute),
   462  		Value:     uint64(1000),
   463  	})
   464  	assert.Equal(res[2], TimePoint{
   465  		Timestamp: now.Add(23 * time.Minute),
   466  		Value:     uint64(1000),
   467  	})
   468  	assert.Equal(res[3], TimePoint{
   469  		Timestamp: now.Add(22 * time.Minute),
   470  		Value:     uint64(1000),
   471  	})
   472  	assert.Equal(res[4], TimePoint{
   473  		Timestamp: now.Add(21 * time.Minute),
   474  		Value:     uint64(1000),
   475  	})
   476  	assert.Equal(res[5], TimePoint{
   477  		Timestamp: now.Add(20 * time.Minute),
   478  		Value:     uint64(1000),
   479  	})
   480  
   481  }
   482  
   483  // TestAverage tests all flows of the Average method.
   484  func TestAverage(t *testing.T) {
   485  	// epsilon: 100, resolution: 1 minute, total: 5 minutes, no percentiles
   486  	store := NewStatStore(100, time.Minute, 5, []float64{})
   487  	assert := assert.New(t)
   488  	now := time.Now().Truncate(time.Minute)
   489  
   490  	// Invocation with nothing in the StatStore - error
   491  	avg, err := store.Average()
   492  	assert.Error(err)
   493  	assert.Equal(avg, uint64(0))
   494  
   495  	// Populate StatStore
   496  	assert.NoError(store.Put(TimePoint{
   497  		Timestamp: now,
   498  		Value:     uint64(190),
   499  	}))
   500  
   501  	// Put 1 Point in the next minute. Same bucket (200)
   502  	assert.NoError(store.Put(TimePoint{
   503  		Timestamp: now.Add(time.Minute),
   504  		Value:     uint64(199),
   505  	}))
   506  
   507  	// Invocation with one element in the StatStore
   508  	avg, err = store.Average()
   509  	assert.NoError(err)
   510  	assert.Equal(avg, 200)
   511  
   512  	// Put one Point in the next minute. Same bucket (200)
   513  	assert.NoError(store.Put(TimePoint{
   514  		Timestamp: now.Add(2 * time.Minute),
   515  		Value:     uint64(120),
   516  	}))
   517  
   518  	// Put one point in the next minute. Different bucket (600)
   519  	assert.NoError(store.Put(TimePoint{
   520  		Timestamp: now.Add(3 * time.Minute),
   521  		Value:     uint64(511),
   522  	}))
   523  
   524  	// Put one point in the next minute. Same bucket (600)
   525  	assert.NoError(store.Put(TimePoint{
   526  		Timestamp: now.Add(4 * time.Minute),
   527  		Value:     uint64(599),
   528  	}))
   529  
   530  	// Put one point in the next minute. StatStore is full now
   531  	assert.NoError(store.Put(TimePoint{
   532  		Timestamp: now.Add(5 * time.Minute),
   533  		Value:     uint64(1081),
   534  	}))
   535  
   536  	// Invocation with five elements in the StatStore
   537  	avg, err = store.Average()
   538  	assert.NoError(err)
   539  	assert.Equal(avg, uint64(360))
   540  
   541  	// Call again to assert validity of the cache
   542  	avg, err = store.Average()
   543  	assert.NoError(err)
   544  	assert.Equal(avg, uint64(360))
   545  }
   546  
   547  // TestPercentile tests all flows of the Percentile method.
   548  func TestPercentile(t *testing.T) {
   549  	// epsilon: 50, resolution: 1 minute, total: 5 minutes, two percentiles
   550  	store := NewStatStore(50, time.Minute, 5, []float64{0.5, 0.95})
   551  	assert := assert.New(t)
   552  	now := time.Now().Truncate(time.Minute)
   553  
   554  	// Invocation with nothing in the StatStore - error
   555  	pc, err := store.Percentile(0.95)
   556  	assert.Error(err)
   557  	assert.Equal(pc, uint64(0))
   558  
   559  	// Populate StatStore
   560  	assert.NoError(store.Put(TimePoint{
   561  		Timestamp: now,
   562  		Value:     uint64(190),
   563  	}))
   564  
   565  	// Put 1 Point in the next minute. Same bucket (200)
   566  	assert.NoError(store.Put(TimePoint{
   567  		Timestamp: now.Add(time.Minute),
   568  		Value:     uint64(199),
   569  	}))
   570  
   571  	// Invocation with an unsupported percentile
   572  	pc, err = store.Percentile(0.2)
   573  	assert.Error(err)
   574  	assert.Equal(pc, uint64(0))
   575  
   576  	// Invocation with one element in the StatStore
   577  	pc, err = store.Percentile(0.5)
   578  	assert.NoError(err)
   579  	assert.Equal(pc, 200)
   580  	pc, err = store.Percentile(0.95)
   581  	assert.NoError(err)
   582  	assert.Equal(pc, 200)
   583  
   584  	// Put one Point in the next minute. Different bucket (550)
   585  	assert.NoError(store.Put(TimePoint{
   586  		Timestamp: now.Add(2 * time.Minute),
   587  		Value:     uint64(532),
   588  	}))
   589  
   590  	// Put one point in the next minute. Same bucket (550)
   591  	assert.NoError(store.Put(TimePoint{
   592  		Timestamp: now.Add(3 * time.Minute),
   593  		Value:     uint64(511),
   594  	}))
   595  
   596  	// Put one point in the next minute. Different bucket (50)
   597  	assert.NoError(store.Put(TimePoint{
   598  		Timestamp: now.Add(4 * time.Minute),
   599  		Value:     uint64(30),
   600  	}))
   601  
   602  	// Put one point in the next minute. StatStore is full now
   603  	assert.NoError(store.Put(TimePoint{
   604  		Timestamp: now.Add(5 * time.Minute),
   605  		Value:     uint64(50),
   606  	}))
   607  
   608  	// Invocation with five elements in the StatStore
   609  	pc, err = store.Percentile(0.5)
   610  	assert.NoError(err)
   611  	assert.Equal(pc, uint64(200))
   612  	pc, err = store.Percentile(0.95)
   613  	assert.NoError(err)
   614  	assert.Equal(pc, uint64(550))
   615  
   616  	// Call again to assert validity of the cache
   617  	pc, err = store.Percentile(0.5)
   618  	assert.NoError(err)
   619  	assert.Equal(pc, uint64(200))
   620  	pc, err = store.Percentile(0.95)
   621  	assert.NoError(err)
   622  	assert.Equal(pc, uint64(550))
   623  }
   624  
   625  // TestIsEmpty tests all flows of the IsEmpty method.
   626  func TestIsEmpty(t *testing.T) {
   627  	// epsilon: 50, resolution: 1 minute, total: 5 minutes, no percentiles
   628  	store := NewStatStore(50, time.Minute, 5, []float64{})
   629  	assert := assert.New(t)
   630  	now := time.Now().Truncate(time.Minute)
   631  
   632  	// Invocation with nothing in the StatStore
   633  	assert.True(store.IsEmpty())
   634  
   635  	// Put one point in the StatStore.
   636  	assert.NoError(store.Put(TimePoint{
   637  		Timestamp: now,
   638  		Value:     uint64(30),
   639  	}))
   640  
   641  	// Invocation with values only in the lastPut field.
   642  	assert.True(store.IsEmpty())
   643  
   644  	// Put one point in the next minute. StatStore is not empty now
   645  	assert.NoError(store.Put(TimePoint{
   646  		Timestamp: now.Add(1 * time.Minute),
   647  		Value:     uint64(50),
   648  	}))
   649  
   650  	// Invocation with a value in the StatStore
   651  	assert.False(store.IsEmpty())
   652  }
   653  
   654  // TestMaxSize tests all flows of the MaxSize method.
   655  func TestMaxSize(t *testing.T) {
   656  	assert := assert.New(t)
   657  
   658  	// Invocation with a StatStore of 5 minutes, 1 min resolution.
   659  	store := NewStatStore(50, time.Minute, 5, []float64{})
   660  	assert.Equal(5*time.Minute, store.MaxSize())
   661  
   662  	// Invocation with a StatStore of 1 hour, 5 min resolution.
   663  	store = NewStatStore(50, 5*time.Minute, 12, []float64{})
   664  	assert.Equal(time.Hour, store.MaxSize())
   665  
   666  	// Invocation with a StatStore of 1 hour, 1 hour resolution.
   667  	store = NewStatStore(50, time.Hour, 1, []float64{})
   668  	assert.Equal(time.Hour, store.MaxSize())
   669  
   670  	// Invocation with a StatStore of 1 minute, 10 second resolution.
   671  	store = NewStatStore(50, 10*time.Second, 6, []float64{})
   672  	assert.Equal(time.Minute, store.MaxSize())
   673  }