/*
 * Copyright 2015-2017 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 example;

// @formatter:off
// tag::user_guide[]
import static java.time.Duration.ofMillis;
import static java.time.Duration.ofMinutes;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTimeout;
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class AssertionsDemo {

	// end::user_guide[]
	Address address = new Address("John", "User");

	// tag::user_guide[]
	@Test
	void standardAssertions() {
		assertEquals(2, 2);
		assertEquals(4, 4, "The optional assertion message is now the last parameter.");
		assertTrue(2 == 2, () -> "Assertion messages can be lazily evaluated -- "
				+ "to avoid constructing complex messages unnecessarily.");
	}

	@Test
	void groupedAssertions() {
		// In a grouped assertion all assertions are executed, and any
		// failures will be reported together.
		assertAll("address",
			() -> assertEquals("John", address.getFirstName()),
			() -> assertEquals("User", address.getLastName())
		);
	}

	@Test
	void exceptionTesting() {
		Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
			throw new IllegalArgumentException("a message");
		});
		assertEquals("a message", exception.getMessage());
	}

	@Test
	void timeoutNotExceeded() {
		// The following assertion succeeds.
		assertTimeout(ofMinutes(2), () -> {
			// Perform task that takes less than 2 minutes.
		});
	}

	@Test
	void timeoutNotExceededWithResult() {
		// The following assertion succeeds, and returns the supplied object.
		String actualResult = assertTimeout(ofMinutes(2), () -> {
			return "a result";
		});
		assertEquals("a result", actualResult);
	}

	@Test
	void timeoutNotExceededWithMethod() {
		// The following assertion invokes a method reference and returns an object.
		String actualGreeting = assertTimeout(ofMinutes(2), AssertionsDemo::greeting);
		assertEquals("hello world!", actualGreeting);
	}

	// end::user_guide[]
	@extensions.ExpectToFail
	// tag::user_guide[]
	@Test
	void timeoutExceeded() {
		// The following assertion fails with an error message similar to:
		// execution exceeded timeout of 10 ms by 91 ms
		assertTimeout(ofMillis(10), () -> {
			// Simulate task that takes more than 10 ms.
			Thread.sleep(100);
		});
	}

	// end::user_guide[]
	@extensions.ExpectToFail
	// tag::user_guide[]
	@Test
	void timeoutExceededWithPreemptiveTermination() {
		// The following assertion fails with an error message similar to:
		// execution timed out after 10 ms
		assertTimeoutPreemptively(ofMillis(10), () -> {
			// Simulate task that takes more than 10 ms.
			Thread.sleep(100);
		});
	}

	private static String greeting() {
		return "hello world!";
	}

}
// end::user_guide[]
// @formatter:on

class Address {

	private final String firstName;

	public String getLastName() {
		return lastName;
	}

	private final String lastName;

	public String getFirstName() {
		return firstName;
	}

	public Address(String firstName, String lastName) {

		this.firstName = firstName;
		this.lastName = lastName;
	}

}

@@ -570,16 +570,78 @@
 Equals;%0A
+import static org.junit.jupiter.api.Assertions.assertNotNull;%0A
 import s
@@ -1604,24 +1604,848 @@
 ))%0A%09%09);%0A%09%7D%0A%0A
+%09@Test%0A%09void dependentAssertions() %7B%0A%09%09// In a code block first failed assertion throws exception,%0A%09%09// subsequent code in the same block is skipped.%0A%09%09assertAll(%22properties%22,%0A%09%09%09() -%3E %7B%0A%09%09%09%09String firstName = address.getFirstName();%0A%09%09%09%09assertNotNull(firstName);%0A%0A%09%09%09%09// Executed only when previous test is valid.%0A%09%09%09%09assertAll(%22first name%22,%0A%09%09%09%09%09() -%3E assertTrue(firstName.startsWith(%22J%22)),%0A%09%09%09%09%09() -%3E assertTrue(firstName.endsWith(%22n%22))%0A%09%09%09%09);%0A%09%09%09%7D,%0A%09%09%09() -%3E %7B%0A%09%09%09%09// Grouped assertion, so processed independently%0A%09%09%09%09// of results of first-name tests.%0A%09%09%09%09String lastName = address.getLastName();%0A%0A%09%09%09%09assertNotNull(lastName);%0A%09%09%09%09// Executed only when previous test is valid.%0A%09%09%09%09assertAll(%22last name%22,%0A%09%09%09%09%09() -%3E assertTrue(lastName.startsWith(%22U%22)),%0A%09%09%09%09%09() -%3E assertTrue(lastName.endsWith(%22r%22))%0A%09%09%09%09);%0A%09%09%09%7D%0A%09%09);%0A%09%7D%0A%0A
 %09@Test%0A%09void

Introduce example for dependent assertions