use piecrust::{ContractData, Error, SessionData, VM, contract_bytecode};
use piecrust_uplink::ContractId;
const LIMIT: u64 = 1_000_000;
#[test]
fn metadata() -> Result<(), Error> {
const EXPECTED_OWNER: [u8; 33] = [3u8; 33];
let vm = VM::ephemeral()?;
let mut session = vm.session(SessionData::builder())?;
let (id, _) = session.deploy::<_, (), _>(
contract_bytecode!("metadata"),
ContractData::builder().owner(EXPECTED_OWNER),
LIMIT,
)?;
let owner = session
.call::<_, [u8; 33]>(id, "read_owner", &(), LIMIT)?
.data;
let self_id = session
.call::<_, ContractId>(id, "read_id", &(), LIMIT)?
.data;
assert_eq!(owner, EXPECTED_OWNER);
assert_eq!(self_id, id);
let commit_id = session.commit()?;
let mut session = vm.session(SessionData::builder().base(commit_id))?;
let owner = session
.call::<_, [u8; 33]>(id, "read_owner", &(), LIMIT)?
.data;
let self_id = session
.call::<_, ContractId>(id, "read_id", &(), LIMIT)?
.data;
assert_eq!(owner, EXPECTED_OWNER);
assert_eq!(self_id, id);
Ok(())
}
#[test]
fn owner_of() -> Result<(), Error> {
const EXPECTED_OWNER_0: [u8; 33] = [3u8; 33];
const EXPECTED_OWNER_1: [u8; 33] = [4u8; 33];
const CONTRACT_ID_0: ContractId = ContractId::from_bytes([1; 32]);
const CONTRACT_ID_1: ContractId = ContractId::from_bytes([2; 32]);
const CONTRACT_ID_2: ContractId = ContractId::from_bytes([3; 32]);
let vm = VM::ephemeral()?;
let mut session = vm.session(SessionData::builder())?;
session.deploy::<_, (), _>(
contract_bytecode!("metadata"),
ContractData::builder()
.owner(EXPECTED_OWNER_0)
.contract_id(CONTRACT_ID_0),
LIMIT,
)?;
session.deploy::<_, (), _>(
contract_bytecode!("metadata"),
ContractData::builder()
.owner(EXPECTED_OWNER_1)
.contract_id(CONTRACT_ID_1),
LIMIT,
)?;
let owner = session
.call::<_, Option<[u8; 33]>>(
CONTRACT_ID_0,
"read_owner_of",
&CONTRACT_ID_1,
LIMIT,
)?
.data;
assert_eq!(
owner,
Some(EXPECTED_OWNER_1),
"The first contract should think the second contract has the correct owner"
);
let owner = session
.call::<_, Option<[u8; 33]>>(
CONTRACT_ID_1,
"read_owner_of",
&CONTRACT_ID_0,
LIMIT,
)?
.data;
assert_eq!(
owner,
Some(EXPECTED_OWNER_0),
"The second contract should think the first contract has the correct owner"
);
let owner = session
.call::<_, Option<[u8; 33]>>(
CONTRACT_ID_0,
"read_owner_of",
&CONTRACT_ID_2,
LIMIT,
)?
.data;
assert_eq!(
owner, None,
"The first contract should think that the owner of a non-existing contract is None"
);
Ok(())
}
#[test]
fn owner_wrong_n_panics() -> Result<(), Error> {
const OWNER_33: [u8; 33] = [5u8; 33];
let vm = VM::ephemeral()?;
let mut session = vm.session(SessionData::builder())?;
let (id, _) = session.deploy::<_, (), _>(
contract_bytecode!("metadata"),
ContractData::builder().owner(OWNER_33),
LIMIT,
)?;
let result =
session.call::<_, [u8; 32]>(id, "read_owner_wrong_n", &(), LIMIT);
let err = result
.expect_err("self_owner with wrong N should panic inside the contract");
let msg = match &err {
Error::Panic(msg) => msg,
_ => panic!("Expected Error::Panic, got: {err:?}"),
};
assert!(
msg.contains("does not match host owner length"),
"Panic message should mention length mismatch, got: {msg}"
);
let result = session.call::<_, Option<[u8; 32]>>(
id,
"read_owner_of_wrong_n",
&id,
LIMIT,
);
let err = result
.expect_err("owner with wrong N should panic inside the contract");
let msg = match &err {
Error::Panic(msg) => msg,
_ => panic!("Expected Error::Panic, got: {err:?}"),
};
assert!(
msg.contains("does not match host owner length"),
"Panic message should mention length mismatch, got: {msg}"
);
Ok(())
}