package com.github.junit5docker;

import org.junit.jupiter.api.Test;

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

import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.assertj.core.api.Assertions.assertThat;

public class OpenQueueIteratorTest {

    @Test
    public void shouldHaveNothingIfClosed() throws InterruptedException {
        ArrayBlockingQueue<String> lines = new ArrayBlockingQueue<>(1);
        lines.put("a line");
        OpenQueueIterator iterator = new OpenQueueIterator(new AtomicBoolean(false), lines);
        assertThat(iterator.hasNext()).isFalse();
    }

    @Test
    public void shouldHaveContentIfDataIsInQueue() throws InterruptedException {
        ArrayBlockingQueue<String> lines = new ArrayBlockingQueue<>(1);
        lines.put("a line");
        OpenQueueIterator iterator = new OpenQueueIterator(new AtomicBoolean(true), lines);
        assertThat(iterator.hasNext()).isTrue();
        assertThat(iterator.next()).isEqualTo("a line");
    }

    @Test
    public void shouldInterruptIfBooleanPassesToFalse() throws InterruptedException, TimeoutException, ExecutionException {
        ArrayBlockingQueue<String> lines = new ArrayBlockingQueue<>(1);
        AtomicBoolean opened = new AtomicBoolean(true);
        OpenQueueIterator iterator = new OpenQueueIterator(opened, lines);
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
        Future<Boolean> hasNext = executor.submit(iterator::hasNext);
        executor.schedule(() -> opened.set(false), 50, MILLISECONDS);
        executor.shutdown();
        assertThat(executor.awaitTermination(200, MILLISECONDS)).isTrue();
        assertThat(hasNext.get()).isFalse();
    }

    @Test
    public void shouldGiveFirstLineEvenAfterTwoCallToHasNext() throws InterruptedException {
        ArrayBlockingQueue<String> lines = new ArrayBlockingQueue<>(1);
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        executor.submit(() -> {
            try {
                lines.put("a line");
            } catch (InterruptedException e) {
            }
        });
        executor.schedule(() -> {
            try {
                lines.put("a line 2");
            } catch (InterruptedException e) {
            }
        }, 20, MILLISECONDS);
        OpenQueueIterator iterator = new OpenQueueIterator(new AtomicBoolean(true), lines);
        assertThat(iterator.hasNext()).isTrue();
        assertThat(iterator.hasNext()).isTrue();
        assertThat(iterator.next()).isEqualTo("a line");
        executor.shutdownNow();
    }

    @Test
    public void shouldInterruptIfThreadIsInterrupted() throws InterruptedException, TimeoutException,
            ExecutionException {
        ArrayBlockingQueue<String> lines = new ArrayBlockingQueue<>(1);
        AtomicBoolean opened = new AtomicBoolean(true);
        OpenQueueIterator iterator = new OpenQueueIterator(opened, lines);
        Thread.currentThread().interrupt();
        assertThat(iterator.hasNext()).isFalse();
        assertThat(Thread.interrupted()).isTrue();
        assertThat(opened.get()).isFalse();
    }


    @Test
    public void shouldReadLineOnlyOnce() throws InterruptedException {
        AtomicBoolean opened = new AtomicBoolean(true);
        ArrayBlockingQueue<String> lines = new ArrayBlockingQueue<>(1);
        lines.put("a line");
        OpenQueueIterator iterator = new OpenQueueIterator(opened, lines);
        iterator.hasNext();
        iterator.next();
        opened.set(false);
        assertThat(iterator.hasNext()).isFalse();
    }
}
@@ -95,9 +95,163 @@
 ent.
-*
+ArrayBlockingQueue;%0Aimport java.util.concurrent.CountDownLatch;%0Aimport java.util.concurrent.Executors;%0Aimport java.util.concurrent.ScheduledExecutorService
 ;%0Aim
@@ -1283,46 +1283,8 @@
 tion
-, TimeoutException, ExecutionException
  %7B%0A 
@@ -1402,32 +1402,159 @@
 cBoolean(true);%0A
+        CountDownLatch hasNextStarted = new CountDownLatch(1);%0A        CountDownLatch hasNextReturned = new CountDownLatch(1);%0A
         OpenQueu
@@ -1674,89 +1674,132 @@
 newS
-cheduledThreadPool(2);%0A        Future%3CBoolean%3E hasNext = executor.submit(
+ingleThreadScheduledExecutor();%0A        executor.submit(() -%3E %7B%0A            hasNextStarted.countDown();%0A            
 iterator
 ::ha
@@ -1798,17 +1798,17 @@
 ator
-::
+.
 hasNext
+(
 );%0A 
@@ -1818,215 +1818,297 @@
     
-executor.schedule(() -%3E opened.set(false), 50, MILLISECONDS);%0A        executor.shutdown();%0A        assertThat(executor.awaitTermination(200, MILLISECONDS)).isTrue();%0A        assertThat(hasNext.get()).isFalse
+    hasNextReturned.countDown();%0A        %7D);%0A        hasNextStarted.await();%0A        opened.set(false);%0A        assertThat(hasNextReturned.await(100, MILLISECONDS))%0A                .overridingErrorMessage(%22hasNext should have returned%22)%0A                .isTrue();%0A        executor.shutdown
 ();%0A
@@ -2281,32 +2281,96 @@
 kingQueue%3C%3E(1);%0A
+        CountDownLatch firstLinePushed = new CountDownLatch(1);%0A
         Schedule
@@ -2513,32 +2513,77 @@
 .put(%22a line%22);%0A
+                firstLinePushed.countDown();%0A
             %7D ca
@@ -2657,23 +2657,21 @@
 ecutor.s
-chedule
+ubmit
 (() -%3E %7B
@@ -2681,32 +2681,73 @@
           try %7B%0A
+                firstLinePushed.await();%0A
                 
@@ -2843,26 +2843,8 @@
    %7D
-, 20, MILLISECONDS
 );%0A 
@@ -3224,58 +3224,8 @@
 tion
-, TimeoutException,%0A            ExecutionException
  %7B%0A 
@@ -3622,17 +3622,16 @@
 %0A    %7D%0A%0A
-%0A
     @Tes

Make IT test more determinist