Skip to content

Commit

Permalink
Add the new unit test system.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vilhelm Sjöberg committed Dec 11, 2020
1 parent 4720270 commit b399696
Show file tree
Hide file tree
Showing 34 changed files with 2,788 additions and 414 deletions.
5 changes: 5 additions & 0 deletions unittests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
To run the tests:
1. `npm install` to get Node.js dependencies
2. `./start_conflux.sh` in a separate terminal, and start Ganache (for Ethereum tests)
- Be sure to clone the `conflux-rust` repo, and within `start_conflux.sh`, set `conflux` to the location of your repo clone.
3. `./run_unittests.sh`
48 changes: 0 additions & 48 deletions unittests/address_test.js

This file was deleted.

11 changes: 0 additions & 11 deletions unittests/asserts_test.js

This file was deleted.

8 changes: 8 additions & 0 deletions unittests/builtins.ds
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ object signature OS = {
const get_coinbase : unit -> uint;
const get_timestamp : unit -> uint;
const get_number : unit -> uint;
(* const get_chainid : unit -> uint; *) (*Not supported by our ethereum test yet*)
(* const get_selfbalance : unit -> uint; *)
const get_balance_this : unit -> uint;
const get_blockhash_prev : unit -> uint
}
Expand All @@ -20,6 +22,8 @@ object O : OS {
let _coinbase : uint := 0u0
let _timestamp : uint := 0u0
let _number : uint := 0u0
(* let _chainid : uint := 0u0 *)
(* let _selfbalance : uint := 0u0 *)
let _balance_this : uint := 0u0
let _blockhash_prev : uint := 0u0

Expand All @@ -31,6 +35,8 @@ object O : OS {
let get_coinbase () = let x = _coinbase in x
let get_timestamp () = let x = _timestamp in x
let get_number () = let x = _number in x
(* let get_chainid () = let x = _chainid in x *)
(* let get_selfbalance () = let x = _selfbalance in x *)
let get_balance_this () = let x = _balance_this in x
let get_blockhash_prev () = let x = _blockhash_prev in x

Expand All @@ -42,6 +48,8 @@ object O : OS {
_coinbase := block_coinbase;
_timestamp := block_timestamp;
_number := block_number;
(* _chainid := chain_id; *)
(* _selfbalance := self_balance; *)
_balance_this := balance(this_address);
_blockhash_prev := blockhash(block_number-0u1);
true
Expand Down
57 changes: 0 additions & 57 deletions unittests/builtins_test.js

This file was deleted.

45 changes: 45 additions & 0 deletions unittests/builtins_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Chain } from './chain'
import { printTest } from './utils'

export async function runTest(chain: Chain) {
await chain.deployContract('builtins')

const _value = 5;

let blockNumber = await chain.callMethod('f', [], {value: _value})

const [
_address,
_origin,
_caller,
_callvalue,
_coinbase,
_timestamp,
_number,
_balance_this,
_blockhash_prev
] = await Promise.all([
chain.callMethod('get_address'),
chain.callMethod('get_origin'),
chain.callMethod('get_caller'),
chain.callMethod('get_callvalue'),
chain.callMethod('get_coinbase'),
chain.callMethod('get_timestamp'),
chain.callMethod('get_number'),
chain.callMethod('get_balance_this'),
chain.callMethod('get_blockhash_prev')
])

printTest("address", _address == chain.getContractAddress());
printTest("origin", _origin == chain.getAccountAddress());
printTest("caller", _caller == chain.getAccountAddress());
printTest("callvalue", _callvalue == _value);
printTest("timestamp", _timestamp == await chain.getBlockTimestamp(blockNumber));
printTest("number", _number == blockNumber);
printTest("balance(this_address)", _balance_this == _value);
printTest("blockhash(parent)", chain.hashToString(_blockhash_prev)
== await chain.getBlockParentHash(blockNumber));
// the hash of the current block is not available, you just get 0x0 if you try, so we query the parent
}

export default { runTest }
17 changes: 17 additions & 0 deletions unittests/chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export interface Chain {
deployContract(jsonFilename: string, constructorArgs?: any[]): void
callMethod(func: string, args?: any[], options?: {}): any

getContractAddress(): string
getAccountAddress(): string
getBlockTimestamp(blockNumber: number): Promise<number>
getBlockParentHash(blockNumber: number): Promise<string>
getEvents(): Promise<Event[]>

hashToString(hash: any): string
}

export interface Event {
signature: string
args: {}
}
11 changes: 11 additions & 0 deletions unittests/clean-json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import sys
import json

s = sys.stdin.read()
obj = json.loads(s)
contracts = obj[list(obj)[0]]
first_contract = contracts[list(contracts)[0]]
first_contract['bytecode'] = '0x' + first_contract['bin']
del first_contract['bin']
first_contract['abi'] = json.loads(first_contract['abi'])
print(json.dumps(first_contract))
121 changes: 121 additions & 0 deletions unittests/conflux-chain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { Conflux, Account } from 'js-conflux-sdk'
import { Chain, Event } from './chain'
import { getJsonFilename } from './utils'
import _ from 'lodash'


export class ConfluxChain implements Chain {
private _conflux: Conflux
private _contract
private _genesisAccount: Account
private _abi: any[]

constructor(verbose=false) {
let logger = this.getLogger(verbose)

this._conflux = new Conflux({
url: 'http://localhost:12537',
// defaultGasPrice: 1000,
// defaultGas: 1000,
// logger: this._logger,
logger: logger,
})

const genesisPrivateKey =
'0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
this._genesisAccount = this._conflux.wallet.addPrivateKey(genesisPrivateKey)
}
private getLogger(verbose: boolean): Logger {
if (verbose)
return console

let logger: Logger = {
info: function() {}, // Output nothing.
error: function() {}
}
return logger
}

async deployContract(jsonFilename: string, constructorArgs=[]){
const {abi, bytecode} = require(getJsonFilename(jsonFilename))
this._contract = this._conflux.Contract({ abi, bytecode })
this._abi = abi

const receipt = await this._contract
.constructor(...constructorArgs)
.sendTransaction({ from: this._genesisAccount })
.executed();
this._contract.address = receipt.contractCreated;
}

async callRead(func: string, args=[]){
return await this._contract[func](...args)
}

async callWrite(func: string, args=[], options={}) {
// console.log("func: " + func)
// console.log("args: " + args)
// console.log("options: " + JSON.stringify(options))
let receipt = await this._contract[func](...args)
.sendTransaction({ from: this._genesisAccount, ...options })
.executed();
return receipt.epochNumber
}

isRead(func: string): boolean {
const f = this._abi.find(element => element.name == func)
let readStates = [ "view", "pure" ]
return readStates.includes(f.stateMutability)
}

async callMethod(func: string, args=[], options={}) {
if (this.isRead(func)) {
if (!_.isEmpty(options))
throw Error("Options specified but ignored.")
return this.callRead(func, args) // returns the read value
} else
return this.callWrite(func, args, options) // returns the block number
}

// Getter functions
getContractAddress(): string {
return this._contract.address
}
getAccountAddress(): string {
return this._genesisAccount.toString()
}
async getBlockTimestamp(blockNumber: number): Promise<number> {
let receipt: any = await this._conflux.getBlockByEpochNumber(blockNumber)
return receipt.timestamp
}
async getBlockParentHash(blockNumber: number): Promise<string> {
let receipt: any = await this._conflux.getBlockByEpochNumber(blockNumber)
return receipt.parentHash
}

hashToString(hash: any): string {
return hash
}

async getEvents(): Promise<Event[]> {
const logs = await this._conflux.getLogs({address: this._contract.address})
let decoded = logs.map(l => this._contract.abi.decodeLog(l))
return decoded.map(o => {
if (!o) return o
let substitutions = {type: "signature", object: "args"}
for (const old_key in substitutions) {
const new_key = substitutions[old_key]
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key))
delete o[old_key];
}
return o
}
)
}
}

interface Logger {
info()
error()
}
8 changes: 0 additions & 8 deletions unittests/constructor2_test.js

This file was deleted.

7 changes: 0 additions & 7 deletions unittests/constructor_test.js

This file was deleted.

Loading

0 comments on commit b399696

Please sign in to comment.