• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 package utils.resources;
17 
18 import java.util.HashSet;
19 import java.util.Set;
20 import org.junit.jupiter.api.Disabled;
21 import org.junit.runner.Description;
22 import org.junit.runner.notification.Failure;
23 import org.junit.runner.notification.RunNotifier;
24 import org.junit.runners.BlockJUnit4ClassRunner;
25 import org.junit.runners.model.FrameworkMethod;
26 import org.junit.runners.model.InitializationError;
27 import org.junit.runners.model.Statement;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import utils.resources.RequiredResources.RequiredResource;
31 import utils.resources.RequiredResources.ResourceRetentionPolicy;
32 
33 public class ResourceCentricBlockJUnit4ClassRunner extends BlockJUnit4ClassRunner {
34 
35     private final Set<TestResource> resourcesToBeDestroyedAfterAllTests;
36 
37     private final RequiredResources classRequiredResourcesAnnotation;
38 
39     private final Logger log = LoggerFactory.getLogger(ResourceCentricBlockJUnit4ClassRunner.class);
40 
ResourceCentricBlockJUnit4ClassRunner(Class<?> klass)41     public ResourceCentricBlockJUnit4ClassRunner(Class<?> klass)
42             throws InitializationError {
43         super(klass);
44 
45         classRequiredResourcesAnnotation = klass.getAnnotation(RequiredResources.class);
46         resourcesToBeDestroyedAfterAllTests = new HashSet<TestResource>();
47     }
48 
49     /**
50      *
51      */
createResourceInstance(RequiredResource resourceAnnotation)52     private static TestResource createResourceInstance(RequiredResource resourceAnnotation)
53             throws InstantiationException, IllegalAccessException {
54         Class<? extends TestResource> resourceClazz = resourceAnnotation.resource();
55         if (resourceClazz == null) {
56             throw new IllegalArgumentException(
57                     "resource parameter is missing for the @RequiredResource annotation.");
58         }
59         return resourceClazz.newInstance();
60     }
61 
62     @Override
runChild(final FrameworkMethod method, RunNotifier notifier)63     protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
64         Description description = describeChild(method);
65         if (method.getAnnotation(Disabled.class) != null) {
66             notifier.fireTestIgnored(description);
67         } else {
68             RequiredResources annotation = method.getAnnotation(RequiredResources.class);
69             if (annotation != null) {
70                 try {
71                     beforeRunLeaf(annotation.value());
72                 } catch (Exception e) {
73                     notifier.fireTestFailure(new Failure(description, e));
74                 }
75 
76             }
77 
78             runLeaf(methodBlock(method), description, notifier);
79 
80             if (annotation != null) {
81                 try {
82                     afterRunLeaf(annotation.value());
83                 } catch (Exception e) {
84                     notifier.fireTestFailure(new Failure(description, e));
85                 }
86             }
87         }
88     }
89 
90     /**
91      * Override the withBeforeClasses method to inject executing resource
92      * creation between @BeforeClass methods and test methods.
93      */
94     @Override
withBeforeClasses(final Statement statement)95     protected Statement withBeforeClasses(final Statement statement) {
96         Statement withRequiredResourcesCreation = new Statement() {
97 
98             @Override
99             public void evaluate() throws Throwable {
100                 if (classRequiredResourcesAnnotation != null) {
101                     beforeRunClass(classRequiredResourcesAnnotation.value());
102                 }
103                 statement.evaluate();
104             }
105         };
106         return super.withBeforeClasses(withRequiredResourcesCreation);
107     }
108 
109     /**
110      * Override the withAfterClasses method to inject executing resource
111      * creation between test methods and the @AfterClass methods.
112      */
113     @Override
withAfterClasses(final Statement statement)114     protected Statement withAfterClasses(final Statement statement) {
115         Statement withRequiredResourcesDeletion = new Statement() {
116 
117             @Override
118             public void evaluate() throws Throwable {
119                 statement.evaluate();
120                 afterRunClass();
121             }
122         };
123         return super.withAfterClasses(withRequiredResourcesDeletion);
124     }
125 
beforeRunClass(RequiredResource[] resourcesAnnotation)126     private void beforeRunClass(RequiredResource[] resourcesAnnotation)
127             throws InstantiationException, IllegalAccessException, InterruptedException {
128         log.debug("Processing @RequiredResources before running the test class...");
129         for (RequiredResource resourceAnnotation : resourcesAnnotation) {
130             TestResource resource = createResourceInstance(resourceAnnotation);
131             TestResourceUtils.createResource(resource, resourceAnnotation.creationPolicy());
132 
133             if (resourceAnnotation.retentionPolicy() != ResourceRetentionPolicy.KEEP) {
134                 resourcesToBeDestroyedAfterAllTests.add(resource);
135             }
136         }
137     }
138 
afterRunClass()139     private void afterRunClass()
140             throws InstantiationException, IllegalAccessException, InterruptedException {
141         log.debug("Processing @RequiredResources after running the test class...");
142         for (TestResource resource : resourcesToBeDestroyedAfterAllTests) {
143             TestResourceUtils.deleteResource(resource);
144         }
145     }
146 
beforeRunLeaf(RequiredResource[] resourcesAnnotation)147     private void beforeRunLeaf(RequiredResource[] resourcesAnnotation)
148             throws InstantiationException, IllegalAccessException, InterruptedException {
149         log.debug("Processing @RequiredResources before running the test...");
150         for (RequiredResource resourceAnnotation : resourcesAnnotation) {
151             TestResource resource = createResourceInstance(resourceAnnotation);
152             TestResourceUtils.createResource(resource, resourceAnnotation.creationPolicy());
153 
154             if (resourceAnnotation.retentionPolicy() == ResourceRetentionPolicy.DESTROY_AFTER_ALL_TESTS) {
155                 resourcesToBeDestroyedAfterAllTests.add(resource);
156             }
157         }
158     }
159 
afterRunLeaf(RequiredResource[] resourcesAnnotation)160     private void afterRunLeaf(RequiredResource[] resourcesAnnotation)
161             throws InstantiationException, IllegalAccessException, InterruptedException {
162         log.debug("Processing @RequiredResources after running the test...");
163         for (RequiredResource resourceAnnotation : resourcesAnnotation) {
164             TestResource resource = createResourceInstance(resourceAnnotation);
165 
166             if (resourceAnnotation.retentionPolicy() == ResourceRetentionPolicy.DESTROY_IMMEDIATELY) {
167                 TestResourceUtils.deleteResource(resource);
168             }
169         }
170     }
171 }
172