|
|
@@ -0,0 +1,132 @@
|
|
|
+/*
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ * @copyright Ranides Atterwim
|
|
|
+ * @license WTFPL
|
|
|
+ * @url http://ranides.net/projects/assira
|
|
|
+ */
|
|
|
+package net.ranides.assira.generic;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
+import java.util.function.Consumer;
|
|
|
+import java.util.function.Supplier;
|
|
|
+import junit.framework.Assert;
|
|
|
+import static net.ranides.assira.junit.NewAssert.*;
|
|
|
+import org.junit.Ignore;
|
|
|
+import org.junit.Test;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ */
|
|
|
+public class LazyReferenceTest {
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testUnique() {
|
|
|
+ AtomicInteger ai = new AtomicInteger(5);
|
|
|
+ Supplier<Integer> ref = LazyReference.unique(() -> ai.getAndIncrement());
|
|
|
+ assertEquals(5, ref.get().intValue());
|
|
|
+ assertEquals(5, ref.get().intValue());
|
|
|
+ assertEquals(5, ref.get().intValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testLocal() throws InterruptedException, Throwable {
|
|
|
+ List<Throwable> errors = Collections.synchronizedList(new ArrayList<>());
|
|
|
+
|
|
|
+ AtomicInteger ai = new AtomicInteger(5);
|
|
|
+ Supplier<Integer> ref = LazyReference.local(() -> ai.getAndIncrement());
|
|
|
+
|
|
|
+ thread(0, errors::add, ()->{
|
|
|
+ for(int i=0; i<5; i++) {
|
|
|
+ sleep(50);
|
|
|
+ assertEquals(5, ref.get().intValue());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ thread(50, errors::add, ()->{
|
|
|
+ for(int i=0; i<5; i++) {
|
|
|
+ sleep(50);
|
|
|
+ assertEquals(6, ref.get().intValue());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ thread(100, errors::add, ()->{
|
|
|
+ for(int i=0; i<5; i++) {
|
|
|
+ sleep(50);
|
|
|
+ assertEquals(7, ref.get().intValue());
|
|
|
+ }
|
|
|
+ }).join();
|
|
|
+
|
|
|
+ if(!errors.isEmpty()) {
|
|
|
+ throw errors.get(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testShared() throws InterruptedException, Throwable {
|
|
|
+ List<Throwable> errors = Collections.synchronizedList(new ArrayList<>());
|
|
|
+
|
|
|
+ AtomicInteger ai = new AtomicInteger(5);
|
|
|
+ Supplier<Integer> ref = LazyReference.shared(() -> ai.getAndIncrement());
|
|
|
+
|
|
|
+ for(int t=0; t<20; t++) {
|
|
|
+ thread(50, errors::add, ()->{
|
|
|
+ for(int i=0; i<10; i++) {
|
|
|
+ sleep(50);
|
|
|
+ Integer v = ref.get();
|
|
|
+ assertEquals(5, v.intValue());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ sleep(1000);
|
|
|
+
|
|
|
+ if(!errors.isEmpty()) {
|
|
|
+ throw errors.get(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void testConcurrent() throws InterruptedException, Throwable {
|
|
|
+ List<Throwable> errors = Collections.synchronizedList(new ArrayList<>());
|
|
|
+
|
|
|
+ AtomicInteger ai = new AtomicInteger(5);
|
|
|
+ Supplier<Integer> ref = LazyReference.concurrent(() -> ai.getAndIncrement());
|
|
|
+
|
|
|
+ for(int t=0; t<10; t++) {
|
|
|
+ thread(50, errors::add, ()->{
|
|
|
+ for(int i=0; i<10; i++) {
|
|
|
+ sleep(10);
|
|
|
+ int v = ref.get().intValue();
|
|
|
+ if(v > 10) {
|
|
|
+ fail("ref.value = " + v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ sleep(500);
|
|
|
+
|
|
|
+ if(!errors.isEmpty()) {
|
|
|
+ throw errors.get(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void sleep(long ms) {
|
|
|
+ try {
|
|
|
+ Thread.sleep(ms);
|
|
|
+ } catch (InterruptedException $0) {
|
|
|
+ /* do nothing */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Thread thread(long delay, Consumer<Throwable> handler, Runnable runnable) {
|
|
|
+ Thread thread = new Thread(()->{
|
|
|
+ sleep(delay);
|
|
|
+ runnable.run();
|
|
|
+ });
|
|
|
+ thread.setUncaughtExceptionHandler((t,e) -> handler.accept(e));
|
|
|
+ thread.start();
|
|
|
+ return thread;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|