From 7209ac1c7ce81b10fecba9b95f1e135b0864261c Mon Sep 17 00:00:00 2001 From: Davide Angelocola Date: Sat, 20 Jun 2026 16:32:40 +0200 Subject: [PATCH] =?UTF-8?q?test(writer):=20mutation-cover=20WriteRegistry?= =?UTF-8?q?=20=E2=80=94=20writer=20scope=20to=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add WriteRegistry to the writer pitest scope. It started at 95% (exercised indirectly via loadAll), with three survivors no test pinned: - register(EncodingEncoder) / register(ExtensionEncoder) `return this` — nothing asserted the fluent builder return (NullReturn survived). - empty() — NO_COVERAGE; no test used the empty factory. WriteRegistryTest covers registration, duplicate-id rejection, extension lookup, the same-builder fluent returns, and the empty/loadAll factories, using mock encoders/extensions (BDDMockito). Writer now 64/64 mutations killed (ChunkImpl + WriteRegistry), strength 100%. Co-Authored-By: Claude Opus 4.8 --- writer/pom.xml | 2 + .../dfa1/vortex/writer/WriteRegistryTest.java | 128 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 writer/src/test/java/io/github/dfa1/vortex/writer/WriteRegistryTest.java diff --git a/writer/pom.xml b/writer/pom.xml index c82126f5..f80bf6c9 100644 --- a/writer/pom.xml +++ b/writer/pom.xml @@ -79,6 +79,8 @@ io.github.dfa1.vortex.writer.ChunkImpl + io.github.dfa1.vortex.writer.WriteRegistry + io.github.dfa1.vortex.writer.WriteRegistry$Builder diff --git a/writer/src/test/java/io/github/dfa1/vortex/writer/WriteRegistryTest.java b/writer/src/test/java/io/github/dfa1/vortex/writer/WriteRegistryTest.java new file mode 100644 index 00000000..dbcb41ba --- /dev/null +++ b/writer/src/test/java/io/github/dfa1/vortex/writer/WriteRegistryTest.java @@ -0,0 +1,128 @@ +package io.github.dfa1.vortex.writer; + +import io.github.dfa1.vortex.core.VortexException; +import io.github.dfa1.vortex.encoding.EncodingId; +import io.github.dfa1.vortex.extension.ExtensionId; +import io.github.dfa1.vortex.writer.encode.EncodingEncoder; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/// Unit tests for [WriteRegistry] and its [WriteRegistry.Builder] — encoder/extension +/// registration, duplicate rejection, lookup, and the fluent builder return. +class WriteRegistryTest { + + private static EncodingEncoder encoder(EncodingId id) { + EncodingEncoder enc = mock(EncodingEncoder.class); + given(enc.encodingId()).willReturn(id); + return enc; + } + + private static ExtensionEncoder extension(ExtensionId id) { + ExtensionEncoder ext = mock(ExtensionEncoder.class); + given(ext.extensionId()).willReturn(id); + return ext; + } + + @Test + void register_thenEncoderMap_containsEncoder() { + // Given + EncodingEncoder enc = encoder(EncodingId.VORTEX_PRIMITIVE); + + // When + WriteRegistry result = WriteRegistry.builder().register(enc).build(); + + // Then + assertThat(result.encoderMap()).containsEntry(EncodingId.VORTEX_PRIMITIVE, enc); + } + + @Test + void register_returnsSameBuilderForChaining() { + // Given + WriteRegistry.Builder sut = WriteRegistry.builder(); + + // When + WriteRegistry.Builder result = sut.register(encoder(EncodingId.VORTEX_PRIMITIVE)); + + // Then — the fluent return must be the same builder, not null + assertThat(result).isSameAs(sut); + } + + @Test + void register_duplicateEncoderId_throws() { + // Given — two encoders advertising the same id + WriteRegistry.Builder sut = WriteRegistry.builder() + .register(encoder(EncodingId.VORTEX_PRIMITIVE)); + + // When / Then + assertThatThrownBy(() -> sut.register(encoder(EncodingId.VORTEX_PRIMITIVE))) + .isInstanceOf(VortexException.class) + .hasMessageContaining("already registered"); + } + + @Test + void registerExtension_thenLookup_returnsIt() { + // Given + ExtensionEncoder ext = extension(ExtensionId.VORTEX_DATE); + + // When + WriteRegistry result = WriteRegistry.builder().register(ext).build(); + + // Then + assertThat(result.lookup(ExtensionId.VORTEX_DATE)).isSameAs(ext); + } + + @Test + void registerExtension_returnsSameBuilderForChaining() { + // Given + WriteRegistry.Builder sut = WriteRegistry.builder(); + + // When + WriteRegistry.Builder result = sut.register(extension(ExtensionId.VORTEX_DATE)); + + // Then + assertThat(result).isSameAs(sut); + } + + @Test + void registerExtension_duplicateId_throws() { + // Given + WriteRegistry.Builder sut = WriteRegistry.builder() + .register(extension(ExtensionId.VORTEX_DATE)); + + // When / Then + assertThatThrownBy(() -> sut.register(extension(ExtensionId.VORTEX_DATE))) + .isInstanceOf(VortexException.class) + .hasMessageContaining("already registered"); + } + + @Test + void lookup_unregisteredExtension_returnsNull() { + // Given — empty registry + + // When / Then + assertThat(WriteRegistry.empty().lookup(ExtensionId.VORTEX_UUID)).isNull(); + } + + @Test + void empty_hasNoEncodersAndNullLookup() { + // Given / When + WriteRegistry sut = WriteRegistry.empty(); + + // Then + assertThat(sut.encoderMap()).isEmpty(); + assertThat(sut.lookup(ExtensionId.VORTEX_DATE)).isNull(); + } + + @Test + void loadAll_discoversServiceLoadedEncoders() { + // Given / When — the module ships encoders via META-INF/services + WriteRegistry sut = WriteRegistry.loadAll(); + + // Then + assertThat(sut.encoderMap()).isNotEmpty(); + } +}