Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(e2e): wallet restoration load test
- use artillery as load test engine - add wallet restoration scenario - update readme with usage
- Loading branch information
Ivaylo Andonov
committed
Nov 22, 2022
1 parent
3b7c820
commit 9be492d
Showing
13 changed files
with
470 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Logger | ||
TL_LEVEL=info | ||
|
||
# Providers setup | ||
FAUCET_PROVIDER=cardano-wallet | ||
FAUCET_PROVIDER_PARAMS='{"baseUrl":"http://localhost:8090/v2","mnemonic":"fire method repair aware foot tray accuse brother popular olive find account sick rocket next"}' | ||
KEY_MANAGEMENT_PROVIDER=inMemory | ||
KEY_MANAGEMENT_PARAMS='{"accountIndex": 0, "networkId": 0, "password":"some_password","mnemonic":"vacant violin soft weird deliver render brief always monitor general maid smart jelly core drastic erode echo there clump dizzy card filter option defense"}' | ||
ASSET_PROVIDER=http | ||
ASSET_PROVIDER_PARAMS='{"baseUrl":"http://localhost:4000/asset"}' | ||
CHAIN_HISTORY_PROVIDER=http | ||
CHAIN_HISTORY_PROVIDER_PARAMS='{"baseUrl":"http://localhost:4000/chain-history"}' | ||
NETWORK_INFO_PROVIDER=http | ||
NETWORK_INFO_PROVIDER_PARAMS='{"baseUrl":"http://localhost:4000/network-info"}' | ||
REWARDS_PROVIDER=http | ||
REWARDS_PROVIDER_PARAMS='{"baseUrl":"http://localhost:4000/rewards"}' | ||
TX_SUBMIT_PROVIDER=http | ||
TX_SUBMIT_PROVIDER_PARAMS='{"baseUrl":"http://localhost:4000/tx-submit"}' | ||
UTXO_PROVIDER=http | ||
UTXO_PROVIDER_PARAMS='{"baseUrl":"http://localhost:4000/utxo"}' | ||
STAKE_POOL_PROVIDER=http | ||
STAKE_POOL_PROVIDER_PARAMS='{"baseUrl":"http://localhost:4000/stake-pool"}' | ||
|
||
DB_SYNC_CONNECTION_STRING='postgresql://postgres:doNoUseThisSecret!@localhost:5432/cexplorer' | ||
OGMIOS_SERVER_URL='ws://localhost:1340/' | ||
|
||
# Wallet restoration load test scenario | ||
ARRIVAL_PHASE_DURATION_IN_SECS=60 | ||
WALLETS_COUNT=20 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './factories'; | ||
export * from './FaucetProvider'; | ||
export * from './util/StubKeyAgent'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { | ||
AccountAddressDerivationPath, | ||
AccountKeyDerivationPath, | ||
GroupedAddress, | ||
KeyAgent, | ||
SerializableKeyAgentData, | ||
SignBlobResult, | ||
SignTransactionOptions | ||
} from '@cardano-sdk/key-management'; | ||
import { Cardano, NotImplementedError } from '@cardano-sdk/core'; | ||
|
||
export class StubKeyAgent implements KeyAgent { | ||
readonly #knownAddresses: GroupedAddress[]; | ||
|
||
constructor(groupedAddress: GroupedAddress) { | ||
this.#knownAddresses = [groupedAddress]; | ||
} | ||
|
||
get knownAddresses(): GroupedAddress[] { | ||
return this.#knownAddresses; | ||
} | ||
|
||
get networkId(): Cardano.NetworkId { | ||
throw new NotImplementedError('networkId'); | ||
} | ||
|
||
get accountIndex(): number { | ||
throw new NotImplementedError('accountIndex'); | ||
} | ||
|
||
get serializableData(): SerializableKeyAgentData { | ||
throw new NotImplementedError('serializableData'); | ||
} | ||
|
||
get extendedAccountPublicKey(): Cardano.Bip32PublicKey { | ||
throw new NotImplementedError('extendedAccountPublicKey'); | ||
} | ||
|
||
deriveAddress(_derivationPath: AccountAddressDerivationPath): Promise<GroupedAddress> { | ||
throw new NotImplementedError('deriveAddress'); | ||
} | ||
|
||
derivePublicKey(_derivationPath: AccountKeyDerivationPath): Promise<Cardano.Ed25519PublicKey> { | ||
throw new NotImplementedError('derivePublicKey'); | ||
} | ||
|
||
signBlob(_derivationPath: AccountKeyDerivationPath, _blob: Cardano.util.HexBlob): Promise<SignBlobResult> { | ||
throw new NotImplementedError('signBlob'); | ||
} | ||
|
||
signTransaction( | ||
_txInternals: Cardano.TxBodyWithHash, | ||
_options?: SignTransactionOptions | undefined | ||
): Promise<Cardano.Signatures> { | ||
throw new NotImplementedError('signTransaction'); | ||
} | ||
|
||
exportRootPrivateKey(): Promise<Cardano.Bip32PrivateKey> { | ||
throw new NotImplementedError('exportRootPrivateKey'); | ||
} | ||
} |
84 changes: 84 additions & 0 deletions
84
packages/e2e/test/artillery/wallet-restoration/WalletRestoration.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { AddressType, GroupedAddress } from '@cardano-sdk/key-management'; | ||
import { AddressesModel, WalletVars } from './types'; | ||
import { Cardano } from '@cardano-sdk/core'; | ||
import { FunctionHook } from '../artillery'; | ||
import { Pool, QueryResult } from 'pg'; | ||
import { StubKeyAgent, getWallet } from '../../../src'; | ||
import { env } from '../../environment'; | ||
import { findAddressesWithRewardsHistory } from './queries'; | ||
import { logger } from '@cardano-sdk/util-dev'; | ||
import { walletReady } from '../../util'; | ||
|
||
const operationName = 'wallet-restoration'; | ||
const SHORTAGE_OF_WALLETS_FOUND_ERROR_MESSAGE = 'Addresses found from db are less than desired wallets count'; | ||
|
||
const mapToGroupedAddress = (addrModel: AddressesModel): GroupedAddress => ({ | ||
accountIndex: 0, | ||
address: Cardano.Address(addrModel.address), | ||
index: 0, | ||
networkId: addrModel.address.startsWith('addr_test') ? Cardano.NetworkId.testnet : Cardano.NetworkId.mainnet, | ||
rewardAccount: Cardano.RewardAccount(addrModel.stake_address), | ||
type: AddressType.External | ||
}); | ||
|
||
export const findAddresses: FunctionHook<WalletVars> = async ({ vars }, ee, done) => { | ||
vars.walletsCount = Number(env.WALLETS_COUNT); | ||
const db: Pool = new Pool({ connectionString: env.DB_SYNC_CONNECTION_STRING }); | ||
|
||
try { | ||
logger.info('About to query db for distinct addresses'); | ||
const result: QueryResult<AddressesModel> = await db.query(findAddressesWithRewardsHistory, [vars.walletsCount]); | ||
logger.info('Found addresses count', result.rowCount); | ||
|
||
vars.addresses = result.rows.map(mapToGroupedAddress); | ||
} catch (error) { | ||
ee.emit('counter', 'findAddresses.error', 1); | ||
logger.error('Error thrown while performing findAddresses db sync query', error); | ||
} | ||
|
||
if (vars.addresses.length < vars.walletsCount) { | ||
logger.error(SHORTAGE_OF_WALLETS_FOUND_ERROR_MESSAGE); | ||
throw new Error(SHORTAGE_OF_WALLETS_FOUND_ERROR_MESSAGE); | ||
} | ||
done(); | ||
}; | ||
|
||
export const walletRestoration: FunctionHook<WalletVars> = async ({ vars, _uid }, ee, done) => { | ||
let index = 0; | ||
return (async () => { | ||
const currentAddress = vars.addresses[index]; | ||
|
||
try { | ||
const keyAgent = new StubKeyAgent(currentAddress); | ||
|
||
// Start to measure wallet restoration time | ||
const startedAt = Date.now(); | ||
const { wallet } = await getWallet({ | ||
env, | ||
idx: 0, | ||
keyAgent, | ||
logger, | ||
name: `Test Wallet of VU with id: ${_uid}`, | ||
polling: { interval: 50 } | ||
}); | ||
await walletReady(wallet); | ||
vars.currentWallet = wallet; | ||
|
||
// Emit custom metrics | ||
ee.emit('histogram', `${operationName}.time`, Date.now() - startedAt); | ||
ee.emit('counter', operationName, 1); | ||
|
||
logger.info(`Wallet with name ${wallet.name} is successfully restored`); | ||
} catch (error) { | ||
ee.emit('counter', `${operationName}.error`, 1); | ||
logger.error(error); | ||
} | ||
++index; | ||
done(); | ||
})(); | ||
}; | ||
|
||
export const shutdownWallet: FunctionHook<WalletVars> = async ({ vars }, _ee, done) => { | ||
vars.currentWallet.shutdown(); | ||
done(); | ||
}; |
22 changes: 22 additions & 0 deletions
22
packages/e2e/test/artillery/wallet-restoration/WalletRestoration.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
config: | ||
# target is a required field for artillery, but it is actually | ||
# ignored since we are not using artillery to perform the HTTP requests. | ||
target: "http://localhost" | ||
http: | ||
timeout: 180 | ||
phases: | ||
- name: 'Restore wallet' | ||
# The duration of an arrival phase determines only how long virtual users will be generated for. It is not the same as the duration of a test run. | ||
duration: "{{$processEnvironment.ARRIVAL_PHASE_DURATION_IN_SECS}}" | ||
# Fixed number of arrivals (VUs) per second | ||
arrivalCount: "{{$processEnvironment.WALLETS_COUNT}}" | ||
processor: "./WalletRestoration.ts" | ||
before: | ||
flow: | ||
- log: "Find distinct addresses from DB" | ||
- function: "findAddresses" | ||
scenarios: | ||
- name: "Wallet restoration" | ||
afterScenario: "shutdownWallet" | ||
flow: | ||
- function: "walletRestoration" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* Query randomized distinct addresses from db associated with users who are staking | ||
*/ | ||
export const findAddressesWithRewardsHistory = ` | ||
SELECT * FROM ( | ||
SELECT DISTINCT txOut.address as address, sa.view as stake_address | ||
FROM public.delegation d | ||
LEFT JOIN public.tx_out txOut on | ||
d.addr_id = txOut.stake_address_id | ||
LEFT JOIN public.stake_address sa on | ||
txOut.stake_address_id = sa.id | ||
) distinct_addresses | ||
ORDER BY RANDOM() LIMIT $1 | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { GroupedAddress } from '@cardano-sdk/key-management'; | ||
import { SingleAddressWallet } from '@cardano-sdk/wallet'; | ||
|
||
/** | ||
* The context variables shared between all the hooks. | ||
*/ | ||
export interface WalletVars { | ||
walletsCount: number; | ||
addresses: GroupedAddress[]; | ||
currentWallet: SingleAddressWallet; | ||
} | ||
|
||
export interface AddressesModel { | ||
address: string; | ||
stake_address: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.