mirror of
https://github.com/rancher/steve.git
synced 2025-08-01 23:03:28 +00:00
Adding tests for improved schema cache
This commit is contained in:
parent
2f8e64840b
commit
0f32ff22e0
47
pkg/debounce/refresher_test.go
Normal file
47
pkg/debounce/refresher_test.go
Normal file
@ -0,0 +1,47 @@
|
||||
package debounce
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type refreshable struct {
|
||||
wasRefreshed atomic.Bool
|
||||
retErr error
|
||||
}
|
||||
|
||||
func (r *refreshable) Refresh() error {
|
||||
r.wasRefreshed.Store(true)
|
||||
return r.retErr
|
||||
}
|
||||
|
||||
func TestRefreshAfter(t *testing.T) {
|
||||
ref := refreshable{}
|
||||
debounce := DebounceableRefresher{
|
||||
Refreshable: &ref,
|
||||
}
|
||||
debounce.RefreshAfter(time.Millisecond * 2)
|
||||
debounce.RefreshAfter(time.Microsecond * 2)
|
||||
time.Sleep(time.Millisecond * 1)
|
||||
// test that the second refresh call overrode the first - Micro < Milli so this should have ran
|
||||
require.True(t, ref.wasRefreshed.Load())
|
||||
ref.wasRefreshed.Store(false)
|
||||
time.Sleep(time.Millisecond * 2)
|
||||
// test that the call was debounced - though we called this twice only one refresh should be called
|
||||
require.False(t, ref.wasRefreshed.Load())
|
||||
|
||||
ref = refreshable{
|
||||
retErr: fmt.Errorf("Some error"),
|
||||
}
|
||||
debounce = DebounceableRefresher{
|
||||
Refreshable: &ref,
|
||||
}
|
||||
debounce.RefreshAfter(time.Microsecond * 2)
|
||||
// test the error case
|
||||
time.Sleep(time.Millisecond * 1)
|
||||
require.True(t, ref.wasRefreshed.Load())
|
||||
}
|
@ -3,7 +3,6 @@ package definitions
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
openapi_v2 "github.com/google/gnostic-models/openapiv2"
|
||||
"github.com/rancher/apiserver/pkg/apierror"
|
||||
@ -16,166 +15,50 @@ import (
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/openapi"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/kube-openapi/pkg/util/proto"
|
||||
)
|
||||
|
||||
var globalRoleObject = types.APIObject{
|
||||
ID: "management.cattle.io.globalrole",
|
||||
Type: "schemaDefinition",
|
||||
Object: schemaDefinition{
|
||||
DefinitionType: "io.cattle.management.v2.GlobalRole",
|
||||
Definitions: map[string]definition{
|
||||
"io.cattle.management.v2.GlobalRole": {
|
||||
ResourceFields: map[string]definitionField{
|
||||
"apiVersion": {
|
||||
Type: "string",
|
||||
Description: "The APIVersion of this resource",
|
||||
},
|
||||
"kind": {
|
||||
Type: "string",
|
||||
Description: "The kind",
|
||||
},
|
||||
"metadata": {
|
||||
Type: "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta",
|
||||
Description: "The metadata",
|
||||
},
|
||||
"spec": {
|
||||
Type: "io.cattle.management.v2.GlobalRole.spec", Description: "The spec for the project",
|
||||
},
|
||||
},
|
||||
Type: "io.cattle.management.v2.GlobalRole",
|
||||
Description: "A Global Role V2 provides Global Permissions in Rancher",
|
||||
},
|
||||
"io.cattle.management.v2.GlobalRole.spec": {
|
||||
ResourceFields: map[string]definitionField{
|
||||
"clusterName": {
|
||||
Type: "string",
|
||||
Description: "The name of the cluster",
|
||||
Required: true,
|
||||
},
|
||||
"displayName": {
|
||||
Type: "string",
|
||||
Description: "The UI readable name",
|
||||
Required: true,
|
||||
},
|
||||
"newField": {
|
||||
Type: "string",
|
||||
Description: "A new field not present in v1",
|
||||
},
|
||||
"notRequired": {
|
||||
Type: "boolean",
|
||||
Description: "Some field that isn't required",
|
||||
},
|
||||
},
|
||||
Type: "io.cattle.management.v2.GlobalRole.spec",
|
||||
Description: "The spec for the project",
|
||||
},
|
||||
"io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": {
|
||||
ResourceFields: map[string]definitionField{
|
||||
"annotations": {
|
||||
Type: "map",
|
||||
SubType: "string",
|
||||
Description: "annotations of the resource",
|
||||
},
|
||||
"name": {
|
||||
Type: "string",
|
||||
SubType: "",
|
||||
Description: "name of the resource",
|
||||
},
|
||||
},
|
||||
Type: "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta",
|
||||
Description: "Object Metadata",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestByID(t *testing.T) {
|
||||
schemas := types.EmptyAPISchemas()
|
||||
addBaseSchema := func(names ...string) {
|
||||
for _, name := range names {
|
||||
schemas.MustAddSchema(types.APISchema{
|
||||
Schema: &wschemas.Schema{
|
||||
ID: name,
|
||||
CollectionMethods: []string{"get"},
|
||||
ResourceMethods: []string{"get"},
|
||||
},
|
||||
})
|
||||
}
|
||||
func TestRefresh(t *testing.T) {
|
||||
defaultDocument, err := openapi_v2.ParseDocument([]byte(openapi_raw))
|
||||
require.NoError(t, err)
|
||||
defaultModels, err := proto.NewOpenAPIData(defaultDocument)
|
||||
require.NoError(t, err)
|
||||
defaultSchemaToModel := map[string]string{
|
||||
"management.cattle.io.globalrole": "io.cattle.management.v2.GlobalRole",
|
||||
}
|
||||
|
||||
intPtr := func(input int) *int {
|
||||
return &input
|
||||
}
|
||||
|
||||
addBaseSchema("management.cattle.io.globalrole", "management.cattle.io.missingfrommodel")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
schemaName string
|
||||
needsRefresh bool
|
||||
openapiError error
|
||||
serverGroupsResourcesErr error
|
||||
useBadOpenApiDoc bool
|
||||
unparseableGV bool
|
||||
wantObject *types.APIObject
|
||||
wantModels *proto.Models
|
||||
wantSchemaToModel map[string]string
|
||||
wantError bool
|
||||
wantErrorCode *int
|
||||
}{
|
||||
{
|
||||
name: "global role definition",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
needsRefresh: true,
|
||||
wantObject: &globalRoleObject,
|
||||
name: "success",
|
||||
wantModels: &defaultModels,
|
||||
wantSchemaToModel: defaultSchemaToModel,
|
||||
},
|
||||
{
|
||||
name: "missing definition",
|
||||
schemaName: "management.cattle.io.cluster",
|
||||
needsRefresh: true,
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(404),
|
||||
name: "error - openapi doc unavailable",
|
||||
openapiError: fmt.Errorf("server unavailable"),
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "not refreshed",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
needsRefresh: false,
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(503),
|
||||
},
|
||||
{
|
||||
name: "missing from model",
|
||||
schemaName: "management.cattle.io.missingfrommodel",
|
||||
needsRefresh: true,
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(503),
|
||||
},
|
||||
{
|
||||
name: "refresh error - openapi doc unavailable",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
needsRefresh: true,
|
||||
openapiError: fmt.Errorf("server unavailable"),
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(500),
|
||||
},
|
||||
{
|
||||
name: "refresh error - unable to parse openapi doc",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
needsRefresh: true,
|
||||
name: "error - unable to parse openapi doc",
|
||||
useBadOpenApiDoc: true,
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(500),
|
||||
},
|
||||
{
|
||||
name: "refresh error - unable to retrieve groups and resources",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
needsRefresh: true,
|
||||
name: "error - unable to retrieve groups and resources",
|
||||
serverGroupsResourcesErr: fmt.Errorf("server not available"),
|
||||
wantModels: &defaultModels,
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(500),
|
||||
},
|
||||
{
|
||||
name: "refresh error - unable to retrieve all groups and resources",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
needsRefresh: true,
|
||||
name: "error - unable to retrieve all groups and resources",
|
||||
serverGroupsResourcesErr: &discovery.ErrGroupDiscoveryFailed{
|
||||
Groups: map[schema.GroupVersion]error{
|
||||
{
|
||||
@ -184,19 +67,18 @@ func TestByID(t *testing.T) {
|
||||
}: fmt.Errorf("some group error"),
|
||||
},
|
||||
},
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(500),
|
||||
wantModels: &defaultModels,
|
||||
wantSchemaToModel: defaultSchemaToModel,
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "refresh error - unparesable gv",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
needsRefresh: true,
|
||||
unparseableGV: true,
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(500),
|
||||
name: "error - unparesable gv",
|
||||
unparseableGV: true,
|
||||
wantModels: &defaultModels,
|
||||
wantSchemaToModel: defaultSchemaToModel,
|
||||
wantError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
@ -216,12 +98,175 @@ func TestByID(t *testing.T) {
|
||||
})
|
||||
}
|
||||
require.Nil(t, err)
|
||||
handler := schemaDefinitionHandler{
|
||||
handler := SchemaDefinitionHandler{
|
||||
client: client,
|
||||
}
|
||||
if !test.needsRefresh {
|
||||
handler.lastRefresh = time.Now()
|
||||
handler.refreshStale = time.Minute * 1
|
||||
err = handler.Refresh()
|
||||
if test.wantError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
require.Equal(t, test.wantModels, handler.models)
|
||||
require.Equal(t, test.wantSchemaToModel, handler.schemaToModel)
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func Test_byID(t *testing.T) {
|
||||
defaultDocument, err := openapi_v2.ParseDocument([]byte(openapi_raw))
|
||||
require.NoError(t, err)
|
||||
defaultModels, err := proto.NewOpenAPIData(defaultDocument)
|
||||
require.NoError(t, err)
|
||||
defaultSchemaToModel := map[string]string{
|
||||
"management.cattle.io.globalrole": "io.cattle.management.v2.GlobalRole",
|
||||
}
|
||||
schemas := types.EmptyAPISchemas()
|
||||
addBaseSchema := func(names ...string) {
|
||||
for _, name := range names {
|
||||
schemas.MustAddSchema(types.APISchema{
|
||||
Schema: &wschemas.Schema{
|
||||
ID: name,
|
||||
CollectionMethods: []string{"get"},
|
||||
ResourceMethods: []string{"get"},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
intPtr := func(input int) *int {
|
||||
return &input
|
||||
}
|
||||
|
||||
addBaseSchema("management.cattle.io.globalrole", "management.cattle.io.missingfrommodel", "management.cattle.io.notakind")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
schemaName string
|
||||
models *proto.Models
|
||||
schemaToModel map[string]string
|
||||
wantObject *types.APIObject
|
||||
wantError bool
|
||||
wantErrorCode *int
|
||||
}{
|
||||
{
|
||||
name: "global role definition",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
models: &defaultModels,
|
||||
schemaToModel: defaultSchemaToModel,
|
||||
wantObject: &types.APIObject{
|
||||
ID: "management.cattle.io.globalrole",
|
||||
Type: "schemaDefinition",
|
||||
Object: schemaDefinition{
|
||||
DefinitionType: "io.cattle.management.v2.GlobalRole",
|
||||
Definitions: map[string]definition{
|
||||
"io.cattle.management.v2.GlobalRole": {
|
||||
ResourceFields: map[string]definitionField{
|
||||
"apiVersion": {
|
||||
Type: "string",
|
||||
Description: "The APIVersion of this resource",
|
||||
},
|
||||
"kind": {
|
||||
Type: "string",
|
||||
Description: "The kind",
|
||||
},
|
||||
"metadata": {
|
||||
Type: "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta",
|
||||
Description: "The metadata",
|
||||
},
|
||||
"spec": {
|
||||
Type: "io.cattle.management.v2.GlobalRole.spec", Description: "The spec for the project",
|
||||
},
|
||||
},
|
||||
Type: "io.cattle.management.v2.GlobalRole",
|
||||
Description: "A Global Role V2 provides Global Permissions in Rancher",
|
||||
},
|
||||
"io.cattle.management.v2.GlobalRole.spec": {
|
||||
ResourceFields: map[string]definitionField{
|
||||
"clusterName": {
|
||||
Type: "string",
|
||||
Description: "The name of the cluster",
|
||||
Required: true,
|
||||
},
|
||||
"displayName": {
|
||||
Type: "string",
|
||||
Description: "The UI readable name",
|
||||
Required: true,
|
||||
},
|
||||
"newField": {
|
||||
Type: "string",
|
||||
Description: "A new field not present in v1",
|
||||
},
|
||||
"notRequired": {
|
||||
Type: "boolean",
|
||||
Description: "Some field that isn't required",
|
||||
},
|
||||
},
|
||||
Type: "io.cattle.management.v2.GlobalRole.spec",
|
||||
Description: "The spec for the project",
|
||||
},
|
||||
"io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta": {
|
||||
ResourceFields: map[string]definitionField{
|
||||
"annotations": {
|
||||
Type: "map",
|
||||
SubType: "string",
|
||||
Description: "annotations of the resource",
|
||||
},
|
||||
"name": {
|
||||
Type: "string",
|
||||
SubType: "",
|
||||
Description: "name of the resource",
|
||||
},
|
||||
},
|
||||
Type: "io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta",
|
||||
Description: "Object Metadata",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing definition",
|
||||
schemaName: "management.cattle.io.cluster",
|
||||
models: &defaultModels,
|
||||
schemaToModel: defaultSchemaToModel,
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(404),
|
||||
},
|
||||
{
|
||||
name: "not refreshed",
|
||||
schemaName: "management.cattle.io.globalrole",
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(503),
|
||||
},
|
||||
{
|
||||
name: "has schema, missing from model",
|
||||
schemaName: "management.cattle.io.missingfrommodel",
|
||||
models: &defaultModels,
|
||||
schemaToModel: defaultSchemaToModel,
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(503),
|
||||
},
|
||||
{
|
||||
name: "has schema, model is not a kind",
|
||||
schemaName: "management.cattle.io.notakind",
|
||||
models: &defaultModels,
|
||||
schemaToModel: map[string]string{
|
||||
"management.cattle.io.notakind": "io.management.cattle.NotAKind",
|
||||
},
|
||||
wantError: true,
|
||||
wantErrorCode: intPtr(500),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
handler := SchemaDefinitionHandler{
|
||||
models: test.models,
|
||||
schemaToModel: test.schemaToModel,
|
||||
}
|
||||
request := types.APIRequest{
|
||||
Schemas: schemas,
|
||||
|
@ -82,7 +82,7 @@ definitions:
|
||||
- group: "management.cattle.io"
|
||||
version: "v2"
|
||||
kind: "GlobalRole"
|
||||
io.management.cattle.NotAKind:
|
||||
io.cattle.management.NotAKind:
|
||||
type: "string"
|
||||
description: "Some string which isn't a kind"
|
||||
io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta:
|
||||
|
84
pkg/schema/definitions/refresh_test.go
Normal file
84
pkg/schema/definitions/refresh_test.go
Normal file
@ -0,0 +1,84 @@
|
||||
package definitions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rancher/steve/pkg/debounce"
|
||||
"github.com/stretchr/testify/require"
|
||||
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
apiregv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
)
|
||||
|
||||
type refreshable struct {
|
||||
wasRefreshed atomic.Bool
|
||||
}
|
||||
|
||||
func (r *refreshable) Refresh() error {
|
||||
r.wasRefreshed.Store(true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Test_onChangeCRD(t *testing.T) {
|
||||
internalRefresh := refreshable{}
|
||||
refresher := debounce.DebounceableRefresher{
|
||||
Refreshable: &internalRefresh,
|
||||
}
|
||||
refreshHandler := refreshHandler{
|
||||
debounceRef: &refresher,
|
||||
debounceDuration: time.Microsecond * 5,
|
||||
}
|
||||
input := apiextv1.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-crd",
|
||||
},
|
||||
}
|
||||
output, err := refreshHandler.onChangeCRD("test-crd", &input)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, input, *output)
|
||||
// waiting to allow the debouncer to refresh the refreshable
|
||||
time.Sleep(time.Millisecond * 2)
|
||||
require.True(t, internalRefresh.wasRefreshed.Load())
|
||||
}
|
||||
|
||||
func Test_onChangeAPIService(t *testing.T) {
|
||||
internalRefresh := refreshable{}
|
||||
refresher := debounce.DebounceableRefresher{
|
||||
Refreshable: &internalRefresh,
|
||||
}
|
||||
refreshHandler := refreshHandler{
|
||||
debounceRef: &refresher,
|
||||
debounceDuration: time.Microsecond * 5,
|
||||
}
|
||||
input := apiregv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-apiservice",
|
||||
},
|
||||
}
|
||||
output, err := refreshHandler.onChangeAPIService("test-apiservice", &input)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, input, *output)
|
||||
// waiting to allow the debouncer to refresh the refreshable
|
||||
time.Sleep(time.Millisecond * 2)
|
||||
require.True(t, internalRefresh.wasRefreshed.Load())
|
||||
|
||||
}
|
||||
|
||||
func Test_startBackgroundRefresh(t *testing.T) {
|
||||
internalRefresh := refreshable{}
|
||||
refresher := debounce.DebounceableRefresher{
|
||||
Refreshable: &internalRefresh,
|
||||
}
|
||||
refreshHandler := refreshHandler{
|
||||
debounceRef: &refresher,
|
||||
debounceDuration: time.Microsecond * 5,
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
refreshHandler.startBackgroundRefresh(ctx, time.Microsecond*10)
|
||||
time.Sleep(time.Millisecond * 2)
|
||||
require.True(t, internalRefresh.wasRefreshed.Load())
|
||||
cancel()
|
||||
}
|
76
pkg/schema/definitions/schema_test.go
Normal file
76
pkg/schema/definitions/schema_test.go
Normal file
@ -0,0 +1,76 @@
|
||||
package definitions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/rancher/apiserver/pkg/types"
|
||||
"github.com/rancher/wrangler/v2/pkg/generic/fake"
|
||||
"github.com/stretchr/testify/require"
|
||||
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
apiregv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
)
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
schemas := types.EmptyAPISchemas()
|
||||
client := fakeDiscovery{}
|
||||
ctrl := gomock.NewController(t)
|
||||
crdController := fake.NewMockNonNamespacedControllerInterface[*apiextv1.CustomResourceDefinition, *apiextv1.CustomResourceDefinitionList](ctrl)
|
||||
apisvcController := fake.NewMockNonNamespacedControllerInterface[*apiregv1.APIService, *apiregv1.APIServiceList](ctrl)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
crdController.EXPECT().OnChange(ctx, handlerKey, gomock.Any())
|
||||
apisvcController.EXPECT().OnChange(ctx, handlerKey, gomock.Any())
|
||||
Register(ctx, schemas, &client, crdController, apisvcController)
|
||||
registeredSchema := schemas.LookupSchema("schemaDefinition")
|
||||
require.NotNil(t, registeredSchema)
|
||||
require.Len(t, registeredSchema.ResourceMethods, 1)
|
||||
require.Equal(t, registeredSchema.ResourceMethods[0], "GET")
|
||||
require.NotNil(t, registeredSchema.ByIDHandler)
|
||||
// Register will spawn a background thread, so we want to stop that to not impact other tests
|
||||
cancel()
|
||||
}
|
||||
|
||||
func Test_getDurationEnvVarOrDefault(t *testing.T) {
|
||||
os.Setenv("VALID", "1")
|
||||
os.Setenv("INVALID", "NOTANUMBER")
|
||||
tests := []struct {
|
||||
name string
|
||||
envVar string
|
||||
defaultValue int
|
||||
unit time.Duration
|
||||
wantDuration time.Duration
|
||||
}{
|
||||
{
|
||||
name: "not found, use default",
|
||||
envVar: "NOT_FOUND",
|
||||
defaultValue: 12,
|
||||
unit: time.Second,
|
||||
wantDuration: time.Second * 12,
|
||||
},
|
||||
{
|
||||
name: "found but not an int",
|
||||
envVar: "INVALID",
|
||||
defaultValue: 24,
|
||||
unit: time.Minute,
|
||||
wantDuration: time.Minute * 24,
|
||||
},
|
||||
{
|
||||
name: "found and valid int",
|
||||
envVar: "VALID",
|
||||
defaultValue: 30,
|
||||
unit: time.Hour,
|
||||
wantDuration: time.Hour * 1,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got := getDurationEnvVarOrDefault(test.envVar, test.defaultValue, test.unit)
|
||||
require.Equal(t, test.wantDuration, got)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user