# Test Package Structure ## Overview This document defines the complete test package organization, test class structure, and mock server setup for the Log Data Collector system. ## Test Source Directory Structure ``` src/test/ ├── java/ │ └── com/ │ └── logcollector/ │ ├── unit/ # Unit Tests (75% of suite) │ │ ├── config/ │ │ │ ├── ConfigurationLoaderTest.java │ │ │ ├── YamlParserTest.java │ │ │ └── ValidationServiceTest.java │ │ ├── serialization/ │ │ │ ├── DataSerializerTest.java │ │ │ ├── JsonSerializerTest.java │ │ │ └── ProtobufSerializerTest.java │ │ ├── buffer/ │ │ │ ├── CircularBufferTest.java │ │ │ ├── BufferOverflowHandlerTest.java │ │ │ └── BufferThreadSafetyTest.java │ │ ├── retry/ │ │ │ ├── RetryMechanismTest.java │ │ │ ├── ExponentialBackoffTest.java │ │ │ └── RetryPolicyTest.java │ │ ├── health/ │ │ │ ├── HealthCheckEndpointTest.java │ │ │ ├── HttpHealthCheckTest.java │ │ │ └── GrpcHealthCheckTest.java │ │ ├── collector/ │ │ │ ├── HttpCollectorTest.java │ │ │ ├── EndpointSchedulerTest.java │ │ │ └── ResponseParserTest.java │ │ ├── transmitter/ │ │ │ ├── GrpcTransmitterTest.java │ │ │ ├── ConnectionManagerTest.java │ │ │ └── TransmissionQueueTest.java │ │ └── startup/ │ │ ├── StartupSequenceTest.java │ │ ├── ComponentInitializerTest.java │ │ └── DependencyResolverTest.java │ │ │ ├── integration/ # Integration Tests (20% of suite) │ │ ├── collector/ │ │ │ ├── HttpCollectionIntegrationTest.java │ │ │ └── MultiEndpointIntegrationTest.java │ │ ├── transmitter/ │ │ │ ├── GrpcTransmissionIntegrationTest.java │ │ │ └── ReconnectionIntegrationTest.java │ │ ├── e2e/ │ │ │ ├── EndToEndDataFlowTest.java │ │ │ └── BackpressureIntegrationTest.java │ │ ├── config/ │ │ │ ├── ConfigurationFileIntegrationTest.java │ │ │ └── ConfigurationReloadIntegrationTest.java │ │ └── buffer/ │ │ ├── CircularBufferIntegrationTest.java │ │ └── BufferPerformanceIntegrationTest.java │ │ │ ├── performance/ # Performance Tests │ │ ├── PerformanceConcurrentEndpointsTest.java │ │ ├── PerformanceMemoryUsageTest.java │ │ ├── PerformanceVirtualThreadTest.java │ │ └── PerformanceStartupTimeTest.java │ │ │ ├── reliability/ # Reliability Tests │ │ ├── ReliabilityStartupSequenceTest.java │ │ ├── ReliabilityGrpcRetryTest.java │ │ ├── ReliabilityHttpFailureTest.java │ │ ├── ReliabilityBufferOverflowTest.java │ │ └── ReliabilityPartialFailureTest.java │ │ │ ├── compliance/ # Compliance Tests │ │ ├── ComplianceErrorDetectionTest.java │ │ ├── ComplianceIso9001Test.java │ │ ├── ComplianceEn50716Test.java │ │ └── ComplianceAuditLoggingTest.java │ │ │ └── util/ # Test Utilities │ ├── mock/ │ │ ├── HttpMockServerSetup.java │ │ ├── GrpcMockServerSetup.java │ │ └── MockClockProvider.java │ ├── builder/ │ │ ├── TestDataFactory.java │ │ ├── TestConfigurationBuilder.java │ │ ├── TestEndpointBuilder.java │ │ └── TestLogEntryBuilder.java │ ├── assertion/ │ │ ├── CustomAssertions.java │ │ └── PerformanceAssertions.java │ └── extension/ │ ├── MockServerExtension.java │ ├── GrpcServerExtension.java │ └── PerformanceTestExtension.java │ └── resources/ ├── config/ │ ├── test-config.yaml # Valid test configuration │ ├── test-config-invalid.yaml # Invalid format │ ├── test-config-minimal.yaml # Minimal valid config │ └── test-config-maximal.yaml # Maximum complexity config ├── data/ │ ├── sample-log-entries.json # Sample log data │ └── large-payload.json # Large payload test data ├── wiremock/ │ ├── mappings/ # WireMock stub mappings │ │ ├── health-check-success.json │ │ ├── health-check-failure.json │ │ ├── log-endpoint-success.json │ │ └── log-endpoint-timeout.json │ └── __files/ # WireMock response files │ ├── sample-response.json │ └── error-response.json ├── proto/ │ └── test-log-data.proto # Test Protocol Buffer definitions ├── logback-test.xml # Test logging configuration └── junit-platform.properties # JUnit configuration ``` ## Test Class Templates ### Unit Test Template ```java package com.logcollector.unit.config; import org.junit.jupiter.api.*; import org.mockito.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; /** * Unit tests for ConfigurationLoader component. * * @validates Req-FR-11 - Configuration file detection * @validates Req-FR-12 - Configuration parsing * @validates Req-FR-13 - Configuration validation * @validates Req-Norm-3 - Error detection */ @DisplayName("Configuration Loader Unit Tests") @Tag("unit") @Tag("config") class ConfigurationLoaderTest { @Mock private FileSystem fileSystem; @Mock private YamlParser yamlParser; @InjectMocks private ConfigurationLoader configurationLoader; private AutoCloseable mocks; @BeforeEach void setUp() { mocks = MockitoAnnotations.openMocks(this); } @AfterEach void tearDown() throws Exception { mocks.close(); } @Nested @DisplayName("Configuration File Detection") class FileDetectionTests { @Test @DisplayName("should detect config file when file exists") void shouldDetectConfigFile_whenFileExists() { // Arrange when(fileSystem.exists("/etc/logcollector/config.yaml")) .thenReturn(true); // Act boolean result = configurationLoader.detectConfigFile(); // Assert assertThat(result).isTrue(); verify(fileSystem).exists("/etc/logcollector/config.yaml"); } @Test @DisplayName("should throw exception when file not found") void shouldThrowException_whenFileNotFound() { // Arrange when(fileSystem.exists(anyString())).thenReturn(false); // Act & Assert assertThatThrownBy(() -> configurationLoader.load()) .isInstanceOf(ConfigurationNotFoundException.class) .hasMessageContaining("Configuration file not found"); } } @Nested @DisplayName("Configuration Parsing") class ParsingTests { // Parsing test methods... } @Nested @DisplayName("Configuration Validation") class ValidationTests { // Validation test methods... } } ``` ### Integration Test Template ```java package com.logcollector.integration.collector; import com.github.tomakehurst.wiremock.WireMockServer; import com.logcollector.util.extension.MockServerExtension; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.Assertions.*; /** * Integration tests for HTTP collection with mock server. * * @validates Req-Test-1 - Mock HTTP server * @validates Req-FR-14 - HTTP endpoint collection * @validates Req-FR-15 - Response parsing */ @DisplayName("HTTP Collection Integration Tests") @Tag("integration") @Tag("http") @ExtendWith(MockServerExtension.class) class HttpCollectionIntegrationTest { private WireMockServer wireMockServer; private HttpCollector httpCollector; @BeforeEach void setUp(WireMockServer server) { this.wireMockServer = server; this.httpCollector = new HttpCollector( "http://localhost:" + server.port() ); } @Test @DisplayName("should collect from mock endpoint when server running") void shouldCollectFromMockEndpoint_whenServerRunning() { // Arrange wireMockServer.stubFor(get(urlEqualTo("/logs")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBodyFile("sample-response.json"))); // Act LogData result = httpCollector.collect("/logs"); // Assert assertThat(result).isNotNull(); assertThat(result.getEntries()).isNotEmpty(); // Verify interaction wireMockServer.verify(1, getRequestedFor(urlEqualTo("/logs"))); } @Test @DisplayName("should handle multiple endpoints concurrently") void shouldHandleMultipleEndpoints_concurrently() { // Test implementation... } } ``` ### Performance Test Template ```java package com.logcollector.performance; import org.junit.jupiter.api.*; import org.openjdk.jmh.annotations.*; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.*; /** * Performance tests for concurrent endpoint handling. * * @validates Req-NFR-1 - 1000 concurrent endpoints support */ @DisplayName("Performance: Concurrent Endpoints") @Tag("performance") class PerformanceConcurrentEndpointsTest { @Test @DisplayName("should handle 1000 endpoints concurrently") @Timeout(value = 60, unit = TimeUnit.SECONDS) void shouldHandle1000Endpoints_concurrently() throws Exception { // Arrange List endpoints = IntStream.range(0, 1000) .mapToObj(i -> "http://endpoint-" + i + ".test/logs") .collect(Collectors.toList()); HttpCollector collector = new HttpCollector(); // Act long startTime = System.nanoTime(); List> futures = endpoints.stream() .map(collector::collectAsync) .toList(); List results = CompletableFuture.allOf( futures.toArray(new CompletableFuture[0]) ).thenApply(v -> futures.stream() .map(CompletableFuture::join) .toList() ).get(); long duration = System.nanoTime() - startTime; // Assert assertThat(results).hasSize(1000); assertThat(duration).isLessThan(TimeUnit.MINUTES.toNanos(1)); // Report metrics System.out.printf("Collected 1000 endpoints in %.2f seconds%n", duration / 1_000_000_000.0); } @Benchmark @BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) public void benchmarkEndpointCollection() { // JMH benchmark implementation... } } ``` ## Mock Server Setup ### WireMock HTTP Server ```java package com.logcollector.util.mock; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import static com.github.tomakehurst.wiremock.client.WireMock.*; /** * Mock HTTP server setup for testing HTTP collection. * * @validates Req-Test-1 - Mock HTTP server requirement */ public class HttpMockServerSetup { private final WireMockServer server; public HttpMockServerSetup() { this.server = new WireMockServer( WireMockConfiguration.options() .dynamicPort() .usingFilesUnderClasspath("wiremock") ); } public void start() { server.start(); configureDefaultStubs(); } public void stop() { server.stop(); } public int getPort() { return server.port(); } public WireMockServer getServer() { return server; } private void configureDefaultStubs() { // Health check success server.stubFor(get(urlEqualTo("/health")) .willReturn(aResponse() .withStatus(200) .withBody("{\"status\":\"UP\"}"))); // Log endpoint success server.stubFor(get(urlPathMatching("/logs.*")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBodyFile("sample-response.json"))); // Simulate timeout server.stubFor(get(urlEqualTo("/slow")) .willReturn(aResponse() .withStatus(200) .withFixedDelay(10000))); // Simulate error server.stubFor(get(urlEqualTo("/error")) .willReturn(aResponse() .withStatus(500) .withBody("{\"error\":\"Internal Server Error\"}"))); } } ``` ### gRPC Mock Server ```java package com.logcollector.util.mock; import io.grpc.*; import io.grpc.inprocess.*; import io.grpc.stub.StreamObserver; import java.io.IOException; /** * Mock gRPC server setup for testing transmission. * * @validates Req-Test-2 - Mock gRPC server requirement */ public class GrpcMockServerSetup { private final String serverName; private final Server server; private final MockLogDataService mockService; public GrpcMockServerSetup() { this.serverName = InProcessServerBuilder.generateName(); this.mockService = new MockLogDataService(); this.server = InProcessServerBuilder .forName(serverName) .directExecutor() .addService(mockService) .build(); } public void start() throws IOException { server.start(); } public void stop() { server.shutdownNow(); } public String getServerName() { return serverName; } public MockLogDataService getMockService() { return mockService; } public ManagedChannel createChannel() { return InProcessChannelBuilder .forName(serverName) .directExecutor() .build(); } /** * Mock implementation of LogDataService for testing. */ public static class MockLogDataService extends LogDataServiceGrpc.LogDataServiceImplBase { private int callCount = 0; private boolean shouldFail = false; @Override public void sendLogData( LogDataRequest request, StreamObserver responseObserver) { callCount++; if (shouldFail) { responseObserver.onError( Status.UNAVAILABLE .withDescription("Mock failure") .asRuntimeException() ); return; } LogDataResponse response = LogDataResponse.newBuilder() .setSuccess(true) .setMessageId(UUID.randomUUID().toString()) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); } public int getCallCount() { return callCount; } public void setShouldFail(boolean shouldFail) { this.shouldFail = shouldFail; } public void reset() { callCount = 0; shouldFail = false; } } } ``` ## Test Data Builders ### Test Configuration Builder ```java package com.logcollector.util.builder; import com.logcollector.config.Configuration; import com.logcollector.config.EndpointConfig; import com.logcollector.config.GrpcConfig; import java.util.*; /** * Fluent builder for test Configuration objects. */ public class TestConfigurationBuilder { private List endpoints = new ArrayList<>(); private String grpcHost = "localhost"; private int grpcPort = 9090; private int bufferSize = 10000; private int retryMaxAttempts = 3; private int retryBaseDelay = 100; public static TestConfigurationBuilder aConfiguration() { return new TestConfigurationBuilder(); } public TestConfigurationBuilder withEndpoint(EndpointConfig endpoint) { this.endpoints.add(endpoint); return this; } public TestConfigurationBuilder withEndpoints(int count) { for (int i = 0; i < count; i++) { endpoints.add(TestEndpointBuilder.anEndpoint() .withUrl("http://endpoint-" + i + ".test/logs") .withSchedule("0/30 * * * * ?") .build()); } return this; } public TestConfigurationBuilder withGrpcHost(String host) { this.grpcHost = host; return this; } public TestConfigurationBuilder withGrpcPort(int port) { this.grpcPort = port; return this; } public TestConfigurationBuilder withBufferSize(int size) { this.bufferSize = size; return this; } public TestConfigurationBuilder withRetryConfig(int maxAttempts, int baseDelay) { this.retryMaxAttempts = maxAttempts; this.retryBaseDelay = baseDelay; return this; } public Configuration build() { return Configuration.builder() .endpoints(endpoints) .grpcConfig(GrpcConfig.builder() .host(grpcHost) .port(grpcPort) .build()) .bufferSize(bufferSize) .retryMaxAttempts(retryMaxAttempts) .retryBaseDelayMs(retryBaseDelay) .build(); } } ``` ## JUnit Extensions ### Mock Server Extension ```java package com.logcollector.util.extension; import com.logcollector.util.mock.HttpMockServerSetup; import org.junit.jupiter.api.extension.*; /** * JUnit 5 extension for WireMock server lifecycle management. */ public class MockServerExtension implements BeforeEachCallback, AfterEachCallback { private static final String SERVER_KEY = "mockServer"; @Override public void beforeEach(ExtensionContext context) throws Exception { HttpMockServerSetup server = new HttpMockServerSetup(); server.start(); context.getStore(ExtensionContext.Namespace.GLOBAL) .put(SERVER_KEY, server); } @Override public void afterEach(ExtensionContext context) throws Exception { HttpMockServerSetup server = context.getStore( ExtensionContext.Namespace.GLOBAL ).get(SERVER_KEY, HttpMockServerSetup.class); if (server != null) { server.stop(); } } } ``` ## Test Resource Files ### test-config.yaml ```yaml # Valid test configuration endpoints: - url: "http://endpoint1.test/logs" schedule: "0/30 * * * * ?" timeout: 5000 - url: "http://endpoint2.test/logs" schedule: "0/60 * * * * ?" timeout: 5000 grpc: host: "localhost" port: 9090 tls: false buffer: size: 10000 overflow: "overwrite" retry: maxAttempts: 3 baseDelayMs: 100 maxDelayMs: 5000 ``` ### logback-test.xml ```xml %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ``` ## Maven Test Configuration ### pom.xml (Test Section) ```xml src/test/java src/test/resources org.apache.maven.plugins maven-surefire-plugin 3.2.5 **/*Test.java **/integration/** **/performance/** classes 4 org.apache.maven.plugins maven-failsafe-plugin 3.2.5 **/integration/**/*Test.java integration-test verify performance-tests org.apache.maven.plugins maven-surefire-plugin **/performance/**/*Test.java ``` --- **Version**: 1.0 **Last Updated**: 2025-11-19 **Author**: Test Strategist Agent **Status**: Complete - Test Infrastructure Defined