From c8f5b0c0018b62a17e3acc3b704fd2b5bbecdd26 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 23 May 2024 09:58:53 -0400 Subject: [PATCH] Refactor AbstractConcurrentInitializerTest to add non-Object test --- .../AbstractConcurrentInitializerTest.java | 86 ++++++++++--------- .../AtomicInitializerNonObjectTest.java | 62 +++++++++++++ ....java => AtomicInitializerObjectTest.java} | 3 +- 3 files changed, 111 insertions(+), 40 deletions(-) create mode 100644 src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerNonObjectTest.java rename src/test/java/org/apache/commons/lang3/concurrent/{AtomicInitializerTest.java => AtomicInitializerObjectTest.java} (95%) diff --git a/src/test/java/org/apache/commons/lang3/concurrent/AbstractConcurrentInitializerTest.java b/src/test/java/org/apache/commons/lang3/concurrent/AbstractConcurrentInitializerTest.java index f2b8517ee..da8f5636c 100644 --- a/src/test/java/org/apache/commons/lang3/concurrent/AbstractConcurrentInitializerTest.java +++ b/src/test/java/org/apache/commons/lang3/concurrent/AbstractConcurrentInitializerTest.java @@ -28,23 +28,49 @@ import org.junit.jupiter.api.Test; /** *

- * An abstract base class for tests of concrete {@code ConcurrentInitializer} - * implementations. + * An abstract base class for tests of concrete {@code ConcurrentInitializer} implementations. *

*

- * This class provides some basic tests for initializer implementations. Derived - * class have to create a {@link ConcurrentInitializer} object on which the - * tests are executed. + * This class provides some basic tests for initializer implementations. Derived class have to create a {@link ConcurrentInitializer} object on which the tests + * are executed. *

+ * + * @param Domain type. */ -public abstract class AbstractConcurrentInitializerTest extends AbstractLangTest { +public abstract class AbstractConcurrentInitializerTest extends AbstractLangTest { + + static final class GetThread extends Thread { + + private Object object; + private final CountDownLatch startLatch; + private final ConcurrentInitializer initializer; + + GetThread(final CountDownLatch startLatch, final ConcurrentInitializer initializer) { + this.startLatch = startLatch; + this.initializer = initializer; + } + + @Override + public void run() { + try { + // wait until all threads are ready for maximum parallelism + startLatch.await(); + // access the initializer + object = initializer.get(); + } catch (final InterruptedException iex) { + // ignore + } catch (final ConcurrentException cex) { + object = cex; + } + } + } + /** - * Creates the {@link ConcurrentInitializer} object to be tested. This - * method is called whenever the test fixture needs to be obtained. + * Creates the {@link ConcurrentInitializer} object to be tested. This method is called whenever the test fixture needs to be obtained. * * @return the initializer object to be tested */ - protected abstract ConcurrentInitializer createInitializer(); + protected abstract ConcurrentInitializer createInitializer(); /** * Tests a simple invocation of the get() method. @@ -57,39 +83,19 @@ public abstract class AbstractConcurrentInitializerTest extends AbstractLangTest } /** - * Tests whether get() can be invoked from multiple threads concurrently. - * Always the same object should be returned. + * Tests whether get() can be invoked from multiple threads concurrently. Always the same object should be returned. * * @throws org.apache.commons.lang3.concurrent.ConcurrentException because the object under test may throw it. - * @throws InterruptedException because the threading API my throw it. + * @throws InterruptedException because the threading API my throw it. */ @Test - public void testGetConcurrent() throws ConcurrentException, - InterruptedException { - final ConcurrentInitializer initializer = createInitializer(); + public void testGetConcurrent() throws ConcurrentException, InterruptedException { + final ConcurrentInitializer initializer = createInitializer(); final int threadCount = 20; final CountDownLatch startLatch = new CountDownLatch(1); - final class GetThread extends Thread { - Object object; - - @Override - public void run() { - try { - // wait until all threads are ready for maximum parallelism - startLatch.await(); - // access the initializer - object = initializer.get(); - } catch (final InterruptedException iex) { - // ignore - } catch (final ConcurrentException cex) { - object = cex; - } - } - } - final GetThread[] threads = new GetThread[threadCount]; for (int i = 0; i < threadCount; i++) { - threads[i] = new GetThread(); + threads[i] = new GetThread(startLatch, initializer); threads[i].start(); } @@ -107,14 +113,13 @@ public abstract class AbstractConcurrentInitializerTest extends AbstractLangTest } /** - * Tests whether sequential get() invocations always return the same - * instance. + * Tests whether sequential get() invocations always return the same instance. * * @throws org.apache.commons.lang3.concurrent.ConcurrentException because the object under test may throw it. */ @Test public void testGetMultipleTimes() throws ConcurrentException { - final ConcurrentInitializer initializer = createInitializer(); + final ConcurrentInitializer initializer = createInitializer(); final Object obj = initializer.get(); for (int i = 0; i < 10; i++) { assertEquals(obj, initializer.get(), "Got different object at " + i); @@ -123,12 +128,15 @@ public abstract class AbstractConcurrentInitializerTest extends AbstractLangTest /** * Tests a simple invocation of the isInitialized() method. + * + * @throws Throwable on test failure. */ @Test public void testisInitialized() throws Throwable { - final ConcurrentInitializer initializer = createInitializer(); + final ConcurrentInitializer initializer = createInitializer(); if (initializer instanceof AbstractConcurrentInitializer) { - final AbstractConcurrentInitializer castedInitializer = (AbstractConcurrentInitializer) initializer; + @SuppressWarnings("unchecked") + final AbstractConcurrentInitializer castedInitializer = (AbstractConcurrentInitializer) initializer; assertFalse(castedInitializer.isInitialized(), "was initialized before get()"); assertNotNull(castedInitializer.get(), "No managed object"); assertTrue(castedInitializer.isInitialized(), "was not initialized after get()"); diff --git a/src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerNonObjectTest.java b/src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerNonObjectTest.java new file mode 100644 index 000000000..3a0966bfd --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerNonObjectTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.commons.lang3.concurrent; + +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.jupiter.api.Test; + +/** + * Test class for {@code AtomicInitializer}. + */ +public class AtomicInitializerNonObjectTest extends AbstractConcurrentInitializerTest { + + /** + * Returns the initializer to be tested. + * + * @return the {@code AtomicInitializer} + */ + @Override + protected ConcurrentInitializer createInitializer() { + return new AtomicInitializer() { + @Override + protected Integer initialize() { + return new Integer(0); + } + }; + } + + @Test + public void testGetThatReturnsNullFirstTime() throws ConcurrentException { + final AtomicInitializer initializer = new AtomicInitializer() { + final AtomicInteger firstRun = new AtomicInteger(1); + + @Override + protected Integer initialize() { + if (firstRun.getAndSet(0) == 1) { + return null; + } + return new Integer(0); + } + }; + + assertNull(initializer.get()); + assertNull(initializer.get()); + } +} diff --git a/src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerTest.java b/src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerObjectTest.java similarity index 95% rename from src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerTest.java rename to src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerObjectTest.java index a8e9d54d8..9ab1be5be 100644 --- a/src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerTest.java +++ b/src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerObjectTest.java @@ -25,7 +25,8 @@ import org.junit.jupiter.api.Test; /** * Test class for {@code AtomicInitializer}. */ -public class AtomicInitializerTest extends AbstractConcurrentInitializerTest { +public class AtomicInitializerObjectTest extends AbstractConcurrentInitializerTest { + /** * Returns the initializer to be tested. *