mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-22 16:36:27 +01:00
63fc200f16
See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5376
(cherry picked from commit 6af732b6f7
)
551 lines
11 KiB
Go
551 lines
11 KiB
Go
package stepper
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type testTimeRange []string
|
|
|
|
func mustParseDatetime(t string) time.Time {
|
|
result, err := time.Parse(time.RFC3339, t)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func Test_splitDateRange(t *testing.T) {
|
|
type args struct {
|
|
start string
|
|
end string
|
|
granularity string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want []testTimeRange
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "validates start is before end",
|
|
args: args{
|
|
start: "2022-02-01T00:00:00Z",
|
|
end: "2022-01-01T00:00:00Z",
|
|
granularity: StepMonth,
|
|
},
|
|
want: nil,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "validates granularity value",
|
|
args: args{
|
|
start: "2022-01-01T00:00:00Z",
|
|
end: "2022-02-01T00:00:00Z",
|
|
granularity: "non-existent-format",
|
|
},
|
|
want: nil,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "month chunking",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-03-03T12:12:12Z",
|
|
granularity: StepMonth,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-31T23:59:59.999999999Z",
|
|
},
|
|
{
|
|
"2022-02-01T00:00:00Z",
|
|
"2022-02-28T23:59:59.999999999Z",
|
|
},
|
|
{
|
|
"2022-03-01T00:00:00Z",
|
|
"2022-03-03T12:12:12Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "daily chunking",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-01-05T12:12:12Z",
|
|
granularity: StepDay,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-04T11:11:11Z",
|
|
},
|
|
{
|
|
"2022-01-04T11:11:11Z",
|
|
"2022-01-05T11:11:11Z",
|
|
},
|
|
{
|
|
"2022-01-05T11:11:11Z",
|
|
"2022-01-05T12:12:12Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "hourly chunking",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-01-03T14:14:14Z",
|
|
granularity: StepHour,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-03T12:11:11Z",
|
|
},
|
|
{
|
|
"2022-01-03T12:11:11Z",
|
|
"2022-01-03T13:11:11Z",
|
|
},
|
|
{
|
|
"2022-01-03T13:11:11Z",
|
|
"2022-01-03T14:11:11Z",
|
|
},
|
|
{
|
|
"2022-01-03T14:11:11Z",
|
|
"2022-01-03T14:14:14Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "month chunking with one day time range",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-01-04T12:12:12Z",
|
|
granularity: StepMonth,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-04T12:12:12Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "month chunking with same day time range",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-01-03T12:12:12Z",
|
|
granularity: StepMonth,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-03T12:12:12Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "month chunking with one month and two days range",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-02-03T00:00:00Z",
|
|
granularity: StepMonth,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-31T23:59:59.999999999Z",
|
|
},
|
|
{
|
|
"2022-02-01T00:00:00Z",
|
|
"2022-02-03T00:00:00Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "week chunking with not full week",
|
|
args: args{
|
|
start: "2023-07-30T00:00:00Z",
|
|
end: "2023-08-05T23:59:59.999999999Z",
|
|
granularity: StepWeek,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2023-07-30T00:00:00Z",
|
|
"2023-08-05T23:59:59.999999999Z",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "week chunking with start of the week and end of the week",
|
|
args: args{
|
|
start: "2023-07-30T00:00:00Z",
|
|
end: "2023-08-06T00:00:00Z",
|
|
granularity: StepWeek,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2023-07-30T00:00:00Z",
|
|
"2023-08-06T00:00:00Z",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "week chunking with next one day week",
|
|
args: args{
|
|
start: "2023-07-30T00:00:00Z",
|
|
end: "2023-08-07T01:12:00Z",
|
|
granularity: StepWeek,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2023-07-30T00:00:00Z",
|
|
"2023-08-06T00:00:00Z",
|
|
},
|
|
{
|
|
"2023-08-06T00:00:00Z",
|
|
"2023-08-07T01:12:00Z",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "week chunking with month and not full week representation",
|
|
args: args{
|
|
start: "2023-07-30T00:00:00Z",
|
|
end: "2023-09-01T01:12:00Z",
|
|
granularity: StepWeek,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2023-07-30T00:00:00Z",
|
|
"2023-08-06T00:00:00Z",
|
|
},
|
|
{
|
|
"2023-08-06T00:00:00Z",
|
|
"2023-08-13T00:00:00Z",
|
|
},
|
|
{
|
|
"2023-08-13T00:00:00Z",
|
|
"2023-08-20T00:00:00Z",
|
|
},
|
|
{
|
|
"2023-08-20T00:00:00Z",
|
|
"2023-08-27T00:00:00Z",
|
|
},
|
|
{
|
|
"2023-08-27T00:00:00Z",
|
|
"2023-09-01T01:12:00Z",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
start := mustParseDatetime(tt.args.start)
|
|
end := mustParseDatetime(tt.args.end)
|
|
|
|
got, err := SplitDateRange(start, end, tt.args.granularity, false)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("splitDateRange() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
|
|
var testExpectedResults [][]time.Time
|
|
if tt.want != nil {
|
|
testExpectedResults = make([][]time.Time, 0)
|
|
for _, dr := range tt.want {
|
|
testExpectedResults = append(testExpectedResults, []time.Time{
|
|
mustParseDatetime(dr[0]),
|
|
mustParseDatetime(dr[1]),
|
|
})
|
|
}
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, testExpectedResults) {
|
|
t.Errorf("splitDateRange() got = %v, want %v", got, testExpectedResults)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_splitDateRange_reverse(t *testing.T) {
|
|
type args struct {
|
|
start string
|
|
end string
|
|
granularity string
|
|
timeReverse bool
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want []testTimeRange
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "validates start is before end",
|
|
args: args{
|
|
start: "2022-02-01T00:00:00Z",
|
|
end: "2022-01-01T00:00:00Z",
|
|
granularity: StepMonth,
|
|
timeReverse: true,
|
|
},
|
|
want: nil,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "validates granularity value",
|
|
args: args{
|
|
start: "2022-01-01T00:00:00Z",
|
|
end: "2022-02-01T00:00:00Z",
|
|
granularity: "non-existent-format",
|
|
timeReverse: true,
|
|
},
|
|
want: nil,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "month chunking",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-03-03T12:12:12Z",
|
|
granularity: StepMonth,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-03-01T00:00:00Z",
|
|
"2022-03-03T12:12:12Z",
|
|
},
|
|
{
|
|
"2022-02-01T00:00:00Z",
|
|
"2022-02-28T23:59:59.999999999Z",
|
|
},
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-31T23:59:59.999999999Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "daily chunking",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-01-05T12:12:12Z",
|
|
granularity: StepDay,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-05T11:11:11Z",
|
|
"2022-01-05T12:12:12Z",
|
|
},
|
|
{
|
|
"2022-01-04T11:11:11Z",
|
|
"2022-01-05T11:11:11Z",
|
|
},
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-04T11:11:11Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "hourly chunking",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-01-03T14:14:14Z",
|
|
granularity: StepHour,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T14:11:11Z",
|
|
"2022-01-03T14:14:14Z",
|
|
},
|
|
{
|
|
"2022-01-03T13:11:11Z",
|
|
"2022-01-03T14:11:11Z",
|
|
},
|
|
{
|
|
"2022-01-03T12:11:11Z",
|
|
"2022-01-03T13:11:11Z",
|
|
},
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-03T12:11:11Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "month chunking with one day time range",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-01-04T12:12:12Z",
|
|
granularity: StepMonth,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-04T12:12:12Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "month chunking with same day time range",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-01-03T12:12:12Z",
|
|
granularity: StepMonth,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-03T12:12:12Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "month chunking with one month and two days range",
|
|
args: args{
|
|
start: "2022-01-03T11:11:11Z",
|
|
end: "2022-02-03T00:00:00Z",
|
|
granularity: StepMonth,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2022-02-01T00:00:00Z",
|
|
"2022-02-03T00:00:00Z",
|
|
},
|
|
{
|
|
"2022-01-03T11:11:11Z",
|
|
"2022-01-31T23:59:59.999999999Z",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "week chunking with not full week",
|
|
args: args{
|
|
start: "2023-07-30T00:00:00Z",
|
|
end: "2023-08-05T23:59:59.999999999Z",
|
|
granularity: StepWeek,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2023-07-30T00:00:00Z",
|
|
"2023-08-05T23:59:59.999999999Z",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "week chunking with start of the week and end of the week",
|
|
args: args{
|
|
start: "2023-07-30T00:00:00Z",
|
|
end: "2023-08-06T00:00:00Z",
|
|
granularity: StepWeek,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2023-07-30T00:00:00Z",
|
|
"2023-08-06T00:00:00Z",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "week chunking with next one day week",
|
|
args: args{
|
|
start: "2023-07-30T00:00:00Z",
|
|
end: "2023-08-07T01:12:00Z",
|
|
granularity: StepWeek,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2023-08-06T00:00:00Z",
|
|
"2023-08-07T01:12:00Z",
|
|
},
|
|
{
|
|
"2023-07-30T00:00:00Z",
|
|
"2023-08-06T00:00:00Z",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "week chunking with month and not full week representation",
|
|
args: args{
|
|
start: "2023-07-30T00:00:00Z",
|
|
end: "2023-09-01T01:12:00Z",
|
|
granularity: StepWeek,
|
|
timeReverse: true,
|
|
},
|
|
want: []testTimeRange{
|
|
{
|
|
"2023-08-27T00:00:00Z",
|
|
"2023-09-01T01:12:00Z",
|
|
},
|
|
{
|
|
"2023-08-20T00:00:00Z",
|
|
"2023-08-27T00:00:00Z",
|
|
},
|
|
{
|
|
"2023-08-13T00:00:00Z",
|
|
"2023-08-20T00:00:00Z",
|
|
},
|
|
{
|
|
"2023-08-06T00:00:00Z",
|
|
"2023-08-13T00:00:00Z",
|
|
},
|
|
{
|
|
"2023-07-30T00:00:00Z",
|
|
"2023-08-06T00:00:00Z",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
start := mustParseDatetime(tt.args.start)
|
|
end := mustParseDatetime(tt.args.end)
|
|
|
|
got, err := SplitDateRange(start, end, tt.args.granularity, tt.args.timeReverse)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("splitDateRange() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
|
|
var testExpectedResults [][]time.Time
|
|
if tt.want != nil {
|
|
testExpectedResults = make([][]time.Time, 0)
|
|
for _, dr := range tt.want {
|
|
testExpectedResults = append(testExpectedResults, []time.Time{
|
|
mustParseDatetime(dr[0]),
|
|
mustParseDatetime(dr[1]),
|
|
})
|
|
}
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, testExpectedResults) {
|
|
t.Errorf("splitDateRange() got = %v, want %v", got, testExpectedResults)
|
|
}
|
|
})
|
|
}
|
|
}
|