X-Git-Url: https://juplo.de/gitweb/?a=blobdiff_plain;f=src%2Ftest%2Fjava%2Fde%2Fjuplo%2Fkafka%2Fchat%2Fbackend%2Fapi%2FChatBackendControllerTest.java;h=32b1e3578a02206b670e8d049231fee0aa92bad3;hb=e9a4bf3c31d504611fba0cc0be4a1e04812e2c65;hp=b72294d95611292d55b42db52422b3c142f48b80;hpb=7281b4220170f451062bb32e0d5f63ec48d141d3;p=demos%2Fkafka%2Fchat diff --git a/src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java b/src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java index b72294d9..32b1e357 100644 --- a/src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java +++ b/src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java @@ -1,7 +1,9 @@ package de.juplo.kafka.chat.backend.api; +import de.juplo.kafka.chat.backend.ChatBackendProperties; import de.juplo.kafka.chat.backend.domain.*; import de.juplo.kafka.chat.backend.persistence.inmemory.InMemoryChatHomeService; +import de.juplo.kafka.chat.backend.persistence.inmemory.ShardingStrategy; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,7 +17,10 @@ import reactor.core.publisher.Mono; import java.time.Clock; import java.time.LocalDateTime; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @@ -23,11 +28,19 @@ import static org.mockito.Mockito.*; @SpringBootTest(properties = { "spring.main.allow-bean-definition-overriding=true", - "chat.backend.inmemory.sharding-strategy=none" }) + "chat.backend.inmemory.sharding-strategy=kafkalike", + "chat.backend.inmemory.num-shards=10", + "chat.backend.inmemory.owned-shards=6", + }) @AutoConfigureWebTestClient @Slf4j public class ChatBackendControllerTest { + @Autowired + ChatBackendProperties properties; + @Autowired + ShardingStrategy shardingStrategy; + @MockBean InMemoryChatHomeService chatHomeService; @MockBean @@ -38,8 +51,9 @@ public class ChatBackendControllerTest void testUnknownChatroomExceptionForListChatroom(@Autowired WebTestClient client) { // Given - UUID chatroomId = UUID.randomUUID(); + UUID chatroomId = getRandomIdForOwnedShard(); when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty()); + when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 }); // When WebTestClient.ResponseSpec responseSpec = client @@ -58,8 +72,9 @@ public class ChatBackendControllerTest void testUnknownChatroomExceptionForGetChatroom(@Autowired WebTestClient client) { // Given - UUID chatroomId = UUID.randomUUID(); + UUID chatroomId = getRandomIdForOwnedShard(); when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty()); + when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 }); // When WebTestClient.ResponseSpec responseSpec = client @@ -77,10 +92,11 @@ public class ChatBackendControllerTest void testUnknownChatroomExceptionForPutMessage(@Autowired WebTestClient client) { // Given - UUID chatroomId = UUID.randomUUID(); + UUID chatroomId = getRandomIdForOwnedShard(); String username = "foo"; Long messageId = 66l; when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty()); + when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 }); // When WebTestClient.ResponseSpec responseSpec = client @@ -103,10 +119,11 @@ public class ChatBackendControllerTest void testUnknownChatroomExceptionForGetMessage(@Autowired WebTestClient client) { // Given - UUID chatroomId = UUID.randomUUID(); + UUID chatroomId = getRandomIdForOwnedShard(); String username = "foo"; Long messageId = 66l; when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty()); + when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 }); // When WebTestClient.ResponseSpec responseSpec = client @@ -128,8 +145,9 @@ public class ChatBackendControllerTest void testUnknownChatroomExceptionForListenChatroom(@Autowired WebTestClient client) { // Given - UUID chatroomId = UUID.randomUUID(); + UUID chatroomId = getRandomIdForOwnedShard(); when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty()); + when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 }); // When WebTestClient.ResponseSpec responseSpec = client @@ -155,10 +173,10 @@ public class ChatBackendControllerTest @Test @DisplayName("Assert expected problem-details for message mutation on PUT /put/{chatroomId}/{username}/{messageId}") - void testMessageMutationException(@Autowired WebTestClient client) throws Exception + void testMessageMutationException(@Autowired WebTestClient client) { // Given - UUID chatroomId = UUID.randomUUID(); + UUID chatroomId = getRandomIdForOwnedShard(); String user = "foo"; Long messageId = 66l; Message.MessageKey key = Message.MessageKey.of(user, messageId); @@ -211,10 +229,10 @@ public class ChatBackendControllerTest @Test @DisplayName("Assert expected problem-details for invalid username on PUT /put/{chatroomId}/{username}/{messageId}") - void testInvalidUsernameException(@Autowired WebTestClient client) throws Exception + void testInvalidUsernameException(@Autowired WebTestClient client) { // Given - UUID chatroomId = UUID.randomUUID(); + UUID chatroomId = getRandomIdForOwnedShard(); String user = "Foo"; Long messageId = 66l; Message.MessageKey key = Message.MessageKey.of(user, messageId); @@ -251,4 +269,157 @@ public class ChatBackendControllerTest .jsonPath("$.username").isEqualTo(user); verify(chatRoomService, never()).persistMessage(eq(key), any(LocalDateTime.class), any(String.class)); } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on GET /{chatroomId}") + void testShardNotOwnedExceptionForGetChatroom(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = getRandomIdForForeignShard(); + + // When + WebTestClient.ResponseSpec responseSpec = client + .get() + .uri("/{chatroomId}", chatroomId) + .accept(MediaType.APPLICATION_JSON) + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId)); + } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on GET /list/{chatroomId}") + void testShardNotOwnedExceptionForListChatroom(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = getRandomIdForForeignShard(); + + // When + WebTestClient.ResponseSpec responseSpec = client + .get() + .uri("/{chatroomId}/list", chatroomId) + .accept(MediaType.APPLICATION_JSON) + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId)); + } + + @Test + @DisplayName("Assert expected problem-details for now owned shard on PUT /put/{chatroomId}/{username}/{messageId}") + void testShardNotOwnedExceptionForPutMessage(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = getRandomIdForForeignShard(); + String username = "foo"; + Long messageId = 66l; + when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty()); + + // When + WebTestClient.ResponseSpec responseSpec = client + .put() + .uri( + "/{chatroomId}/{username}/{messageId}", + chatroomId, + username, + messageId) + .bodyValue("bar") + .accept(MediaType.APPLICATION_JSON) + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId)); + } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on GET /get/{chatroomId}/{username}/{messageId}") + void testShardNotOwnedExceptionForGetMessage(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = getRandomIdForForeignShard(); + String username = "foo"; + Long messageId = 66l; + when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty()); + + // When + WebTestClient.ResponseSpec responseSpec = client + .get() + .uri( + "/{chatroomId}/{username}/{messageId}", + chatroomId, + username, + messageId) + .accept(MediaType.APPLICATION_JSON) + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId)); + } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on GET /listen/{chatroomId}") + void testShardNotOwnedExceptionForListenChatroom(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = getRandomIdForForeignShard(); + when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty()); + + // When + WebTestClient.ResponseSpec responseSpec = client + .get() + .uri("/{chatroomId}/listen", chatroomId) + // .accept(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_JSON) << TODO: Does not work! + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId)); + } + + private void assertProblemDetailsForShardNotOwnedException( + WebTestClient.ResponseSpec responseSpec, + int shard) + { + responseSpec + .expectStatus().isNotFound() + .expectBody() + .jsonPath("$.type").isEqualTo("/problem/shard-not-owned") + .jsonPath("$.shard").isEqualTo(shard); + } + + private UUID getRandomIdForOwnedShard() + { + Set ownedShards = ownedShards(); + UUID randomId; + + do + { + randomId = UUID.randomUUID(); + } + while (!ownedShards.contains(shardingStrategy.selectShard(randomId))); + + return randomId; + } + + private UUID getRandomIdForForeignShard() + { + Set ownedShards = ownedShards(); + UUID randomId; + + do + { + randomId = UUID.randomUUID(); + } + while (ownedShards.contains(shardingStrategy.selectShard(randomId))); + + return randomId; + } + + private Set ownedShards() + { + return IntStream + .of(properties.getInmemory().getOwnedShards()) + .mapToObj(shard -> Integer.valueOf(shard)) + .collect(Collectors.toSet()); + } }