package de.retest.recheck.persistence.bin;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;

import de.retest.recheck.persistence.IncompatibleReportVersionException;
import de.retest.recheck.util.VersionProvider;

class KryoPersistenceTest {

	@Test
	void roundtrip_should_work( @TempDir final Path temp ) throws IOException {
		final Path file = temp.resolve( "test.test" );
		Files.createFile( file );
		final URI identifier = file.toUri();

		final KryoPersistence<de.retest.recheck.test.Test> kryoPersistence = new KryoPersistence<>();
		final de.retest.recheck.test.Test persisted = createDummyTest();
		kryoPersistence.save( identifier, persisted );
		final de.retest.recheck.test.Test loaded = kryoPersistence.load( identifier );

		assertThat( persisted.getRelativeActionSequencePaths() ).isEqualTo( loaded.getRelativeActionSequencePaths() );
	}

	public de.retest.recheck.test.Test createDummyTest() {
		final ArrayList<String> tests = new ArrayList<>();
		tests.add( "../test.test" );
		return new de.retest.recheck.test.Test( tests );
	}

	@Test
	void incompatible_version_should_give_persisting_version( @TempDir final Path temp ) throws IOException {
		final Path file = temp.resolve( "incompatible-test.test" );
		Files.createFile( file );
		final URI identifier = file.toUri();

		final KryoPersistence<de.retest.recheck.test.Test> kryoPersistence = new KryoPersistence<>();
		kryoPersistence.save( identifier, createDummyTest() );

		final Kryo kryoMock = mock( Kryo.class );
		when( kryoMock.readClassAndObject( any() ) ).thenThrow( KryoException.class );
		final KryoPersistence<de.retest.recheck.test.Test> differentKryoPersistence =
				new KryoPersistence<>( kryoMock, "old Version" );

		assertThatThrownBy( () -> differentKryoPersistence.load( identifier ) )
				.isInstanceOf( IncompatibleReportVersionException.class )
				.hasMessageContaining( "Incompatible recheck versions: report was written with "
						+ VersionProvider.RETEST_VERSION + ", but read with old Version." );
	}

	@Test
	void unknown_version_should_give_correct_error() throws IOException {
		final Path file = Paths.get( "src/test/resources/de/retest/recheck/persistence/bin/old.report" );
		final URI identifier = file.toUri();

		final KryoPersistence<de.retest.recheck.test.Test> differentKryoPersistence = new KryoPersistence<>();

		assertThatThrownBy( () -> differentKryoPersistence.load( identifier ) )
				.isInstanceOf( IncompatibleReportVersionException.class ).hasMessageContaining(
						"Incompatible recheck versions: report was written with an old recheck version (pre 1.5.0), but read with "
								+ VersionProvider.RETEST_VERSION + "." );
	}
}

@@ -209,16 +209,59 @@
 rs.any;%0A
+import static org.mockito.Mockito.doThrow;%0A
 import s
@@ -329,24 +329,45 @@
 kito.when;%0A%0A
+import java.io.File;%0A
 import java.
@@ -3243,11 +3243,572 @@
 .%22 );%0A%09%7D
+%0A%0A%09@Test%0A%09void on_error_file_should_be_deleted() throws IOException %7B%0A%09%09final File nonexistent = new File( %22nonexistent.report%22 );%0A%09%09final Kryo kryoMock = mock( Kryo.class );%0A%09%09doThrow( KryoException.class ).when( kryoMock ).writeClassAndObject( any(), any() );%0A%09%09final KryoPersistence%3Cde.retest.recheck.test.Test%3E persistence =%0A%09%09%09%09new KryoPersistence%3C%3E( kryoMock, %22some version%22 );%0A%09%09assertThatThrownBy( () -%3E persistence.save( nonexistent.toURI(), createDummyTest() ) )%0A%09%09%09%09.isInstanceOf( KryoException.class );%0A%09%09assertThat( nonexistent ).doesNotExist();%0A%09%7D
 %0A%7D%0A

Add test that file gets removed. Test fails if that code is removed...