Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: separate the resource registration and permission phase for tes… #2627

Merged
merged 3 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ jobs:
- run: |
chmod +x /tmp/bins/sozo
/tmp/bins/sozo --manifest-path crates/dojo/core/Scarb.toml test
/tmp/bins/sozo --manifest-path crates/dojo/core-cairo-test/Scarb.toml test

dojo-spawn-and-move-example-test:
needs: build
Expand All @@ -148,6 +149,7 @@ jobs:
- run: |
chmod +x /tmp/bins/sozo
/tmp/bins/sozo --manifest-path examples/spawn-and-move/Scarb.toml test
/tmp/bins/sozo --manifest-path examples/simple/Scarb.toml test

clippy:
runs-on: ubuntu-latest-4-cores
Expand Down
6 changes: 3 additions & 3 deletions crates/dojo/core-cairo-test/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use utils::{GasCounter, assert_array, GasCounterTrait};
#[cfg(target: "test")]
pub use world::{
deploy_contract, deploy_with_world_address, spawn_test_world, NamespaceDef, TestResource,
ContractDef, ContractDefTrait
ContractDef, ContractDefTrait, WorldStorageTestTrait,
};

#[cfg(test)]
Expand Down Expand Up @@ -45,8 +45,8 @@ mod tests {
mod world {
mod acl;
//mod entities;
//mod resources;
//mod world;
//mod resources;
mod world;
}

mod utils {
Expand Down
4 changes: 4 additions & 0 deletions crates/dojo/core-cairo-test/src/tests/contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub mod test_contract_upgrade {
#[available_gas(7000000)]
fn test_upgrade_from_world() {
let world = deploy_world();
let world = world.dispatcher;

let base_address = world
.register_contract('salt', "dojo", test_contract::TEST_CLASS_HASH.try_into().unwrap());
Expand All @@ -85,6 +86,7 @@ fn test_upgrade_from_world() {
#[should_panic(expected: ('ENTRYPOINT_NOT_FOUND', 'ENTRYPOINT_FAILED'))]
fn test_upgrade_from_world_not_world_provider() {
let world = deploy_world();
let world = world.dispatcher;

let _ = world
.register_contract('salt', "dojo", test_contract::TEST_CLASS_HASH.try_into().unwrap());
Expand All @@ -98,6 +100,7 @@ fn test_upgrade_from_world_not_world_provider() {
#[should_panic(expected: ('must be called by world', 'ENTRYPOINT_FAILED'))]
fn test_upgrade_direct() {
let world = deploy_world();
let world = world.dispatcher;

let base_address = world
.register_contract('salt', "dojo", test_contract::TEST_CLASS_HASH.try_into().unwrap());
Expand Down Expand Up @@ -174,6 +177,7 @@ mod invalid_model_world {
)]
fn test_register_namespace_empty_name() {
let world = deploy_world();
let world = world.dispatcher;

world.register_namespace("");
}
81 changes: 32 additions & 49 deletions crates/dojo/core-cairo-test/src/tests/helpers.cairo
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use starknet::ContractAddress;

use dojo::world::{
IWorldDispatcher, IWorldDispatcherTrait, IWorldTestDispatcher, IWorldTestDispatcherTrait
};
use dojo::world::{IWorldDispatcher, WorldStorage, WorldStorageTrait};
use dojo::model::Model;

use crate::world::{spawn_test_world, NamespaceDef, TestResource, ContractDefTrait};
use crate::world::{
spawn_test_world, NamespaceDef, TestResource, ContractDefTrait, WorldStorageTestTrait
};

pub const DOJO_NSH: felt252 = 0x309e09669bc1fdc1dd6563a7ef862aa6227c97d099d08cc7b81bad58a7443fa;

Expand Down Expand Up @@ -165,90 +165,73 @@ pub enum Weapon {
pub trait Ibar<TContractState> {
fn set_foo(self: @TContractState, a: felt252, b: u128);
fn delete_foo(self: @TContractState);
fn delete_foo_macro(self: @TContractState, foo: Foo);
fn set_char(self: @TContractState, a: felt252, b: u32);
}

#[starknet::contract]
#[dojo::contract]
pub mod bar {
use core::traits::Into;
use starknet::{get_caller_address, ContractAddress};
use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess};
use dojo::model::{Model, ModelIndex};
use super::DOJO_NSH;
use starknet::{get_caller_address};
use dojo::model::{ModelStorage, ModelPtr};

use super::{Foo, IWorldDispatcher, IWorldDispatcherTrait};
use super::{Foo, IWorldDispatcher};

#[storage]
struct Storage {
world: IWorldDispatcher,
}
#[constructor]
fn constructor(ref self: ContractState, world: ContractAddress) {
self.world.write(IWorldDispatcher { contract_address: world })
}

#[abi(embed_v0)]
impl IbarImpl of super::Ibar<ContractState> {
fn set_foo(
self: @ContractState, a: felt252, b: u128
) { // set!(self.world.read(), Foo { caller: get_caller_address(), a, b });
fn set_foo(self: @ContractState, a: felt252, b: u128) {
let mut world = self.world(@"dojo");
world.write_model(@Foo { caller: get_caller_address(), a, b });
}

fn delete_foo(self: @ContractState) {
self
.world
.read()
.delete_entity(
Model::<Foo>::selector(DOJO_NSH),
ModelIndex::Keys([get_caller_address().into()].span()),
Model::<Foo>::layout()
);
}

fn delete_foo_macro(
self: @ContractState, foo: Foo
) { //delete!(self.world.read(), Foo { caller: foo.caller, a: foo.a, b: foo.b });
let mut world = self.world(@"dojo");
let ptr = ModelPtr::<
Foo
>::Id(core::poseidon::poseidon_hash_span([get_caller_address().into()].span()));
world.erase_model_ptr(ptr);
}

fn set_char(self: @ContractState, a: felt252, b: u32) {}
}
}

/// Deploys an empty world with the `dojo` namespace.
pub fn deploy_world() -> IWorldDispatcher {
pub fn deploy_world() -> WorldStorage {
let namespace_def = NamespaceDef { namespace: "dojo", resources: [].span(), };

spawn_test_world([namespace_def].span()).dispatcher
spawn_test_world([namespace_def].span())
}

/// Deploys an empty world with the `dojo` namespace and registers the `foo` model.
/// No permissions are granted.
pub fn deploy_world_and_foo() -> (IWorldDispatcher, felt252) {
let world = deploy_world();
world.register_model("dojo", m_Foo::TEST_CLASS_HASH.try_into().unwrap());
let foo_selector = Model::<Foo>::selector(DOJO_NSH);
pub fn deploy_world_and_foo() -> (WorldStorage, felt252) {
let namespace_def = NamespaceDef {
namespace: "dojo", resources: [TestResource::Model(m_Foo::TEST_CLASS_HASH)].span(),
};

(world, foo_selector)
(spawn_test_world([namespace_def].span()), Model::<Foo>::selector(DOJO_NSH))
}

/// Deploys an empty world with the `dojo` namespace and registers the `foo` model.
/// Grants the `bar` contract writer permissions to the `foo` model.
pub fn deploy_world_and_bar() -> (IWorldDispatcher, IbarDispatcher) {
pub fn deploy_world_and_bar() -> (WorldStorage, IbarDispatcher) {
let namespace_def = NamespaceDef {
namespace: "dojo", resources: [
TestResource::Model(m_Foo::TEST_CLASS_HASH.try_into().unwrap()),
TestResource::Contract(ContractDefTrait::new(bar::TEST_CLASS_HASH, "bar")),
TestResource::Model(m_Foo::TEST_CLASS_HASH),
TestResource::Contract(bar::TEST_CLASS_HASH),
].span(),
};

let world = spawn_test_world([namespace_def].span()).dispatcher;
let bar_address = IWorldTestDispatcher { contract_address: world.contract_address }
.dojo_contract_address(selector_from_tag!("dojo-bar"));
let bar_def = ContractDefTrait::new(@"dojo", @"bar")
.with_writer_of([Model::<Foo>::selector(DOJO_NSH)].span());

let bar_contract = IbarDispatcher { contract_address: bar_address };
let mut world = spawn_test_world([namespace_def].span());
world.sync_perms_and_inits([bar_def].span());

world.grant_writer(Model::<Foo>::selector(DOJO_NSH), bar_address);
let (bar_address, _) = world.dns(@"bar").unwrap();
let bar_contract = IbarDispatcher { contract_address: bar_address };

(world, bar_contract)
}
Expand Down
16 changes: 16 additions & 0 deletions crates/dojo/core-cairo-test/src/tests/world/acl.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use crate::tests::expanded::selector_attack::{attacker_model, attacker_contract}
fn test_owner() {
let (world, foo_selector) = deploy_world_and_foo();

let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();

Expand All @@ -34,6 +36,7 @@ fn test_owner() {
#[should_panic(expected: ("Resource `42` is not registered", 'ENTRYPOINT_FAILED'))]
fn test_grant_owner_not_registered_resource() {
let world = deploy_world();
let world = world.dispatcher;

// 42 is not a registered resource ID
world.grant_owner(42, 69.try_into().unwrap());
Expand All @@ -43,6 +46,7 @@ fn test_grant_owner_not_registered_resource() {
#[should_panic(expected: ('CONTRACT_NOT_DEPLOYED', 'ENTRYPOINT_FAILED'))]
fn test_grant_owner_through_malicious_contract() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -65,6 +69,7 @@ fn test_grant_owner_through_malicious_contract() {
)]
fn test_grant_owner_fails_for_non_owner() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -79,6 +84,7 @@ fn test_grant_owner_fails_for_non_owner() {
#[should_panic(expected: ('CONTRACT_NOT_DEPLOYED', 'ENTRYPOINT_FAILED'))]
fn test_revoke_owner_through_malicious_contract() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -102,6 +108,7 @@ fn test_revoke_owner_through_malicious_contract() {
)]
fn test_revoke_owner_fails_for_non_owner() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -118,6 +125,7 @@ fn test_revoke_owner_fails_for_non_owner() {
#[available_gas(6000000)]
fn test_writer() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

assert(!world.is_writer(foo_selector, 69.try_into().unwrap()), 'should not be writer');

Expand All @@ -131,6 +139,7 @@ fn test_writer() {
#[test]
fn test_writer_not_registered_resource() {
let world = deploy_world();
let world = world.dispatcher;

// 42 is not a registered resource ID
!world.is_writer(42, 69.try_into().unwrap());
Expand All @@ -140,6 +149,7 @@ fn test_writer_not_registered_resource() {
#[should_panic(expected: ('CONTRACT_NOT_DEPLOYED', 'ENTRYPOINT_FAILED'))]
fn test_grant_writer_through_malicious_contract() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -162,6 +172,7 @@ fn test_grant_writer_through_malicious_contract() {
)]
fn test_grant_writer_fails_for_non_owner() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -176,6 +187,7 @@ fn test_grant_writer_fails_for_non_owner() {
#[should_panic(expected: ('CONTRACT_NOT_DEPLOYED', 'ENTRYPOINT_FAILED'))]
fn test_revoke_writer_through_malicious_contract() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -199,6 +211,7 @@ fn test_revoke_writer_through_malicious_contract() {
)]
fn test_revoke_writer_fails_for_non_owner() {
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

let alice = starknet::contract_address_const::<0xa11ce>();
let bob = starknet::contract_address_const::<0xb0b>();
Expand All @@ -221,6 +234,7 @@ fn test_revoke_writer_fails_for_non_owner() {
)]
fn test_not_writer_with_known_contract() {
let (world, _) = deploy_world_and_foo();
let world = world.dispatcher;

let account = starknet::contract_address_const::<0xb0b>();
world.grant_owner(bytearray_hash(@"dojo"), account);
Expand Down Expand Up @@ -259,6 +273,7 @@ fn test_register_model_namespace_not_owner() {

// Owner deploys the world and register Foo model.
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

assert(world.is_owner(foo_selector, owner), 'should be owner');

Expand Down Expand Up @@ -290,6 +305,7 @@ fn test_register_contract_namespace_not_owner() {

// Owner deploys the world and register Foo model.
let (world, foo_selector) = deploy_world_and_foo();
let world = world.dispatcher;

assert(world.is_owner(foo_selector, owner), 'should be owner');

Expand Down
Loading
Loading