GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

beforeEach(ExtensionContext)   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 16
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
c 0
b 0
f 0
dl 0
loc 16
rs 9.75
eloc 13
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
package io.github.glytching.junit.extension.system;
18
19
import org.junit.jupiter.api.extension.*;
20
21
import java.lang.reflect.AnnotatedElement;
22
import java.util.ArrayList;
23
import java.util.Arrays;
24
import java.util.List;
25
26
import static io.github.glytching.junit.extension.util.ExtensionUtil.getStore;
27
import static org.junit.platform.commons.util.AnnotationUtils.isAnnotated;
28
29
/**
30
 * The system property extension sets system properties before test execution and unsets them on
31
 * completion. More specifically:
32
 *
33
 * <ul>
34
 *   <li>If a new system property was added then it is removed after test execution completes
35
 *   <li>If an existing system property was overwritten then its original value is reinstated after
36
 *       test execution completes
37
 * </ul>
38
 *
39
 * <p>System properties can be injected into your test or test case with either of the following
40
 * approaches:
41
 *
42
 * <ul>
43
 *   <li>Class level annotation. Note: you cannot annotate a base test case and expect the extension
44
 *       to be engaged for its children. So, if you want a system property to be available for all
45
 *       test methods in a Class {@code X} which extends {@code Y} then you must add the annotation
46
 *       to Class {@code X} not to Class {@code Y}. For example:
47
 *       <pre>
48
 *  &#064;SystemProperty(name = "nameA", value = "valueA")
49
 *  public class MyTest {
50
 *      // ...
51
 *  }
52
 * </pre>
53
 *   <li>Parameter injection into a {@code @Test} method. For example:
54
 *       <pre>
55
 *  &#064;Test
56
 *  &#064;SystemProperty(name = "nameA", value = "valueA")
57
 *  public void testUsingSystemProperty() {
58
 *      // ...
59
 *  }
60
 * </pre>
61
 * </ul>
62
 *
63
 * <p>The {@link SystemProperty} annotation is repeatable.
64
 *
65
 * <p>Usage examples:
66
 *
67
 * <p>Declaring system properties at class level:
68
 *
69
 * <pre>
70
 *  &#064;SystemProperty(name = "nameA", value = "valueA")
71
 *  &#064;SystemProperty(name = "nameB", value = "valueB")
72
 * public class MyTest {
73
 *
74
 *     &#064;Test
75
 *     public void test() {
76
 *         // the system properties nameA:valueA, nameB:valueB have been set
77
 *         // ...
78
 *     }
79
 * }
80
 * </pre>
81
 *
82
 * <p>Declaring system properties at method level:
83
 *
84
 * <pre>
85
 * public class MyTest {
86
 *
87
 *     &#064;Test
88
 *     &#064;SystemProperty(name = "nameA", value = "valueA")
89
 *     &#064;SystemProperty(name = "nameB", value = "valueB")
90
 *     public void testUsingSystemProperties(TemporaryFolder temporaryFolder) {
91
 *         // the system properties nameA:valueA, nameB:valueB have been set
92
 *         // ...
93
 *     }
94
 *
95
 *     &#064;Test
96
 *     &#064;SystemProperty(name = "nameC", value = "valueC")
97
 *     public void testUsingSystemProperty(TemporaryFolder temporaryFolder) {
98
 *         // the system property nameC:valueC has been set
99
 *         // ...
100
 *     }
101
 *
102
 *     &#064;Test
103
 *     public void testWithoutSystemProperties() {
104
 *         // the system properties nameA:valueA, nameB:valueB, nameC:valueC have *not* been set
105
 *         // ...
106
 *     }
107
 * }
108
 * </pre>
109
 *
110
 * @since 1.0.0
111
 */
112
public class SystemPropertyExtension
113
    implements AfterEachCallback, BeforeEachCallback, BeforeAllCallback, AfterAllCallback {
114
115
  private static final String KEY = "restoreContext";
116
117
  /**
118
   * If the current test class has a system property annotation(s) then create a {@link
119
   * RestoreContext} representing the annotation(s). This causes the requested system properties to
120
   * be set and retains a copy of pre-set values for reinstatement after test execution.
121
   *
122
   * @param extensionContext the <em>context</em> in which the current test or container is being
123
   *     executed
124
   * @throws Exception
125
   */
126
  @Override
127
  public void beforeAll(ExtensionContext extensionContext) throws Exception {
128
    List<SystemProperty> systemProperties =
129
        getSystemProperties(extensionContext.getRequiredTestClass());
130
    if (!systemProperties.isEmpty()) {
131
      RestoreContext.Builder builder = RestoreContext.createBuilder();
132
      for (SystemProperty systemProperty : systemProperties) {
133
        builder.addPropertyName(systemProperty.name());
134
        if (System.getProperty(systemProperty.name()) != null) {
135
          builder.addRestoreProperty(
136
              systemProperty.name(), System.getProperty(systemProperty.name()));
137
        }
138
139
        set(systemProperty);
140
      }
141
      writeRestoreContext(extensionContext, builder.build());
142
    }
143
  }
144
145
  /**
146
   * If a {@link RestoreContext} exists for the given {@code extensionContext} then restore it i.e.
147
   * unset any system properties which were set in {@link #beforeAll(ExtensionContext)} for this
148
   * {@code extensionContext} and reinstate original value, if applicable.
149
   *
150
   * @param extensionContext the <em>context</em> in which the current test or container is being
151
   *     executed
152
   * @throws Exception
153
   */
154
  @Override
155
  public void afterAll(ExtensionContext extensionContext) throws Exception {
156
    RestoreContext restoreContext = readRestoreContext(extensionContext);
157
    if (restoreContext != null) {
158
      restoreContext.restore();
159
    }
160
  }
161
162
  /**
163
   * If the current test method has a system property annotation(s) then create a {@link
164
   * RestoreContext} representing the annotation(s). This causes the requested system properties to
165
   * be set and retains a copy of pre-set values for reinstatement after test execution.
166
   *
167
   * @param extensionContext the <em>context</em> in which the current test or container is being
168
   *     executed
169
   * @throws Exception
170
   */
171
  @Override
172
  public void beforeEach(ExtensionContext extensionContext) throws Exception {
173
    List<SystemProperty> systemProperties =
174
        getSystemProperties(extensionContext.getRequiredTestMethod());
175
    if (!systemProperties.isEmpty()) {
176
      RestoreContext.Builder builder = RestoreContext.createBuilder();
177
      for (SystemProperty systemProperty : systemProperties) {
178
        builder.addPropertyName(systemProperty.name());
179
        if (System.getProperty(systemProperty.name()) != null) {
180
          builder.addRestoreProperty(
181
              systemProperty.name(), System.getProperty(systemProperty.name()));
182
        }
183
184
        set(systemProperty);
185
      }
186
      writeRestoreContext(extensionContext, builder.build());
187
    }
188
  }
189
190
  /**
191
   * If a {@link RestoreContext} exists for the given {@code extensionContext} then restore it i.e.
192
   * unset any system properties which were set in {@link #beforeEach(ExtensionContext)} for this
193
   * {@code extensionContext} and reinstate original value, if applicable.
194
   *
195
   * @param extensionContext the <em>context</em> in which the current test or container is being
196
   *     executed
197
   * @throws Exception
198
   */
199
  @Override
200
  public void afterEach(ExtensionContext extensionContext) throws Exception {
201
    RestoreContext restoreContext = readRestoreContext(extensionContext);
202
    if (restoreContext != null) {
203
      restoreContext.restore();
204
    }
205
  }
206
207
  /**
208
   * Get a collection of {@link SystemProperty} for the given {@code annotatedElement}. If the given
209
   * {@code annotatedElement} has no such annotations then an empty list is returned, if the given
210
   * {@code annotatedElement} is annotated with {@link SystemProperty} then a list with one element
211
   * is returned, if the given {@code annotatedElement} is annotated with {@link SystemProperties}
212
   * then a list with one element for each of the repeated {@link SystemProperty} values is
213
   * returned.
214
   *
215
   * <p>This is essentially a shortcut for logic such as: 'does this element have the {@link
216
   * SystemProperty} annotation, if not does it have the {@link SystemProperties}' followed by
217
   * gathering these annotation values.
218
   *
219
   * @param annotatedElement either a test class or a test method which may be annotated with a
220
   *     system property annotation
221
   * @return 0..* {@link SystemProperty} elements
222
   */
223
  private List<SystemProperty> getSystemProperties(AnnotatedElement annotatedElement) {
224
    List<SystemProperty> systemProperties = new ArrayList<>();
225
    if (isAnnotated(annotatedElement, SystemProperties.class)) {
226
      // gather the repeating system property values
227
      systemProperties.addAll(
228
          Arrays.asList(annotatedElement.getAnnotation(SystemProperties.class).value()));
229
    }
230
    if (isAnnotated(annotatedElement, SystemProperty.class)) {
231
      // add the single system property value
232
      systemProperties.add(annotatedElement.getAnnotation(SystemProperty.class));
233
    }
234
    return systemProperties;
235
  }
236
237
  private void set(SystemProperty systemProperty) {
238
    System.setProperty(systemProperty.name(), systemProperty.value());
239
  }
240
241
  private void writeRestoreContext(
242
      ExtensionContext extensionContext, RestoreContext restoreContext) {
243
    getStore(extensionContext, this.getClass()).getOrComputeIfAbsent(KEY, key -> restoreContext);
244
  }
245
246
  private RestoreContext readRestoreContext(ExtensionContext extensionContext) {
247
    return getStore(extensionContext, this.getClass()).get(KEY, RestoreContext.class);
248
  }
249
}
250