Skip to content

Commit

Permalink
test: Test setup refactor & remove RPC sequencer (starknet-io#1044)
Browse files Browse the repository at this point in the history
* test: test setup refactor & remove rpc sequencer

* fix: enable sequencer tests to run on goerli

* chore: format markdowns

* fix: remove unnecessary goerli describeIf comment

* chore: remove setup verifier & simplify envs check logic

* test: naming improvements

* test: update test setup data log for testnet

* test: change from goerli to sepolia

* test: rename from rpc testnet to testnet

* test: remove `TEST_PROVIDER_BASE_URL`

---------

Co-authored-by: Luka Saric <[email protected]>
Co-authored-by: Ivan Pavičić <[email protected]>
  • Loading branch information
3 people authored Apr 8, 2024
1 parent d396275 commit d5f0b75
Show file tree
Hide file tree
Showing 17 changed files with 230 additions and 614 deletions.
7 changes: 2 additions & 5 deletions __tests__/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import {
compiledOpenZeppelinAccount,
compiledTestDapp,
describeIfDevnet,
describeIfDevnetSequencer,
erc20ClassHash,
getTestAccount,
getTestProvider,
Expand Down Expand Up @@ -113,7 +112,7 @@ describe('deploy and test Wallet', () => {
// this is tested indirectly true declareAndDeploy while declaring
});

describeIfDevnetSequencer('Test on Devnet Sequencer', () => {
describeIfDevnet('Test on Devnet', () => {
test('deployAccount with rawArgs - test on devnet', async () => {
const priKey = stark.randomAddress();
const pubKey = ec.starkCurve.getStarkKey(priKey);
Expand Down Expand Up @@ -195,7 +194,6 @@ describe('deploy and test Wallet', () => {

describe('simulate transaction - single transaction S0.11.2', () => {
test('simulate INVOKE Cairo 0', async () => {
// INFO: Sequencer S0.11.2 support only one transaction per simulate request
const res = await account.simulateTransaction([
{
type: TransactionType.INVOKE,
Expand All @@ -206,7 +204,6 @@ describe('deploy and test Wallet', () => {
amount: uint256(10),
},
},
// This transaction will be skipped on sequencer
{
type: TransactionType.INVOKE,
contractAddress: erc20Address,
Expand Down Expand Up @@ -753,7 +750,7 @@ describe('deploy and test Wallet', () => {
});

describe('unit', () => {
describeIfDevnetSequencer('devnet sequencer', () => {
describeIfDevnet('Devnet', () => {
initializeMatcher(expect);
const provider = getTestProvider();
const account = getTestAccount(provider);
Expand Down
20 changes: 10 additions & 10 deletions __tests__/cairo1.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { Abi } from 'abi-wan-kanabi';
import {
Abi,
type BigNumberish,
type Calldata,
type CompiledSierra,
type DeclareDeployUDCResponse,
type RawArgsArray,
type RawArgsObject,
Account,
BigNumberish,
CallData,
Calldata,
CompiledSierra,
Contract,
ContractFactory,
DeclareDeployUDCResponse,
RawArgsArray,
RawArgsObject,
cairo,
ec,
hash,
Expand All @@ -26,7 +26,7 @@ import {
compiledHelloSierra,
compiledHelloSierraCasm,
describeIfDevnet,
describeIfSequencerGoerli,
describeIfTestnet,
getTestAccount,
getTestProvider,
} from './config/fixtures';
Expand Down Expand Up @@ -550,8 +550,8 @@ describeIfDevnet('Cairo 1 Devnet', () => {
});
});

describeIfSequencerGoerli('Cairo1 Testnet', () => {
describe('Sequencer API - C1 Testnet C:0x00305e...', () => {
describeIfTestnet('Testnet', () => {
describe('TS validation for testnet', () => {
const provider = getTestProvider();
const account = getTestAccount(provider);
const classHash: any = '0x022332bb9c1e22ae13ae7fd9f3101eced4644533c6bfe51a25cf8dea028e5045';
Expand Down
8 changes: 8 additions & 0 deletions __tests__/config/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
/* Default test config based on run `starknet-devnet --seed 0` */
export const GS_DEFAULT_TEST_PROVIDER_URL = 'http://127.0.0.1:5050/';

export const LOCAL_DEVNET_NOT_RUNNING_MESSAGE = `
Local devnet is not running. In order to properly run it you need to do the following: \n
- Go to the: https://hub.docker.com/r/shardlabs/starknet-devnet-rs/tags
- Find the latest tag and copy the "docker pull" command
- Run Docker on your machine
- Run the command: "docker pull shardlabs/starknet-devnet-rs:latest"
`;
13 changes: 5 additions & 8 deletions __tests__/config/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export function getTestProvider(isProvider: boolean = true): ProviderInterface |
? new Provider({ nodeUrl: process.env.TEST_RPC_URL })
: new RpcProvider({ nodeUrl: process.env.TEST_RPC_URL });

if (process.env.IS_LOCALHOST_DEVNET === 'true') {
if (process.env.IS_DEVNET === 'true') {
// accelerate the tests when running locally
const originalWaitForTransaction = provider.waitForTransaction.bind(provider);
provider.waitForTransaction = (txHash: string, options: waitForTransactionOptions = {}) => {
Expand All @@ -104,18 +104,15 @@ export const getTestAccount = (provider: ProviderInterface) => {
};

export const createBlockForDevnet = async (): Promise<void> => {
if (!(process.env.IS_RPC_DEVNET === 'true')) return;
if (!(process.env.IS_DEVNET === 'true')) return;
await fetch(new URL('/create_block', process.env.TEST_RPC_URL), { method: 'POST' });
};

const describeIf = (condition: boolean) => (condition ? describe : describe.skip);
export const describeIfSequencer = describeIf(process.env.IS_SEQUENCER === 'true');
export const describeIfRpc = describeIf(process.env.IS_RPC === 'true');
export const describeIfNotDevnet = describeIf(process.env.IS_LOCALHOST_DEVNET === 'false');
export const describeIfDevnet = describeIf(process.env.IS_LOCALHOST_DEVNET === 'true');
export const describeIfDevnetRpc = describeIf(process.env.IS_RPC_DEVNET === 'true');
export const describeIfDevnetSequencer = describeIf(process.env.IS_SEQUENCER_DEVNET === 'true');
export const describeIfSequencerGoerli = describeIf(process.env.IS_SEQUENCER_GOERLI === 'true');
export const describeIfNotDevnet = describeIf(process.env.IS_DEVNET === 'false');
export const describeIfDevnet = describeIf(process.env.IS_DEVNET === 'true');
export const describeIfTestnet = describeIf(process.env.IS_TESTNET === 'true');

export const erc20ClassHash = '0x54328a1075b8820eb43caf0caa233923148c983742402dcfc38541dd843d01a';
export const wrongClassHash = '0x000000000000000000000000000000000000000000000000000000000000000';
64 changes: 64 additions & 0 deletions __tests__/config/helpers/accountResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* eslint-disable no-console */
import { GS_DEFAULT_TEST_PROVIDER_URL } from '../constants';

class AccountResolver {
get providedUrl() {
return process.env.TEST_RPC_URL;
}

get hasAllAccountEnvs() {
return process.env.TEST_ACCOUNT_ADDRESS && process.env.TEST_ACCOUNT_PRIVATE_KEY;
}

get hasPartialAccountEnvs() {
return process.env.TEST_ACCOUNT_ADDRESS || process.env.TEST_ACCOUNT_PRIVATE_KEY;
}

private async fetchAccount(url: string) {
const response = await fetch(`${url}predeployed_accounts`);
const [account] = await response.json();
const { address, private_key, initial_balance } = account;
process.env.TEST_ACCOUNT_ADDRESS = address;
process.env.TEST_ACCOUNT_PRIVATE_KEY = private_key;
process.env.INITIAL_BALANCE = initial_balance;
}

private async isAccountSet(isDevnet: boolean): Promise<boolean> {
if (this.hasAllAccountEnvs) {
return true;
}
if (this.hasPartialAccountEnvs) {
throw new Error(
'If you are providing one of you need to provide both: TEST_ACCOUNT_ADDRESS & TEST_ACCOUNT_PRIVATE_KEY'
);
}
if (isDevnet) {
// get account from devnet
try {
await this.fetchAccount(GS_DEFAULT_TEST_PROVIDER_URL);
return true;
} catch (error) {
console.error('Fetching account from devnet failed');
}
} else if (this.providedUrl) {
// try to get it from remote devnet
try {
await this.fetchAccount(this.providedUrl);
return true;
} catch (error) {
console.error(`Fetching account from provided url ${this.providedUrl} failed`);
}
}

throw new Error(
'Setting Account using all known strategies failed, provide basic test parameters'
);
}

async execute(isDevnet: boolean): Promise<void> {
const isAccountSet = await this.isAccountSet(isDevnet);
if (isAccountSet) console.log('Detected Account');
}
}

export default new AccountResolver();
73 changes: 0 additions & 73 deletions __tests__/config/helpers/localDevnetDetector.ts

This file was deleted.

131 changes: 131 additions & 0 deletions __tests__/config/helpers/strategyResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/* eslint-disable no-console */
import accountResolver from './accountResolver';
import { GS_DEFAULT_TEST_PROVIDER_URL, LOCAL_DEVNET_NOT_RUNNING_MESSAGE } from '../constants';
import { setIfNullish } from './env';
import { BaseUrl } from '../../../src/constants';

class StrategyResolver {
private isDevnet = false;

private isRpcNode = false;

get isRpcDevnet() {
return this.isDevnet || !!process.env.TEST_RPC_URL;
}

get isTestnet() {
return process.env.TEST_RPC_URL?.includes(BaseUrl.SN_SEPOLIA);
}

get hasAllAccountEnvs() {
const { TEST_ACCOUNT_ADDRESS, TEST_ACCOUNT_PRIVATE_KEY } = process.env;
return !!(TEST_ACCOUNT_PRIVATE_KEY && TEST_ACCOUNT_ADDRESS);
}

private async isRsDevnet(): Promise<boolean> {
const response = await fetch(GS_DEFAULT_TEST_PROVIDER_URL, {
method: 'POST',
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'starknet_syncing' }),
});
const { jsonrpc } = await response.json();
return jsonrpc === '2.0';
}

async detectDevnet(): Promise<void> {
// if on base url RPC endpoint work it is devnet-rs else it devnet-py
try {
this.isDevnet = await this.isRsDevnet();
if (this.isDevnet) console.log('Detected Devnet-RS');
} catch (error) {
console.log('\x1b[36m%s\x1b[0m', LOCAL_DEVNET_NOT_RUNNING_MESSAGE);
throw new Error(
'Local RS devnet is not Running. Please follow the devnet setup instructions.'
);
}

setIfNullish('IS_DEVNET', this.isRpcDevnet);
}

resolveRpc(): void {
const hasRpcUrl = !!process.env.TEST_RPC_URL;

this.isRpcNode = hasRpcUrl || this.isDevnet;

if (!hasRpcUrl && this.isDevnet) {
process.env.TEST_RPC_URL = GS_DEFAULT_TEST_PROVIDER_URL;
}

setIfNullish('IS_RPC', this.isRpcNode);
setIfNullish('IS_TESTNET', this.isTestnet);

console.log('Detected RPC');
}

private logConfigInfo(): void {
console.table({
TEST_ACCOUNT_ADDRESS: process.env.TEST_ACCOUNT_ADDRESS,
TEST_ACCOUNT_PRIVATE_KEY: '****',
INITIAL_BALANCE: process.env.INITIAL_BALANCE,
TEST_RPC_URL: process.env.TEST_RPC_URL,
TX_VERSION: process.env.TX_VERSION === 'v3' ? 'v3' : 'v2',
});

console.table({
IS_DEVNET: process.env.IS_DEVNET,
IS_RPC: process.env.IS_RPC,
IS_TESTNET: process.env.IS_TESTNET,
});

console.log('Global Test Environment is Ready');
}

private verifyAccountData(shouldThrow?: boolean): void {
const { TEST_ACCOUNT_ADDRESS, TEST_ACCOUNT_PRIVATE_KEY } = process.env;
if (!TEST_ACCOUNT_ADDRESS) {
if (shouldThrow) throw new Error('TEST_ACCOUNT_ADDRESS env is not provided');
console.log('\x1b[33m', 'TEST_ACCOUNT_ADDRESS env is not provided!');
delete process.env.TEST_ACCOUNT_ADDRESS;
}
if (!TEST_ACCOUNT_PRIVATE_KEY) {
if (shouldThrow) throw new Error('TEST_ACCOUNT_PRIVATE_KEY env is not provided');
console.log('\x1b[33m', 'TEST_ACCOUNT_PRIVATE_KEY env is not provided!', '\x1b[0m');
delete process.env.TEST_ACCOUNT_PRIVATE_KEY;
}
}

private useProvidedSetup(): void {
setIfNullish('IS_DEVNET', false);
setIfNullish('IS_RPC', !!process.env.TEST_RPC_URL);
setIfNullish('IS_TESTNET', this.isTestnet);

this.logConfigInfo();

console.log('Using Provided Test Setup');
}

async execute(): Promise<void> {
// 1. Assume setup is provided and ready;
console.log('Global Test Setup Started');
this.verifyAccountData();

if (this.hasAllAccountEnvs) {
this.useProvidedSetup();
return;
}

// 2. Try to detect devnet setup
console.log('Basic test parameters are missing, Auto Setup Started');

await this.detectDevnet();
this.resolveRpc();
await accountResolver.execute(this.isDevnet);

this.verifyAccountData(true);
if (!this.hasAllAccountEnvs) console.error('Test Setup Environment is NOT Ready');

this.logConfigInfo();
}
}

export default new StrategyResolver();
Loading

0 comments on commit d5f0b75

Please sign in to comment.