Skip to content

Commit

Permalink
test: add backup e2e scenarios (#242)
Browse files Browse the repository at this point in the history
Signed-off-by: Allain Magyar <[email protected]>
  • Loading branch information
amagyar-iohk authored Jul 3, 2024
1 parent a22d3dd commit 447869c
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 18 deletions.
25 changes: 25 additions & 0 deletions integration-tests/e2e-tests/features/backup.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@backup
Feature: Backup
The Edge Agent should be able to create and restore a backup

Scenario: Create and restore a backup
Given Edge Agent has created a backup
Then a new SDK can be restored from Edge Agent

Scenario: Agent without a seed should not be able to restore the backup
Given Edge Agent has created a backup
Then a new SDK cannot be restored from Edge Agent with wrong seed

Scenario: Restored backup should be functional
Given Cloud Agent is connected to Edge Agent
And Edge Agent has '1' jwt credentials issued by Cloud Agent
And Edge Agent creates '5' peer DIDs
And Edge Agent creates '3' prism DIDs
And Edge Agent has created a backup
Then a new Restored Agent is restored from Edge Agent
And Restored Agent should have the expected values from Edge Agent
And Edge Agent is dismissed
Given Cloud Agent is connected to Restored Agent
And Cloud Agent asks for present-proof
And Restored Agent sends the present-proof
Then Cloud Agent should see the present-proof is verified
8 changes: 5 additions & 3 deletions integration-tests/e2e-tests/src/abilities/WalletSdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class WalletSdk extends Ability implements Initialisable, Discardable {
}
}

async initialise(): Promise<void> {
async createSdk(seed: SDK.Domain.Seed = undefined) {
const apollo = new Apollo()
this.store = new SDK.Store({
name: [...Array(30)].map(() => Math.random().toString(36)[2]).join(""),
Expand All @@ -80,7 +80,7 @@ export class WalletSdk extends Ability implements Initialisable, Discardable {
})
const pluto = new SDK.Pluto(this.store, apollo)
const mediatorDID = Domain.DID.fromString(await WalletSdk.getMediatorDidThroughOob())
this.sdk = Agent.initialize({ apollo, pluto, mediatorDID })
this.sdk = Agent.initialize({ seed, apollo, pluto, mediatorDID })

this.sdk.addListener(
ListenerKey.MESSAGE, (messages: SDK.Domain.Message[]) => {
Expand All @@ -89,7 +89,10 @@ export class WalletSdk extends Ability implements Initialisable, Discardable {
}
}
)
}

async initialise(): Promise<void> {
await this.createSdk()
await this.sdk.start()
}

Expand All @@ -114,7 +117,6 @@ class MessageQueue {
revocationStack: Message[] = []
receivedMessages: string[] = []


enqueue(message: Message) {
this.queue.push(message)

Expand Down
81 changes: 70 additions & 11 deletions integration-tests/e2e-tests/src/steps/EdgeAgentSteps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,26 @@ Given("{actor} has '{int}' anonymous credentials issued by {actor}",
await EdgeAgentWorkflow.processIssuedCredential(edgeAgent, recordId)
})
await cloudAgent.attemptsTo(Notepad.notes().set("recordIdList", recordIdList))
})
}
)

Given("{actor} has created a backup",
async function(edgeAgent: Actor) {
await EdgeAgentWorkflow.createBackup(edgeAgent)
}
)

Given("{actor} creates '{}' peer DIDs",
async function(edgeAgent: Actor, numberOfDids: number) {
await EdgeAgentWorkflow.createPeerDids(edgeAgent, numberOfDids)
}
)

Given("{actor} creates '{}' prism DIDs",
async function(edgeAgent: Actor, numberOfDids: number) {
await EdgeAgentWorkflow.createPrismDids(edgeAgent, numberOfDids)
}
)

When("{actor} accepts {int} jwt credential offer sequentially from {actor}",
async function (edgeAgent: Actor, numberOfCredentialOffers: number, cloudAgent: Actor) {
Expand All @@ -48,7 +67,8 @@ When("{actor} accepts {int} jwt credential offer sequentially from {actor}",
recordIdList.push(recordId)
})
await cloudAgent.attemptsTo(Notepad.notes().set("recordIdList", recordIdList))
})
}
)

When("{actor} accepts {int} jwt credentials offer at once from {actor}",
async function (edgeAgent: Actor, numberOfCredentials: number, cloudAgent: Actor) {
Expand All @@ -65,55 +85,94 @@ When("{actor} accepts {int} jwt credentials offer at once from {actor}",
await Utils.repeat(numberOfCredentials, async () => {
await EdgeAgentWorkflow.acceptCredential(edgeAgent)
})
})
}
)

When("{actor} connects through the invite",
async function (edgeAgent: Actor) {
await EdgeAgentWorkflow.connect(edgeAgent)
})
}
)

When("{actor} accepts the credentials offer from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const recordIdList = await cloudAgent.answer(Notepad.notes().get("recordIdList"))
Utils.repeat(recordIdList.length, async () => {
await EdgeAgentWorkflow.acceptCredential(edgeAgent)
})
})
}
)

When("{actor} sends the present-proof",
async function (edgeAgent: Actor) {
await EdgeAgentWorkflow.waitForProofRequest(edgeAgent)
await EdgeAgentWorkflow.presentProof(edgeAgent)
})
}
)

Then("{actor} should receive the credentials offer from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const recordIdList = await cloudAgent.answer(Notepad.notes().get("recordIdList"))
await EdgeAgentWorkflow.waitForCredentialOffer(edgeAgent, recordIdList.length)
})
}
)

Then("{actor} waits to receive the revocation notifications from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const revokedRecordIdList = await cloudAgent.answer(Notepad.notes().get("revokedRecordIdList"))
await EdgeAgentWorkflow.waitForCredentialRevocationMessage(edgeAgent, revokedRecordIdList.length)
})
}
)

Then("{actor} should see the credentials were revoked by {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const revokedRecordIdList = await cloudAgent.answer(Notepad.notes().get("revokedRecordIdList"))
await EdgeAgentWorkflow.waitUntilCredentialIsRevoked(edgeAgent, revokedRecordIdList)
})
}
)

Then("{actor} process issued credentials from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const recordIdList = await cloudAgent.answer<string[]>(Notepad.notes().get("recordIdList"))
for (const recordId of recordIdList) {
await EdgeAgentWorkflow.processIssuedCredential(edgeAgent, recordId)
}
})
}
)

Then("{actor} wait to receive issued credentials from {actor}",
async function (edgeAgent: Actor, cloudAgent: Actor) {
const recordIdList = await cloudAgent.answer(Notepad.notes().get("recordIdList"))
await EdgeAgentWorkflow.waitToReceiveCredentialIssuance(edgeAgent, recordIdList.length)
})
}
)

Then("a new SDK can be restored from {actor}",
async function(edgeAgent: Actor) {
await EdgeAgentWorkflow.createNewWalletFromBackup(edgeAgent)
}
)

Then("a new SDK cannot be restored from {actor} with wrong seed",
async function(edgeAgent: Actor) {
await EdgeAgentWorkflow.createNewWalletFromBackupWithWrongSeed(edgeAgent)
}
)

Then("a new {actor} is restored from {actor}",
async function(newAgent: Actor, edgeAgent: Actor) {
await EdgeAgentWorkflow.backupAndRestoreToNewAgent(newAgent, edgeAgent)
}
)

Then("{actor} should have the expected values from {actor}",
async function(copyEdgeAgent: Actor, originalEdgeAgent: Actor) {
await EdgeAgentWorkflow.copyAgentShouldMatchOriginalAgent(copyEdgeAgent, originalEdgeAgent)
}
)

Then("{actor} is dismissed",
async function(edgeAgent: Actor) {
await edgeAgent.dismiss()
}
)
3 changes: 1 addition & 2 deletions integration-tests/e2e-tests/src/steps/LifecycleSteps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class Actors implements Cast {
actors.add(cloudAgent)
actors.add(edgeAgent)
actors.add(verifierEdgeAgent)

engage(actors)
}

Expand All @@ -48,7 +47,7 @@ class Actors implements Cast {

prepare(actor: Actor): Actor {
if (!this.actors.has(actor.name)) {
throw new Error(`Unable to find actor ${actor.name}`)
return actor
}
return this.actors.get(actor.name)!
}
Expand Down
113 changes: 111 additions & 2 deletions integration-tests/e2e-tests/src/workflow/EdgeAgentWorkflow.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import SDK from "@atala/prism-wallet-sdk"
import { Actor, Duration, Notepad, Wait } from "@serenity-js/core"
import { Actor, Duration, Notepad, TakeNotes, Wait } from "@serenity-js/core"
import { Ensure, equals } from "@serenity-js/assertions"
import { WalletSdk } from "../abilities/WalletSdk"
import { Utils } from "../Utils"
import { randomUUID } from "crypto"
import _ from "lodash"
import { assert } from "chai"

const { IssueCredential, OfferCredential, RequestPresentation, } = SDK

export class EdgeAgentWorkflow {


static async connect(edgeAgent: Actor) {
const url = await edgeAgent.answer<string>(Notepad.notes().get("invitation"))
await edgeAgent.attemptsTo(
Expand Down Expand Up @@ -120,4 +122,111 @@ export class EdgeAgentWorkflow {
})
)
}

static async createPeerDids(edgeAgent: Actor, numberOfDids: number) {
await edgeAgent.attemptsTo(
WalletSdk.execute(async sdk => {
await Utils.repeat(numberOfDids, async () => {
await sdk.createNewPeerDID()
})
})
)
}

static async createPrismDids(edgeAgent: Actor, numberOfDids: number) {
await edgeAgent.attemptsTo(
WalletSdk.execute(async sdk => {
await Utils.repeat(numberOfDids, async () => {
await sdk.createNewPrismDID(randomUUID())
})
})
)
}

static async copyAgentShouldMatchOriginalAgent(copyEdgeAgent: Actor, originalEdgeAgent: Actor) {
let expectedCredentials: SDK.Domain.Credential[]
let expectedPeerDids: SDK.PeerDID[]
let expectedPrismDids: SDK.Domain.PrismDID[]
let expectedDidPairs: SDK.Domain.DIDPair[]

await originalEdgeAgent.attemptsTo(
WalletSdk.execute(async sdk => {
expectedCredentials = await sdk.verifiableCredentials()
expectedPeerDids = await sdk.pluto.getAllPeerDIDs()
expectedPrismDids = await sdk.pluto.getAllPrismDIDs()
expectedDidPairs = await sdk.pluto.getAllDidPairs()
})
)

await copyEdgeAgent.attemptsTo(
WalletSdk.execute(async sdk => {
const credentials = await sdk.verifiableCredentials()
const peerDids = await sdk.pluto.getAllPeerDIDs()
const prismDids = await sdk.pluto.getAllPrismDIDs()
const didPairs = await sdk.pluto.getAllDidPairs()

await copyEdgeAgent.attemptsTo(
Ensure.that(credentials.length, equals(expectedCredentials.length)),
Ensure.that(peerDids.length, equals(expectedPeerDids.length)),
Ensure.that(prismDids.length, equals(expectedPrismDids.length)),
Ensure.that(didPairs.length, equals(expectedDidPairs.length)),
)

assert.isTrue(_.isEqual(expectedCredentials.map(it => it.id), credentials.map(it => it.id)))
assert.isTrue(_.isEqual(expectedPeerDids.map(it => it.did.uuid), peerDids.map(it => it.did.uuid)))
assert.isTrue(_.isEqual(expectedPrismDids.map(it => it.did.uuid), prismDids.map(it => it.did.uuid)))
assert.isTrue(_.isEqual(expectedDidPairs.map(it => it.name), expectedDidPairs.map(it => it.name)))
})
)
}


static async createBackup(edgeAgent: Actor) {
await edgeAgent.attemptsTo(
WalletSdk.execute(async (sdk) => {
const backup = await sdk.backup.createJWE()
await edgeAgent.attemptsTo(
Notepad.notes().set("backup", backup),
Notepad.notes().set("seed", sdk.seed)
)
})
)
}

static async createNewWalletFromBackup(edgeAgent: Actor) {
const backup = await edgeAgent.answer(Notepad.notes().get("backup"))
const seed = await edgeAgent.answer(Notepad.notes().get("seed"))
const walletSdk = new WalletSdk()
await walletSdk.createSdk(seed)
await walletSdk.sdk.pluto.start()
await walletSdk.sdk.backup.restore(backup)
await walletSdk.sdk.start()
await walletSdk.sdk.stop()
}

static async createNewWalletFromBackupWithWrongSeed(edgeAgent: Actor) {
const backup = await edgeAgent.answer(Notepad.notes().get("backup"))
const walletSdk = new WalletSdk()
const seed = new SDK.Apollo().createRandomSeed().seed
await walletSdk.createSdk(seed)
await walletSdk.sdk.pluto.start()

try {
await walletSdk.sdk.backup.restore(backup)
assert.fail("SDK should not be able to restore with wrong seed phrase.")
} catch (e) {
assert.isTrue(e != undefined)
}
}

static async backupAndRestoreToNewAgent(newAgent: Actor, edgeAgent: Actor) {
const backup = await edgeAgent.answer(Notepad.notes().get("backup"))
const seed = await edgeAgent.answer(Notepad.notes().get("seed"))
const walletSdk = new WalletSdk()
await walletSdk.createSdk(seed)
await walletSdk.sdk.pluto.start()
await walletSdk.sdk.backup.restore(backup)
await walletSdk.sdk.start()
newAgent.whoCan(walletSdk, TakeNotes.usingAnEmptyNotepad())
}
}

1 comment on commit 447869c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines Statements Branches Functions
Coverage: 75%
75.2% (2781/3698) 64.93% (1352/2082) 80.53% (720/894)

JUnit

Tests Skipped Failures Errors Time
501 6 💤 0 ❌ 0 🔥 1m 15s ⏱️

Please sign in to comment.