Skip to content

Commit

Permalink
Cleanup state after future has completed - tests
Browse files Browse the repository at this point in the history
- Fix and improve tests

(cherry picked from commit 6179a4e2530e432c867a28a32d58bcfe5d639a91)
  • Loading branch information
martinfkaeser committed Mar 28, 2024
1 parent 03b8a2a commit 92aabc5
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 11 deletions.
85 changes: 79 additions & 6 deletions ocpp-common/src/test/java/eu/chargetime/ocpp/test/ClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,30 @@ of this software and associated documentation files (the "Software"), to deal
SOFTWARE.
*/

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;

import eu.chargetime.ocpp.*;
import eu.chargetime.ocpp.feature.Feature;
import eu.chargetime.ocpp.model.Confirmation;
import eu.chargetime.ocpp.model.Request;
import eu.chargetime.ocpp.model.TestConfirmation;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class ClientTest {
private Client client;
Expand All @@ -63,8 +70,10 @@ public void setup() {
.when(session)
.open(any(), any());

when(promiseRepository.createPromise(any())).then(invocation -> new CompletableFuture<Confirmation>());
when(featureRepository.findFeature(any())).thenReturn(Optional.of(feature));
when(session.getFeatureRepository()).thenReturn(featureRepository);
when(session.storeRequest(any())).then(invocation -> UUID.randomUUID().toString());
client = new Client(session, promiseRepository);
}

Expand Down Expand Up @@ -164,4 +173,68 @@ public void send_aMessage_validatesMessage() throws Exception {
// Then
verify(request, times(1)).validate();
}

@Test
public void send_aMessage_promiseCompletes() throws Exception {
// Given
CompletableFuture<Confirmation> internalFuture = new CompletableFuture<>();
when(promiseRepository.createPromise(any())).thenReturn(internalFuture);

// When
CompletableFuture<Confirmation> returnedFuture = client.send(request);
TestConfirmation confirmation = new TestConfirmation();
internalFuture.complete(confirmation);

// Then
assertThat(returnedFuture, is(internalFuture));
assertThat(returnedFuture.isDone(), is(true));
assertThat(returnedFuture.get(), is(confirmation));
verify(session, times(1)).removeRequest(any());
verify(promiseRepository, times(1)).removePromise(any());
}

@Test
public void send_aMessage_promiseCompletesExceptionally() throws Exception {
// Given
CompletableFuture<Confirmation> internalFuture = new CompletableFuture<>();
when(promiseRepository.createPromise(any())).thenReturn(internalFuture);

// When
CompletableFuture<Confirmation> returnedFuture = client.send(request);
internalFuture.completeExceptionally(new IllegalStateException());

// Then
assertThat(returnedFuture, is(internalFuture));
assertThat(returnedFuture.isDone(), is(true));
assertThat(returnedFuture.isCompletedExceptionally(), is(true));
ExecutionException executionException = assertThrows(ExecutionException.class, returnedFuture::get);
assertThat(executionException.getCause().getClass(), is(equalTo(IllegalStateException.class)));
verify(session, times(1)).removeRequest(any());
verify(promiseRepository, times(1)).removePromise(any());
}

@Test
public void send_aMessage_promiseCompletesWithTimeout() throws Exception {
// Given
CompletableFuture<Confirmation> internalFuture = new CompletableFuture<>();
when(promiseRepository.createPromise(any())).thenReturn(internalFuture);

// When
CompletableFuture<Confirmation> returnedFuture = client.send(request);
// If the client uses at least Java 9, it could use CompletableFuture::orTimeout(..) ..
returnedFuture.orTimeout(50, TimeUnit.MILLISECONDS);
assertThat(returnedFuture.isDone(), is(false));
Thread.sleep(100);
// .. alternatively, it can be implemented manually
// returnedFuture.completeExceptionally(new TimeoutException());

// Then
assertThat(returnedFuture, is(internalFuture));
assertThat(returnedFuture.isDone(), is(true));
assertThat(returnedFuture.isCompletedExceptionally(), is(true));
ExecutionException executionException = assertThrows(ExecutionException.class, returnedFuture::get);
assertThat(executionException.getCause().getClass(), is(equalTo(TimeoutException.class)));
verify(session, times(1)).removeRequest(any());
verify(promiseRepository, times(1)).removePromise(any());
}
}
93 changes: 88 additions & 5 deletions ocpp-common/src/test/java/eu/chargetime/ocpp/test/ServerTest.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
package eu.chargetime.ocpp.test;

import static org.mockito.Mockito.*;

import eu.chargetime.ocpp.*;
import eu.chargetime.ocpp.feature.Feature;
import eu.chargetime.ocpp.model.Confirmation;
import eu.chargetime.ocpp.model.Request;
import eu.chargetime.ocpp.model.SessionInformation;
import java.util.Optional;
import java.util.UUID;
import eu.chargetime.ocpp.model.TestConfirmation;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.*;

/*
ChargeTime.eu - Java-OCA-OCPP
Expand Down Expand Up @@ -58,7 +69,7 @@ public class ServerTest {
@Mock private Request request;
@Mock private SessionInformation information;
@Mock private IFeatureRepository featureRepository;
@Mock private IPromiseRepository promiseRepository;
@Mock IPromiseRepository promiseRepository;

@Before
public void setup() {
Expand All @@ -75,8 +86,10 @@ public void setup() {
.when(serverEvents)
.newSession(any(), any());

when(promiseRepository.createPromise(any())).then(invocation -> new CompletableFuture<Confirmation>());
when(featureRepository.findFeature(any())).thenReturn(Optional.of(feature));
when(session.getFeatureRepository()).thenReturn(featureRepository);
when(session.storeRequest(any())).thenAnswer(invocation -> UUID.randomUUID().toString());
server = new Server(listener, promiseRepository);
}

Expand Down Expand Up @@ -143,4 +156,74 @@ public void send_aMessage_validatesMessage() throws Exception {
// Then
verify(request, times(1)).validate();
}

@Test
public void send_aMessage_promiseCompletes() throws Exception {
// Given
server.open(LOCALHOST, PORT, serverEvents);
listenerEvents.newSession(session, information);
CompletableFuture<Confirmation> internalFuture = new CompletableFuture<>();
when(promiseRepository.createPromise(any())).thenReturn(internalFuture);

// When
CompletableFuture<Confirmation> returnedFuture = server.send(sessionIndex, request);
TestConfirmation confirmation = new TestConfirmation();
internalFuture.complete(confirmation);

// Then
assertThat(returnedFuture, is(internalFuture));
assertThat(returnedFuture.isDone(), is(true));
assertThat(returnedFuture.get(), is(confirmation));
verify(session, times(1)).removeRequest(any());
verify(promiseRepository, times(1)).removePromise(any());
}

@Test
public void send_aMessage_promiseCompletesExceptionally() throws Exception {
// Given
server.open(LOCALHOST, PORT, serverEvents);
listenerEvents.newSession(session, information);
CompletableFuture<Confirmation> internalFuture = new CompletableFuture<>();
when(promiseRepository.createPromise(any())).thenReturn(internalFuture);

// When
CompletableFuture<Confirmation> returnedFuture = server.send(sessionIndex, request);
internalFuture.completeExceptionally(new IllegalStateException());

// Then
assertThat(returnedFuture, is(internalFuture));
assertThat(returnedFuture.isDone(), is(true));
assertThat(returnedFuture.isCompletedExceptionally(), is(true));
ExecutionException executionException = assertThrows(ExecutionException.class, returnedFuture::get);
assertThat(executionException.getCause().getClass(), is(equalTo(IllegalStateException.class)));
verify(session, times(1)).removeRequest(any());
verify(promiseRepository, times(1)).removePromise(any());
}

@Test
public void send_aMessage_promiseCompletesWithTimeout() throws Exception {
// Given
server.open(LOCALHOST, PORT, serverEvents);
listenerEvents.newSession(session, information);
CompletableFuture<Confirmation> internalFuture = new CompletableFuture<>();
when(promiseRepository.createPromise(any())).thenReturn(internalFuture);

// When
CompletableFuture<Confirmation> returnedFuture = server.send(sessionIndex, request);
// If the client uses at least Java 9, it could use CompletableFuture::orTimeout(..).
returnedFuture.orTimeout(50, TimeUnit.MILLISECONDS);
assertThat(returnedFuture.isDone(), is(false));
Thread.sleep(100);
// .. alternatively, it can be implemented manually
// returnedFuture.completeExceptionally(new TimeoutException());

// Then
assertThat(returnedFuture, is(internalFuture));
assertThat(returnedFuture.isDone(), is(true));
assertThat(returnedFuture.isCompletedExceptionally(), is(true));
ExecutionException executionException = assertThrows(ExecutionException.class, returnedFuture::get);
assertThat(executionException.getCause().getClass(), is(equalTo(TimeoutException.class)));
verify(session, times(1)).removeRequest(any());
verify(promiseRepository, times(1)).removePromise(any());
}
}

0 comments on commit 92aabc5

Please sign in to comment.