Skip to content

Commit 2b35570

Browse files
committed
Little help on test coverage for SPI and Verification plugins.
Signed-off-by: jasperpotts <[email protected]>
1 parent 031b2cf commit 2b35570

File tree

7 files changed

+159
-38
lines changed

7 files changed

+159
-38
lines changed

block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/plugintest/AllwaysRunningHealthFacility.java

Lines changed: 0 additions & 28 deletions
This file was deleted.

block-node/app/src/testFixtures/java/org/hiero/block/node/app/fixtures/plugintest/PluginTestBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public PluginTestBase(P plugin, HistoricalBlockFacility historicalBlockFacility)
5252
final Metrics metrics = metricsProvider.createGlobalMetrics();
5353
metricsProvider.start();
5454
// mock health facility
55-
final HealthFacility healthFacility = new AllwaysRunningHealthFacility();
55+
final HealthFacility healthFacility = new TestHealthFacility();
5656
// create block node context
5757
blockNodeContext = new BlockNodeContext() {
5858
@Override
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
package org.hiero.block.node.app.fixtures.plugintest;
3+
4+
import java.lang.System.Logger.Level;
5+
import java.util.concurrent.atomic.AtomicBoolean;
6+
import org.hiero.block.node.spi.health.HealthFacility;
7+
8+
/**
9+
* A testing {@link HealthFacility} that always returns {@link State#RUNNING} for the block node state. And fails test
10+
* if the shutdown method is called.
11+
*/
12+
public class TestHealthFacility implements HealthFacility {
13+
/** The logger for this class. */
14+
private final System.Logger LOGGER = System.getLogger(getClass().getName());
15+
/** Track if shutdown method was called, for tests that need to know. */
16+
public final AtomicBoolean shutdownCalled = new AtomicBoolean(false);
17+
/** If the node is running. Can be set by tests that need it to be false */
18+
public final AtomicBoolean isRunning = new AtomicBoolean(true);
19+
20+
/**
21+
* {@inheritDoc}
22+
*/
23+
@Override
24+
public State blockNodeState() {
25+
return isRunning.get() ? State.RUNNING : State.SHUTTING_DOWN;
26+
}
27+
28+
/**
29+
* {@inheritDoc}
30+
*/
31+
@Override
32+
public void shutdown(String className, String reason) {
33+
LOGGER.log(Level.ERROR, "Shutting down " + className + " " + reason);
34+
shutdownCalled.set(true);
35+
isRunning.set(false);
36+
}
37+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
package org.hiero.block.node.spi.historicalblocks;
3+
4+
import static org.hiero.block.node.spi.BlockNodePlugin.UNKNOWN_BLOCK_NUMBER;
5+
import static org.junit.jupiter.api.Assertions.assertEquals;
6+
import static org.junit.jupiter.api.Assertions.assertFalse;
7+
8+
import org.junit.jupiter.api.DisplayName;
9+
import org.junit.jupiter.api.Test;
10+
11+
/**
12+
* Test class for {@link BlockRangeSet}.
13+
*/
14+
class BlockRangeSetTest {
15+
16+
@Test
17+
@DisplayName("Test EMPTY set contains no block numbers")
18+
void testEmptySetContains() {
19+
final BlockRangeSet emptySet = BlockRangeSet.EMPTY;
20+
21+
assertFalse(emptySet.contains(1), "EMPTY set should not contain any block number");
22+
assertFalse(emptySet.contains(0, 10), "EMPTY set should not contain any range");
23+
}
24+
25+
@Test
26+
@DisplayName("Test EMPTY set size is zero")
27+
void testEmptySetSize() {
28+
final BlockRangeSet emptySet = BlockRangeSet.EMPTY;
29+
30+
assertEquals(0, emptySet.size(), "EMPTY set size should be zero");
31+
}
32+
33+
@Test
34+
@DisplayName("Test EMPTY set min and max return UNKNOWN_BLOCK_NUMBER")
35+
void testEmptySetMinMax() {
36+
final BlockRangeSet emptySet = BlockRangeSet.EMPTY;
37+
38+
assertEquals(UNKNOWN_BLOCK_NUMBER, emptySet.min(), "EMPTY set min should return UNKNOWN_BLOCK_NUMBER");
39+
assertEquals(UNKNOWN_BLOCK_NUMBER, emptySet.max(), "EMPTY set max should return UNKNOWN_BLOCK_NUMBER");
40+
}
41+
42+
@Test
43+
@DisplayName("Test EMPTY set stream is empty")
44+
void testEmptySetStream() {
45+
final BlockRangeSet emptySet = BlockRangeSet.EMPTY;
46+
47+
assertEquals(0, emptySet.stream().count(), "Stream from EMPTY set should be empty");
48+
}
49+
50+
@Test
51+
@DisplayName("Test EMPTY set streamRanges is empty")
52+
void testEmptySetStreamRanges() {
53+
final BlockRangeSet emptySet = BlockRangeSet.EMPTY;
54+
55+
assertEquals(0, emptySet.streamRanges().count(), "Stream of ranges from EMPTY set should be empty");
56+
}
57+
58+
@Test
59+
@DisplayName("Test EMPTY set edge cases")
60+
void testEmptySetEdgeCases() {
61+
final BlockRangeSet emptySet = BlockRangeSet.EMPTY;
62+
63+
assertFalse(emptySet.contains(Long.MIN_VALUE), "EMPTY set should not contain Long.MIN_VALUE");
64+
assertFalse(emptySet.contains(Long.MAX_VALUE), "EMPTY set should not contain Long.MAX_VALUE");
65+
assertFalse(emptySet.contains(Long.MIN_VALUE, Long.MAX_VALUE), "EMPTY set should not contain full range");
66+
}
67+
}

block-node/verification/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ mainModuleInfo {
1717
testModuleInfo {
1818
requires("org.junit.jupiter.api")
1919
requires("org.hiero.block.node.app.test.fixtures")
20+
requires("org.mockito")
2021
}

block-node/verification/src/main/java/org/hiero/block/node/verification/VerificationServicePlugin.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,4 @@ public void handleBlockItemsReceived(BlockItems blockItems) {
145145
context.serverHealth().shutdown(VerificationServicePlugin.class.getSimpleName(), e.getMessage());
146146
}
147147
}
148-
149-
public VerificationConfig verificationConfig() {
150-
return verificationConfig;
151-
}
152-
153-
public void setVerificationConfig(VerificationConfig verificationConfig) {
154-
this.verificationConfig = verificationConfig;
155-
}
156148
}

block-node/verification/src/test/java/org/hiero/block/node/verification/VerificationServicePluginTest.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,29 @@
44
import static org.junit.jupiter.api.Assertions.assertEquals;
55
import static org.junit.jupiter.api.Assertions.assertNotEquals;
66
import static org.junit.jupiter.api.Assertions.assertNotNull;
7+
import static org.junit.jupiter.api.Assertions.assertTrue;
8+
import static org.mockito.Mockito.mock;
9+
import static org.mockito.Mockito.when;
710

11+
import com.hedera.pbj.runtime.OneOf;
812
import com.hedera.pbj.runtime.ParseException;
913
import java.io.IOException;
1014
import java.util.List;
1115
import org.hiero.block.node.app.fixtures.blocks.BlockUtils;
1216
import org.hiero.block.node.app.fixtures.plugintest.NoBlocksHistoricalBlockFacility;
1317
import org.hiero.block.node.app.fixtures.plugintest.PluginTestBase;
18+
import org.hiero.block.node.app.fixtures.plugintest.TestHealthFacility;
1419
import org.hiero.block.node.spi.blockmessaging.BlockItems;
1520
import org.hiero.block.node.spi.blockmessaging.BlockNotification;
1621
import org.hiero.hapi.block.node.BlockItemUnparsed;
22+
import org.hiero.hapi.block.node.BlockItemUnparsed.ItemOneOfType;
23+
import org.junit.jupiter.api.DisplayName;
1724
import org.junit.jupiter.api.Test;
1825

19-
class VerificationServicePluginTest extends PluginTestBase {
26+
/**
27+
* Unit test for {@link VerificationServicePlugin}.
28+
*/
29+
class VerificationServicePluginTest extends PluginTestBase<VerificationServicePlugin> {
2030

2131
public VerificationServicePluginTest() {
2232
super(new VerificationServicePlugin(), new NoBlocksHistoricalBlockFacility());
@@ -82,4 +92,46 @@ void testFailedVerification() throws IOException, ParseException {
8292
blockNotification.blockHash(),
8393
"The block hash should NOT be the same");
8494
}
95+
96+
@Test
97+
@DisplayName("Test handleBlockItemsReceived without a block header")
98+
void testHandleBlockItemsReceived_NoCurrentSession() throws IOException, ParseException {
99+
// create sample block data
100+
BlockUtils.SampleBlockInfo sampleBlockInfo =
101+
BlockUtils.getSampleBlockInfo(BlockUtils.SAMPLE_BLOCKS.GENERATED_10);
102+
long blockNumber = sampleBlockInfo.blockNumber();
103+
List<BlockItemUnparsed> blockItems = sampleBlockInfo.blockUnparsed().blockItems();
104+
// remove the header to simulate a case where receive items and have never received a header
105+
blockItems.removeFirst();
106+
// send some items to the plugin, they should be ignored
107+
plugin.handleBlockItemsReceived(new BlockItems(blockItems, blockNumber));
108+
// check we did not receive a block verification
109+
assertEquals(0, blockMessaging.getSentBlockNotifications().size());
110+
}
111+
112+
@Test
113+
@DisplayName("Test handleBlockItemsReceived with non-running server")
114+
void testHandleBlockItemsReceived_NotRunning() {
115+
// make the server state not running
116+
((TestHealthFacility) blockNodeContext.serverHealth()).isRunning.set(false);
117+
// send some items to the plugin, they should be ignored
118+
plugin.handleBlockItemsReceived(
119+
new BlockItems(List.of(new BlockItemUnparsed(new OneOf<>(ItemOneOfType.BLOCK_HEADER, null))), -1));
120+
// check we did not receive a block verification
121+
assertEquals(0, blockMessaging.getSentBlockNotifications().size());
122+
}
123+
124+
@Test
125+
@DisplayName("Test handleBlockItemsReceived with BlockItems that throws an exception")
126+
void testHandleBlockItemsReceived_ExceptionThrown() {
127+
// mock a BlockItems object to throw an exception when isStartOfNewBlock is called
128+
BlockItems blockItems = mock(BlockItems.class);
129+
when(blockItems.isStartOfNewBlock()).thenThrow(new RuntimeException("Test Exception"));
130+
// sent the mocked BlockItems to the plugin
131+
plugin.handleBlockItemsReceived(blockItems);
132+
// check the exception was thrown and resulted in a shutdown
133+
assertTrue(
134+
((TestHealthFacility) blockNodeContext.serverHealth()).shutdownCalled.get(),
135+
"The server should be shutdown after an exception is thrown");
136+
}
85137
}

0 commit comments

Comments
 (0)