UNPKG

@hashgraph/solo

Version:

An opinionated CLI tool to deploy and manage private Hedera Networks.

206 lines 11.1 kB
/** * SPDX-License-Identifier: Apache-2.0 */ import { after, afterEach, before, describe, it } from 'mocha'; import { expect } from 'chai'; import { Flags as flags } from '../../../src/commands/flags.js'; import { accountCreationShouldSucceed, balanceQueryShouldSucceed, e2eTestSuite, getDefaultArgv, HEDERA_PLATFORM_VERSION_TAG, TEST_CLUSTER, } from '../../test_util.js'; import * as version from '../../../version.js'; import { sleep } from '../../../src/core/helpers.js'; import { MirrorNodeCommand } from '../../../src/commands/mirror_node.js'; import { Status, TopicCreateTransaction, TopicMessageSubmitTransaction } from '@hashgraph/sdk'; import * as http from 'http'; import { PodName } from '../../../src/core/kube/resources/pod/pod_name.js'; import { PackageDownloader } from '../../../src/core/package_downloader.js'; import { Duration } from '../../../src/core/time/duration.js'; import { ExplorerCommand } from '../../../src/commands/explorer.js'; import { NamespaceName } from '../../../src/core/kube/resources/namespace/namespace_name.js'; import { PodRef } from '../../../src/core/kube/resources/pod/pod_ref.js'; import { container } from 'tsyringe-neo'; import { InjectTokens } from '../../../src/core/dependency_injection/inject_tokens.js'; const testName = 'mirror-cmd-e2e'; const namespace = NamespaceName.of(testName); const argv = getDefaultArgv(namespace); argv[flags.namespace.name] = namespace.name; argv[flags.releaseTag.name] = HEDERA_PLATFORM_VERSION_TAG; argv[flags.forcePortForward.name] = true; argv[flags.nodeAliasesUnparsed.name] = 'node1'; // use a single node to reduce resource during e2e tests argv[flags.generateGossipKeys.name] = true; argv[flags.generateTlsKeys.name] = true; argv[flags.clusterRef.name] = TEST_CLUSTER; argv[flags.soloChartVersion.name] = version.SOLO_CHART_VERSION; argv[flags.force.name] = true; argv[flags.relayReleaseTag.name] = flags.relayReleaseTag.definition.defaultValue; // set the env variable SOLO_CHARTS_DIR if developer wants to use local Solo charts argv[flags.chartDirectory.name] = process.env.SOLO_CHARTS_DIR ?? undefined; argv[flags.quiet.name] = true; argv[flags.pinger.name] = true; argv[flags.enableHederaExplorerTls.name] = true; e2eTestSuite(testName, argv, undefined, undefined, undefined, undefined, undefined, undefined, true, bootstrapResp => { describe('MirrorNodeCommand', async () => { const k8Factory = bootstrapResp.opts.k8Factory; const mirrorNodeCmd = new MirrorNodeCommand(bootstrapResp.opts); const explorerCommand = new ExplorerCommand(bootstrapResp.opts); const downloader = new PackageDownloader(mirrorNodeCmd.logger); const accountManager = bootstrapResp.opts.accountManager; const testMessage = 'Mirror node test message'; let portForwarder = null; let newTopicId = null; before(() => { bootstrapResp.opts.logger.showUser(`------------------------- START: ${testName} ----------------------------`); }); after(async function () { this.timeout(Duration.ofMinutes(3).toMillis()); await container.resolve(InjectTokens.NetworkNodes).getLogs(namespace); await k8Factory.default().namespaces().delete(namespace); await accountManager.close(); bootstrapResp.opts.logger.showUser(`------------------------- END: ${testName} ----------------------------`); }); // give a few ticks so that connections can close afterEach(async () => await sleep(Duration.ofMillis(500))); balanceQueryShouldSucceed(accountManager, mirrorNodeCmd, namespace); it('mirror node and explorer deploy should success', async () => { try { expect(await mirrorNodeCmd.deploy(argv)).to.be.true; expect(await explorerCommand.deploy(argv)).to.be.true; } catch (e) { mirrorNodeCmd.logger.showUserError(e); expect.fail(); } expect(mirrorNodeCmd.getUnusedConfigs(MirrorNodeCommand.DEPLOY_CONFIGS_NAME)).to.deep.equal([ flags.clusterRef.constName, flags.chartDirectory.constName, flags.deployment.constName, flags.profileFile.constName, flags.profileName.constName, flags.storageAccessKey.constName, flags.storageSecrets.constName, flags.storageEndpoint.constName, flags.externalDatabaseHost.constName, flags.externalDatabaseOwnerUsername.constName, flags.externalDatabaseOwnerPassword.constName, flags.externalDatabaseReadonlyUsername.constName, flags.externalDatabaseReadonlyPassword.constName, ]); expect(explorerCommand.getUnusedConfigs(MirrorNodeCommand.DEPLOY_CONFIGS_NAME)).to.deep.equal([ flags.hederaExplorerTlsHostName.constName, flags.deployment.constName, flags.profileFile.constName, flags.profileName.constName, flags.quiet.constName, ]); }).timeout(Duration.ofMinutes(10).toMillis()); it('mirror node API should be running', async () => { const clusterRefs = mirrorNodeCmd.getClusterRefs(); await accountManager.loadNodeClient(namespace, clusterRefs, argv[flags.deployment.name], argv[flags.forcePortForward.name]); try { // find hedera explorer pod const pods = await k8Factory .default() .pods() .list(namespace, ['app.kubernetes.io/component=hedera-explorer']); const explorerPod = pods[0]; portForwarder = await k8Factory .default() .pods() .readByRef(PodRef.of(namespace, PodName.of(explorerPod.metadata.name))) .portForward(8_080, 8_080); await sleep(Duration.ofSeconds(2)); // check if mirror node api server is running const apiURL = 'http://127.0.0.1:8080/api/v1/transactions'; expect(await downloader.urlExists(apiURL)).to.be.true; await sleep(Duration.ofSeconds(2)); } catch (e) { mirrorNodeCmd.logger.showUserError(e); expect.fail(); } }).timeout(Duration.ofMinutes(1).toMillis()); it('Explorer GUI should be running', async () => { try { const guiURL = 'http://127.0.0.1:8080/localnet/dashboard'; expect(await downloader.urlExists(guiURL)).to.be.true; await sleep(Duration.ofSeconds(2)); mirrorNodeCmd.logger.debug('mirror node API and explorer GUI are running'); } catch (e) { mirrorNodeCmd.logger.showUserError(e); expect.fail(); } }).timeout(Duration.ofMinutes(1).toMillis()); it('Create topic and submit message should success', async () => { try { // Create a new public topic and submit a message const txResponse = await new TopicCreateTransaction().execute(accountManager._nodeClient); const receipt = await txResponse.getReceipt(accountManager._nodeClient); newTopicId = receipt.topicId; mirrorNodeCmd.logger.debug(`Newly created topic ID is: ${newTopicId}`); const submitResponse = await new TopicMessageSubmitTransaction({ topicId: newTopicId, message: testMessage, }).execute(accountManager._nodeClient); const submitReceipt = await submitResponse.getReceipt(accountManager._nodeClient); expect(submitReceipt.status).to.deep.equal(Status.Success); } catch (e) { mirrorNodeCmd.logger.showUserError(e); expect.fail(); } }).timeout(Duration.ofMinutes(1).toMillis()); // trigger some extra transactions to trigger MirrorNode to fetch the transactions accountCreationShouldSucceed(accountManager, mirrorNodeCmd, namespace); accountCreationShouldSucceed(accountManager, mirrorNodeCmd, namespace); it('Check submit message result should success', async () => { try { const queryURL = `http://localhost:8080/api/v1/topics/${newTopicId}/messages`; let received = false; let receivedMessage = ''; // wait until the transaction reached consensus and retrievable from the mirror node API while (!received) { const req = http.request(queryURL, { method: 'GET', timeout: 100, headers: { Connection: 'close' } }, res => { res.setEncoding('utf8'); res.on('data', chunk => { // convert chunk to json object const obj = JSON.parse(chunk); if (obj.messages.length === 0) { mirrorNodeCmd.logger.debug('No messages yet'); } else { // convert message from base64 to utf-8 const base64 = obj.messages[0].message; const buff = Buffer.from(base64, 'base64'); receivedMessage = buff.toString('utf-8'); mirrorNodeCmd.logger.debug(`Received message: ${receivedMessage}`); received = true; } }); }); req.on('error', e => { mirrorNodeCmd.logger.debug(`problem with request: ${e.message}`); }); req.end(); // make the request await sleep(Duration.ofSeconds(2)); } await sleep(Duration.ofSeconds(1)); expect(receivedMessage).to.equal(testMessage); await k8Factory.default().pods().readByRef(null).stopPortForward(portForwarder); } catch (e) { mirrorNodeCmd.logger.showUserError(e); expect.fail(); } }).timeout(Duration.ofMinutes(5).toMillis()); it('mirror node destroy should success', async () => { try { expect(await mirrorNodeCmd.destroy(argv)).to.be.true; expect(await explorerCommand.destroy(argv)).to.be.true; } catch (e) { mirrorNodeCmd.logger.showUserError(e); expect.fail(); } }).timeout(Duration.ofMinutes(1).toMillis()); }); }); //# sourceMappingURL=mirror_node.test.js.map