|
2 | 2 | package com.hedera.services.yahcli.test.regression; |
3 | 3 |
|
4 | 4 | import static com.hedera.services.bdd.spec.HapiSpec.hapiTest; |
| 5 | +import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoCreate; |
| 6 | +import static com.hedera.services.bdd.spec.transactions.TxnVerbs.cryptoUpdate; |
5 | 7 | import static com.hedera.services.bdd.spec.utilops.CustomSpecAssert.allRunFor; |
6 | 8 | import static com.hedera.services.bdd.spec.utilops.UtilVerbs.doingContextual; |
7 | 9 | import static com.hedera.services.bdd.spec.utilops.UtilVerbs.newKeyNamed; |
| 10 | +import static com.hedera.services.bdd.spec.utilops.UtilVerbs.overriding; |
8 | 11 | import static com.hedera.services.bdd.spec.utilops.UtilVerbs.sourcingContextual; |
9 | 12 | import static com.hedera.services.yahcli.test.YahcliTestBase.REGRESSION; |
10 | 13 | import static com.hedera.services.yahcli.test.bdd.YahcliVerbs.asYcDefaultNetworkKey; |
|
14 | 17 | import static org.junit.jupiter.api.Assertions.assertTrue; |
15 | 18 |
|
16 | 19 | import com.hedera.services.bdd.junit.HapiTest; |
| 20 | +import com.hedera.services.bdd.junit.LeakyHapiTest; |
17 | 21 | import com.hedera.services.bdd.spec.keys.SigControl; |
| 22 | +import com.hedera.services.bdd.spec.utilops.ContextualActionOp; |
18 | 23 | import java.util.concurrent.atomic.AtomicLong; |
19 | 24 | import java.util.stream.Stream; |
20 | 25 | import org.junit.jupiter.api.DynamicTest; |
|
23 | 28 | @Tag(REGRESSION) |
24 | 29 | public class NodesCommandsTest { |
25 | 30 |
|
| 31 | + private int uniqueAdminKeyCounter = 0; |
| 32 | + |
26 | 33 | @HapiTest |
27 | 34 | final Stream<DynamicTest> basicNodeCommandsTest() { |
28 | 35 | final var newNodeNum = new AtomicLong(); |
29 | | - final var adminKey = "adminKey"; |
| 36 | + final var adminKey = getUniqueAdminKey(); |
30 | 37 | final var adminKeyFileName = adminKey + ".pem"; |
31 | 38 | final var certFilePath = loadResourceFile("testFiles/s-public-node1.pem"); |
32 | 39 | return hapiTest( |
@@ -70,4 +77,120 @@ final Stream<DynamicTest> basicNodeCommandsTest() { |
70 | 77 | .exposingOutputTo(output -> assertTrue( |
71 | 78 | output.contains("node" + newNodeNum.get() + " has been deleted"))))))); |
72 | 79 | } |
| 80 | + |
| 81 | + @LeakyHapiTest(overrides = {"nodes.updateAccountIdAllowed"}) |
| 82 | + final Stream<DynamicTest> updateNodeAccountIdCommandTest() { |
| 83 | + final var newNodeNum = new AtomicLong(); |
| 84 | + final var zeroBalanceAccNum = new AtomicLong(); |
| 85 | + final var newAccNum = new AtomicLong(); |
| 86 | + |
| 87 | + final var adminKey = getUniqueAdminKey(); |
| 88 | + final var adminKeyFileName = adminKey + ".pem"; |
| 89 | + |
| 90 | + final var zeroBalanceAccount = "zeroBalanceAccount"; |
| 91 | + final var newAccount = "newAccount"; |
| 92 | + |
| 93 | + final var certFilePath = loadResourceFile("testFiles/s-public-node1.pem"); |
| 94 | + return hapiTest( |
| 95 | + overriding("nodes.updateAccountIdAllowed", "true"), |
| 96 | + newKeyNamed(adminKey) |
| 97 | + .shape(SigControl.ED25519_ON) |
| 98 | + .exportingTo(() -> asYcDefaultNetworkKey(adminKeyFileName), "keypass"), |
| 99 | + // create new account with 0 balance |
| 100 | + cryptoCreate(zeroBalanceAccount) |
| 101 | + .balance(0L) |
| 102 | + .exposingCreatedIdTo(id -> zeroBalanceAccNum.set(id.getAccountNum())), |
| 103 | + saveAccountKeyToFile(zeroBalanceAccount), |
| 104 | + // create account with positive balance |
| 105 | + cryptoCreate(newAccount) |
| 106 | + .balance(100_000_000L) |
| 107 | + .exposingCreatedIdTo(id -> newAccNum.set(id.getAccountNum())), |
| 108 | + saveAccountKeyToFile(newAccount), |
| 109 | + |
| 110 | + // Create new node |
| 111 | + doingContextual(spec -> allRunFor( |
| 112 | + spec, |
| 113 | + yahcliNodes( |
| 114 | + "create", |
| 115 | + "-a", |
| 116 | + "23", |
| 117 | + "-d", |
| 118 | + "Test node", |
| 119 | + "-k", |
| 120 | + asYcDefaultNetworkKey(adminKeyFileName), |
| 121 | + // We are using the full option name here, as -c overrides the config location |
| 122 | + "--gossipCaCertificate", |
| 123 | + certFilePath.toString(), |
| 124 | + "-h", |
| 125 | + certFilePath.toString(), |
| 126 | + "-g", |
| 127 | + "127.0.0.1:50211", |
| 128 | + "-s", |
| 129 | + "a.b.com:50212") |
| 130 | + .exposingOutputTo(newNodeCapturer(newNodeNum::set)))), |
| 131 | + |
| 132 | + // Update the node |
| 133 | + doingContextual(spec -> allRunFor( |
| 134 | + spec, |
| 135 | + // Try to update node accountId with 0 balance |
| 136 | + yahcliNodes( |
| 137 | + "update", |
| 138 | + "-n", |
| 139 | + Long.toString(newNodeNum.get()), |
| 140 | + "-a", |
| 141 | + Long.toString(zeroBalanceAccNum.get()), |
| 142 | + "-k", |
| 143 | + asYcDefaultNetworkKey(adminKeyFileName), |
| 144 | + "-d", |
| 145 | + "Updated test node with O balance account id should fail") |
| 146 | + .expectFail() |
| 147 | + .exposingOutputTo(output -> { |
| 148 | + assertTrue(output.contains("FAILED to update node" + newNodeNum.get())); |
| 149 | + }), |
| 150 | + // Update the node with accountId with positive balance |
| 151 | + yahcliNodes( |
| 152 | + "update", |
| 153 | + "-n", |
| 154 | + Long.toString(newNodeNum.get()), |
| 155 | + "-a", |
| 156 | + Long.toString(newAccNum.get()), |
| 157 | + "-k", |
| 158 | + asYcDefaultNetworkKey(adminKeyFileName), |
| 159 | + "-d", |
| 160 | + "Update node with positive balance account id") |
| 161 | + .exposingOutputTo(output -> |
| 162 | + assertTrue(output.contains("node" + newNodeNum.get() + " has been updated"))), |
| 163 | + |
| 164 | + // Finally delete the just created node |
| 165 | + yahcliNodes("delete", "-n", Long.toString(newNodeNum.get())) |
| 166 | + .exposingOutputTo(output -> assertTrue( |
| 167 | + output.contains("node" + newNodeNum.get() + " has been deleted")))))); |
| 168 | + } |
| 169 | + |
| 170 | + // Helpers |
| 171 | + |
| 172 | + private String getUniqueAdminKey() { |
| 173 | + uniqueAdminKeyCounter++; |
| 174 | + return "adminKey_" + uniqueAdminKeyCounter; |
| 175 | + } |
| 176 | + |
| 177 | + private String getAccountKeyFileName(Long accountNum) { |
| 178 | + return "account" + accountNum + ".pem"; |
| 179 | + } |
| 180 | + |
| 181 | + private ContextualActionOp saveAccountKeyToFile(String account) { |
| 182 | + final var accountKey = account + "Key"; |
| 183 | + |
| 184 | + return doingContextual(spec -> { |
| 185 | + final var accountId = spec.registry().getAccountID(account); |
| 186 | + final var accountKeyFileName = getAccountKeyFileName(accountId.getAccountNum()); |
| 187 | + allRunFor( |
| 188 | + spec, |
| 189 | + // create new key and export it to file |
| 190 | + newKeyNamed(accountKey) |
| 191 | + .shape(SigControl.ED25519_ON) |
| 192 | + .exportingTo(() -> asYcDefaultNetworkKey(accountKeyFileName), "keypass"), |
| 193 | + cryptoUpdate(account).key(accountKey)); |
| 194 | + }); |
| 195 | + } |
73 | 196 | } |
0 commit comments