Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build a way to test the examples work with each mainnet release and new SDK release #1629

Merged
merged 6 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,45 @@ jobs:

- name: Stop the local node
run: npx @hashgraph/hedera-local stop

examples:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Assemble SDK
run: ./gradlew :sdk:assemble
- name: Assemble Examples
run: ./gradlew :examples:assemble

- name: Start the local node
run: npx @hashgraph/[email protected] start -d --network local

- name: Prepare .env for Examples
run: |
echo "OPERATOR_KEY=0xa608e2130a0a3cb34f86e757303c862bee353d9ab77ba4387ec084f881d420d4" > examples/.env
echo "OPERATOR_ID=0.0.1022" >> examples/.env
echo "HEDERA_NETWORK=localhost" >> examples/.env

- name: Run Examples
run: |
./gradlew :examples:runAllExamples

- name: Stop the local node
run: npx @hashgraph/hedera-local stop
35 changes: 35 additions & 0 deletions examples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,41 @@ dependencies {
implementation "com.google.errorprone:error_prone_core:2.21.1"
}

task runAllExamples {
def exampleClasses = fileTree('src/main/java')
.toList()
.stream()
.filter { it.name.endsWith('Example.java') }
.map { it.name.replaceAll('\\.java$', '') }
.filter { !it.equals('ValidateChecksumExample') } // disabled this example, because it needs user input (but it WORKS)
.filter { !it.equals('ZeroTokenOperationsExample') } // doesn't work
.filter { !it.equals('SolidityPrecompileExample') } // doesn't work with hedera-local-node
.filter { !it.equals('ConsensusPubSubChunkedExample') } // doesn't work on CI
.toList()

exampleClasses.each { className ->
def multilineString = """

---EXECUTING $className:

"""

doLast {
javaexec {
println multilineString

classpath = sourceSets.main.runtimeClasspath
main = className
standardInput(System.in)

// NOTE: Uncomment to enable trace logs in the SDK during the examples
// jvmArgs "-Dorg.slf4j.simpleLogger.log.com.hedera.hashgraph=trace"
}
}
}

}

tasks.addRule("Pattern: run<Example>: Runs an example.") { String taskName ->
if (taskName.startsWith("run")) {
task(taskName, type: JavaExec) {
Expand Down
5 changes: 3 additions & 2 deletions examples/src/main/java/AccountAliasExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ public class AccountAliasExample {
// HEDERA_NETWORK defaults to testnet if not specified in dotenv
private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet");

public static void main(String[] args) throws TimeoutException, PrecheckStatusException, ReceiptStatusException {
Client client = Client.forName(HEDERA_NETWORK);
public static void main(String[] args)
throws TimeoutException, PrecheckStatusException, ReceiptStatusException, InterruptedException {
Client client = ClientHelper.forName(HEDERA_NETWORK);

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
Expand Down
8 changes: 5 additions & 3 deletions examples/src/main/java/AccountAllowanceExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,17 @@ public class AccountAllowanceExample {
private final PrivateKey charlieKey;
private final AccountId charlieId;

public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException {
public static void main(String[] args)
throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException {
AccountAllowanceExample example = new AccountAllowanceExample();
example.demonstrateAllowances();
example.cleanUp();
System.out.println("End of example");
}

private AccountAllowanceExample() throws PrecheckStatusException, TimeoutException, ReceiptStatusException {
client = Client.forName(HEDERA_NETWORK);
private AccountAllowanceExample()
throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException {
client = ClientHelper.forName(HEDERA_NETWORK);

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
Expand Down
14 changes: 7 additions & 7 deletions examples/src/main/java/AccountCreateWithHtsExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public final class AccountCreateWithHtsExample {
private AccountCreateWithHtsExample() {
}

public static void main(String[] args) throws NullPointerException, PrecheckStatusException, ReceiptStatusException, InterruptedException, TimeoutException {
Client client = Client.forName(HEDERA_NETWORK);
public static void main(String[] args) throws Exception {
Client client = ClientHelper.forName(HEDERA_NETWORK);

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
Expand Down Expand Up @@ -149,11 +149,11 @@ public static void main(String[] args) throws NullPointerException, PrecheckStat

System.out.println("The normal account ID of the given alias: " + accountId);

if (nftOwnerAccountId.equals(accountId))
if (nftOwnerAccountId.equals(accountId)) {
System.out.println("The NFT owner accountId matches the accountId created with the HTS");
else
System.out.println("The two account IDs does not match");

} else {
throw new Exception("The two account IDs does not match");
}

System.out.println("Example 2");

Expand Down Expand Up @@ -224,7 +224,7 @@ public static void main(String[] args) throws NullPointerException, PrecheckStat
if (tokenBalanceAccountId2 == 10)
System.out.println("Account is created successfully using HTS 'TransferTransaction'");
else
System.out.println("Creating account with HTS using public key alias failed");
throw new Exception("Creating account with HTS using public key alias failed");

client.close();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ private AutoCreateAccountTransferTransactionExample() {
- Sign with the private key that corresponds to the public key on the hollow account
- Get the `AccountInfo` for the account and return the public key on the account to show it is a complete account
*/
public static void main(String[] args) throws PrecheckStatusException, TimeoutException, ReceiptStatusException, InterruptedException, IOException {
Client client = Client.forName(HEDERA_NETWORK);
public static void main(String[] args) throws Exception {
Client client = ClientHelper.forName(HEDERA_NETWORK);

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
Expand Down Expand Up @@ -111,7 +111,7 @@ public static void main(String[] args) throws PrecheckStatusException, TimeoutEx
if (((KeyList) accountInfo.key).isEmpty()) {
System.out.println("The newly created account is a hollow account");
} else {
System.out.println("Not a hollow account");
throw new Exception("Not a hollow account");
}

/*
Expand Down
27 changes: 27 additions & 0 deletions examples/src/main/java/ClientHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import com.hedera.hashgraph.sdk.AccountId;
import com.hedera.hashgraph.sdk.Client;
import java.util.HashMap;
import java.util.List;

public class ClientHelper {
public static final String LOCAL_NETWORK_NAME = "localhost";
private static final String DEFAULT_LOCAL_NODE_ADDRESS = "127.0.0.1:50211";
private static final String DEFAULT_LOCAL_MIRROR_NODE_ADDRESS = "127.0.0.1:5600";

public static Client forName(String network) throws InterruptedException {
if (network.equals(LOCAL_NETWORK_NAME)) {
return forLocalNetwork();
} else {
return Client.forName(network);
}
}

public static Client forLocalNetwork() throws InterruptedException {
var network = new HashMap<String, AccountId>();
network.put(DEFAULT_LOCAL_NODE_ADDRESS, new AccountId(3));

return Client
.forNetwork(network)
.setMirrorNetwork(List.of(DEFAULT_LOCAL_MIRROR_NODE_ADDRESS));
}
}
16 changes: 9 additions & 7 deletions examples/src/main/java/ConsensusPubSubChunkedExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static java.nio.charset.StandardCharsets.UTF_8;
Expand All @@ -46,11 +48,13 @@ public final class ConsensusPubSubChunkedExample {
// HEDERA_NETWORK defaults to testnet if not specified in dotenv
private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet");

private static final CountDownLatch largeMessageLatch = new CountDownLatch(1);

private ConsensusPubSubChunkedExample() {
}

public static void main(String[] args) throws TimeoutException, PrecheckStatusException, ReceiptStatusException, InterruptedException, InvalidProtocolBufferException {
Client client = Client.forName(HEDERA_NETWORK);
Client client = ClientHelper.forName(HEDERA_NETWORK);

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
Expand Down Expand Up @@ -80,6 +84,7 @@ public static void main(String[] args) throws TimeoutException, PrecheckStatusEx
.setTopicId(newTopicId)
.subscribe(client, topicMessage -> {
System.out.println("at " + topicMessage.consensusTimestamp + " ( seq = " + topicMessage.sequenceNumber + " ) received topic message of " + topicMessage.contents.length + " bytes");
largeMessageLatch.countDown();
});

// get a large file to send
Expand Down Expand Up @@ -115,12 +120,9 @@ public static void main(String[] args) throws TimeoutException, PrecheckStatusEx
// get the receipt to ensure there were no errors
transaction.execute(client).getReceipt(client);

// noinspection InfiniteLoopStatement
while (true) {
System.out.println("waiting ...");

// noinspection BusyWait
Thread.sleep(2500);
boolean largeMessageReceived = largeMessageLatch.await(60, TimeUnit.SECONDS);
if (!largeMessageReceived) {
throw new TimeoutException("Large topic message was not received!");
}
}

Expand Down
17 changes: 13 additions & 4 deletions examples/src/main/java/ConsensusPubSubExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;


Expand All @@ -41,11 +43,14 @@ class ConsensusPubSubExample {
// HEDERA_NETWORK defaults to testnet if not specified in dotenv
private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet");

private static final int TOTAL_MESSAGES = 5;
private static final CountDownLatch messagesLatch = new CountDownLatch(TOTAL_MESSAGES);

private ConsensusPubSubExample() {
}

public static void main(String[] args) throws TimeoutException, InterruptedException, PrecheckStatusException, ReceiptStatusException {
Client client = Client.forName(HEDERA_NETWORK);
Client client = ClientHelper.forName(HEDERA_NETWORK);

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
Expand All @@ -68,11 +73,10 @@ public static void main(String[] args) throws TimeoutException, InterruptedExcep
String messageAsString = new String(resp.contents, StandardCharsets.UTF_8);

System.out.println(resp.consensusTimestamp + " received topic message: " + messageAsString);
messagesLatch.countDown();
});

// keep the main thread from exiting because the listeners run on daemon threads
// noinspection InfiniteLoopStatement
for (int i = 0; ; i++) {
for (int i = 0; i <= TOTAL_MESSAGES; i++) {
new TopicMessageSubmitTransaction()
.setTopicId(topicId)
.setMessage("hello, HCS! " + i)
Expand All @@ -81,5 +85,10 @@ public static void main(String[] args) throws TimeoutException, InterruptedExcep

Thread.sleep(2500);
}

boolean allMessagesReceived = messagesLatch.await(30, TimeUnit.SECONDS);
if (!allMessagesReceived) {
throw new TimeoutException("Not all topic messages were received!");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public class ConsensusPubSubWithSubmitKeyExample {
private TopicId topicId;
private PrivateKey submitKey;

public ConsensusPubSubWithSubmitKeyExample(int messagesToPublish, int millisBetweenMessages) {
public ConsensusPubSubWithSubmitKeyExample(int messagesToPublish, int millisBetweenMessages)
throws InterruptedException {
this.messagesToPublish = messagesToPublish;
this.millisBetweenMessages = millisBetweenMessages;
setupClient();
Expand All @@ -77,8 +78,8 @@ public void execute() throws TimeoutException, InterruptedException, PrecheckSta
publishMessagesToTopic();
}

private void setupClient() {
client = Client.forName(HEDERA_NETWORK);
private void setupClient() throws InterruptedException {
client = ClientHelper.forName(HEDERA_NETWORK);

// Defaults the operator account ID and key such that all generated transactions will be paid for by this
// account and be signed by this key
Expand Down
3 changes: 1 addition & 2 deletions examples/src/main/java/ConstructClientExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ public class ConstructClientExample {
// or set environment variables with the same names
@Nullable
private static final String CONFIG_FILE = Dotenv.load().get("CONFIG_FILE");
// HEDERA_NETWORK defaults to testnet if not specified in dotenv
private static final String HEDERA_NETWORK = Dotenv.load().get("HEDERA_NETWORK", "testnet");
private static final String HEDERA_NETWORK = "testnet";

ConstructClientExample() {
}
Expand Down
26 changes: 11 additions & 15 deletions examples/src/main/java/ContractHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,22 +187,18 @@ public ContractHelper executeSteps(
.setValidateStatus(false)
.getRecord(client);

try {
if (record.receipt.status != Status.SUCCESS) {
throw new Exception("transaction receipt yielded unsuccessful response code " + record.receipt.status);
}
ContractFunctionResult functionResult = Objects.requireNonNull(record.contractFunctionResult);
System.out.println("gas used: " + functionResult.gasUsed);
if (getResultValidator(stepIndex).apply(functionResult)) {
System.out.println("step " + stepIndex + " completed, and returned valid result. (TransactionId \"" + record.transactionId + "\")");
} else {
throw new Exception("returned invalid result");
}
} catch (Throwable error) {
System.out.println("Error occurred in step " + stepIndex + ": " + error.getMessage());
System.out.println("Transaction record: " + record);
break;
if (record.receipt.status != Status.SUCCESS) {
throw new Exception("transaction receipt yielded unsuccessful response code " + record.receipt.status);
}
ContractFunctionResult functionResult = Objects.requireNonNull(record.contractFunctionResult);
System.out.println("gas used: " + functionResult.gasUsed);
if (getResultValidator(stepIndex).apply(functionResult)) {
System.out.println("step " + stepIndex + " completed, and returned valid result. (TransactionId \"" + record.transactionId + "\")");
} else {
throw new Exception("returned invalid result");
}

break;
}
return this;
}
Expand Down
8 changes: 4 additions & 4 deletions examples/src/main/java/ContractNoncesExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ public final class ContractNoncesExample {
private ContractNoncesExample() {
}

public static void main(String[] args) throws TimeoutException, PrecheckStatusException, ReceiptStatusException {
Client client = Client.forName(HEDERA_NETWORK);
public static void main(String[] args)
throws Exception {
Client client = ClientHelper.forName(HEDERA_NETWORK);

// Defaults the operator account ID and key such that all generated transactions will be paid for
// by this account and be signed by this key
Expand Down Expand Up @@ -89,8 +90,7 @@ public static void main(String[] args) throws TimeoutException, PrecheckStatusEx
.getReceipt(client);

if (contractDeleteResult.status != Status.SUCCESS) {
System.out.println("error deleting contract: " + contractDeleteResult.status);
return;
throw new Exception("error deleting contract: " + contractDeleteResult.status);
}
System.out.println("Contract successfully deleted");
}
Expand Down
Loading