diff --git a/Makefile b/Makefile index 4401711ac..5461cf128 100644 --- a/Makefile +++ b/Makefile @@ -90,9 +90,12 @@ start-docs: ## Start the local mkdocs based development environment. clean-docs: ## Remove all local mkdocs Docker images (cleanup). docker container prune --force --filter "label=project=onmetal_api_documentation" -ENVTEST_ASSETS_DIR=$(shell pwd)/testbin .PHONY: test -test: manifests generate fmt vet ## Run tests. +test: manifests generate fmt vet test-only ## Run tests. + +ENVTEST_ASSETS_DIR=$(shell pwd)/testbin +.PHONY: test-only +test-only: ## Run *only* the tests - no generation, linting etc. mkdir -p ${ENVTEST_ASSETS_DIR} test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.8.3/hack/setup-envtest.sh source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out diff --git a/apis/common/v1alpha1/common_types_test.go b/apis/common/v1alpha1/common_types_test.go index d0e7c081f..fb0701a72 100644 --- a/apis/common/v1alpha1/common_types_test.go +++ b/apis/common/v1alpha1/common_types_test.go @@ -17,7 +17,7 @@ package v1alpha1 import ( - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) diff --git a/apis/common/v1alpha1/suite_test.go b/apis/common/v1alpha1/suite_test.go index 803b44647..f052ee199 100644 --- a/apis/common/v1alpha1/suite_test.go +++ b/apis/common/v1alpha1/suite_test.go @@ -19,7 +19,7 @@ package v1alpha1 import ( "testing" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) diff --git a/apis/ipam/validation/prefix_test.go b/apis/ipam/validation/prefix_test.go index 7fd7949db..e7bde9e46 100644 --- a/apis/ipam/validation/prefix_test.go +++ b/apis/ipam/validation/prefix_test.go @@ -19,8 +19,7 @@ import ( "github.com/onmetal/onmetal-api/apis/ipam" . "github.com/onmetal/onmetal-api/apis/ipam/validation" . "github.com/onmetal/onmetal-api/testutils/validation" - . "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" diff --git a/apis/ipam/validation/prefixallocation_test.go b/apis/ipam/validation/prefixallocation_test.go index 672c4cd28..bf67c4d40 100644 --- a/apis/ipam/validation/prefixallocation_test.go +++ b/apis/ipam/validation/prefixallocation_test.go @@ -18,8 +18,7 @@ import ( commonv1alpha1 "github.com/onmetal/onmetal-api/apis/common/v1alpha1" "github.com/onmetal/onmetal-api/apis/ipam" . "github.com/onmetal/onmetal-api/testutils/validation" - . "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" diff --git a/apis/ipam/validation/prefixtemplate_test.go b/apis/ipam/validation/prefixtemplate_test.go index 4a94feffc..ddbc90599 100644 --- a/apis/ipam/validation/prefixtemplate_test.go +++ b/apis/ipam/validation/prefixtemplate_test.go @@ -17,8 +17,7 @@ package validation_test import ( "github.com/onmetal/onmetal-api/apis/ipam" . "github.com/onmetal/onmetal-api/testutils/validation" - . "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" diff --git a/apis/ipam/validation/validation_suite_test.go b/apis/ipam/validation/validation_suite_test.go index d1004a13e..f01c77456 100644 --- a/apis/ipam/validation/validation_suite_test.go +++ b/apis/ipam/validation/validation_suite_test.go @@ -17,7 +17,7 @@ package validation_test import ( "testing" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) diff --git a/apis/storage/validation/validation_suite_test.go b/apis/storage/validation/validation_suite_test.go index d1004a13e..f01c77456 100644 --- a/apis/storage/validation/validation_suite_test.go +++ b/apis/storage/validation/validation_suite_test.go @@ -17,7 +17,7 @@ package validation_test import ( "testing" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) diff --git a/apis/storage/validation/volume_test.go b/apis/storage/validation/volume_test.go index 9f7144e93..03828f9de 100644 --- a/apis/storage/validation/volume_test.go +++ b/apis/storage/validation/volume_test.go @@ -18,8 +18,7 @@ import ( "github.com/onmetal/onmetal-api/apis/storage" . "github.com/onmetal/onmetal-api/apis/storage/validation" . "github.com/onmetal/onmetal-api/testutils/validation" - . "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" diff --git a/apis/storage/validation/volumeclaim_test.go b/apis/storage/validation/volumeclaim_test.go index f98553926..300f808dc 100644 --- a/apis/storage/validation/volumeclaim_test.go +++ b/apis/storage/validation/volumeclaim_test.go @@ -18,8 +18,7 @@ import ( "github.com/onmetal/onmetal-api/apis/storage" . "github.com/onmetal/onmetal-api/apis/storage/validation" . "github.com/onmetal/onmetal-api/testutils/validation" - . "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" diff --git a/apis/storage/validation/volumeclass_test.go b/apis/storage/validation/volumeclass_test.go index 85ed154cc..c7023830c 100644 --- a/apis/storage/validation/volumeclass_test.go +++ b/apis/storage/validation/volumeclass_test.go @@ -18,8 +18,7 @@ import ( "github.com/onmetal/onmetal-api/apis/storage" . "github.com/onmetal/onmetal-api/apis/storage/validation" . "github.com/onmetal/onmetal-api/testutils/validation" - . "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" corev1 "k8s.io/api/core/v1" diff --git a/apis/storage/validation/volumepool_test.go b/apis/storage/validation/volumepool_test.go index b70d1779f..74af2f778 100644 --- a/apis/storage/validation/volumepool_test.go +++ b/apis/storage/validation/volumepool_test.go @@ -18,8 +18,7 @@ import ( "github.com/onmetal/onmetal-api/apis/storage" . "github.com/onmetal/onmetal-api/apis/storage/validation" . "github.com/onmetal/onmetal-api/testutils/validation" - . "github.com/onsi/ginkgo" - . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/types" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/controllers/compute/machine_controller_test.go b/controllers/compute/machine_controller_test.go index f83916928..597f3f7a5 100644 --- a/controllers/compute/machine_controller_test.go +++ b/controllers/compute/machine_controller_test.go @@ -17,7 +17,7 @@ package compute import ( - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" ) var _ = Describe("machine controller", func() { diff --git a/controllers/compute/machine_scheduler_test.go b/controllers/compute/machine_scheduler_test.go index dc5cc4a10..5410a9713 100644 --- a/controllers/compute/machine_scheduler_test.go +++ b/controllers/compute/machine_scheduler_test.go @@ -15,7 +15,8 @@ package compute import ( - . "github.com/onsi/ginkgo" + "github.com/onmetal/onmetal-api/testutils" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -26,6 +27,7 @@ import ( ) var _ = Describe("MachineScheduler", func() { + ctx := testutils.SetupContext() ns := SetupTest(ctx) It("should schedule machines on machine pools", func() { @@ -219,7 +221,7 @@ var _ = Describe("MachineScheduler", func() { Consistently(func() string { Expect(k8sClient.Get(ctx, machineKey, machine)).To(Succeed()) return machine.Spec.MachinePoolRef.Name - }, timeout, interval).Should(BeEmpty()) + }).Should(BeEmpty()) By("patching the machine to contain only one of the corresponding tolerations") machineBase := machine.DeepCopy() @@ -235,7 +237,7 @@ var _ = Describe("MachineScheduler", func() { Consistently(func() string { Expect(k8sClient.Get(ctx, machineKey, machine)).To(Succeed()) return machine.Spec.MachinePoolRef.Name - }, timeout, interval).Should(BeEmpty()) + }).Should(BeEmpty()) By("patching the machine to contain all of the corresponding tolerations") machineBase = machine.DeepCopy() diff --git a/controllers/compute/machineclass_controller_test.go b/controllers/compute/machineclass_controller_test.go index c59fc0084..fc34e1d0c 100644 --- a/controllers/compute/machineclass_controller_test.go +++ b/controllers/compute/machineclass_controller_test.go @@ -17,7 +17,8 @@ package compute import ( - . "github.com/onsi/ginkgo" + "github.com/onmetal/onmetal-api/testutils" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -28,6 +29,7 @@ import ( ) var _ = Describe("machineclass controller", func() { + ctx := testutils.SetupContext() ns := SetupTest(ctx) It("removes the finalizer from machineclass only if there's no machine still using the machineclass", func() { By("creating the machineclass consumed by the machine") @@ -60,7 +62,7 @@ var _ = Describe("machineclass controller", func() { Expect(client.IgnoreNotFound(err)).To(Succeed(), "errors other than `not found` are not expected") g.Expect(err).NotTo(HaveOccurred()) return machineClass.Finalizers - }, timeout, interval).Should(ContainElement(computev1alpha1.MachineClassFinalizer)) + }).Should(ContainElement(computev1alpha1.MachineClassFinalizer)) By("checking the machineclass and its finalizer consistently exist upon deletion ") Expect(k8sClient.Delete(ctx, machineClass)).Should(Succeed()) @@ -70,7 +72,7 @@ var _ = Describe("machineclass controller", func() { Expect(client.IgnoreNotFound(err)).To(Succeed(), "errors other than `not found` are not expected") g.Expect(err).NotTo(HaveOccurred()) return machineClass.Finalizers - }, timeout).Should(ContainElement(computev1alpha1.MachineClassFinalizer)) + }).Should(ContainElement(computev1alpha1.MachineClassFinalizer)) By("checking the machineclass is eventually gone after the deletion of the machine") Expect(k8sClient.Delete(ctx, m)).Should(Succeed()) @@ -78,6 +80,6 @@ var _ = Describe("machineclass controller", func() { err := k8sClient.Get(ctx, machineClassKey, machineClass) Expect(client.IgnoreNotFound(err)).To(Succeed(), "errors other than `not found` are not expected") return apierrors.IsNotFound(err) - }, timeout, interval).Should(BeTrue(), "the error should be `not found`") + }).Should(BeTrue(), "the error should be `not found`") }) }) diff --git a/controllers/compute/suite_test.go b/controllers/compute/suite_test.go index c6d3544b9..d175060be 100644 --- a/controllers/compute/suite_test.go +++ b/controllers/compute/suite_test.go @@ -24,7 +24,7 @@ import ( "github.com/onmetal/onmetal-api/envtestutils" "github.com/onmetal/onmetal-api/envtestutils/apiserver" "github.com/onmetal/onmetal-api/testutils/apiserverbin" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,13 +45,12 @@ import ( // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. const ( - interval = 50 * time.Millisecond - timeout = 3 * time.Second + pollingInterval = 50 * time.Millisecond + eventuallyTimeout = 3 * time.Second + consistentlyDuration = 1 * time.Second ) var ( - ctx, cancel = context.WithCancel(context.Background()) - cfg *rest.Config k8sClient client.Client testEnv *envtest.Environment @@ -59,6 +58,13 @@ var ( ) func TestAPIs(t *testing.T) { + _, reporterConfig := GinkgoConfiguration() + reporterConfig.SlowSpecThreshold = 10 * time.Second + SetDefaultConsistentlyPollingInterval(pollingInterval) + SetDefaultEventuallyPollingInterval(pollingInterval) + SetDefaultEventuallyTimeout(eventuallyTimeout) + SetDefaultConsistentlyDuration(consistentlyDuration) + RegisterFailHandler(Fail) RunSpecs(t, "Compute Controller Suite") @@ -79,6 +85,7 @@ var _ = BeforeSuite(func() { cfg, err = envtestutils.StartWithExtensions(testEnv, testEnvExt) Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) + DeferCleanup(envtestutils.StopWithExtensions, testEnv, testEnvExt) Expect(computev1alpha1.AddToScheme(scheme.Scheme)).To(Succeed()) Expect(ipamv1alpha1.AddToScheme(scheme.Scheme)).To(Succeed()) @@ -98,15 +105,17 @@ var _ = BeforeSuite(func() { }) Expect(err).NotTo(HaveOccurred()) + ctx, cancel := context.WithCancel(context.Background()) + DeferCleanup(cancel) go func() { defer GinkgoRecover() err := apiSrv.Start(ctx) Expect(err).NotTo(HaveOccurred()) }() - err = envtestutils.WaitUntilAPIServicesReadyWithTimeout(30*time.Second, testEnvExt, k8sClient, scheme.Scheme) + err = envtestutils.WaitUntilAPIServicesReadyWithTimeout(60*time.Second, testEnvExt, k8sClient, scheme.Scheme) Expect(err).NotTo(HaveOccurred()) -}, 60) +}) // SetupTest returns a namespace which will be created before each ginkgo `It` block and deleted at the end of `It` // so that each test case can run in an independent way @@ -151,6 +160,7 @@ func SetupTest(ctx context.Context) *corev1.Namespace { }).SetupWithManager(k8sManager)).To(Succeed()) go func() { + defer GinkgoRecover() Expect(k8sManager.Start(mgrCtx)).To(Succeed(), "failed to start manager") }() }) @@ -163,10 +173,3 @@ func SetupTest(ctx context.Context) *corev1.Namespace { return ns } - -var _ = AfterSuite(func() { - cancel() - By("tearing down the test environment") - err := envtestutils.StopWithExtensions(testEnv, testEnvExt) - Expect(err).NotTo(HaveOccurred()) -}) diff --git a/controllers/ipam/prefix_controller_test.go b/controllers/ipam/prefix_controller_test.go index 307d9d0dd..fc3618cf5 100644 --- a/controllers/ipam/prefix_controller_test.go +++ b/controllers/ipam/prefix_controller_test.go @@ -16,12 +16,11 @@ package ipam import ( - "time" - "github.com/onmetal/controller-utils/clientutils" commonv1alpha1 "github.com/onmetal/onmetal-api/apis/common/v1alpha1" ipamv1alpha1 "github.com/onmetal/onmetal-api/apis/ipam/v1alpha1" - . "github.com/onsi/ginkgo" + "github.com/onmetal/onmetal-api/testutils" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,7 +28,8 @@ import ( ) var _ = Describe("PrefixReconciler", func() { - ns := SetupTest() + ctx := testutils.SetupContext() + ns := SetupTest(ctx) It("should mark root prefixes as ready", func() { By("creating a root prefix") @@ -50,7 +50,7 @@ var _ = Describe("PrefixReconciler", func() { list := &ipamv1alpha1.PrefixAllocationList{} g.Expect(clientutils.ListAndFilterControlledBy(ctx, k8sClient, prefix, list, client.InNamespace(ns.Name))).To(Succeed()) g.Expect(list.Items).To(BeEmpty()) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("waiting for the prefix to be marked as ready and report its available ranges") prefixKey := client.ObjectKeyFromObject(prefix) @@ -58,7 +58,7 @@ var _ = Describe("PrefixReconciler", func() { Expect(k8sClient.Get(ctx, prefixKey, prefix)).To(Succeed()) g.Expect(ipamv1alpha1.GetPrefixReadiness(prefix)).To(Equal(ipamv1alpha1.ReadinessSucceeded)) g.Expect(prefix.Status.Used).To(BeEmpty()) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("should allocate child prefixes", func() { @@ -101,7 +101,7 @@ var _ = Describe("PrefixReconciler", func() { Name: rootPrefix.Name, })) g.Expect(childPrefix.Status.Used).To(BeEmpty()) - }, 1000*time.Second, interval).Should(Succeed()) + }).Should(Succeed()) By("asserting the parent's available ranges have been updated") rootPrefixKey := client.ObjectKeyFromObject(rootPrefix) @@ -165,7 +165,7 @@ var _ = Describe("PrefixReconciler", func() { g.Expect(list.Items).To(HaveLen(1)) allocation := list.Items[0] g.Expect(ipamv1alpha1.GetPrefixAllocationReadiness(&allocation)).To(Equal(ipamv1alpha1.ReadinessFailed)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("should assign a prefix on matching parents", func() { @@ -196,7 +196,7 @@ var _ = Describe("PrefixReconciler", func() { Equal(ipamv1alpha1.ReadinessUnknown), )) g.Expect(childPrefix.Spec.ParentRef).To(BeNil()) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("creating a root prefix that would fit but does not match") prefixValue := commonv1alpha1.MustParseNewIPPrefix("10.0.0.0/24") @@ -216,7 +216,7 @@ var _ = Describe("PrefixReconciler", func() { g.Expect(k8sClient.Get(ctx, childPrefixKey, childPrefix)).Should(Succeed()) g.Expect(ipamv1alpha1.GetPrefixReadiness(childPrefix)).To(Equal(ipamv1alpha1.ReadinessPending)) g.Expect(childPrefix.Spec.ParentRef).To(BeNil()) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("creating a root prefix that fits and matches") rootPrefix := &ipamv1alpha1.Prefix{ @@ -242,7 +242,7 @@ var _ = Describe("PrefixReconciler", func() { Name: rootPrefix.Name, })) g.Expect(childPrefix.Spec.Prefix).To(HaveValue(Equal(expectedChildPrefix))) - }, 100*time.Second, interval).Should(Succeed()) + }).Should(Succeed()) By("asserting the parent's used ranges have been updated") rootPrefixKey := client.ObjectKeyFromObject(rootPrefix) @@ -301,7 +301,7 @@ var _ = Describe("PrefixReconciler", func() { Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, childPrefixKey, childPrefix)).To(Succeed()) g.Expect(ipamv1alpha1.GetPrefixReadiness(childPrefix)).To(Equal(ipamv1alpha1.ReadinessSucceeded)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("should not allocate a prefix equal to the prefix of the parent", func() { @@ -335,7 +335,7 @@ var _ = Describe("PrefixReconciler", func() { Consistently(func(g Gomega) { Expect(k8sClient.Get(ctx, childPrefixKey, childPrefix)).To(Succeed()) g.Expect(ipamv1alpha1.GetPrefixReadiness(childPrefix)).NotTo(Equal(ipamv1alpha1.ReadinessSucceeded)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("should not allocate a prefix length equal to the prefix bits of the parent", func() { @@ -370,6 +370,6 @@ var _ = Describe("PrefixReconciler", func() { Consistently(func(g Gomega) { Expect(k8sClient.Get(ctx, childPrefixKey, childPrefix)).To(Succeed()) g.Expect(ipamv1alpha1.GetPrefixReadiness(childPrefix)).NotTo(Equal(ipamv1alpha1.ReadinessSucceeded)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) }) diff --git a/controllers/ipam/suite_test.go b/controllers/ipam/suite_test.go index 9f8c56f7d..737b12209 100644 --- a/controllers/ipam/suite_test.go +++ b/controllers/ipam/suite_test.go @@ -24,8 +24,7 @@ import ( "github.com/onmetal/onmetal-api/envtestutils" "github.com/onmetal/onmetal-api/envtestutils/apiserver" "github.com/onmetal/onmetal-api/testutils/apiserverbin" - . "github.com/onsi/ginkgo" - "github.com/onsi/ginkgo/config" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -41,20 +40,24 @@ import ( ) const ( - interval = 50 * time.Millisecond - timeout = 2 * time.Second + pollingInterval = 50 * time.Millisecond + eventuallyTimeout = 3 * time.Second + consistentlyDuration = 1 * time.Second ) var ( - ctx, cancel = context.WithCancel(context.Background()) - k8sClient client.Client testEnv *envtest.Environment testEnvExt *envtestutils.EnvironmentExtensions ) func TestAPIs(t *testing.T) { - config.DefaultReporterConfig.SlowSpecThreshold = 10 * time.Second.Seconds() + _, reporterConfig := GinkgoConfiguration() + reporterConfig.SlowSpecThreshold = 10 * time.Second + SetDefaultConsistentlyPollingInterval(pollingInterval) + SetDefaultEventuallyPollingInterval(pollingInterval) + SetDefaultEventuallyTimeout(eventuallyTimeout) + SetDefaultConsistentlyDuration(consistentlyDuration) RegisterFailHandler(Fail) RunSpecs(t, "IPAM Controller Suite") @@ -74,6 +77,8 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) + DeferCleanup(envtestutils.StopWithExtensions, testEnv, testEnvExt) + Expect(ipamv1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) // Init package-level k8sClient @@ -90,13 +95,15 @@ var _ = BeforeSuite(func() { }) Expect(err).NotTo(HaveOccurred()) + ctx, cancel := context.WithCancel(context.Background()) + DeferCleanup(cancel) go func() { defer GinkgoRecover() err := apiSrv.Start(ctx) Expect(err).NotTo(HaveOccurred()) }() - Expect(envtestutils.WaitUntilAPIServicesReadyWithTimeout(30*time.Second, testEnvExt, k8sClient, scheme.Scheme)).To(Succeed()) + Expect(envtestutils.WaitUntilAPIServicesReadyWithTimeout(60*time.Second, testEnvExt, k8sClient, scheme.Scheme)).To(Succeed()) k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: scheme.Scheme, @@ -126,9 +133,9 @@ var _ = BeforeSuite(func() { err = k8sManager.Start(ctx) Expect(err).ToNot(HaveOccurred()) }() -}, 60) +}) -func SetupTest() *corev1.Namespace { +func SetupTest(ctx context.Context) *corev1.Namespace { ns := &corev1.Namespace{} BeforeEach(func() { @@ -136,18 +143,9 @@ func SetupTest() *corev1.Namespace { ObjectMeta: metav1.ObjectMeta{GenerateName: "testns-"}, } Expect(k8sClient.Create(ctx, ns)).NotTo(HaveOccurred(), "failed to create test namespace") - }) - AfterEach(func() { - Expect(k8sClient.Delete(ctx, ns)).NotTo(HaveOccurred(), "failed to delete test namespace") + DeferCleanup(k8sClient.Delete, ctx, ns) }) return ns } - -var _ = AfterSuite(func() { - cancel() - By("tearing down the test environment") - err := envtestutils.StopWithExtensions(testEnv, testEnvExt) - Expect(err).NotTo(HaveOccurred()) -}) diff --git a/controllers/storage/suite_test.go b/controllers/storage/suite_test.go index 16a00c53c..e6767bd56 100644 --- a/controllers/storage/suite_test.go +++ b/controllers/storage/suite_test.go @@ -32,7 +32,7 @@ import ( storagev1alpha1 "github.com/onmetal/onmetal-api/apis/storage/v1alpha1" - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -47,13 +47,12 @@ import ( // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. const ( - interval = 50 * time.Millisecond - timeout = 3 * time.Second + pollingInterval = 50 * time.Millisecond + eventuallyTimeout = 3 * time.Second + consistentlyDuration = 1 * time.Second ) var ( - ctx, cancel = context.WithCancel(context.Background()) - cfg *rest.Config k8sClient client.Client testEnv *envtest.Environment @@ -61,6 +60,12 @@ var ( ) func TestAPIs(t *testing.T) { + _, reporterConfig := GinkgoConfiguration() + reporterConfig.SlowSpecThreshold = 10 * time.Second + SetDefaultConsistentlyPollingInterval(pollingInterval) + SetDefaultEventuallyPollingInterval(pollingInterval) + SetDefaultEventuallyTimeout(eventuallyTimeout) + SetDefaultConsistentlyDuration(consistentlyDuration) RegisterFailHandler(Fail) RunSpecs(t, "Controller Suite") @@ -82,6 +87,8 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) + DeferCleanup(envtestutils.StopWithExtensions, testEnv, testEnvExt) + err = storagev1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) @@ -100,15 +107,16 @@ var _ = BeforeSuite(func() { }) Expect(err).NotTo(HaveOccurred()) + ctx, cancel := context.WithCancel(context.Background()) + DeferCleanup(cancel) go func() { defer GinkgoRecover() err := apiSrv.Start(ctx) Expect(err).NotTo(HaveOccurred()) }() - err = envtestutils.WaitUntilAPIServicesReadyWithTimeout(30*time.Second, testEnvExt, k8sClient, scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) -}, 60) + Expect(envtestutils.WaitUntilAPIServicesReadyWithTimeout(60*time.Second, testEnvExt, k8sClient, scheme.Scheme)).To(Succeed()) +}) func SetupTest(ctx context.Context) *corev1.Namespace { var ( @@ -169,6 +177,7 @@ func SetupTest(ctx context.Context) *corev1.Namespace { }).SetupWithManager(k8sManager)).To(Succeed()) go func() { + defer GinkgoRecover() Expect(k8sManager.Start(mgrCtx)).To(Succeed(), "failed to start manager") }() }) @@ -181,11 +190,3 @@ func SetupTest(ctx context.Context) *corev1.Namespace { return ns } - -var _ = AfterSuite(func() { - cancel() - - By("tearing down the test environment") - err := envtestutils.StopWithExtensions(testEnv, testEnvExt) - Expect(err).NotTo(HaveOccurred()) -}) diff --git a/controllers/storage/volume_controller_test.go b/controllers/storage/volume_controller_test.go index 843ba7e76..e30b8c3e7 100644 --- a/controllers/storage/volume_controller_test.go +++ b/controllers/storage/volume_controller_test.go @@ -18,7 +18,8 @@ package storage import ( storagev1alpha1 "github.com/onmetal/onmetal-api/apis/storage/v1alpha1" - . "github.com/onsi/ginkgo" + "github.com/onmetal/onmetal-api/testutils" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -27,6 +28,7 @@ import ( ) var _ = Describe("VolumeReconciler", func() { + ctx := testutils.SetupContext() ns := SetupTest(ctx) var volume *storagev1alpha1.Volume @@ -83,13 +85,13 @@ var _ = Describe("VolumeReconciler", func() { Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(storagev1alpha1.GetVolumePhase(volume)).To(Equal(storagev1alpha1.VolumePhaseBound)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("making sure the volume stays bound") Consistently(func(g Gomega) { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(storagev1alpha1.GetVolumePhase(volume)).To(Equal(storagev1alpha1.VolumePhaseBound)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("should un-bind a volume if the underlying volume claim changes its volume ref", func() { @@ -109,7 +111,7 @@ var _ = Describe("VolumeReconciler", func() { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(volume.Spec.ClaimRef.Name).To(Equal(volumeClaim.Name)) g.Expect(storagev1alpha1.GetVolumePhase(volume)).To(Equal(storagev1alpha1.VolumePhaseBound)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("deleting the volume claim") Expect(k8sClient.Delete(ctx, volumeClaim)).To(Succeed(), "failed to delete volume claim") @@ -119,6 +121,6 @@ var _ = Describe("VolumeReconciler", func() { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(storagev1alpha1.GetVolumePhase(volume)).To(Equal(storagev1alpha1.VolumePhaseUnbound)) g.Expect(volume.Spec.ClaimRef).To(BeZero()) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) }) diff --git a/controllers/storage/volume_scheduler_test.go b/controllers/storage/volume_scheduler_test.go index 15f863c73..c351c5038 100644 --- a/controllers/storage/volume_scheduler_test.go +++ b/controllers/storage/volume_scheduler_test.go @@ -15,9 +15,8 @@ package storage import ( - "time" - - . "github.com/onsi/ginkgo" + "github.com/onmetal/onmetal-api/testutils" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -29,6 +28,7 @@ import ( ) var _ = Describe("VolumeScheduler", func() { + ctx := testutils.SetupContext() ns := SetupTest(ctx) It("should schedule volumes on volume pools", func() { @@ -230,7 +230,7 @@ var _ = Describe("VolumeScheduler", func() { Consistently(func() string { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed()) return volume.Spec.VolumePoolRef.Name - }, 1*time.Second, interval).Should(BeEmpty()) + }).Should(BeEmpty()) By("patching the volume to contain only one of the corresponding tolerations") volumeBase := volume.DeepCopy() @@ -246,7 +246,7 @@ var _ = Describe("VolumeScheduler", func() { Consistently(func() string { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed()) return volume.Spec.VolumePoolRef.Name - }, 1*time.Second, interval).Should(BeEmpty()) + }).Should(BeEmpty()) By("patching the volume to contain all of the corresponding tolerations") volumeBase = volume.DeepCopy() @@ -261,6 +261,6 @@ var _ = Describe("VolumeScheduler", func() { Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get the volume") g.Expect(volume.Spec.VolumePoolRef.Name).To(Equal(taintedVolumePool.Name)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) }) diff --git a/controllers/storage/volumeclaim_controller_test.go b/controllers/storage/volumeclaim_controller_test.go index 3ba5fc812..cbf743100 100644 --- a/controllers/storage/volumeclaim_controller_test.go +++ b/controllers/storage/volumeclaim_controller_test.go @@ -18,7 +18,8 @@ package storage import ( storagev1alpha1 "github.com/onmetal/onmetal-api/apis/storage/v1alpha1" - . "github.com/onsi/ginkgo" + "github.com/onmetal/onmetal-api/testutils" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -27,6 +28,7 @@ import ( ) var _ = Describe("VolumeClaimReconciler", func() { + ctx := testutils.SetupContext() ns := SetupTest(ctx) var volume *storagev1alpha1.Volume @@ -85,7 +87,7 @@ var _ = Describe("VolumeClaimReconciler", func() { Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, claimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Status.Phase).To(Equal(storagev1alpha1.VolumeClaimBound)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("Should un-bind a volumeclaim if the underlying volume is deleted", func() { @@ -107,7 +109,7 @@ var _ = Describe("VolumeClaimReconciler", func() { Expect(k8sClient.Get(ctx, volumeClaimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Spec.VolumeRef.Name).To(Equal(volume.Name)) g.Expect(volumeClaim.Status.Phase).To(Equal(storagev1alpha1.VolumeClaimBound)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("deleting the volume") Expect(k8sClient.Delete(ctx, volume)).To(Succeed(), "failed to delete volume") @@ -116,6 +118,6 @@ var _ = Describe("VolumeClaimReconciler", func() { Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, volumeClaimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Status.Phase).To(Equal(storagev1alpha1.VolumeClaimLost)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) }) diff --git a/controllers/storage/volumeclaim_scheduler_test.go b/controllers/storage/volumeclaim_scheduler_test.go index 65b4d72b7..7053df473 100644 --- a/controllers/storage/volumeclaim_scheduler_test.go +++ b/controllers/storage/volumeclaim_scheduler_test.go @@ -18,7 +18,8 @@ package storage import ( storagev1alpha1 "github.com/onmetal/onmetal-api/apis/storage/v1alpha1" - . "github.com/onsi/ginkgo" + "github.com/onmetal/onmetal-api/testutils" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -28,6 +29,7 @@ import ( ) var _ = Describe("VolumeClaimScheduler", func() { + ctx := testutils.SetupContext() ns := SetupTest(ctx) var volume, volume2 *storagev1alpha1.Volume @@ -106,14 +108,14 @@ var _ = Describe("VolumeClaimScheduler", func() { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(volume.Spec.ClaimRef.Name).To(Equal(volumeClaim.Name)) g.Expect(volume.Spec.ClaimRef.UID).To(Equal(volumeClaim.UID)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("waiting for the volumeclaim to reference the volume") claimKey := client.ObjectKeyFromObject(volumeClaim) Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, claimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Spec.VolumeRef.Name).To(Equal(volume.Name)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("Should not claim a volume if volumeclaim with matching resource requirements is found", func() { @@ -135,14 +137,14 @@ var _ = Describe("VolumeClaimScheduler", func() { Expect(k8sClient.Get(ctx, volume2Key, volume2)).To(Succeed(), "failed to get volume") g.Expect(volume2.Spec.ClaimRef.Name).To(Equal("")) g.Expect(volume2.Spec.ClaimRef.UID).To(Equal(types.UID(""))) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("waiting for the volumeclaim to reference the volume") claimKey := client.ObjectKeyFromObject(volumeClaim) Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, claimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Spec.VolumeRef.Name).To(Equal("")) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("Should not claim a volume if the volume status is not set to available", func() { @@ -164,14 +166,14 @@ var _ = Describe("VolumeClaimScheduler", func() { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(volume.Spec.ClaimRef.Name).To(Equal("")) g.Expect(volume.Spec.ClaimRef.UID).To(Equal(types.UID(""))) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("waiting for the volumeclaim to reference the volume") claimKey := client.ObjectKeyFromObject(volumeClaim) Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, claimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Spec.VolumeRef.Name).To(Equal("")) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("Should not claim a volume when the volumeclasses are different", func() { @@ -195,7 +197,7 @@ var _ = Describe("VolumeClaimScheduler", func() { Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, claimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Spec.VolumeRef.Name).To(Equal("")) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("waiting for the volume to reference the claim") volumeKey := client.ObjectKeyFromObject(volume) @@ -203,7 +205,7 @@ var _ = Describe("VolumeClaimScheduler", func() { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(volume.Spec.ClaimRef.Name).To(Equal("")) g.Expect(volume.Spec.ClaimRef.UID).To(Equal(types.UID(""))) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("Should claim one volume out of two where the resources match", func() { @@ -230,7 +232,7 @@ var _ = Describe("VolumeClaimScheduler", func() { Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(volume.Spec.ClaimRef.Name).To(Equal(volumeClaim.Name)) g.Expect(volume.Spec.ClaimRef.UID).To(Equal(volumeClaim.UID)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("waiting for the incorrect volume to not be claimed") volumeKey2 := client.ObjectKeyFromObject(volume2) @@ -238,14 +240,14 @@ var _ = Describe("VolumeClaimScheduler", func() { Expect(k8sClient.Get(ctx, volumeKey2, volume2)).To(Succeed(), "failed to get volume") g.Expect(volume2.Spec.ClaimRef.Name).To(Equal("")) g.Expect(volume2.Spec.ClaimRef.UID).To(Equal(types.UID(""))) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) By("waiting for the volumeclaim to reference the volume") claimKey := client.ObjectKeyFromObject(volumeClaim) Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, claimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Spec.VolumeRef.Name).To(Equal(volume.Name)) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("Should not claim a volume when the volumeref is set", func() { @@ -270,7 +272,7 @@ var _ = Describe("VolumeClaimScheduler", func() { Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, claimKey, volumeClaim)).To(Succeed(), "failed to get volumeclaim") g.Expect(volumeClaim.Spec.VolumeRef.Name).To(Equal("")) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) It("should claim a volume when the volumeref is set explicitly", func() { @@ -290,13 +292,13 @@ var _ = Describe("VolumeClaimScheduler", func() { volumeClaimKey := client.ObjectKeyFromObject(volumeClaim) Eventually(func(g Gomega) { Expect(k8sClient.Get(ctx, volumeClaimKey, volumeClaim)).To(Succeed(), "failed to get volume claim") - //g.Expect(volumeClaim.Status.Phase).To(Equal(storagev1alpha1.VolumeClaimBound)) + g.Expect(volumeClaim.Status.Phase).To(Equal(storagev1alpha1.VolumeClaimBound)) Expect(k8sClient.Get(ctx, volumeKey, volume)).To(Succeed(), "failed to get volume") g.Expect(volume.Spec.ClaimRef).To(Equal(storagev1alpha1.ClaimReference{ Name: volumeClaim.Name, UID: volumeClaim.UID, })) - }, timeout, interval).Should(Succeed()) + }).Should(Succeed()) }) }) diff --git a/controllers/storage/volumeclass_controller_test.go b/controllers/storage/volumeclass_controller_test.go index a31ddefdd..1265b3b8b 100644 --- a/controllers/storage/volumeclass_controller_test.go +++ b/controllers/storage/volumeclass_controller_test.go @@ -18,7 +18,8 @@ package storage import ( . "github.com/onmetal/controller-utils/testutils" - . "github.com/onsi/ginkgo" + "github.com/onmetal/onmetal-api/testutils" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -30,7 +31,9 @@ import ( ) var _ = Describe("VolumeClass controller", func() { + ctx := testutils.SetupContext() ns := SetupTest(ctx) + It("should finalize the volume class if no volume is using it", func() { By("creating the volume class consumed by the volume") volumeClass := &storagev1alpha1.VolumeClass{ @@ -64,7 +67,7 @@ var _ = Describe("VolumeClass controller", func() { Expect(client.IgnoreNotFound(err)).NotTo(HaveOccurred()) g.Expect(err).NotTo(HaveOccurred()) return volumeClass.Finalizers - }, timeout, interval).Should(ContainElement(storagev1alpha1.VolumeClassFinalizer)) + }).Should(ContainElement(storagev1alpha1.VolumeClassFinalizer)) By("issuing a delete request for the volume class") Expect(k8sClient.Delete(ctx, volumeClass)).Should(Succeed()) @@ -74,7 +77,7 @@ var _ = Describe("VolumeClass controller", func() { err := k8sClient.Get(ctx, volumeClassKey, volumeClass) g.Expect(err).NotTo(HaveOccurred()) return volumeClass.Finalizers - }, timeout).Should(ContainElement(storagev1alpha1.VolumeClassFinalizer)) + }).Should(ContainElement(storagev1alpha1.VolumeClassFinalizer)) By("deleting the referencing volume") Expect(k8sClient.Delete(ctx, volume)).Should(Succeed()) @@ -82,6 +85,6 @@ var _ = Describe("VolumeClass controller", func() { By("waiting for the volume class to be gone") Eventually(func() error { return k8sClient.Get(ctx, volumeClassKey, volumeClass) - }, timeout, interval).Should(MatchErrorFunc(apierrors.IsNotFound)) + }).Should(MatchErrorFunc(apierrors.IsNotFound)) }) }) diff --git a/docs/development/testing.md b/docs/development/testing.md index 531b2af0d..0a3d2d7af 100644 --- a/docs/development/testing.md +++ b/docs/development/testing.md @@ -13,7 +13,7 @@ Example of test suite setup is below: package mypackage import ( - . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "testing" ) diff --git a/go.mod b/go.mod index 6d095e9d0..db467b346 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/google/go-cmp v0.5.6 github.com/onmetal/controller-utils v0.5.6 github.com/onmetal/vgopath v0.0.2 - github.com/onsi/ginkgo v1.16.5 github.com/onsi/ginkgo/v2 v2.1.3 github.com/onsi/gomega v1.19.0 github.com/spf13/cobra v1.4.0 @@ -73,7 +72,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/nxadm/tail v1.4.8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect @@ -117,7 +115,6 @@ require ( google.golang.org/protobuf v1.27.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect k8s.io/apiextensions-apiserver v0.23.6 // indirect diff --git a/testutils/testutils.go b/testutils/testutils.go new file mode 100644 index 000000000..87818fc76 --- /dev/null +++ b/testutils/testutils.go @@ -0,0 +1,80 @@ +// Copyright 2022 OnMetal authors +// +// 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 testutils + +import ( + "context" + "sync" + "time" + + "github.com/onsi/ginkgo/v2" +) + +type DelegatingContext struct { + lock sync.RWMutex + ctx context.Context +} + +func (d *DelegatingContext) Deadline() (deadline time.Time, ok bool) { + d.lock.RLock() + defer d.lock.RUnlock() + return d.ctx.Deadline() +} + +func (d *DelegatingContext) Done() <-chan struct{} { + d.lock.RLock() + defer d.lock.RUnlock() + return d.ctx.Done() +} + +func (d *DelegatingContext) Err() error { + d.lock.RLock() + defer d.lock.RUnlock() + return d.ctx.Err() +} + +func (d *DelegatingContext) Value(key interface{}) interface{} { + d.lock.RLock() + defer d.lock.RUnlock() + return d.ctx.Value(key) +} + +func (d *DelegatingContext) Fulfill(ctx context.Context) { + d.lock.Lock() + defer d.lock.Unlock() + d.ctx = ctx +} + +func NewDelegatingContext(ctx context.Context) *DelegatingContext { + return &DelegatingContext{ctx: ctx} +} + +func SetupContext() context.Context { + initCtx, initCancel := context.WithCancel(context.Background()) + delegCtx := NewDelegatingContext(initCtx) + + ginkgo.BeforeEach(func() { + ctx, cancel := context.WithCancel(context.Background()) + ginkgo.DeferCleanup(cancel) + + delegCtx.Fulfill(ctx) + if initCancel != nil { + initCancel() + initCancel = nil + } + }) + + return delegCtx +}