import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.RepeatedTest;

import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Function;
import java.util.stream.Collectors;

public class MockForDeadLoop {

    @RepeatedTest(100)
    public void test34() throws Exception{
        LinkedBlockingQueue<String> eventQueue = new LinkedBlockingQueue<>();
        final int LOOP = 3;
        final long sleepTime = 100;
        boolean print = true;
        eventQueue.put("a");
        eventQueue.put("b");
        eventQueue.put("c");
        eventQueue.put("d");
        eventQueue.put("e");

        long joinCoef = 3;
        long expectMaxTime = eventQueue.size() * LOOP * sleepTime * 2;
        long joinExpectTime = expectMaxTime * joinCoef;
        System.out.println("expectTime is " + expectMaxTime);

        long start = System.currentTimeMillis();
        Thread takeThread = new Thread(){
            @Override
            public void run() {
                int n = LOOP;
                for (int i=0;i<n;i++) {
                    try {
                        String val = eventQueue.take();
                        if (print) {
                            System.out.println("take : " + val);
                        }
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Thread iteThread = new Thread(){
            @Override
            public void run() {
                int n = LOOP;
                for (int i=0;i<n;i++) {
                    Map<String, Long> counterMap = eventQueue.stream().
                            collect(Collectors.
                                    groupingBy(new Function<String, String>() {
                                        @Override
                                        public String apply(String s) {
                                            try {
                                                Thread.sleep(sleepTime *2 );
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                            return s;
                                        }
                                    }, Collectors.counting())
                            );
                    if (print) {
                        for (Map.Entry<String, Long> entry : counterMap.entrySet()) {
                            System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue());
                        }
                    }
                }
            }
        };

        iteThread.start();
        Thread.sleep(sleepTime);
        takeThread.start();
        takeThread.join(joinExpectTime);
        iteThread.join(joinExpectTime);
        long interval = System.currentTimeMillis() - start;
        System.out.println("interval = " + interval);
        Assertions.assertTrue(interval < joinExpectTime);
        /*
        if (interval >= joinExpectTime) {
            System.out.println("stuck!!!");
        } else {
            System.out.println("not stuck!!!");
        }*/
    }
} 