/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file 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 utils.resources; import java.util.HashSet; import java.util.Set; import org.junit.jupiter.api.Disabled; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import utils.resources.RequiredResources.RequiredResource; import utils.resources.RequiredResources.ResourceRetentionPolicy; public class ResourceCentricBlockJUnit4ClassRunner extends BlockJUnit4ClassRunner { private final Set resourcesToBeDestroyedAfterAllTests; private final RequiredResources classRequiredResourcesAnnotation; private final Logger log = LoggerFactory.getLogger(ResourceCentricBlockJUnit4ClassRunner.class); public ResourceCentricBlockJUnit4ClassRunner(Class klass) throws InitializationError { super(klass); classRequiredResourcesAnnotation = klass.getAnnotation(RequiredResources.class); resourcesToBeDestroyedAfterAllTests = new HashSet(); } /** * */ private static TestResource createResourceInstance(RequiredResource resourceAnnotation) throws InstantiationException, IllegalAccessException { Class resourceClazz = resourceAnnotation.resource(); if (resourceClazz == null) { throw new IllegalArgumentException( "resource parameter is missing for the @RequiredResource annotation."); } return resourceClazz.newInstance(); } @Override protected void runChild(final FrameworkMethod method, RunNotifier notifier) { Description description = describeChild(method); if (method.getAnnotation(Disabled.class) != null) { notifier.fireTestIgnored(description); } else { RequiredResources annotation = method.getAnnotation(RequiredResources.class); if (annotation != null) { try { beforeRunLeaf(annotation.value()); } catch (Exception e) { notifier.fireTestFailure(new Failure(description, e)); } } runLeaf(methodBlock(method), description, notifier); if (annotation != null) { try { afterRunLeaf(annotation.value()); } catch (Exception e) { notifier.fireTestFailure(new Failure(description, e)); } } } } /** * Override the withBeforeClasses method to inject executing resource * creation between @BeforeClass methods and test methods. */ @Override protected Statement withBeforeClasses(final Statement statement) { Statement withRequiredResourcesCreation = new Statement() { @Override public void evaluate() throws Throwable { if (classRequiredResourcesAnnotation != null) { beforeRunClass(classRequiredResourcesAnnotation.value()); } statement.evaluate(); } }; return super.withBeforeClasses(withRequiredResourcesCreation); } /** * Override the withAfterClasses method to inject executing resource * creation between test methods and the @AfterClass methods. */ @Override protected Statement withAfterClasses(final Statement statement) { Statement withRequiredResourcesDeletion = new Statement() { @Override public void evaluate() throws Throwable { statement.evaluate(); afterRunClass(); } }; return super.withAfterClasses(withRequiredResourcesDeletion); } private void beforeRunClass(RequiredResource[] resourcesAnnotation) throws InstantiationException, IllegalAccessException, InterruptedException { log.debug("Processing @RequiredResources before running the test class..."); for (RequiredResource resourceAnnotation : resourcesAnnotation) { TestResource resource = createResourceInstance(resourceAnnotation); TestResourceUtils.createResource(resource, resourceAnnotation.creationPolicy()); if (resourceAnnotation.retentionPolicy() != ResourceRetentionPolicy.KEEP) { resourcesToBeDestroyedAfterAllTests.add(resource); } } } private void afterRunClass() throws InstantiationException, IllegalAccessException, InterruptedException { log.debug("Processing @RequiredResources after running the test class..."); for (TestResource resource : resourcesToBeDestroyedAfterAllTests) { TestResourceUtils.deleteResource(resource); } } private void beforeRunLeaf(RequiredResource[] resourcesAnnotation) throws InstantiationException, IllegalAccessException, InterruptedException { log.debug("Processing @RequiredResources before running the test..."); for (RequiredResource resourceAnnotation : resourcesAnnotation) { TestResource resource = createResourceInstance(resourceAnnotation); TestResourceUtils.createResource(resource, resourceAnnotation.creationPolicy()); if (resourceAnnotation.retentionPolicy() == ResourceRetentionPolicy.DESTROY_AFTER_ALL_TESTS) { resourcesToBeDestroyedAfterAllTests.add(resource); } } } private void afterRunLeaf(RequiredResource[] resourcesAnnotation) throws InstantiationException, IllegalAccessException, InterruptedException { log.debug("Processing @RequiredResources after running the test..."); for (RequiredResource resourceAnnotation : resourcesAnnotation) { TestResource resource = createResourceInstance(resourceAnnotation); if (resourceAnnotation.retentionPolicy() == ResourceRetentionPolicy.DESTROY_IMMEDIATELY) { TestResourceUtils.deleteResource(resource); } } } }