Compare commits
	
		
			3 commits
		
	
	
		
			dbdfb0c8a4
			...
			a613a92adb
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a613a92adb | |||
| 87b16cb24a | |||
| f370037289 | 
					 6 changed files with 213 additions and 44 deletions
				
			
		
							
								
								
									
										13
									
								
								pom.xml
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								pom.xml
									
										
									
									
									
								
							|  | @ -1,5 +1,6 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  |          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
|     <modelVersion>4.0.0</modelVersion> |     <modelVersion>4.0.0</modelVersion> | ||||||
| 
 | 
 | ||||||
|     <parent> |     <parent> | ||||||
|  | @ -57,7 +58,7 @@ | ||||||
|     <properties> |     <properties> | ||||||
|         <maze-generator.version>0.2.1</maze-generator.version> |         <maze-generator.version>0.2.1</maze-generator.version> | ||||||
|         <maven-site-plugin.version>4.0.0-M8</maven-site-plugin.version> |         <maven-site-plugin.version>4.0.0-M8</maven-site-plugin.version> | ||||||
|         <undertow.version>2.3.13.Final</undertow.version> |         <undertow.version>2.3.18.Final</undertow.version> | ||||||
|     </properties> |     </properties> | ||||||
| 
 | 
 | ||||||
|     <dependencies> |     <dependencies> | ||||||
|  | @ -95,6 +96,11 @@ | ||||||
|             <groupId>org.junit.jupiter</groupId> |             <groupId>org.junit.jupiter</groupId> | ||||||
|             <artifactId>junit-jupiter-api</artifactId> |             <artifactId>junit-jupiter-api</artifactId> | ||||||
|         </dependency> |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.assertj</groupId> | ||||||
|  |             <artifactId>assertj-core</artifactId> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|     </dependencies> |     </dependencies> | ||||||
| 
 | 
 | ||||||
|     <build> |     <build> | ||||||
|  | @ -104,7 +110,8 @@ | ||||||
|                 <artifactId>maven-shade-plugin</artifactId> |                 <artifactId>maven-shade-plugin</artifactId> | ||||||
|                 <configuration> |                 <configuration> | ||||||
|                     <transformers> |                     <transformers> | ||||||
|                         <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> |                         <transformer | ||||||
|  |                                 implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> | ||||||
|                             <mainClass>ch.fritteli.maze.server.Main</mainClass> |                             <mainClass>ch.fritteli.maze.server.Main</mainClass> | ||||||
|                         </transformer> |                         </transformer> | ||||||
|                     </transformers> |                     </transformers> | ||||||
|  |  | ||||||
|  | @ -18,11 +18,11 @@ public class MazeServer { | ||||||
|     private final Undertow undertow; |     private final Undertow undertow; | ||||||
| 
 | 
 | ||||||
|     private MazeServer(@NotNull final ServerConfig config) { |     private MazeServer(@NotNull final ServerConfig config) { | ||||||
|         final String hostAddress = config.getAddress().getHostAddress(); |         final String hostAddress = config.address().getHostAddress(); | ||||||
|         final int port = config.getPort(); |         final int port = config.port(); | ||||||
|         log.info("Starting Server at http://{}:{}/", hostAddress, port); |         log.info("Starting Server at http://{}:{}/", hostAddress, port); | ||||||
|         final RoutingHandler routingHandler = new RoutingHandler() |         final RoutingHandler routingHandler = new RoutingHandler() | ||||||
|                 .get(CreateHandler.PATH_TEMPLATE, new CreateHandler()) |                 .get(CreateHandler.PATH_TEMPLATE, new CreateHandler(config.maxMazeHeight(), config.maxMazeWidth())) | ||||||
|                 .post(RenderV1Handler.PATH_TEMPLATE, new RenderV1Handler()) |                 .post(RenderV1Handler.PATH_TEMPLATE, new RenderV1Handler()) | ||||||
|                 .post(RenderV2Handler.PATH_TEMPLATE, new RenderV2Handler()); |                 .post(RenderV2Handler.PATH_TEMPLATE, new RenderV2Handler()); | ||||||
| 
 | 
 | ||||||
|  | @ -47,7 +47,7 @@ public class MazeServer { | ||||||
|     private void start() { |     private void start() { | ||||||
|         Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper")); |         Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper")); | ||||||
|         this.undertow.start(); |         this.undertow.start(); | ||||||
|         final InetSocketAddress address = (InetSocketAddress) this.undertow.getListenerInfo().get(0).getAddress(); |         final InetSocketAddress address = (InetSocketAddress) this.undertow.getListenerInfo().getFirst().getAddress(); | ||||||
|         final String hostAddress = address.getAddress().getHostAddress(); |         final String hostAddress = address.getAddress().getHostAddress(); | ||||||
|         final int port = address.getPort(); |         final int port = address.getPort(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,42 +1,56 @@ | ||||||
| package ch.fritteli.maze.server; | package ch.fritteli.maze.server; | ||||||
| 
 | 
 | ||||||
|  | import io.vavr.control.Option; | ||||||
| import io.vavr.control.Try; | import io.vavr.control.Try; | ||||||
| import lombok.AccessLevel; |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Value; |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| import org.jetbrains.annotations.Nullable; | import org.jetbrains.annotations.Nullable; | ||||||
| import org.wildfly.common.annotation.NotNull; |  | ||||||
| 
 | 
 | ||||||
| import java.net.InetAddress; | import java.net.InetAddress; | ||||||
| 
 | 
 | ||||||
| @AllArgsConstructor(access = AccessLevel.PRIVATE) |  | ||||||
| @Slf4j | @Slf4j | ||||||
| @Value | public record ServerConfig(@NotNull InetAddress address, | ||||||
| public class ServerConfig { |                            int port, | ||||||
|  |                            @NotNull Option<Integer> maxMazeHeight, | ||||||
|  |                            @NotNull Option<Integer> maxMazeWidth) { | ||||||
|     public static final String SYSPROP_HOST = "fritteli.maze.server.host"; |     public static final String SYSPROP_HOST = "fritteli.maze.server.host"; | ||||||
|     public static final String SYSPROP_PORT = "fritteli.maze.server.port"; |     public static final String SYSPROP_PORT = "fritteli.maze.server.port"; | ||||||
|  |     public static final String SYSPROP_MAX_MAZE_HEIGHT = "fritteli.maze.maxheight"; | ||||||
|  |     public static final String SYSPROP_MAX_MAZE_WIDTH = "fritteli.maze.maxwidth"; | ||||||
| 
 | 
 | ||||||
|     @NotNull |     public ServerConfig(@NotNull final InetAddress address, | ||||||
|     InetAddress address; |                         final int port, | ||||||
|     int port; |                         @NotNull final Option<Integer> maxMazeHeight, | ||||||
| 
 |                         @NotNull final Option<Integer> maxMazeWidth) { | ||||||
|     public ServerConfig(@Nullable final String address, final int port) throws ConfigurationException { |         this.address = address; | ||||||
|         this.address = validateAddress(address); |  | ||||||
|         this.port = validatePort(port); |         this.port = validatePort(port); | ||||||
|         log.debug("host={}, port={}", this.address, this.port); |         this.maxMazeHeight = validateDimension(maxMazeHeight, "height"); | ||||||
|  |         this.maxMazeWidth = validateDimension(maxMazeWidth, "width"); | ||||||
|  |         log.debug("host={}, port={}, maxHeight={}, maxWidth={}", this.address, this.port, this.maxMazeHeight, this.maxMazeWidth); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public ServerConfig(@Nullable final String address, | ||||||
|  |                         final int port, | ||||||
|  |                         @NotNull final Option<Integer> maxMazeHeight, | ||||||
|  |                         @NotNull final Option<Integer> maxMazeWidth) | ||||||
|  |             throws ConfigurationException { | ||||||
|  |         this(validateAddress(address), port, maxMazeHeight, maxMazeWidth); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NotNull |     @NotNull | ||||||
|     public static ServerConfig init() throws ConfigurationException { |     public static ServerConfig init() throws ConfigurationException { | ||||||
|         final String host = System.getProperty(SYSPROP_HOST); |         final String host = System.getProperty(SYSPROP_HOST); | ||||||
|         final String portString = System.getProperty(SYSPROP_PORT); |         final String portString = System.getProperty(SYSPROP_PORT); | ||||||
|  |         final String maxMazeHeightString = System.getProperty(SYSPROP_MAX_MAZE_HEIGHT); | ||||||
|  |         final String maxMazeWidthString = System.getProperty(SYSPROP_MAX_MAZE_WIDTH); | ||||||
|         final int port = validatePort(portString); |         final int port = validatePort(portString); | ||||||
|         return new ServerConfig(host, port); |         final Option<Integer> maxMazeHeight = validateDimension(maxMazeHeightString, "height", SYSPROP_MAX_MAZE_HEIGHT); | ||||||
|  |         final Option<Integer> maxMazeWidth = validateDimension(maxMazeWidthString, "width", SYSPROP_MAX_MAZE_WIDTH); | ||||||
|  |         return new ServerConfig(host, port, maxMazeHeight, maxMazeWidth); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NotNull |     @NotNull | ||||||
|     private static InetAddress validateAddress(@Nullable final String address) { |     private static InetAddress validateAddress(@Nullable final String address) throws ConfigurationException { | ||||||
|         return Try.of(() -> InetAddress.getByName(address)) |         return Try.of(() -> InetAddress.getByName(address)) | ||||||
|                 .getOrElseThrow(cause -> new ConfigurationException( |                 .getOrElseThrow(cause -> new ConfigurationException( | ||||||
|                         "Invalid hostname/address: %s".formatted(address), |                         "Invalid hostname/address: %s".formatted(address), | ||||||
|  | @ -44,22 +58,48 @@ public class ServerConfig { | ||||||
|                 )); |                 )); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static int validatePort(final int port) { |     private static int validatePort(final int port) throws ConfigurationException { | ||||||
|         if (port < 0 || port > 0xFFFF) { |         if (port < 0 || port > 0xFFFF) { | ||||||
|             throw new ConfigurationException("Port out of range (0..65535): %s".formatted(port)); |             throw new ConfigurationException("Port out of range (0..65535): %s".formatted(port)); | ||||||
|         } |         } | ||||||
|         return port; |         return port; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static int validatePort(@Nullable final String portString) { |     private static int validatePort(@Nullable final String portString) throws ConfigurationException { | ||||||
|         if (portString == null) { |         if (portString == null) { | ||||||
|             log.info("No port configured; using default."); |             log.info("No port configured; using default."); | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|         return Try.of(() -> Integer.valueOf(portString)) |         return Try.of(() -> Integer.parseInt(portString)) | ||||||
|                 .getOrElseThrow(cause -> new ConfigurationException( |                 .getOrElseThrow(cause -> new ConfigurationException( | ||||||
|                         "Failed to parse port specified in system property '%s': %s".formatted(SYSPROP_PORT, portString), |                         "Failed to parse port specified in system property '%s': %s".formatted(SYSPROP_PORT, portString), | ||||||
|                         cause |                         cause | ||||||
|                 )); |                 )); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     @NotNull | ||||||
|  |     private static Option<Integer> validateDimension(@NotNull final Option<Integer> dimension, | ||||||
|  |                                                      @NotNull final String identifier) { | ||||||
|  |         if (dimension.exists(d -> d <= 1)) { | ||||||
|  |             throw new ConfigurationException("Maximum %s must be greater than 1: %s" | ||||||
|  |                     .formatted(identifier, dimension.get())); | ||||||
|  |         } | ||||||
|  |         return dimension; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static Option<Integer> validateDimension(@Nullable final String dimensionString, | ||||||
|  |                                                      @NotNull final String identifier, | ||||||
|  |                                                      @NotNull final String syspropName) { | ||||||
|  |         if (dimensionString == null) { | ||||||
|  |             log.info("No maximum {} configured; using default (unlimited).", identifier); | ||||||
|  |             return Option.none(); | ||||||
|  |         } | ||||||
|  |         final int desiredDimension = Try.of(() -> Integer.parseInt(dimensionString)) | ||||||
|  |                 .getOrElseThrow(cause -> new ConfigurationException( | ||||||
|  |                         "Failed to parse maximum %s specified in system property '%s': %s" | ||||||
|  |                                 .formatted(identifier, syspropName, dimensionString), | ||||||
|  |                         cause | ||||||
|  |                 )); | ||||||
|  |         return Option.some(desiredDimension); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ import io.undertow.server.HttpServerExchange; | ||||||
| import io.undertow.util.Headers; | import io.undertow.util.Headers; | ||||||
| import io.undertow.util.HttpString; | import io.undertow.util.HttpString; | ||||||
| import io.undertow.util.StatusCodes; | import io.undertow.util.StatusCodes; | ||||||
|  | import io.vavr.control.Option; | ||||||
| import io.vavr.control.Try; | import io.vavr.control.Try; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
|  | @ -22,6 +23,15 @@ import java.util.Map; | ||||||
| public class CreateHandler extends AbstractHttpHandler { | public class CreateHandler extends AbstractHttpHandler { | ||||||
| 
 | 
 | ||||||
|     public static final String PATH_TEMPLATE = "/create/{output}"; |     public static final String PATH_TEMPLATE = "/create/{output}"; | ||||||
|  |     @NotNull | ||||||
|  |     private final Option<Integer> maxHeight; | ||||||
|  |     @NotNull | ||||||
|  |     private final Option<Integer> maxWidth; | ||||||
|  | 
 | ||||||
|  |     public CreateHandler(@NotNull final Option<Integer> maxHeight, @NotNull final Option<Integer> maxWidth) { | ||||||
|  |         this.maxHeight = maxHeight; | ||||||
|  |         this.maxWidth = maxWidth; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     protected void handle(@NotNull final HttpServerExchange exchange) { |     protected void handle(@NotNull final HttpServerExchange exchange) { | ||||||
|  | @ -29,10 +39,11 @@ public class CreateHandler extends AbstractHttpHandler { | ||||||
|         log.debug("Handling create request"); |         log.debug("Handling create request"); | ||||||
|         this.createMazeFromRequestParameters(exchange.getQueryParameters()) |         this.createMazeFromRequestParameters(exchange.getQueryParameters()) | ||||||
|                 .onFailure(e -> { |                 .onFailure(e -> { | ||||||
|                     log.error("Error creating maze from request", e); |  | ||||||
|                     if (e instanceof InvalidRequestParameterException) { |                     if (e instanceof InvalidRequestParameterException) { | ||||||
|  |                         log.debug("Error creating maze from request", e); | ||||||
|                         exchange.setStatusCode(StatusCodes.BAD_REQUEST); |                         exchange.setStatusCode(StatusCodes.BAD_REQUEST); | ||||||
|                     } else { |                     } else { | ||||||
|  |                         log.error("Error creating maze from request", e); | ||||||
|                         exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR); |                         exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR); | ||||||
|                     } |                     } | ||||||
|                     exchange.getResponseSender() |                     exchange.getResponseSender() | ||||||
|  | @ -75,6 +86,6 @@ public class CreateHandler extends AbstractHttpHandler { | ||||||
| 
 | 
 | ||||||
|     @NotNull |     @NotNull | ||||||
|     private Try<ParametersToMazeExtractor.GeneratedMaze> createMazeFromRequestParameters(final Map<String, Deque<String>> queryParameters) { |     private Try<ParametersToMazeExtractor.GeneratedMaze> createMazeFromRequestParameters(final Map<String, Deque<String>> queryParameters) { | ||||||
|         return new ParametersToMazeExtractor(queryParameters).createMaze(); |         return new ParametersToMazeExtractor(queryParameters, this.maxHeight, this.maxWidth).createMaze(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -20,6 +20,10 @@ class ParametersToMazeExtractor { | ||||||
| 
 | 
 | ||||||
|     @NotNull |     @NotNull | ||||||
|     private final Map<String, Deque<String>> queryParameters; |     private final Map<String, Deque<String>> queryParameters; | ||||||
|  |     @NotNull | ||||||
|  |     private final Option<Integer> maxHeight; | ||||||
|  |     @NotNull | ||||||
|  |     private final Option<Integer> maxWidth; | ||||||
| 
 | 
 | ||||||
|     @NotNull |     @NotNull | ||||||
|     Try<GeneratedMaze> createMaze() { |     Try<GeneratedMaze> createMaze() { | ||||||
|  | @ -49,12 +53,29 @@ class ParametersToMazeExtractor { | ||||||
|             ))); |             ))); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         final int desiredHeight = height.get(); | ||||||
|  |         final int desiredWidth = width.get(); | ||||||
|  | 
 | ||||||
|  |         if (desiredHeight <= 1) { | ||||||
|  |             return Try.failure(new InvalidRequestParameterException("Specified height (%s) must be > 1".formatted(desiredHeight))); | ||||||
|  |         } | ||||||
|  |         if (desiredWidth <= 1) { | ||||||
|  |             return Try.failure(new InvalidRequestParameterException("Specified width (%s) must be > 1".formatted(desiredHeight))); | ||||||
|  |         } | ||||||
|  |         if (this.maxHeight.exists(max -> desiredHeight > max)) { | ||||||
|  |             return Try.failure(new InvalidRequestParameterException("Specified height (%s) is greater than allowed maximum of %s".formatted(desiredHeight, this.maxHeight.get()))); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (this.maxWidth.exists(max -> desiredWidth > max)) { | ||||||
|  |             return Try.failure(new InvalidRequestParameterException("Specified width (%s) is greater than allowed maximum of %s".formatted(desiredWidth, this.maxWidth.get()))); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         return Try.of(() -> { |         return Try.of(() -> { | ||||||
|             final Maze maze; |             final Maze maze; | ||||||
|             if (start.isDefined() && end.isDefined()) { |             if (start.isDefined() && end.isDefined()) { | ||||||
|                 maze = new Maze(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong()), start.get(), end.get()); |                 maze = new Maze(desiredWidth, desiredHeight, id.getOrElse(() -> new Random().nextLong()), start.get(), end.get()); | ||||||
|             } else { |             } else { | ||||||
|                 maze = new Maze(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong())); |                 maze = new Maze(desiredWidth, desiredHeight, id.getOrElse(() -> new Random().nextLong())); | ||||||
|             } |             } | ||||||
|             new RandomDepthFirst(maze).run(); |             new RandomDepthFirst(maze).run(); | ||||||
|             return new GeneratedMaze(maze, output.get(), RandomDepthFirst.class.getSimpleName()); |             return new GeneratedMaze(maze, output.get(), RandomDepthFirst.class.getSimpleName()); | ||||||
|  |  | ||||||
|  | @ -3,16 +3,16 @@ package ch.fritteli.maze.server; | ||||||
| import org.junit.jupiter.api.BeforeEach; | import org.junit.jupiter.api.BeforeEach; | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| 
 | 
 | ||||||
| import java.net.UnknownHostException; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| 
 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; | ||||||
| import static org.junit.jupiter.api.Assertions.assertEquals; |  | ||||||
| import static org.junit.jupiter.api.Assertions.assertThrows; |  | ||||||
| 
 | 
 | ||||||
| class ServerConfigTest { | class ServerConfigTest { | ||||||
|     @BeforeEach |     @BeforeEach | ||||||
|     void clearSysProperties() { |     void clearSysProperties() { | ||||||
|         System.clearProperty(ServerConfig.SYSPROP_HOST); |         System.clearProperty(ServerConfig.SYSPROP_HOST); | ||||||
|         System.clearProperty(ServerConfig.SYSPROP_PORT); |         System.clearProperty(ServerConfig.SYSPROP_PORT); | ||||||
|  |         System.clearProperty(ServerConfig.SYSPROP_MAX_MAZE_HEIGHT); | ||||||
|  |         System.clearProperty(ServerConfig.SYSPROP_MAX_MAZE_WIDTH); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|  | @ -22,9 +22,27 @@ class ServerConfigTest { | ||||||
|         final ServerConfig sut = ServerConfig.init(); |         final ServerConfig sut = ServerConfig.init(); | ||||||
| 
 | 
 | ||||||
|         // assert |         // assert | ||||||
|         assertEquals("127.0.0.1", sut.getAddress().getHostAddress()); |         assertThat(sut.address()) | ||||||
|         assertEquals("localhost", sut.getAddress().getHostName()); |                 .satisfies( | ||||||
|         assertEquals(0, sut.getPort()); |                         address -> assertThat(address.getHostAddress()).isEqualTo("127.0.0.1"), | ||||||
|  |                         address -> assertThat(address.getHostName()).isEqualTo("localhost") | ||||||
|  |                 ); | ||||||
|  |         assertThat(sut.port()).isZero(); | ||||||
|  |         assertThat(sut.maxMazeHeight()).isEmpty(); | ||||||
|  |         assertThat(sut.maxMazeWidth()).isEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testInit_invalidAddress() { | ||||||
|  |         // arrange | ||||||
|  |         System.setProperty(ServerConfig.SYSPROP_HOST, "256.2515.19.0"); | ||||||
|  | 
 | ||||||
|  |         // act / assert | ||||||
|  |         assertThatExceptionOfType(ConfigurationException.class) | ||||||
|  |                 .isThrownBy(ServerConfig::init) | ||||||
|  |                 .withMessageContaining("Invalid hostname/address") | ||||||
|  |                 .withMessageContaining("256.2515.19.0"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|  | @ -33,29 +51,101 @@ class ServerConfigTest { | ||||||
|         System.setProperty(ServerConfig.SYSPROP_PORT, "Hello World!"); |         System.setProperty(ServerConfig.SYSPROP_PORT, "Hello World!"); | ||||||
| 
 | 
 | ||||||
|         // act / assert |         // act / assert | ||||||
|         assertThrows(ConfigurationException.class, ServerConfig::init); |         assertThatExceptionOfType(ConfigurationException.class) | ||||||
|  |                 .isThrownBy(ServerConfig::init) | ||||||
|  |                 .withMessageContaining("Failed to parse port") | ||||||
|  |                 .withMessageContaining("Hello World!"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     void testInit_invalidPort() { |     void testInit_invalidPortTooSmall() { | ||||||
|  |         // arrange | ||||||
|  |         System.setProperty(ServerConfig.SYSPROP_PORT, "-5"); | ||||||
|  | 
 | ||||||
|  |         // act / assert | ||||||
|  |         assertThatExceptionOfType(ConfigurationException.class) | ||||||
|  |                 .isThrownBy(ServerConfig::init) | ||||||
|  |                 .withMessageContaining("Port out of range") | ||||||
|  |                 .withMessageContaining("-5"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testInit_invalidPortTooLarge() { | ||||||
|         // arrange |         // arrange | ||||||
|         System.setProperty(ServerConfig.SYSPROP_PORT, "99999"); |         System.setProperty(ServerConfig.SYSPROP_PORT, "99999"); | ||||||
| 
 | 
 | ||||||
|         // act / assert |         // act / assert | ||||||
|         assertThrows(ConfigurationException.class, ServerConfig::init); |         assertThatExceptionOfType(ConfigurationException.class) | ||||||
|  |                 .isThrownBy(ServerConfig::init) | ||||||
|  |                 .withMessageContaining("Port out of range") | ||||||
|  |                 .withMessageContaining("99999"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     void testInit() throws ConfigurationException, UnknownHostException { |     void testInit_unparseableMaxMazeHeight() { | ||||||
|         // arrange |         // arrange | ||||||
|         System.setProperty(ServerConfig.SYSPROP_HOST, "127.0.0.1"); |         System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_HEIGHT, "Hello World!"); | ||||||
|  | 
 | ||||||
|  |         // act / assert | ||||||
|  |         assertThatExceptionOfType(ConfigurationException.class) | ||||||
|  |                 .isThrownBy(ServerConfig::init) | ||||||
|  |                 .withMessageContaining("Failed to parse maximum height") | ||||||
|  |                 .withMessageContaining("Hello World!"); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testInit_invalidMaxMazeHeight() { | ||||||
|  |         // arrange | ||||||
|  |         System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_HEIGHT, "1"); | ||||||
|  | 
 | ||||||
|  |         // act / assert | ||||||
|  |         assertThatExceptionOfType(ConfigurationException.class) | ||||||
|  |                 .isThrownBy(ServerConfig::init) | ||||||
|  |                 .withMessageContaining("Maximum height must be greater than 1:") | ||||||
|  |                 .withMessageEndingWith("1"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testInit_unparseableMaxMazeWidth() { | ||||||
|  |         // arrange | ||||||
|  |         System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_WIDTH, "Hello World!"); | ||||||
|  | 
 | ||||||
|  |         // act / assert | ||||||
|  |         assertThatExceptionOfType(ConfigurationException.class) | ||||||
|  |                 .isThrownBy(ServerConfig::init) | ||||||
|  |                 .withMessageContaining("Failed to parse maximum width") | ||||||
|  |                 .withMessageContaining("Hello World!"); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testInit_invalidMaxMazeWidth() { | ||||||
|  |         // arrange | ||||||
|  |         System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_WIDTH, "-24"); | ||||||
|  | 
 | ||||||
|  |         // act / assert | ||||||
|  |         assertThatExceptionOfType(ConfigurationException.class) | ||||||
|  |                 .isThrownBy(ServerConfig::init) | ||||||
|  |                 .withMessageContaining("Maximum width must be greater than 1:") | ||||||
|  |                 .withMessageContaining("-24"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void testInit() throws ConfigurationException { | ||||||
|  |         // arrange | ||||||
|  |         System.setProperty(ServerConfig.SYSPROP_HOST, "10.0.9.12"); | ||||||
|         System.setProperty(ServerConfig.SYSPROP_PORT, "12345"); |         System.setProperty(ServerConfig.SYSPROP_PORT, "12345"); | ||||||
|  |         System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_HEIGHT, "100"); | ||||||
|  |         System.setProperty(ServerConfig.SYSPROP_MAX_MAZE_WIDTH, "42"); | ||||||
| 
 | 
 | ||||||
|         // act |         // act | ||||||
|         final ServerConfig sut = ServerConfig.init(); |         final ServerConfig sut = ServerConfig.init(); | ||||||
| 
 | 
 | ||||||
|         // assert |         // assert | ||||||
|         assertEquals("127.0.0.1", sut.getAddress().getHostAddress()); |         assertThat(sut.address().getHostAddress()).isEqualTo("10.0.9.12"); | ||||||
|         assertEquals(12345, sut.getPort()); |         assertThat(sut.port()).isEqualTo(12345); | ||||||
|  |         assertThat(sut.maxMazeHeight()).singleElement().isEqualTo(100); | ||||||
|  |         assertThat(sut.maxMazeWidth()).singleElement().isEqualTo(42); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue