From 78b183b581f92e7492952fac0abf6e9503ac4052 Mon Sep 17 00:00:00 2001 From: Amol Gote Date: Thu, 14 Sep 2023 22:00:04 -0400 Subject: [PATCH] BAEL-6791 - Added in existing module Unit tests and Bench mark tests. (#14744) * BAEL-6791 - Added in existing module Unit tests and Bench mark tests. * BAEL-6791 - Put all of your code in a single package that refers to your article * BAEL-6791 - PR - add a newline after the package statements PR - use 2-space indents for line continuations. Use given-when-then naming convention for test methods --- .../BenchMarkRunner.java | 73 +++++++++++++++++++ .../ConcurrentHashMapUnitTest.java | 62 ++++++++++++++++ .../HashtableUnitTest.java | 63 ++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/BenchMarkRunner.java create mode 100644 core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/ConcurrentHashMapUnitTest.java create mode 100644 core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/HashtableUnitTest.java diff --git a/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/BenchMarkRunner.java b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/BenchMarkRunner.java new file mode 100644 index 0000000000..3c7132ffcd --- /dev/null +++ b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/BenchMarkRunner.java @@ -0,0 +1,73 @@ +package com.baeldung.hashtableandconcurrenthashmap; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.Hashtable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +@Fork(value = 1) +@Warmup(iterations = 3) +@Measurement(iterations = 5) +@Threads(10) // 10 threads for the test +public class BenchMarkRunner { + private Hashtable hashTable; + private ConcurrentHashMap concurrentHashMap; + + @Setup(Level.Trial) + public void setup() { + hashTable = new Hashtable<>(); + concurrentHashMap = new ConcurrentHashMap<>(); + } + + @Benchmark + @Group("hashtable") + public void benchmarkHashtablePut() { + for (int i = 0; i < 10000; i++) { + hashTable.put(String.valueOf(i), i); + } + } + + @Benchmark + @Group("hashtable") + public void benchmarkHashtableGet(Blackhole blackhole) { + for (int i = 0; i < 10000; i++) { + Integer value = hashTable.get(String.valueOf(i)); + blackhole.consume(value); + } + } + + @Benchmark + @Group("concurrentHashMap") + public void benchmarkConcurrentHashMapPut() { + for (int i = 0; i < 10000; i++) { + concurrentHashMap.put(String.valueOf(i), i); + } + } + + @Benchmark + @Group("concurrentHashMap") + public void benchmarkConcurrentHashMapGet(Blackhole blackhole) { + for (int i = 0; i < 10000; i++) { + Integer value = concurrentHashMap.get(String.valueOf(i)); + blackhole.consume(value); + } + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(BenchMarkRunner.class.getSimpleName()) + .shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server") + .build(); + new Runner(options).run(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/ConcurrentHashMapUnitTest.java b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/ConcurrentHashMapUnitTest.java new file mode 100644 index 0000000000..c936583abb --- /dev/null +++ b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/ConcurrentHashMapUnitTest.java @@ -0,0 +1,62 @@ +package com.baeldung.hashtableandconcurrenthashmap; + +import org.junit.Test; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +public class ConcurrentHashMapUnitTest { + @Test + public void givenEmptyConcurrentHashMap_whenValuesAreAdded_thenValuesCanBeRetrieved() { + ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap<>(); + concurrentHashMap.put("Key1", "1"); + concurrentHashMap.put("Key2", "2"); + concurrentHashMap.putIfAbsent("Key3", "3"); + String value = concurrentHashMap.get("Key2"); + + assertEquals("1", concurrentHashMap.get("Key1")); + assertEquals("2", value); + assertEquals("3", concurrentHashMap.get("Key3")); + } + @Test + public void givenPopulatedConcurrentHashMap_whenModifiedDuringIteration_thenShouldNotThrowConcurrentModificationException() throws InterruptedException { + ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap<>(); + concurrentHashMap.put("Key1", 1); + concurrentHashMap.put("Key2", 2); + concurrentHashMap.put("Key3", 3); + AtomicBoolean exceptionCaught = new AtomicBoolean(false); + + Thread iteratorThread = new Thread(() -> { + Iterator it = concurrentHashMap.keySet().iterator(); + try { + while (it.hasNext()) { + it.next(); + Thread.sleep(100); + } + } catch (ConcurrentModificationException e) { + exceptionCaught.set(true); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + Thread modifierThread = new Thread(() -> { + try { + Thread.sleep(50); + concurrentHashMap.put("Key4", 4); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + iteratorThread.start(); + modifierThread.start(); + + iteratorThread.join(); + modifierThread.join(); + + assertFalse(exceptionCaught.get()); + } +} diff --git a/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/HashtableUnitTest.java b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/HashtableUnitTest.java new file mode 100644 index 0000000000..8f8195fdef --- /dev/null +++ b/core-java-modules/core-java-concurrency-collections-2/src/test/java/com/baeldung/hashtableandconcurrenthashmap/HashtableUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.hashtableandconcurrenthashmap; + +import org.junit.Test; +import java.util.ConcurrentModificationException; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +public class HashtableUnitTest { + @Test + public void givenEmptyHashtable_whenValuesAreAdded_thenValuesCanBeRetrieved() { + Hashtable hashtable = new Hashtable<>(); + hashtable.put("Key1", "1"); + hashtable.put("Key2", "2"); + hashtable.putIfAbsent("Key3", "3"); + String value = hashtable.get("Key2"); + + assertEquals("1", hashtable.get("Key1")); + assertEquals("2", value); + assertEquals("3", hashtable.get("Key3")); + } + @Test + public void givenPopulatedHashtable_whenModifiedDuringIteration_thenShouldThrowConcurrentModificationException() throws InterruptedException { + Hashtable hashtable = new Hashtable<>(); + hashtable.put("Key1", 1); + hashtable.put("Key2", 2); + hashtable.put("Key3", 3); + AtomicBoolean exceptionCaught = new AtomicBoolean(false); + + Thread iteratorThread = new Thread(() -> { + Iterator it = hashtable.keySet().iterator(); + try { + while (it.hasNext()) { + it.next(); + Thread.sleep(100); + } + } catch (ConcurrentModificationException e) { + exceptionCaught.set(true); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + Thread modifierThread = new Thread(() -> { + try { + Thread.sleep(50); + hashtable.put("Key4", 4); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + iteratorThread.start(); + modifierThread.start(); + + iteratorThread.join(); + modifierThread.join(); + + assertTrue(exceptionCaught.get()); + } +} \ No newline at end of file