Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
52d32336e0
|
@ -0,0 +1,21 @@
|
|||
package com.baeldung.concurrent.skiplist;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
public class Event {
|
||||
private final ZonedDateTime eventTime;
|
||||
private final String content;
|
||||
|
||||
public Event(ZonedDateTime eventTime, String content) {
|
||||
this.eventTime = eventTime;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public ZonedDateTime getEventTime() {
|
||||
return eventTime;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.concurrent.skiplist;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.ConcurrentNavigableMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.function.ToLongFunction;
|
||||
|
||||
public class EventWindowSort {
|
||||
private final ConcurrentSkipListMap<ZonedDateTime, String> events = new ConcurrentSkipListMap<>(Comparator.comparingLong(new ToLongFunction<ZonedDateTime>() {
|
||||
@Override
|
||||
public long applyAsLong(ZonedDateTime value) {
|
||||
return value
|
||||
.toInstant()
|
||||
.toEpochMilli();
|
||||
}
|
||||
}));
|
||||
|
||||
public void acceptEvent(Event event) {
|
||||
events.put(event.getEventTime(), event.getContent());
|
||||
}
|
||||
|
||||
public ConcurrentNavigableMap<ZonedDateTime, String> getEventsFromLastMinute() {
|
||||
return events.tailMap(ZonedDateTime
|
||||
.now()
|
||||
.minusMinutes(1));
|
||||
}
|
||||
|
||||
public ConcurrentNavigableMap<ZonedDateTime, String> getEventsOlderThatOneMinute() {
|
||||
return events.headMap(ZonedDateTime
|
||||
.now()
|
||||
.minusMinutes(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package com.baeldung.concurrent.skiplist;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentNavigableMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ConcurrentSkipListSetTest {
|
||||
|
||||
@Test
|
||||
public void givenThreadsProducingEvents_whenGetForEventsFromLastMinute_thenReturnThoseEventsInTheLockFreeWay() throws InterruptedException {
|
||||
//given
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(3);
|
||||
EventWindowSort eventWindowSort = new EventWindowSort();
|
||||
int numberOfThreads = 2;
|
||||
//when
|
||||
Runnable producer = () -> IntStream
|
||||
.rangeClosed(0, 100)
|
||||
.forEach(index -> eventWindowSort.acceptEvent(new Event(ZonedDateTime
|
||||
.now()
|
||||
.minusSeconds(index), UUID
|
||||
.randomUUID()
|
||||
.toString())));
|
||||
|
||||
for (int i = 0; i < numberOfThreads; i++) {
|
||||
executorService.execute(producer);
|
||||
}
|
||||
|
||||
Thread.sleep(500);
|
||||
|
||||
ConcurrentNavigableMap<ZonedDateTime, String> eventsFromLastMinute = eventWindowSort.getEventsFromLastMinute();
|
||||
|
||||
long eventsOlderThanOneMinute = eventsFromLastMinute
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e
|
||||
.getKey()
|
||||
.isBefore(ZonedDateTime
|
||||
.now()
|
||||
.minusMinutes(1)))
|
||||
.count();
|
||||
assertEquals(eventsOlderThanOneMinute, 0);
|
||||
|
||||
long eventYoungerThanOneMinute = eventsFromLastMinute
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e
|
||||
.getKey()
|
||||
.isAfter(ZonedDateTime
|
||||
.now()
|
||||
.minusMinutes(1)))
|
||||
.count();
|
||||
|
||||
//then
|
||||
assertTrue(eventYoungerThanOneMinute > 0);
|
||||
|
||||
executorService.awaitTermination(1, TimeUnit.SECONDS);
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenThreadsProducingEvents_whenGetForEventsOlderThanOneMinute_thenReturnThoseEventsInTheLockFreeWay() throws InterruptedException {
|
||||
//given
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(3);
|
||||
EventWindowSort eventWindowSort = new EventWindowSort();
|
||||
int numberOfThreads = 2;
|
||||
//when
|
||||
Runnable producer = () -> IntStream
|
||||
.rangeClosed(0, 100)
|
||||
.forEach(index -> eventWindowSort.acceptEvent(new Event(ZonedDateTime
|
||||
.now()
|
||||
.minusSeconds(index), UUID
|
||||
.randomUUID()
|
||||
.toString())));
|
||||
|
||||
for (int i = 0; i < numberOfThreads; i++) {
|
||||
executorService.execute(producer);
|
||||
}
|
||||
|
||||
Thread.sleep(500);
|
||||
|
||||
ConcurrentNavigableMap<ZonedDateTime, String> eventsFromLastMinute = eventWindowSort.getEventsOlderThatOneMinute();
|
||||
|
||||
long eventsOlderThanOneMinute = eventsFromLastMinute
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e
|
||||
.getKey()
|
||||
.isBefore(ZonedDateTime
|
||||
.now()
|
||||
.minusMinutes(1)))
|
||||
.count();
|
||||
assertTrue(eventsOlderThanOneMinute > 0);
|
||||
|
||||
long eventYoungerThanOneMinute = eventsFromLastMinute
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e
|
||||
.getKey()
|
||||
.isAfter(ZonedDateTime
|
||||
.now()
|
||||
.minusMinutes(1)))
|
||||
.count();
|
||||
|
||||
//then
|
||||
assertEquals(eventYoungerThanOneMinute, 0);
|
||||
|
||||
executorService.awaitTermination(1, TimeUnit.SECONDS);
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@ -58,21 +58,22 @@
|
|||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.test.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.jupiter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
|
@ -91,6 +92,7 @@
|
|||
<version>${junit.platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -107,6 +109,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<forkCount>3</forkCount>
|
||||
<reuseForks>true</reuseForks>
|
||||
|
@ -171,10 +174,9 @@
|
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<junit.platform.version>1.0.0-M3</junit.platform.version>
|
||||
<junit.jupiter.version>5.0.0-M3</junit.jupiter.version>
|
||||
<spring.test.version>4.3.7.RELEASE</spring.test.version>
|
||||
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
|
||||
<junit.platform.version>1.0.0-M4</junit.platform.version>
|
||||
<junit.jupiter.version>5.0.0-M4</junit.jupiter.version>
|
||||
<maven-surefire-plugin.version>2.20</maven-surefire-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -56,49 +56,49 @@ public class Spring5ReactiveServerClientTest {
|
|||
nettyContext.dispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCheckTask_whenServerHandle_thenServerResponseALiveString() throws Exception {
|
||||
WebClient client = WebClient.create("http://localhost:8080");
|
||||
Mono<String> result = client
|
||||
.get()
|
||||
.uri("/task")
|
||||
.exchange()
|
||||
.then(response -> response.bodyToMono(String.class));
|
||||
// @Test
|
||||
// public void givenCheckTask_whenServerHandle_thenServerResponseALiveString() throws Exception {
|
||||
// WebClient client = WebClient.create("http://localhost:8080");
|
||||
// Mono<String> result = client
|
||||
// .get()
|
||||
// .uri("/task")
|
||||
// .exchange()
|
||||
// .then(response -> response.bodyToMono(String.class));
|
||||
//
|
||||
// assertThat(result.block()).isInstanceOf(String.class);
|
||||
// }
|
||||
|
||||
assertThat(result.block()).isInstanceOf(String.class);
|
||||
}
|
||||
// @Test
|
||||
// public void givenThreeTasks_whenServerHandleTheTasks_thenServerResponseATask() throws Exception {
|
||||
// URI uri = URI.create("http://localhost:8080/task/process");
|
||||
// ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
|
||||
// ClientRequest request = ClientRequest
|
||||
// .method(HttpMethod.POST, uri)
|
||||
// .body(BodyInserters.fromPublisher(getLatLngs(), Task.class))
|
||||
// .build();
|
||||
//
|
||||
// Flux<Task> taskResponse = exchange
|
||||
// .exchange(request)
|
||||
// .flatMap(response -> response.bodyToFlux(Task.class));
|
||||
//
|
||||
// assertThat(taskResponse.blockFirst()).isInstanceOf(Task.class);
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void givenThreeTasks_whenServerHandleTheTasks_thenServerResponseATask() throws Exception {
|
||||
URI uri = URI.create("http://localhost:8080/task/process");
|
||||
ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
|
||||
ClientRequest request = ClientRequest
|
||||
.method(HttpMethod.POST, uri)
|
||||
.body(BodyInserters.fromPublisher(getLatLngs(), Task.class))
|
||||
.build();
|
||||
|
||||
Flux<Task> taskResponse = exchange
|
||||
.exchange(request)
|
||||
.flatMap(response -> response.bodyToFlux(Task.class));
|
||||
|
||||
assertThat(taskResponse.blockFirst()).isInstanceOf(Task.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCheckTask_whenServerHandle_thenOragicServerResponseALiveString() throws Exception {
|
||||
URI uri = URI.create("http://localhost:8080/task");
|
||||
ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
|
||||
ClientRequest request = ClientRequest
|
||||
.method(HttpMethod.GET, uri)
|
||||
.body(BodyInserters.fromPublisher(getLatLngs(), Task.class))
|
||||
.build();
|
||||
|
||||
Flux<String> taskResponse = exchange
|
||||
.exchange(request)
|
||||
.flatMap(response -> response.bodyToFlux(String.class));
|
||||
|
||||
assertThat(taskResponse.blockFirst()).isInstanceOf(String.class);
|
||||
}
|
||||
// @Test
|
||||
// public void givenCheckTask_whenServerHandle_thenOragicServerResponseALiveString() throws Exception {
|
||||
// URI uri = URI.create("http://localhost:8080/task");
|
||||
// ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
|
||||
// ClientRequest request = ClientRequest
|
||||
// .method(HttpMethod.GET, uri)
|
||||
// .body(BodyInserters.fromPublisher(getLatLngs(), Task.class))
|
||||
// .build();
|
||||
//
|
||||
// Flux<String> taskResponse = exchange
|
||||
// .exchange(request)
|
||||
// .flatMap(response -> response.bodyToFlux(String.class));
|
||||
//
|
||||
// assertThat(taskResponse.blockFirst()).isInstanceOf(String.class);
|
||||
// }
|
||||
|
||||
private static Flux<Task> getLatLngs() {
|
||||
return Flux
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.4.3.RELEASE</version>
|
||||
<version>1.4.6.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
|
|
@ -163,6 +163,30 @@ public class RestTemplateBasicLiveTest {
|
|||
assertThat(foo.getName(), is(updatedInstance.getName()));
|
||||
}
|
||||
|
||||
// PATCH
|
||||
|
||||
@Test
|
||||
public void givenFooService_whenPatchExistingEntity_thenItIsUpdated() {
|
||||
final RestTemplate template = new RestTemplate();
|
||||
final HttpHeaders headers = prepareBasicAuthHeaders();
|
||||
final HttpEntity<Foo> request = new HttpEntity<>(new Foo("bar"), headers);
|
||||
|
||||
// Create Resource
|
||||
final ResponseEntity<Foo> createResponse = template.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class);
|
||||
|
||||
// Update Resource
|
||||
final Foo updatedResource = new Foo("newName");
|
||||
updatedResource.setId(createResponse.getBody().getId());
|
||||
final String resourceUrl = fooResourceUrl + '/' + createResponse.getBody().getId();
|
||||
final HttpEntity<Foo> requestUpdate = new HttpEntity<>(updatedResource, headers);
|
||||
template.patchForObject(resourceUrl, requestUpdate, Void.class);
|
||||
|
||||
// Check that Resource was updated
|
||||
final ResponseEntity<Foo> updateResponse = template.exchange(resourceUrl, HttpMethod.GET, new HttpEntity<>(headers), Foo.class);
|
||||
final Foo foo = updateResponse.getBody();
|
||||
assertThat(foo.getName(), is(updatedResource.getName()));
|
||||
}
|
||||
|
||||
// DELETE
|
||||
|
||||
@Test
|
||||
|
|
|
@ -7,7 +7,7 @@ import org.testng.ITestListener;
|
|||
import org.testng.ITestResult;
|
||||
|
||||
public class CustomisedListener implements ITestListener {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("TEST_REPORT");
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("CUSTOM_LOGS");
|
||||
|
||||
@Override
|
||||
public void onFinish(ITestContext context) {
|
||||
|
@ -25,7 +25,8 @@ public class CustomisedListener implements ITestListener {
|
|||
.forEach(result -> {
|
||||
LOGGER.info(result.getName());
|
||||
});
|
||||
LOGGER.info("Test completed on: " + context.getEndDate().toString());
|
||||
LOGGER.info("Test completed on: " + context.getEndDate()
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -54,13 +55,14 @@ public class CustomisedListener implements ITestListener {
|
|||
|
||||
@Override
|
||||
public void onTestStart(ITestResult arg0) {
|
||||
LOGGER.info("Testing: " + arg0.getName() + " " + arg0.getStartMillis());
|
||||
LOGGER.info("Testing: " + arg0.getName());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTestSuccess(ITestResult arg0) {
|
||||
LOGGER.info("Tested: " + arg0.getName() + " " + arg0.getEndMillis());
|
||||
long timeTaken = ((arg0.getEndMillis() - arg0.getStartMillis()));
|
||||
LOGGER.info("Tested: " + arg0.getName() + " Time taken:" + timeTaken + " ms");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,50 +1,73 @@
|
|||
package com.baeldung.reports;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testng.IReporter;
|
||||
import org.testng.IResultMap;
|
||||
import org.testng.ISuite;
|
||||
import org.testng.ISuiteResult;
|
||||
import org.testng.ITestContext;
|
||||
import org.testng.ITestResult;
|
||||
import org.testng.xml.XmlSuite;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CustomisedReports implements IReporter {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("TEST_REPORT");
|
||||
private PrintWriter reportWriter;
|
||||
|
||||
@Override
|
||||
public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
|
||||
|
||||
suites.stream()
|
||||
.forEach(suite -> {
|
||||
String suiteName = suite.getName();
|
||||
new File(outputDirectory).mkdirs();
|
||||
try {
|
||||
reportWriter = new PrintWriter(new BufferedWriter(new FileWriter(new File(outputDirectory, "my-report.html"))));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String resultRow = "<tr class=\"%s\"><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>";
|
||||
initReportTemplate();
|
||||
for (ISuite suite : suites) {
|
||||
Map<String, ISuiteResult> suiteResults = suite.getResults();
|
||||
suiteResults.values()
|
||||
.stream()
|
||||
.forEach(result -> {
|
||||
ITestContext context
|
||||
= ((ISuiteResult) result).getTestContext();
|
||||
|
||||
LOGGER.info("Passed tests for suite '"
|
||||
+ suiteName + "' is:"
|
||||
+ context.getPassedTests()
|
||||
.getAllResults()
|
||||
.size());
|
||||
LOGGER.info("Failed tests for suite '"
|
||||
+ suiteName + "' is:"
|
||||
+ context.getFailedTests()
|
||||
.getAllResults()
|
||||
.size());
|
||||
LOGGER.info("Skipped tests for suite '"
|
||||
+ suiteName + "' is:"
|
||||
+ context.getSkippedTests()
|
||||
.getAllResults()
|
||||
.size());
|
||||
});
|
||||
});
|
||||
for (String testName : suiteResults.keySet()) {
|
||||
ISuiteResult suiteResult = suiteResults.get(testName);
|
||||
ITestContext testContext = suiteResult.getTestContext();
|
||||
|
||||
IResultMap failedResult = testContext.getFailedTests();
|
||||
Set<ITestResult> testsFailed = failedResult.getAllResults();
|
||||
for (ITestResult testResult : testsFailed) {
|
||||
reportWriter.println(String.format(resultRow, "danger", suite.getName(), testName, testResult.getName(), "FAILED", "NA"));
|
||||
}
|
||||
|
||||
IResultMap passResult = testContext.getPassedTests();
|
||||
Set<ITestResult> testsPassed = passResult.getAllResults();
|
||||
for (ITestResult testResult : testsPassed) {
|
||||
reportWriter.println(String.format(resultRow, "success", suite.getName(), testName, testResult.getName(), "PASSED", String.valueOf(testResult.getEndMillis() - testResult.getStartMillis())));
|
||||
}
|
||||
|
||||
IResultMap skippedResult = testContext.getSkippedTests();
|
||||
Set<ITestResult> testsSkipped = skippedResult.getAllResults();
|
||||
for (ITestResult testResult : testsSkipped) {
|
||||
reportWriter.println(String.format(resultRow, "warning", suite.getName(), testName, testResult.getName(), "SKIPPED", "NA"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
finishReportTemplate();
|
||||
reportWriter.flush();
|
||||
reportWriter.close();
|
||||
}
|
||||
|
||||
private void initReportTemplate() {
|
||||
reportWriter.println(
|
||||
"<html>" + "<head>" + "<title>My Custom Report</title>" + "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" + "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\">"
|
||||
+ "<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js\"></script>" + "<script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js\"></script></head>" + "<body><div class=\"container\">");
|
||||
reportWriter.println("<table class=\"table\"><thead><tr>" + "<th>Suite</th>" + "<th>Test</th>" + "<th>Method</th>" + "<th>Status</th>" + "<th>Execution Time(ms)</th>" + "</tr></thead> <tbody>");
|
||||
}
|
||||
|
||||
private void finishReportTemplate() {
|
||||
reportWriter.println(" </tbody></div></body></html>");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue