From 7089887732f9bf6207e0534d1e98cbabbc22841a Mon Sep 17 00:00:00 2001 From: Nana Essilfie-Conduah Date: Mon, 21 Jul 2025 23:30:34 -0400 Subject: [PATCH 1/4] Remove BlockAcknowledgement.block_root_hash from Publisher API Signed-off-by: Nana Essilfie-Conduah --- .../api/block_stream_publish_service.proto | 9 ---- .../grpc/impl/PublishStreamObserver.java | 3 +- .../startup/SimulatorStartupData.java | 3 +- .../impl/SimulatorStartupDataImpl.java | 3 +- .../impl/SimulatorStartupDataImplTest.java | 51 ++----------------- 5 files changed, 7 insertions(+), 62 deletions(-) diff --git a/protobuf-sources/src/main/proto/block-node/api/block_stream_publish_service.proto b/protobuf-sources/src/main/proto/block-node/api/block_stream_publish_service.proto index 1e6a9db35..cb9246ec4 100644 --- a/protobuf-sources/src/main/proto/block-node/api/block_stream_publish_service.proto +++ b/protobuf-sources/src/main/proto/block-node/api/block_stream_publish_service.proto @@ -230,15 +230,6 @@ message PublishStreamResponse { * one greater than this value. */ uint64 block_number = 1; - - /** - * A hash of the virtual merkle root for the block. - *

- * This SHALL be the hash calculated by the Block-Node for the - * root node of the virtual merkle tree that is signed by the source - * system to validate the block. - */ - bytes block_root_hash = 2; } /** diff --git a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserver.java b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserver.java index ed978f79e..bd93a531a 100644 --- a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserver.java +++ b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserver.java @@ -66,8 +66,7 @@ public void onNext(final PublishStreamResponse publishStreamResponse) { if (publishStreamResponse.hasAcknowledgement()) { final BlockAcknowledgement ack = publishStreamResponse.getAcknowledgement(); try { - startupData.updateLatestAckBlockStartupData( - ack.getBlockNumber(), ack.getBlockRootHash().toByteArray()); + startupData.updateLatestAckBlockStartupData(ack.getBlockNumber()); } catch (final IOException e) { throw new UncheckedIOException(e); } diff --git a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/SimulatorStartupData.java b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/SimulatorStartupData.java index e192e178c..75eda423f 100644 --- a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/SimulatorStartupData.java +++ b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/SimulatorStartupData.java @@ -23,10 +23,9 @@ public interface SimulatorStartupData { * response. At the next startup of the application, values based on the * last update will be used for initialization. * @param blockNumber the block number to update the startup data with - * @param blockHash the block hash to update the startup data with * @throws IOException if an error occurs while updating the startup data */ - void updateLatestAckBlockStartupData(final long blockNumber, final byte[] blockHash) throws IOException; + void updateLatestAckBlockStartupData(final long blockNumber) throws IOException; /** * This method returns the latest acknowledged block number based on startup diff --git a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java index 85c185491..240125318 100644 --- a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java +++ b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java @@ -104,13 +104,12 @@ public boolean isEnabled() { } @Override - public void updateLatestAckBlockStartupData(final long blockNumber, final byte[] blockHash) throws IOException { + public void updateLatestAckBlockStartupData(final long blockNumber) throws IOException { if (enabled) { // @todo(904) we need the correct response code, currently it seems that // the response code is not being set correctly? The if check should // be different and based on the response code, only saving Files.write(latestAckBlockNumberPath, String.valueOf(blockNumber).getBytes()); - Files.write(latestAckBlockHashPath, blockHash); LOGGER.log(DEBUG, "Updated startup data for latest ack block with number: {0}", blockNumber); } } diff --git a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java index 1267270cc..e4c31d80f 100644 --- a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java +++ b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java @@ -25,18 +25,11 @@ class SimulatorStartupDataImplTest { @TempDir private Path tempDir; - private byte[] validSimulatedBlockHash; private Path latestAckBlockNumberPath; - private Path latestAckBlockHashPath; @BeforeEach void setup() { - validSimulatedBlockHash = new byte[StreamingTreeHasher.HASH_LENGTH]; - for (byte i = 0; i < StreamingTreeHasher.HASH_LENGTH; i++) { - validSimulatedBlockHash[i] = i; - } latestAckBlockNumberPath = tempDir.resolve("latestAckBlockNumber"); - latestAckBlockHashPath = tempDir.resolve("latestAckBlockHash"); } /** @@ -57,7 +50,6 @@ private SimulatorStartupDataImpl newInstanceToTest(final boolean enabled) { .withConfigDataType(SimulatorStartupDataConfig.class) .withValue("simulator.startup.data.enabled", enabled ? "true" : "false") .withValue("simulator.startup.data.latestAckBlockNumberPath", latestAckBlockNumberPath.toString()) - .withValue("simulator.startup.data.latestAckBlockHashPath", latestAckBlockHashPath.toString()) .build(); final BlockGeneratorConfig blockGeneratorConfig = configuration.getConfigData(BlockGeneratorConfig.class); final SimulatorStartupDataConfig simulatorStartupDataConfig = @@ -73,10 +65,8 @@ private SimulatorStartupDataImpl newInstanceToTest(final boolean enabled) { @Test void testInitializationWhenDisabled() { assertThat(latestAckBlockNumberPath).doesNotExist(); - assertThat(latestAckBlockHashPath).doesNotExist(); newInstanceToTest(false); assertThat(latestAckBlockNumberPath).doesNotExist(); - assertThat(latestAckBlockHashPath).doesNotExist(); } /** @@ -87,7 +77,6 @@ void testInitializationWhenDisabled() { @Test void testInitializationWhenEnabled() { assertThat(latestAckBlockNumberPath).doesNotExist(); - assertThat(latestAckBlockHashPath).doesNotExist(); newInstanceToTest(true); assertThat(latestAckBlockNumberPath) .exists() @@ -95,12 +84,6 @@ void testInitializationWhenEnabled() { .isReadable() .isWritable() .isEmptyFile(); - assertThat(latestAckBlockHashPath) - .exists() - .isRegularFile() - .isReadable() - .isWritable() - .isEmptyFile(); } /** @@ -109,7 +92,6 @@ void testInitializationWhenEnabled() { */ @Test void testDefaultValues() { - assertThat(latestAckBlockHashPath).doesNotExist(); assertThat(latestAckBlockNumberPath).doesNotExist(); final SimulatorStartupDataImpl toTest = newInstanceToTest(false); assertThat(toTest) @@ -126,7 +108,6 @@ void testDefaultValues() { */ @Test void testDefaultValuesIfInitialStartup() { - assertThat(latestAckBlockHashPath).doesNotExist(); assertThat(latestAckBlockNumberPath).doesNotExist(); final SimulatorStartupDataImpl toTest = newInstanceToTest(true); assertThat(toTest) @@ -144,11 +125,8 @@ void testDefaultValuesIfInitialStartup() { @Test void testCorrectValuesStartup() throws IOException { Files.write(latestAckBlockNumberPath, "1".getBytes()); - Files.write(latestAckBlockHashPath, validSimulatedBlockHash); final SimulatorStartupDataImpl toTest = newInstanceToTest(true); - assertThat(toTest) - .returns(1L, from(SimulatorStartupDataImpl::getLatestAckBlockNumber)) - .returns(validSimulatedBlockHash, from(SimulatorStartupDataImpl::getLatestAckBlockHash)); + assertThat(toTest).returns(1L, from(SimulatorStartupDataImpl::getLatestAckBlockNumber)); } /** @@ -158,7 +136,6 @@ void testCorrectValuesStartup() throws IOException { @Test void testFailedInitializationUnavailableHashFile() throws IOException { Files.write(latestAckBlockNumberPath, "1".getBytes()); - assertThat(latestAckBlockHashPath).doesNotExist(); assertThatIllegalStateException().isThrownBy(() -> newInstanceToTest(true)); } @@ -169,7 +146,6 @@ void testFailedInitializationUnavailableHashFile() throws IOException { @Test void testFailedInitializationUnavailableBlockNumberFile() throws IOException { assertThat(latestAckBlockNumberPath).doesNotExist(); - Files.write(latestAckBlockHashPath, validSimulatedBlockHash); assertThatIllegalStateException().isThrownBy(() -> newInstanceToTest(true)); } @@ -181,7 +157,6 @@ void testFailedInitializationUnavailableBlockNumberFile() throws IOException { @Test void testFailedInitializationWrongNumberFormat() throws IOException { Files.write(latestAckBlockNumberPath, "wrongNumberFormat".getBytes()); - Files.write(latestAckBlockHashPath, validSimulatedBlockHash); assertThatExceptionOfType(NumberFormatException.class).isThrownBy(() -> newInstanceToTest(true)); } @@ -193,34 +168,29 @@ void testFailedInitializationWrongNumberFormat() throws IOException { @Test void testFailedInitializationWrongHashLength() throws IOException { Files.write(latestAckBlockNumberPath, "1".getBytes()); - Files.write(latestAckBlockHashPath, new byte[StreamingTreeHasher.HASH_LENGTH - 1]); assertThatIllegalStateException().isThrownBy(() -> newInstanceToTest(true)); } /** * This test aims to verify that the - * {@link SimulatorStartupDataImpl#updateLatestAckBlockStartupData(long, byte[])} + * {@link SimulatorStartupDataImpl#updateLatestAckBlockStartupData(long)} * will correctly not update the startup data if the functionality is disabled. */ @Test void testUpdateStartupDataDisabled() throws IOException { - assertThat(latestAckBlockHashPath).doesNotExist(); assertThat(latestAckBlockNumberPath).doesNotExist(); final SimulatorStartupDataImpl toTest = newInstanceToTest(false); assertThat(toTest.isEnabled()).isFalse(); - toTest.updateLatestAckBlockStartupData(1L, validSimulatedBlockHash); - assertThat(latestAckBlockHashPath).doesNotExist(); assertThat(latestAckBlockNumberPath).doesNotExist(); } /** * This test aims to verify that the - * {@link SimulatorStartupDataImpl#updateLatestAckBlockStartupData(long, byte[])} + * {@link SimulatorStartupDataImpl#updateLatestAckBlockStartupData(long)} * will correctly update the startup data if the functionality is enabled. */ @Test void testUpdateStartupDataEnabled() throws IOException { - assertThat(latestAckBlockHashPath).doesNotExist(); assertThat(latestAckBlockNumberPath).doesNotExist(); final SimulatorStartupDataImpl toTest = newInstanceToTest(true); assertThat(toTest.isEnabled()).isTrue(); @@ -230,14 +200,8 @@ void testUpdateStartupDataEnabled() throws IOException { .isReadable() .isWritable() .isEmptyFile(); - assertThat(latestAckBlockHashPath) - .exists() - .isRegularFile() - .isReadable() - .isWritable() - .isEmptyFile(); // @todo(904) we need the correct response code - toTest.updateLatestAckBlockStartupData(1L, validSimulatedBlockHash); + toTest.updateLatestAckBlockStartupData(1L); assertThat(latestAckBlockNumberPath) .exists() .isRegularFile() @@ -245,12 +209,5 @@ void testUpdateStartupDataEnabled() throws IOException { .isWritable() .isNotEmptyFile() .hasBinaryContent("1".getBytes()); - assertThat(latestAckBlockHashPath) - .exists() - .isRegularFile() - .isReadable() - .isWritable() - .isNotEmptyFile() - .hasBinaryContent(validSimulatedBlockHash); } } From f5e379ba12272799390188455a8621fc76469708 Mon Sep 17 00:00:00 2001 From: Nana Essilfie-Conduah Date: Mon, 21 Jul 2025 23:45:51 -0400 Subject: [PATCH 2/4] Remove failure logic around block hash file Signed-off-by: Nana Essilfie-Conduah --- .../impl/SimulatorStartupDataImpl.java | 24 ++------------ .../impl/SimulatorStartupDataImplTest.java | 32 ------------------- 2 files changed, 2 insertions(+), 54 deletions(-) diff --git a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java index 240125318..1db15ae2f 100644 --- a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java +++ b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java @@ -20,7 +20,6 @@ public final class SimulatorStartupDataImpl implements SimulatorStartupData { private final System.Logger LOGGER = System.getLogger(SimulatorStartupDataImpl.class.getName()); private final boolean enabled; private final Path latestAckBlockNumberPath; - private final Path latestAckBlockHashPath; private final long startupDataBlockNumber; private final byte[] startupDataBlockHash; @@ -30,32 +29,20 @@ public SimulatorStartupDataImpl( @NonNull final BlockGeneratorConfig blockGeneratorConfig) { this.enabled = simulatorStartupDataConfig.enabled(); this.latestAckBlockNumberPath = simulatorStartupDataConfig.latestAckBlockNumberPath(); - this.latestAckBlockHashPath = simulatorStartupDataConfig.latestAckBlockHashPath(); long localStartupDataBlockNumber = blockGeneratorConfig.startBlockNumber() - 1L; byte[] localStartupDataBlockHash = new byte[StreamingTreeHasher.HASH_LENGTH]; if (enabled) { try { final int existsLatestAckBlockNumberFile = Files.exists(latestAckBlockNumberPath) ? 1 : 0; - final int existsLatestAckBlockHashFile = Files.exists(latestAckBlockHashPath) ? 1 : 0; - // determine the number of existing startup data files - final int existingStartupDataFileCount = existsLatestAckBlockNumberFile + existsLatestAckBlockHashFile; - switch (existingStartupDataFileCount) { + // manage presence of data file + switch (existsLatestAckBlockNumberFile) { case 0 -> { // if no startup data files exist, this means that this // is the initial setup, we only need to create the // startup data files FileUtilities.createFile(latestAckBlockNumberPath); - FileUtilities.createFile(latestAckBlockHashPath); } case 1 -> { - // if only one file exists, then this is an erroneous - // state. We must investigate why this is happening. - // Generally we never ever expect to enter here, but - // we cannot continue to initialize the simulator - throw new IllegalStateException( - "Failed to initialize Simulator Startup Data, only one startup data file exists!"); - } - case 2 -> { // entering here means that both files exist, so now we // must attempt to read the startup data from the files. // If successful, we can finish initialization, otherwise @@ -67,13 +54,6 @@ public SimulatorStartupDataImpl( throw new IllegalStateException( "Failed to initialize latest ack block number from Simulator Startup Data"); } - final byte[] previousHashFromFile = Files.readAllBytes(latestAckBlockHashPath); - if (previousHashFromFile.length == StreamingTreeHasher.HASH_LENGTH) { - localStartupDataBlockHash = previousHashFromFile; - } else { - throw new IllegalStateException( - "Failed to initialize latest ack block hash from Simulator Startup Data"); - } } default -> throw new IllegalStateException( diff --git a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java index e4c31d80f..e9e419be2 100644 --- a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java +++ b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.from; import com.swirlds.config.api.Configuration; @@ -129,26 +128,6 @@ void testCorrectValuesStartup() throws IOException { assertThat(toTest).returns(1L, from(SimulatorStartupDataImpl::getLatestAckBlockNumber)); } - /** - * This test aims to verify that the {@link SimulatorStartupDataImpl} will - * fail initialization if only the block number startup data file exists. - */ - @Test - void testFailedInitializationUnavailableHashFile() throws IOException { - Files.write(latestAckBlockNumberPath, "1".getBytes()); - assertThatIllegalStateException().isThrownBy(() -> newInstanceToTest(true)); - } - - /** - * This test aims to verify that the {@link SimulatorStartupDataImpl} will - * fail initialization if only the block hash startup data file exists. - */ - @Test - void testFailedInitializationUnavailableBlockNumberFile() throws IOException { - assertThat(latestAckBlockNumberPath).doesNotExist(); - assertThatIllegalStateException().isThrownBy(() -> newInstanceToTest(true)); - } - /** * This test aims to verify that the {@link SimulatorStartupDataImpl} will * fail initialization if the block number startup data file contains an @@ -160,17 +139,6 @@ void testFailedInitializationWrongNumberFormat() throws IOException { assertThatExceptionOfType(NumberFormatException.class).isThrownBy(() -> newInstanceToTest(true)); } - /** - * This test aims to verify that the {@link SimulatorStartupDataImpl} will - * fail initialization if the block hash startup data file contains an invalid - * hash length. - */ - @Test - void testFailedInitializationWrongHashLength() throws IOException { - Files.write(latestAckBlockNumberPath, "1".getBytes()); - assertThatIllegalStateException().isThrownBy(() -> newInstanceToTest(true)); - } - /** * This test aims to verify that the * {@link SimulatorStartupDataImpl#updateLatestAckBlockStartupData(long)} From d5e582ee2a882a248116230d025c4547155046da Mon Sep 17 00:00:00 2001 From: Nana Essilfie-Conduah Date: Tue, 22 Jul 2025 01:04:59 -0400 Subject: [PATCH 3/4] Fix tests and increase coverage Signed-off-by: Nana Essilfie-Conduah --- .../impl/SimulatorStartupDataImpl.java | 39 +++++++------------ .../grpc/impl/PublishStreamObserverTest.java | 25 +++++++++++- .../impl/SimulatorStartupDataImplTest.java | 12 ++++++ 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java index 1db15ae2f..2d6e36c70 100644 --- a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java +++ b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java @@ -33,31 +33,22 @@ public SimulatorStartupDataImpl( byte[] localStartupDataBlockHash = new byte[StreamingTreeHasher.HASH_LENGTH]; if (enabled) { try { - final int existsLatestAckBlockNumberFile = Files.exists(latestAckBlockNumberPath) ? 1 : 0; - // manage presence of data file - switch (existsLatestAckBlockNumberFile) { - case 0 -> { - // if no startup data files exist, this means that this - // is the initial setup, we only need to create the - // startup data files - FileUtilities.createFile(latestAckBlockNumberPath); - } - case 1 -> { - // entering here means that both files exist, so now we - // must attempt to read the startup data from the files. - // If successful, we can finish initialization, otherwise - // we have broken state and cannot continue. - final String blockNumberFromFile = Files.readString(latestAckBlockNumberPath); - if (!StringUtilities.isBlank(blockNumberFromFile)) { - localStartupDataBlockNumber = Long.parseLong(blockNumberFromFile); - } else { - throw new IllegalStateException( - "Failed to initialize latest ack block number from Simulator Startup Data"); - } - } - default -> + if (!Files.exists(latestAckBlockNumberPath)) { + // if no startup data files exist, this means that this + // is the initial setup, we only need to create the + // startup data files + Files.createFile(latestAckBlockNumberPath); + } else { + // data from the files. + // If successful, we can finish initialization, otherwise + // we have broken state and cannot continue. + final String blockNumberFromFile = Files.readString(latestAckBlockNumberPath); + if (!StringUtilities.isBlank(blockNumberFromFile)) { + localStartupDataBlockNumber = Long.parseLong(blockNumberFromFile); + } else { throw new IllegalStateException( - "Failed to initialize Simulator Startup Data, invalid number of startup data files!"); + "Failed to initialize latest ack block number from Simulator Startup Data"); + } } } catch (final IOException e) { throw new UncheckedIOException(e); diff --git a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserverTest.java b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserverTest.java index c3277f739..954a54042 100644 --- a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserverTest.java +++ b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserverTest.java @@ -4,7 +4,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doThrow; +import java.io.IOException; +import java.io.UncheckedIOException; import java.util.ArrayDeque; import java.util.concurrent.atomic.AtomicBoolean; import org.hiero.block.api.protoc.PublishStreamResponse; @@ -21,7 +26,9 @@ class PublishStreamObserverTest { @Test void onNext() { - PublishStreamResponse response = PublishStreamResponse.newBuilder().build(); + PublishStreamResponse response = PublishStreamResponse.newBuilder().setAcknowledgement( + PublishStreamResponse.BlockAcknowledgement.newBuilder().setBlockNumber(12345L) + ).build(); AtomicBoolean streamEnabled = new AtomicBoolean(true); ArrayDeque lastKnownStatuses = new ArrayDeque<>(); final int lastKnownStatusesCapacity = 10; @@ -58,4 +65,20 @@ void onCompleted() { assertTrue(streamEnabled.get(), "streamEnabled should remain true after onCompleted"); assertEquals(0, lastKnownStatuses.size(), "lastKnownStatuses should not have elements after onCompleted"); } + + @Test + void verifyUpdateLatestAckBlockStartupDataHandlesIOException() throws Exception { + PublishStreamResponse response = PublishStreamResponse.newBuilder().setAcknowledgement( + PublishStreamResponse.BlockAcknowledgement.newBuilder().setBlockNumber(12345L) + ).build(); + AtomicBoolean streamEnabled = new AtomicBoolean(true); + ArrayDeque lastKnownStatuses = new ArrayDeque<>(); + final int lastKnownStatusesCapacity = 10; + PublishStreamObserver publishStreamObserver = + new PublishStreamObserver(startupDataMock, streamEnabled, lastKnownStatuses, lastKnownStatusesCapacity); + + doThrow(new IOException("Test exception")).when(startupDataMock).updateLatestAckBlockStartupData(anyLong()); + + assertThrows(UncheckedIOException.class, () -> publishStreamObserver.onNext(response)); + } } diff --git a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java index e9e419be2..a2c5e6d0d 100644 --- a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java +++ b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.from; import com.swirlds.config.api.Configuration; @@ -128,6 +129,17 @@ void testCorrectValuesStartup() throws IOException { assertThat(toTest).returns(1L, from(SimulatorStartupDataImpl::getLatestAckBlockNumber)); } + + /** + * This test aims to verify that the {@link SimulatorStartupDataImpl} will + * fail initialization if only the block number startup data file exists. + */ + @Test + void testFailedInitializationUnavailableHashFile() throws IOException { + Files.write(latestAckBlockNumberPath, "".getBytes()); + assertThatIllegalStateException().isThrownBy(() -> newInstanceToTest(true)); + } + /** * This test aims to verify that the {@link SimulatorStartupDataImpl} will * fail initialization if the block number startup data file contains an From f741574f6f76716bfb22ebacd986583020746ba3 Mon Sep 17 00:00:00 2001 From: Nana Essilfie-Conduah Date: Tue, 22 Jul 2025 01:10:28 -0400 Subject: [PATCH 4/4] Ran spotless Signed-off-by: Nana Essilfie-Conduah --- .../startup/impl/SimulatorStartupDataImpl.java | 1 - .../grpc/impl/PublishStreamObserverTest.java | 16 +++++++++------- .../impl/SimulatorStartupDataImplTest.java | 5 ++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java index 2d6e36c70..3fe491f82 100644 --- a/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java +++ b/tools-and-tests/simulator/src/main/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImpl.java @@ -10,7 +10,6 @@ import java.nio.file.Path; import javax.inject.Inject; import org.hiero.block.common.hasher.StreamingTreeHasher; -import org.hiero.block.common.utils.FileUtilities; import org.hiero.block.common.utils.StringUtilities; import org.hiero.block.simulator.config.data.BlockGeneratorConfig; import org.hiero.block.simulator.config.data.SimulatorStartupDataConfig; diff --git a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserverTest.java b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserverTest.java index 954a54042..02d212ef5 100644 --- a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserverTest.java +++ b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/grpc/impl/PublishStreamObserverTest.java @@ -3,8 +3,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doThrow; @@ -26,9 +26,10 @@ class PublishStreamObserverTest { @Test void onNext() { - PublishStreamResponse response = PublishStreamResponse.newBuilder().setAcknowledgement( - PublishStreamResponse.BlockAcknowledgement.newBuilder().setBlockNumber(12345L) - ).build(); + PublishStreamResponse response = PublishStreamResponse.newBuilder() + .setAcknowledgement( + PublishStreamResponse.BlockAcknowledgement.newBuilder().setBlockNumber(12345L)) + .build(); AtomicBoolean streamEnabled = new AtomicBoolean(true); ArrayDeque lastKnownStatuses = new ArrayDeque<>(); final int lastKnownStatusesCapacity = 10; @@ -68,9 +69,10 @@ void onCompleted() { @Test void verifyUpdateLatestAckBlockStartupDataHandlesIOException() throws Exception { - PublishStreamResponse response = PublishStreamResponse.newBuilder().setAcknowledgement( - PublishStreamResponse.BlockAcknowledgement.newBuilder().setBlockNumber(12345L) - ).build(); + PublishStreamResponse response = PublishStreamResponse.newBuilder() + .setAcknowledgement( + PublishStreamResponse.BlockAcknowledgement.newBuilder().setBlockNumber(12345L)) + .build(); AtomicBoolean streamEnabled = new AtomicBoolean(true); ArrayDeque lastKnownStatuses = new ArrayDeque<>(); final int lastKnownStatusesCapacity = 10; diff --git a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java index a2c5e6d0d..c5b695651 100644 --- a/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java +++ b/tools-and-tests/simulator/src/test/java/org/hiero/block/simulator/startup/impl/SimulatorStartupDataImplTest.java @@ -129,13 +129,12 @@ void testCorrectValuesStartup() throws IOException { assertThat(toTest).returns(1L, from(SimulatorStartupDataImpl::getLatestAckBlockNumber)); } - /** * This test aims to verify that the {@link SimulatorStartupDataImpl} will - * fail initialization if only the block number startup data file exists. + * fail initialization if the block number startup data file exists with a blank value. */ @Test - void testFailedInitializationUnavailableHashFile() throws IOException { + void testFailedInitializationUnavailableBlockNumberFile() throws IOException { Files.write(latestAckBlockNumberPath, "".getBytes()); assertThatIllegalStateException().isThrownBy(() -> newInstanceToTest(true)); }