Skip to content

Commit d0cdf84

Browse files
committed
Added tests for singleton pattern
1 parent a375b2d commit d0cdf84

File tree

7 files changed

+173
-90
lines changed

7 files changed

+173
-90
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.iluwatar.singleton;
2+
3+
/**
4+
* Date: 12/29/15 - 19:20 PM
5+
*
6+
* @author Jeroen Meulemeester
7+
*/
8+
public class EnumIvoryTowerTest extends SingletonTest<EnumIvoryTower> {
9+
10+
/**
11+
* Create a new singleton test instance using the given 'getInstance' method
12+
*/
13+
public EnumIvoryTowerTest() {
14+
super(() -> EnumIvoryTower.INSTANCE);
15+
}
16+
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.iluwatar.singleton;
2+
3+
/**
4+
* Date: 12/29/15 - 19:22 PM
5+
*
6+
* @author Jeroen Meulemeester
7+
*/
8+
public class InitializingOnDemandHolderIdiomTest extends SingletonTest<InitializingOnDemandHolderIdiom> {
9+
10+
/**
11+
* Create a new singleton test instance using the given 'getInstance' method
12+
*/
13+
public InitializingOnDemandHolderIdiomTest() {
14+
super(InitializingOnDemandHolderIdiom::getInstance);
15+
}
16+
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.iluwatar.singleton;
2+
3+
/**
4+
* Date: 12/29/15 - 19:23 PM
5+
*
6+
* @author Jeroen Meulemeester
7+
*/
8+
public class IvoryTowerTest extends SingletonTest<IvoryTower> {
9+
10+
/**
11+
* Create a new singleton test instance using the given 'getInstance' method
12+
*/
13+
public IvoryTowerTest() {
14+
super(IvoryTower::getInstance);
15+
}
16+
17+
}

singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java

Lines changed: 0 additions & 90 deletions
This file was deleted.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.iluwatar.singleton;
2+
3+
import org.junit.Test;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import java.util.concurrent.Callable;
8+
import java.util.concurrent.ExecutorService;
9+
import java.util.concurrent.Executors;
10+
import java.util.concurrent.Future;
11+
import java.util.function.Supplier;
12+
13+
import static org.junit.Assert.assertNotNull;
14+
import static org.junit.Assert.assertSame;
15+
16+
/**
17+
* This class provides several test case that test singleton construction.
18+
*
19+
* The first proves that multiple calls to the singleton getInstance object are the same when called
20+
* in the SAME thread. The second proves that multiple calls to the singleton getInstance object are
21+
* the same when called in the DIFFERENT thread.
22+
*
23+
* Date: 12/29/15 - 19:25 PM
24+
*
25+
* @author Jeroen Meulemeester
26+
* @author Richard Jones
27+
*/
28+
public abstract class SingletonTest<S> {
29+
30+
/**
31+
* The singleton's getInstance method
32+
*/
33+
private final Supplier<S> singletonInstanceMethod;
34+
35+
/**
36+
* Create a new singleton test instance using the given 'getInstance' method
37+
*
38+
* @param singletonInstanceMethod The singleton's getInstance method
39+
*/
40+
public SingletonTest(final Supplier<S> singletonInstanceMethod) {
41+
this.singletonInstanceMethod = singletonInstanceMethod;
42+
}
43+
44+
/**
45+
* Test the singleton in a non-concurrent setting
46+
*/
47+
@Test
48+
public void testMultipleCallsReturnTheSameObjectInSameThread() {
49+
// Create several instances in the same calling thread
50+
S instance1 = this.singletonInstanceMethod.get();
51+
S instance2 = this.singletonInstanceMethod.get();
52+
S instance3 = this.singletonInstanceMethod.get();
53+
// now check they are equal
54+
assertSame(instance1, instance2);
55+
assertSame(instance1, instance3);
56+
assertSame(instance2, instance3);
57+
}
58+
59+
/**
60+
* Test singleton instance in a concurrent setting
61+
*/
62+
@Test(timeout = 10000)
63+
public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws Exception {
64+
65+
// Create 10000 tasks and inside each callable instantiate the singleton class
66+
final List<Callable<S>> tasks = new ArrayList<>();
67+
for (int i = 0; i < 10000; i++) {
68+
tasks.add(this.singletonInstanceMethod::get);
69+
}
70+
71+
// Use up to 8 concurrent threads to handle the tasks
72+
final ExecutorService executorService = Executors.newFixedThreadPool(8);
73+
final List<Future<S>> results = executorService.invokeAll(tasks);
74+
75+
// wait for all of the threads to complete
76+
final S expectedInstance = this.singletonInstanceMethod.get();
77+
for (Future<S> res : results) {
78+
final S instance = res.get();
79+
assertNotNull(instance);
80+
assertSame(expectedInstance, instance);
81+
}
82+
83+
// tidy up the executor
84+
executorService.shutdown();
85+
86+
}
87+
88+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.iluwatar.singleton;
2+
3+
/**
4+
* Date: 12/29/15 - 19:26 PM
5+
*
6+
* @author Jeroen Meulemeester
7+
*/
8+
public class ThreadSafeDoubleCheckLockingTest extends SingletonTest<ThreadSafeDoubleCheckLocking> {
9+
10+
/**
11+
* Create a new singleton test instance using the given 'getInstance' method
12+
*/
13+
public ThreadSafeDoubleCheckLockingTest() {
14+
super(ThreadSafeDoubleCheckLocking::getInstance);
15+
}
16+
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.iluwatar.singleton;
2+
3+
/**
4+
* Date: 12/29/15 - 19:26 PM
5+
*
6+
* @author Jeroen Meulemeester
7+
*/
8+
public class ThreadSafeLazyLoadedIvoryTowerTest extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
9+
10+
/**
11+
* Create a new singleton test instance using the given 'getInstance' method
12+
*/
13+
public ThreadSafeLazyLoadedIvoryTowerTest() {
14+
super(ThreadSafeLazyLoadedIvoryTower::getInstance);
15+
}
16+
17+
}

0 commit comments

Comments
 (0)