parent
568caa1206
commit
1b237de5f5
|
|
@ -345,6 +345,11 @@
|
||||||
<artifactId>jersey-media-json-jackson</artifactId>
|
<artifactId>jersey-media-json-jackson</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.jayway.jsonpath</groupId>
|
<groupId>com.jayway.jsonpath</groupId>
|
||||||
<artifactId>json-path</artifactId>
|
<artifactId>json-path</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,10 @@ package org.springframework.boot.actuate.management;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
||||||
import org.springframework.boot.actuate.endpoint.web.test.WebEndpointTest;
|
import org.springframework.boot.actuate.endpoint.web.test.WebEndpointTest;
|
||||||
|
|
@ -31,7 +33,7 @@ import org.springframework.http.MediaType;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests for {@link HeapDumpWebEndpoint} exposed by Jersey, Spring MVC, and
|
* Integration tests for {@link HeapDumpWebEndpoint} exposed by Jersey, Spring MVC, and
|
||||||
|
|
@ -64,11 +66,7 @@ class HeapDumpWebEndpointWebIntegrationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertHeapDumpFileIsDeleted() throws InterruptedException {
|
private void assertHeapDumpFileIsDeleted() throws InterruptedException {
|
||||||
long end = System.currentTimeMillis() + 5000;
|
Awaitility.waitAtMost(Duration.ofSeconds(5)).until(this.endpoint.file::exists, is(false));
|
||||||
while (System.currentTimeMillis() < end && this.endpoint.file.exists()) {
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
assertThat(this.endpoint.file.exists()).isFalse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
|
||||||
|
|
@ -897,6 +897,11 @@
|
||||||
<artifactId>tomcat-embed-jasper</artifactId>
|
<artifactId>tomcat-embed-jasper</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hsqldb</groupId>
|
<groupId>org.hsqldb</groupId>
|
||||||
<artifactId>hsqldb</artifactId>
|
<artifactId>hsqldb</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.orm.jpa;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -27,6 +28,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
|
@ -37,6 +39,7 @@ import javax.transaction.TransactionManager;
|
||||||
import javax.transaction.UserTransaction;
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
|
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
|
||||||
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
|
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
@ -77,6 +80,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.entry;
|
import static org.assertj.core.api.Assertions.entry;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -387,12 +391,8 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes
|
||||||
assertThat(context).hasNotFailed();
|
assertThat(context).hasNotFailed();
|
||||||
EventCapturingApplicationListener listener = context
|
EventCapturingApplicationListener listener = context
|
||||||
.getBean(EventCapturingApplicationListener.class);
|
.getBean(EventCapturingApplicationListener.class);
|
||||||
long end = System.currentTimeMillis() + 30000;
|
Awaitility.waitAtMost(Duration.ofSeconds(30))
|
||||||
while ((System.currentTimeMillis() < end) && !dataSourceSchemaCreatedEventReceived(listener)) {
|
.until(() -> dataSourceSchemaCreatedEventsReceivedBy(listener), hasSize(1));
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
assertThat(listener.events.stream().filter(DataSourceSchemaCreatedEvent.class::isInstance))
|
|
||||||
.hasSize(1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -408,13 +408,9 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean dataSourceSchemaCreatedEventReceived(EventCapturingApplicationListener listener) {
|
private List<ApplicationEvent> dataSourceSchemaCreatedEventsReceivedBy(EventCapturingApplicationListener listener) {
|
||||||
for (ApplicationEvent event : listener.events) {
|
return listener.events.stream().filter(DataSourceSchemaCreatedEvent.class::isInstance)
|
||||||
if (event instanceof DataSourceSchemaCreatedEvent) {
|
.collect(Collectors.toList());
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,11 @@
|
||||||
<artifactId>HikariCP</artifactId>
|
<artifactId>HikariCP</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-webmvc</artifactId>
|
<artifactId>spring-webmvc</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,14 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.tomcat.websocket.WsWebSocketContainer;
|
import org.apache.tomcat.websocket.WsWebSocketContainer;
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
|
@ -43,6 +45,9 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
||||||
import org.springframework.web.socket.handler.TextWebSocketHandler;
|
import org.springframework.web.socket.handler.TextWebSocketHandler;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link LiveReloadServer}.
|
* Tests for {@link LiveReloadServer}.
|
||||||
|
|
@ -107,10 +112,7 @@ class LiveReloadServerTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void awaitClosedException() throws InterruptedException {
|
private void awaitClosedException() throws InterruptedException {
|
||||||
long startTime = System.currentTimeMillis();
|
Awaitility.waitAtMost(Duration.ofSeconds(10)).until(this.server::getClosedExceptions, is(not(empty())));
|
||||||
while (this.server.getClosedExceptions().isEmpty() && System.currentTimeMillis() - startTime < 10000) {
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,19 @@
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Test -->
|
<!-- Test -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-test-support</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.awaitility</groupId>
|
||||||
<artifactId>spring-webmvc</artifactId>
|
<artifactId>awaitility</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
@ -39,8 +44,8 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-boot-test-support</artifactId>
|
<artifactId>spring-webmvc</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -28,6 +29,7 @@ import java.util.jar.Attributes;
|
||||||
import java.util.jar.Manifest;
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
import org.assertj.core.api.Condition;
|
import org.assertj.core.api.Condition;
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
@ -44,6 +46,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link PropertiesLauncher}.
|
* Tests for {@link PropertiesLauncher}.
|
||||||
|
|
@ -339,14 +342,7 @@ class PropertiesLauncherTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitFor(String value) throws Exception {
|
private void waitFor(String value) throws Exception {
|
||||||
int count = 0;
|
Awaitility.waitAtMost(Duration.ofSeconds(5)).until(this.output::toString, containsString(value));
|
||||||
boolean timeout = false;
|
|
||||||
while (!timeout && count < 100) {
|
|
||||||
count++;
|
|
||||||
Thread.sleep(50L);
|
|
||||||
timeout = this.output.toString().contains(value);
|
|
||||||
}
|
|
||||||
assertThat(timeout).as("Timed out waiting for (" + value + ")").isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Condition<Archive> endingWith(String value) {
|
private Condition<Archive> endingWith(String value) {
|
||||||
|
|
|
||||||
|
|
@ -421,6 +421,11 @@
|
||||||
<artifactId>httpasyncclient</artifactId>
|
<artifactId>httpasyncclient</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.firebirdsql.jdbc</groupId>
|
<groupId>org.firebirdsql.jdbc</groupId>
|
||||||
<artifactId>jaybird-jdk18</artifactId>
|
<artifactId>jaybird-jdk18</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import java.time.Duration;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import io.undertow.Undertow;
|
import io.undertow.Undertow;
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
@ -36,6 +37,7 @@ import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.inOrder;
|
import static org.mockito.Mockito.inOrder;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
@ -124,11 +126,8 @@ class UndertowReactiveWebServerFactoryTests extends AbstractReactiveWebServerFac
|
||||||
assertThat(accessLogDirectory.listFiles()).contains(accessLog);
|
assertThat(accessLogDirectory.listFiles()).contains(accessLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void awaitFile(File file) throws InterruptedException {
|
private void awaitFile(File file) {
|
||||||
long end = System.currentTimeMillis() + 10000;
|
Awaitility.waitAtMost(Duration.ofSeconds(10)).until(file::exists, is(true));
|
||||||
while (!file.exists() && System.currentTimeMillis() < end) {
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -34,6 +35,7 @@ import io.undertow.Undertow.Builder;
|
||||||
import io.undertow.servlet.api.DeploymentInfo;
|
import io.undertow.servlet.api.DeploymentInfo;
|
||||||
import io.undertow.servlet.api.ServletContainer;
|
import io.undertow.servlet.api.ServletContainer;
|
||||||
import org.apache.jasper.servlet.JspServlet;
|
import org.apache.jasper.servlet.JspServlet;
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
|
|
@ -49,6 +51,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIOException;
|
import static org.assertj.core.api.Assertions.assertThatIOException;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.inOrder;
|
import static org.mockito.Mockito.inOrder;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
@ -234,11 +237,8 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
||||||
return null; // Undertow does not support JSPs
|
return null; // Undertow does not support JSPs
|
||||||
}
|
}
|
||||||
|
|
||||||
private void awaitFile(File file) throws InterruptedException {
|
private void awaitFile(File file) {
|
||||||
long end = System.currentTimeMillis() + 10000;
|
Awaitility.waitAtMost(Duration.ofSeconds(10)).until(file::exists, is(true));
|
||||||
while (!file.exists() && System.currentTimeMillis() < end) {
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServletContainer getServletContainerFromNewFactory() {
|
private ServletContainer getServletContainerFromNewFactory() {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.bytebuddy</groupId>
|
||||||
|
<artifactId>byte-buddy</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
|
@ -32,8 +36,9 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.bytebuddy</groupId>
|
<groupId>org.awaitility</groupId>
|
||||||
<artifactId>byte-buddy</artifactId>
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.devtools.tests;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.bytebuddy.ByteBuddy;
|
||||||
|
import net.bytebuddy.description.annotation.AnnotationDescription;
|
||||||
|
import net.bytebuddy.description.modifier.Visibility;
|
||||||
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
import net.bytebuddy.implementation.FixedValue;
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.BuildOutput;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for DevTools integration tests.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
abstract class AbstractDevToolsIntegrationTests {
|
||||||
|
|
||||||
|
protected static final BuildOutput buildOutput = new BuildOutput(AbstractDevToolsIntegrationTests.class);
|
||||||
|
|
||||||
|
protected final File serverPortFile = new File(buildOutput.getRootLocation(), "server.port");
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
protected final JvmLauncher javaLauncher = new JvmLauncher();
|
||||||
|
|
||||||
|
@TempDir
|
||||||
|
protected static File temp;
|
||||||
|
|
||||||
|
protected LaunchedApplication launchedApplication;
|
||||||
|
|
||||||
|
protected void launchApplication(ApplicationLauncher applicationLauncher, String... args) throws Exception {
|
||||||
|
this.serverPortFile.delete();
|
||||||
|
this.launchedApplication = applicationLauncher.launchApplication(this.javaLauncher, this.serverPortFile, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void stopApplication() throws InterruptedException {
|
||||||
|
this.launchedApplication.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int awaitServerPort() throws Exception {
|
||||||
|
int port = Awaitility.waitAtMost(Duration.ofSeconds(30))
|
||||||
|
.until(() -> new ApplicationState(this.serverPortFile, this.launchedApplication),
|
||||||
|
ApplicationState::hasServerPort)
|
||||||
|
.getServerPort();
|
||||||
|
this.serverPortFile.delete();
|
||||||
|
System.out.println("Got port " + port);
|
||||||
|
this.launchedApplication.restartRemote(port);
|
||||||
|
Thread.sleep(1000);
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ControllerBuilder controller(String name) {
|
||||||
|
return new ControllerBuilder(name, this.launchedApplication.getClassesDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static final class ControllerBuilder {
|
||||||
|
|
||||||
|
private final List<String> mappings = new ArrayList<>();
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private final File classesDirectory;
|
||||||
|
|
||||||
|
protected ControllerBuilder(String name, File classesDirectory) {
|
||||||
|
this.name = name;
|
||||||
|
this.classesDirectory = classesDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ControllerBuilder withRequestMapping(String mapping) {
|
||||||
|
this.mappings.add(mapping);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build() throws Exception {
|
||||||
|
DynamicType.Builder<Object> builder = new ByteBuddy().subclass(Object.class).name(this.name)
|
||||||
|
.annotateType(AnnotationDescription.Builder.ofType(RestController.class).build());
|
||||||
|
for (String mapping : this.mappings) {
|
||||||
|
builder = builder.defineMethod(mapping, String.class, Visibility.PUBLIC)
|
||||||
|
.intercept(FixedValue.value(mapping)).annotateMethod(AnnotationDescription.Builder
|
||||||
|
.ofType(RequestMapping.class).defineArray("value", mapping).build());
|
||||||
|
}
|
||||||
|
builder.make().saveIn(this.classesDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.devtools.tests;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of an application.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
final class ApplicationState {
|
||||||
|
|
||||||
|
private final Integer serverPort;
|
||||||
|
|
||||||
|
private final FileContents out;
|
||||||
|
|
||||||
|
private final FileContents err;
|
||||||
|
|
||||||
|
ApplicationState(File serverPortFile, LaunchedJvm jvm) {
|
||||||
|
this(serverPortFile, jvm.getStandardOut(), jvm.getStandardError());
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationState(File serverPortFile, LaunchedApplication application) {
|
||||||
|
this(serverPortFile, application.getStandardOut(), application.getStandardError());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApplicationState(File serverPortFile, File out, File err) {
|
||||||
|
this.serverPort = new FileContents(serverPortFile).get(Integer::parseInt);
|
||||||
|
this.out = new FileContents(out);
|
||||||
|
this.err = new FileContents(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasServerPort() {
|
||||||
|
return this.serverPort != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getServerPort() {
|
||||||
|
return this.serverPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Application output:%n%s%n%s", this.out, this.err);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -17,29 +17,13 @@
|
||||||
package org.springframework.boot.devtools.tests;
|
package org.springframework.boot.devtools.tests;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import net.bytebuddy.description.annotation.AnnotationDescription;
|
|
||||||
import net.bytebuddy.description.modifier.Visibility;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType.Builder;
|
|
||||||
import net.bytebuddy.implementation.FixedValue;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
import org.springframework.boot.testsupport.BuildOutput;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
@ -48,29 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
public class DevToolsIntegrationTests {
|
public class DevToolsIntegrationTests extends AbstractDevToolsIntegrationTests {
|
||||||
|
|
||||||
@TempDir
|
|
||||||
static File temp;
|
|
||||||
|
|
||||||
private static final BuildOutput buildOutput = new BuildOutput(DevToolsIntegrationTests.class);
|
|
||||||
|
|
||||||
private LaunchedApplication launchedApplication;
|
|
||||||
|
|
||||||
private final File serverPortFile = new File(buildOutput.getRootLocation(), "server.port");
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
final JvmLauncher javaLauncher = new JvmLauncher();
|
|
||||||
|
|
||||||
private void launchApplication(ApplicationLauncher applicationLauncher) throws Exception {
|
|
||||||
this.serverPortFile.delete();
|
|
||||||
this.launchedApplication = applicationLauncher.launchApplication(this.javaLauncher, this.serverPortFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
void stopApplication() throws InterruptedException {
|
|
||||||
this.launchedApplication.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest(name = "{0}")
|
@ParameterizedTest(name = "{0}")
|
||||||
@MethodSource("parameters")
|
@MethodSource("parameters")
|
||||||
|
|
@ -191,33 +153,6 @@ public class DevToolsIntegrationTests {
|
||||||
.isEqualTo(HttpStatus.NOT_FOUND);
|
.isEqualTo(HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int awaitServerPort() throws Exception {
|
|
||||||
Duration timeToWait = Duration.ofSeconds(40);
|
|
||||||
long end = System.currentTimeMillis() + timeToWait.toMillis();
|
|
||||||
System.out.println("Reading server port from '" + this.serverPortFile + "'");
|
|
||||||
while (this.serverPortFile.length() == 0) {
|
|
||||||
if (System.currentTimeMillis() > end) {
|
|
||||||
throw new IllegalStateException(String.format(
|
|
||||||
"server.port file '" + this.serverPortFile + "' was not written within " + timeToWait.toMillis()
|
|
||||||
+ "ms. Application output:%n%s%s",
|
|
||||||
FileCopyUtils.copyToString(new FileReader(this.launchedApplication.getStandardOut())),
|
|
||||||
FileCopyUtils.copyToString(new FileReader(this.launchedApplication.getStandardError()))));
|
|
||||||
}
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
FileReader portReader = new FileReader(this.serverPortFile);
|
|
||||||
int port = Integer.valueOf(FileCopyUtils.copyToString(portReader));
|
|
||||||
this.serverPortFile.delete();
|
|
||||||
System.out.println("Got port " + port);
|
|
||||||
this.launchedApplication.restartRemote(port);
|
|
||||||
Thread.sleep(1000);
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ControllerBuilder controller(String name) {
|
|
||||||
return new ControllerBuilder(name, this.launchedApplication.getClassesDirectory());
|
|
||||||
}
|
|
||||||
|
|
||||||
static Object[] parameters() throws IOException {
|
static Object[] parameters() throws IOException {
|
||||||
Directories directories = new Directories(buildOutput, temp);
|
Directories directories = new Directories(buildOutput, temp);
|
||||||
return new Object[] { new Object[] { new LocalApplicationLauncher(directories) },
|
return new Object[] { new Object[] { new LocalApplicationLauncher(directories) },
|
||||||
|
|
@ -225,35 +160,4 @@ public class DevToolsIntegrationTests {
|
||||||
new Object[] { new JarFileRemoteApplicationLauncher(directories) } };
|
new Object[] { new JarFileRemoteApplicationLauncher(directories) } };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ControllerBuilder {
|
|
||||||
|
|
||||||
private final List<String> mappings = new ArrayList<>();
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
private final File classesDirectory;
|
|
||||||
|
|
||||||
private ControllerBuilder(String name, File classesDirectory) {
|
|
||||||
this.name = name;
|
|
||||||
this.classesDirectory = classesDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerBuilder withRequestMapping(String mapping) {
|
|
||||||
this.mappings.add(mapping);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void build() throws Exception {
|
|
||||||
Builder<Object> builder = new ByteBuddy().subclass(Object.class).name(this.name)
|
|
||||||
.annotateType(AnnotationDescription.Builder.ofType(RestController.class).build());
|
|
||||||
for (String mapping : this.mappings) {
|
|
||||||
builder = builder.defineMethod(mapping, String.class, Visibility.PUBLIC)
|
|
||||||
.intercept(FixedValue.value(mapping)).annotateMethod(AnnotationDescription.Builder
|
|
||||||
.ofType(RequestMapping.class).defineArray("value", mapping).build());
|
|
||||||
}
|
|
||||||
builder.make().saveIn(this.classesDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,30 +16,13 @@
|
||||||
|
|
||||||
package org.springframework.boot.devtools.tests;
|
package org.springframework.boot.devtools.tests;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import net.bytebuddy.description.annotation.AnnotationDescription;
|
|
||||||
import net.bytebuddy.description.modifier.Visibility;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import net.bytebuddy.implementation.FixedValue;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
import org.springframework.boot.testsupport.BuildOutput;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
@ -48,36 +31,13 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*
|
*
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
*/
|
*/
|
||||||
public class DevToolsWithLazyInitializationIntegrationTests {
|
public class DevToolsWithLazyInitializationIntegrationTests extends AbstractDevToolsIntegrationTests {
|
||||||
|
|
||||||
@TempDir
|
|
||||||
static File temp;
|
|
||||||
|
|
||||||
private static final BuildOutput buildOutput = new BuildOutput(DevToolsIntegrationTests.class);
|
|
||||||
|
|
||||||
private LaunchedApplication launchedApplication;
|
|
||||||
|
|
||||||
private final File serverPortFile = new File(buildOutput.getRootLocation(), "server.port");
|
|
||||||
|
|
||||||
@RegisterExtension
|
|
||||||
final JvmLauncher javaLauncher = new JvmLauncher();
|
|
||||||
|
|
||||||
private void launchApplication(ApplicationLauncher applicationLauncher) throws Exception {
|
|
||||||
this.serverPortFile.delete();
|
|
||||||
this.launchedApplication = applicationLauncher.launchApplication(this.javaLauncher, this.serverPortFile,
|
|
||||||
"--spring.main.lazy-initialization=true");
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
void stopApplication() throws InterruptedException {
|
|
||||||
this.launchedApplication.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest(name = "{0}")
|
@ParameterizedTest(name = "{0}")
|
||||||
@MethodSource("parameters")
|
@MethodSource("parameters")
|
||||||
public void addARequestMappingToAnExistingControllerWhenLazyInit(ApplicationLauncher applicationLauncher)
|
public void addARequestMappingToAnExistingControllerWhenLazyInit(ApplicationLauncher applicationLauncher)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
launchApplication(applicationLauncher);
|
launchApplication(applicationLauncher, "--spring.main.lazy-initialization=true");
|
||||||
TestRestTemplate template = new TestRestTemplate();
|
TestRestTemplate template = new TestRestTemplate();
|
||||||
String urlBase = "http://localhost:" + awaitServerPort();
|
String urlBase = "http://localhost:" + awaitServerPort();
|
||||||
assertThat(template.getForObject(urlBase + "/one", String.class)).isEqualTo("one");
|
assertThat(template.getForObject(urlBase + "/one", String.class)).isEqualTo("one");
|
||||||
|
|
@ -89,33 +49,6 @@ public class DevToolsWithLazyInitializationIntegrationTests {
|
||||||
assertThat(template.getForObject(urlBase + "/two", String.class)).isEqualTo("two");
|
assertThat(template.getForObject(urlBase + "/two", String.class)).isEqualTo("two");
|
||||||
}
|
}
|
||||||
|
|
||||||
private int awaitServerPort() throws Exception {
|
|
||||||
Duration timeToWait = Duration.ofSeconds(40);
|
|
||||||
long end = System.currentTimeMillis() + timeToWait.toMillis();
|
|
||||||
System.out.println("Reading server port from '" + this.serverPortFile + "'");
|
|
||||||
while (this.serverPortFile.length() == 0) {
|
|
||||||
if (System.currentTimeMillis() > end) {
|
|
||||||
throw new IllegalStateException(String.format(
|
|
||||||
"server.port file '" + this.serverPortFile + "' was not written within " + timeToWait.toMillis()
|
|
||||||
+ "ms. Application output:%n%s%s",
|
|
||||||
FileCopyUtils.copyToString(new FileReader(this.launchedApplication.getStandardOut())),
|
|
||||||
FileCopyUtils.copyToString(new FileReader(this.launchedApplication.getStandardError()))));
|
|
||||||
}
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
FileReader portReader = new FileReader(this.serverPortFile);
|
|
||||||
int port = Integer.valueOf(FileCopyUtils.copyToString(portReader));
|
|
||||||
this.serverPortFile.delete();
|
|
||||||
System.out.println("Got port " + port);
|
|
||||||
this.launchedApplication.restartRemote(port);
|
|
||||||
Thread.sleep(1000);
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ControllerBuilder controller(String name) {
|
|
||||||
return new ControllerBuilder(name, this.launchedApplication.getClassesDirectory());
|
|
||||||
}
|
|
||||||
|
|
||||||
static Object[] parameters() throws IOException {
|
static Object[] parameters() throws IOException {
|
||||||
Directories directories = new Directories(buildOutput, temp);
|
Directories directories = new Directories(buildOutput, temp);
|
||||||
return new Object[] { new Object[] { new LocalApplicationLauncher(directories) },
|
return new Object[] { new Object[] { new LocalApplicationLauncher(directories) },
|
||||||
|
|
@ -124,35 +57,4 @@ public class DevToolsWithLazyInitializationIntegrationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class ControllerBuilder {
|
|
||||||
|
|
||||||
private final List<String> mappings = new ArrayList<>();
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
private final File classesDirectory;
|
|
||||||
|
|
||||||
private ControllerBuilder(String name, File classesDirectory) {
|
|
||||||
this.name = name;
|
|
||||||
this.classesDirectory = classesDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerBuilder withRequestMapping(String mapping) {
|
|
||||||
this.mappings.add(mapping);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void build() throws Exception {
|
|
||||||
DynamicType.Builder<Object> builder = new ByteBuddy().subclass(Object.class).name(this.name)
|
|
||||||
.annotateType(AnnotationDescription.Builder.ofType(RestController.class).build());
|
|
||||||
for (String mapping : this.mappings) {
|
|
||||||
builder = builder.defineMethod(mapping, String.class, Visibility.PUBLIC)
|
|
||||||
.intercept(FixedValue.value(mapping)).annotateMethod(AnnotationDescription.Builder
|
|
||||||
.ofType(RequestMapping.class).defineArray("value", mapping).build());
|
|
||||||
}
|
|
||||||
builder.make().saveIn(this.classesDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.devtools.tests;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the contents of a file.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
class FileContents {
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
FileContents(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get() {
|
||||||
|
return get(Function.identity());
|
||||||
|
}
|
||||||
|
|
||||||
|
<T> T get(Function<String, T> transformer) {
|
||||||
|
if ((!this.file.exists()) || this.file.length() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return transformer.apply(FileCopyUtils.copyToString(new FileReader(this.file)));
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -17,17 +17,20 @@
|
||||||
package org.springframework.boot.devtools.tests;
|
package org.springframework.boot.devtools.tests;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
|
|
||||||
import org.springframework.boot.devtools.RemoteSpringApplication;
|
import org.springframework.boot.devtools.RemoteSpringApplication;
|
||||||
import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm;
|
import org.springframework.boot.devtools.tests.JvmLauncher.LaunchedJvm;
|
||||||
import org.springframework.util.FileCopyUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for {@link ApplicationLauncher} implementations that use
|
* Base class for {@link ApplicationLauncher} implementations that use
|
||||||
* {@link RemoteSpringApplication}.
|
* {@link RemoteSpringApplication}.
|
||||||
|
|
@ -45,7 +48,7 @@ abstract class RemoteApplicationLauncher extends AbstractApplicationLauncher {
|
||||||
LaunchedJvm applicationJvm = javaLauncher.launch("app", createApplicationClassPath(),
|
LaunchedJvm applicationJvm = javaLauncher.launch("app", createApplicationClassPath(),
|
||||||
"com.example.DevToolsTestApplication", serverPortFile.getAbsolutePath(), "--server.port=0",
|
"com.example.DevToolsTestApplication", serverPortFile.getAbsolutePath(), "--server.port=0",
|
||||||
"--spring.devtools.remote.secret=secret");
|
"--spring.devtools.remote.secret=secret");
|
||||||
int port = awaitServerPort(applicationJvm.getStandardOut(), serverPortFile);
|
int port = awaitServerPort(applicationJvm, serverPortFile);
|
||||||
BiFunction<Integer, File, Process> remoteRestarter = getRemoteRestarter(javaLauncher);
|
BiFunction<Integer, File, Process> remoteRestarter = getRemoteRestarter(javaLauncher);
|
||||||
return new LaunchedApplication(getDirectories().getRemoteAppDirectory(), applicationJvm.getStandardOut(),
|
return new LaunchedApplication(getDirectories().getRemoteAppDirectory(), applicationJvm.getStandardOut(),
|
||||||
applicationJvm.getStandardError(), applicationJvm.getProcess(), remoteRestarter.apply(port, null),
|
applicationJvm.getStandardError(), applicationJvm.getProcess(), remoteRestarter.apply(port, null),
|
||||||
|
|
@ -60,7 +63,7 @@ abstract class RemoteApplicationLauncher extends AbstractApplicationLauncher {
|
||||||
args.addAll(Arrays.asList(additionalArgs));
|
args.addAll(Arrays.asList(additionalArgs));
|
||||||
LaunchedJvm applicationJvm = javaLauncher.launch("app", createApplicationClassPath(),
|
LaunchedJvm applicationJvm = javaLauncher.launch("app", createApplicationClassPath(),
|
||||||
args.toArray(new String[] {}));
|
args.toArray(new String[] {}));
|
||||||
int port = awaitServerPort(applicationJvm.getStandardOut(), serverPortFile);
|
int port = awaitServerPort(applicationJvm, serverPortFile);
|
||||||
BiFunction<Integer, File, Process> remoteRestarter = getRemoteRestarter(javaLauncher);
|
BiFunction<Integer, File, Process> remoteRestarter = getRemoteRestarter(javaLauncher);
|
||||||
return new LaunchedApplication(getDirectories().getRemoteAppDirectory(), applicationJvm.getStandardOut(),
|
return new LaunchedApplication(getDirectories().getRemoteAppDirectory(), applicationJvm.getStandardOut(),
|
||||||
applicationJvm.getStandardError(), applicationJvm.getProcess(), remoteRestarter.apply(port, null),
|
applicationJvm.getStandardError(), applicationJvm.getProcess(), remoteRestarter.apply(port, null),
|
||||||
|
|
@ -96,35 +99,16 @@ abstract class RemoteApplicationLauncher extends AbstractApplicationLauncher {
|
||||||
return StringUtils.collectionToDelimitedString(entries, File.pathSeparator);
|
return StringUtils.collectionToDelimitedString(entries, File.pathSeparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int awaitServerPort(File standardOut, File serverPortFile) throws Exception {
|
private int awaitServerPort(LaunchedJvm jvm, File serverPortFile) throws Exception {
|
||||||
long end = System.currentTimeMillis() + 30000;
|
return Awaitility.waitAtMost(Duration.ofSeconds(30))
|
||||||
while (serverPortFile.length() == 0) {
|
.until(() -> new ApplicationState(serverPortFile, jvm), ApplicationState::hasServerPort)
|
||||||
if (System.currentTimeMillis() > end) {
|
.getServerPort();
|
||||||
throw new IllegalStateException(
|
|
||||||
String.format("server.port file was not written within 30 seconds. Application output:%n%s",
|
|
||||||
FileCopyUtils.copyToString(new FileReader(standardOut))));
|
|
||||||
}
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
FileReader portReader = new FileReader(serverPortFile);
|
|
||||||
int port = Integer.valueOf(FileCopyUtils.copyToString(portReader));
|
|
||||||
return port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void awaitRemoteSpringApplication(File standardOut) throws Exception {
|
private void awaitRemoteSpringApplication(File standardOut) throws Exception {
|
||||||
long end = System.currentTimeMillis() + 30000;
|
FileContents contents = new FileContents(standardOut);
|
||||||
while (!standardOut.exists()) {
|
Awaitility.waitAtMost(Duration.ofSeconds(30)).until(contents::get,
|
||||||
if (System.currentTimeMillis() > end) {
|
containsString("Started RemoteSpringApplication"));
|
||||||
throw new IllegalStateException("Standard out file was not written within 30 seconds");
|
|
||||||
}
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
while (!FileCopyUtils.copyToString(new FileReader(standardOut)).contains("Started RemoteSpringApplication")) {
|
|
||||||
if (System.currentTimeMillis() > end) {
|
|
||||||
throw new IllegalStateException("RemoteSpringApplication did not start within 30 seconds");
|
|
||||||
}
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,11 @@
|
||||||
<version>3.0.0</version>
|
<version>3.0.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-webapp</artifactId>
|
<artifactId>jetty-webapp</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,11 @@ import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
|
|
@ -93,16 +95,12 @@ abstract class AbstractApplicationLauncher implements BeforeEachCallback, AfterE
|
||||||
}
|
}
|
||||||
|
|
||||||
private int awaitServerPort(Process process, File serverPortFile) throws Exception {
|
private int awaitServerPort(Process process, File serverPortFile) throws Exception {
|
||||||
long end = System.currentTimeMillis() + 30000;
|
Awaitility.waitAtMost(Duration.ofSeconds(30)).until(serverPortFile::length, (length) -> {
|
||||||
while (serverPortFile.length() == 0) {
|
|
||||||
if (System.currentTimeMillis() > end) {
|
|
||||||
throw new IllegalStateException("server.port file was not written within 30 seconds");
|
|
||||||
}
|
|
||||||
if (!process.isAlive()) {
|
if (!process.isAlive()) {
|
||||||
throw new IllegalStateException("Application failed to launch");
|
throw new IllegalStateException("Application failed to start");
|
||||||
}
|
}
|
||||||
Thread.sleep(100);
|
return length > 0;
|
||||||
}
|
});
|
||||||
return Integer.parseInt(FileCopyUtils.copyToString(new FileReader(serverPortFile)));
|
return Integer.parseInt(FileCopyUtils.copyToString(new FileReader(serverPortFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,11 @@
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,9 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.concurrent.Callable;
|
import java.time.Duration;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
@ -39,7 +37,7 @@ import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic integration tests for service demo application.
|
* Basic integration tests for service demo application.
|
||||||
|
|
@ -66,8 +64,7 @@ class SampleIntegrationApplicationTests {
|
||||||
"--service.output-dir=" + outputDir);
|
"--service.output-dir=" + outputDir);
|
||||||
SpringApplication.run(ProducerApplication.class, "World", "--service.input-dir=" + inputDir,
|
SpringApplication.run(ProducerApplication.class, "World", "--service.input-dir=" + inputDir,
|
||||||
"--service.output-dir=" + outputDir);
|
"--service.output-dir=" + outputDir);
|
||||||
String output = getOutput(outputDir);
|
awaitOutputContaining(outputDir, "Hello World");
|
||||||
assertThat(output).contains("Hello World");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -76,41 +73,35 @@ class SampleIntegrationApplicationTests {
|
||||||
File outputDir = new File(temp.toFile(), "output");
|
File outputDir = new File(temp.toFile(), "output");
|
||||||
this.context = SpringApplication.run(SampleIntegrationApplication.class, "testviamg",
|
this.context = SpringApplication.run(SampleIntegrationApplication.class, "testviamg",
|
||||||
"--service.input-dir=" + inputDir, "--service.output-dir=" + outputDir);
|
"--service.input-dir=" + inputDir, "--service.output-dir=" + outputDir);
|
||||||
String output = getOutput(this.context.getBean(ServiceProperties.class).getOutputDir());
|
awaitOutputContaining(this.context.getBean(ServiceProperties.class).getOutputDir(), "testviamg");
|
||||||
assertThat(output).contains("testviamg");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getOutput(File outputDir) throws Exception {
|
private void awaitOutputContaining(File outputDir, String requiredContents) throws Exception {
|
||||||
Future<String> future = Executors.newSingleThreadExecutor().submit(new Callable<String>() {
|
Awaitility.waitAtMost(Duration.ofSeconds(30)).until(() -> outputIn(outputDir),
|
||||||
@Override
|
containsString(requiredContents));
|
||||||
public String call() throws Exception {
|
|
||||||
Resource[] resources = getResourcesWithContent(outputDir);
|
|
||||||
while (resources.length == 0) {
|
|
||||||
Thread.sleep(200);
|
|
||||||
resources = getResourcesWithContent(outputDir);
|
|
||||||
}
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
for (Resource resource : resources) {
|
|
||||||
try (InputStream inputStream = resource.getInputStream()) {
|
|
||||||
builder.append(new String(StreamUtils.copyToByteArray(inputStream)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return future.get(30, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Resource[] getResourcesWithContent(File outputDir) throws IOException {
|
private String outputIn(File outputDir) throws IOException {
|
||||||
Resource[] candidates = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader())
|
Resource[] resources = findResources(outputDir);
|
||||||
.getResources("file:" + outputDir.getAbsolutePath() + "/**");
|
if (resources.length == 0) {
|
||||||
for (Resource candidate : candidates) {
|
return null;
|
||||||
if ((candidate.getFilename() != null && candidate.getFilename().endsWith(".writing"))
|
}
|
||||||
|| candidate.contentLength() == 0) {
|
return readResources(resources);
|
||||||
return new Resource[0];
|
}
|
||||||
|
|
||||||
|
private Resource[] findResources(File outputDir) throws IOException {
|
||||||
|
return ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader())
|
||||||
|
.getResources("file:" + outputDir.getAbsolutePath() + "/*.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readResources(Resource[] resources) throws IOException {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (Resource resource : resources) {
|
||||||
|
try (InputStream input = resource.getInputStream()) {
|
||||||
|
builder.append(new String(StreamUtils.copyToByteArray(input)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return candidates;
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,11 @@
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.kafka</groupId>
|
<groupId>org.springframework.kafka</groupId>
|
||||||
<artifactId>spring-kafka-test</artifactId>
|
<artifactId>spring-kafka-test</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package smoketest.kafka;
|
package smoketest.kafka;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -22,6 +25,8 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.kafka.test.context.EmbeddedKafka;
|
import org.springframework.kafka.test.context.EmbeddedKafka;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests for demo application.
|
* Integration tests for demo application.
|
||||||
|
|
@ -39,10 +44,7 @@ class SampleKafkaApplicationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testVanillaExchange() throws Exception {
|
void testVanillaExchange() throws Exception {
|
||||||
long end = System.currentTimeMillis() + 10000;
|
Awaitility.waitAtMost(Duration.ofSeconds(30)).until(this.consumer::getMessages, not(empty()));
|
||||||
while (this.consumer.getMessages().isEmpty() && System.currentTimeMillis() < end) {
|
|
||||||
Thread.sleep(250);
|
|
||||||
}
|
|
||||||
assertThat(this.consumer.getMessages()).extracting("message").containsOnly("A simple test message");
|
assertThat(this.consumer.getMessages()).extracting("message").containsOnly("A simple test message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,11 @@
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
import smoketest.parent.SampleParentContextApplication;
|
import smoketest.parent.SampleParentContextApplication;
|
||||||
|
|
@ -33,7 +35,7 @@ import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic integration tests for service demo application.
|
* Basic integration tests for service demo application.
|
||||||
|
|
@ -65,26 +67,16 @@ class SampleIntegrationParentApplicationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void awaitOutputContaining(File outputDir, String requiredContents) throws Exception {
|
private void awaitOutputContaining(File outputDir, String requiredContents) throws Exception {
|
||||||
long endTime = System.currentTimeMillis() + 30000;
|
Awaitility.waitAtMost(Duration.ofSeconds(30)).until(() -> outputIn(outputDir),
|
||||||
String output = null;
|
containsString(requiredContents));
|
||||||
while (System.currentTimeMillis() < endTime) {
|
}
|
||||||
Resource[] resources = findResources(outputDir);
|
|
||||||
if (resources.length == 0) {
|
private String outputIn(File outputDir) throws IOException {
|
||||||
Thread.sleep(200);
|
Resource[] resources = findResources(outputDir);
|
||||||
resources = findResources(outputDir);
|
if (resources.length == 0) {
|
||||||
}
|
return null;
|
||||||
else {
|
|
||||||
output = readResources(resources);
|
|
||||||
if (output != null && output.contains(requiredContents)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Thread.sleep(200);
|
|
||||||
output = readResources(resources);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fail("Timed out awaiting output containing '" + requiredContents + "'. Output was '" + output + "'");
|
return readResources(resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Resource[] findResources(File outputDir) throws IOException {
|
private Resource[] findResources(File outputDir) throws IOException {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,11 @@
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.awaitility</groupId>
|
||||||
|
<artifactId>awaitility</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@
|
||||||
|
|
||||||
package smoketest.quartz;
|
package smoketest.quartz;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
|
|
@ -24,7 +27,7 @@ import org.springframework.boot.test.system.CapturedOutput;
|
||||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link SampleQuartzApplication}.
|
* Tests for {@link SampleQuartzApplication}.
|
||||||
|
|
@ -37,11 +40,7 @@ class SampleQuartzApplicationTests {
|
||||||
@Test
|
@Test
|
||||||
void quartzJobIsTriggered(CapturedOutput output) throws InterruptedException {
|
void quartzJobIsTriggered(CapturedOutput output) throws InterruptedException {
|
||||||
try (ConfigurableApplicationContext context = SpringApplication.run(SampleQuartzApplication.class)) {
|
try (ConfigurableApplicationContext context = SpringApplication.run(SampleQuartzApplication.class)) {
|
||||||
long end = System.currentTimeMillis() + 5000;
|
Awaitility.waitAtMost(Duration.ofSeconds(5)).until(output::toString, containsString("Hello World!"));
|
||||||
while ((!output.toString().contains("Hello World!")) && System.currentTimeMillis() < end) {
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
assertThat(output).contains("Hello World!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue