test(@embark): move solidity test to folder structure matching src/; add compiler test

This commit is contained in:
Iuri Matias 2018-12-14 11:53:51 -05:00
parent caf97af0f5
commit ac32cdbfc7
5 changed files with 323 additions and 13 deletions

View File

@ -0,0 +1,78 @@
/*globals describe, it*/
const assert = require('assert');
// TODO: need to rethink i18n and how that is required in each module
require('../../../lib/core/i18n/i18n');
const Compiler = require('../../../lib/modules/compiler');
const File = require('../../../lib/core/file.js');
const Plugins = require('../../../lib/core/plugins.js');
const TestLogger = require('../../../lib/utils/test_logger');
const Events = require('../../../lib/core/events');
const readFile = function(file) {
return new File({filename: file, type: File.types.dapp_file, path: file});
};
const currentSolcVersion = require('../../../../package.json').dependencies.solc;
const TestEvents = {
request: (cmd, cb) => {
cb(currentSolcVersion);
},
emit: (_ev, _data) => {}
};
describe('embark.Compiler', function() {
this.timeout(0);
describe('command: compiler:contracts', function() {
let plugins = new Plugins({
logger: new TestLogger({}),
events: TestEvents,
config: {
contractDirectories: ['app/contracts/'],
embarkConfig: {
options: {
solc: {
"optimize": true,
"optimize-runs": 200
}
}
}
}
});
plugins.createPlugin("sol", {}).registerCompiler(".sol", (_matchingFiles, options, cb) => { return cb(null, {contractA: "solResult"}); });
plugins.createPlugin("vyp", {}).registerCompiler(".vy", (_matchingFiles, options, cb) => { return cb(null, {contractB: "vyResult"}); });
const events = new Events();
const embarkObject = {
registerAPICall: () => {},
events: events,
logger: plugins.logger,
embarkConfig: {
options: {
solc: {
"optimize": true,
"optimize-runs": 200
}
}
}
};
const compiler = new Compiler(embarkObject, {plugins: plugins});
it("should return aggregated result", (done) => {
events.request("compiler:contracts", [
readFile('dist/test/contracts/simple_storage.sol'),
readFile('dist/test/contracts/token.sol'),
readFile('dist/test/contracts/erc20.vy')
], {}, (err, compiledObject) => {
assert.deepEqual(compiledObject, { contractA: 'solResult', contractB: 'vyResult' })
done();
})
})
})
});

View File

@ -0,0 +1,139 @@
# @dev Implementation of ERC-20 token standard.
# @author Takayuki Jimba (@yudetamago)
Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256})
Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256})
name: public(bytes32)
symbol: public(bytes32)
decimals: public(uint256)
balances: map(address, uint256)
allowances: map(address, map(address, uint256))
total_supply: uint256
minter: address
@public
def __init__(_name: bytes32, _symbol: bytes32, _decimals: uint256, _supply: uint256):
init_supply: uint256 = _supply * 10 ** _decimals
sender: address = msg.sender
self.name = _name
self.symbol = _symbol
self.decimals = _decimals
self.balances[sender] = init_supply
self.total_supply = init_supply
self.minter = sender
log.Transfer(ZERO_ADDRESS, sender, init_supply)
# @dev Total number of tokens in existence.
@public
@constant
def totalSupply() -> uint256:
return self.total_supply
# @dev Gets the balance of the specified address.
# @param _owner The address to query the balance of.
# @return An uint256 representing the amount owned by the passed address.
@public
@constant
def balanceOf(_owner : address) -> uint256:
return self.balances[_owner]
# @dev Function to check the amount of tokens that an owner allowed to a spender.
# @param _owner The address which owns the funds.
# @param _spender The address which will spend the funds.
# @return An uint256 specifying the amount of tokens still available for the spender.
@public
@constant
def allowance(_owner : address, _spender : address) -> uint256:
return self.allowances[_owner][_spender]
# @dev Transfer token for a specified address
# @param _to The address to transfer to.
# @param _value The amount to be transferred.
@public
def transfer(_to : address, _value : uint256) -> bool:
_sender: address = msg.sender
self.balances[_sender] = self.balances[_sender] - _value
self.balances[_to] = self.balances[_to] + _value
log.Transfer(_sender, _to, _value)
return True
# @dev Transfer tokens from one address to another.
# Note that while this function emits an Approval event, this is not required as per the specification,
# and other compliant implementations may not emit the event.
# @param _from address The address which you want to send tokens from
# @param _to address The address which you want to transfer to
# @param _value uint256 the amount of tokens to be transferred
@public
def transferFrom(_from : address, _to : address, _value : uint256) -> bool:
_sender: address = msg.sender
allowance: uint256 = self.allowances[_from][_sender]
self.balances[_from] = self.balances[_from] - _value
self.balances[_to] = self.balances[_to] + _value
self.allowances[_from][_sender] = allowance - _value
log.Transfer(_from, _to, _value)
return True
# @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
# Beware that changing an allowance with this method brings the risk that someone may use both the old
# and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
# race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
# https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
# @param _spender The address which will spend the funds.
# @param _value The amount of tokens to be spent.
@public
def approve(_spender : address, _value : uint256) -> bool:
_sender: address = msg.sender
self.allowances[_sender][_spender] = _value
log.Approval(_sender, _spender, _value)
return True
# @dev Mint an amount of the token and assigns it to an account.
# This encapsulates the modification of balances such that the
# proper events are emitted.
# @param _to The account that will receive the created tokens.
# @param _value The amount that will be created.
@public
def mint(_to: address, _value: uint256):
assert msg.sender == self.minter
assert _to != ZERO_ADDRESS
self.total_supply = self.total_supply + _value
self.balances[_to] = self.balances[_to] + _value
log.Transfer(ZERO_ADDRESS, _to, _value)
# @dev Internal function that burns an amount of the token of a given
# account.
# @param _to The account whose tokens will be burned.
# @param _value The amount that will be burned.
@private
def _burn(_to: address, _value: uint256):
assert _to != ZERO_ADDRESS
self.total_supply = self.total_supply - _value
self.balances[_to] = self.balances[_to] - _value
log.Transfer(_to, ZERO_ADDRESS, _value)
# @dev Burn an amount of the token of msg.sender.
# @param _value The amount that will be burned.
@public
def burn(_value: uint256):
self._burn(msg.sender, _value)
# @dev Burn an amount of the token from a given account.
# @param _to The account whose tokens will be burned.
# @param _value The amount that will be burned.
@public
def burnFrom(_to: address, _value: uint256):
_sender: address = msg.sender
self.allowances[_to][_sender] = self.allowances[_to][_sender] - _value
self._burn(_to, _value)

View File

@ -0,0 +1,19 @@
pragma solidity ^0.5.0;
contract SimpleStorage {
uint public storedData;
constructor(uint initialValue) public {
storedData = initialValue;
}
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint retVal) {
return storedData;
}
}

View File

@ -0,0 +1,74 @@
// https://github.com/nexusdev/erc20/blob/master/contracts/base.sol
pragma solidity ^0.5.0;
contract Token {
event Transfer(address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);
mapping( address => uint ) _balances;
mapping( address => mapping( address => uint ) ) _approvals;
uint _supply;
constructor(uint initial_balance) public {
_balances[msg.sender] = initial_balance;
_supply = initial_balance;
}
function totalSupply() public view returns (uint supply) {
return _supply;
}
function balanceOf(address who) public view returns (uint value) {
return _balances[who];
}
function transfer(address to, uint value) public returns (bool ok) {
if( _balances[msg.sender] < value ) {
revert();
}
if( !safeToAdd(_balances[to], value) ) {
revert();
}
_balances[msg.sender] -= value;
_balances[to] += value;
emit Transfer( msg.sender, to, value );
return true;
}
function transferFrom(address from, address to, uint value) public returns (bool ok) {
// if you don't have enough balance, throw
if( _balances[from] < value ) {
revert();
}
// if you don't have approval, throw
if( _approvals[from][msg.sender] < value ) {
revert();
}
if( !safeToAdd(_balances[to], value) ) {
revert();
}
// transfer and return true
_approvals[from][msg.sender] -= value;
_balances[from] -= value;
_balances[to] += value;
emit Transfer( from, to, value );
return true;
}
function approve(address spender, uint value) public returns (bool ok) {
// TODO: should increase instead
_approvals[msg.sender][spender] = value;
emit Approval( msg.sender, spender, value );
return true;
}
function allowance(address owner, address spender) public view returns (uint _allowance) {
return _approvals[owner][spender];
}
function safeToAdd(uint a, uint b) internal pure returns (bool) {
return (a + b >= a);
}
}

View File

@ -1,8 +1,8 @@
/*globals describe, it*/
let SolidityCompiler = require('../lib/modules/solidity');
let TestLogger = require('../lib/utils/test_logger');
let File = require('../lib/core/file.js');
let Ipc = require('../lib/core/ipc.js');
let SolidityCompiler = require('../../../lib/modules/solidity');
let TestLogger = require('../../../lib/utils/test_logger');
let File = require('../../../lib/core/file.js');
let Ipc = require('../../../lib/core/ipc.js');
let assert = require('assert');
let readFile = function(file) {
@ -44,7 +44,7 @@ let generateApiObject = function() {
return apiObject;
}
describe('embark.Compiler', function() {
describe('embark.Solidity', function() {
describe('#compile_solidity', function() {
this.timeout(0);
@ -61,7 +61,7 @@ describe('embark.Compiler', function() {
"gasEstimates":{"creation":{"codeDepositCost":"45000","executionCost":"20141","totalCost":"65141"},"external":{"get()":"428","set(uint256)":"20161","storedData()":"384"}},
"functionHashes":{"get()":"6d4ce63c","set(uint256)":"60fe47b1","storedData()":"2a1afcd9"},
"abiDefinition":[{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}],
"filename":"dist/test/contracts/simple_storage.sol"
"filename":"dist/test/modules/solidity/contracts/simple_storage.sol"
};
expectedObject["Token"] = {
@ -72,13 +72,13 @@ describe('embark.Compiler', function() {
"gasEstimates":{"creation":{"codeDepositCost":"209600","executionCost":"40385","totalCost":"249985"},"external":{"allowance(address,address)":"818","approve(address,uint256)":"22332","balanceOf(address)":"675","totalSupply()":"406","transfer(address,uint256)":"43544","transferFrom(address,address,uint256)":"64387"},"internal":{"safeToAdd(uint256,uint256)":"24"}},
"functionHashes":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"},
"abiDefinition":[{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"supply","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"value","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"_allowance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initial_balance","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}],
"filename":"dist/test/contracts/token.sol"
"filename":"dist/test/modules/solidity/contracts/token.sol"
};
it('should generate compiled code and abi', function(done) {
compiler.compile_solidity([
readFile('dist/test/contracts/simple_storage.sol'),
readFile('dist/test/contracts/token.sol')
readFile('dist/test/modules/solidity/contracts/simple_storage.sol'),
readFile('dist/test/modules/solidity/contracts/token.sol')
], {}, function(err, compiledContracts) {
//assert.deepEqual(compiledContracts, expectedObject);
done();
@ -104,7 +104,7 @@ describe('embark.Compiler', function() {
"gasEstimates":{"creation":{"codeDepositCost":"55800","executionCost":"20205","totalCost":"76005"},"external":{"get()":"446","set(uint256)":"20227","storedData()":"394"}},
"functionHashes":{"get()":"6d4ce63c","set(uint256)":"60fe47b1","storedData()":"2a1afcd9"},
"abiDefinition":[{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}],
"filename":"dist/test/contracts/simple_storage.sol"
"filename":"dist/test/modules/solidity/contracts/simple_storage.sol"
};
expectedObject["Token"] = {
@ -115,13 +115,13 @@ describe('embark.Compiler', function() {
"gasEstimates":{"creation":{"codeDepositCost":"470000","executionCost":"40708","totalCost":"510708"},"external":{"allowance(address,address)":"794","approve(address,uint256)":"22331","balanceOf(address)":"625","totalSupply()":"424","transfer(address,uint256)":"43562","transferFrom(address,address,uint256)":"64373"},"internal":{"safeToAdd(uint256,uint256)":"45"}},
"functionHashes":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"},
"abiDefinition":[{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"supply","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"value","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"_allowance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initial_balance","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}],
"filename":"dist/test/contracts/token.sol"
"filename":"dist/test/modules/solidity/contracts/token.sol"
};
it('should generate compiled code and abi', function(done) {
compiler.compile_solidity([
readFile('dist/test/contracts/simple_storage.sol'),
readFile('dist/test/contracts/token.sol')
readFile('dist/test/modules/solidity/contracts/simple_storage.sol'),
readFile('dist/test/modules/solidity/contracts/token.sol')
], {}, function(err, compiledContracts) {
//assert.deepEqual(compiledContracts, expectedObject);
done();