Skip to content

Commit

Permalink
tests: execution context (#57)
Browse files Browse the repository at this point in the history
* tests: execution context

* rebase main

* chore: add explanation comment in tests
  • Loading branch information
enitrat authored Aug 14, 2023
1 parent 29bf3ad commit 50a12f1
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 34 deletions.
8 changes: 3 additions & 5 deletions src/context.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,13 @@ impl ExecutionContextImpl of ExecutionContextTrait {
returned_data: Array<u8>,
read_only: bool
) -> ExecutionContext {
let mut stack = StackTrait::new();
ExecutionContext {
call_context,
program_counter: 0,
stack: StackTrait::new(),
stack: Default::default(),
stopped: false,
return_data: ArrayTrait::new(),
memory: MemoryTrait::new(),
return_data: Default::default(),
memory: Default::default(),
gas_used: 0,
gas_limit,
gas_price,
Expand Down Expand Up @@ -241,4 +240,3 @@ impl DefaultExecutionContext of Default<ExecutionContext> {
/// The execution summary.
#[derive(Drop, Copy)]
struct ExecutionSummary {}

1 change: 0 additions & 1 deletion src/model.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ struct Event {
keys: Array<u256>,
data: Array<felt252>,
}

92 changes: 65 additions & 27 deletions src/tests/test_execution_context.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,92 @@ use traits::Into;
use traits::TryInto;
use option::OptionTrait;
use debug::PrintTrait;
use traits::PartialEq;
use array::{ArrayTrait, SpanTrait};
use starknet::{EthAddress, ContractAddress};
use starknet::testing::{set_contract_address, set_caller_address};

use kakarot::memory::{Memory, MemoryTrait};
use kakarot::model::Event;
use kakarot::stack::{Stack, StackTrait};
use kakarot::context::{CallContext, CallContextTrait, ExecutionContext, ExecutionContextTrait};
use kakarot::utils::helpers::{SpanPartialEq};
use traits::PartialEq;
use starknet::{EthAddress, ContractAddress};
//TODO remove import once merged in corelib
use kakarot::utils::helpers::{SpanPartialEq, ArrayPartialEq};
use kakarot::tests::test_utils::{setup_call_context, setup_execution_context, CallContextPartialEq};
use kakarot::tests::test_utils;
use starknet::testing::{set_contract_address, set_caller_address};

fn setup_call_context() -> CallContext {
// TODO remove once no longer required (see https://github.com/starkware-libs/cairo/issues/3863)
#[inline(never)]
fn no_op() {}


#[test]
#[available_gas(1000000)]
fn test_call_context_new() {
// When
let bytecode: Span<u8> = array![1, 2, 3].span();
let call_data: Span<u8> = array![4, 5, 6].span();
let value: u256 = 100;

CallContextTrait::new(bytecode, call_data, value)
let call_ctx = CallContextTrait::new(bytecode, call_data, value);
// TODO remove once no longer required (see https://github.com/starkware-libs/cairo/issues/3863)
no_op();

// Then
assert(call_ctx.bytecode() == bytecode, 'wrong bytecode');
assert(call_ctx.call_data() == call_data, 'wrong call_data');
assert(call_ctx.value() == value, 'wrong value');
}

fn setup_execution_context() -> ExecutionContext {
#[test]
#[available_gas(500000)]
fn test_execution_context_new() {
// Given
let call_context = setup_call_context();
let starknet_address: ContractAddress = test_utils::starknet_address();
let evm_address: EthAddress = test_utils::evm_address();
let program_counter: u32 = 0;
let stack = StackTrait::new();
let stopped: bool = false;
let return_data: Array<u8> = ArrayTrait::new();
let memory = MemoryTrait::new();
let gas_used: u64 = 0;
let gas_limit: u64 = 1000;
let gas_price: u64 = 10;
let starknet_address: ContractAddress = 0.try_into().unwrap();
let evm_address: EthAddress = 0.try_into().unwrap();
let destroy_contracts: Array<EthAddress> = Default::default();
let events: Array<Event> = Default::default();
let create_addresses: Array<EthAddress> = Default::default();
let revert_contract_state: Felt252Dict<felt252> = Default::default();
let reverted: bool = false;
let read_only: bool = false;
let returned_data = Default::default();

ExecutionContextTrait::new(
call_context, starknet_address, evm_address, gas_limit, gas_price, returned_data, read_only
)
}


#[test]
#[available_gas(1000000)]
fn test_call_context_new() {
// When
let call_context = setup_call_context();
// Then
// TODO: uncomment once cairo-test bug is solved
let execution_context = ExecutionContextTrait::new(
call_context, starknet_address, evm_address, gas_limit, gas_price, return_data, read_only
);

// assert(call_context.bytecode() == bytecode, 'wrong bytecode');
// assert(call_context.value() == value, 'wrong value');
// assert(call_context.call_data() == call_data, 'wrong call_data');
// Then
let call_context = setup_call_context();
assert(execution_context.call_context == call_context, 'wrong call_context');
assert(execution_context.program_counter == program_counter, 'wrong program_counter');
assert(execution_context.stack.is_empty(), 'wrong stack');
assert(execution_context.stopped == stopped, 'wrong stopped');
assert(execution_context.return_data == Default::default(), 'wrong return_data');
assert(execution_context.memory.bytes_len == 0, 'wrong memory');
assert(execution_context.gas_used == gas_used, 'wrong gas_used');
assert(execution_context.gas_limit == gas_limit, 'wrong gas_limit');
assert(execution_context.gas_price == gas_price, 'wrong gas_price');
assert(execution_context.starknet_address == starknet_address, 'wrong starknet_address');
assert(execution_context.evm_address == evm_address, 'wrong evm_address');
assert(execution_context.destroy_contracts == destroy_contracts, 'wrong destroy_contracts');
assert(execution_context.events.len() == events.len(), 'wrong events');
assert(execution_context.create_addresses == create_addresses, 'wrong create_addresses');
// Can't verify that reverted_contract_state is empty as we can't compare dictionaries directly
// But initializing it using `Default`, it will be empty.
assert(execution_context.reverted == reverted, 'wrong reverted');
assert(execution_context.read_only == read_only, 'wrong read_only');
}


#[test]
#[available_gas(100000)]
fn test_execution_context_new_and_intrinsic_gas() {
Expand Down Expand Up @@ -88,6 +126,7 @@ fn test_execution_context_revert() {

// Then
assert(execution_context.is_reverted() == true, 'should be reverted');
assert(execution_context.return_data.span() == revert_reason, 'wrong revert reason');
}

#[test]
Expand Down Expand Up @@ -137,7 +176,6 @@ fn test_is_root() {
#[test]
#[available_gas(300000)]
fn test_is_caller_eoa() {
// TODO: finish this test once calling_contexts are implemented
// Given
let mut execution_context = setup_execution_context();

Expand Down
11 changes: 10 additions & 1 deletion src/tests/test_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use starknet::{contract_address_try_from_felt252, ContractAddress, EthAddress};
use traits::{Into, TryInto};
use option::OptionTrait;
use array::{ArrayTrait, SpanTrait};

use kakarot::utils::helpers::{SpanPartialEq};
use kakarot::context::{CallContext, CallContextTrait, ExecutionContext, ExecutionContextTrait};

mod test_helpers;
Expand Down Expand Up @@ -41,3 +41,12 @@ fn setup_execution_context() -> ExecutionContext {
call_context, starknet_address, evm_address, gas_limit, gas_price, returned_data, read_only
)
}

impl CallContextPartialEq of PartialEq<CallContext> {
fn eq(lhs: @CallContext, rhs: @CallContext) -> bool {
lhs.bytecode() == rhs.bytecode() && lhs.call_data == rhs.call_data && lhs.value == rhs.value
}
fn ne(lhs: @CallContext, rhs: @CallContext) -> bool {
!(lhs == rhs)
}
}
10 changes: 10 additions & 0 deletions src/utils/helpers.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ impl ArrayExtension of ArrayExtensionTrait {
}
}

//TODO remove once merged in corelib
impl SpanPartialEq<T, impl PartialEqImpl: PartialEq<T>> of PartialEq<Span<T>> {
fn eq(lhs: @Span<T>, rhs: @Span<T>) -> bool {
if (*lhs).len() != (*rhs).len() {
Expand All @@ -228,3 +229,12 @@ impl SpanPartialEq<T, impl PartialEqImpl: PartialEq<T>> of PartialEq<Span<T>> {
}
}

//TODO remove once merged in corelib
impl ArrayPartialEq<T, impl PartialEqImpl: PartialEq<T>> of PartialEq<Array<T>> {
fn eq(lhs: @Array<T>, rhs: @Array<T>) -> bool {
lhs.span() == rhs.span()
}
fn ne(lhs: @Array<T>, rhs: @Array<T>) -> bool {
!ArrayPartialEq::eq(lhs, rhs)
}
}

0 comments on commit 50a12f1

Please sign in to comment.