6161import java .util .Optional ;
6262import java .util .UUID ;
6363import java .util .concurrent .ConcurrentHashMap ;
64+ import java .util .concurrent .locks .ReadWriteLock ;
65+ import java .util .concurrent .locks .ReentrantReadWriteLock ;
6466import java .util .function .Consumer ;
6567import java .util .stream .Collectors ;
6668import java .util .stream .Stream ;
@@ -106,37 +108,26 @@ public class AllureTestNg implements
106108 /**
107109 * Store current testng result uuid to attach before/after methods into.
108110 */
109- private final ThreadLocal <Current > currentTestResult = new InheritableThreadLocal <Current >() {
110- @ Override
111- protected Current initialValue () {
112- return new Current ();
113- }
114- };
111+ private final ThreadLocal <Current > currentTestResult = ThreadLocal
112+ .withInitial (Current ::new );
115113
116114 /**
117115 * Store current container uuid for fake containers around before/after methods.
118116 */
119- private final ThreadLocal <String > currentTestContainer = new InheritableThreadLocal <String >() {
120- @ Override
121- protected String initialValue () {
122- return UUID .randomUUID ().toString ();
123- }
124- };
117+ private final ThreadLocal <String > currentTestContainer = ThreadLocal
118+ .withInitial (() -> UUID .randomUUID ().toString ());
125119
126120 /**
127121 * Store uuid for current executable item to catch steps and attachments.
128122 */
129- private final ThreadLocal <String > currentExecutable = new InheritableThreadLocal <String >() {
130- @ Override
131- protected String initialValue () {
132- return UUID .randomUUID ().toString ();
133- }
134- };
123+ private final ThreadLocal <String > currentExecutable = ThreadLocal
124+ .withInitial (() -> UUID .randomUUID ().toString ());
135125
136126 /**
137127 * Store uuid for class test containers.
138128 */
139129 private final Map <ITestClass , String > classContainerUuidStorage = new ConcurrentHashMap <>();
130+ private final ReadWriteLock lock = new ReentrantReadWriteLock ();
140131
141132 private final AllureLifecycle lifecycle ;
142133
@@ -215,16 +206,14 @@ public void onBeforeClass(final ITestClass testClass) {
215206 .setUuid (uuid )
216207 .setName (testClass .getName ());
217208 getLifecycle ().startTestContainer (container );
218- classContainerUuidStorage . put (testClass , uuid );
209+ setClassContainer (testClass , uuid );
219210 }
220211
221212 public void onAfterClass (final ITestClass testClass ) {
222- if (!classContainerUuidStorage .containsKey (testClass )) {
223- return ;
224- }
225- final String uuid = classContainerUuidStorage .get (testClass );
226- getLifecycle ().stopTestContainer (uuid );
227- getLifecycle ().writeTestContainer (uuid );
213+ getClassContainer (testClass ).ifPresent (uuid -> {
214+ getLifecycle ().stopTestContainer (uuid );
215+ getLifecycle ().writeTestContainer (uuid );
216+ });
228217 }
229218
230219 @ Override
@@ -242,11 +231,7 @@ public void onTestStart(final ITestResult testResult) {
242231 Optional .of (testResult )
243232 .map (ITestResult ::getMethod )
244233 .map (ITestNGMethod ::getTestClass )
245- .map (classContainerUuidStorage ::get )
246- .ifPresent (testClassContainerUuid -> getLifecycle ().updateTestContainer (
247- testClassContainerUuid ,
248- container -> container .getChildren ().add (uuid )
249- ));
234+ .ifPresent (clazz -> addClassContainerChild (clazz , uuid ));
250235 }
251236
252237 protected void startTestCase (final ITestResult testResult ,
@@ -400,12 +385,12 @@ private void ifSuiteFixtureStarted(final ISuite suite, final ITestNGMethod testM
400385
401386 private void ifClassFixtureStarted (final ITestNGMethod testMethod ) {
402387 if (testMethod .isBeforeClassConfiguration ()) {
403- final String parentUuid = classContainerUuidStorage . get (testMethod .getTestClass ());
404- startBefore (parentUuid , testMethod );
388+ getClassContainer (testMethod .getTestClass ())
389+ . ifPresent ( parentUuid -> startBefore (parentUuid , testMethod ) );
405390 }
406391 if (testMethod .isAfterClassConfiguration ()) {
407- final String parentUuid = classContainerUuidStorage . get (testMethod .getTestClass ());
408- startAfter (parentUuid , testMethod );
392+ getClassContainer (testMethod .getTestClass ())
393+ . ifPresent ( parentUuid -> startAfter (parentUuid , testMethod ) );
409394 }
410395 }
411396
@@ -696,6 +681,39 @@ private Consumer<TestResult> setStatus(final Status status, final StatusDetails
696681 };
697682 }
698683
684+ private void addClassContainerChild (final ITestClass clazz , final String childUuid ) {
685+ lock .writeLock ().lock ();
686+ try {
687+ final String parentUuid = classContainerUuidStorage .get (clazz );
688+ if (nonNull (parentUuid )) {
689+ getLifecycle ().updateTestContainer (
690+ parentUuid ,
691+ container -> container .getChildren ().add (childUuid )
692+ );
693+ }
694+ } finally {
695+ lock .writeLock ().unlock ();
696+ }
697+ }
698+
699+ private Optional <String > getClassContainer (final ITestClass clazz ) {
700+ lock .readLock ().lock ();
701+ try {
702+ return Optional .ofNullable (classContainerUuidStorage .get (clazz ));
703+ } finally {
704+ lock .readLock ().unlock ();
705+ }
706+ }
707+
708+ private void setClassContainer (final ITestClass clazz , final String uuid ) {
709+ lock .writeLock ().lock ();
710+ try {
711+ classContainerUuidStorage .put (clazz , uuid );
712+ } finally {
713+ lock .writeLock ().unlock ();
714+ }
715+ }
716+
699717 private Current refreshContext () {
700718 currentTestResult .remove ();
701719 return currentTestResult .get ();
0 commit comments