Skip to content

Commit

Permalink
wip: test(agent): 88.69% coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
egasimus committed Nov 16, 2023
1 parent bc16318 commit d44112d
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 63 deletions.
6 changes: 3 additions & 3 deletions agent/connec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export abstract class Endpoint extends Logged {
super(properties)
this.log.label += (
this[Symbol.toStringTag]
? ` (${bold(this[Symbol.toStringTag])})`
? `(${bold(this[Symbol.toStringTag])})`
: '')
}

Expand Down Expand Up @@ -74,14 +74,14 @@ export abstract class Connection extends Endpoint {
this.fees = properties.fees || this.fees
this.log.label += (
this[Symbol.toStringTag]
? ` (${bold(this[Symbol.toStringTag])})`
? `(${bold(this[Symbol.toStringTag])})`
: '')
}

get [Symbol.toStringTag] () {
let tag = super[Symbol.toStringTag]
if ((this.identity && (this.identity.name||this.identity.address))) {
tag = `${this.identity.name||this.identity.address}@` + tag
tag = [`${this.identity.name||this.identity.address}`, tag].filter(Boolean).join('@')
}
return tag
}
Expand Down
93 changes: 49 additions & 44 deletions agent/deploy.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** Fadroma. Copyright (C) 2023 Hack.bg. License: GNU AGPLv3 or custom.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. **/
import assert, { deepEqual, rejects } from 'node:assert'
import assert, { equal, deepEqual, rejects, throws } from 'node:assert'
import { Contract } from './connec'
import * as Stub from './stub'
import {
Expand Down Expand Up @@ -29,26 +29,34 @@ export default new Suite([

export async function testDeploymentUnits () {
const contract = new ContractInstance({ address: 'present' })
assert.equal(await contract.deploy(), contract)
assert(contract.connect(new Stub.Connection()) instanceof Contract)

assert.rejects(()=>new ContractInstance({
uploaded: { codeId: 123 } as any,
}).deploy())

assert.rejects(()=>new ContractInstance({
uploaded: { codeId: 123 } as any,
deployer: 'onlyaddress'
}).deploy())

assert.rejects(()=>new ContractInstance({
uploaded: { codeId: 123 } as any,
deployer: { instantiate: ((...args: any) => Promise.resolve({ isValid: () => false })) } as any
}).deploy())
equal(
await contract.deploy(), contract)
assert(
contract.connect(new Stub.Connection()) instanceof Contract)
rejects(
()=>new ContractInstance({
uploaded: { codeId: 123 } as any,
}).deploy())
rejects(
()=>new ContractInstance({
uploaded: { codeId: 123 } as any,
deployer: 'onlyaddress'
}).deploy())
rejects(
()=>new ContractInstance({
uploaded: { codeId: 123 } as any,
deployer: { instantiate: ((...args: any) => Promise.resolve({ isValid: () => false })) } as any
}).deploy())
}

export async function testDeployment () {

const uploadStore = new UploadStore()
const deployStore = new DeployStore()
const compiler = new Stub.Compiler()
const uploader = new Stub.Connection()
const deployer = uploader

class MyBuildableDeployment extends Deployment {
template1 = this.template('template1', {
codeHash: "asdf",
Expand All @@ -59,9 +67,7 @@ export async function testDeployment () {
})
}

await new MyBuildableDeployment().build({
compiler: new Stub.Compiler()
})
await new MyBuildableDeployment().build({ compiler })

class MyDeployment extends Deployment {
template1 = this.template('template1', {
Expand All @@ -84,44 +90,43 @@ export async function testDeployment () {
})
}

await new MyDeployment().contract1.deploy({
deployer: new Stub.Connection()
})
await new MyDeployment().contract1.deploy({ deployer })

new MyDeployment().contract1.serialize()

new MyDeployment().serialize()

MyDeployment.fromSnapshot(new MyDeployment().serialize())

assert.throws(()=>new MyDeployment().set('foo', {} as any))

await new MyDeployment().upload({
compiler: new Stub.Compiler(),
uploader: new Stub.Connection(),
})

await new MyDeployment().deploy({
compiler: new Stub.Compiler(),
uploader: new Stub.Connection(),
deployer: new Stub.Connection(),
})
assert(
MyDeployment.fromSnapshot(new MyDeployment().serialize()))
throws(
()=>new MyDeployment().set('foo', {} as any))
assert(
await new MyDeployment().upload({ compiler, uploader }))
assert(
await new MyDeployment().deploy({ compiler, uploader, deployer }))
}

export async function testUploadStore () {
const uploadStore = new UploadStore()
assert.equal(uploadStore.get('name'), undefined)
assert.equal(uploadStore.set('name', {}), uploadStore)
assert.throws(()=>uploadStore.set('foo', { codeHash: 'bar' }))
assert(uploadStore.get('name') instanceof UploadedCode)
equal(
uploadStore.get('name'), undefined)
equal(
uploadStore.set('name', {}), uploadStore)
throws(
()=>uploadStore.set('foo', { codeHash: 'bar' }))
assert(
uploadStore.get('name') instanceof UploadedCode)
}

export async function testDeployStore () {
const deployStore = new DeployStore()
assert.equal(deployStore.get('name'), undefined)
assert.equal(
deployStore.get('name'), undefined)
const deployment = new Deployment({ name: 'foo' })
assert.equal(deployStore.set('name', deployment), deployStore)
assert.deepEqual(deployStore.get('name'), deployment.serialize())
assert.equal(
deployStore.set('name', deployment), deployStore)
assert.deepEqual(
deployStore.get('name'), deployment.serialize())
}
export async function testCodeContract () {
//const contract1 = new ContractCode({
Expand Down
5 changes: 3 additions & 2 deletions agent/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class ContractCode extends Logged {
/** Compile this contract, unless a valid binary is present and a rebuild is not requested. */
async compile ({
compiler = this.compiler,
rebuild = false,
rebuild = false,
...buildOptions
}: {
compiler?: Compiler
Expand Down Expand Up @@ -89,7 +89,7 @@ export class ContractCode extends Logged {

/** Upload this contract, unless a valid upload is present and a rebuild is not requested. */
async upload ({
compiler = this.compiler,
compiler = this.compiler,
rebuild = false,
uploader = this.uploader,
reupload = rebuild,
Expand All @@ -108,6 +108,7 @@ export class ContractCode extends Logged {
}
const compiled = await this.compile({ compiler, rebuild })
const uploaded = await uploader.upload(compiled, uploadOptions)
console.log({uploaded})
if (!uploaded.canInstantiate) {
throw new Error("upload failed")
}
Expand Down
3 changes: 2 additions & 1 deletion agent/stub.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { testChainSupport } from './tester'
import * as Stub from './stub'
import { fixture } from '@fadroma/fixtures'
export default async function testStubImpl () {
await testChainSupport(
Stub.Connection,
Stub.Backend,
'',
'',
''
fixture('scrt-null.wasm')
)
}
50 changes: 42 additions & 8 deletions agent/stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ class StubConnection extends Connection {
doGetBlockInfo () {
return Promise.resolve({ height: + new Date() })
}
doGetBalance (...args: unknown[]): Promise<number> {
doGetBalance (
token: string = (this.constructor as Function & { gasToken: Token.Native }).gasToken.id,
address: string|undefined = this.address
): Promise<string> {
this.log.warn('getBalance: stub')
return Promise.resolve(0)
const balance = (this.backend.balances.get(address!)||{})[token] ?? 0
return Promise.resolve(String(balance))
}
async doGetCodeId (address: Address): Promise<CodeId> {
const contract = this.backend.instances.get(address)
Expand All @@ -60,10 +64,31 @@ class StubConnection extends Connection {
doQuery <Q> (contract: { address: Address }, message: Message): Promise<Q> {
return Promise.resolve({} as Q)
}
doSend (to: Address, amounts: Token.ICoin[], opts?: never): Promise<void> {
for (const { amount, denom } of amounts) {
const x = BigInt(amount)
doSend (recipient: Address, sums: Token.ICoin[], opts?: never): Promise<void> {
if (!this.address) {
throw new Error('not authenticated')
}
const senderBalances = {
...this.backend.balances.get(this.address) || {}}
const recipientBalances = {
...this.backend.balances.get(recipient) || {}}
for (const sum of sums) {
if (!Object.keys(senderBalances).includes(sum.denom)) {
throw new Error(`sender has no balance in ${sum.denom}`)
}
const amount = BigInt(sum.amount)
if (senderBalances[sum.denom] < amount) {
throw new Error(
`sender has insufficient balance in ${sum.denom}: ${senderBalances[sum.denom]} < ${amount}`
)
}
senderBalances[sum.denom] =
senderBalances[sum.denom] - amount
recipientBalances[sum.denom] =
(recipientBalances[sum.denom] ?? BigInt(0)) + amount
}
this.backend.balances.set(this.address, senderBalances)
this.backend.balances.set(recipient, recipientBalances)
return Promise.resolve()
}
doSendMany (outputs: [Address, Token.ICoin[]][], opts?: never): Promise<void> {
Expand All @@ -90,7 +115,7 @@ class StubConnection extends Connection {
}

class StubBackend extends Backend {
chainId =
id =
'stub'
url =
'http://stub'
Expand All @@ -105,9 +130,17 @@ class StubBackend extends Backend {
instances =
new Map<Address, {codeId: CodeId}>()

constructor (properties?: Partial<StubBackend>) {
constructor (properties?: Partial<StubBackend & {
genesisAccounts: Record<string, string|number>
}>) {
super(properties as Partial<Backend>)
assign(this, properties, ["chainId", "lastCodeId", "uploads", "instances"])
for (const [name, balance] of Object.entries(properties?.genesisAccounts||{})) {
const address = `stub1${name}`
const balances = this.balances.get(address) || {}
balances['ustub'] = BigInt(balance)
this.balances.set(address, balances)
}
}

async connect (parameter: string|Partial<Identity & { mnemonic?: string }> = {}): Promise<Connection> {
Expand All @@ -121,6 +154,7 @@ class StubBackend extends Backend {
id: this.chainId,
url: 'stub',
alive: true,
backend: this,
identity: new Identity(parameter)
})
}
Expand Down Expand Up @@ -153,7 +187,7 @@ class StubBackend extends Backend {
let upload
this.uploads.set(codeId, upload = {
codeId,
chainId: this.chainId,
chainId: this.id,
codeHash: base16.encode(sha256(codeData)).toLowerCase(),
codeData,
})
Expand Down
6 changes: 3 additions & 3 deletions agent/tester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export async function testChainSupport <
const execFee = Chain.gas(10000000)

const genesisAccounts = { Alice: "123456789000", Bob: "987654321000" }
const backend = new Backend({ version, genesisAccounts })
const $B = Backend as any
const backend = new $B({ version, genesisAccounts })

//const chain = await backend.connect()

Expand All @@ -29,7 +30,7 @@ export async function testChainSupport <
console.log('Querying block height...')
await alice.height

console.log('Querying balances...', alice)
console.log('Querying balances...')
await alice.balance
await bob.balance

Expand All @@ -45,7 +46,6 @@ export async function testChainSupport <
})

console.log('Querying non-genesis account balance...')
console.log({guest})
equal((await guest.balance)??'0', '0')

console.log('Topping up non-genesis account balance from genesis accounts...')
Expand Down
4 changes: 4 additions & 0 deletions agent/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class TokenAmount {
}
return []
}

get denom () {
return this.token?.id
}
}

/** The chain's natively implemented token (such as SCRT on Secret Network). */
Expand Down
4 changes: 2 additions & 2 deletions connect/scrt/scrt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url'
import { Devnets } from '@hackbg/fadroma'
import { fixture } from '@fadroma/fixtures'
import Scrt, { BatchBuilder, SecretJS } from '@fadroma/scrt'
import { Token, Test } from '@fadroma/agent'
import { Token, Tester } from '@fadroma/agent'
//import * as Mocknet from './scrt-mocknet'

//@ts-ignore
Expand All @@ -29,7 +29,7 @@ export default new Suite([
])

export async function testScrtChain () {
const { devnet, alice, bob, guest } = await Test.testChainSupport(
const { devnet, alice, bob, guest } = await Tester.testChainSupport(
Scrt,
Devnets.ScrtContainer,
'v1.9',
Expand Down

0 comments on commit d44112d

Please sign in to comment.