diff --git a/README-TODO.md b/README-TODO.md index 59ca993f..f620b0c7 100644 --- a/README-TODO.md +++ b/README-TODO.md @@ -54,7 +54,7 @@ If you need your conductor to be configured in a really specific way, fear not, > 3. Conductors from different scenarios must remain independent and invisible to each other -To achieve the independence of conductors, Tryorama ensure that various values are unique. It uses UUIDs during DNA config as well as for Agent IDs to ensure unique values; it ensures that it automatically creates temp directories for file storage when necessary, adding the paths to the config. So how can we let Tryorama handle these concerns while still generating a custom config? The answer is in a key concept: +To achieve the independence of conductors, Tryorama ensure that various values are unique. It uses UIDs during DNA config as well as for Agent IDs to ensure unique values; it ensures that it automatically creates temp directories for file storage when necessary, adding the paths to the config. So how can we let Tryorama handle these concerns while still generating a custom config? The answer is in a key concept: **Players are configured by giving them *functions* that generate their config**. For instance, when you call `Config.gen`, it's actually creating a function for you like this: @@ -63,7 +63,7 @@ To achieve the independence of conductors, Tryorama ensure that various values a const config = Config.gen({alice: dnaConfig}) // becomes this -const config = ({playerName, uuid, configDir, adminInterfacePort}) => { +const config = ({playerName, uid, configDir, adminInterfacePort}) => { return { environment_path: configDir, network: {/* ... */}, @@ -80,7 +80,7 @@ Config seeds take an object as a parameter, with five values: * `scenarioName`: the name of the current scenario, i.e. `registerScenario(scenarioName, ...)` * `playerName`: the name of the player for this conductor, e.g. `"alice"` -* `uuid`: a UUID which is guaranteed to be the same within a scenario but unique between different scenarios +* `uid`: a UID which is guaranteed to be the same within a scenario but unique between different scenarios * `configDir`: a temp dir created specifically for this conductor * `adminInterfacePort`: a free port on the machine which is used for the admin Websocket interface @@ -90,7 +90,7 @@ Under the hood, Tryorama generates unique and valid values for these parameters * There must be an admin interface running over WebSockets at `adminInterfacePort` which includes all instances that are part of this test * *All* agents within a scenario must have a unique name (even across different conductors!) -* You must incorporate the UUID or some other source of uniqueness into the DNA config's `uuid` field, to ensure that conductors in different tests do not attempt to connect to each other on the same network +* You must incorporate the UID or some other source of uniqueness into the DNA config's `uid` field, to ensure that conductors in different tests do not attempt to connect to each other on the same network ### Using seed functions in `Config.gen` @@ -99,12 +99,12 @@ Since configuring a full config that properly uses these injected values is real ```js Config.gen( {alice: dnaConfig}, - ({playerName, uuid}) => { + ({playerName, uid}) => { return { dpki: { instance_id: 'my-instance', init_params: JSON.stringify({ - someValueThatNeedsToBeUnique: uuid, + someValueThatNeedsToBeUnique: uid, someValueThatWantsToBeThePlayerName: playerName, }) } diff --git a/README.md b/README.md index 57cf200c..a5681188 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ An end-to-end/scenario testing framework for Holochain applications, written in Tryorama allows you to write test suites about the behavior of multiple Holochain nodes which are networked together, while ensuring that test nodes in different tests do not accidentally join a network together. -Note: this version of tryorama is tested against holochain rev a82372a62d46a503e48f345360d0fb18cc5822d1. Please see [testing Readme](test/README.md) for details on how to run tryorama's own tests. +Note: this version of tryorama is tested against holochain rev 8d6c4cd29bd17e8224aeffb87dc03eaf3ff33508. Please see [testing Readme](test/README.md) for details on how to run tryorama's own tests. ```bash npm install @holochain/tryorama @@ -100,7 +100,7 @@ orchestrator.registerScenario('proper zome call', async (s, t) => { // or install a happ using // - a previously generated key // - and the hash of a dna that was previously registered with the same conductor - // (a dna can be registered either by installing a happ with that dna or by calling registerDna with an old dna's hash and a new UUID) + // (a dna can be registered either by installing a happ with that dna or by calling registerDna with an old dna's hash and a new UID) const blogDnaHash = carol_test_happ.cells[0].dnaHash() const derivedDnaHash = await carol.registerDna({hash: blogDnaHash}, "1234567890") const carol_derived_happ_with_bobs_test_key = await carol.installHapp([derivedDnaHash], bob_blog_happ.agent) diff --git a/ci_scripts/install-holochain.sh b/ci_scripts/install-holochain.sh index 11f27aca..c8827151 100755 --- a/ci_scripts/install-holochain.sh +++ b/ci_scripts/install-holochain.sh @@ -1,6 +1,6 @@ #!/bin/bash -REV=a82372a62d46a503e48f345360d0fb18cc5822d1 +REV=8d6c4cd29bd17e8224aeffb87dc03eaf3ff33508 LAIR_REV=a01a40640574d3cfabae33dfe3f861de7bd7a57c export CARGO_TARGET_DIR="$PWD/target" diff --git a/package.json b/package.json index 9254ec67..0c4a8915 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "git", "url": "https://github.com/holochain/tryorama" }, - "version": "0.4.1", + "version": "0.4.2", "description": "test framework for holochain hApps", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -24,7 +24,7 @@ "author": "", "license": "Apache-2.0", "dependencies": { - "@holochain/conductor-api": "^0.0.1", + "@holochain/conductor-api": "^0.0.3", "@holochain/hachiko": "^0.5.2", "@iarna/toml": "^2.2.5", "@msgpack/msgpack": "^2.1.0", diff --git a/src/api.ts b/src/api.ts index 4f71306c..f475effd 100644 --- a/src/api.ts +++ b/src/api.ts @@ -28,19 +28,19 @@ export class ScenarioApi { _localPlayers: Array _trycpClients: Array - _uuid: string + _uid: string _waiter: Waiter _modifiers: Modifiers _activityTimer: any _conductorIndex: number - constructor(description: string, orchestratorData, uuid: string, modifiers: Modifiers = { singleConductor: false }) { + constructor(description: string, orchestratorData, uid: string, modifiers: Modifiers = { singleConductor: false }) { this.description = description this.fail = (reason) => { throw new Error(`s.fail: ${reason}`) } this._localPlayers = [] this._trycpClients = [] - this._uuid = uuid + this._uid = uid this._waiter = new Waiter(FullSyncNetwork, undefined, orchestratorData.waiterConfig) this._modifiers = modifiers this._activityTimer = null @@ -132,7 +132,7 @@ export class ScenarioApi { await trycpClient.configurePlayer(playerName, configJson) logger.debug('api.players: player config committed for %s', playerName) return new Player({ - scenarioUUID: this._uuid, + scenarioUID: this._uid, name: playerName, config: configJson, spawnConductor: spawnRemote(trycpClient), @@ -160,7 +160,7 @@ export class ScenarioApi { logger.debug('api.players: player config committed for %s', playerName) return new Player({ - scenarioUUID: this._uuid, + scenarioUID: this._uid, name: playerName, config: configYaml, spawnConductor: spawnLocal(configDir, adminInterfacePort, appInterfacePort), @@ -175,7 +175,7 @@ export class ScenarioApi { const configSeedArgs: T.ConfigSeedArgs = _.assign(partialConfigSeedArgs, { scenarioName: this.description, playerName, - uuid: this._uuid + uid: this._uid }) logger.debug('api.players: seed args generated for %s = %j', playerName, configSeedArgs) const configJson = configSeed(configSeedArgs) diff --git a/src/conductor.ts b/src/conductor.ts index 56272fd3..eec7a875 100644 --- a/src/conductor.ts +++ b/src/conductor.ts @@ -1,5 +1,5 @@ const colors = require('colors/safe') -import { v4 as uuidGen } from 'uuid' +import { v4 as uidGen } from 'uuid' import { KillFn } from "./types"; import { makeLogger } from "./logger"; @@ -139,7 +139,7 @@ export class Conductor { } // this function registers a DNA from a given source - registerDna = async (source: T.DnaSource, uuid?, properties?): Promise => { + registerDna = async (source: T.DnaSource, uid?, properties?): Promise => { if ("path" in source && "saveDnaRemote" in this._backend) { const contents = () => new Promise((resolve, reject) => { fs.readFile((source as { path: string }).path, null, (err, data) => { @@ -158,29 +158,30 @@ export class Conductor { } source = await this._backend.downloadDnaRemote((source as T.DnaUrl).url) } - const registerDnaReq: RegisterDnaRequest = { ...source, uuid, properties } + const registerDnaReq: RegisterDnaRequest = { ...source, uid, properties } return await this.adminClient!.registerDna(registerDnaReq) } // this function will install an app bundle as generated by hc app pack - installBundledHapp = async (bundleSource: AppBundleSource, agentPubKey?: AgentPubKey, installedAppId?: string): Promise => { + installBundledHapp = async (bundleSource: AppBundleSource, agentPubKey?: AgentPubKey, installedAppId?: string, uid?: string): Promise => { if (!agentPubKey) { agentPubKey = await this.adminClient!.generateAgentPubKey() } - const bundleInstalledAppId = installedAppId || `app-${uuidGen()}` + const bundleInstalledAppId = installedAppId || `app-${uidGen()}` const installAppBundleReq: InstallAppBundleRequest = { ...bundleSource, installed_app_id: bundleInstalledAppId, agent_key: agentPubKey, - membrane_proofs: {} + membrane_proofs: {}, + uid } return await this._installBundledHapp(installAppBundleReq) } // install a hApp using the InstallAppBundleRequest struct from conductor-admin-api // you must create your own app_id and bundle, this is useful also if you - // need to pass in uuid, properties or membrane-proof + // need to pass in uid, properties or membrane-proof _installBundledHapp = async (installAppBundleReq: InstallAppBundleRequest): Promise => { const installedApp: InstalledApp = await this.adminClient!.installAppBundle(installAppBundleReq) @@ -197,7 +198,7 @@ export class Conductor { } const dnaSources = agentHapp const installAppReq: InstallAppRequest = { - installed_app_id: `app-${uuidGen()}`, + installed_app_id: `app-${uidGen()}`, agent_key: agentPubKey, dnas: await Promise.all(dnaSources.map(async (src, index) => { let source: T.DnaSource @@ -210,8 +211,8 @@ export class Conductor { } let dna = { - hash: await this.registerDna(source, this._player.scenarioUUID), - nick: `${index}${src}-${uuidGen()}`, + hash: await this.registerDna(source, this._player.scenarioUID), + nick: `${index}${src}-${uidGen()}`, } return dna })) @@ -266,7 +267,7 @@ export class Conductor { } const {port: appInterfacePort} = await this.adminClient!.attachAppInterface({ port: appPortNumber }) console.log("App Port spun up on port ", appInterfacePort); - + switch (this._backend.type) { case "local": diff --git a/src/config/gen.ts b/src/config/gen.ts index ecfb4994..d0e1c7dd 100644 --- a/src/config/gen.ts +++ b/src/config/gen.ts @@ -16,7 +16,7 @@ const defaultCommonConfig = { export const gen = ( commonConfig: T.CommonConfig = {} ): T.ConfigSeed => ( args: T.ConfigSeedArgs ): T.RawConductorConfig => { - const { configDir, adminInterfacePort, uuid } = args + const { configDir, adminInterfacePort, uid } = args const keystorePath = path.join(configDir, 'keystore'); // don't put any keys on this object that you want to fall back to defaults diff --git a/src/orchestrator.ts b/src/orchestrator.ts index 48238f18..6ffcf905 100644 --- a/src/orchestrator.ts +++ b/src/orchestrator.ts @@ -1,4 +1,4 @@ -import { v4 as uuidGen } from 'uuid' +import { v4 as uidGen } from 'uuid' import * as _ from 'lodash' import * as T from "./types"; import * as M from "./middleware"; @@ -161,11 +161,10 @@ export class Orchestrator { '_globalConfig', 'waiterConfig', ]) - const api = new ScenarioApi(desc, orchestratorData, uuidGen()) + const api = new ScenarioApi(desc, orchestratorData, uidGen()) const runner = scenario => scenario(api) const execute = () => this._middleware(runner, scenario) this._scenarios.push({ api, desc, execute, modifier }) } } - diff --git a/src/player.ts b/src/player.ts index 3876ceca..d07b3c5c 100644 --- a/src/player.ts +++ b/src/player.ts @@ -14,7 +14,7 @@ import { TunneledAdminClient, TunneledAppClient } from './trycp'; const fs = require('fs').promises type ConstructorArgs = { - scenarioUUID: string, + scenarioUID: string, name: string, config: RawConductorConfig, adminInterfacePort?: number, @@ -41,20 +41,20 @@ export class Player { onLeave: () => void onSignal: ((signal: any) => void) | null = null onActivity: () => void - scenarioUUID: string + scenarioUID: string _conductor: Conductor | null _adminInterfacePort?: number _spawnConductor: SpawnConductorFn - constructor({ scenarioUUID, name, config, adminInterfacePort, onJoin, onLeave, onActivity, spawnConductor }: ConstructorArgs) { + constructor({ scenarioUID, name, config, adminInterfacePort, onJoin, onLeave, onActivity, spawnConductor }: ConstructorArgs) { this.name = name this.logger = makeLogger(`player ${name}`) this.onJoin = onJoin this.onLeave = onLeave this.onActivity = onActivity this.config = config - this.scenarioUUID = scenarioUUID, + this.scenarioUID = scenarioUID, this._conductor = null this._adminInterfacePort = adminInterfacePort diff --git a/src/types.ts b/src/types.ts index bb00e9cc..5b4c47f5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -44,7 +44,7 @@ export type CommonConfig = { export type ConfigSeedArgs = PartialConfigSeedArgs & { scenarioName: string, playerName: string, - uuid: string, + uid: string, } // export type PlayerConfigs = ObjectS diff --git a/test/common.ts b/test/common.ts index b4112d8e..a6ce52a7 100644 --- a/test/common.ts +++ b/test/common.ts @@ -45,6 +45,6 @@ export const genConfigArgs: () => Promise = async () => ({ adminInterfacePort: 1000, playerName: 'playerName', scenarioName: 'scenarioName', - uuid: 'uuid', + uid: 'uid', }) export const spawnConductor = (() => { }) as unknown as T.SpawnConductorFn diff --git a/test/e2e/fixture/dna.yaml b/test/e2e/fixture/dna.yaml index 6db1e242..4927291a 100644 --- a/test/e2e/fixture/dna.yaml +++ b/test/e2e/fixture/dna.yaml @@ -1,7 +1,7 @@ --- manifest_version: "1" name: test-dna -uuid: 9a28aac8-337c-11eb-adc1-0Z02acw20115 +uid: 9a28aac8-337c-11eb-adc1-0Z02acw20115 properties: ~ zomes: - name: test diff --git a/test/e2e/fixture/happ.yaml b/test/e2e/fixture/happ.yaml index 7fea73c5..9ffb1c80 100644 --- a/test/e2e/fixture/happ.yaml +++ b/test/e2e/fixture/happ.yaml @@ -10,6 +10,6 @@ slots: dna: bundled: ./test.dna properties: ~ - uuid: ~ + uid: ~ version: ~ clone_limit: 0 diff --git a/test/unit/test-api.ts b/test/unit/test-api.ts index dbdeeff7..e86ff1bf 100644 --- a/test/unit/test-api.ts +++ b/test/unit/test-api.ts @@ -5,7 +5,7 @@ import { Orchestrator } from '../../src'; test('API complains if a non-function was used for config', async t => { const orchestrator = new Orchestrator({ middleware: undefined }) - const api = new ScenarioApi("description", orchestrator, "uuid") + const api = new ScenarioApi("description", orchestrator, "uid") await t.rejects( // @ts-ignore api.players([{}]),