From e64faab05ffe39e3c668d68758eeb50ccd095c09 Mon Sep 17 00:00:00 2001 From: Thomas Moran <152873392+thomas-swirlds-labs@users.noreply.github.com> Date: Wed, 15 May 2024 09:44:51 +0100 Subject: [PATCH] chore: Improve unit test coverage on adding test coverage on CryptoCreateHandler (#13269) Signed-off-by: Thomas Moran <152873392+thomas-swirlds-labs@users.noreply.github.com> --- .../handlers/CryptoCreateHandlerTest.java | 82 +++++++++++++++---- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/hedera-node/hedera-token-service-impl/src/test/java/com/hedera/node/app/service/token/impl/test/handlers/CryptoCreateHandlerTest.java b/hedera-node/hedera-token-service-impl/src/test/java/com/hedera/node/app/service/token/impl/test/handlers/CryptoCreateHandlerTest.java index 66431edb4745..941aad86e074 100644 --- a/hedera-node/hedera-token-service-impl/src/test/java/com/hedera/node/app/service/token/impl/test/handlers/CryptoCreateHandlerTest.java +++ b/hedera-node/hedera-token-service-impl/src/test/java/com/hedera/node/app/service/token/impl/test/handlers/CryptoCreateHandlerTest.java @@ -31,10 +31,14 @@ import static com.hedera.hapi.node.base.ResponseCodeEnum.MEMO_TOO_LONG; import static com.hedera.hapi.node.base.ResponseCodeEnum.NOT_SUPPORTED; import static com.hedera.hapi.node.base.ResponseCodeEnum.PROXY_ACCOUNT_ID_FIELD_IS_DEPRECATED; +import static com.hedera.hapi.node.base.SubType.DEFAULT; import static com.hedera.node.app.service.token.impl.handlers.BaseCryptoHandler.asAccount; import static com.hedera.node.app.service.token.impl.test.handlers.util.StateBuilderUtil.ACCOUNTS; import static com.hedera.node.app.service.token.impl.test.handlers.util.StateBuilderUtil.ALIASES; +import static com.hedera.node.app.spi.fixtures.workflows.ExceptionConditions.responseCode; +import static com.hedera.test.utils.KeyUtils.A_COMPLEX_KEY; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -73,7 +77,9 @@ import com.hedera.node.app.service.token.records.CryptoCreateRecordBuilder; import com.hedera.node.app.spi.fees.FeeAccumulator; import com.hedera.node.app.spi.fees.FeeCalculator; +import com.hedera.node.app.spi.fees.FeeContext; import com.hedera.node.app.spi.fees.Fees; +import com.hedera.node.app.spi.fixtures.fees.FakeFeeCalculator; import com.hedera.node.app.spi.fixtures.workflows.FakePreHandleContext; import com.hedera.node.app.spi.info.NetworkInfo; import com.hedera.node.app.spi.info.NodeInfo; @@ -94,7 +100,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.Mock.Strictness; import org.mockito.junit.jupiter.MockitoExtension; /** @@ -105,12 +110,15 @@ class CryptoCreateHandlerTest extends CryptoHandlerTestBase { @Mock(strictness = LENIENT) private HandleContext handleContext; - @Mock(strictness = Strictness.LENIENT) + @Mock(strictness = LENIENT) private LongSupplier consensusSecondNow; @Mock(strictness = LENIENT) private GlobalDynamicProperties dynamicProperties; + @Mock(strictness = LENIENT) + private FeeContext feeContext; + @Mock private PropertySource compositeProps; @@ -176,16 +184,30 @@ public void setUp() { subject = new CryptoCreateHandler(cryptoCreateValidator, stakingValidator); } + @Test + @DisplayName("test CalculateFees When Free") + void testCalculateFeesWhenFree() { + var transactionBody = new CryptoCreateBuilder() + .withStakedAccountId(3) + .withMemo("blank") + .withKey(A_COMPLEX_KEY) + .build(); + feeCalculator = new FakeFeeCalculator(); + given(feeContext.body()).willReturn(transactionBody); + given(feeContext.feeCalculator(DEFAULT)).willReturn(feeCalculator); + final var result = subject.calculateFees(feeContext); + assertThat(result).isEqualTo(Fees.FREE); + } + @Test @DisplayName("preHandle works when there is a receiverSigRequired") void preHandleCryptoCreateVanilla() throws PreCheckException { final var context = new FakePreHandleContext(readableStore, txn); subject.pureChecks(txn); subject.preHandle(context); - - assertEquals(txn, context.body()); + assertThat(txn).isEqualTo(context.body()); basicMetaAssertions(context, 1); - assertEquals(key, context.payerKey()); + assertThat(key).isEqualTo(context.payerKey()); } @Test @@ -193,7 +215,7 @@ void preHandleCryptoCreateVanilla() throws PreCheckException { void whenInitialBalanceIsNegative() throws PreCheckException { txn = new CryptoCreateBuilder().withInitialBalance(-1L).build(); final var msg = assertThrows(PreCheckException.class, () -> subject.pureChecks(txn)); - assertEquals(INVALID_INITIAL_BALANCE, msg.responseCode()); + assertThat(INVALID_INITIAL_BALANCE).isEqualTo(msg.responseCode()); } @Test @@ -201,7 +223,7 @@ void whenInitialBalanceIsNegative() throws PreCheckException { void whenNoAutoRenewPeriodSpecified() throws PreCheckException { txn = new CryptoCreateBuilder().withNoAutoRenewPeriod().build(); final var msg = assertThrows(PreCheckException.class, () -> subject.pureChecks(txn)); - assertEquals(INVALID_RENEWAL_PERIOD, msg.responseCode()); + assertThat(INVALID_RENEWAL_PERIOD).isEqualTo(msg.responseCode()); } @Test @@ -216,7 +238,7 @@ void validateWhenZeroShardId() throws PreCheckException { void failsWhenInvalidMaxAutoAssociations() throws PreCheckException { txn = new CryptoCreateBuilder().withMaxAutoAssociations(-5).build(); final var msg = assertThrows(PreCheckException.class, () -> subject.pureChecks(txn)); - assertEquals(INVALID_TRANSACTION_BODY, msg.responseCode()); + assertThat(msg.responseCode()).isEqualTo(INVALID_TRANSACTION_BODY); } @Test @@ -224,7 +246,7 @@ void failsWhenInvalidMaxAutoAssociations() throws PreCheckException { void sendRecordThresholdIsNegative() throws PreCheckException { txn = new CryptoCreateBuilder().withSendRecordThreshold(-1).build(); final var msg = assertThrows(PreCheckException.class, () -> subject.pureChecks(txn)); - assertEquals(INVALID_SEND_RECORD_THRESHOLD, msg.responseCode()); + assertThat(msg.responseCode()).isEqualTo(INVALID_SEND_RECORD_THRESHOLD); } @Test @@ -232,7 +254,7 @@ void sendRecordThresholdIsNegative() throws PreCheckException { void receiveRecordThresholdIsNegative() throws PreCheckException { txn = new CryptoCreateBuilder().withReceiveRecordThreshold(-1).build(); final var msg = assertThrows(PreCheckException.class, () -> subject.pureChecks(txn)); - assertEquals(INVALID_RECEIVE_RECORD_THRESHOLD, msg.responseCode()); + assertThat(msg.responseCode()).isEqualTo(INVALID_RECEIVE_RECORD_THRESHOLD); } @Test @@ -240,7 +262,7 @@ void receiveRecordThresholdIsNegative() throws PreCheckException { void whenProxyAccountIdIsSpecified() throws PreCheckException { txn = new CryptoCreateBuilder().withProxyAccountNum(1).build(); final var msg = assertThrows(PreCheckException.class, () -> subject.pureChecks(txn)); - assertEquals(PROXY_ACCOUNT_ID_FIELD_IS_DEPRECATED, msg.responseCode()); + assertThat(msg.responseCode()).isEqualTo(PROXY_ACCOUNT_ID_FIELD_IS_DEPRECATED); } @Test @@ -250,10 +272,39 @@ void preHandleWorksWhenInitialBalanceIsZero() throws PreCheckException { final var context = new FakePreHandleContext(readableStore, txn); subject.pureChecks(txn); subject.preHandle(context); + assertThat(txn).isEqualTo(context.body()); + basicMetaAssertions(context, 1); + assertThat(key).isEqualTo(context.payerKey()); + } - assertEquals(txn, context.body()); + @Test + @DisplayName("preHandle succeeds when has non zero evm alias") + void preHandleWorksWhenHasEvmAlias() throws PreCheckException { + final byte[] evmAddress = CommonUtils.unhex("6aeb3773ea468a814d954e6dec795bfee7d76e26"); + txn = new CryptoCreateBuilder() + .withAlias(Bytes.wrap(evmAddress)) + .withStakedAccountId(3) + .build(); + final var context = new FakePreHandleContext(readableStore, txn); + subject.preHandle(context); + assertThat(txn).isEqualTo(context.body()); basicMetaAssertions(context, 1); - assertEquals(key, context.payerKey()); + assertThat(key).isEqualTo(context.payerKey()); + } + + @Test + @DisplayName("preHandle fails when invalid alias key") + void preHandleWorksWhenHasAlias() throws PreCheckException { + final Bytes SENDER_ALIAS = + Bytes.fromHex("3a21030edcc130e13fb5102e7c883535af8c2b0a5a617231f77fd127ce5f3b9a620591"); + txn = new CryptoCreateBuilder() + .withAlias(SENDER_ALIAS) + .withStakedAccountId(3) + .build(); + final var context = new FakePreHandleContext(readableStore, txn); + assertThatThrownBy(() -> subject.preHandle(context)) + .isInstanceOf(PreCheckException.class) + .has(responseCode(INVALID_ALIAS_KEY)); } @Test @@ -265,12 +316,11 @@ void noReceiverSigRequiredPreHandleCryptoCreate() throws PreCheckException { final var context = new FakePreHandleContext(readableStore, noReceiverSigTxn); subject.preHandle(context); - - assertEquals(expected.body(), context.body()); + assertThat(expected.body()).isEqualTo(context.body()); assertFalse(context.requiredNonPayerKeys().contains(key)); basicMetaAssertions(context, 0); assertThat(context.requiredNonPayerKeys()).isEmpty(); - assertEquals(key, context.payerKey()); + assertThat(key).isEqualTo(context.payerKey()); } @Test