/*
 * 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.assertNotNull;
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 dependentAssertions() {
		// Within a code block, if an assertion fails the
		// subsequent code in the same block will be skipped.
		assertAll("properties",
			() -> {
				String firstName = address.getFirstName();
				assertNotNull(firstName);

				// Executed only if the previous assertion is valid.
				assertAll("first name",
					() -> assertTrue(firstName.startsWith("J")),
					() -> assertTrue(firstName.endsWith("n"))
				);
			},
			() -> {
				// Grouped assertion, so processed independently
				// of results of first name assertions.
				String lastName = address.getLastName();
				assertNotNull(lastName);

				// Executed only if the previous assertion is valid.
				assertAll("last name",
					() -> assertTrue(lastName.startsWith("U")),
					() -> assertTrue(lastName.endsWith("r"))
				);
			}
		);
	}

	@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;
	}

}

@@ -976,37 +976,34 @@
 %5B%5D%0A%09
-Address address = new Address
+Person person = new Person
 (%22Jo
@@ -1008,20 +1008,19 @@
 John%22, %22
-User
+Doe
 %22);%0A%0A%09//
@@ -1477,23 +1477,22 @@
 ertAll(%22
-address
+person
 %22,%0A%09%09%09()
@@ -1516,23 +1516,22 @@
 %22John%22, 
-address
+person
 .getFirs
@@ -1567,22 +1567,20 @@
 ls(%22
-User%22, address
+Doe%22, person
 .get
@@ -1801,31 +1801,30 @@
 firstName = 
-address
+person
 .getFirstNam
@@ -2188,15 +2188,14 @@
 e = 
-address
+person
 .get
@@ -2367,9 +2367,9 @@
 th(%22
-U
+D
 %22)),
@@ -2410,17 +2410,17 @@
 dsWith(%22
-r
+e
 %22))%0A%09%09%09%09
@@ -4162,23 +4162,22 @@
 %0A%0Aclass 
-Address
+Person
  %7B%0A%0A%09pri
@@ -4205,32 +4205,38 @@
 stName;%0A
-%0A
 %09p
-ublic
+rivate final
  String 
 getLastN
@@ -4231,68 +4231,111 @@
 ing 
-getL
+l
 astName
-() %7B%0A%09%09return lastName;%0A%09%7D%0A%0A%09private final String
+;%0A%0A%09Person(String firstName, String lastName) %7B%0A%09%09this.firstName = firstName;%0A%09%09this.lastName =
  las
@@ -4341,25 +4341,21 @@
 stName;%0A
-%0A%09public 
+%09%7D%0A%0A%09
 String g
@@ -4399,108 +4399,39 @@
 %7D%0A%0A%09
-public Address(String firstName, String l
+String getL
 astName
+(
 ) %7B%0A
-%0A
 %09%09
-this.firstName = firstName;%0A%09%09this.lastName =
+return
  las

Replace Address with Person in assertion examples