github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/graphite/native/summarize_test.go (about)

     1  // Copyright (c) 2019 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package native
    22  
    23  import (
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/m3db/m3/src/query/graphite/common"
    28  	"github.com/m3db/m3/src/query/graphite/ts"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  func TestSummarize(t *testing.T) {
    35  	// NB(mmihic): Intentionally not aligned on summarization boundaries
    36  	var (
    37  		start  = time.Unix(131, 0)
    38  		end    = time.Unix(251, 0)
    39  		ctx    = common.NewContext(common.ContextOptions{Start: start, End: end})
    40  		vals   = ts.NewValues(ctx, 10000, 12)
    41  		series = []*ts.Series{ts.NewSeries(ctx, "foo", start, vals)}
    42  	)
    43  
    44  	defer ctx.Close()
    45  
    46  	// 0+1+2
    47  	// 3+4+5
    48  	// 6+7+8
    49  	// 9+10+11
    50  	for i := 0; i < vals.Len(); i++ {
    51  		vals.SetValueAt(i, float64(i))
    52  	}
    53  
    54  	tests := []struct {
    55  		name          string
    56  		interval      string
    57  		fname         string
    58  		alignToFrom   bool
    59  		expectedStart time.Time
    60  		expectedEnd   time.Time
    61  		expectedVals  []float64
    62  	}{
    63  		{"summarize(foo, \"30s\", \"sum\")", "30s", "", false,
    64  			time.Unix(120, 0), time.Unix(270, 0),
    65  			[]float64{1, 9, 18, 27, 11},
    66  		},
    67  		{"summarize(foo, \"30s\", \"sum\", true)", "30s", "", true,
    68  			start, end,
    69  			[]float64{3, 12, 21, 30},
    70  		},
    71  		{"summarize(foo, \"1min\", \"sum\")", "1min", "", false,
    72  			time.Unix(120, 0), time.Unix(300, 0),
    73  			[]float64{10, 45, 11},
    74  		},
    75  		{"summarize(foo, \"1min\", \"sum\", true)", "1min", "", true,
    76  			start, end,
    77  			[]float64{15, 51},
    78  		},
    79  		{"summarize(foo, \"1min\", \"avg\")", "1min", "avg", false,
    80  			time.Unix(120, 0), time.Unix(300, 0),
    81  			[]float64{2, 7.5, 11},
    82  		},
    83  		{"summarize(foo, \"1min\", \"last\")", "1min", "last", false,
    84  			start.Truncate(time.Minute), end.Truncate(time.Minute).Add(time.Minute),
    85  			[]float64{4, 10, 11},
    86  		},
    87  	}
    88  
    89  	for _, test := range tests {
    90  		outSeries, err := summarize(ctx, singlePathSpec{
    91  			Values: series,
    92  		}, test.interval, test.fname, test.alignToFrom)
    93  		require.NoError(t, err)
    94  		require.Equal(t, 1, len(outSeries.Values))
    95  
    96  		out := outSeries.Values[0]
    97  		assert.Equal(t, test.name, out.Name(), "incorrect name for %s", test.name)
    98  		assert.Equal(t, test.expectedStart, out.StartTime(), "incorrect start for %s", test.name)
    99  		assert.Equal(t, test.expectedEnd, out.EndTime(), "incorrect end for %s", test.name)
   100  		require.Equal(t, len(test.expectedVals), out.Len(), "incorrect len for %s", test.name)
   101  
   102  		for i := 0; i < out.Len(); i++ {
   103  			assert.Equal(t, test.expectedVals[i], out.ValueAt(i), "incorrect val %d for %s", i, test.name)
   104  		}
   105  	}
   106  
   107  	_, err := summarize(ctx, singlePathSpec{
   108  		Values: series,
   109  	}, "0min", "avg", false)
   110  	require.Error(t, err)
   111  }
   112  
   113  func TestSmartSummarize(t *testing.T) {
   114  	var (
   115  		start  = time.Unix(131, 0)
   116  		end    = time.Unix(251, 0)
   117  		ctx    = common.NewContext(common.ContextOptions{Start: start, End: end})
   118  		vals   = ts.NewValues(ctx, 10000, 12)
   119  		series = []*ts.Series{ts.NewSeries(ctx, "foo", start, vals)}
   120  	)
   121  
   122  	defer ctx.Close()
   123  
   124  	// 0+1+2
   125  	// 3+4+5
   126  	// 6+7+8
   127  	// 9+10+11
   128  	for i := 0; i < vals.Len(); i++ {
   129  		vals.SetValueAt(i, float64(i))
   130  	}
   131  
   132  	tests := []struct {
   133  		name          string
   134  		interval      string
   135  		fname         string
   136  		expectedStart time.Time
   137  		expectedEnd   time.Time
   138  		expectedVals  []float64
   139  	}{
   140  		{"smartSummarize(foo, \"30s\", \"sum\")",
   141  			"30s",
   142  			"",
   143  			start, end,
   144  			[]float64{3, 12, 21, 30},
   145  		},
   146  		{"smartSummarize(foo, \"1min\", \"sum\")",
   147  			"1min",
   148  			"",
   149  			start,
   150  			end,
   151  			[]float64{15, 51},
   152  		},
   153  		{"smartSummarize(foo, \"40s\", \"median\")",
   154  			"40s",
   155  			"median",
   156  			start,
   157  			end,
   158  			[]float64{1.5, 5.5, 9.5},
   159  		},
   160  		{"smartSummarize(foo, \"30s\", \"median\")",
   161  			"30s",
   162  			"median",
   163  			start,
   164  			end,
   165  			[]float64{1, 4, 7, 10},
   166  		},
   167  	}
   168  
   169  	for _, test := range tests {
   170  		outSeries, err := smartSummarize(ctx, singlePathSpec{
   171  			Values: series,
   172  		}, test.interval, test.fname)
   173  		require.NoError(t, err)
   174  		require.Equal(t, 1, len(outSeries.Values))
   175  
   176  		out := outSeries.Values[0]
   177  		assert.Equal(t, test.name, out.Name(), "incorrect name for %s", test.name)
   178  		assert.Equal(t, test.expectedStart, out.StartTime(), "incorrect start for %s", test.name)
   179  		assert.Equal(t, test.expectedEnd, out.EndTime(), "incorrect end for %s", test.name)
   180  		require.Equal(t, len(test.expectedVals), out.Len(), "incorrect len for %s", test.name)
   181  
   182  		for i := 0; i < out.Len(); i++ {
   183  			assert.Equal(t, test.expectedVals[i], out.ValueAt(i), "incorrect val %d for %s", i, test.name)
   184  		}
   185  	}
   186  
   187  	_, err := smartSummarize(ctx, singlePathSpec{
   188  		Values: series,
   189  	}, "0min", "avg")
   190  	require.Error(t, err)
   191  }
   192  
   193  func TestSummarizeInvalidInterval(t *testing.T) {
   194  
   195  	var (
   196  		start  = time.Unix(131, 0)
   197  		end    = time.Unix(251, 0)
   198  		ctx    = common.NewContext(common.ContextOptions{Start: start, End: end})
   199  		vals   = ts.NewValues(ctx, 10000, 12)
   200  		series = []*ts.Series{ts.NewSeries(ctx, "foo", start, vals)}
   201  	)
   202  
   203  	defer ctx.Close()
   204  
   205  	_, err := summarize(ctx, singlePathSpec{
   206  		Values: series,
   207  	}, "0min", "avg", false)
   208  	require.Error(t, err)
   209  
   210  	_, err = summarize(ctx, singlePathSpec{
   211  		Values: series,
   212  	}, "-1hour", "avg", false)
   213  	require.Error(t, err)
   214  }