use insta::assert_snapshot;
use sails_sol_gen::{SolidityFile, generate_solidity_contract};
const SIMPLE_IDL: &str = r#"
program TestProgram {
constructors {
CreatePrg();
}
services {
Svc1: Svc1
}
}
service Svc1 {
functions {
DoThis(p1: u32, p2: String) -> u32;
}
}
"#;
const IDL_W_EVENTS: &str = r#"
program TestProgram {
constructors {
Create();
}
services {
Svc1: Svc1
}
}
service Svc1 {
functions {
DoThis(p1: u32, p2: String) -> u32;
}
events {
DoThisEvent { p1: u32, p2: String },
DoThisEvent2(u32, String),
}
}
"#;
#[test]
fn test_generate_simple_contract() {
let contract = generate_solidity_contract("TestContract", SIMPLE_IDL, SolidityFile::SingleFile);
assert!(
contract.is_ok(),
"Failed to generate contract: {:?}",
contract.err()
);
assert_snapshot!(String::from_utf8(contract.unwrap()).unwrap());
}
#[test]
fn test_generate_contract_w_events() {
let contract =
generate_solidity_contract("TestContract", IDL_W_EVENTS, SolidityFile::SingleFile);
assert!(
contract.is_ok(),
"Failed to generate contract: {:?}",
contract.err()
);
assert_snapshot!(String::from_utf8(contract.unwrap()).unwrap());
}
const IDL_MIXED_INDEXED: &str = r#"
program TestProgram {
constructors {
Create();
}
services {
Svc: Svc
}
}
service Svc {
events {
MixedEvent {
@indexed
f1: u32,
f2: String,
@indexed
f3: u128,
f4: u128
}
}
}
"#;
#[test]
fn test_generate_contract_w_mixed_indexed_events() {
let contract =
generate_solidity_contract("TestContract", IDL_MIXED_INDEXED, SolidityFile::SingleFile);
assert!(
contract.is_ok(),
"Failed to generate contract: {:?}",
contract.err()
);
assert_snapshot!(String::from_utf8(contract.unwrap()).unwrap());
}
const PAYABLE_IDL: &str = r#"
program TestProgram {
constructors {
@payable
Create();
}
services {
MyService
}
}
service MyService {
functions {
@payable
Deposit() -> ();
@returns_value
Withdraw() -> u128;
@payable
@returns_value
SwapAndRefund() -> u128;
@query
RegularCall() -> bool;
}
}
"#;
#[test]
fn test_generate_payable_contract() {
let contract =
generate_solidity_contract("PayableContract", PAYABLE_IDL, SolidityFile::SingleFile);
assert!(
contract.is_ok(),
"Failed to generate contract: {:?}",
contract.err()
);
assert_snapshot!(String::from_utf8(contract.unwrap()).unwrap());
}
const IDL_W_ADDRESS: &str = r#"
program TokenProgram {
constructors {
New();
}
services {
TokenSvc: TokenSvc
}
}
service TokenSvc {
functions {
Transfer(from: Address, to: Address, amount: u128) -> bool;
BalanceOf(owner: Address) -> u128;
Batch(recipients: [Address]) -> [Address];
Fixed(addrs: [Address; 3]) -> [Address; 3];
}
types {
@sol_type: address
struct Address(H160);
}
}
"#;
#[test]
fn test_generate_contract_w_address_type() {
let contract =
generate_solidity_contract("TokenContract", IDL_W_ADDRESS, SolidityFile::SingleFile);
assert!(
contract.is_ok(),
"Failed to generate contract: {:?}",
contract.err()
);
assert_snapshot!(String::from_utf8(contract.unwrap()).unwrap());
}
#[test]
fn codec_selection() {
let idl = r#"
program CodecProgram {
services {
CodecTest
}
}
service CodecTest {
functions {
/// Both codecs
@entry_id: 0
BothMethod(p1: u32) -> string;
/// SCALE only - should be excluded from Solidity
@entry_id: 1
@codec: scale
ScaleOnly(p1: u32) -> u32;
/// Ethabi only
@entry_id: 2
@codec: ethabi
EthabiOnly(p1: u32) -> u32;
/// Payable ethabi
@entry_id: 3
@codec: ethabi
@payable
PayableEthabi(p1: u32) -> u32;
}
events {
/// Both codecs
@entry_id: 0
BothEvent(u32),
/// SCALE only - should be excluded from Solidity
@entry_id: 1
@codec: scale
ScaleOnlyEvent(u32),
/// Ethabi only
@entry_id: 2
@codec: ethabi
EthabiOnlyEvent(u32),
}
}
"#;
let data = generate_solidity_contract("CodecTest", idl, SolidityFile::SingleFile)
.expect("generate solidity contract");
let generated = String::from_utf8(data).expect("utf8 contract");
assert!(
generated.contains("function codecTestBothMethod"),
"expected codecTestBothMethod to be present"
);
assert!(
generated.contains("function codecTestEthabiOnly"),
"expected codecTestEthabiOnly to be present"
);
assert!(
generated.contains("function codecTestPayableEthabi"),
"expected codecTestPayableEthabi to be present"
);
assert!(
!generated.contains("function codecTestScaleOnly"),
"expected codecTestScaleOnly to be filtered out, got:\n{generated}"
);
assert!(
generated.contains("event BothEvent"),
"expected BothEvent to be present"
);
assert!(
generated.contains("event EthabiOnlyEvent"),
"expected EthabiOnlyEvent to be present"
);
assert!(
!generated.contains("event ScaleOnlyEvent"),
"expected ScaleOnlyEvent to be filtered out, got:\n{generated}"
);
assert_snapshot!(generated);
}