diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalDirPathResolver.java b/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalDirPathResolver.java index c850a605..612569a6 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalDirPathResolver.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalDirPathResolver.java @@ -1,10 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.block.server.persistence.storage.path; -import com.hedera.block.common.utils.FileUtilities; import com.hedera.block.common.utils.Preconditions; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; -import com.hedera.block.server.persistence.storage.PersistenceStorageConfig.CompressionType; import edu.umd.cs.findbugs.annotations.NonNull; import java.nio.file.Files; import java.nio.file.Path; @@ -15,7 +13,6 @@ */ public final class BlockAsLocalDirPathResolver implements BlockPathResolver { private final Path liveRootPath; - private final CompressionType compressionType; /** * Constructor. @@ -25,7 +22,6 @@ public final class BlockAsLocalDirPathResolver implements BlockPathResolver { */ private BlockAsLocalDirPathResolver(@NonNull final PersistenceStorageConfig config) { this.liveRootPath = Path.of(config.liveRootPath()); - this.compressionType = config.compression(); } /** @@ -55,16 +51,21 @@ public Path resolveArchiveRawPathToBlock(final long blockNumber) { throw new UnsupportedOperationException("Not implemented yet"); } + /** + * The block-as-local-dir implementation does not support + * compression/decompression. A block will only be found if it exists and is + * not compressed. + * + * @param blockNumber the block number to find the block file for + * @return an {@link Optional} containing the path to the block file if it + * exists, otherwise an empty {@link Optional} + */ @NonNull @Override - public Optional findBlock(final long blockNumber) { // todo add archive root search & abstract if common + public Optional findBlock(final long blockNumber) { Preconditions.requireWhole(blockNumber); final Path liveRawRootPath = resolveLiveRawPathToBlock(blockNumber); - final Path compressionExtendedLiveRawRootPath = - FileUtilities.appendExtension(liveRawRootPath, compressionType.getFileExtension()); - if (Files.exists(compressionExtendedLiveRawRootPath)) { - return Optional.of(compressionExtendedLiveRawRootPath); - } else if (Files.exists(liveRawRootPath)) { + if (Files.exists(liveRawRootPath)) { return Optional.of(liveRawRootPath); } else { return Optional.empty(); diff --git a/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalFilePathResolver.java b/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalFilePathResolver.java index ed75e2aa..3907b116 100644 --- a/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalFilePathResolver.java +++ b/server/src/main/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalFilePathResolver.java @@ -62,7 +62,7 @@ public Path resolveArchiveRawPathToBlock(final long blockNumber) { @NonNull @Override - public Optional findBlock(final long blockNumber) { // todo add archive root search & abstract if common + public Optional findBlock(final long blockNumber) { Preconditions.requireWhole(blockNumber); final Path liveRawRootPath = resolveLiveRawPathToBlock(blockNumber); final Path compressionExtendedLiveRawRootPath = @@ -74,5 +74,6 @@ public Optional findBlock(final long blockNumber) { // todo add archive ro } else { return Optional.empty(); } - } + } // todo consider to add additional handling here, like test for other compression types (currently not existing) + // and also look for archived blocks (will be implemented in a follow-up PR) } diff --git a/server/src/test/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalDirPathResolverTest.java b/server/src/test/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalDirPathResolverTest.java index 92767d0a..562979f2 100644 --- a/server/src/test/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalDirPathResolverTest.java +++ b/server/src/test/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalDirPathResolverTest.java @@ -9,10 +9,13 @@ import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; import com.hedera.block.server.util.TestConfigUtil; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; +import java.util.Optional; import java.util.stream.Stream; import org.assertj.core.api.Assertions; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; @@ -106,6 +109,71 @@ void testInvalidBlockNumberArchiveResolve(final long toResolve) { assertThatIllegalArgumentException().isThrownBy(() -> toTest.resolveArchiveRawPathToBlock(toResolve)); } + /** + * This test aims to verify that the + * {@link BlockAsLocalDirPathResolver#findBlock(long)} correctly finds a + * block with the given block number. + * + * @param blockNumber parameterized, valid block number + * @param expectedBlockFile parameterized, expected block file + */ + @ParameterizedTest + @MethodSource("validBlockNumbers") + void testSuccessfulFindBlockNoCompression(final long blockNumber, final String expectedBlockFile) + throws IOException { + final Path expected = testLiveRootPath.resolve(expectedBlockFile); + Files.createDirectories(expected.getParent()); + Files.createFile(expected); + + // assert block was created successfully + assertThat(expected).exists().isRegularFile().isReadable(); + + final Optional actual = toTest.findBlock(blockNumber); + assertThat(actual) + .isNotNull() + .isPresent() + .get(InstanceOfAssertFactories.PATH) + .isAbsolute() + .exists() + .isReadable() + .isRegularFile() + .isEqualByComparingTo(expected); + } + + /** + * This test aims to verify that the + * {@link BlockAsLocalDirPathResolver#findBlock(long)} correctly returns an + * empty {@link Optional} when a block with the given block number does not + * exist. + * + * @param blockNumber parameterized, valid block number + * @param expectedBlockFile parameterized, expected block file + */ + @ParameterizedTest + @MethodSource("validBlockNumbers") + void testBlockNotFound(final long blockNumber, final String expectedBlockFile) throws IOException { + final Path expected = testLiveRootPath.resolve(expectedBlockFile); + + // assert block does not exist + assertThat(expected).doesNotExist(); + + final Optional actual = toTest.findBlock(blockNumber); + assertThat(actual).isNotNull().isEmpty(); + } + + /** + * This test aims to verify that the + * {@link BlockAsLocalDirPathResolver#findBlock(long)} correctly throws an + * {@link IllegalArgumentException} when an invalid block number is invalid. + * + * @param blockNumber parameterized, invalid block number + */ + @ParameterizedTest + @MethodSource("invalidBlockNumbers") + void testInvalidBlockNumberFindBlock(final long blockNumber) { + assertThatIllegalArgumentException().isThrownBy(() -> toTest.findBlock(blockNumber)); + } + /** * Some valid block numbers. * diff --git a/server/src/test/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalFilePathResolverTest.java b/server/src/test/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalFilePathResolverTest.java index 5e23d169..7d72b01f 100644 --- a/server/src/test/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalFilePathResolverTest.java +++ b/server/src/test/java/com/hedera/block/server/persistence/storage/path/BlockAsLocalFilePathResolverTest.java @@ -7,12 +7,16 @@ import com.hedera.block.server.config.BlockNodeContext; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; +import com.hedera.block.server.persistence.storage.PersistenceStorageConfig.CompressionType; import com.hedera.block.server.util.TestConfigUtil; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; +import java.util.Optional; import java.util.stream.Stream; import org.assertj.core.api.Assertions; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; @@ -108,6 +112,103 @@ void testInvalidBlockNumberArchiveResolve(final long toResolve) { assertThatIllegalArgumentException().isThrownBy(() -> toTest.resolveArchiveRawPathToBlock(toResolve)); } + /** + * This test aims to verify that the + * {@link BlockAsLocalFilePathResolver#findBlock(long)} correctly finds a + * block by a given number, with no compression. + * + * @param blockNumber parameterized, valid block number + * @param expectedBlockFile parameterized, expected block file + */ + @ParameterizedTest + @MethodSource("validBlockNumbers") + void testSuccessfulFindBlockNoCompression(final long blockNumber, final String expectedBlockFile) + throws IOException { + final Path expected = testLiveRootPath.resolve(expectedBlockFile); + Files.createDirectories(expected.getParent()); + Files.createFile(expected); + + // assert block was created successfully + assertThat(expected).exists().isRegularFile().isReadable(); + + final Optional actual = toTest.findBlock(blockNumber); + assertThat(actual) + .isNotNull() + .isPresent() + .get(InstanceOfAssertFactories.PATH) + .isAbsolute() + .exists() + .isReadable() + .isRegularFile() + .isEqualByComparingTo(expected); + } + + /** + * This test aims to verify that the + * {@link BlockAsLocalFilePathResolver#findBlock(long)} correctly finds a + * block by a given number, with zstd compression. + * + * @param blockNumber parameterized, valid block number + * @param expectedBlockFile parameterized, expected block file + */ + @ParameterizedTest + @MethodSource("validBlockNumbers") + void testSuccessfulFindBlockZstdCompressed(final long blockNumber, final String expectedBlockFile) + throws IOException { + final String expectedBlockFileWithExtension = expectedBlockFile.concat(CompressionType.ZSTD.getFileExtension()); + final Path expected = testLiveRootPath.resolve(expectedBlockFileWithExtension); + Files.createDirectories(expected.getParent()); + Files.createFile(expected); + + // assert block was created successfully + assertThat(expected).exists().isRegularFile().isReadable(); + + final Optional actual = toTest.findBlock(blockNumber); + assertThat(actual) + .isNotNull() + .isPresent() + .get(InstanceOfAssertFactories.PATH) + .isAbsolute() + .exists() + .isReadable() + .isRegularFile() + .isEqualByComparingTo(expected); + } + + /** + * This test aims to verify that the + * {@link BlockAsLocalFilePathResolver#findBlock(long)} correctly returns an + * empty {@link Optional} when a block is not found. + * + * @param blockNumber parameterized, valid block number + * @param expectedBlockFile parameterized, expected block file + */ + @ParameterizedTest + @MethodSource("validBlockNumbers") + void testBlockNotFound(final long blockNumber, final String expectedBlockFile) throws IOException { + final Path expected = testLiveRootPath.resolve(expectedBlockFile); + + // assert block does not exist + assertThat(expected).doesNotExist(); + + final Optional actual = toTest.findBlock(blockNumber); + assertThat(actual).isNotNull().isEmpty(); + } + + /** + * This test aims to verify that the + * {@link BlockAsLocalFilePathResolver#findBlock(long)} correctly throws an + * {@link IllegalArgumentException} when an invalid block number + * is provided. + * + * @param blockNumber parameterized, invalid block number + */ + @ParameterizedTest + @MethodSource("invalidBlockNumbers") + void testInvalidBlockNumberFindBlock(final long blockNumber) { + assertThatIllegalArgumentException().isThrownBy(() -> toTest.findBlock(blockNumber)); + } + /** * Some valid block numbers. *