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 }