mirror of
https://github.com/taigrr/most-specific-period.git
synced 2026-04-02 03:38:41 -07:00
Use a struct instead of string slices
This commit is contained in:
6
main.go
6
main.go
@@ -123,13 +123,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vals := msp.GenerateTimeline(periods...)
|
vals := msp.GenerateTimeline(periods...)
|
||||||
fmt.Print("\n")
|
fmt.Print("\nTimeline of changeovers:\n")
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
fmt.Print(val)
|
fmt.Println(val)
|
||||||
}
|
}
|
||||||
m, err := msp.MostSpecificPeriod(start, periods...)
|
m, err := msp.MostSpecificPeriod(start, periods...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("No significant period found")
|
fmt.Printf("No significant period found\n")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if terminal {
|
if terminal {
|
||||||
|
|||||||
@@ -26,81 +26,137 @@ func TestGetChangeOvers(t *testing.T) {
|
|||||||
testID string
|
testID string
|
||||||
result []time.Time
|
result []time.Time
|
||||||
periods []Period
|
periods []Period
|
||||||
}{{testID: "No choices",
|
}{
|
||||||
ts: now,
|
{
|
||||||
result: []time.Time{},
|
testID: "No choices",
|
||||||
periods: []Period{}},
|
ts: now,
|
||||||
{testID: "Two Choices, shorter is second",
|
result: []time.Time{},
|
||||||
|
periods: []Period{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, shorter is second",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []time.Time{now.Add(-5 * time.Minute), now.Add(-2 * time.Minute), now.Add(time.Minute)},
|
result: []time.Time{now.Add(-5 * time.Minute), now.Add(-2 * time.Minute), now.Add(time.Minute)},
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Two Choices, one is a year, other a minute",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one is a year, other a minute",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []time.Time{now.Add(-1 * time.Hour * 24 * 365), now.Add(-5 * time.Minute), now.Add(time.Minute)},
|
result: []time.Time{now.Add(-1 * time.Hour * 24 * 365), now.Add(-5 * time.Minute), now.Add(time.Minute)},
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-1 * time.Hour * 24 * 365),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-1 * time.Hour * 24 * 365),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{testID: "Two Choices, shorter is first",
|
{
|
||||||
|
testID: "Two Choices, shorter is first",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []time.Time{now.Add(-5 * time.Minute), now.Add(-2 * time.Minute), now.Add(time.Minute)},
|
result: []time.Time{now.Add(-5 * time.Minute), now.Add(-2 * time.Minute), now.Add(time.Minute)},
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Two Choices, one in the past",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one in the past",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []time.Time{now.Add(-2 * time.Minute), now.Add(-time.Minute), now.Add(time.Minute)},
|
result: []time.Time{now.Add(-2 * time.Minute), now.Add(-time.Minute), now.Add(time.Minute)},
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(-time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "Two Choices, one invalid",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one invalid",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []time.Time{now.Add(-2 * time.Minute), now.Add(time.Minute)},
|
result: []time.Time{now.Add(-2 * time.Minute), now.Add(time.Minute)},
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(-time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "Two Choices, Identical periods",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, Identical periods",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []time.Time{now.Add(-time.Minute), now.Add(time.Minute)},
|
result: []time.Time{now.Add(-time.Minute), now.Add(time.Minute)},
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "One choice",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "One choice",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []time.Time{now.Add(-time.Minute), now.Add(time.Minute)},
|
result: []time.Time{now.Add(-time.Minute), now.Add(time.Minute)},
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{TimeWindow{
|
||||||
|
StartTime: now.Add(-time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"}}}}
|
Identifier: "A",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) {
|
||||||
changeovers := GetChangeOvers(tc.periods...)
|
changeovers := GetChangeOvers(tc.periods...)
|
||||||
if !slicesEqual(changeovers, tc.result) {
|
if !slicesEqual(changeovers, tc.result) {
|
||||||
t.Errorf("Expected %v but got %v", tc.result, changeovers)
|
t.Errorf("Expected %v but got %v", tc.result, changeovers)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFlattenPeriods(t *testing.T) {
|
func TestFlattenPeriods(t *testing.T) {
|
||||||
// use a static timestamp to make sure tests don't fail on slower systems or during a process pause
|
// use a static timestamp to make sure tests don't fail on slower systems or during a process pause
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -110,92 +166,158 @@ func TestFlattenPeriods(t *testing.T) {
|
|||||||
result []string
|
result []string
|
||||||
err error
|
err error
|
||||||
periods []Period
|
periods []Period
|
||||||
}{{testID: "No choices",
|
}{
|
||||||
ts: now,
|
{
|
||||||
result: []string{},
|
testID: "No choices",
|
||||||
err: ErrNoValidPeriods,
|
ts: now,
|
||||||
periods: []Period{}},
|
result: []string{},
|
||||||
{testID: "Two Choices, shorter is second",
|
err: ErrNoValidPeriods,
|
||||||
|
periods: []Period{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, shorter is second",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []string{"A", "B"},
|
result: []string{"A", "B"},
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Two Choices, one is a year, other a minute",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one is a year, other a minute",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []string{"A", "B"},
|
result: []string{"A", "B"},
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-1 * time.Hour * 24 * 365),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-1 * time.Hour * 24 * 365),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{testID: "Two Choices, shorter is first",
|
{
|
||||||
|
testID: "Two Choices, shorter is first",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []string{"B", "A"},
|
result: []string{"B", "A"},
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Two Choices, one in the past",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one in the past",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []string{"B", "A"},
|
result: []string{"B", "A"},
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(-time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "Two Choices, one invalid",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one invalid",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []string{"B"},
|
result: []string{"B"},
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(-time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "Two Choices, Identical periods",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, Identical periods",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []string{"B"},
|
result: []string{"B"},
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Triple Nested Periods",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Triple Nested Periods",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []string{"A", "B", "C", "B", "A"},
|
result: []string{"A", "B", "C", "B", "A"},
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-15 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(15 * time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-15 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
EndTime: now.Add(15 * time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
EndTime: now.Add(5 * time.Minute),
|
EndTime: now.Add(5 * time.Minute),
|
||||||
Identifier: "C"},
|
Identifier: "C",
|
||||||
TimeWindow{StartTime: now.Add(-10 * time.Minute),
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-10 * time.Minute),
|
||||||
EndTime: now.Add(10 * time.Minute),
|
EndTime: now.Add(10 * time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "One choice",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "One choice",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: []string{"A"},
|
result: []string{"A"},
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{TimeWindow{
|
||||||
|
StartTime: now.Add(-time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"}}}}
|
Identifier: "A",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) {
|
||||||
@@ -203,10 +325,10 @@ func TestFlattenPeriods(t *testing.T) {
|
|||||||
if !slicesEqual(changeovers, tc.result) {
|
if !slicesEqual(changeovers, tc.result) {
|
||||||
t.Errorf("Expected %v but got %v", tc.result, changeovers)
|
t.Errorf("Expected %v but got %v", tc.result, changeovers)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetNextChangeOver(t *testing.T) {
|
func TestGetNextChangeOver(t *testing.T) {
|
||||||
// use a static timestamp to make sure tests don't fail on slower systems or during a process pause
|
// use a static timestamp to make sure tests don't fail on slower systems or during a process pause
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -216,79 +338,135 @@ func TestGetNextChangeOver(t *testing.T) {
|
|||||||
result time.Time
|
result time.Time
|
||||||
err error
|
err error
|
||||||
periods []Period
|
periods []Period
|
||||||
}{{testID: "No choices",
|
}{
|
||||||
ts: now,
|
{
|
||||||
result: time.Time{},
|
testID: "No choices",
|
||||||
err: ErrNoNextChangeover,
|
ts: now,
|
||||||
periods: []Period{}},
|
result: time.Time{},
|
||||||
{testID: "Two Choices, shorter is second",
|
err: ErrNoNextChangeover,
|
||||||
|
periods: []Period{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, shorter is second",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: now.Add(time.Minute),
|
result: now.Add(time.Minute),
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Two Choices, one is a year, other a minute",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one is a year, other a minute",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: now.Add(time.Minute),
|
result: now.Add(time.Minute),
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-1 * time.Hour * 24 * 365),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-1 * time.Hour * 24 * 365),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{testID: "Two Choices, shorter is first",
|
{
|
||||||
|
testID: "Two Choices, shorter is first",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: now.Add(time.Minute),
|
result: now.Add(time.Minute),
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Two Choices, one in the past",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one in the past",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: now.Add(time.Minute),
|
result: now.Add(time.Minute),
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(-time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "Two Choices, one invalid",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one invalid",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: now.Add(time.Minute),
|
result: now.Add(time.Minute),
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(-time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "Two Choices, Identical periods",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, Identical periods",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: now.Add(time.Minute),
|
result: now.Add(time.Minute),
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "One choice",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "One choice",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: now.Add(time.Minute),
|
result: now.Add(time.Minute),
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{TimeWindow{
|
||||||
|
StartTime: now.Add(-time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"}}}}
|
Identifier: "A",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) {
|
||||||
ts, err := GetNextChangeOver(now, tc.periods...)
|
ts, err := GetNextChangeOver(now, tc.periods...)
|
||||||
@@ -298,7 +476,6 @@ func TestGetNextChangeOver(t *testing.T) {
|
|||||||
if ts != tc.result {
|
if ts != tc.result {
|
||||||
t.Errorf("Got %v but expected %v", ts, tc.result)
|
t.Errorf("Got %v but expected %v", ts, tc.result)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
163
msp/msp_test.go
163
msp/msp_test.go
@@ -6,23 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TimeWindow struct {
|
// (periods ...Period) (id string, err error) {
|
||||||
StartTime time.Time
|
|
||||||
EndTime time.Time
|
|
||||||
Identifier string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p TimeWindow) GetIdentifier() string {
|
|
||||||
return p.Identifier
|
|
||||||
}
|
|
||||||
func (p TimeWindow) GetEndTime() time.Time {
|
|
||||||
return p.EndTime
|
|
||||||
}
|
|
||||||
func (p TimeWindow) GetStartTime() time.Time {
|
|
||||||
return p.StartTime
|
|
||||||
}
|
|
||||||
|
|
||||||
//(periods ...Period) (id string, err error) {
|
|
||||||
func TestMostSpecificPeriod(t *testing.T) {
|
func TestMostSpecificPeriod(t *testing.T) {
|
||||||
// use a static timestamp to make sure tests don't fail on slower systems or during a process pause
|
// use a static timestamp to make sure tests don't fail on slower systems or during a process pause
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -32,79 +16,135 @@ func TestMostSpecificPeriod(t *testing.T) {
|
|||||||
result string
|
result string
|
||||||
err error
|
err error
|
||||||
periods []Period
|
periods []Period
|
||||||
}{{testID: "No choices",
|
}{
|
||||||
ts: now,
|
{
|
||||||
result: "",
|
testID: "No choices",
|
||||||
err: ErrNoValidPeriods,
|
ts: now,
|
||||||
periods: []Period{}},
|
result: "",
|
||||||
{testID: "Two Choices, shorter is second",
|
err: ErrNoValidPeriods,
|
||||||
|
periods: []Period{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, shorter is second",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "B",
|
result: "B",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Two Choices, one is a year, other a minute",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one is a year, other a minute",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "B",
|
result: "B",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-1 * time.Hour * 24 * 365),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-1 * time.Hour * 24 * 365),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{testID: "Two Choices, shorter is first",
|
{
|
||||||
|
testID: "Two Choices, shorter is first",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "A",
|
result: "A",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "Two Choices, one in the past",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-5 * time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one in the past",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "A",
|
result: "A",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(-time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "Two Choices, one invalid",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, one invalid",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "B",
|
result: "B",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(-time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
|
Identifier: "A",
|
||||||
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B",
|
||||||
{testID: "Two Choices, Identical periods",
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "Two Choices, Identical periods",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "B",
|
result: "B",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{
|
||||||
EndTime: now.Add(time.Minute),
|
TimeWindow{
|
||||||
Identifier: "A"},
|
StartTime: now.Add(-time.Minute),
|
||||||
TimeWindow{StartTime: now.Add(-time.Minute),
|
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "A",
|
||||||
{testID: "One choice",
|
},
|
||||||
|
TimeWindow{
|
||||||
|
StartTime: now.Add(-time.Minute),
|
||||||
|
EndTime: now.Add(time.Minute),
|
||||||
|
Identifier: "B",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
testID: "One choice",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "A",
|
result: "A",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
periods: []Period{TimeWindow{
|
||||||
|
StartTime: now.Add(-time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"}}}}
|
Identifier: "A",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) {
|
||||||
id, err := MostSpecificPeriod(tc.ts, tc.periods...)
|
id, err := MostSpecificPeriod(tc.ts, tc.periods...)
|
||||||
@@ -114,7 +154,6 @@ func TestMostSpecificPeriod(t *testing.T) {
|
|||||||
if err != tc.err {
|
if err != tc.err {
|
||||||
t.Errorf("Error '%v' does not match expected '%v'", err, tc.err)
|
t.Errorf("Error '%v' does not match expected '%v'", err, tc.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,38 @@
|
|||||||
package msp
|
package msp
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TimeWindow struct {
|
||||||
|
StartTime time.Time
|
||||||
|
EndTime time.Time
|
||||||
|
Identifier string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p TimeWindow) GetIdentifier() string {
|
||||||
|
return p.Identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p TimeWindow) GetEndTime() time.Time {
|
||||||
|
return p.EndTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p TimeWindow) GetStartTime() time.Time {
|
||||||
|
return p.StartTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t TimeWindow) String() string {
|
||||||
|
return fmt.Sprintf("%s\t%s\t%s",
|
||||||
|
t.GetIdentifier(),
|
||||||
|
t.GetStartTime(),
|
||||||
|
t.GetEndTime())
|
||||||
|
}
|
||||||
|
|
||||||
// Outputs a formatted timeline of periods
|
// Outputs a formatted timeline of periods
|
||||||
func GenerateTimeline(periods ...Period) (out []string) {
|
func GenerateTimeline(periods ...Period) (out []Period) {
|
||||||
if len(periods) == 0 {
|
if len(periods) == 0 {
|
||||||
out = []string{}
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
periodsByID := make(map[string]Period)
|
periodsByID := make(map[string]Period)
|
||||||
@@ -22,8 +49,7 @@ func GenerateTimeline(periods ...Period) (out []string) {
|
|||||||
start = periodsByID[val].GetStartTime()
|
start = periodsByID[val].GetStartTime()
|
||||||
next = periodsByID[val].GetEndTime()
|
next = periodsByID[val].GetEndTime()
|
||||||
}
|
}
|
||||||
frame := fmt.Sprintf("%s\t%s\t%s\n", val, start, next)
|
out = append(out, TimeWindow{StartTime: start, EndTime: next, Identifier: val})
|
||||||
out = append(out, frame)
|
|
||||||
start = next
|
start = next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ func TestGenerateTime(t *testing.T) {
|
|||||||
t.Fatalf("Time line had %d results, expected %d", len(timeline), len(tc.result))
|
t.Fatalf("Time line had %d results, expected %d", len(timeline), len(tc.result))
|
||||||
}
|
}
|
||||||
for idx, period := range timeline {
|
for idx, period := range timeline {
|
||||||
if period != tc.result[idx] {
|
if period.(TimeWindow).String()+"\n" != tc.result[idx] {
|
||||||
t.Errorf("Expected:\t%s\nHad:\t%s", period, tc.result[idx])
|
t.Errorf("Expected:\t%s\nHad:\t%s", period, tc.result[idx])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user