Skip to content
Snippets Groups Projects
XtaClientITCase.java 13.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • package de.ozgcloud.xta.client;
    
    
    import static de.ozgcloud.xta.client.XtaClient.*;
    
    import static de.ozgcloud.xta.client.extension.XtaServerSetupExtensionTestUtil.*;
    
    import static java.util.Collections.*;
    
    import static org.assertj.core.api.Assertions.*;
    
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.function.Consumer;
    import java.util.function.Predicate;
    
    
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Nested;
    import org.junit.jupiter.api.Test;
    
    import org.junit.jupiter.api.extension.RegisterExtension;
    
    import de.ozgcloud.xta.client.exception.XtaClientException;
    
    import de.ozgcloud.xta.client.extension.StaticStringListAppender;
    
    import de.ozgcloud.xta.client.extension.XtaMessageExampleLoader;
    
    import de.ozgcloud.xta.client.extension.XtaTestServerSetupExtension;
    
    import de.ozgcloud.xta.client.model.XtaIdentifier;
    
    import de.ozgcloud.xta.client.model.XtaMessage;
    
    import de.ozgcloud.xta.client.model.XtaMessageMetaData;
    
    import de.ozgcloud.xta.client.model.XtaMessageStatus;
    
    import de.ozgcloud.xta.client.model.XtaTransportReport;
    
    import lombok.SneakyThrows;
    
    class XtaClientITCase {
    
    
    	private static final XtaTestServerSetupExtension XTA_TEST_SERVER_SETUP_EXTENSION = new XtaTestServerSetupExtension();
    
    	static final int TWO_MAX_LIST_ITEMS = 2;
    
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    	private XtaClient silentTestClient;
    
    	private XtaClient testClient;
    
    	private List<XtaMessageMetaData> supportCheckedMetadataItems;
    	private List<XtaMessage> processedMessages;
    	private Consumer<XtaMessage> processMessageDummy;
    	private Predicate<XtaMessageMetaData> isSupportedDummy;
    
    		processMessageDummy = message -> {
    
    		};
    		supportCheckedMetadataItems = new ArrayList<>();
    
    		isSupportedDummy = metaData -> true;
    
    		processedMessages = new ArrayList<>();
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    		silentTestClient = XTA_TEST_SERVER_SETUP_EXTENSION.getSilentTestClient();
    
    		StaticStringListAppender.clearLogLines();
    
    		closeMessagesForAllReaders();
    	}
    
    	private void closeMessagesForAllReaders() {
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    		var silentTestClientConfig = XTA_TEST_SERVER_SETUP_EXTENSION.getSilentTestClientConfig();
    		closeAllMessages(silentTestClientConfig, READER_CLIENT_IDENTIFIER1);
    		closeAllMessages(silentTestClientConfig, READER_CLIENT_IDENTIFIER2);
    		closeAllMessages(silentTestClientConfig, READER_CLIENT_IDENTIFIER3);
    
    	@DisplayName("fetch messages")
    
    	class TestFetchMessages {
    
    
    		private List<XtaMessage> sendMessages;
    
    		private List<String> sendMessageIds;
    
    
    		@BeforeEach
    		void setup() {
    			sendMessages = List.of(
    					createMessage("dfoerdermittel", AUTHOR_CLIENT_IDENTIFIER, READER_CLIENT_IDENTIFIER1),
    					createMessage("dfoerdermittel", AUTHOR_CLIENT_IDENTIFIER, READER_CLIENT_IDENTIFIER2),
    					createMessage("abgabe0401-kleiner-waffenschein", AUTHOR_CLIENT_IDENTIFIER, READER_CLIENT_IDENTIFIER2),
    					createMessage("versammlungsanzeige", AUTHOR_CLIENT_IDENTIFIER2, READER_CLIENT_IDENTIFIER2),
    					createMessage("versammlungsanzeige", AUTHOR_CLIENT_IDENTIFIER2, READER_CLIENT_IDENTIFIER3),
    					createMessage("versammlungsanzeige", AUTHOR_CLIENT_IDENTIFIER3, READER_CLIENT_IDENTIFIER3)
    			);
    
    			sendMessageIds = sendMessages.stream()
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.map(message -> sendTestMessage(silentTestClient, message))
    
    		}
    
    		private XtaMessage createMessage(String messageLabel, XtaIdentifier author, XtaIdentifier reader) {
    			return XtaMessageExampleLoader.load(
    					XtaMessageExampleLoader.MessageExampleConfig.builder()
    							.messageLabel(messageLabel)
    							.reader(reader)
    							.author(author)
    							.build());
    		}
    
    
    		@DisplayName("should throw exception on connection failure")
    		@Test
    		@SneakyThrows
    		void shouldThrowExceptionOnConnectionFailure() {
    			setupClientWithoutTrustStore();
    
    
    			assertThatThrownBy(() -> testClient.fetchMessages(message -> fail("Should not process any message!")))
    
    					.isInstanceOf(XtaClientException.class);
    		}
    
    
    		@DisplayName("should fetch no messages if no client identifier is configured")
    		@Test
    		void shouldFetchNoMessagesIfNoClientIdentifierIsConfigured() {
    			setupClientWithIdentifiers(emptyList());
    
    			var messages = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).isEmpty();
    			assertThat(processedMessages).isEmpty();
    			assertThat(messages).isEmpty();
    		}
    
    		@DisplayName("should fetch no messages if client identifier has no messages pending")
    		@Test
    		void shouldFetchNoMessagesIfClientIdentifierHasNoMessagesPending() {
    			setupClientWithIdentifiers(List.of(AUTHOR_CLIENT_IDENTIFIER));
    
    			var messages = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).isEmpty();
    			assertThat(processedMessages).isEmpty();
    			assertThat(messages).isEmpty();
    		}
    
    		@DisplayName("should fetch messages from first reader")
    		@Test
    		@SneakyThrows
    		void shouldFetchMessagesFromFirstReader() {
    			setupClientWithIdentifiers(List.of(READER_CLIENT_IDENTIFIER1));
    
    			var transportReports = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).hasSize(1);
    			assertThatMessages(processedMessages).containExactlyInAnyOrder(sendMessages.getFirst());
    			assertThatTransportReports(transportReports)
    					.reportExactlyFor(processedMessages)
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.haveExactlyClosedStatusFor(messageIdBySendIndex(0));
    
    		}
    
    		@DisplayName("should fetch messages from second reader")
    		@Test
    		void shouldFetchMessagesFromSecondReader() {
    			setupClientWithIdentifiers(List.of(READER_CLIENT_IDENTIFIER2));
    
    			var transportReports = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).hasSize(3);
    			assertThatMessages(processedMessages).containExactlyInAnyOrder(sendMessages.get(1), sendMessages.get(2), sendMessages.get(3));
    			assertThatTransportReports(transportReports)
    					.reportExactlyFor(processedMessages)
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.haveExactlyClosedStatusFor(messageIdBySendIndex(1), messageIdBySendIndex(2), messageIdBySendIndex(3));
    
    		}
    
    		@DisplayName("should fetch messages from first and second reader")
    		@Test
    		void shouldFetchMessagesFromFirstAndSecondReader() {
    			setupClientWithIdentifiers(List.of(READER_CLIENT_IDENTIFIER1, READER_CLIENT_IDENTIFIER2));
    
    			var transportReports = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).hasSize(1 + 3);
    			assertThatMessages(processedMessages).containExactlyInAnyOrder(
    					sendMessages.get(0),
    					sendMessages.get(1), sendMessages.get(2), sendMessages.get(3)
    			);
    			assertThatTransportReports(transportReports)
    					.reportExactlyFor(processedMessages)
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.haveExactlyClosedStatusFor(
    
    							messageIdBySendIndex(0),
    							messageIdBySendIndex(1), messageIdBySendIndex(2), messageIdBySendIndex(3)
    					);
    		}
    
    		@DisplayName("should fetch messages from first, second and third reader")
    		@Test
    		void shouldFetchMessagesFromFirstSecondAndThirdReader() {
    			setupClientWithIdentifiers(List.of(READER_CLIENT_IDENTIFIER1, READER_CLIENT_IDENTIFIER2, READER_CLIENT_IDENTIFIER3));
    
    			var transportReports = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).hasSize(1 + 3 + 2);
    			assertThatMessages(processedMessages).containExactlyInAnyOrder(
    					sendMessages.get(0),
    					sendMessages.get(1), sendMessages.get(2), sendMessages.get(3),
    					sendMessages.get(4), sendMessages.get(5)
    			);
    			assertThatTransportReports(transportReports)
    					.reportExactlyFor(processedMessages)
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.haveExactlyClosedStatusFor(
    
    							messageIdBySendIndex(0),
    							messageIdBySendIndex(1), messageIdBySendIndex(2), messageIdBySendIndex(3),
    							messageIdBySendIndex(4), messageIdBySendIndex(5)
    					);
    		}
    
    		@DisplayName("should close messages only if no exception occurs during processing, with no exception for author1")
    		@Test
    		void shouldCloseMessagesOnlyIfNoExceptionOccursDuringProcessingWithNoExceptionForAuthor1() {
    			setupClientWithIdentifiers(List.of(READER_CLIENT_IDENTIFIER1, READER_CLIENT_IDENTIFIER2, READER_CLIENT_IDENTIFIER3));
    			processMessageDummy = message -> throwRuntimeExceptionExceptForAuthorIdentifier(message, AUTHOR_CLIENT_IDENTIFIER);
    
    			var transportReports = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).hasSize(1 + 3 + 2);
    
    			assertThat(hasLogLineContaining(NO_MESSAGE_CLOSED_WARNING)).isFalse();
    
    			assertThatMessages(processedMessages).containExactlyInAnyOrder(
    					sendMessages.get(0),
    					sendMessages.get(1), sendMessages.get(2), sendMessages.get(3),
    					sendMessages.get(4), sendMessages.get(5)
    			);
    			assertThatTransportReports(transportReports)
    					.reportExactlyFor(processedMessages)
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.haveExactlyClosedStatusFor(
    
    							messageIdBySendIndex(0),
    							messageIdBySendIndex(1), messageIdBySendIndex(2)
    					);
    		}
    
    
    		@DisplayName("should close messages only if no exception occurs during processing, with no exception for author3")
    		@Test
    		void shouldCloseMessagesOnlyIfNoExceptionOccursDuringProcessingWithNoExceptionForAuthor3() {
    			setupClientWithIdentifiers(List.of(READER_CLIENT_IDENTIFIER1, READER_CLIENT_IDENTIFIER2, READER_CLIENT_IDENTIFIER3));
    			processMessageDummy = message -> throwRuntimeExceptionExceptForAuthorIdentifier(message, AUTHOR_CLIENT_IDENTIFIER3);
    
    			var transportReports = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).hasSize(1 + 2 + 2);
    			assertThat(hasLogLineContaining(NO_MESSAGE_CLOSED_WARNING)).isTrue();
    			assertThatMessages(processedMessages).containMetaDataExactlyInAnyOrder(
    					sendMessages.get(0).metaData(),
    					supportCheckedMetadataItems.get(1), supportCheckedMetadataItems.get(2),
    					sendMessages.get(4).metaData(), sendMessages.get(5).metaData()
    			);
    			assertThatTransportReports(transportReports)
    					.reportExactlyFor(processedMessages)
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.haveExactlyClosedStatusFor(
    
    		private void throwRuntimeExceptionExceptForAuthorIdentifier(XtaMessage message, XtaIdentifier authorIdentifier) {
    			var authorId = message.metaData().authorIdentifier().value();
    			var readerId = message.metaData().readerIdentifier().value();
    			if (!authorId.equals(authorIdentifier.value())) {
    				throw new RuntimeException("Test exception for message with author '%s' and reader '%s'!".formatted(authorId, readerId));
    			}
    		}
    
    		@DisplayName("should process messages only if supported, with support for author1")
    		@Test
    		void shouldProcessMessagesOnlyIfSupportedWithSupportForAuthor1() {
    			setupClientWithIdentifiers(List.of(READER_CLIENT_IDENTIFIER1, READER_CLIENT_IDENTIFIER2, READER_CLIENT_IDENTIFIER3));
    			isSupportedDummy = metaData -> metaData.authorIdentifier().value().equals(AUTHOR_CLIENT_IDENTIFIER.value());
    
    			var transportReports = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).hasSize(1 + 3 + 2);
    
    			assertThat(hasLogLineContaining(NO_MESSAGE_CLOSED_WARNING)).isFalse();
    
    			assertThatMessages(processedMessages).containExactlyInAnyOrder(sendMessages.get(0), sendMessages.get(1), sendMessages.get(2));
    			assertThatTransportReports(transportReports)
    					.reportExactlyFor(processedMessages)
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.haveExactlyClosedStatusFor(messageIdBySendIndex(0), messageIdBySendIndex(1), messageIdBySendIndex(2));
    
    		@DisplayName("should process messages only if supported, with support for author3")
    		@Test
    		void shouldProcessMessagesOnlyIfSupportedWithSupportForAuthor3() {
    			setupClientWithIdentifiers(List.of(READER_CLIENT_IDENTIFIER1, READER_CLIENT_IDENTIFIER2, READER_CLIENT_IDENTIFIER3));
    			isSupportedDummy = metaData -> metaData.authorIdentifier().value().equals(AUTHOR_CLIENT_IDENTIFIER3.value());
    
    			var transportReports = fetchMessages();
    
    			assertThat(supportCheckedMetadataItems).hasSize(1 + 2 + 2);
    			assertThat(hasLogLineContaining(NO_MESSAGE_CLOSED_WARNING)).isTrue();
    			assertThatMessages(processedMessages).containExactlyInAnyOrder(sendMessages.get(5));
    			assertThatTransportReports(transportReports)
    					.reportExactlyFor(processedMessages)
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    					.haveExactlyClosedStatusFor(messageIdBySendIndex(5));
    
    		@SneakyThrows
    		private void setupClientWithIdentifiers(List<XtaIdentifier> identifiers) {
    			testClient = XtaClient.from(
    					XTA_TEST_SERVER_SETUP_EXTENSION.createSpecificClientConfigBuilder()
    							.clientIdentifiers(identifiers)
    							.maxListItems(TWO_MAX_LIST_ITEMS)
    							.isMessageSupported(metaData -> {
    								supportCheckedMetadataItems.add(metaData);
    								return isSupportedDummy.test(metaData);
    							})
    							.build()
    			);
    		}
    
    		private String messageIdBySendIndex(int sendIndex) {
    
    			return sendMessageIds.get(sendIndex);
    
    		private List<XtaTransportReport> fetchMessages() {
    
    			return testClient.fetchMessages(message -> {
    
    				processedMessages.add(message);
    				processMessageDummy.accept(message);
    			});
    		}
    
    	@DisplayName("send message")
    	@Nested
    	class TestSendMessage {
    
    		private XtaMessage message;
    
    		@BeforeEach
    		void beforeEach() {
    			var messageConfig = XtaMessageExampleLoader.MessageExampleConfig.builder()
    					.messageLabel("dfoerdermittel")
    
    					.reader(READER_CLIENT_IDENTIFIER1)
    
    					.author(AUTHOR_CLIENT_IDENTIFIER)
    
    					.build();
    			message = XtaMessageExampleLoader.load(messageConfig);
    		}
    
    
    		@DisplayName("should throw exception on connection failure")
    		@Test
    		@SneakyThrows
    		void shouldThrowExceptionOnConnectionFailure() {
    			setupClientWithoutTrustStore();
    
    			assertThatThrownBy(() -> testClient.sendMessage(message))
    					.isInstanceOf(XtaClientException.class);
    		}
    
    
    		@DisplayName("should return transport report with open status")
    		@Test
    		@SneakyThrows
    		void shouldReturnTransportReportWithOpenStatus() {
    
    Jan Zickermann's avatar
    Jan Zickermann committed
    			var transportReport = silentTestClient.sendMessage(message);
    
    
    			assertThat(transportReport.status()).isEqualTo(XtaMessageStatus.OPEN);
    		}
    	}
    
    
    	@SneakyThrows
    	private void setupClientWithoutTrustStore() {
    		testClient = XtaClient.from(
    				XTA_TEST_SERVER_SETUP_EXTENSION.createSpecificClientConfigBuilder()
    						.trustStore(null)
    						.clientIdentifiers(List.of(READER_CLIENT_IDENTIFIER1))
    						.maxListItems(TWO_MAX_LIST_ITEMS)
    						.isMessageSupported(metaData -> fail("Should not process any message!"))
    						.build()
    		);
    	}