package org.cryptomator.cryptofs.migration.api;

import org.cryptomator.cryptofs.migration.api.MigrationContinuationListener.ContinuationEvent;
import org.cryptomator.cryptofs.migration.api.MigrationContinuationListener.ContinuationResult;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.time.Duration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class SimpleMigrationContinuationListenerTest {
	
	@Test
	public void testConcurrency() {
		ExecutorService threadPool = Executors.newFixedThreadPool(1);
		Lock lock = new ReentrantLock();
		Condition receivedEvent = lock.newCondition();

		SimpleMigrationContinuationListener inTest = new SimpleMigrationContinuationListener() {
			@Override
			void migrationHaltedDueToEvent(ContinuationEvent event) {
				System.out.println("received event on " + Thread.currentThread());
				lock.lock();
				try {
					receivedEvent.signal();
				} finally {
					lock.unlock();
				}
			}
		};

		threadPool.submit(() -> {
			lock.lock();
			try {
				receivedEvent.await();
				System.out.println("choosing PROCEED on thread " + Thread.currentThread());
				inTest.continueMigrationWithResult(ContinuationResult.PROCEED);
			} catch (InterruptedException e) {
				Thread.interrupted();
				Assertions.fail();
			} finally {
				lock.unlock();
			}
		});

		Assertions.assertTimeoutPreemptively(Duration.ofSeconds(1), () -> { // deadlock protection
			ContinuationResult result = inTest.continueMigrationOnEvent(ContinuationEvent.REQUIRES_FULL_VAULT_DIR_SCAN);
			Assertions.assertEquals(ContinuationResult.PROCEED, result);
		});
	}

}
@@ -424,142 +424,8 @@
 ors;
-%0Aimport java.util.concurrent.locks.Condition;%0Aimport java.util.concurrent.locks.Lock;%0Aimport java.util.concurrent.locks.ReentrantLock;
 %0A%0Acl
@@ -560,11 +560,12 @@
 .new
-Fix
+Cach
 edTh
@@ -577,93 +577,8 @@
 ool(
-1);%0A%09%09Lock lock = new ReentrantLock();%0A%09%09Condition receivedEvent = lock.newCondition(
 );%0A%0A
@@ -738,24 +738,87 @@
 nt event) %7B%0A
+%09%09%09%09// receive event on background thread that runs migration:%0A
 %09%09%09%09System.o
@@ -877,120 +877,28 @@
 ad()
-);%0A%09%09%09%09lock.lock();%0A%09%09%09%09try %7B%0A%09%09%09%09%09receivedEvent.signal();%0A%09%09%09%09%7D finally %7B%0A%09%09%09%09%09lock.unlock(
+.getName()
 );%0A%09%09%09%09
-%7D
 %0A%09%09
-%09%7D%0A%09%09%7D;%0A%0A
 %09%09th
@@ -928,57 +928,72 @@
 %0A%09%09%09
-lock.lock();%0A%09%09%09try %7B%0A%09%09%09%09receivedEvent.await();%0A
+%09%09// choose PROCEED on different thread (like from UI events):%0A%09
 %09%09%09%09
@@ -1069,21 +1069,30 @@
 ad()
+.getName()
 );%0A%09%09%09%09
+%09
-inTest
+this
 .con
@@ -1152,123 +1152,10 @@
 %0A%09%09%09
+%09
 %7D
- catch (InterruptedException e) %7B%0A%09%09%09%09Thread.interrupted();%0A%09%09%09%09Assertions.fail();%0A%09%09%09%7D finally %7B%0A%09%09%09%09lock.unlock(
 );%0A%09
@@ -1161,17 +1161,16 @@
 %09%09%09%7D%0A%09%09%7D
-)
 ;%0A%0A%09%09Ass
@@ -1223,16 +1223,17 @@
 econds(1
+0
 ), () -%3E
@@ -1370,16 +1370,112 @@
 _SCAN);%0A
+%09%09%09System.out.println(%22received result %22 + result + %22 on %22 + Thread.currentThread().getName());%0A
 %09%09%09Asser
@@ -1535,14 +1535,40 @@
 );%0A%09%09%7D);
+%0A%0A%09%09threadPool.shutdown();
 %0A%09%7D%0A%0A%7D

simplify unit test (for #77)