diff --git a/double-checked-locking/pom.xml b/double-checked-locking/pom.xml
index 7ad651339..9b87d6859 100644
--- a/double-checked-locking/pom.xml
+++ b/double-checked-locking/pom.xml
@@ -12,5 +12,10 @@
junit
test
+
+ org.mockito
+ mockito-core
+ test
+
diff --git a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java
index b51e000a7..0a17ac13d 100644
--- a/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java
+++ b/double-checked-locking/src/main/java/com/iluwatar/doublechecked/locking/Inventory.java
@@ -1,6 +1,7 @@
package com.iluwatar.doublechecked.locking;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -38,4 +39,14 @@ public class Inventory {
}
return false;
}
+
+ /**
+ * Get all the items in the inventory
+ *
+ * @return All the items of the inventory, as an unmodifiable list
+ */
+ public final List- getItems() {
+ return Collections.unmodifiableList(items);
+ }
+
}
diff --git a/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java
new file mode 100644
index 000000000..1bc43263f
--- /dev/null
+++ b/double-checked-locking/src/test/java/com/iluwatar/doublechecked/locking/InventoryTest.java
@@ -0,0 +1,110 @@
+package com.iluwatar.doublechecked.locking;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.io.PrintStream;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.TestCase.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+/**
+ * Date: 12/10/15 - 9:34 PM
+ *
+ * @author Jeroen Meulemeester
+ */
+public class InventoryTest {
+
+ /**
+ * The mocked standard out {@link PrintStream}, used to verify a steady increasing size of the
+ * {@link Inventory} while adding items from multiple threads concurrently
+ */
+ private final PrintStream stdOutMock = mock(PrintStream.class);
+
+ /**
+ * Keep the original std-out so it can be restored after the test
+ */
+ private final PrintStream stdOutOrig = System.out;
+
+ /**
+ * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test
+ */
+ @Before
+ public void setUp() {
+ System.setOut(this.stdOutMock);
+ }
+
+ /**
+ * Removed the mocked std-out {@link PrintStream} again from the {@link System} class
+ */
+ @After
+ public void tearDown() {
+ System.setOut(this.stdOutOrig);
+ }
+
+ /**
+ * The number of threads used to stress test the locking of the {@link Inventory#addItem(Item)}
+ * method
+ */
+ private static final int THREAD_COUNT = 8;
+
+ /**
+ * The maximum number of {@link Item}s allowed in the {@link Inventory}
+ */
+ private static final int INVENTORY_SIZE = 1000;
+
+ /**
+ * Concurrently add multiple items to the inventory, and check if the items were added in order by
+ * checking the stdOut for continuous growth of the inventory. When 'items.size()=xx' shows up out
+ * of order, it means that the locking is not ok, increasing the risk of going over the inventory
+ * item limit.
+ */
+ @Test(timeout = 10000)
+ public void testAddItem() throws Exception {
+ // Create a new inventory with a limit of 1000 items and put some load on the add method
+ final Inventory inventory = new Inventory(INVENTORY_SIZE);
+ final ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);
+ for (int i = 0; i < THREAD_COUNT; i++) {
+ executorService.execute(() -> {
+ while (inventory.addItem(new Item())) ;
+ });
+ }
+
+ // Wait until all threads have finished
+ executorService.shutdown();
+ executorService.awaitTermination(5, TimeUnit.SECONDS);
+
+ // Check the number of items in the inventory. It should not have exceeded the allowed maximum
+ final List
- items = inventory.getItems();
+ assertNotNull(items);
+ assertEquals(INVENTORY_SIZE, items.size());
+
+ // Capture all stdOut messages ...
+ final ArgumentCaptor stdOutCaptor = ArgumentCaptor.forClass(String.class);
+ verify(this.stdOutMock, times(INVENTORY_SIZE)).println(stdOutCaptor.capture());
+
+ // ... verify if we got all 1000
+ final List values = stdOutCaptor.getAllValues();
+ assertEquals(INVENTORY_SIZE, values.size());
+
+ // ... and check if the inventory size is increasing continuously
+ for (int i = 0; i < values.size(); i++) {
+ assertNotNull(values.get(i));
+ assertTrue(values.get(i).contains("items.size()=" + (i + 1)));
+ }
+
+ verifyNoMoreInteractions(this.stdOutMock);
+ }
+
+}
\ No newline at end of file