diff --git a/.taprc b/.taprc index ba16cc18b68..7a654deb2e9 100644 --- a/.taprc +++ b/.taprc @@ -6,7 +6,6 @@ timeout: 3600 ts: true files: - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/add-orgs.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/obtain-profiles.test.ts - ./packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/plugin-factory-keychain.test.ts - ./packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/plugin-factory-keychain.test.ts - ./packages/cactus-plugin-keychain-azure-kv/src/test/typescript/integration/plugin-keychain-azure-kv.test.ts @@ -30,14 +29,6 @@ files: - ./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/get-transaction-endpoint.test.ts - ./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/get-block-endpoint.test.ts - ./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/v21-sign-transaction-endpoint.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/identity-client.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-with-identities.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-golang-source.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-typescript-source.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation.test.ts - - ./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/unit/identity-internal-crypto-utils.test.ts - ./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/cactus-keychain-vault-server.test.ts - ./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/plugin-keychain-vault.test.ts - ./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/openapi/openapi-validation.test.ts diff --git a/jest.config.js b/jest.config.js index e72ea6af093..4bbddf6a951 100644 --- a/jest.config.js +++ b/jest.config.js @@ -18,7 +18,6 @@ module.exports = { testPathIgnorePatterns: [ `./packages/cactus-plugin-ledger-connector-ethereum/src/test/typescript/manual/geth-alchemy-integration-manual-check.test.ts`, `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/add-orgs.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/obtain-profiles.test.ts`, `./packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/plugin-factory-keychain.test.ts`, `./packages/cactus-plugin-keychain-aws-sm/src/test/typescript/integration/plugin-factory-keychain.test.ts`, `./packages/cactus-plugin-keychain-azure-kv/src/test/typescript/integration/plugin-keychain-azure-kv.test.ts`, @@ -42,14 +41,6 @@ module.exports = { `./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/get-transaction-endpoint.test.ts`, `./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/get-block-endpoint.test.ts`, `./packages/cactus-test-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-validator-besu/v21-sign-transaction-endpoint.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/identity-client.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-with-identities.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-golang-source.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-typescript-source.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation.test.ts`, - `./packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/unit/identity-internal-crypto-utils.test.ts`, `./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/cactus-keychain-vault-server.test.ts`, `./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/plugin-keychain-vault.test.ts`, `./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/openapi/openapi-validation.test.ts`, diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-golang-source.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-golang-source.test.ts index 770237471c3..cb99331e502 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-golang-source.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-golang-source.test.ts @@ -1,16 +1,13 @@ +import "jest-extended"; import { AddressInfo } from "net"; -import http from "http"; +import http, { Server } from "http"; import fs from "fs-extra"; import path from "path"; - -import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; - import express from "express"; import bodyParser from "body-parser"; import { - Containers, FABRIC_25_LTS_AIO_FABRIC_VERSION, FABRIC_25_LTS_AIO_IMAGE_VERSION, FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, @@ -20,7 +17,6 @@ import { } from "@hyperledger/cactus-test-tooling"; import { - Checks, IListenOptions, LogLevelDesc, Servers, @@ -46,248 +42,216 @@ import { DEFAULT_FABRIC_2_AIO_IMAGE_NAME } from "@hyperledger/cactus-test-toolin const testCase = "deploys Fabric 2.x contract from go source"; const logLevel: LogLevelDesc = "INFO"; -test("BEFORE " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); -}); - -test(testCase, async (t: Test) => { +describe("Deploy CC from Golang Source Test", () => { + let ledger: FabricTestLedgerV1; const channelId = "mychannel"; const channelName = channelId; - - test.onFailure(async () => { - await Containers.logDiagnostics({ logLevel }); - }); - - const ledger = new FabricTestLedgerV1({ - emitContainerLogs: true, - publishAllPorts: true, - imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, - imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, - envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), - logLevel, - }); - - const tearDown = async () => { - await ledger.stop(); - await ledger.destroy(); - await pruneDockerAllIfGithubAction({ logLevel }); - }; - - test.onFinish(tearDown); - await ledger.start(); - - const connectionProfile = await ledger.getConnectionProfileOrg1(); - t.ok(connectionProfile, "getConnectionProfileOrg1() out truthy OK"); - - const enrollAdminOut = await ledger.enrollAdmin(); - const adminWallet = enrollAdminOut[1]; - const [userIdentity] = await ledger.enrollUser(adminWallet); - const sshConfig = await ledger.getSshConfig(); - - const keychainInstanceId = uuidv4(); - const keychainId = uuidv4(); - const keychainEntryKey = "user2"; - const keychainEntryValue = JSON.stringify(userIdentity); - - const keychainPlugin = new PluginKeychainMemory({ - instanceId: keychainInstanceId, - keychainId, - logLevel, - backend: new Map([ - [keychainEntryKey, keychainEntryValue], - ["some-other-entry-key", "some-other-entry-value"], - ]), - }); - - const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); - - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; - - const pluginOptions: IPluginLedgerConnectorFabricOptions = { - instanceId: uuidv4(), - dockerBinary: "/usr/local/bin/docker", - peerBinary: "/fabric-samples/bin/peer", - goBinary: "/usr/local/go/bin/go", - pluginRegistry, - cliContainerEnv: FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, - sshConfig, - logLevel, - connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, - commitTimeout: 300, - }, - }; - const plugin = new PluginLedgerConnectorFabric(pluginOptions); - - const expressApp = express(); - expressApp.use(bodyParser.json({ limit: "250mb" })); - const server = http.createServer(expressApp); - const listenOptions: IListenOptions = { - hostname: "127.0.0.1", - port: 0, - server, - }; - const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; - const { port } = addressInfo; - test.onFinish(async () => await Servers.shutdown(server)); - - await plugin.getOrCreateWebServices(); - await plugin.registerWebServices(expressApp); - const apiUrl = `http://127.0.0.1:${port}`; - - const config = new Configuration({ basePath: apiUrl }); - - const apiClient = new FabricApi(config); - + let server: Server; + let apiClient: FabricApi; const contractName = "basic-asset-transfer-2"; - const contractRelPath = "../../fixtures/go/basic-asset-transfer/chaincode-go"; const contractDir = path.join(__dirname, contractRelPath); - - const smartContractGoPath = path.join( - contractDir, - "./chaincode/", - "./smartcontract.go", - ); - const smartContractGoBuf = await fs.readFile(smartContractGoPath); - const smartContractGo = { - body: smartContractGoBuf.toString("base64"), - filepath: "./chaincode/", - filename: `smartcontract.go`, - }; - - const assetTransferGoPath = path.join(contractDir, "./assetTransfer.go"); - const assetTransferGoBuf = await fs.readFile(assetTransferGoPath); - const assetTransferGo = { - body: assetTransferGoBuf.toString("base64"), - filename: `${contractName}.go`, - }; - - const goModPath = path.join(contractDir, "./go.mod"); - const goModBuf = await fs.readFile(goModPath); - const goMod = { - body: goModBuf.toString("base64"), - filename: "go.mod", - }; - - const goSumPath = path.join(contractDir, "./go.sum"); - const goSumBuf = await fs.readFile(goSumPath); - const goSum = { - body: goSumBuf.toString("base64"), - filename: "go.sum", - }; - - const res = await apiClient.deployContractV1({ - channelId, - ccVersion: "1.0.0", - // constructorArgs: { Args: ["john", "99"] }, - sourceFiles: [assetTransferGo, smartContractGo, goMod, goSum], - ccName: contractName, - targetOrganizations: [ - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_2, - ], - caFile: - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1.ORDERER_TLS_ROOTCERT_FILE, - ccLabel: "basic-asset-transfer-2", - ccLang: ChainCodeProgrammingLanguage.Golang, - ccSequence: 1, - orderer: "orderer.example.com:7050", - ordererTLSHostnameOverride: "orderer.example.com", - connTimeout: 60, - }); - - const { packageIds, lifecycle, success } = res.data; - t.equal(res.status, 200, "res.status === 200 OK"); - t.true(success, "res.data.success === true"); - - const { - approveForMyOrgList, - installList, - queryInstalledList, - commit, - packaging, - queryCommitted, - } = lifecycle; - - Checks.truthy(packageIds, `packageIds truthy OK`); - Checks.truthy( - Array.isArray(packageIds), - `Array.isArray(packageIds) truthy OK`, - ); - Checks.truthy(approveForMyOrgList, `approveForMyOrgList truthy OK`); - Checks.truthy( - Array.isArray(approveForMyOrgList), - `Array.isArray(approveForMyOrgList) truthy OK`, - ); - Checks.truthy(installList, `installList truthy OK`); - Checks.truthy( - Array.isArray(installList), - `Array.isArray(installList) truthy OK`, - ); - Checks.truthy(queryInstalledList, `queryInstalledList truthy OK`); - Checks.truthy( - Array.isArray(queryInstalledList), - `Array.isArray(queryInstalledList) truthy OK`, - ); - Checks.truthy(commit, `commit truthy OK`); - // Checks.truthy(init, `init truthy OK`); - Checks.truthy(packaging, `packaging truthy OK`); - Checks.truthy(queryCommitted, `queryCommitted truthy OK`); - - const assetId = uuidv4(); - const assetOwner = uuidv4(); - - // CreateAsset(id string, color string, size int, owner string, appraisedValue int) - const createRes = await apiClient.runTransactionV1({ - contractName, - channelName, - params: [assetId, "Green", "19", assetOwner, "9999"], - methodName: "CreateAsset", - invocationType: FabricContractInvocationType.Send, - signingCredential: { + const keychainId = uuidv4(); + const keychainEntryKey = "user2"; + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.not.toThrow(); + ledger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, + envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), + logLevel, + }); + await ledger.start(); + const connectionProfile = await ledger.getConnectionProfileOrg1(); + expect(connectionProfile).toBeTruthy(); + const enrollAdminOut = await ledger.enrollAdmin(); + const adminWallet = enrollAdminOut[1]; + const [userIdentity] = await ledger.enrollUser(adminWallet); + const sshConfig = await ledger.getSshConfig(); + + const keychainInstanceId = uuidv4(); + const keychainEntryValue = JSON.stringify(userIdentity); + + const keychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, keychainId, - keychainRef: keychainEntryKey, - }, + logLevel, + backend: new Map([ + [keychainEntryKey, keychainEntryValue], + ["some-other-entry-key", "some-other-entry-value"], + ]), + }); + const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); + + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + dockerBinary: "/usr/local/bin/docker", + peerBinary: "/fabric-samples/bin/peer", + goBinary: "/usr/local/go/bin/go", + pluginRegistry, + cliContainerEnv: FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, + sshConfig, + logLevel, + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, + }, + }; + const plugin = new PluginLedgerConnectorFabric(pluginOptions); + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { port } = addressInfo; + await plugin.getOrCreateWebServices(); + await plugin.registerWebServices(expressApp); + const apiUrl = `http://127.0.0.1:${port}`; + const config = new Configuration({ basePath: apiUrl }); + apiClient = new FabricApi(config); }); - t.ok(createRes, "setRes truthy OK"); - t.true(createRes.status > 199, "createRes status > 199 OK"); - t.true(createRes.status < 300, "createRes status < 300 OK"); - t.comment(`BassicAssetTransfer.Create(): ${JSON.stringify(createRes.data)}`); - - const getRes = await apiClient.runTransactionV1({ - contractName, - channelName, - params: [assetId], - methodName: "ReadAsset", - invocationType: FabricContractInvocationType.Call, - signingCredential: { - keychainId, - keychainRef: keychainEntryKey, - }, + afterAll(async () => { + await ledger.stop(); + await ledger.destroy(); + await pruneDockerAllIfGithubAction({ logLevel }); + await Servers.shutdown(server); + }); + test(`${testCase}`, async () => { + const smartContractGoPath = path.join( + contractDir, + "./chaincode/", + "./smartcontract.go", + ); + const smartContractGoBuf = await fs.readFile(smartContractGoPath); + const smartContractGo = { + body: smartContractGoBuf.toString("base64"), + filepath: "./chaincode/", + filename: `smartcontract.go`, + }; + const assetTransferGoPath = path.join(contractDir, "./assetTransfer.go"); + const assetTransferGoBuf = await fs.readFile(assetTransferGoPath); + const assetTransferGo = { + body: assetTransferGoBuf.toString("base64"), + filename: `${contractName}.go`, + }; + const goModPath = path.join(contractDir, "./go.mod"); + const goModBuf = await fs.readFile(goModPath); + const goMod = { + body: goModBuf.toString("base64"), + filename: "go.mod", + }; + + const goSumPath = path.join(contractDir, "./go.sum"); + const goSumBuf = await fs.readFile(goSumPath); + const goSum = { + body: goSumBuf.toString("base64"), + filename: "go.sum", + }; + const res = await apiClient.deployContractV1({ + channelId, + ccVersion: "1.0.0", + // constructorArgs: { Args: ["john", "99"] }, + sourceFiles: [assetTransferGo, smartContractGo, goMod, goSum], + ccName: contractName, + targetOrganizations: [ + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_2, + ], + caFile: + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1.ORDERER_TLS_ROOTCERT_FILE, + ccLabel: "basic-asset-transfer-2", + ccLang: ChainCodeProgrammingLanguage.Golang, + ccSequence: 1, + orderer: "orderer.example.com:7050", + ordererTLSHostnameOverride: "orderer.example.com", + connTimeout: 60, + }); + const { packageIds, lifecycle, success } = res.data; + expect(res.status).toBe(200); + expect(success).toBeTruthy(); + const { + approveForMyOrgList, + installList, + queryInstalledList, + commit, + packaging, + queryCommitted, + } = lifecycle; + expect(packageIds).toBeTruthy(); + expect(Array.isArray(packageIds)).toBe(true); + expect(approveForMyOrgList).toBeTruthy(); + expect(Array.isArray(approveForMyOrgList)).toBe(true); + expect(installList).toBeTruthy(); + expect(Array.isArray(installList)).toBe(true); + expect(queryInstalledList).toBeTruthy(); + expect(Array.isArray(queryInstalledList)).toBe(true); + expect(commit).toBeTruthy(); + expect(packaging).toBeTruthy(); + expect(queryCommitted).toBeTruthy(); + + const assetId = uuidv4(); + const assetOwner = uuidv4(); + // CreateAsset(id string, color string, size int, owner string, appraisedValue int) + const createRes = await apiClient.runTransactionV1({ + contractName, + channelName, + params: [assetId, "Green", "19", assetOwner, "9999"], + methodName: "CreateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: { + keychainId, + keychainRef: keychainEntryKey, + }, + }); + expect(createRes).toBeTruthy(); + expect(createRes.status).toBeGreaterThan(199); + expect(createRes.status).toBeLessThan(300); + + console.log( + `BassicAssetTransfer.Create(): ${JSON.stringify(createRes.data)}`, + ); + + const getRes = await apiClient.runTransactionV1({ + contractName, + channelName, + params: [assetId], + methodName: "ReadAsset", + invocationType: FabricContractInvocationType.Call, + signingCredential: { + keychainId, + keychainRef: keychainEntryKey, + }, + }); + + expect(getRes).toBeTruthy(); + expect(getRes.data).toBeTruthy(); + expect(getRes.data.functionOutput).toBeTruthy(); + expect(getRes.status).toBeGreaterThan(199); + expect(getRes.status).toBeLessThan(300); + + console.log( + `HelloWorld.get() ResponseBody: ${JSON.stringify(getRes.data)}`, + ); + + const asset = JSON.parse(getRes.data.functionOutput); + + expect(asset).toBeTruthy(); + expect(asset.ID).toBeTruthy(); + expect(asset.ID).toEqual(assetId); + expect(asset.owner).toBeTruthy(); + expect(asset.owner).toEqual(assetOwner); }); - t.ok(getRes, "getRes truthy OK"); - t.ok(getRes.data, "getRes.data truthy OK"); - t.ok(getRes.data.functionOutput, "getRes.data.functionOutput truthy OK"); - t.true(getRes.status > 199 && createRes.status < 300, "getRes status 2xx OK"); - t.comment(`HelloWorld.get() ResponseBody: ${JSON.stringify(getRes.data)}`); - - const asset = JSON.parse(getRes.data.functionOutput); - - t.ok(asset, "JSON.parse(getRes.data.functionOutput) truthy OK"); - - t.ok(asset.ID, "asset.ID truthy OK"); - t.equal(asset.ID, assetId, "asset.ID === assetId truthy OK"); - - t.ok(asset.owner, "asset.owner truthy OK"); - t.equal(asset.owner, assetOwner, "asset.owner === assetOwner OK"); - - t.end(); }); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts index 1c3f38ea90b..6baa6f133f9 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts @@ -1,16 +1,15 @@ +import "jest-extended"; import { AddressInfo } from "net"; -import http from "http"; +import http, { Server } from "http"; import fs from "fs-extra"; import path from "path"; -import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import express from "express"; import bodyParser from "body-parser"; import { - Containers, DEFAULT_FABRIC_2_AIO_IMAGE_NAME, FABRIC_25_LTS_AIO_FABRIC_VERSION, FABRIC_25_LTS_AIO_IMAGE_VERSION, @@ -21,7 +20,6 @@ import { } from "@hyperledger/cactus-test-tooling"; import { - Checks, IListenOptions, LogLevelDesc, Servers, @@ -48,257 +46,230 @@ const testCase = "deploys Fabric 2.x contract from javascript source"; const logLevel: LogLevelDesc = "TRACE"; // Skipping due to test being flaky, see https://github.com/hyperledger/cactus/issues/1471 -test.skip("BEFORE " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); -}); - -// Skipping due to test being flaky, see https://github.com/hyperledger/cactus/issues/1471 -test(testCase, async (t: Test) => { +describe("Deploy CC from Javascript Source Test", () => { + let ledger: FabricTestLedgerV1; + const contractName = "basic-asset-transfer-2"; + const contractRelPath = + "../../fixtures/go/basic-asset-transfer/chaincode-javascript/"; + let apiClient: FabricApi; + let server: Server; const channelId = "mychannel"; const channelName = channelId; - - test.onFailure(async () => { - await Containers.logDiagnostics({ logLevel }); - }); - - const ledger = new FabricTestLedgerV1({ - emitContainerLogs: true, - publishAllPorts: true, - imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, - imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, - envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), - logLevel, + const keychainId = uuidv4(); + const keychainEntryKey = "user2"; + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.not.toThrow(); + ledger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, + envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), + logLevel, + }); + await ledger.start({ omitPull: false }); + const connectionProfile = await ledger.getConnectionProfileOrg1(); + expect(connectionProfile).toBeTruthy(); + const enrollAdminOut = await ledger.enrollAdmin(); + const adminWallet = enrollAdminOut[1]; + const [userIdentity] = await ledger.enrollUser(adminWallet); + const sshConfig = await ledger.getSshConfig(); + const keychainInstanceId = uuidv4(); + const keychainEntryValue = JSON.stringify(userIdentity); + const keychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, + keychainId, + logLevel, + backend: new Map([ + [keychainEntryKey, keychainEntryValue], + ["some-other-entry-key", "some-other-entry-value"], + ]), + }); + const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + dockerBinary: "/usr/local/bin/docker", + peerBinary: "/fabric-samples/bin/peer", + goBinary: "/usr/local/go/bin/go", + pluginRegistry, + cliContainerEnv: FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, + sshConfig, + logLevel, + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, + }, + }; + const plugin = new PluginLedgerConnectorFabric(pluginOptions); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { port } = addressInfo; + await plugin.getOrCreateWebServices(); + await plugin.registerWebServices(expressApp); + const apiUrl = `http://127.0.0.1:${port}`; + const config = new Configuration({ basePath: apiUrl }); + + apiClient = new FabricApi(config); }); - const tearDown = async () => { + afterAll(async () => { await ledger.stop(); await ledger.destroy(); await pruneDockerAllIfGithubAction({ logLevel }); - }; - - test.onFinish(tearDown); - await ledger.start({ omitPull: false }); - - const connectionProfile = await ledger.getConnectionProfileOrg1(); - t.ok(connectionProfile, "getConnectionProfileOrg1() out truthy OK"); - - const enrollAdminOut = await ledger.enrollAdmin(); - const adminWallet = enrollAdminOut[1]; - const [userIdentity] = await ledger.enrollUser(adminWallet); - const sshConfig = await ledger.getSshConfig(); - - const keychainInstanceId = uuidv4(); - const keychainId = uuidv4(); - const keychainEntryKey = "user2"; - const keychainEntryValue = JSON.stringify(userIdentity); - - const keychainPlugin = new PluginKeychainMemory({ - instanceId: keychainInstanceId, - keychainId, - logLevel, - backend: new Map([ - [keychainEntryKey, keychainEntryValue], - ["some-other-entry-key", "some-other-entry-value"], - ]), + await Servers.shutdown(server); }); - - const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); - - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; - - const pluginOptions: IPluginLedgerConnectorFabricOptions = { - instanceId: uuidv4(), - dockerBinary: "/usr/local/bin/docker", - peerBinary: "/fabric-samples/bin/peer", - goBinary: "/usr/local/go/bin/go", - pluginRegistry, - cliContainerEnv: FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, - sshConfig, - logLevel, - connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, - commitTimeout: 300, - }, - }; - const plugin = new PluginLedgerConnectorFabric(pluginOptions); - - const expressApp = express(); - expressApp.use(bodyParser.json({ limit: "250mb" })); - const server = http.createServer(expressApp); - const listenOptions: IListenOptions = { - hostname: "127.0.0.1", - port: 0, - server, - }; - const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; - const { port } = addressInfo; - test.onFinish(async () => await Servers.shutdown(server)); - - await plugin.getOrCreateWebServices(); - await plugin.registerWebServices(expressApp); - const apiUrl = `http://127.0.0.1:${port}`; - - const config = new Configuration({ basePath: apiUrl }); - - const apiClient = new FabricApi(config); - - const contractName = "basic-asset-transfer-2"; - - const contractRelPath = - "../../fixtures/go/basic-asset-transfer/chaincode-javascript/"; - const contractDir = path.join(__dirname, contractRelPath); - - // . - // ├── index.js - // ├── lib - // │ └── assetTransfer.js - // └── package.json - const sourceFiles: FileBase64[] = []; - { - const filename = "./package.json"; - const relativePath = "./"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, + test(`${testCase}`, async () => { + const contractDir = path.join(__dirname, contractRelPath); + // . + // ├── index.js + // ├── lib + // │ └── assetTransfer.js + // └── package.json + const sourceFiles: FileBase64[] = []; + { + const filename = "./package.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./index.js"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./assetTransfer.js"; + const relativePath = "./lib/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + const res = await apiClient.deployContractV1({ + channelId, + ccVersion: "1.0.0", + // constructorArgs: { Args: ["john", "99"] }, + sourceFiles, + ccName: contractName, + targetOrganizations: [ + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_2, + ], + caFile: + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1.ORDERER_TLS_ROOTCERT_FILE, + ccLabel: "basic-asset-transfer-2", + ccLang: ChainCodeProgrammingLanguage.Javascript, + ccSequence: 1, + orderer: "orderer.example.com:7050", + ordererTLSHostnameOverride: "orderer.example.com", + connTimeout: 60, }); - } - { - const filename = "./index.js"; - const relativePath = "./"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, + const { packageIds, lifecycle, success } = res.data; + expect(res.status).toBe(200); // Check if res.status is 200 + expect(success).toBeTruthy(); // Check if success is truthy + const { + approveForMyOrgList, + installList, + queryInstalledList, + commit, + packaging, + queryCommitted, + } = lifecycle; + expect(packageIds).toBeTruthy(); + expect(Array.isArray(packageIds)).toBe(true); + + expect(approveForMyOrgList).toBeTruthy(); + expect(Array.isArray(approveForMyOrgList)).toBe(true); + + expect(installList).toBeTruthy(); + expect(Array.isArray(installList)).toBe(true); + + expect(queryInstalledList).toBeTruthy(); + expect(Array.isArray(queryInstalledList)).toBe(true); + + expect(commit).toBeTruthy(); + expect(packaging).toBeTruthy(); + expect(queryCommitted).toBeTruthy(); + + const assetId = uuidv4(); + const assetOwner = uuidv4(); + // CreateAsset(id string, color string, size int, owner string, appraisedValue int) + const createRes = await apiClient.runTransactionV1({ + contractName, + channelName, + params: [assetId, "Green", "19", assetOwner, "9999"], + methodName: "CreateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: { + keychainId, + keychainRef: keychainEntryKey, + }, }); - } - { - const filename = "./assetTransfer.js"; - const relativePath = "./lib/"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, + expect(createRes).toBeTruthy(); + expect(createRes.status).toBeGreaterThan(199); + expect(createRes.status).toBeLessThan(300); + + console.log( + `BassicAssetTransfer.Create(): ${JSON.stringify(createRes.data)}`, + ); // Log the createRes data + + const getRes = await apiClient.runTransactionV1({ + contractName, + channelName, + params: [assetId], + methodName: "ReadAsset", + invocationType: FabricContractInvocationType.Call, + signingCredential: { + keychainId, + keychainRef: keychainEntryKey, + }, }); - } - - const res = await apiClient.deployContractV1({ - channelId, - ccVersion: "1.0.0", - // constructorArgs: { Args: ["john", "99"] }, - sourceFiles, - ccName: contractName, - targetOrganizations: [ - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_2, - ], - caFile: - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1.ORDERER_TLS_ROOTCERT_FILE, - ccLabel: "basic-asset-transfer-2", - ccLang: ChainCodeProgrammingLanguage.Javascript, - ccSequence: 1, - orderer: "orderer.example.com:7050", - ordererTLSHostnameOverride: "orderer.example.com", - connTimeout: 60, + expect(getRes).toBeTruthy(); + expect(getRes.data).toBeTruthy(); + expect(getRes.data.functionOutput).toBeTruthy(); + + expect(getRes.status).toBeGreaterThan(199); + expect(getRes.status).toBeLessThan(300); + + console.log( + `HelloWorld.get() ResponseBody: ${JSON.stringify(getRes.data)}`, + ); + const asset = JSON.parse(getRes.data.functionOutput); + expect(asset).toBeTruthy(); + expect(asset.ID).toBeTruthy(); + expect(asset.ID).toEqual(assetId); + + // Note: the capital spelling on "Owner" is not a bug. The fabric-samples + // repo has the spelling different from the golang chaincode as well. + expect(asset.Owner).toBeTruthy(); + expect(asset.Owner).toEqual(assetOwner); }); - - const { packageIds, lifecycle, success } = res.data; - t.equal(res.status, 200, "res.status === 200 OK"); - t.true(success, "res.data.success === true"); - - const { - approveForMyOrgList, - installList, - queryInstalledList, - commit, - packaging, - queryCommitted, - } = lifecycle; - - Checks.truthy(packageIds, `packageIds truthy OK`); - Checks.truthy( - Array.isArray(packageIds), - `Array.isArray(packageIds) truthy OK`, - ); - Checks.truthy(approveForMyOrgList, `approveForMyOrgList truthy OK`); - Checks.truthy( - Array.isArray(approveForMyOrgList), - `Array.isArray(approveForMyOrgList) truthy OK`, - ); - Checks.truthy(installList, `installList truthy OK`); - Checks.truthy( - Array.isArray(installList), - `Array.isArray(installList) truthy OK`, - ); - Checks.truthy(queryInstalledList, `queryInstalledList truthy OK`); - Checks.truthy( - Array.isArray(queryInstalledList), - `Array.isArray(queryInstalledList) truthy OK`, - ); - Checks.truthy(commit, `commit truthy OK`); - Checks.truthy(packaging, `packaging truthy OK`); - Checks.truthy(queryCommitted, `queryCommitted truthy OK`); - - const assetId = uuidv4(); - const assetOwner = uuidv4(); - - // CreateAsset(id string, color string, size int, owner string, appraisedValue int) - const createRes = await apiClient.runTransactionV1({ - contractName, - channelName, - params: [assetId, "Green", "19", assetOwner, "9999"], - methodName: "CreateAsset", - invocationType: FabricContractInvocationType.Send, - signingCredential: { - keychainId, - keychainRef: keychainEntryKey, - }, - }); - t.ok(createRes, "setRes truthy OK"); - t.true(createRes.status > 199, "createRes status > 199 OK"); - t.true(createRes.status < 300, "createRes status < 300 OK"); - t.comment(`BassicAssetTransfer.Create(): ${JSON.stringify(createRes.data)}`); - - const getRes = await apiClient.runTransactionV1({ - contractName, - channelName, - params: [assetId], - methodName: "ReadAsset", - invocationType: FabricContractInvocationType.Call, - signingCredential: { - keychainId, - keychainRef: keychainEntryKey, - }, - }); - t.ok(getRes, "getRes truthy OK"); - t.ok(getRes.data, "getRes.data truthy OK"); - t.ok(getRes.data.functionOutput, "getRes.data.functionOutput truthy OK"); - t.true(getRes.status > 199 && createRes.status < 300, "getRes status 2xx OK"); - t.comment(`HelloWorld.get() ResponseBody: ${JSON.stringify(getRes.data)}`); - - const asset = JSON.parse(getRes.data.functionOutput); - - t.ok(asset, "JSON.parse(getRes.data.functionOutput) truthy OK"); - - t.ok(asset.ID, "asset.ID truthy OK"); - t.equal(asset.ID, assetId, "asset.ID === assetId truthy OK"); - - // Note: the capital spelling on "Owner" is not a bug. The fabric-samples - // repo has the spelling different from the golang chaincode as well. - t.ok(asset.Owner, "asset.Owner truthy OK"); - t.equal(asset.Owner, assetOwner, "asset.owner === assetOwner OK"); - - t.end(); }); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-typescript-source.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-typescript-source.test.ts index 8e661616eb4..7cbf3585c41 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-typescript-source.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-typescript-source.test.ts @@ -1,16 +1,15 @@ +import "jest-extended"; import { AddressInfo } from "net"; -import http from "http"; +import http, { Server } from "http"; import fs from "fs-extra"; import path from "path"; -import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import express from "express"; import bodyParser from "body-parser"; import { - Containers, DEFAULT_FABRIC_2_AIO_IMAGE_NAME, FABRIC_25_LTS_AIO_FABRIC_VERSION, FABRIC_25_LTS_AIO_IMAGE_VERSION, @@ -21,7 +20,6 @@ import { } from "@hyperledger/cactus-test-tooling"; import { - Checks, IListenOptions, LogLevelDesc, Servers, @@ -47,291 +45,264 @@ import { Configuration } from "@hyperledger/cactus-core-api"; const testCase = "deploys Fabric 2.x contract from typescript source"; const logLevel: LogLevelDesc = "INFO"; -test("BEFORE " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); -}); - -test(testCase, async (t: Test) => { +describe("Deploy CC from typescript source test", () => { const channelId = "mychannel"; const channelName = channelId; - - test.onFailure(async () => { - await Containers.logDiagnostics({ logLevel }); - }); - - const ledger = new FabricTestLedgerV1({ - emitContainerLogs: true, - publishAllPorts: true, - imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, - imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, - envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), - logLevel, - }); - const tearDown = async () => { - await ledger.stop(); - await ledger.destroy(); - await pruneDockerAllIfGithubAction({ logLevel }); - }; - - test.onFinish(tearDown); - await ledger.start({ omitPull: false }); - - const connectionProfile = await ledger.getConnectionProfileOrg1(); - t.ok(connectionProfile, "getConnectionProfileOrg1() out truthy OK"); - - const enrollAdminOut = await ledger.enrollAdmin(); - const adminWallet = enrollAdminOut[1]; - const [userIdentity] = await ledger.enrollUser(adminWallet); - const sshConfig = await ledger.getSshConfig(); - - const keychainInstanceId = uuidv4(); + let ledger: FabricTestLedgerV1; const keychainId = uuidv4(); const keychainEntryKey = "user2"; - const keychainEntryValue = JSON.stringify(userIdentity); - - const keychainPlugin = new PluginKeychainMemory({ - instanceId: keychainInstanceId, - keychainId, - logLevel, - backend: new Map([ - [keychainEntryKey, keychainEntryValue], - ["some-other-entry-key", "some-other-entry-value"], - ]), - }); - - const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); - - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; - - const pluginOptions: IPluginLedgerConnectorFabricOptions = { - instanceId: uuidv4(), - dockerBinary: "/usr/local/bin/docker", - peerBinary: "/fabric-samples/bin/peer", - goBinary: "/usr/local/go/bin/go", - pluginRegistry, - cliContainerEnv: FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, - sshConfig, - logLevel, - connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, - commitTimeout: 300, - }, - }; - const plugin = new PluginLedgerConnectorFabric(pluginOptions); - - const expressApp = express(); - expressApp.use(bodyParser.json({ limit: "250mb" })); - const server = http.createServer(expressApp); - const listenOptions: IListenOptions = { - hostname: "127.0.0.1", - port: 0, - server, - }; - const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; - const { port } = addressInfo; - test.onFinish(async () => await Servers.shutdown(server)); - - await plugin.getOrCreateWebServices(); - await plugin.registerWebServices(expressApp); - const apiUrl = `http://127.0.0.1:${port}`; - - const config = new Configuration({ basePath: apiUrl }); - - const apiClient = new FabricApi(config); - + let apiClient: FabricApi; const contractName = "basic-asset-transfer-2"; - const contractRelPath = "../../fixtures/go/basic-asset-transfer/chaincode-typescript"; - const contractDir = path.join(__dirname, contractRelPath); - - // ├── package.json - // ├── src - // │ ├── assetTransfer.ts - // │ ├── asset.ts - // │ └── index.ts - // ├── tsconfig.json - // └── tslint.json - const sourceFiles: FileBase64[] = []; - { - const filename = "./tslint.json"; - const relativePath = "./"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, + let server: Server; + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.not.toThrow(); + ledger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, + envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), + logLevel, }); - } - { - const filename = "./tsconfig.json"; - const relativePath = "./"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./package.json"; - const relativePath = "./"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./index.ts"; - const relativePath = "./src/"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./asset.ts"; - const relativePath = "./src/"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./assetTransfer.ts"; - const relativePath = "./src/"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, + await ledger.start({ omitPull: false }); + const connectionProfile = await ledger.getConnectionProfileOrg1(); + expect(connectionProfile).toBeTruthy(); // Check if connectionProfile is truthy + const enrollAdminOut = await ledger.enrollAdmin(); + const adminWallet = enrollAdminOut[1]; + const [userIdentity] = await ledger.enrollUser(adminWallet); + const sshConfig = await ledger.getSshConfig(); + const keychainInstanceId = uuidv4(); + const keychainEntryValue = JSON.stringify(userIdentity); + const keychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, + keychainId, + logLevel, + backend: new Map([ + [keychainEntryKey, keychainEntryValue], + ["some-other-entry-key", "some-other-entry-value"], + ]), }); - } - - const res = await apiClient.deployContractV1({ - channelId, - ccVersion: "1.0.0", - // constructorArgs: { Args: ["john", "99"] }, - sourceFiles, - ccName: contractName, - targetOrganizations: [ - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_2, - ], - caFile: - FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1.ORDERER_TLS_ROOTCERT_FILE, - ccLabel: "basic-asset-transfer-2", - ccLang: ChainCodeProgrammingLanguage.Typescript, - ccSequence: 1, - orderer: "orderer.example.com:7050", - ordererTLSHostnameOverride: "orderer.example.com", - connTimeout: 60, + const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); + + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + dockerBinary: "/usr/local/bin/docker", + peerBinary: "/fabric-samples/bin/peer", + goBinary: "/usr/local/go/bin/go", + pluginRegistry, + cliContainerEnv: FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, + sshConfig, + logLevel, + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, + }, + }; + const plugin = new PluginLedgerConnectorFabric(pluginOptions); + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { port } = addressInfo; + await plugin.getOrCreateWebServices(); + await plugin.registerWebServices(expressApp); + const apiUrl = `http://127.0.0.1:${port}`; + + const config = new Configuration({ basePath: apiUrl }); + + apiClient = new FabricApi(config); }); - - const { packageIds, lifecycle, success } = res.data; - t.equal(res.status, 200, "res.status === 200 OK"); - t.true(success, "res.data.success === true"); - - const { - approveForMyOrgList, - installList, - queryInstalledList, - commit, - packaging, - queryCommitted, - } = lifecycle; - - Checks.truthy(packageIds, `packageIds truthy OK`); - Checks.truthy( - Array.isArray(packageIds), - `Array.isArray(packageIds) truthy OK`, - ); - Checks.truthy(approveForMyOrgList, `approveForMyOrgList truthy OK`); - Checks.truthy( - Array.isArray(approveForMyOrgList), - `Array.isArray(approveForMyOrgList) truthy OK`, - ); - Checks.truthy(installList, `installList truthy OK`); - Checks.truthy( - Array.isArray(installList), - `Array.isArray(installList) truthy OK`, - ); - Checks.truthy(queryInstalledList, `queryInstalledList truthy OK`); - Checks.truthy( - Array.isArray(queryInstalledList), - `Array.isArray(queryInstalledList) truthy OK`, - ); - Checks.truthy(commit, `commit truthy OK`); - Checks.truthy(packaging, `packaging truthy OK`); - Checks.truthy(queryCommitted, `queryCommitted truthy OK`); - - const assetId = uuidv4(); - const assetOwner = uuidv4(); - - // CreateAsset(id string, color string, size int, owner string, appraisedValue int) - const createRes = await apiClient.runTransactionV1({ - contractName, - channelName, - params: [assetId, "Green", "19", assetOwner, "9999"], - methodName: "CreateAsset", - invocationType: FabricContractInvocationType.Send, - signingCredential: { - keychainId, - keychainRef: keychainEntryKey, - }, + afterAll(async () => { + await ledger.stop(); + await ledger.destroy(); + await pruneDockerAllIfGithubAction({ logLevel }); + await Servers.shutdown(server); }); - t.ok(createRes, "setRes truthy OK"); - t.true(createRes.status > 199, "createRes status > 199 OK"); - t.true(createRes.status < 300, "createRes status < 300 OK"); - t.comment(`BassicAssetTransfer.Create(): ${JSON.stringify(createRes.data)}`); + test(`${testCase}`, async () => { + const contractDir = path.join(__dirname, contractRelPath); + // ├── package.json + // ├── src + // │ ├── assetTransfer.ts + // │ ├── asset.ts + // │ └── index.ts + // ├── tsconfig.json + // └── tslint.json + const sourceFiles: FileBase64[] = []; + { + const filename = "./tslint.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./tsconfig.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./package.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./index.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./asset.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./assetTransfer.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + const res = await apiClient.deployContractV1({ + channelId, + ccVersion: "1.0.0", + // constructorArgs: { Args: ["john", "99"] }, + sourceFiles, + ccName: contractName, + targetOrganizations: [ + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_2, + ], + caFile: + FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1.ORDERER_TLS_ROOTCERT_FILE, + ccLabel: "basic-asset-transfer-2", + ccLang: ChainCodeProgrammingLanguage.Typescript, + ccSequence: 1, + orderer: "orderer.example.com:7050", + ordererTLSHostnameOverride: "orderer.example.com", + connTimeout: 60, + }); - const getRes = await apiClient.runTransactionV1({ - contractName, - channelName, - params: [assetId], - methodName: "ReadAsset", - invocationType: FabricContractInvocationType.Call, - signingCredential: { - keychainId, - keychainRef: keychainEntryKey, - }, + const { packageIds, lifecycle, success } = res.data; + expect(res.status).toBe(200); + expect(success).toBeTruthy(); + + const { + approveForMyOrgList, + installList, + queryInstalledList, + commit, + packaging, + queryCommitted, + } = lifecycle; + expect(packageIds).toBeTruthy(); + expect(Array.isArray(packageIds)).toBeTruthy(); + expect(approveForMyOrgList).toBeTruthy(); + expect(Array.isArray(approveForMyOrgList)).toBeTruthy(); + expect(installList).toBeTruthy(); + expect(Array.isArray(installList)).toBeTruthy(); + expect(queryInstalledList).toBeTruthy(); + expect(Array.isArray(queryInstalledList)).toBeTruthy(); + expect(commit).toBeTruthy(); + expect(packaging).toBeTruthy(); + expect(queryCommitted).toBeTruthy(); + + const assetId = uuidv4(); + const assetOwner = uuidv4(); + + // CreateAsset(id string, color string, size int, owner string, appraisedValue int) + const createRes = await apiClient.runTransactionV1({ + contractName, + channelName, + params: [assetId, "Green", "19", assetOwner, "9999"], + methodName: "CreateAsset", + invocationType: FabricContractInvocationType.Send, + signingCredential: { + keychainId, + keychainRef: keychainEntryKey, + }, + }); + expect(createRes).toBeTruthy(); + expect(createRes.status).toBeGreaterThan(199); + expect(createRes.status).toBeLessThan(300); + console.log( + `BassicAssetTransfer.Create(): ${JSON.stringify(createRes.data)}`, + ); + + const getRes = await apiClient.runTransactionV1({ + contractName, + channelName, + params: [assetId], + methodName: "ReadAsset", + invocationType: FabricContractInvocationType.Call, + signingCredential: { + keychainId, + keychainRef: keychainEntryKey, + }, + }); + expect(getRes).toBeTruthy(); + expect(getRes.data).toBeTruthy(); + expect(getRes.data.functionOutput).toBeTruthy(); + expect(getRes.status).toBeGreaterThan(199); + expect(getRes.status).toBeLessThan(300); + + console.log( + `HelloWorld.get() ResponseBody: ${JSON.stringify(getRes.data)}`, + ); + const asset = JSON.parse(getRes.data.functionOutput); + expect(asset).toBeTruthy(); + + expect(asset.ID).toBeTruthy(); + expect(asset.ID).toEqual(assetId); + + // Note: the capital spelling on "Owner" is not a bug. The fabric-samples + // repo has the spelling different from the golang chaincode as well. + expect(asset.Owner).toBeTruthy(); + expect(asset.Owner).toEqual(assetOwner); }); - t.ok(getRes, "getRes truthy OK"); - t.ok(getRes.data, "getRes.data truthy OK"); - t.ok(getRes.data.functionOutput, "getRes.data.functionOutput truthy OK"); - t.true(getRes.status > 199 && createRes.status < 300, "getRes status 2xx OK"); - t.comment(`HelloWorld.get() ResponseBody: ${JSON.stringify(getRes.data)}`); - - const asset = JSON.parse(getRes.data.functionOutput); - - t.ok(asset, "JSON.parse(getRes.data.functionOutput) truthy OK"); - - t.ok(asset.ID, "asset.ID truthy OK"); - t.equal(asset.ID, assetId, "asset.ID === assetId truthy OK"); - - // Note: the capital spelling on "Owner" is not a bug. The fabric-samples - // repo has the spelling different from the golang chaincode as well. - t.ok(asset.Owner, "asset.Owner truthy OK"); - t.equal(asset.Owner, assetOwner, "asset.owner === assetOwner OK"); - - t.end(); }); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/obtain-profiles.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/obtain-profiles.test.ts index a61ef6ea4b3..44600030507 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/obtain-profiles.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/obtain-profiles.test.ts @@ -1,7 +1,4 @@ -// The TAP runner has a bug and prevents the test from passing in the CI when yarn "tap --ts ..."" is used -// if test is run with ts-node, it successfully executes -import test, { Test } from "tape-promise/tape"; - +import "jest-extended"; import { DEFAULT_FABRIC_2_AIO_IMAGE_NAME, FABRIC_25_LTS_AIO_FABRIC_VERSION, @@ -15,54 +12,38 @@ import { LogLevelDesc } from "@hyperledger/cactus-common"; const testCase = "obtains configuration profiles from Fabric 2.x ledger"; const logLevel: LogLevelDesc = "TRACE"; -test("BEFORE " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning did not throw OK"); - t.end(); -}); - -test(testCase, async (t: Test) => { - const ledger = new FabricTestLedgerV1({ - emitContainerLogs: true, - publishAllPorts: true, - imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, - imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, - envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), +describe("Obtain configuration profiles test", () => { + let ledger: FabricTestLedgerV1; + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.not.toThrow(); + ledger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, + envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), + }); + await ledger.start({ omitPull: false }); }); - const tearDown = async () => { + afterAll(async () => { await ledger.stop(); await ledger.destroy(); - }; - - test.onFinish(tearDown); - - await ledger.start({ omitPull: false }); - - const connectionProfile = await ledger.getConnectionProfileOrg1(); - - t.ok(connectionProfile, "getConnectionProfileOrg1() out truthy OK"); - - const connectionProfileOrg1 = await ledger.getConnectionProfileOrgX("org1"); - t.isEquivalent(connectionProfile, connectionProfileOrg1); - - const connectionProfileOrg2 = await ledger.getConnectionProfileOrgX("org2"); - t.ok(connectionProfileOrg2, "getConnectionProfileOrg2() out truthy OK"); - - t.notDeepEqual( - connectionProfileOrg1, - connectionProfileOrg2, - "connection profiles are different", - ); + }); + test(`${testCase}`, async () => { + const connectionProfile = await ledger.getConnectionProfileOrg1(); + expect(connectionProfile).toBeTruthy(); + const connectionProfileOrg1 = await ledger.getConnectionProfileOrgX("org1"); + expect(connectionProfile).toEqual(connectionProfileOrg1); - //Should return error, as there is no Org3 in the default deployment of Fabric AIO image - const error = "/no such container - Could not find the file.*/"; - await t.rejects(ledger.getConnectionProfileOrgX("org3"), error); + const connectionProfileOrg2 = await ledger.getConnectionProfileOrgX("org2"); + expect(connectionProfileOrg2).toBeTruthy(); - t.end(); -}); + expect(connectionProfileOrg1).not.toEqual(connectionProfileOrg2); -test("AFTER " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning did not throw OK"); - t.end(); + //Should return error, as there is no Org3 in the default deployment of Fabric AIO image + const error = "getConnectionProfileOrgX() crashed."; + const promise = ledger.getConnectionProfileOrgX("org3"); + await expect(promise).rejects.toThrow(error); + }); }); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-with-identities.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-with-identities.test.ts index 9554aeaf446..7ab8752dd52 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-with-identities.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-with-identities.test.ts @@ -1,5 +1,5 @@ +import "jest-extended"; import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; -import test, { Test } from "tape-promise/tape"; import { IPluginLedgerConnectorFabricOptions } from "../../../../main/typescript/plugin-ledger-connector-fabric"; import { v4 as uuidv4 } from "uuid"; import { LogLevelDesc } from "@hyperledger/cactus-common"; @@ -36,118 +36,115 @@ import axios from "axios"; // - make invoke (InitLedger) using 1st client // - make invoke (TransferAsset) using 2nd client (p384) client // - make query ("ReadAsset") using registrar(p256) -test("run-transaction-with-identities", async (t: Test) => { - test.onFailure(async () => { - await Containers.logDiagnostics({ logLevel }); - }); - - const ledger = new FabricTestLedgerV1({ - emitContainerLogs: true, - publishAllPorts: true, - imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, - imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, - envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), - logLevel, - }); - - const tearDown = async () => { - await ledger.stop(); - await ledger.destroy(); - await pruneDockerAllIfGithubAction({ logLevel }); - }; - - test.onFinish(tearDown); - await ledger.start({ omitPull: false }); - - const connectionProfile = await ledger.getConnectionProfileOrg1(); - t.ok(connectionProfile, "getConnectionProfileOrg1() out truthy OK"); +describe("Run transaction with identities", () => { const registrarKey = "registrar"; const client1Key = "client-default-"; const client2Key = "client-vault"; const keychainInstanceId = uuidv4(); const keychainId = uuidv4(); - ///// - const vaultTestContainer = new VaultTestServer({}); - await vaultTestContainer.start(); - - const ci = await Containers.getById(vaultTestContainer.containerId); - const vaultIpAddr = await internalIpV4(); - const hostPort = await Containers.getPublicPort( - K_DEFAULT_VAULT_HTTP_PORT, - ci, - ); - const vaultHost = `http://${vaultIpAddr}:${hostPort}`; - ///// - const vaultConfig: IVaultConfig = { - endpoint: vaultHost, - transitEngineMountPath: "/transit", - }; + let plugin: PluginLedgerConnectorFabric; + let ledger: FabricTestLedgerV1; + let vaultTestContainer: VaultTestServer; + let keychainPlugin: PluginKeychainMemory; const testToken = "myroot"; - { - // mount engine and create some test keys - const vaultHTTPClient = axios.create({ - baseURL: vaultConfig.endpoint + "/v1", - headers: { - "X-Vault-Token": testToken, - }, + beforeAll(async () => { + ledger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, + envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), + logLevel, }); - await vaultHTTPClient.post( - "/sys/mounts" + vaultConfig.transitEngineMountPath, - { type: "transit" }, - ); - await vaultHTTPClient.post( - vaultConfig.transitEngineMountPath + "/keys/" + registrarKey, - { - type: "ecdsa-p256", - }, + await ledger.start({ omitPull: false }); + const connectionProfile = await ledger.getConnectionProfileOrg1(); + expect(connectionProfile).toBeTruthy(); + + vaultTestContainer = new VaultTestServer({}); + await vaultTestContainer.start(); + + const ci = await Containers.getById(vaultTestContainer.containerId); + const vaultIpAddr = await internalIpV4(); + const hostPort = await Containers.getPublicPort( + K_DEFAULT_VAULT_HTTP_PORT, + ci, ); - await vaultHTTPClient.post( - vaultConfig.transitEngineMountPath + "/keys/" + client2Key, - { - type: "ecdsa-p384", + const vaultHost = `http://${vaultIpAddr}:${hostPort}`; + + ///// + const vaultConfig: IVaultConfig = { + endpoint: vaultHost, + transitEngineMountPath: "/transit", + }; + + { + // mount engine and create some test keys + const vaultHTTPClient = axios.create({ + baseURL: vaultConfig.endpoint + "/v1", + headers: { + "X-Vault-Token": testToken, + }, + }); + await vaultHTTPClient.post( + "/sys/mounts" + vaultConfig.transitEngineMountPath, + { type: "transit" }, + ); + await vaultHTTPClient.post( + vaultConfig.transitEngineMountPath + "/keys/" + registrarKey, + { + type: "ecdsa-p256", + }, + ); + await vaultHTTPClient.post( + vaultConfig.transitEngineMountPath + "/keys/" + client2Key, + { + type: "ecdsa-p384", + }, + ); + } + /// + keychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, + keychainId: keychainId, + logLevel, + }); + const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); + + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + const supportedIdentity: FabricSigningCredentialType[] = [ + FabricSigningCredentialType.VaultX509, + FabricSigningCredentialType.X509, + ]; + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + pluginRegistry, + sshConfig: {}, + cliContainerEnv: {}, + peerBinary: "not-required", + logLevel, + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, }, - ); - } - test.onFinish(async () => { + supportedIdentity, + vaultConfig: vaultConfig, + }; + plugin = new PluginLedgerConnectorFabric(pluginOptions); + }); + afterAll(async () => { + await ledger.stop(); + await ledger.destroy(); + await pruneDockerAllIfGithubAction({ logLevel }); await vaultTestContainer.stop(); await vaultTestContainer.destroy(); }); - /// - const keychainPlugin = new PluginKeychainMemory({ - instanceId: keychainInstanceId, - keychainId: keychainId, - logLevel, - }); - const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); - - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; - const supportedIdentity: FabricSigningCredentialType[] = [ - FabricSigningCredentialType.VaultX509, - FabricSigningCredentialType.X509, - ]; - - const pluginOptions: IPluginLedgerConnectorFabricOptions = { - instanceId: uuidv4(), - pluginRegistry, - sshConfig: {}, - cliContainerEnv: {}, - peerBinary: "not-required", - logLevel, - connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, - commitTimeout: 300, - }, - supportedIdentity, - vaultConfig: vaultConfig, - }; - const plugin = new PluginLedgerConnectorFabric(pluginOptions); - t.test("with-vaultKey", async (t: Test) => { + test(`test with-vaultKey`, async () => { { // enroll registrar using default identity await plugin.enroll( @@ -165,10 +162,10 @@ test("run-transaction-with-identities", async (t: Test) => { ); const rawCert = await keychainPlugin.get(registrarKey + "-x.509"); - t.ok(rawCert); + expect(rawCert).toBeTruthy(); const certData = JSON.parse(rawCert) as IIdentityData; - t.equal(certData.type, FabricSigningCredentialType.X509); - t.ok(certData.credentials.privateKey); + expect(certData.type).toEqual(FabricSigningCredentialType.X509); + expect(certData.credentials.privateKey).toBeTruthy(); } { // enroll registrar using vault identity @@ -191,10 +188,10 @@ test("run-transaction-with-identities", async (t: Test) => { ); const rawCert = await keychainPlugin.get(registrarKey + "-vault"); - t.ok(rawCert); + expect(rawCert).toBeTruthy(); const certData = JSON.parse(rawCert) as IIdentityData; - t.equal(certData.type, FabricSigningCredentialType.VaultX509); - t.notok(certData.credentials.privateKey); + expect(certData.type).toEqual(FabricSigningCredentialType.VaultX509); + expect(certData.credentials.privateKey).toBeFalsy(); } { // register a client1 using registrar's default x509 identity @@ -210,7 +207,7 @@ test("run-transaction-with-identities", async (t: Test) => { }, "ca.org1.example.com", ); - t.equal(secret, "pw"); + expect(secret).toEqual("pw"); } { // register a client using registrar's vault identity @@ -231,9 +228,8 @@ test("run-transaction-with-identities", async (t: Test) => { }, "ca.org1.example.com", ); - t.equal(secret, "pw"); + expect(secret).toEqual("pw"); } - { // enroll client client1 registered above await plugin.enroll( @@ -250,10 +246,10 @@ test("run-transaction-with-identities", async (t: Test) => { ); const rawCert = await keychainPlugin.get(client1Key); - t.ok(rawCert); + expect(rawCert).toBeTruthy(); const certData = JSON.parse(rawCert) as IIdentityData; - t.equal(certData.type, FabricSigningCredentialType.X509); - t.ok(certData.credentials.privateKey); + expect(certData.type).toEqual(FabricSigningCredentialType.X509); + expect(certData.credentials.privateKey).toBeTruthy(); } { // enroll client2 using vault identity @@ -276,11 +272,11 @@ test("run-transaction-with-identities", async (t: Test) => { ); const rawCert = await keychainPlugin.get(client2Key); - t.ok(rawCert, "rawCert truthy OK"); + expect(rawCert).toBeTruthy(); const { type, credentials } = JSON.parse(rawCert) as IIdentityData; const { privateKey } = credentials; - t.equal(type, FabricSigningCredentialType.VaultX509, "Cert is X509 OK"); - t.notok(privateKey, "certData.credentials.privateKey falsy OK"); + expect(type).toEqual(FabricSigningCredentialType.VaultX509); + expect(privateKey).toBeFalsy(); } // Temporary workaround here: Deploy a second contract because the default @@ -308,9 +304,10 @@ test("run-transaction-with-identities", async (t: Test) => { const timeout = 180000; // 3 minutes const cwd = "/fabric-samples/test-network/"; const out = await Containers.exec(container, cmd, timeout, logLevel, cwd); - t.ok(out, "deploy Basic2 command output truthy OK"); - t.comment("Output of Basic2 contract deployment below:"); - t.comment(out); + expect(out).toBeTruthy(); + console.log("Output of Basic2 contract deployment below:"); + console.log(out); + { // make invoke InitLedger using a client1 client await plugin.transact({ @@ -363,9 +360,7 @@ test("run-transaction-with-identities", async (t: Test) => { params: ["asset1"], }); const asset = JSON.parse(resp.functionOutput); - t.equal(asset.Owner, "client2"); + expect(asset.Owner).toEqual("client2"); } - t.end(); }); - t.end(); }); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/identity-client.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/identity-client.test.ts index c51f0d9c0f2..09ccadbf30d 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/identity-client.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/identity-client.test.ts @@ -1,3 +1,4 @@ +import "jest-extended"; import axios from "axios"; import { v4 as internalIpV4 } from "internal-ip"; import { @@ -7,7 +8,6 @@ import { WsTestServer, WS_IDENTITY_HTTP_PORT, } from "@hyperledger/cactus-test-tooling"; -import test, { Test } from "tape-promise/tape"; import { InternalIdentityClient } from "../../../main/typescript/identity/internal/client"; import { VaultTransitClient } from "../../../main/typescript/identity/vault-client"; import { WebSocketClient } from "../../../main/typescript/identity/web-socket-client"; @@ -18,19 +18,27 @@ import { KJUR } from "jsrsasign"; import { WsWallet, ECCurveType as ECCurveTypeW } from "ws-wallet"; import { WsIdentityClient } from "ws-identity-client"; -const logLevel: LogLevelDesc = "ERROR"; // a generic test suite for testing all the identity clients // supported by this package -test("identity-clients", async (t: Test) => { +describe("identity clients test", () => { + const logLevel: LogLevelDesc = "ERROR"; const testClients: Map = new Map(); const testECP256 = "test-ec-p256"; const testECP384 = "test-ec-p384"; const testNotFoundKey = "keyNotFound"; - { - const IpAdd = await internalIpV4(); - // + let wsTestContainer: WsTestServer; + let vaultTestContainer: VaultTestServer; + let IpAdd: string; + let wsWallet256: WsWallet; + let wsWallet384: WsWallet; + let vaultHost: string; + // let wsPathPrefix: any; + let wsUrl: string; + beforeAll(async () => { + IpAdd = (await internalIpV4()) as string; + // setup web-socket client - const wsTestContainer = new WsTestServer({ + wsTestContainer = new WsTestServer({ logLevel, imageVersion: "0.0.1", }); @@ -41,41 +49,31 @@ test("identity-clients", async (t: Test) => { ci, ); // setup vault client - const vaultTestContainer = new VaultTestServer({}); + vaultTestContainer = new VaultTestServer({}); await vaultTestContainer.start(); ci = await Containers.getById(vaultTestContainer.containerId); const hostPort = await Containers.getPublicPort( K_DEFAULT_VAULT_HTTP_PORT, ci, ); - - const vaultHost = `http://${IpAdd}:${hostPort}`; - const wsUrl = `http://${IpAdd}:${wsHostPort}`; + vaultHost = `http://${IpAdd}:${hostPort}`; + wsUrl = `http://${IpAdd}:${wsHostPort}`; // External client with private key - const wsWallet256 = new WsWallet({ + wsWallet256 = new WsWallet({ keyName: "256", logLevel, strictSSL: false, }); // establish session Id to be used by external client with p384 key - const wsWallet384 = new WsWallet({ + wsWallet384 = new WsWallet({ keyName: "384", curve: "p384" as ECCurveTypeW, logLevel, strictSSL: false, }); - test.onFinish(async () => { - await wsTestContainer.stop(); - await wsTestContainer.destroy(); - await vaultTestContainer.stop(); - await vaultTestContainer.destroy(); - await wsWallet384.close(); - await wsWallet256.close(); - }); - const mountPath = "/transit"; const testToken = "myroot"; // mount transit secret engine @@ -185,135 +183,141 @@ test("identity-clients", async (t: Test) => { }), ); } - } + }); + afterAll(async () => { + await wsTestContainer.stop(); + await wsTestContainer.destroy(); + await vaultTestContainer.stop(); + await vaultTestContainer.destroy(); + await wsWallet384.close(); + await wsWallet256.close(); + }); - // - for (const [clientName, client] of testClients) { + it("sign and verify for all clients", async () => { const digest = Buffer.from("Hello Cactus"); const hashDigest = createHash("sha256").update(digest).digest(); - t.test(`${clientName}::sign`, async (t: Test) => { + + for (const [clientName, client] of testClients.entries()) { + console.log("run 1"); if ( - clientName == "web-socket-client-256" || - clientName == "vault-client" + clientName === "web-socket-client-256" || + clientName === "vault-client" ) { const { sig, crv } = await client.sign(testECP256, hashDigest); - t.equal(crv, ECCurveType.P256); - t.ok(sig); - { - // asn1 encoding check - const pSig = (KJUR.crypto.ECDSA as any).parseSigHexInHexRS( - sig.toString("hex"), - ) as { r: string; s: string }; - const re = /[0-9A-Fa-f]{6}/g; - t.true(re.test(pSig.r)); - t.true(re.test(pSig.s)); - } + expect(crv).toBe(ECCurveType.P256); + expect(sig).toBeTruthy(); - { - // signature verification - const pub = await client.getPub(testECP256); - const verify = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" }); - verify.init(pub); - verify.updateHex(digest.toString("hex")); - t.true(verify.verify(sig.toString("hex"))); - } + // ASN.1 encoding check + const pSig = (KJUR.crypto.ECDSA as any).parseSigHexInHexRS( + sig.toString("hex"), + ); + const re = /[0-9A-Fa-f]{6}/g; + expect(re.test(pSig.r)).toBeTruthy(); + expect(re.test(pSig.s)).toBeTruthy(); + + // Signature verification + const pub = await client.getPub(testECP256); + const verify = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" }); + verify.init(pub); + verify.updateHex(digest.toString("hex")); + expect(verify.verify(sig.toString("hex"))).toBeTruthy(); } + if ( - clientName == "web-socket-client-384" || - clientName == "vault-client" + clientName === "web-socket-client-384" || + clientName === "vault-client" ) { const { sig, crv } = await client.sign(testECP384, hashDigest); - t.equal(crv, ECCurveType.P384); - t.ok(sig); - { - // asn1 encoding check - const pSig = (KJUR.crypto.ECDSA as any).parseSigHexInHexRS( - sig.toString("hex"), - ) as { r: string; s: string }; - const re = /[0-9A-Fa-f]{6}/g; - t.true(re.test(pSig.r)); - t.true(re.test(pSig.s)); - } + expect(crv).toBe(ECCurveType.P384); + expect(sig).toBeTruthy(); - { - // signature verification - const pub = await client.getPub(testECP384); - const verify = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" }); - verify.init(pub); - verify.updateHex(digest.toString("hex")); - t.true(verify.verify(sig.toString("hex"))); - } + // ASN.1 encoding check + const pSig = (KJUR.crypto.ECDSA as any).parseSigHexInHexRS( + sig.toString("hex"), + ); + const re = /[0-9A-Fa-f]{6}/g; + expect(re.test(pSig.r)).toBeTruthy(); + expect(re.test(pSig.s)).toBeTruthy(); + + // Signature verification + const pub = await client.getPub(testECP384); + const verify = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" }); + verify.init(pub); + verify.updateHex(digest.toString("hex")); + expect(verify.verify(sig.toString("hex"))).toBeTruthy(); } - t.end(); - }); - t.test(`${clientName}::getPub`, async (t: Test) => { + } + }); + + it("getPub for all clients", async () => { + for (const [clientName, client] of testClients.entries()) { + console.log("run 2"); if ( - clientName == "web-socket-client-256" || - clientName == "vault-client" + clientName === "web-socket-client-256" || + clientName === "vault-client" ) { const pub = await client.getPub(testECP256); - t.ok(pub); - t.equal((pub as any).curveName, "secp256r1"); + expect(pub).toBeTruthy(); + expect((pub as any).curveName).toBe("secp256r1"); } - if ( - //clientName == "web-socket-client-384" || - clientName == "vault-client" - ) { + if (clientName === "vault-client") { const pub = await client.getPub(testECP384); - t.ok(pub); - t.equal((pub as any).curveName, "secp384r1"); - } - if (clientName == "vault-client") { + expect(pub).toBeTruthy(); + expect((pub as any).curveName).toBe("secp384r1"); + try { await client.getPub(testNotFoundKey); - t.fail("Should not get here"); + throw new Error("Should not get here"); } catch (error) { - t.true( - (error as Error).message.includes( - `keyName = ${testNotFoundKey} not found`, - ), + expect((error as Error).message).toContain( + `keyName = ${testNotFoundKey} not found`, ); } } - t.end(); - }); - t.test(`${clientName}::rotateKey`, async (t: Test) => { - if (clientName == "vault-client") { - const pubOld = await client.getPub(testECP256); + } + }); + + it("rotateKey for all clients", async () => { + const digest = Buffer.from("Hello Cactus"); + const hashDigest = createHash("sha256").update(digest).digest(); + + for (const [clientName, client] of testClients.entries()) { + console.log("run 3"); + if (clientName === "vault-client") { + const pubOld256 = await client.getPub(testECP256); await client.rotateKey(testECP256); - const pubNew = await client.getPub(testECP256); - { - // public key should be different - t.notEqual(pubNew.getPublicKeyXYHex(), pubOld.getPublicKeyXYHex()); - } - { - // signature should be made using new key - const { sig } = await client.sign(testECP256, hashDigest); - const verify = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" }); - verify.init(pubOld); - verify.updateHex(digest.toString("hex")); - t.false(verify.verify(sig.toString("hex"))); - } + const pubNew256 = await client.getPub(testECP256); + + // Public key should be different + expect(pubNew256.getPublicKeyXYHex()).not.toBe( + pubOld256.getPublicKeyXYHex(), + ); + + // Signature should be made using the new key + const { sig } = await client.sign(testECP256, hashDigest); + const verify = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" }); + verify.init(pubOld256); + verify.updateHex(digest.toString("hex")); + expect(verify.verify(sig.toString("hex"))).toBeFalsy(); } - if (clientName == "vault-client") { - const pubOld = await client.getPub(testECP384); + + if (clientName === "vault-client") { + const pubOld384 = await client.getPub(testECP384); await client.rotateKey(testECP384); - const pubNew = await client.getPub(testECP384); - { - // public key should be different - t.notEqual(pubNew.getPublicKeyXYHex(), pubOld.getPublicKeyXYHex()); - } - { - // signature should be made using new key - const { sig } = await client.sign(testECP384, hashDigest); - const verify = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" }); - verify.init(pubOld); - verify.updateHex(digest.toString("hex")); - t.false(verify.verify(sig.toString("hex"))); - } + const pubNew384 = await client.getPub(testECP384); + + // Public key should be different + expect(pubNew384.getPublicKeyXYHex()).not.toBe( + pubOld384.getPublicKeyXYHex(), + ); + + // Signature should be made using the new key + const { sig } = await client.sign(testECP384, hashDigest); + const verify = new KJUR.crypto.Signature({ alg: "SHA256withECDSA" }); + verify.init(pubOld384); + verify.updateHex(digest.toString("hex")); + expect(verify.verify(sig.toString("hex"))).toBeFalsy(); } - t.end(); - }); - } - t.end(); + } + }); }); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts index 86cb932ed21..97c4c2f51f7 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation-go.test.ts @@ -1,54 +1,39 @@ +import "jest-extended"; import { AddressInfo } from "net"; import http from "http"; -import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import express from "express"; import bodyParser from "body-parser"; -import { - Containers, - pruneDockerAllIfGithubAction, -} from "@hyperledger/cactus-test-tooling"; +import { pruneDockerAllIfGithubAction } from "@hyperledger/cactus-test-tooling"; import { IListenOptions, LogLevelDesc, Servers, } from "@hyperledger/cactus-common"; import { PluginRegistry } from "@hyperledger/cactus-core"; - import { DefaultEventHandlerStrategy, PluginLedgerConnectorFabric, DeployContractGoSourceV1Request, } from "../../../../main/typescript/public-api"; - import { DefaultApi as FabricApi } from "../../../../main/typescript/public-api"; - import { IPluginLedgerConnectorFabricOptions } from "../../../../main/typescript/plugin-ledger-connector-fabric"; - import { DiscoveryOptions } from "fabric-network"; import { Configuration } from "@hyperledger/cactus-core-api"; - import { installOpenapiValidationMiddleware } from "@hyperledger/cactus-core"; import OAS from "../../../../main/json/openapi.json"; const testCase = "check openapi validation in fabric endpoints"; const logLevel: LogLevelDesc = "TRACE"; -test("BEFORE " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); -}); - -test(testCase, async (t: Test) => { - test.onFailure(async () => { - await Containers.logDiagnostics({ logLevel }); - }); - - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; +describe(testCase, () => { + let apiUrl: string; + let server: http.Server; + let plugin: PluginLedgerConnectorFabric; + let apiClient: FabricApi; + const fDeployGo = "deployContractGoSourceV1"; + const cWithoutParams = "not sending all required parameters"; + const cInvalidParams = "sending invalid parameters"; // these below mirror how the fabric-samples sets up the configuration const org1Env = { @@ -74,61 +59,63 @@ test(testCase, async (t: Test) => { "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem", }; - const pluginOptions: IPluginLedgerConnectorFabricOptions = { - instanceId: uuidv4(), - dockerBinary: "/usr/local/bin/docker", - pluginRegistry: new PluginRegistry({ plugins: [] }), - // pluginRegistry, - peerBinary: "/fabric-samples/bin/peer", - cliContainerEnv: org1Env, - sshConfig: new Configuration(), - // sshConfig, - logLevel, - connectionProfile: { - name: "", - version: "", - organizations: {}, - peers: {}, - }, - // connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, - commitTimeout: 300, - }, - }; - const plugin = new PluginLedgerConnectorFabric(pluginOptions); - - const expressApp = express(); - expressApp.use(bodyParser.json({ limit: "250mb" })); - const server = http.createServer(expressApp); - const listenOptions: IListenOptions = { - hostname: "127.0.0.1", - port: 0, - server, - }; - const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; - const { port } = addressInfo; - test.onFinish(async () => await Servers.shutdown(server)); - - await installOpenapiValidationMiddleware({ - logLevel, - app: expressApp, - apiSpec: OAS, + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.not.toThrow(); + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + dockerBinary: "/usr/local/bin/docker", + pluginRegistry: new PluginRegistry({ plugins: [] }), + peerBinary: "/fabric-samples/bin/peer", + cliContainerEnv: org1Env, + sshConfig: new Configuration(), + logLevel, + connectionProfile: { + name: "", + version: "", + organizations: {}, + peers: {}, + }, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, + }, + }; + plugin = new PluginLedgerConnectorFabric(pluginOptions); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + apiUrl = `http://127.0.0.1:${addressInfo.port}`; + const config = new Configuration({ basePath: apiUrl }); + apiClient = new FabricApi(config); + + await installOpenapiValidationMiddleware({ + logLevel, + app: expressApp, + apiSpec: OAS, + }); + + await plugin.getOrCreateWebServices(); + await plugin.registerWebServices(expressApp); }); - await plugin.getOrCreateWebServices(); - await plugin.registerWebServices(expressApp); - const apiUrl = `http://127.0.0.1:${port}`; - - const config = new Configuration({ basePath: apiUrl }); - const apiClient = new FabricApi(config); - - const fDeployGo = "deployContractGoSourceV1"; - const cWithoutParams = "not sending all required parameters"; - const cInvalidParams = "sending invalid parameters"; + afterAll(async () => { + await Servers.shutdown(server); + }); - test(`${testCase} - ${fDeployGo} - ${cWithoutParams}`, async (t2: Test) => { + test(`${testCase} - ${fDeployGo} - ${cWithoutParams}`, async () => { const parameters = { tlsRootCertFiles: "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", @@ -165,30 +152,22 @@ test(testCase, async (t: Test) => { "google.golang.org/grpc@v1.31.1", ], }; - - try { - await apiClient.deployContractGoSourceV1( - parameters as any as DeployContractGoSourceV1Request, - ); - } catch (e) { - t2.equal( - e.response.status, - 400, - `Endpoint ${fDeployGo} without required targetPeerAddresses: response.status === 400 OK`, - ); - const fields = e.response.data.map((param: any) => - param.path.replace("/body/", ""), - ); - t2.ok( - fields.includes("targetPeerAddresses"), - "Rejected because targetPeerAddresses is required", - ); - } - - t2.end(); + await expect( + apiClient.deployContractGoSourceV1( + parameters as DeployContractGoSourceV1Request, + ), + ).rejects.toMatchObject({ + response: expect.objectContaining({ + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("targetPeerAddresses"), + }), + ]), + }), + }); }); - - test(`${testCase} - ${fDeployGo} - ${cInvalidParams}`, async (t2: Test) => { + test(`${testCase} - ${fDeployGo} - ${cInvalidParams}`, async () => { const parameters = { targetPeerAddresses: ["peer0.org1.example.com:7051"], tlsRootCertFiles: @@ -227,34 +206,17 @@ test(testCase, async (t: Test) => { ], fake: 4, }; - - try { - await apiClient.deployContractGoSourceV1( - parameters as any as DeployContractGoSourceV1Request, - ); - } catch (e) { - t2.equal( - e.response.status, - 400, - `Endpoint ${fDeployGo} with fake=4: response.status === 400 OK`, - ); - const fields = e.response.data.map((param: any) => - param.path.replace("/body/", ""), - ); - t2.ok( - fields.includes("fake"), - "Rejected because fake is not a valid parameter", - ); - } - - t2.end(); + await expect( + apiClient.deployContractGoSourceV1(parameters), + ).rejects.toMatchObject({ + response: expect.objectContaining({ + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("fake"), + }), + ]), + }), + }); }); - - t.end(); -}); - -test("AFTER " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); }); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation.test.ts index f1006ecd743..bdaecd8c48e 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/openapi/openapi-validation.test.ts @@ -1,13 +1,11 @@ import { AddressInfo } from "net"; -import http from "http"; +import http, { Server } from "http"; import fs from "fs-extra"; import path from "path"; -import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import express from "express"; import bodyParser from "body-parser"; import { - Containers, DEFAULT_FABRIC_2_AIO_IMAGE_NAME, FABRIC_25_LTS_AIO_FABRIC_VERSION, FABRIC_25_LTS_AIO_IMAGE_VERSION, @@ -43,198 +41,186 @@ import OAS from "../../../../main/json/openapi.json"; const testCase = "deploys Fabric V2.5.6 contract from typescript source"; const logLevel: LogLevelDesc = "INFO"; -test("BEFORE " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); -}); - -test(testCase, async (t: Test) => { +describe("OpenApi Validation Test", () => { + let ledger: FabricTestLedgerV1; + let server: Server; + let apiClient: FabricApi; const channelId = "mychannel"; const channelName = channelId; - - test.onFailure(async () => { - await Containers.logDiagnostics({ logLevel }); - }); - - const ledger = new FabricTestLedgerV1({ - emitContainerLogs: true, - publishAllPorts: true, - imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, - imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, - envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), - logLevel, - }); - const tearDown = async () => { - await ledger.stop(); - await ledger.destroy(); - }; - - test.onFinish(tearDown); - await ledger.start({ omitPull: false }); - - const connectionProfile = await ledger.getConnectionProfileOrg1(); - t.ok(connectionProfile, "getConnectionProfileOrg1() out truthy OK"); - - const enrollAdminOut = await ledger.enrollAdmin(); - const adminWallet = enrollAdminOut[1]; - const [userIdentity] = await ledger.enrollUser(adminWallet); - const sshConfig = await ledger.getSshConfig(); - - const keychainInstanceId = uuidv4(); - const keychainId = uuidv4(); - const keychainEntryKey = "user2"; - const keychainEntryValue = JSON.stringify(userIdentity); - - const keychainPlugin = new PluginKeychainMemory({ - instanceId: keychainInstanceId, - keychainId, - logLevel, - backend: new Map([ - [keychainEntryKey, keychainEntryValue], - ["some-other-entry-key", "some-other-entry-value"], - ]), - }); - - const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); - - const discoveryOptions: DiscoveryOptions = { - enabled: true, - asLocalhost: true, - }; - - const pluginOptions: IPluginLedgerConnectorFabricOptions = { - instanceId: uuidv4(), - dockerBinary: "/usr/local/bin/docker", - peerBinary: "/fabric-samples/bin/peer", - goBinary: "/usr/local/go/bin/go", - pluginRegistry, - cliContainerEnv: FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, - sshConfig, - logLevel, - connectionProfile, - discoveryOptions, - eventHandlerOptions: { - strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, - commitTimeout: 300, - }, - }; - const plugin = new PluginLedgerConnectorFabric(pluginOptions); - - const expressApp = express(); - expressApp.use(bodyParser.json({ limit: "250mb" })); - const server = http.createServer(expressApp); - const listenOptions: IListenOptions = { - hostname: "127.0.0.1", - port: 0, - server, - }; - const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; - const { port } = addressInfo; - test.onFinish(async () => await Servers.shutdown(server)); - - await installOpenapiValidationMiddleware({ - logLevel, - app: expressApp, - apiSpec: OAS, - }); - - await plugin.getOrCreateWebServices(); - await plugin.registerWebServices(expressApp); - const apiUrl = `http://127.0.0.1:${port}`; - - const config = new Configuration({ basePath: apiUrl }); - - const apiClient = new FabricApi(config); - - const contractName = "basic-asset-transfer-2"; - - const contractRelPath = - "../../fixtures/go/basic-asset-transfer/chaincode-typescript"; - const contractDir = path.join(__dirname, contractRelPath); - - // ├── package.json - // ├── src - // │ ├── assetTransfer.ts - // │ ├── asset.ts - // │ └── index.ts - // ├── tsconfig.json - // └── tslint.json - const sourceFiles: FileBase64[] = []; - { - const filename = "./tslint.json"; - const relativePath = "./"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./tsconfig.json"; - const relativePath = "./"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./package.json"; - const relativePath = "./"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./index.ts"; - const relativePath = "./src/"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./asset.ts"; - const relativePath = "./src/"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - { - const filename = "./assetTransfer.ts"; - const relativePath = "./src/"; - const filePath = path.join(contractDir, relativePath, filename); - const buffer = await fs.readFile(filePath); - sourceFiles.push({ - body: buffer.toString("base64"), - filepath: relativePath, - filename, - }); - } - const fDeploy = "deployContractV1"; const fRun = "runTransactionV1"; const cOk = "without bad request error"; const cWithoutParams = "not sending all required parameters"; const cInvalidParams = "sending invalid parameters"; + const contractName = "basic-asset-transfer-2"; + const sourceFiles: FileBase64[] = []; + const keychainId = uuidv4(); + const keychainEntryKey = "user2"; + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.not.toThrow(); + ledger = new FabricTestLedgerV1({ + emitContainerLogs: true, + publishAllPorts: true, + imageName: DEFAULT_FABRIC_2_AIO_IMAGE_NAME, + imageVersion: FABRIC_25_LTS_AIO_IMAGE_VERSION, + envVars: new Map([["FABRIC_VERSION", FABRIC_25_LTS_AIO_FABRIC_VERSION]]), + logLevel, + }); + await ledger.start({ omitPull: false }); + const connectionProfile = await ledger.getConnectionProfileOrg1(); + expect(connectionProfile).toBeTruthy(); + const enrollAdminOut = await ledger.enrollAdmin(); + const adminWallet = enrollAdminOut[1]; + const [userIdentity] = await ledger.enrollUser(adminWallet); + const sshConfig = await ledger.getSshConfig(); + + const keychainInstanceId = uuidv4(); + const keychainEntryValue = JSON.stringify(userIdentity); + + const keychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, + keychainId, + logLevel, + backend: new Map([ + [keychainEntryKey, keychainEntryValue], + ["some-other-entry-key", "some-other-entry-value"], + ]), + }); + const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); - test(`${testCase} - ${fDeploy} - ${cOk}`, async (t2: Test) => { + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + dockerBinary: "/usr/local/bin/docker", + peerBinary: "/fabric-samples/bin/peer", + goBinary: "/usr/local/go/bin/go", + pluginRegistry, + cliContainerEnv: FABRIC_25_LTS_FABRIC_SAMPLES_ENV_INFO_ORG_1, + sshConfig, + logLevel, + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NetworkScopeAllfortx, + commitTimeout: 300, + }, + }; + const plugin = new PluginLedgerConnectorFabric(pluginOptions); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + const { port } = addressInfo; + await installOpenapiValidationMiddleware({ + logLevel, + app: expressApp, + apiSpec: OAS, + }); + + await plugin.getOrCreateWebServices(); + await plugin.registerWebServices(expressApp); + const apiUrl = `http://127.0.0.1:${port}`; + + const config = new Configuration({ basePath: apiUrl }); + + apiClient = new FabricApi(config); + + const contractRelPath = + "../../fixtures/go/basic-asset-transfer/chaincode-typescript"; + const contractDir = path.join(__dirname, contractRelPath); + + // ├── package.json + // ├── src + // │ ├── assetTransfer.ts + // │ ├── asset.ts + // │ └── index.ts + // ├── tsconfig.json + // └── tslint.json + // const sourceFiles: FileBase64[] = []; + { + const filename = "./tslint.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./tsconfig.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./package.json"; + const relativePath = "./"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./index.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./asset.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + { + const filename = "./assetTransfer.ts"; + const relativePath = "./src/"; + const filePath = path.join(contractDir, relativePath, filename); + const buffer = await fs.readFile(filePath); + sourceFiles.push({ + body: buffer.toString("base64"), + filepath: relativePath, + filename, + }); + } + }); + afterAll(async () => { + await ledger.stop(); + await ledger.destroy(); + await Servers.shutdown(server); + }); + test(`${testCase} - ${fDeploy} - ${cOk}`, async () => { const parameters = { channelId, ccVersion: "1.0.0", @@ -256,19 +242,12 @@ test(testCase, async (t: Test) => { const res = await apiClient.deployContractV1(parameters); - t2.equal( - res.status, - 200, - `Endpoint ${fDeploy}: response.status === 200 OK`, - ); - t2.true(res.data.success, "res.data.success === true"); - - t2.end(); + expect(res.status).toBe(200); + expect(res.data.success).toBe(true); }); - - test(`${testCase} - ${fDeploy} - ${cWithoutParams}`, async (t2: Test) => { + test(`${testCase} - ${fDeploy} - ${cWithoutParams}`, async () => { const parameters = { - // channelId, + // channelId is intentionally left out ccVersion: "1.0.0", sourceFiles, ccName: contractName, @@ -286,29 +265,22 @@ test(testCase, async (t: Test) => { connTimeout: 60, }; - try { - await apiClient.deployContractV1( + await expect( + apiClient.deployContractV1( parameters as unknown as DeployContractV1Request, - ); - } catch (e) { - t2.equal( - e.response.status, - 400, - `Endpoint ${fDeploy} without required channelId: response.status === 400 OK`, - ); - const fields = e.response.data.map((param: any) => - param.path.replace("/body/", ""), - ); - t2.ok( - fields.includes("channelId"), - "Rejected because channelId is required", - ); - } - - t2.end(); + ), + ).rejects.toMatchObject({ + response: expect.objectContaining({ + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/channelId"), + }), + ]), + }), + }); }); - - test(`${testCase} - ${fDeploy} - ${cInvalidParams}`, async (t2: Test) => { + test(`${testCase} - ${fDeploy} - ${cInvalidParams}`, async () => { const parameters = { channelId, ccVersion: "1.0.0", @@ -326,30 +298,25 @@ test(testCase, async (t: Test) => { orderer: "orderer.example.com:7050", ordererTLSHostnameOverride: "orderer.example.com", connTimeout: 60, - fake: 4, + fake: 4, // Invalid parameter }; - - try { - await apiClient.deployContractV1(parameters as DeployContractV1Request); - } catch (e) { - t2.equal( - e.response.status, - 400, - `Endpoint ${fDeploy} with fake=4: response.status === 400 OK`, - ); - const fields = e.response.data.map((param: any) => - param.path.replace("/body/", ""), - ); - t2.ok( - fields.includes("fake"), - "Rejected because fake is not a valid parameter", - ); - } - - t2.end(); + await expect( + apiClient.deployContractV1(parameters as DeployContractV1Request), + ).rejects.toThrow( + expect.objectContaining({ + response: expect.objectContaining({ + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("fake"), + }), + ]), + }), + }), + ); }); - - test(`${testCase} - ${fRun} - ${cOk}`, async (t2: Test) => { + test(`${testCase} - ${fRun} - ${cOk}`, async () => { + // Wait for 10 seconds await new Promise((resolve) => setTimeout(resolve, 10000)); const assetId = uuidv4(); @@ -366,19 +333,17 @@ test(testCase, async (t: Test) => { keychainRef: keychainEntryKey, }, }; + const res = await apiClient.runTransactionV1(parameters); - t2.ok(res, "res truthy OK"); - t2.equal(res.status, 200, `Endpoint ${fRun}: response.status === 200 OK`); - t2.end(); + expect(res).toBeTruthy(); + expect(res.status).toBe(200); }); - - test(`${testCase} - ${fRun} - ${cWithoutParams}`, async (t2: Test) => { + test(`${testCase} - ${fRun} - ${cWithoutParams}`, async () => { const assetId = uuidv4(); const assetOwner = uuidv4(); const parameters = { - // contractName, channelName, params: [assetId, "Green", "19", assetOwner, "9999"], methodName: "CreateAsset", @@ -388,28 +353,20 @@ test(testCase, async (t: Test) => { keychainRef: keychainEntryKey, }, }; - - try { - await apiClient.runTransactionV1(parameters as RunTransactionRequest); - } catch (e) { - t2.equal( - e.response.status, - 400, - `Endpoint ${fRun} without required contractName: response.status === 400 OK`, - ); - const fields = e.response.data.map((param: any) => - param.path.replace("/body/", ""), - ); - t2.ok( - fields.includes("contractName"), - "Rejected because contractName is required", - ); - } - - t2.end(); + await expect( + apiClient.runTransactionV1(parameters as RunTransactionRequest), + ).rejects.toMatchObject({ + response: expect.objectContaining({ + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/contractName"), + }), + ]), + }), + }); }); - - test(`${testCase} - ${fRun} - ${cInvalidParams}`, async (t2: Test) => { + test(`${testCase} - ${fRun} - ${cInvalidParams}`, async () => { const assetId = uuidv4(); const assetOwner = uuidv4(); @@ -423,34 +380,19 @@ test(testCase, async (t: Test) => { keychainId, keychainRef: keychainEntryKey, }, - fake: 4, + fake: 4, // Invalid parameter }; - - try { - await apiClient.runTransactionV1(parameters as RunTransactionRequest); - } catch (e) { - t2.equal( - e.response.status, - 400, - `Endpoint ${fRun} with fake=4: response.status === 400 OK`, - ); - const fields = e.response.data.map((param: any) => - param.path.replace("/body/", ""), - ); - t2.ok( - fields.includes("fake"), - "Rejected because fake is not a valid parameter", - ); - } - - t2.end(); + await expect( + apiClient.runTransactionV1(parameters as RunTransactionRequest), + ).rejects.toMatchObject({ + response: expect.objectContaining({ + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/fake"), + }), + ]), + }), + }); }); - - t.end(); -}); - -test("AFTER " + testCase, async (t: Test) => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await t.doesNotReject(pruning, "Pruning didn't throw OK"); - t.end(); }); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/unit/identity-internal-crypto-utils.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/unit/identity-internal-crypto-utils.test.ts index 5cbb3f2c9a8..474c8ca5e57 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/unit/identity-internal-crypto-utils.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/unit/identity-internal-crypto-utils.test.ts @@ -1,79 +1,71 @@ +import "jest-extended"; import { KEYUTIL, KJUR } from "jsrsasign"; -import test, { Test } from "tape"; import { CryptoUtil, ECCurveType, } from "../../../main/typescript/identity/internal/crypto-util"; + const KJ = KJUR as any; -test("cryptoUtil", (t: Test) => { - t.test("encodeASN1Sig", (t: Test) => { - { - const asn1Sig = - "MEYCIQDb+euisbUGQCpisQh9xEKof8zVNorerfhMHv3kWmuCfQIhAI8A3f21hAHga0WK6lS6cD/ZUtWVy/xsYZGGaldM7Tl3"; - const derSig = CryptoUtil.encodeASN1Sig( - Buffer.from(asn1Sig, "base64"), - ECCurveType.P256, - ); - const want = - "3045022100dbf9eba2b1b506402a62b1087dc442a87fccd5368adeadf84c1efde45a6b827d022070ff22014a7bfe2094ba7515ab458fbfe3942517db1b32236233606baf75ebda"; - t.equal(derSig.toString("hex"), want); - } - { - const asn1Sig = - "MGYCMQDFEvlhmQlTj7YGTjnZwERmj+/0IA2rDdb7F5iE1QLGQUUlHn353mizpFeXAcjWGH4CMQDZ1td1ISnjAPkUlohwjiJAShtaFITLG1NEr0G29Hgglt0mfvgJ0k2DXXy+mOyn57o="; - const derSig = CryptoUtil.encodeASN1Sig( - Buffer.from(asn1Sig, "base64"), - ECCurveType.P384, - ); - const want = - "3065023100c512f9619909538fb6064e39d9c044668feff4200dab0dd6fb179884d502c64145251e7df9de68b3a4579701c8d6187e02302629288aded61cff06eb69778f71ddbfb5e4a5eb7b34e4ac82b40bcaffbf0d487af38eba3ede59f78f6f5ad1e01d41b9"; - t.equal(derSig.toString("hex"), want); - } - { - const asn1Sig = - "MGYCMQDFEvlhmQlTj7YGTjnZwERmj+/0IA2rDdb7F5iE1QLGQUUlHn353mizpFeXAcjWGH4CMQDZ1td1ISnjAPkUlohwjiJAShtaFITLG1NEr0G29Hgglt0mfvgJ0k2DXXy+mOyn57o="; - try { - CryptoUtil.encodeASN1Sig( - Buffer.from(asn1Sig, "base64"), - "invalidCrv" as ECCurveType, - ); - } catch (error) { - t.equal( - "CryptoUtil#encodeASN1Sig invalid ec curve type", - (error as Error).message, - ); - } - } - t.end(); - }); +test("encodeASN1Sig for P256 curve", () => { + const asn1Sig = + "MEYCIQDb+euisbUGQCpisQh9xEKof8zVNorerfhMHv3kWmuCfQIhAI8A3f21hAHga0WK6lS6cD/ZUtWVy/xsYZGGaldM7Tl3"; + const derSig = CryptoUtil.encodeASN1Sig( + Buffer.from(asn1Sig, "base64"), + ECCurveType.P256, + ); + const want = + "3045022100dbf9eba2b1b506402a62b1087dc442a87fccd5368adeadf84c1efde45a6b827d022070ff22014a7bfe2094ba7515ab458fbfe3942517db1b32236233606baf75ebda"; + expect(derSig.toString("hex")).toBe(want); +}); + +test("encodeASN1Sig for P384 curve", () => { + const asn1Sig = + "MGYCMQDFEvlhmQlTj7YGTjnZwERmj+/0IA2rDdb7F5iE1QLGQUUlHn353mizpFeXAcjWGH4CMQDZ1td1ISnjAPkUlohwjiJAShtaFITLG1NEr0G29Hgglt0mfvgJ0k2DXXy+mOyn57o="; + const derSig = CryptoUtil.encodeASN1Sig( + Buffer.from(asn1Sig, "base64"), + ECCurveType.P384, + ); + const want = + "3065023100c512f9619909538fb6064e39d9c044668feff4200dab0dd6fb179884d502c64145251e7df9de68b3a4579701c8d6187e02302629288aded61cff06eb69778f71ddbfb5e4a5eb7b34e4ac82b40bcaffbf0d487af38eba3ede59f78f6f5ad1e01d41b9"; + expect(derSig.toString("hex")).toBe(want); +}); + +test("invalid curve type", () => { + const asn1Sig = + "MGYCMQDFEvlhmQlTj7YGTjnZwERmj+/0IA2rDdb7F5iE1QLGQUUlHn353mizpFeXAcjWGH4CMQDZ1td1ISnjAPkUlohwjiJAShtaFITLG1NEr0G29Hgglt0mfvgJ0k2DXXy+mOyn57o="; + + expect(() => { + CryptoUtil.encodeASN1Sig( + Buffer.from(asn1Sig, "base64"), + "invalidCrv" as ECCurveType, + ); + }).toThrow("CryptoUtil#encodeASN1Sig invalid ec curve type"); +}); - t.test("CSR", (t: Test) => { - const pem = `-----BEGIN PUBLIC KEY----- +test("CSR", () => { + const pem = `-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEziQUVVrao4nXmhe3jaMdsxAyszHY GfNTZZQn1F9PQCxOequ4XS4XFmng3MD8jkP58Sak/6QaXYvqAEB6pBT/gA== ------END PUBLIC KEY----- -`; - const csr = CryptoUtil.createCSR( - KEYUTIL.getKey(pem) as KJUR.crypto.ECDSA, - "Cactus", - ); - t.ok(csr); - const csrDigest = CryptoUtil.getCSRDigest(csr); - t.equal( - csrDigest.toString("base64"), - "S5E8XQhxbltjJLE2n3krEOC5cgmENCKtvUrj3AX4StY=", - ); - const signature = Buffer.from( - "MEYCIQDzWXNQkzf4DO2Ds7MJ4RdIdQfIGbsRpK5iQAmRWyQvpAIhAKVHJL2yFIQba/S09XccNCEZhfZW3XvFqY54rz4ZIjpV", - "base64", - ); - const csrPem = CryptoUtil.getPemCSR(csr, signature); - { - const csr = KJ.asn1.csr.CSRUtil.getParam(csrPem); - t.equal("/CN=Cactus", csr.subject.str); - } - t.end(); - }); - t.end(); +-----END PUBLIC KEY-----`; + + const csr = CryptoUtil.createCSR( + KEYUTIL.getKey(pem) as KJUR.crypto.ECDSA, + "Cactus", + ); + + expect(csr).toBeTruthy(); + const csrDigest = CryptoUtil.getCSRDigest(csr); + expect(csrDigest.toString("base64")).toBe( + "S5E8XQhxbltjJLE2n3krEOC5cgmENCKtvUrj3AX4StY=", + ); + + const signature = Buffer.from( + "MEYCIQDzWXNQkzf4DO2Ds7MJ4RdIdQfIGbsRpK5iQAmRWyQvpAIhAKVHJL2yFIQba/S09XccNCEZhfZW3XvFqY54rz4ZIjpV", + "base64", + ); + + const csrPem = CryptoUtil.getPemCSR(csr, signature); + const csrParams = KJ.asn1.csr.CSRUtil.getParam(csrPem); + expect(csrParams.subject.str).toBe("/CN=Cactus"); });