Skip to content

Commit

Permalink
Merge pull request #40 from skalenetwork/add-network-browser-tests
Browse files Browse the repository at this point in the history
Add test pipeline for network-browser module
  • Loading branch information
dmytrotkk authored Dec 22, 2023
2 parents 0c90b01 + b188a1f commit 073d04f
Show file tree
Hide file tree
Showing 23 changed files with 578 additions and 33 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/network-browser-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: network-browser test
on: [push, pull_request]
env:
ETH_PRIVATE_KEY: ${{ secrets.ETH_PRIVATE_KEY }}
MANAGER_TAG: "1.9.3-beta.0"
jobs:
test_network_browser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: true
- uses: oven-sh/setup-bun@v1
- name: Launch hardhat node
working-directory: hardhat-node
run: docker-compose up -d
- name: Deploy manager contracts
run: |
bash ./helper-scripts/deploy_test_manager.sh
docker rmi -f skalenetwork/skale-manager:${{ env.MANAGER_TAG }}
- name: Install network-browser dependencies
working-directory: network-browser
run: bun i

- name: Run network-browser tests
working-directory: network-browser
run: bash run_tests.sh
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[submodule "IMA"]
path = IMA
url = https://github.com/skalenetwork/IMA.git
[submodule "hardhat-node"]
path = hardhat-node
url = https://github.com/skalenetwork/hardhat-node.git
[submodule "helper-scripts"]
path = helper-scripts
url = https://github.com/skalenetwork/helper-scripts.git
1 change: 1 addition & 0 deletions hardhat-node
Submodule hardhat-node added at 8a4b03
1 change: 1 addition & 0 deletions helper-scripts
Submodule helper-scripts added at 34adbe
2 changes: 2 additions & 0 deletions network-browser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Optional env variables:
- `POST_ERROR_DELAY` - delay before retry if error happened in browser loop (seconds, default: `5`)
- `NETWORK_BROWSER_DELAY` - delay between iterations of the network-browser (seconds, default: `10800`)
- `NETWORK_BROWSER_TIMEOUT` - maximum amount of time allocated to the browse function (seconds, default: `1200`)
- `NETWORK_BROWSER_LOG_LEVEL` - log level (0: silly, 1: trace, 2: debug, 3: info, 4: warn, 5: error, 6: fatal, default: `1`)
- `NETWORK_BROWSER_LOG_PRETTY` - colored logs, (boolean, default: `false`)

## Development

Expand Down
Binary file modified network-browser/bun.lockb
Binary file not shown.
6 changes: 4 additions & 2 deletions network-browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ import {
NETWORK_BROWSER_DELAY,
MULTICALL,
CONNECTED_ONLY,
SCHAIN_RPC_URL
SCHAIN_RPC_URL,
LOG_LEVEL,
LOG_PRETTY
} from './src/constants'

import { Logger, type ILogObj } from 'tslog'

const log = new Logger<ILogObj>()
const log = new Logger<ILogObj>({ minLevel: LOG_LEVEL, stylePrettyLogs: LOG_PRETTY })

async function safeNetworkBrowserLoop() {
log.info(`Running network-browser...`)
Expand Down
8 changes: 5 additions & 3 deletions network-browser/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "network-browser",
"private": true,
"version": "0.0.0",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "bun _fix && bun --hot index.ts",
Expand All @@ -23,11 +23,13 @@
},
"devDependencies": {
"@rollup/plugin-typescript": "^11.1.5",
"bun-types": "^1.0.11",
"@types/elliptic": "^6.4.18",
"bun-types": "^1.0.18-1",
"elliptic": "^6.5.4",
"eslint": "^8.53.0",
"eslint-config-standard-with-typescript": "^39.1.1",
"prettier": "^3.1.0",
"rollup": "^4.7.0",
"typescript": "^5.2.2"
"typescript": "5.3.3"
}
}
7 changes: 6 additions & 1 deletion network-browser/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@ export default {
format: 'es',
preserveModules: true
},
plugins: [typescript()]
plugins: [
typescript({
include: ['src/**', 'index.ts'],
exclude: ['**/tests', '**/build']
})
]
}
16 changes: 16 additions & 0 deletions network-browser/run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -e

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

export IMA_NETWORK_BROWSER_DATA_PATH="$DIR/test_schainsData.json"
export SCHAIN_PROXY_PATH="$DIR/test_ima_schain.json"
export MANAGER_ABI_PATH="$DIR/../helper-scripts/contracts_data/manager.json"

export MAINNET_RPC_URL="http://127.0.0.1:8545"
export SCHAIN_RPC_URL="http://127.0.0.1:8545"
export SCHAIN_NAME="test"
export CONNECTED_ONLY=false

bun test
4 changes: 2 additions & 2 deletions network-browser/src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ import {
filterConnectedHashes
} from './schains'
import { getNodesGroups } from './nodes'
import { CONNECTED_ONLY, IMA_NETWORK_BROWSER_DATA_PATH } from './constants'
import { CONNECTED_ONLY, IMA_NETWORK_BROWSER_DATA_PATH, LOG_LEVEL, LOG_PRETTY } from './constants'
import { writeJson, currentTimestamp, chainIdInt } from './tools'

const log = new Logger<ILogObj>()
const log = new Logger<ILogObj>({ minLevel: LOG_LEVEL, stylePrettyLogs: LOG_PRETTY })

export async function browse(schainsInternal: Contract, nodes: Contract): Promise<void> {
log.info('Browse iteration started, collecting chains')
Expand Down
5 changes: 4 additions & 1 deletion network-browser/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* @copyright SKALE Labs 2023-Present
*/

import { requiredEnv, booleanEnv, secondsEnv } from './envTools'
import { requiredEnv, booleanEnv, secondsEnv, optionalEnvNumber } from './envTools'

// internal

Expand Down Expand Up @@ -53,3 +53,6 @@ export const CONNECTED_ONLY = booleanEnv('CONNECTED_ONLY', true)
export const POST_ERROR_DELAY = secondsEnv(process.env.POST_ERROR_DELAY, 5)
export const NETWORK_BROWSER_DELAY = secondsEnv(process.env.NETWORK_BROWSER_DELAY, 10800)
export const NETWORK_BROWSER_TIMEOUT = secondsEnv(process.env.NETWORK_BROWSER_TIMEOUT, 1200)

export const LOG_LEVEL = optionalEnvNumber('NETWORK_BROWSER_LOG_LEVEL', 1)
export const LOG_PRETTY = booleanEnv('NETWORK_BROWSER_LOG_PRETTY', false)
14 changes: 7 additions & 7 deletions network-browser/src/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* @copyright SKALE Labs 2023-Present
*/

import { JsonRpcProvider, type Provider, Contract, type Network } from 'ethers'
import { JsonRpcProvider, type Provider, Contract, type Network, type ContractRunner } from 'ethers'
import mc from 'ethers-multicall-provider'
import { type SkaleManagerAbi, type SChainImaAbi } from './interfaces'
import { readJson } from './tools'
Expand Down Expand Up @@ -52,14 +52,14 @@ export function getSChainProvider(endpoint: string): Provider {
return new JsonRpcProvider(endpoint)
}

export function schainsInternalContract(abi: SkaleManagerAbi, provider: Provider): Contract {
return new Contract(abi.schains_internal_address, abi.schains_internal_abi, provider)
export function schainsInternalContract(abi: SkaleManagerAbi, runner: ContractRunner): Contract {
return new Contract(abi.schains_internal_address, abi.schains_internal_abi, runner)
}

export function messageProxyContract(abi: SChainImaAbi, provider: Provider): Contract {
return new Contract(abi.message_proxy_chain_address, abi.message_proxy_chain_abi, provider)
export function messageProxyContract(abi: SChainImaAbi, runner: ContractRunner): Contract {
return new Contract(abi.message_proxy_chain_address, abi.message_proxy_chain_abi, runner)
}

export function nodesContract(abi: SkaleManagerAbi, provider: Provider): Contract {
return new Contract(abi.nodes_address, abi.nodes_abi, provider)
export function nodesContract(abi: SkaleManagerAbi, runner: ContractRunner): Contract {
return new Contract(abi.nodes_address, abi.nodes_abi, runner)
}
16 changes: 14 additions & 2 deletions network-browser/src/envTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@

const MS_MULTIPLIER = 1000

export function isValidNumber(str: string): boolean {
return !isNaN(+str) && str.trim().length > 0
}

export function secondsEnv(envValue: string | undefined, defaultSeconds: number): number {
return (envValue !== undefined ? Number(envValue) : defaultSeconds) * MS_MULTIPLIER
}
Expand All @@ -42,10 +46,18 @@ export function requiredEnv(name: string): string {
return value
}

export function optionalEnv(envVar: string, defaultValue: string): string {
const value = process.env[envVar]
export function optionalEnv(name: string, defaultValue: string): string {
const value = process.env[name]
if (value === undefined) {
return defaultValue
}
return value
}

export function optionalEnvNumber(name: string, defaultValue: number): number {
const value = process.env[name]
if (value === undefined || !isValidNumber(value)) {
return defaultValue
}
return Number(value)
}
4 changes: 4 additions & 0 deletions network-browser/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ export interface SkaleManagerAbi {
schains_abi: InterfaceAbi
schains_internal_address: string
schains_internal_abi: InterfaceAbi
validator_service_address: string
validator_service_abi: InterfaceAbi
skale_manager_address: string
skale_manager_abi: InterfaceAbi
}

export interface SChainImaAbi {
Expand Down
2 changes: 1 addition & 1 deletion network-browser/src/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ async function getNodesRaw(
)
}

function nodeStruct(
export function nodeStruct(
nodeArray: NodeArray,
domainName: string,
schainHash?: string,
Expand Down
4 changes: 2 additions & 2 deletions network-browser/src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import { Logger, type ILogObj } from 'tslog'

import { readFileSync, writeFileSync, renameSync } from 'fs'
import { BrowserTimeoutError } from './errors'
import { DEFAULT_PING_DELAY, DEFAULT_PING_ITERATIONS } from './constants'
import { DEFAULT_PING_DELAY, DEFAULT_PING_ITERATIONS, LOG_LEVEL, LOG_PRETTY } from './constants'

const log = new Logger<ILogObj>()
const log = new Logger<ILogObj>({ minLevel: LOG_LEVEL, stylePrettyLogs: LOG_PRETTY })

export function stringifyBigInt(obj: any): string {
return JSON.stringify(
Expand Down
10 changes: 0 additions & 10 deletions network-browser/tests/base.test.ts

This file was deleted.

98 changes: 98 additions & 0 deletions network-browser/tests/browser.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { unlinkSync, existsSync } from 'node:fs'
import { describe, beforeAll, test, expect, beforeEach } from 'bun:test'
import { Contract, Wallet } from 'ethers'

import {
getMainnetProvider,
nodesContract,
getMainnetManagerAbi,
schainsInternalContract
} from '../src/contracts'
import { browse } from '../src/browser'
import { getSChain } from '../src/schains'
import { readJson } from '../src/tools'
import { NetworkBrowserData } from '../src/interfaces'
import { MAINNET_RPC_URL, IMA_NETWORK_BROWSER_DATA_PATH } from '../src/constants'

import {
ETH_PRIVATE_KEY,
NODES_IN_SCHAIN,
validatorsContract,
managerContract,
schainsContract,
addAllPermissions,
generateWallets,
initDefaultValidator,
linkNodes,
registerNodes,
addTestSchainTypes,
createSchain,
randomString
} from './testUtils'

describe('browser module test', () => {
let nodes: Contract
let schainsInternal: Contract
let wallet: Wallet
const chainName = randomString()

beforeAll(async () => {
console.log('initializing provider and contracts')
const provider = await getMainnetProvider(MAINNET_RPC_URL, false)
wallet = new Wallet(ETH_PRIVATE_KEY, provider)

const managerAbi = getMainnetManagerAbi()
const validators = validatorsContract(managerAbi, wallet)
schainsInternal = schainsInternalContract(managerAbi, wallet)
const schains = schainsContract(managerAbi, wallet)
const manager = managerContract(managerAbi, wallet)

nodes = nodesContract(managerAbi, provider)

await addAllPermissions(validators, schainsInternal, schains, wallet)
await initDefaultValidator(validators)
const wallets = await generateWallets(provider, wallet, NODES_IN_SCHAIN)
await linkNodes(validators, wallet, wallets)
await registerNodes(nodes, wallets)

await addTestSchainTypes(schainsInternal)
await createSchain(schains, chainName, wallet.address)
})

beforeEach(async () => {
if (existsSync(IMA_NETWORK_BROWSER_DATA_PATH)) {
console.log('removing browse results')
unlinkSync(IMA_NETWORK_BROWSER_DATA_PATH)
}
})

test('browse', async () => {
const schain = await getSChain(schainsInternal, chainName)
expect(schain.name).toBe(chainName)
expect(schain.mainnetOwner).toBe(wallet.address)

expect(existsSync(IMA_NETWORK_BROWSER_DATA_PATH)).toBeFalse
await browse(schainsInternal, nodes)
expect(existsSync(IMA_NETWORK_BROWSER_DATA_PATH)).toBeTrue

const nbData: NetworkBrowserData = readJson(IMA_NETWORK_BROWSER_DATA_PATH)

expect(nbData.updatedAt).toBeNumber
expect(nbData.schains).toBeArray
expect(nbData.schains[0].name).toBeString
expect(nbData.schains[0].mainnetOwner).toBeString
expect(nbData.schains[0].indexInOwnerList).toBeString
expect(nbData.schains[0].partOfNode).toBeString
expect(nbData.schains[0].lifetime).toBeString
expect(nbData.schains[0].startBlock).toBeString
expect(nbData.schains[0].deposit).toBeString
expect(nbData.schains[0].index).toBeString
expect(nbData.schains[0].generation).toBeString
expect(nbData.schains[0].chainId).toBeNumber
expect(nbData.schains[0].nodes).toBeArrayOfSize(NODES_IN_SCHAIN)
if (nbData.schains[0].nodes) {
expect(nbData.schains[0].nodes[0].endpoints?.domain.https).toBeString
expect(nbData.schains[0].nodes[0].endpoints?.ip.ws).toBeString
}
})
})
Loading

0 comments on commit 073d04f

Please sign in to comment.