/*
 * Copyright 2015-2016 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.api;

import static java.util.Spliterator.ORDERED;
import static java.util.Spliterators.spliteratorUnknownSize;
import static org.junit.gen5.commons.meta.API.Usage.Experimental;

import java.util.Iterator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.junit.gen5.commons.meta.API;
import org.junit.gen5.commons.util.Preconditions;
import org.junit.gen5.commons.util.ToStringBuilder;

/**
 * A {@code DynamicTest} is a test case generated at runtime.
 *
 * <p>It is composed of a {@linkplain #getDisplayName display name} and an
 * {@link #getExecutable Executable}.
 *
 * <p>Instances of {@code DynamicTest} must be generated by factory methods
 * annotated with {@link TestFactory @TestFactory}.
 *
 * <p>Note that dynamic tests are quite different from standard {@link Test @Test}
 * cases since callbacks such as {@link BeforeEach @BeforeEach} and
 * {@link AfterEach @AfterEach} methods are not executed for dynamic tests.
 *
 * @since 5.0
 * @see Test
 * @see TestFactory
 * @see Executable
 */
@API(Experimental)
public class DynamicTest {

	public static <T> Stream<DynamicTest> stream(Iterator<T> inputGenerator,
			Function<? super T, String> displayNameGenerator, Consumer<? super T> testGenerator) {

		Preconditions.notNull(inputGenerator, "inputGenerator must not be null");
		Preconditions.notNull(displayNameGenerator, "displayNameGenerator must not be null");
		Preconditions.notNull(testGenerator, "testGenerator must not be null");

		// @formatter:off
		return StreamSupport.stream(spliteratorUnknownSize(inputGenerator, ORDERED), false)
				.map(input -> new DynamicTest(displayNameGenerator.apply(input), () -> testGenerator.accept(input)));
		// @formatter:on
	}

	private final String displayName;
	private final Executable executable;

	/**
	 * Create a new {@code DynamicTest} for the supplied display name and
	 * executable code block.
	 *
	 * @param displayName the display name of this dynamic test; never
	 * {@code null} or empty
	 * @param executable the executable code block for this dynamic test;
	 * never {@code null}
	 */
	public DynamicTest(String displayName, Executable executable) {
		this.displayName = Preconditions.notBlank(displayName, "displayName must not be null or empty");
		this.executable = Preconditions.notNull(executable, "executable must not be null");
	}

	/**
	 * Get the display name of this {@code DynamicTest}.
	 */
	public String getDisplayName() {
		return this.displayName;
	}

	/**
	 * Get the {@code executable} code block associated with this {@code DynamicTest}.
	 */
	public Executable getExecutable() {
		return this.executable;
	}

	@Override
	public String toString() {
		return new ToStringBuilder(this).append("displayName", displayName).toString();
	}

}

@@ -1486,16 +1486,1107 @@
 Test %7B%0A%0A
+%09/**%0A%09 * Generate a stream of dynamic tests based on the supplied generators%0A%09 * and test executor.%0A%09 *%0A%09 * %3Cp%3EUse this method when the set of dynamic tests is nondeterministic%0A%09 * in nature.%0A%09 *%0A%09 * %3Cp%3EThe supplied %7B@code inputGenerator%7D is responsible for generating%0A%09 * input values. A %7B@link DynamicTest%7D will be added to the resulting%0A%09 * stream for each dynamically generated input value, using the supplied%0A%09 * %7B@code displayNameGenerator%7D and %7B@code testExecutor%7D.%0A%09 *%0A%09 * @param inputGenerator an %7B@code Iterator%7D that serves as a dynamic%0A%09 * %3Cem%3Einput generator%3C/em%3E; never %7B@code null%7D%0A%09 * @param displayNameGenerator a function that generates a display name%0A%09 * based on an input value; never %7B@code null%7D%0A%09 * @param testExecutor a consumer that executes a test based on an%0A%09 * input value; never %7B@code null%7D%0A%09 * @param %3CT%3E the type of %3Cem%3Einput%3C/em%3E generated by the %7B@code inputGenerator%7D%0A%09 * and used by the %7B@code displayNameGenerator%7D and %7B@code testExecutor%7D%0A%09 * @return a stream of dynamic tests based on the supplied generators and%0A%09 * executor; never %7B@code null%7D%0A%09 */%0A
 %09public 
@@ -2728,22 +2728,21 @@
  T%3E test
-Genera
+Execu
 tor) %7B%0A%0A
@@ -2933,22 +2933,21 @@
 ull(test
-Genera
+Execu
 tor, %22te
@@ -2948,22 +2948,21 @@
 r, %22test
-Genera
+Execu
 tor must
@@ -3163,22 +3163,21 @@
  -%3E test
-Genera
+Execu
 tor.acce

Document DynamicTest.stream()