github.com/m3db/m3@v1.5.0/src/query/ts/values_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 ts
    22  
    23  import (
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/m3db/m3/src/query/models"
    28  	xtime "github.com/m3db/m3/src/x/time"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  func generateDatapoints(t xtime.UnixNano, times []int) Datapoints {
    35  	num := len(times)
    36  	dps := make(Datapoints, len(times))
    37  	for i := 0; i < num; i++ {
    38  		dps[i] = Datapoint{
    39  			Timestamp: t.Add(time.Duration(times[i]) * time.Second),
    40  			Value:     float64(i),
    41  		}
    42  	}
    43  	return dps
    44  }
    45  
    46  var (
    47  	now     = xtime.Now()
    48  	samples = []struct {
    49  		input                  Datapoints
    50  		expected               [][]float64
    51  		expectedNoWriteForward [][]float64
    52  		bounds                 models.Bounds
    53  		description            string
    54  	}{
    55  		{
    56  			input:                  generateDatapoints(now, []int{-1, 0, 10, 18, 28, 38}),
    57  			expected:               [][]float64{{0, 1}, {2}, {3}, {4}},
    58  			expectedNoWriteForward: [][]float64{{0, 1}, {2}, {3}, {4}},
    59  			bounds: models.Bounds{
    60  				Start:    now,
    61  				Duration: 40 * time.Second,
    62  				StepSize: 10 * time.Second,
    63  			},
    64  			description: "some points line up and others before",
    65  		},
    66  		{
    67  			input:                  generateDatapoints(now, []int{1, 10, 18, 28}),
    68  			expected:               [][]float64{{}, {0, 1}, {2}, {3}},
    69  			expectedNoWriteForward: [][]float64{{}, {0, 1}, {2}, {3}},
    70  			bounds: models.Bounds{
    71  				Start:    now,
    72  				Duration: 40 * time.Second,
    73  				StepSize: 10 * time.Second,
    74  			},
    75  			description: "only points after start",
    76  		},
    77  		{
    78  			input:                  generateDatapoints(now, []int{0, 10, 18, 28}),
    79  			expected:               [][]float64{{0}, {0}, {1}, {1}, {2}, {2}, {3}, {3}},
    80  			expectedNoWriteForward: [][]float64{{0}, {}, {1}, {}, {2}, {}, {3}, {}},
    81  			bounds: models.Bounds{
    82  				Start:    now,
    83  				Duration: 40 * time.Second,
    84  				StepSize: 5 * time.Second,
    85  			},
    86  			description: "half resolution so datapoints repeated",
    87  		},
    88  		{
    89  			input:                  generateDatapoints(now, []int{0, 10, 18, 28}),
    90  			expected:               [][]float64{{0}, {1, 2}},
    91  			expectedNoWriteForward: [][]float64{{0}, {1, 2}},
    92  			bounds: models.Bounds{
    93  				Start:    now,
    94  				Duration: 40 * time.Second,
    95  				StepSize: 20 * time.Second,
    96  			},
    97  			description: "double resolution so multiple dps in the same interval",
    98  		},
    99  		{
   100  			input:                  generateDatapoints(now, []int{0, 4, 5, 14}),
   101  			expected:               [][]float64{{0}, {1, 2}, {2}, {3}},
   102  			expectedNoWriteForward: [][]float64{{0}, {1, 2}, {}, {3}},
   103  			bounds: models.Bounds{
   104  				Start:    now,
   105  				Duration: 20 * time.Second,
   106  				StepSize: 5 * time.Second,
   107  			},
   108  			description: "third interval has repeated datapoint",
   109  		},
   110  		{
   111  			input: generateDatapoints(now.Add(-10*time.Minute),
   112  				[]int{-1, 0, 10, 18, 28, 38}),
   113  			expected:               [][]float64{{}, {}, {}, {}},
   114  			expectedNoWriteForward: [][]float64{{}, {}, {}, {}},
   115  			bounds: models.Bounds{
   116  				Start:    now,
   117  				Duration: 40 * time.Second,
   118  				StepSize: 10 * time.Second,
   119  			},
   120  			description: "skip really old datapoints",
   121  		},
   122  	}
   123  )
   124  
   125  func TestDPAlign(t *testing.T) {
   126  	for _, sample := range samples {
   127  		dpSlice := sample.input.AlignToBounds(sample.bounds, time.Minute, nil)
   128  		require.Len(t, dpSlice, len(sample.expected), sample.description)
   129  		for i, dps := range dpSlice {
   130  			assert.Equal(t, sample.expected[i], dps.Values())
   131  		}
   132  
   133  		dpSlice = sample.input.AlignToBoundsNoWriteForward(
   134  			sample.bounds, time.Minute, dpSlice)
   135  		require.Len(t, dpSlice, len(sample.expected), sample.description)
   136  		for i, dps := range dpSlice {
   137  			require.Equal(t, sample.expectedNoWriteForward[i], dps.Values())
   138  		}
   139  	}
   140  }