UNPKG

@hashgraph/solo

Version:

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

140 lines 7.39 kB
// SPDX-License-Identifier: Apache-2.0 import { Flags } from '../../../../src/commands/flags.js'; import { getTestCacheDirectory } from '../../../test-utility.js'; import { container } from 'tsyringe-neo'; import { InjectTokens } from '../../../../src/core/dependency-injection/inject-tokens.js'; import { DeploymentCommandDefinition } from '../../../../src/commands/command-definitions/deployment-command-definition.js'; import { Argv } from '../../../helpers/argv-wrapper.js'; import { NamespaceName } from '../../../../src/types/namespace/namespace-name.js'; import { getEnvironmentVariable } from '../../../../src/core/constants.js'; import { ConsensusCommandDefinition } from '../../../../src/commands/command-definitions/consensus-command-definition.js'; import { Templates } from '../../../../src/core/templates.js'; import { PathEx } from '../../../../src/business/utils/path-ex.js'; import { main } from '../../../../src/index.js'; import fs from 'node:fs'; export class BaseCommandTest { static newArgv() { return ['${PATH}/node', '${SOLO_ROOT}/solo.ts']; } static optionFromFlag(flag) { return `--${flag.name}`; } static argvPushGlobalFlags(argv, testName, shouldSetTestCacheDirectory = false, shouldSetChartDirectory = false) { argv.push(BaseCommandTest.optionFromFlag(Flags.devMode), BaseCommandTest.optionFromFlag(Flags.quiet)); const soloChartsDirectory = getEnvironmentVariable('SOLO_CHARTS_DIR'); if (shouldSetChartDirectory && soloChartsDirectory && soloChartsDirectory !== '') { argv.push(BaseCommandTest.optionFromFlag(Flags.chartDirectory), process.env.SOLO_CHARTS_DIR); } if (shouldSetTestCacheDirectory) { argv.push(BaseCommandTest.optionFromFlag(Flags.cacheDir), getTestCacheDirectory(testName)); } return argv; } /** * Collects diagnostic logs using the deployment diagnostics command. * This is a shared helper used by both test patterns. */ static async collectDiagnosticLogs(testName, testLogger, deployment) { try { testLogger.info(`${testName}: Collecting diagnostic logs...`); // Create proper Argv object const argv = Argv.getDefaultArgv(NamespaceName.of(testName), testName); argv.setArg(Flags.deployment, deployment); argv.setCommand(DeploymentCommandDefinition.COMMAND_NAME, DeploymentCommandDefinition.DIAGNOSTICS_SUBCOMMAND_NAME, DeploymentCommandDefinition.DIAGNOSTICS_LOGS); const nodeCmd = container.resolve(InjectTokens.NodeCommand); await nodeCmd.handlers.logs(argv.build()); testLogger.info(`${testName}: Diagnostic logs collected successfully`); } catch (error) { testLogger.error(`${testName}: Error collecting diagnostic logs: ${error}`); if (error instanceof Error && error.stack) { testLogger.error(`${testName}: Stack trace:\n${error.stack}`); } } } static async collectJavaFlightRecorderLogs(testName, testLogger, deployment, nodeAlias) { try { testLogger.info(`${testName}: Collecting jfr logs...`); // Create proper Argv object const argv = Argv.getDefaultArgv(NamespaceName.of(testName), testName); argv.setArg(Flags.deployment, deployment); argv.setArg(Flags.nodeAlias, nodeAlias); argv.setCommand(ConsensusCommandDefinition.COMMAND_NAME, ConsensusCommandDefinition.NODE_SUBCOMMAND_NAME, ConsensusCommandDefinition.COLLECT_JFR); const nodeCmd = container.resolve(InjectTokens.NodeCommand); await nodeCmd.handlers.collectJavaFlightRecorderLogs(argv.build()); testLogger.info(`${testName}: Java Flight Recorder logs for node ${nodeAlias} collected successfully`); } catch (error) { testLogger.error(`${testName}: Error collecting Java Flight Recorder logs for node ${nodeAlias}: ${error}`); if (error instanceof Error && error.stack) { testLogger.error(`${testName}: Stack trace:\n${error.stack}`); } } } /** * Sets up an after() hook for diagnostic log collection in E2E tests. * Call this within your test suite describe block. */ static async setupDiagnosticLogCollection(options) { const { testName, testLogger, deployment } = options; await BaseCommandTest.collectDiagnosticLogs(testName, testLogger, deployment); } /** * Sets up an after() hook for diagnostic log collection in E2E tests. * Call this within your test suite describe block. */ static setupJavaFlightRecorderLogCollection(options) { const { testName, testLogger, deployment } = options; const promises = []; for (let index = 0; index < options.consensusNodesCount; index++) { const nodeAlias = Templates.renderNodeAliasFromNumber(index + 1); promises.push(BaseCommandTest.collectJavaFlightRecorderLogs(testName, testLogger, deployment, nodeAlias)); } return Promise.all(promises); } static async runMainAndCaptureOutputToJson(argv, options) { const stdoutChunks = []; const stderrChunks = []; const outputSubdirectory = options.outputSubdirectory ?? 'command-output'; const originalStdoutWrite = process.stdout.write.bind(process.stdout); const originalStderrWrite = process.stderr.write.bind(process.stderr); process.stdout.write = ((chunk, encoding, callback) => { stdoutChunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString(encoding)); if (encoding === undefined) { return callback ? originalStdoutWrite(chunk, callback) : originalStdoutWrite(chunk); } return callback ? originalStdoutWrite(chunk, encoding, callback) : originalStdoutWrite(chunk, encoding); }); process.stderr.write = ((chunk, encoding, callback) => { stderrChunks.push(typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString(encoding)); if (encoding === undefined) { return callback ? originalStderrWrite(chunk, callback) : originalStderrWrite(chunk); } return callback ? originalStderrWrite(chunk, encoding, callback) : originalStderrWrite(chunk, encoding); }); try { await main(argv); } finally { process.stdout.write = originalStdoutWrite; process.stderr.write = originalStderrWrite; } const outputDirectory = PathEx.join(getTestCacheDirectory(options.testName), outputSubdirectory); fs.mkdirSync(outputDirectory, { recursive: true }); const outputFilePath = PathEx.join(outputDirectory, options.outputFileName); const payload = { timestamp: new Date().toISOString(), argv, stdout: stdoutChunks.join(''), stderr: stderrChunks.join(''), ...options.metadata, }; fs.writeFileSync(outputFilePath, JSON.stringify(payload, undefined, 2), 'utf8'); return { stdout: payload.stdout, stderr: payload.stderr, outputFilePath, }; } } //# sourceMappingURL=base-command-test.js.map