mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-21 22:51:09 +02:00
* moving clientcountutil changes from ent * adding random usage time for repeated clients * replace math.rand with crypto.rand
498 lines
14 KiB
Go
498 lines
14 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package timeutil
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestTimeutil_StartOfPreviousMonth(t *testing.T) {
|
|
testCases := []struct {
|
|
Input time.Time
|
|
Expected time.Time
|
|
}{
|
|
{
|
|
Input: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2019, 12, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 15, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2019, 12, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 3, 31, 23, 59, 59, 999999999, time.UTC),
|
|
Expected: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := StartOfPreviousMonth(tc.Input)
|
|
if !result.Equal(tc.Expected) {
|
|
t.Errorf("start of month before %v is %v, got %v", tc.Input, tc.Expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_StartOfMonth(t *testing.T) {
|
|
testCases := []struct {
|
|
Input time.Time
|
|
Expected time.Time
|
|
}{
|
|
{
|
|
Input: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 1, 0, 0, 0, 1, time.UTC),
|
|
Expected: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.UTC),
|
|
Expected: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 2, 28, 1, 2, 3, 4, time.UTC),
|
|
Expected: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := StartOfMonth(tc.Input)
|
|
if !result.Equal(tc.Expected) {
|
|
t.Errorf("start of %v is %v, expected %v", tc.Input, result, tc.Expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_IsMonthStart(t *testing.T) {
|
|
testCases := []struct {
|
|
input time.Time
|
|
expected bool
|
|
}{
|
|
{
|
|
input: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
expected: true,
|
|
},
|
|
{
|
|
input: time.Date(2020, 1, 1, 0, 0, 0, 1, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: time.Date(2020, 4, 5, 0, 0, 0, 0, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.UTC),
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := IsMonthStart(tc.input)
|
|
if result != tc.expected {
|
|
t.Errorf("is %v the start of the month? expected %t, got %t", tc.input, tc.expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_EndOfMonth(t *testing.T) {
|
|
testCases := []struct {
|
|
Input time.Time
|
|
Expected time.Time
|
|
}{
|
|
{
|
|
// The current behavior does not use the nanoseconds
|
|
// because we didn't want to clutter the result of end-of-month reporting.
|
|
Input: time.Date(2020, 1, 31, 23, 59, 59, 0, time.UTC),
|
|
Expected: time.Date(2020, 1, 31, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 31, 23, 59, 59, 999999999, time.UTC),
|
|
Expected: time.Date(2020, 1, 31, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
{
|
|
Input: time.Date(2020, 1, 15, 1, 2, 3, 4, time.UTC),
|
|
Expected: time.Date(2020, 1, 31, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
{
|
|
// Leap year
|
|
Input: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2020, 2, 29, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
{
|
|
// non-leap year
|
|
Input: time.Date(2100, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
Expected: time.Date(2100, 2, 28, 23, 59, 59, 0, time.UTC),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := EndOfMonth(tc.Input)
|
|
if !result.Equal(tc.Expected) {
|
|
t.Errorf("end of %v is %v, expected %v", tc.Input, result, tc.Expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_IsPreviousMonth(t *testing.T) {
|
|
testCases := []struct {
|
|
tInput time.Time
|
|
compareInput time.Time
|
|
expected bool
|
|
}{
|
|
{
|
|
tInput: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 1, 31, 0, 0, 0, 0, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
tInput: time.Date(2019, 12, 31, 0, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 1, 31, 0, 0, 0, 0, time.UTC),
|
|
expected: true,
|
|
},
|
|
{
|
|
// leap year (false)
|
|
tInput: time.Date(2019, 12, 29, 10, 10, 10, 0, time.UTC),
|
|
compareInput: time.Date(2020, 2, 29, 10, 10, 10, 0, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
// leap year (true)
|
|
tInput: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 2, 29, 10, 10, 10, 0, time.UTC),
|
|
expected: true,
|
|
},
|
|
{
|
|
tInput: time.Date(2018, 5, 5, 5, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
expected: false,
|
|
},
|
|
{
|
|
// test normalization. want to make subtracting 1 month from 3/30/2020 doesn't yield 2/30/2020, normalized
|
|
// to 3/1/2020
|
|
tInput: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
compareInput: time.Date(2020, 3, 30, 0, 0, 0, 0, time.UTC),
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := IsPreviousMonth(tc.tInput, tc.compareInput)
|
|
if result != tc.expected {
|
|
t.Errorf("%v in previous month to %v? expected %t, got %t", tc.tInput, tc.compareInput, tc.expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeutil_IsCurrentMonth(t *testing.T) {
|
|
now := time.Now()
|
|
testCases := []struct {
|
|
input time.Time
|
|
expected bool
|
|
}{
|
|
{
|
|
input: now,
|
|
expected: true,
|
|
},
|
|
{
|
|
input: StartOfMonth(now).AddDate(0, 0, -1),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: EndOfMonth(now).AddDate(0, 0, -1),
|
|
expected: true,
|
|
},
|
|
{
|
|
input: StartOfMonth(now).AddDate(-1, 0, 0),
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := IsCurrentMonth(tc.input, now)
|
|
if result != tc.expected {
|
|
t.Errorf("invalid result. expected %t for %v", tc.expected, tc.input)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestTimeutil_IsCurrentDay checks if the test times equals the current day or not.
|
|
func TestTimeutil_IsCurrentDay(t *testing.T) {
|
|
now := time.Now()
|
|
testCases := []struct {
|
|
input time.Time
|
|
expected bool
|
|
}{
|
|
{
|
|
input: now,
|
|
expected: true,
|
|
},
|
|
{
|
|
input: StartOfDay(now).AddDate(0, 0, -1),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: StartOfDay(now).AddDate(-1, 0, 0),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: StartOfDay(now).Add(1 * time.Second),
|
|
expected: true,
|
|
},
|
|
{
|
|
input: StartOfDay(now).Add(-1 * time.Second),
|
|
expected: false,
|
|
},
|
|
{
|
|
input: StartOfDay(now).Add(86400), // a day is 86400 seconds
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := IsCurrentDay(tc.input, now)
|
|
if result != tc.expected {
|
|
t.Errorf("invalid result. expected %t for %v", tc.expected, tc.input)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeUtil_ContiguousMonths(t *testing.T) {
|
|
testCases := []struct {
|
|
input []time.Time
|
|
expected []time.Time
|
|
}{
|
|
{
|
|
input: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 2, 5, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expected: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 2, 5, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
{
|
|
input: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expected: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
{
|
|
input: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expected: []time.Time{
|
|
time.Date(2020, 4, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
{
|
|
input: []time.Time{},
|
|
expected: []time.Time{},
|
|
},
|
|
{
|
|
input: nil,
|
|
expected: nil,
|
|
},
|
|
{
|
|
input: []time.Time{
|
|
time.Date(2020, 2, 2, 0, 0, 0, 0, time.UTC),
|
|
time.Date(2020, 1, 15, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
expected: []time.Time{
|
|
time.Date(2020, 2, 2, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result := GetMostRecentContiguousMonths(tc.input)
|
|
|
|
if !reflect.DeepEqual(tc.expected, result) {
|
|
t.Errorf("invalid contiguous segment returned. expected %v, got %v", tc.expected, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTimeUtil_ParseTimeFromPath(t *testing.T) {
|
|
testCases := []struct {
|
|
input string
|
|
expectedOut time.Time
|
|
expectError bool
|
|
}{
|
|
{
|
|
input: "719020800/1",
|
|
expectedOut: time.Unix(719020800, 0).UTC(),
|
|
expectError: false,
|
|
},
|
|
{
|
|
input: "1601415205/3",
|
|
expectedOut: time.Unix(1601415205, 0).UTC(),
|
|
expectError: false,
|
|
},
|
|
{
|
|
input: "baddata/3",
|
|
expectedOut: time.Time{},
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
result, err := ParseTimeFromPath(tc.input)
|
|
gotError := err != nil
|
|
|
|
if result != tc.expectedOut {
|
|
t.Errorf("bad timestamp on input %q. expected: %v got: %v", tc.input, tc.expectedOut, result)
|
|
}
|
|
if gotError != tc.expectError {
|
|
t.Errorf("bad error status on input %q. expected error: %t, got error: %t", tc.input, tc.expectError, gotError)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestTimeUtil_NormalizeToYear tests NormalizeToYear function which returns the normalized input date wrt to the normal.
|
|
func TestTimeUtil_NormalizeToYear(t *testing.T) {
|
|
testCases := []struct {
|
|
inputDate time.Time
|
|
normalDate time.Time
|
|
expectedNormalizedDate time.Time
|
|
}{
|
|
{
|
|
inputDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2024, 10, 1, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2025, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2025, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2025, 10, 1, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2025, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
// inputDate more than 2 years prior to normal date
|
|
{
|
|
inputDate: time.Date(2022, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2024, 6, 15, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2023, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2022, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2024, 9, 28, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2023, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2022, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2022, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2024, 9, 30, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2020, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2024, 12, 1, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2024, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
// leap year test cases
|
|
{
|
|
inputDate: time.Date(2020, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2024, 9, 28, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2023, 9, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2025, 2, 28, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2025, 3, 2, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2028, 2, 28, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2027, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2028, 2, 29, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2027, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
{
|
|
inputDate: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
|
|
normalDate: time.Date(2028, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
expectedNormalizedDate: time.Date(2028, 3, 1, 0, 0, 0, 0, time.UTC),
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
normalizedDate := NormalizeToYear(tc.inputDate, tc.normalDate)
|
|
require.Equal(t, tc.expectedNormalizedDate, normalizedDate)
|
|
}
|
|
}
|
|
|
|
// Test_GetRandomTimeInMonth verifies that the random time generated is in the same month of input time.
|
|
func Test_GetRandomTimeInMonth(t *testing.T) {
|
|
currYear, _, _ := time.Now().Date()
|
|
middleOfMonth := time.Date(currYear, 8, 15, 1, 2, 3, 0, time.UTC)
|
|
|
|
cases := []struct {
|
|
name string
|
|
inputTime time.Time
|
|
}{
|
|
{
|
|
name: "input time is in the start of a month",
|
|
inputTime: StartOfMonth(time.Now()),
|
|
},
|
|
{
|
|
name: "input time is in the middle of a month",
|
|
inputTime: middleOfMonth,
|
|
},
|
|
{
|
|
name: "input time is in the last of a month ",
|
|
inputTime: EndOfMonth(time.Now()),
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
randomTime, err := GetRandomTimeInMonth(tc.inputTime)
|
|
require.NoError(t, err)
|
|
startOfMonth := StartOfMonth(tc.inputTime)
|
|
endOfMonth := EndOfMonth(tc.inputTime)
|
|
if !((randomTime.After(startOfMonth) || randomTime.Equal(startOfMonth)) && (randomTime.Before(endOfMonth) || randomTime.Equal(endOfMonth))) {
|
|
t.Fatalf("random time %v is not in the same month as input time %v", randomTime.UTC(), tc.inputTime.UTC())
|
|
}
|
|
})
|
|
}
|
|
}
|