mirror of
				https://github.com/prometheus/prometheus.git
				synced 2025-11-04 10:21:02 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1083 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1083 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2013 Prometheus Team
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
// http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
package metric
 | 
						|
 | 
						|
import (
 | 
						|
	"github.com/prometheus/prometheus/model"
 | 
						|
	"github.com/prometheus/prometheus/utility/test"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
func GetValueAtTimeTests(persistenceMaker func() (MetricPersistence, test.Closer), t test.Tester) {
 | 
						|
	type value struct {
 | 
						|
		year  int
 | 
						|
		month time.Month
 | 
						|
		day   int
 | 
						|
		hour  int
 | 
						|
		value model.SampleValue
 | 
						|
	}
 | 
						|
 | 
						|
	type input struct {
 | 
						|
		year  int
 | 
						|
		month time.Month
 | 
						|
		day   int
 | 
						|
		hour  int
 | 
						|
	}
 | 
						|
 | 
						|
	type output []model.SampleValue
 | 
						|
 | 
						|
	type behavior struct {
 | 
						|
		name   string
 | 
						|
		input  input
 | 
						|
		output output
 | 
						|
	}
 | 
						|
 | 
						|
	var contexts = []struct {
 | 
						|
		name      string
 | 
						|
		values    []value
 | 
						|
		behaviors []behavior
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name:   "no values",
 | 
						|
			values: []value{},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "random target",
 | 
						|
					input: input{
 | 
						|
						year:  1984,
 | 
						|
						month: 3,
 | 
						|
						day:   30,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "singleton",
 | 
						|
			values: []value{
 | 
						|
				{
 | 
						|
					year:  1984,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 0,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "exact",
 | 
						|
					input: input{
 | 
						|
						year:  1984,
 | 
						|
						month: 3,
 | 
						|
						day:   30,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "before",
 | 
						|
					input: input{
 | 
						|
						year:  1984,
 | 
						|
						month: 3,
 | 
						|
						day:   29,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "after",
 | 
						|
					input: input{
 | 
						|
						year:  1984,
 | 
						|
						month: 3,
 | 
						|
						day:   31,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "double",
 | 
						|
			values: []value{
 | 
						|
				{
 | 
						|
					year:  1984,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 0,
 | 
						|
				},
 | 
						|
				{
 | 
						|
					year:  1985,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 1,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "exact first",
 | 
						|
					input: input{
 | 
						|
						year:  1984,
 | 
						|
						month: 3,
 | 
						|
						day:   30,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "exact second",
 | 
						|
					input: input{
 | 
						|
						year:  1985,
 | 
						|
						month: 3,
 | 
						|
						day:   30,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						1,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "before first",
 | 
						|
					input: input{
 | 
						|
						year:  1983,
 | 
						|
						month: 9,
 | 
						|
						day:   29,
 | 
						|
						hour:  12,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "after second",
 | 
						|
					input: input{
 | 
						|
						year:  1985,
 | 
						|
						month: 9,
 | 
						|
						day:   28,
 | 
						|
						hour:  12,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						1,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "middle",
 | 
						|
					input: input{
 | 
						|
						year:  1984,
 | 
						|
						month: 9,
 | 
						|
						day:   28,
 | 
						|
						hour:  12,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
						1,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "triple",
 | 
						|
			values: []value{
 | 
						|
				{
 | 
						|
					year:  1984,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 0,
 | 
						|
				},
 | 
						|
				{
 | 
						|
					year:  1985,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 1,
 | 
						|
				},
 | 
						|
				{
 | 
						|
					year:  1986,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 2,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "exact first",
 | 
						|
					input: input{
 | 
						|
						year:  1984,
 | 
						|
						month: 3,
 | 
						|
						day:   30,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "exact second",
 | 
						|
					input: input{
 | 
						|
						year:  1985,
 | 
						|
						month: 3,
 | 
						|
						day:   30,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						1,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "exact third",
 | 
						|
					input: input{
 | 
						|
						year:  1986,
 | 
						|
						month: 3,
 | 
						|
						day:   30,
 | 
						|
						hour:  0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						2,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "before first",
 | 
						|
					input: input{
 | 
						|
						year:  1983,
 | 
						|
						month: 9,
 | 
						|
						day:   29,
 | 
						|
						hour:  12,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "after third",
 | 
						|
					input: input{
 | 
						|
						year:  1986,
 | 
						|
						month: 9,
 | 
						|
						day:   28,
 | 
						|
						hour:  12,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						2,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "first middle",
 | 
						|
					input: input{
 | 
						|
						year:  1984,
 | 
						|
						month: 9,
 | 
						|
						day:   28,
 | 
						|
						hour:  12,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						0,
 | 
						|
						1,
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "second middle",
 | 
						|
					input: input{
 | 
						|
						year:  1985,
 | 
						|
						month: 9,
 | 
						|
						day:   28,
 | 
						|
						hour:  12,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						1,
 | 
						|
						2,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for i, context := range contexts {
 | 
						|
		// Wrapping in function to enable garbage collection of resources.
 | 
						|
		func() {
 | 
						|
			p, closer := persistenceMaker()
 | 
						|
 | 
						|
			defer closer.Close()
 | 
						|
			defer p.Close()
 | 
						|
 | 
						|
			m := model.Metric{
 | 
						|
				model.MetricNameLabel: "age_in_years",
 | 
						|
			}
 | 
						|
 | 
						|
			for _, value := range context.values {
 | 
						|
				testAppendSample(p, model.Sample{
 | 
						|
					Value:     model.SampleValue(value.value),
 | 
						|
					Timestamp: time.Date(value.year, value.month, value.day, value.hour, 0, 0, 0, time.UTC),
 | 
						|
					Metric:    m,
 | 
						|
				}, t)
 | 
						|
			}
 | 
						|
 | 
						|
			for j, behavior := range context.behaviors {
 | 
						|
				input := behavior.input
 | 
						|
				time := time.Date(input.year, input.month, input.day, input.hour, 0, 0, 0, time.UTC)
 | 
						|
 | 
						|
				actual := p.GetValueAtTime(model.NewFingerprintFromMetric(m), time)
 | 
						|
 | 
						|
				if len(behavior.output) != len(actual) {
 | 
						|
					t.Fatalf("%d.%d(%s). Expected %d samples but got: %v\n", i, j, behavior.name, len(behavior.output), actual)
 | 
						|
				}
 | 
						|
				for k, samplePair := range actual {
 | 
						|
					if samplePair.Value != behavior.output[k] {
 | 
						|
						t.Fatalf("%d.%d.%d(%s). Expected %s but got %s\n", i, j, k, behavior.name, behavior.output[k], samplePair)
 | 
						|
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func GetBoundaryValuesTests(persistenceMaker func() (MetricPersistence, test.Closer), t test.Tester) {
 | 
						|
	type value struct {
 | 
						|
		year  int
 | 
						|
		month time.Month
 | 
						|
		day   int
 | 
						|
		hour  int
 | 
						|
		value model.SampleValue
 | 
						|
	}
 | 
						|
 | 
						|
	type input struct {
 | 
						|
		openYear  int
 | 
						|
		openMonth time.Month
 | 
						|
		openDay   int
 | 
						|
		openHour  int
 | 
						|
		endYear   int
 | 
						|
		endMonth  time.Month
 | 
						|
		endDay    int
 | 
						|
		endHour   int
 | 
						|
	}
 | 
						|
 | 
						|
	type output struct {
 | 
						|
		open []model.SampleValue
 | 
						|
		end  []model.SampleValue
 | 
						|
	}
 | 
						|
 | 
						|
	type behavior struct {
 | 
						|
		name   string
 | 
						|
		input  input
 | 
						|
		output output
 | 
						|
	}
 | 
						|
 | 
						|
	var contexts = []struct {
 | 
						|
		name      string
 | 
						|
		values    []value
 | 
						|
		behaviors []behavior
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name:   "no values",
 | 
						|
			values: []value{},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "non-existent interval",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "single value",
 | 
						|
			values: []value{
 | 
						|
				{
 | 
						|
					year:  1984,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 0,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "on start but missing end",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{0},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "non-existent interval after",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   31,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{0},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "non-existent interval before",
 | 
						|
					input: input{
 | 
						|
						openYear:  1983,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1984,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    29,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{0},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "on end but not start",
 | 
						|
					input: input{
 | 
						|
						openYear:  1983,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1984,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{0},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "before point",
 | 
						|
					input: input{
 | 
						|
						openYear:  1982,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1983,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{0},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "after point",
 | 
						|
					input: input{
 | 
						|
						openYear:  1985,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1986,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{0},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "spanning point",
 | 
						|
					input: input{
 | 
						|
						openYear:  1983,
 | 
						|
						openMonth: 9,
 | 
						|
						openDay:   29,
 | 
						|
						openHour:  12,
 | 
						|
						endYear:   1984,
 | 
						|
						endMonth:  9,
 | 
						|
						endDay:    28,
 | 
						|
						endHour:   12,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{0},
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "double values",
 | 
						|
			values: []value{
 | 
						|
				{
 | 
						|
					year:  1984,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 0,
 | 
						|
				},
 | 
						|
				{
 | 
						|
					year:  1985,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 1,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "on points",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{1},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "on first before second",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1984,
 | 
						|
						endMonth:  6,
 | 
						|
						endDay:    29,
 | 
						|
						endHour:   6,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{0, 1},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "on first after second",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  6,
 | 
						|
						endDay:    29,
 | 
						|
						endHour:   6,
 | 
						|
					},
 | 
						|
					output: output{
 | 
						|
						open: []model.SampleValue{0},
 | 
						|
						end:  []model.SampleValue{1},
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for i, context := range contexts {
 | 
						|
		// Wrapping in function to enable garbage collection of resources.
 | 
						|
		func() {
 | 
						|
			p, closer := persistenceMaker()
 | 
						|
 | 
						|
			defer closer.Close()
 | 
						|
			defer p.Close()
 | 
						|
 | 
						|
			m := model.Metric{
 | 
						|
				model.MetricNameLabel: "age_in_years",
 | 
						|
			}
 | 
						|
 | 
						|
			for _, value := range context.values {
 | 
						|
				testAppendSample(p, model.Sample{
 | 
						|
					Value:     model.SampleValue(value.value),
 | 
						|
					Timestamp: time.Date(value.year, value.month, value.day, value.hour, 0, 0, 0, time.UTC),
 | 
						|
					Metric:    m,
 | 
						|
				}, t)
 | 
						|
			}
 | 
						|
 | 
						|
			for j, behavior := range context.behaviors {
 | 
						|
				input := behavior.input
 | 
						|
				open := time.Date(input.openYear, input.openMonth, input.openDay, input.openHour, 0, 0, 0, time.UTC)
 | 
						|
				end := time.Date(input.endYear, input.endMonth, input.endDay, input.endHour, 0, 0, 0, time.UTC)
 | 
						|
				interval := model.Interval{
 | 
						|
					OldestInclusive: open,
 | 
						|
					NewestInclusive: end,
 | 
						|
				}
 | 
						|
				openValues, endValues := p.GetBoundaryValues(model.NewFingerprintFromMetric(m), interval)
 | 
						|
				if len(behavior.output.open) != len(openValues) {
 | 
						|
					t.Fatalf("%d.%d(%s). Expected %d open values but got: %q\n", i, j, behavior.name, len(behavior.output.open), openValues)
 | 
						|
				}
 | 
						|
				if len(behavior.output.end) != len(endValues) {
 | 
						|
					t.Fatalf("%d.%d(%s). Expected %d open values but got: %q\n", i, j, behavior.name, len(behavior.output.open), openValues)
 | 
						|
				}
 | 
						|
 | 
						|
				for k, samplePair := range openValues {
 | 
						|
					if samplePair.Value != behavior.output.open[k] {
 | 
						|
						t.Fatalf("%d.%d.%d(%s). Expected open to be %v but got %v\n", i, j, k, behavior.name, behavior.output.open[k], samplePair.Value)
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				for k, samplePair := range endValues {
 | 
						|
					if samplePair.Value != behavior.output.end[k] {
 | 
						|
						t.Fatalf("%d.%d.%d(%s). Expected end to be %v but got %v\n", i, j, k, behavior.name, behavior.output.end[k], samplePair.Value)
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func GetRangeValuesTests(persistenceMaker func() (MetricPersistence, test.Closer), t test.Tester) {
 | 
						|
	type value struct {
 | 
						|
		year  int
 | 
						|
		month time.Month
 | 
						|
		day   int
 | 
						|
		hour  int
 | 
						|
		value model.SampleValue
 | 
						|
	}
 | 
						|
 | 
						|
	type input struct {
 | 
						|
		openYear  int
 | 
						|
		openMonth time.Month
 | 
						|
		openDay   int
 | 
						|
		openHour  int
 | 
						|
		endYear   int
 | 
						|
		endMonth  time.Month
 | 
						|
		endDay    int
 | 
						|
		endHour   int
 | 
						|
	}
 | 
						|
 | 
						|
	type output struct {
 | 
						|
		year  int
 | 
						|
		month time.Month
 | 
						|
		day   int
 | 
						|
		hour  int
 | 
						|
		value model.SampleValue
 | 
						|
	}
 | 
						|
 | 
						|
	type behavior struct {
 | 
						|
		name   string
 | 
						|
		input  input
 | 
						|
		output []output
 | 
						|
	}
 | 
						|
 | 
						|
	var contexts = []struct {
 | 
						|
		name      string
 | 
						|
		values    []value
 | 
						|
		behaviors []behavior
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			name:   "no values",
 | 
						|
			values: []value{},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "non-existent interval",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "singleton value",
 | 
						|
			values: []value{
 | 
						|
				{
 | 
						|
					year:  1984,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 0,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "start on first value",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: []output{
 | 
						|
						{
 | 
						|
							year:  1984,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 0,
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "end on first value",
 | 
						|
					input: input{
 | 
						|
						openYear:  1983,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1984,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: []output{
 | 
						|
						{
 | 
						|
							year:  1984,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 0,
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "overlap on first value",
 | 
						|
					input: input{
 | 
						|
						openYear:  1983,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: []output{
 | 
						|
						{
 | 
						|
							year:  1984,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 0,
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name: "two values",
 | 
						|
			values: []value{
 | 
						|
				{
 | 
						|
					year:  1984,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 0,
 | 
						|
				},
 | 
						|
				{
 | 
						|
					year:  1985,
 | 
						|
					month: 3,
 | 
						|
					day:   30,
 | 
						|
					hour:  0,
 | 
						|
					value: 1,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			behaviors: []behavior{
 | 
						|
				{
 | 
						|
					name: "start on first value",
 | 
						|
					input: input{
 | 
						|
						openYear:  1984,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: []output{
 | 
						|
						{
 | 
						|
							year:  1984,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 0,
 | 
						|
						},
 | 
						|
						{
 | 
						|
							year:  1985,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 1,
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "start on second value",
 | 
						|
					input: input{
 | 
						|
						openYear:  1985,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1986,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: []output{
 | 
						|
						{
 | 
						|
							year:  1985,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 1,
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "end on first value",
 | 
						|
					input: input{
 | 
						|
						openYear:  1983,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1984,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: []output{
 | 
						|
						{
 | 
						|
							year:  1984,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 0,
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "end on second value",
 | 
						|
					input: input{
 | 
						|
						openYear:  1985,
 | 
						|
						openMonth: 1,
 | 
						|
						openDay:   1,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1985,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: []output{
 | 
						|
						{
 | 
						|
							year:  1985,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 1,
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
				{
 | 
						|
					name: "overlap on values",
 | 
						|
					input: input{
 | 
						|
						openYear:  1983,
 | 
						|
						openMonth: 3,
 | 
						|
						openDay:   30,
 | 
						|
						openHour:  0,
 | 
						|
						endYear:   1986,
 | 
						|
						endMonth:  3,
 | 
						|
						endDay:    30,
 | 
						|
						endHour:   0,
 | 
						|
					},
 | 
						|
					output: []output{
 | 
						|
						{
 | 
						|
							year:  1984,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 0,
 | 
						|
						},
 | 
						|
						{
 | 
						|
							year:  1985,
 | 
						|
							month: 3,
 | 
						|
							day:   30,
 | 
						|
							hour:  0,
 | 
						|
							value: 1,
 | 
						|
						},
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for i, context := range contexts {
 | 
						|
		// Wrapping in function to enable garbage collection of resources.
 | 
						|
		func() {
 | 
						|
			p, closer := persistenceMaker()
 | 
						|
 | 
						|
			defer closer.Close()
 | 
						|
			defer p.Close()
 | 
						|
 | 
						|
			m := model.Metric{
 | 
						|
				model.MetricNameLabel: "age_in_years",
 | 
						|
			}
 | 
						|
 | 
						|
			for _, value := range context.values {
 | 
						|
				testAppendSample(p, model.Sample{
 | 
						|
					Value:     model.SampleValue(value.value),
 | 
						|
					Timestamp: time.Date(value.year, value.month, value.day, value.hour, 0, 0, 0, time.UTC),
 | 
						|
					Metric:    m,
 | 
						|
				}, t)
 | 
						|
			}
 | 
						|
 | 
						|
			for j, behavior := range context.behaviors {
 | 
						|
				input := behavior.input
 | 
						|
				open := time.Date(input.openYear, input.openMonth, input.openDay, input.openHour, 0, 0, 0, time.UTC)
 | 
						|
				end := time.Date(input.endYear, input.endMonth, input.endDay, input.endHour, 0, 0, 0, time.UTC)
 | 
						|
				in := model.Interval{
 | 
						|
					OldestInclusive: open,
 | 
						|
					NewestInclusive: end,
 | 
						|
				}
 | 
						|
 | 
						|
				values := p.GetRangeValues(model.NewFingerprintFromMetric(m), in)
 | 
						|
 | 
						|
				if values == nil && len(behavior.output) != 0 {
 | 
						|
					t.Fatalf("%d.%d(%s). Expected %s but got: %s\n", i, j, behavior.name, behavior.output, values)
 | 
						|
				}
 | 
						|
 | 
						|
				if behavior.output == nil {
 | 
						|
					if values != nil {
 | 
						|
						t.Fatalf("%d.%d(%s). Expected nil values but got: %s\n", i, j, behavior.name, values)
 | 
						|
					}
 | 
						|
				} else {
 | 
						|
					if len(behavior.output) != len(values) {
 | 
						|
						t.Fatalf("%d.%d(%s). Expected length %d but got: %d\n", i, j, behavior.name, len(behavior.output), len(values))
 | 
						|
					}
 | 
						|
 | 
						|
					for k, actual := range values {
 | 
						|
						expected := behavior.output[k]
 | 
						|
 | 
						|
						if actual.Value != model.SampleValue(expected.value) {
 | 
						|
							t.Fatalf("%d.%d.%d(%s). Expected %d but got: %d\n", i, j, k, behavior.name, expected.value, actual.Value)
 | 
						|
						}
 | 
						|
 | 
						|
						if actual.Timestamp.Year() != expected.year {
 | 
						|
							t.Fatalf("%d.%d.%d(%s). Expected %d but got: %d\n", i, j, k, behavior.name, expected.year, actual.Timestamp.Year())
 | 
						|
						}
 | 
						|
						if actual.Timestamp.Month() != expected.month {
 | 
						|
							t.Fatalf("%d.%d.%d(%s). Expected %d but got: %d\n", i, j, k, behavior.name, expected.month, actual.Timestamp.Month())
 | 
						|
						}
 | 
						|
						// XXX: Find problem here.
 | 
						|
						// Mismatches occur in this and have for a long time in the LevelDB
 | 
						|
						// case, however not im-memory.
 | 
						|
						//
 | 
						|
						// if actual.Timestamp.Day() != expected.day {
 | 
						|
						// 	t.Fatalf("%d.%d.%d(%s). Expected %d but got: %d\n", i, j, k, behavior.name, expected.day, actual.Timestamp.Day())
 | 
						|
						// }
 | 
						|
						// if actual.Timestamp.Hour() != expected.hour {
 | 
						|
						// 	t.Fatalf("%d.%d.%d(%s). Expected %d but got: %d\n", i, j, k, behavior.name, expected.hour, actual.Timestamp.Hour())
 | 
						|
						// }
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Test Definitions Follow
 | 
						|
 | 
						|
func testMemoryGetValueAtTime(t test.Tester) {
 | 
						|
	persistenceMaker := func() (MetricPersistence, test.Closer) {
 | 
						|
		return NewMemorySeriesStorage(), test.NilCloser
 | 
						|
	}
 | 
						|
 | 
						|
	GetValueAtTimeTests(persistenceMaker, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestMemoryGetValueAtTime(t *testing.T) {
 | 
						|
	testMemoryGetValueAtTime(t)
 | 
						|
}
 | 
						|
 | 
						|
func BenchmarkMemoryGetValueAtTime(b *testing.B) {
 | 
						|
	for i := 0; i < b.N; i++ {
 | 
						|
		testMemoryGetValueAtTime(b)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testMemoryGetBoundaryValues(t test.Tester) {
 | 
						|
	persistenceMaker := func() (MetricPersistence, test.Closer) {
 | 
						|
		return NewMemorySeriesStorage(), test.NilCloser
 | 
						|
	}
 | 
						|
 | 
						|
	GetBoundaryValuesTests(persistenceMaker, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestMemoryGetBoundaryValues(t *testing.T) {
 | 
						|
	testMemoryGetBoundaryValues(t)
 | 
						|
}
 | 
						|
 | 
						|
func BenchmarkMemoryGetBoundaryValues(b *testing.B) {
 | 
						|
	for i := 0; i < b.N; i++ {
 | 
						|
		testMemoryGetBoundaryValues(b)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func testMemoryGetRangeValues(t test.Tester) {
 | 
						|
	persistenceMaker := func() (MetricPersistence, test.Closer) {
 | 
						|
		return NewMemorySeriesStorage(), test.NilCloser
 | 
						|
	}
 | 
						|
 | 
						|
	GetRangeValuesTests(persistenceMaker, t)
 | 
						|
}
 | 
						|
 | 
						|
func TestMemoryGetRangeValues(t *testing.T) {
 | 
						|
	testMemoryGetRangeValues(t)
 | 
						|
}
 | 
						|
 | 
						|
func BenchmarkMemoryGetRangeValues(b *testing.B) {
 | 
						|
	for i := 0; i < b.N; i++ {
 | 
						|
		testMemoryGetRangeValues(b)
 | 
						|
	}
 | 
						|
}
 |