/*
 * Copyright 2015 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.junit.gen5.engine.junit5;

import static org.junit.gen5.api.Assertions.*;
import static org.junit.gen5.api.Assumptions.*;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Assert;
import org.junit.gen5.api.Test;
import org.junit.gen5.engine.TestDescriptor;
import org.junit.gen5.engine.TestExecutionListener;
import org.junit.gen5.engine.TestPlanSpecification;

/**
 * Unit tests for {@link JUnit5TestEngine}.
 *
 * @author Sam Brannen
 * @since 5.0
 */
public class JUnit5TestEngineTests {

	@org.junit.Test
	public void executeTestsFromDescriptorsGeneratedFromClasses() {
		JUnit5TestEngine engine = new JUnit5TestEngine();

		TestPlanSpecification spec = TestPlanSpecification.builder().classes(LocalTestCase.class).build();

		List<TestDescriptor> descriptors = engine.discoverTests(spec);
		Assert.assertNotNull(descriptors);
		Assert.assertEquals("# tests", 3, descriptors.size());

		TrackingTestExecutionListener listener = new TrackingTestExecutionListener();

		engine.execute(descriptors, listener);

		Assert.assertEquals(3, listener.testStartedCount.get());
		Assert.assertEquals(1, listener.testSucceededCount.get());
		Assert.assertEquals(1, listener.testAbortedCount.get());
		Assert.assertEquals(1, listener.testFailedCount.get());
	}


	private static class LocalTestCase {

		@Test
		void alwaysPasses() {
			/* no-op */
		}

		@Test
		void aborted() {
			assumeTrue(false);
		}

		@Test
		void alwaysFails() {
			fail("#fail");
		}

	}

	/**
	 * Simple {@link TestExecutionListener} that tracks the number of times
	 * that certain callbacks are invoked.
	 */
	private static class TrackingTestExecutionListener implements TestExecutionListener {

		final AtomicInteger testStartedCount = new AtomicInteger();
		final AtomicInteger testSucceededCount = new AtomicInteger();
		final AtomicInteger testAbortedCount = new AtomicInteger();
		final AtomicInteger testFailedCount = new AtomicInteger();


		@Override
		public void testStarted(TestDescriptor testDescriptor) {
			testStartedCount.incrementAndGet();
		}

		@Override
		public void testSucceeded(TestDescriptor testDescriptor) {
			testSucceededCount.incrementAndGet();
		}

		@Override
		public void testAborted(TestDescriptor testDescriptor, Throwable t) {
			testAbortedCount.incrementAndGet();
		}

		@Override
		public void testFailed(TestDescriptor testDescriptor, Throwable t) {
			testFailedCount.incrementAndGet();
		}

	}

}

@@ -898,28 +898,8 @@
 From
-DescriptorsGenerated
 From
@@ -910,16 +910,16 @@
 ses() %7B%0A
+
 %09%09JUnit5
@@ -963,16 +963,36 @@
 ine();%0A%0A
+%09%09// @formatter:off%0A
 %09%09TestPl
@@ -1045,16 +1045,20 @@
 uilder()
+%0A%09%09%09
 .classes
@@ -1078,16 +1078,20 @@
 e.class)
+%0A%09%09%09
 .build()
@@ -1091,16 +1091,35 @@
 build();
+%0A%09%09// @formatter:on
 %0A%0A%09%09List
@@ -1566,32 +1566,32 @@
 edCount.get());%0A
-
 %09%09Assert.assertE
@@ -1636,16 +1636,752 @@
 ));%0A%09%7D%0A%0A
+%09@org.junit.Test%0A%09public void executeTestFromTestId() %7B%0A%09%09JUnit5TestEngine engine = new JUnit5TestEngine();%0A%0A%09%09// @formatter:off%0A%09%09TestPlanSpecification spec = TestPlanSpecification.builder()%0A%09%09%09.uniqueIds(%22junit5:org.junit.gen5.engine.junit5.JUnit5TestEngineTests$LocalTestCase#alwaysPasses()%22)%0A%09%09%09.build();%0A%09%09// @formatter:on%0A%0A%09%09List%3CTestDescriptor%3E descriptors = engine.discoverTests(spec);%0A%09%09Assert.assertNotNull(descriptors);%0A%09%09Assert.assertEquals(%22# tests%22, 1, descriptors.size());%0A%0A%09%09TrackingTestExecutionListener listener = new TrackingTestExecutionListener();%0A%0A%09%09engine.execute(descriptors, listener);%0A%0A%09%09Assert.assertEquals(1, listener.testStartedCount.get());%0A%09%09Assert.assertEquals(1, listener.testSucceededCount.get());%0A%09%7D%0A%0A
 %0A%09privat

Introduce test for test execution based on test ID