github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/functions/linear/datetime_test.go (about)

     1  // Copyright (c) 2018 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 linear
    22  
    23  import (
    24  	"math"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/m3db/m3/src/query/executor/transform"
    29  	"github.com/m3db/m3/src/query/models"
    30  	"github.com/m3db/m3/src/query/parser"
    31  	"github.com/m3db/m3/src/query/test"
    32  	"github.com/m3db/m3/src/query/test/compare"
    33  	"github.com/m3db/m3/src/query/test/executor"
    34  
    35  	"github.com/stretchr/testify/assert"
    36  	"github.com/stretchr/testify/require"
    37  )
    38  
    39  var withArg = []interface{}{struct{}{}}
    40  
    41  func expectedDateVals(values [][]float64, fn func(t time.Time) float64) [][]float64 {
    42  	expected := make([][]float64, 0, len(values))
    43  	for _, val := range values {
    44  		v := make([]float64, len(val))
    45  		for i, ev := range val {
    46  			if math.IsNaN(ev) {
    47  				v[i] = math.NaN()
    48  				continue
    49  			}
    50  			t := time.Unix(int64(ev), 0).UTC()
    51  			v[i] = fn(t)
    52  		}
    53  
    54  		expected = append(expected, v)
    55  	}
    56  	return expected
    57  }
    58  
    59  func TestDayOfMonth(t *testing.T) {
    60  	v := [][]float64{
    61  		{1493712846039, math.NaN(), 1493712846139, 1493712846239, 1493712846339},
    62  		{math.NaN(), 1493712846439, 1493712846539, 1493712846639, 1493712846739},
    63  	}
    64  
    65  	values, bounds := test.GenerateValuesAndBounds(v, nil)
    66  	block := test.NewBlockFromValues(bounds, values)
    67  	c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1)))
    68  	timeOp, err := NewDateOp(DayOfMonthType, true)
    69  	require.NoError(t, err)
    70  
    71  	op, ok := timeOp.(transform.Params)
    72  	require.True(t, ok)
    73  
    74  	node := op.Node(c, transform.Options{})
    75  	err = node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), block)
    76  	require.NoError(t, err)
    77  	expected := expectedDateVals(values, datetimeFuncs[DayOfMonthType])
    78  	assert.Len(t, sink.Values, 2)
    79  	compare.EqualsWithNans(t, expected, sink.Values)
    80  }
    81  
    82  func TestDayOfWeek(t *testing.T) {
    83  	v := [][]float64{
    84  		{1493712846039, math.NaN(), 1493712846139, 1493712846239, 1493712846339},
    85  		{math.NaN(), 1493712846439, 1493712846539, 1493712846639, 1493712846739},
    86  	}
    87  
    88  	values, bounds := test.GenerateValuesAndBounds(v, nil)
    89  	block := test.NewBlockFromValues(bounds, values)
    90  	c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1)))
    91  	timeOp, err := NewDateOp(DayOfWeekType, true)
    92  	require.NoError(t, err)
    93  
    94  	op, ok := timeOp.(transform.Params)
    95  	require.True(t, ok)
    96  
    97  	node := op.Node(c, transform.Options{})
    98  	err = node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), block)
    99  	require.NoError(t, err)
   100  	expected := expectedDateVals(values, datetimeFuncs[DayOfWeekType])
   101  	assert.Len(t, sink.Values, 2)
   102  	compare.EqualsWithNans(t, expected, sink.Values)
   103  }
   104  
   105  func TestDaysInMonth(t *testing.T) {
   106  	v := [][]float64{
   107  		{1493712846039, math.NaN(), 1493712846139, 1493712846239, 1493712846339},
   108  		{math.NaN(), 1493712846439, 1493712846539, 1493712846639, 1493712846739},
   109  	}
   110  
   111  	values, bounds := test.GenerateValuesAndBounds(v, nil)
   112  	block := test.NewBlockFromValues(bounds, values)
   113  	c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1)))
   114  	timeOp, err := NewDateOp(DaysInMonthType, true)
   115  	require.NoError(t, err)
   116  
   117  	op, ok := timeOp.(transform.Params)
   118  	require.True(t, ok)
   119  
   120  	node := op.Node(c, transform.Options{})
   121  	err = node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), block)
   122  	require.NoError(t, err)
   123  	expected := expectedDateVals(values, datetimeFuncs[DaysInMonthType])
   124  	assert.Len(t, sink.Values, 2)
   125  	compare.EqualsWithNans(t, expected, sink.Values)
   126  }
   127  
   128  func TestHour(t *testing.T) {
   129  	v := [][]float64{
   130  		{1493712846039, math.NaN(), 1493712846139, 1493712846239, 1493712846339},
   131  		{math.NaN(), 1493712846439, 1493712846539, 1493712846639, 1493712846739},
   132  	}
   133  
   134  	values, bounds := test.GenerateValuesAndBounds(v, nil)
   135  	block := test.NewBlockFromValues(bounds, values)
   136  	c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1)))
   137  	timeOp, err := NewDateOp(HourType, true)
   138  	require.NoError(t, err)
   139  
   140  	op, ok := timeOp.(transform.Params)
   141  	require.True(t, ok)
   142  
   143  	node := op.Node(c, transform.Options{})
   144  	err = node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), block)
   145  	require.NoError(t, err)
   146  	expected := expectedDateVals(values, datetimeFuncs[HourType])
   147  	assert.Len(t, sink.Values, 2)
   148  	compare.EqualsWithNans(t, expected, sink.Values)
   149  }
   150  
   151  func TestMinute(t *testing.T) {
   152  	v := [][]float64{
   153  		{1493712846039, math.NaN(), 1493712846139, 1493712846239, 1493712846339},
   154  		{math.NaN(), 1493712846439, 1493712846539, 1493712846639, 1493712846739},
   155  	}
   156  
   157  	values, bounds := test.GenerateValuesAndBounds(v, nil)
   158  	block := test.NewBlockFromValues(bounds, values)
   159  	c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1)))
   160  	timeOp, err := NewDateOp(MinuteType, true)
   161  	require.NoError(t, err)
   162  
   163  	op, ok := timeOp.(transform.Params)
   164  	require.True(t, ok)
   165  
   166  	node := op.Node(c, transform.Options{})
   167  	err = node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), block)
   168  	require.NoError(t, err)
   169  	expected := expectedDateVals(values, datetimeFuncs[MinuteType])
   170  	assert.Len(t, sink.Values, 2)
   171  	compare.EqualsWithNans(t, expected, sink.Values)
   172  }
   173  
   174  func TestMonth(t *testing.T) {
   175  	v := [][]float64{
   176  		{1493712846039, math.NaN(), 1493712846139, 1493712846239, 1493712846339},
   177  		{math.NaN(), 1493712846439, 1493712846539, 1493712846639, 1493712846739},
   178  	}
   179  
   180  	values, bounds := test.GenerateValuesAndBounds(v, nil)
   181  	block := test.NewBlockFromValues(bounds, values)
   182  	c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1)))
   183  	timeOp, err := NewDateOp(MonthType, true)
   184  	require.NoError(t, err)
   185  
   186  	op, ok := timeOp.(transform.Params)
   187  	require.True(t, ok)
   188  
   189  	node := op.Node(c, transform.Options{})
   190  	err = node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), block)
   191  	require.NoError(t, err)
   192  	expected := expectedDateVals(values, datetimeFuncs[MonthType])
   193  	assert.Len(t, sink.Values, 2)
   194  	compare.EqualsWithNans(t, expected, sink.Values)
   195  }
   196  
   197  func TestYear(t *testing.T) {
   198  	v := [][]float64{
   199  		{1493712846039, math.NaN(), 1493712846139, 1493712846239, 1493712846339},
   200  		{math.NaN(), 1493712846439, 1493712846539, 1493712846639, 1493712846739},
   201  	}
   202  
   203  	values, bounds := test.GenerateValuesAndBounds(v, nil)
   204  	block := test.NewBlockFromValues(bounds, values)
   205  	c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1)))
   206  	timeOp, err := NewDateOp(YearType, true)
   207  	require.NoError(t, err)
   208  
   209  	op, ok := timeOp.(transform.Params)
   210  	require.True(t, ok)
   211  
   212  	node := op.Node(c, transform.Options{})
   213  	err = node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), block)
   214  	require.NoError(t, err)
   215  	expected := expectedDateVals(values, datetimeFuncs[YearType])
   216  	assert.Len(t, sink.Values, 2)
   217  	compare.EqualsWithNans(t, expected, sink.Values)
   218  }
   219  
   220  func TestNonExistentDateFunc(t *testing.T) {
   221  	_, err := NewDateOp("nonexistent_func", true)
   222  	require.Error(t, err)
   223  }
   224  
   225  func TestWithoutArgs(t *testing.T) {
   226  	v := [][]float64{
   227  		{1493712846039, math.NaN(), 1493712846139, 1493712846239, 1493712846339},
   228  	}
   229  
   230  	values, bounds := test.GenerateValuesAndBounds(v, nil)
   231  	block := test.NewBlockFromValues(bounds, values)
   232  	c, sink := executor.NewControllerWithSink(parser.NodeID(rune(1)))
   233  	timeOp, err := NewDateOp(YearType, false)
   234  	require.NoError(t, err)
   235  
   236  	op, ok := timeOp.(transform.Params)
   237  	require.True(t, ok)
   238  
   239  	node := op.Node(c, transform.Options{})
   240  	err = node.Process(models.NoopQueryContext(), parser.NodeID(rune(0)), block)
   241  	require.NoError(t, err)
   242  	assert.Len(t, sink.Values, 1)
   243  	ex := float64(time.Now().Year())
   244  	assert.Equal(t, []float64{ex, ex, ex, ex, ex}, sink.Values[0])
   245  }