github.com/mrgossett/heapster@v0.18.2/model/util_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 model
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  
    23  	"k8s.io/heapster/store/daystore"
    24  	"k8s.io/heapster/store/statstore"
    25  )
    26  
    27  // TestLatestsTimestamp tests all flows of latestTimeStamp.
    28  func TestLatestTimestamp(t *testing.T) {
    29  	assert := assert.New(t)
    30  	past := time.Unix(1434212566, 0)
    31  	future := time.Unix(1434212800, 0)
    32  	assert.Equal(latestTimestamp(past, future), future)
    33  	assert.Equal(latestTimestamp(future, past), future)
    34  	assert.Equal(latestTimestamp(future, future), future)
    35  }
    36  
    37  // TestNewInfoType tests both flows of the InfoType constructor.
    38  func TestNewInfoType(t *testing.T) {
    39  	var (
    40  		metrics = make(map[string]*daystore.DayStore)
    41  		labels  = make(map[string]string)
    42  		context = make(map[string]*statstore.TimePoint)
    43  	)
    44  	metrics["test"] = newDayStore()
    45  	labels["name"] = "test"
    46  	assert := assert.New(t)
    47  
    48  	// Invocation with no parameters
    49  	new_infotype := newInfoType(nil, nil, nil)
    50  	assert.Empty(new_infotype.Metrics)
    51  	assert.Empty(new_infotype.Labels)
    52  
    53  	// Invocation with all parameters
    54  	new_infotype = newInfoType(metrics, labels, context)
    55  	assert.Equal(new_infotype.Metrics, metrics)
    56  	assert.Equal(new_infotype.Labels, labels)
    57  	assert.Equal(new_infotype.Context, context)
    58  }
    59  
    60  // TestAddContainerToMap tests all the flows of addContainerToMap.
    61  func TestAddContainerToMap(t *testing.T) {
    62  	new_map := make(map[string]*ContainerInfo)
    63  
    64  	// First Call: A new ContainerInfo is created
    65  	cinfo := addContainerToMap("new_container", new_map)
    66  
    67  	assert := assert.New(t)
    68  	assert.NotNil(cinfo)
    69  	assert.NotNil(cinfo.Metrics)
    70  	assert.NotNil(cinfo.Labels)
    71  	assert.Equal(new_map["new_container"], cinfo)
    72  
    73  	// Second Call: A ContainerInfo is already available for that key
    74  	new_cinfo := addContainerToMap("new_container", new_map)
    75  	assert.Equal(new_map["new_container"], new_cinfo)
    76  	assert.Equal(cinfo, new_cinfo)
    77  }
    78  
    79  // TestAddTimePoints tests all flows of addTimePoints.
    80  func TestAddTimePoints(t *testing.T) {
    81  	var (
    82  		tp1 = statstore.TimePoint{
    83  			Timestamp: time.Unix(1434212800, 0),
    84  			Value:     uint64(500),
    85  		}
    86  		tp2 = statstore.TimePoint{
    87  			Timestamp: time.Unix(1434212805, 0),
    88  			Value:     uint64(700),
    89  		}
    90  		assert = assert.New(t)
    91  	)
    92  	new_tp := addTimePoints(tp1, tp2)
    93  	assert.Equal(new_tp.Timestamp, tp2.Timestamp)
    94  	assert.Equal(new_tp.Value, tp1.Value+tp2.Value)
    95  }
    96  
    97  // TestPopTPSlice tests all flows of PopTPSlice.
    98  func TestPopTPSlice(t *testing.T) {
    99  	var (
   100  		tp1 = statstore.TimePoint{
   101  			Timestamp: time.Now(),
   102  			Value:     uint64(3),
   103  		}
   104  		tp2 = statstore.TimePoint{
   105  			Timestamp: time.Now(),
   106  			Value:     uint64(4),
   107  		}
   108  		assert = assert.New(t)
   109  	)
   110  
   111  	// Invocations with no popped element
   112  	assert.Nil(popTPSlice(nil))
   113  	assert.Nil(popTPSlice(&[]statstore.TimePoint{}))
   114  
   115  	// Invocation with one element
   116  	tps := []statstore.TimePoint{tp1}
   117  	res := popTPSlice(&tps)
   118  	assert.Equal(*res, tp1)
   119  	assert.Empty(tps)
   120  
   121  	// Invocation with two elements
   122  	tps = []statstore.TimePoint{tp1, tp2}
   123  	res = popTPSlice(&tps)
   124  	assert.Equal(*res, tp1)
   125  	assert.Len(tps, 1)
   126  	assert.Equal(tps[0], tp2)
   127  }
   128  
   129  // TestAddMatchingTimeseries tests the normal flow of addMatchingTimeseries.
   130  func TestAddMatchingTimeseries(t *testing.T) {
   131  	var (
   132  		tp11 = statstore.TimePoint{
   133  			Timestamp: time.Unix(1434212800, 0),
   134  			Value:     uint64(4),
   135  		}
   136  		tp21 = statstore.TimePoint{
   137  			Timestamp: time.Unix(1434212805, 0),
   138  			Value:     uint64(9),
   139  		}
   140  		tp31 = statstore.TimePoint{
   141  			Timestamp: time.Unix(1434212807, 0),
   142  			Value:     uint64(10),
   143  		}
   144  		tp41 = statstore.TimePoint{
   145  			Timestamp: time.Unix(1434212850, 0),
   146  			Value:     uint64(533),
   147  		}
   148  
   149  		tp12 = statstore.TimePoint{
   150  			Timestamp: time.Unix(1434212800, 0),
   151  			Value:     uint64(4),
   152  		}
   153  		tp22 = statstore.TimePoint{
   154  			Timestamp: time.Unix(1434212806, 0),
   155  			Value:     uint64(8),
   156  		}
   157  		tp32 = statstore.TimePoint{
   158  			Timestamp: time.Unix(1434212807, 0),
   159  			Value:     uint64(11),
   160  		}
   161  		tp42 = statstore.TimePoint{
   162  			Timestamp: time.Unix(1434212851, 0),
   163  			Value:     uint64(534),
   164  		}
   165  		tp52 = statstore.TimePoint{
   166  			Timestamp: time.Unix(1434212859, 0),
   167  			Value:     uint64(538),
   168  		}
   169  		assert = assert.New(t)
   170  	)
   171  	// Invocation with 1+1 data points
   172  	tps1 := []statstore.TimePoint{tp11}
   173  	tps2 := []statstore.TimePoint{tp12}
   174  	new_ts := addMatchingTimeseries(tps1, tps2)
   175  	assert.Len(new_ts, 1)
   176  	assert.Equal(new_ts[0].Timestamp, tp11.Timestamp)
   177  	assert.Equal(new_ts[0].Value, uint64(8))
   178  
   179  	// Invocation with 3+1 data points
   180  	tps1 = []statstore.TimePoint{tp52, tp42, tp11}
   181  	tps2 = []statstore.TimePoint{tp12}
   182  	new_ts = addMatchingTimeseries(tps1, tps2)
   183  	assert.Len(new_ts, 3)
   184  	assert.Equal(new_ts[0].Timestamp, tp52.Timestamp)
   185  	assert.Equal(new_ts[0].Value, tp52.Value+tp12.Value)
   186  	assert.Equal(new_ts[1].Timestamp, tp42.Timestamp)
   187  	assert.Equal(new_ts[1].Value, tp42.Value+tp12.Value)
   188  	assert.Equal(new_ts[2].Timestamp, tp11.Timestamp)
   189  	assert.Equal(new_ts[2].Value, tp11.Value+tp12.Value)
   190  
   191  	// Invocation with 4+5 data points
   192  	tps1 = []statstore.TimePoint{tp41, tp31, tp21, tp11}
   193  	tps2 = []statstore.TimePoint{tp52, tp42, tp32, tp22, tp12}
   194  	new_ts = addMatchingTimeseries(tps1, tps2)
   195  	assert.Len(new_ts, 7)
   196  	assert.Equal(new_ts[0].Timestamp, tp52.Timestamp)
   197  	assert.Equal(new_ts[0].Value, tp52.Value+tp41.Value)
   198  
   199  	assert.Equal(new_ts[1].Timestamp, tp42.Timestamp)
   200  	assert.Equal(new_ts[1].Value, tp42.Value+tp41.Value)
   201  
   202  	assert.Equal(new_ts[2].Timestamp, tp41.Timestamp)
   203  	assert.Equal(new_ts[2].Value, tp41.Value+tp32.Value)
   204  
   205  	assert.Equal(new_ts[3].Timestamp, tp31.Timestamp)
   206  	assert.Equal(new_ts[3].Value, tp31.Value+tp32.Value)
   207  
   208  	assert.Equal(new_ts[4].Timestamp, tp22.Timestamp)
   209  	assert.Equal(new_ts[4].Value, tp22.Value+tp21.Value)
   210  
   211  	assert.Equal(new_ts[5].Timestamp, tp21.Timestamp)
   212  	assert.Equal(new_ts[5].Value, tp21.Value+tp12.Value)
   213  
   214  	assert.Equal(new_ts[6].Timestamp, tp11.Timestamp)
   215  	assert.Equal(new_ts[6].Value, tp11.Value+tp12.Value)
   216  }
   217  
   218  // TestAddMatchingTimeseriesEmpty tests the alternate flows of addMatchingTimeseries.
   219  // Three permutations of empty parameters are tested.
   220  func TestAddMatchingTimeseriesEmpty(t *testing.T) {
   221  	var (
   222  		tp12 = statstore.TimePoint{
   223  			Timestamp: time.Unix(1434212800, 0),
   224  			Value:     uint64(4),
   225  		}
   226  		tp22 = statstore.TimePoint{
   227  			Timestamp: time.Unix(1434212806, 0),
   228  			Value:     uint64(8),
   229  		}
   230  		tp32 = statstore.TimePoint{
   231  			Timestamp: time.Unix(1434212807, 0),
   232  			Value:     uint64(11),
   233  		}
   234  		assert = assert.New(t)
   235  	)
   236  	empty_tps := []statstore.TimePoint{}
   237  	tps := []statstore.TimePoint{tp12, tp22, tp32}
   238  
   239  	// First call: first argument is empty
   240  	new_ts := addMatchingTimeseries(empty_tps, tps)
   241  	assert.Equal(new_ts, tps)
   242  
   243  	// Second call: second argument is empty
   244  	new_ts = addMatchingTimeseries(tps, empty_tps)
   245  	assert.Equal(new_ts, tps)
   246  
   247  	// Third call: both arguments are empty
   248  	new_ts = addMatchingTimeseries(empty_tps, empty_tps)
   249  	assert.Equal(new_ts, empty_tps)
   250  }
   251  
   252  // TestInstantFromCumulativeMetric tests all the flows of instantFromCumulativeMetric.
   253  func TestInstantFromCumulativeMetric(t *testing.T) {
   254  	var (
   255  		new_value = uint64(15390000000000)
   256  		now       = time.Now().Round(time.Second)
   257  		assert    = assert.New(t)
   258  	)
   259  	afterNow := now.Add(3 * time.Second)
   260  	oldTP := &statstore.TimePoint{
   261  		Timestamp: now,
   262  		Value:     uint64(13851000000000),
   263  	}
   264  
   265  	// Invocation with nil prev argument
   266  	val, err := instantFromCumulativeMetric(new_value, afterNow, nil)
   267  	assert.Error(err)
   268  	assert.Equal(val, uint64(0))
   269  
   270  	// Invocation with regular arguments
   271  	val, err = instantFromCumulativeMetric(new_value, afterNow, oldTP)
   272  	assert.NoError(err)
   273  	assert.Equal(val, 513*1000)
   274  
   275  	// Second Invocation with regular arguments, prev TP has changed
   276  	newerVal := uint64(15900000000000)
   277  	val, err = instantFromCumulativeMetric(newerVal, afterNow.Add(time.Second), oldTP)
   278  	assert.NoError(err)
   279  	assert.Equal(val, 510*1000)
   280  
   281  }
   282  
   283  // TestGetStats tests all flows of getStats.
   284  func TestGetStats(t *testing.T) {
   285  	var (
   286  		metrics = make(map[string]*daystore.DayStore)
   287  		now     = time.Now()
   288  		assert  = assert.New(t)
   289  	)
   290  	// Populate a new DayStore with two hours of data
   291  	metrics[cpuLimit] = newDayStore()
   292  	for i := 0; i < 2; i++ {
   293  		metrics[cpuLimit].Put(statstore.TimePoint{
   294  			Timestamp: now.Add(time.Duration(i) * time.Hour),
   295  			Value:     uint64(50),
   296  		})
   297  		metrics[cpuLimit].Put(statstore.TimePoint{
   298  			Timestamp: now.Add(time.Duration(i) * time.Hour).Add(15 * time.Minute),
   299  			Value:     uint64(500),
   300  		})
   301  		metrics[cpuLimit].Put(statstore.TimePoint{
   302  			Timestamp: now.Add(time.Duration(i) * time.Hour).Add(30 * time.Minute),
   303  			Value:     uint64(2000),
   304  		})
   305  		metrics[cpuLimit].Put(statstore.TimePoint{
   306  			Timestamp: now.Add(time.Duration(i) * time.Hour).Add(45 * time.Minute),
   307  			Value:     uint64(1000),
   308  		})
   309  		metrics[cpuLimit].Put(statstore.TimePoint{
   310  			Timestamp: now.Add(time.Duration(i) * time.Hour).Add(59 * time.Minute),
   311  			Value:     uint64(15000),
   312  		})
   313  	}
   314  
   315  	// flushes the latest TimePoint to the last Hour
   316  	metrics[cpuLimit].Put(statstore.TimePoint{
   317  		Timestamp: now.Add(2 * time.Hour),
   318  		Value:     uint64(300000),
   319  	})
   320  
   321  	metrics[memUsage] = newDayStore()
   322  	metrics[memUsage].Put(statstore.TimePoint{
   323  		Timestamp: now,
   324  		Value:     uint64(50),
   325  	})
   326  	metrics[memUsage].Put(statstore.TimePoint{
   327  		Timestamp: now.Add(30 * time.Minute),
   328  		Value:     uint64(2000),
   329  	})
   330  	metrics[memUsage].Put(statstore.TimePoint{
   331  		// flushes the previous TimePoint to the last Hour
   332  		Timestamp: now.Add(60 * time.Minute),
   333  		Value:     uint64(1000),
   334  	})
   335  	info := newInfoType(metrics, nil, nil)
   336  
   337  	res := getStats(info)
   338  	assert.Len(res, 2)
   339  	assert.Equal(res[cpuLimit].Minute.Average, uint64(300000))
   340  	assert.Equal(res[cpuLimit].Minute.Max, uint64(300000))
   341  	assert.Equal(res[cpuLimit].Minute.NinetyFifth, uint64(300000))
   342  
   343  	assert.Equal(res[cpuLimit].Hour.Average, uint64(1133))
   344  	assert.Equal(res[cpuLimit].Hour.Max, uint64(300000))
   345  	assert.Equal(res[cpuLimit].Hour.NinetyFifth, uint64(2000))
   346  
   347  	assert.Equal(res[cpuLimit].Day.Max, res[cpuLimit].Hour.Max)
   348  	assert.Equal(res[cpuLimit].Day.Average, res[cpuLimit].Hour.Average)
   349  	assert.Equal(res[cpuLimit].Day.NinetyFifth, res[cpuLimit].Hour.NinetyFifth)
   350  }
   351  
   352  func TestEpsilonFromMetric(t *testing.T) {
   353  	assert := assert.New(t)
   354  	assert.Equal(cpuLimitEpsilon, epsilonFromMetric(cpuLimit))
   355  	assert.Equal(cpuUsageEpsilon, epsilonFromMetric(cpuUsage))
   356  	assert.Equal(memLimitEpsilon, epsilonFromMetric(memLimit))
   357  	assert.Equal(memUsageEpsilon, epsilonFromMetric(memUsage))
   358  	assert.Equal(memWorkingEpsilon, epsilonFromMetric(memWorking))
   359  	assert.Equal(fsLimitEpsilon, epsilonFromMetric(fsLimit))
   360  	assert.Equal(fsUsageEpsilon, epsilonFromMetric(fsUsage))
   361  	assert.Equal(defaultEpsilon, epsilonFromMetric("other"))
   362  }