package com.github.phantomthief.test;

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.LongAdder;

import org.junit.jupiter.api.Test;

import com.github.phantomthief.util.MoreSuppliers;
import com.github.phantomthief.util.MoreSuppliers.CloseableSupplier;

/**
 * @author w.vela
 * Created on 2022-01-30.
 */
class MoreSuppliersConcurrentTest {

    @Test
    void test() throws InterruptedException {
        CloseableSupplier<String> supplier = MoreSuppliers.lazy(this::init, true);
        AtomicBoolean term = new AtomicBoolean();
        LongAdder succ = new LongAdder();
        LongAdder failed = new LongAdder();
        new Thread(() -> {
            while(!term.get()) {
                try {
                    supplier.tryClose(it -> {
                        MILLISECONDS.sleep(1);
                    });
                } catch (InterruptedException ignore) {
                    // ignore
                }
            }
        }).start();
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                while (!term.get()) {
                    String s = supplier.get();
                    if (s == null) {
                        failed.increment();
                    } else {
                        succ.increment();
                    }
                }
            }).start();
        }
        for (int i = 0; i < 30; i++) {
            System.out.println("waiting:" + i + ", current:" + succ.sum() + ", " + failed.sum());
            SECONDS.sleep(1);
            if (failed.sum() > 0) {
                break;
            }
        }
        term.set(true);
        assertTrue(failed.sum() == 0);
    }

    private String init() {
        return System.currentTimeMillis() + "";
    }
}

@@ -94,61 +94,8 @@
 DS;%0A
-import static java.util.concurrent.TimeUnit.MINUTES;%0A
 impo
@@ -135,32 +135,32 @@
 meUnit.SECONDS;%0A
+
 import static or
@@ -300,16 +300,64 @@
 Adder;%0A%0A
+import javax.management.RuntimeErrorException;%0A%0A
 import o
@@ -503,16 +503,94 @@
 upplier;
+%0Aimport com.github.phantomthief.util.MoreSuppliers.CloseableThrowableSupplier;
 %0A%0A/**%0A *
@@ -728,16 +728,64 @@
 ption %7B%0A
+        System.out.println(%22test concurrent.%22);%0A
         
@@ -1433,32 +1433,32 @@
 (!term.get()) %7B%0A
-
                 
@@ -2034,16 +2034,1577 @@
 %0A    %7D%0A%0A
+    @Test%0A    void testEx() throws InterruptedException %7B%0A        System.out.println(%22test concurrent ex.%22);%0A        CloseableThrowableSupplier%3CString, Throwable%3E supplier = MoreSuppliers.lazyEx(this::init, true);%0A        AtomicBoolean term = new AtomicBoolean();%0A        LongAdder succ = new LongAdder();%0A        LongAdder failed = new LongAdder();%0A        new Thread(() -%3E %7B%0A            while(!term.get()) %7B%0A                try %7B%0A                    supplier.tryClose(it -%3E %7B%0A                        MILLISECONDS.sleep(1);%0A                    %7D);%0A                %7D catch (InterruptedException ignore) %7B%0A                    // ignore%0A                %7D%0A            %7D%0A        %7D).start();%0A        for (int i = 0; i %3C 100; i++) %7B%0A            new Thread(() -%3E %7B%0A                while (!term.get()) %7B%0A                    String s;%0A                    try %7B%0A                        s = supplier.get();%0A                    %7D catch (Throwable e) %7B%0A                        throw new AssertionError(e);%0A                    %7D%0A                    if (s == null) %7B%0A                        failed.increment();%0A                    %7D else %7B%0A                        succ.increment();%0A                    %7D%0A                %7D%0A            %7D).start();%0A        %7D%0A        for (int i = 0; i %3C 30; i++) %7B%0A            System.out.println(%22waiting:%22 + i + %22, current:%22 + succ.sum() + %22, %22 + failed.sum());%0A            SECONDS.sleep(1);%0A            if (failed.sum() %3E 0) %7B%0A                break;%0A            %7D%0A        %7D%0A        term.set(true);%0A        assertTrue(failed.sum() == 0);%0A    %7D%0A%0A
     priv

add concurrent test for closeable supplier.