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

dev: test emit_events #1003

Merged
merged 7 commits into from
Oct 3, 2024
Merged

dev: test emit_events #1003

merged 7 commits into from
Oct 3, 2024

Conversation

DiegoB1911
Copy link
Contributor

@DiegoB1911 DiegoB1911 commented Oct 1, 2024

This PR implements the unit test for the emit_events function.

Pull Request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no API changes)
  • Build-related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

The emit_events function doesn't have any unit tests.

Resolves: #952

What is the new behavior?

  • The test_emit_events function generates some events and adds them to the state before calling the emit_events function. This allows the events to be asserted using the spy.assert_emitted function.
  • I created a MockEvent struct to implement the event trait, as the append_keys_and_data function is required for the assert_emitted function to work. Without that implementation, attempts to assert the events would fail because the expected events in the comparison were empty.
  • I added a helper function to serialize mock events to match the structure of the emitted events, so they can be properly asserted.

Does this introduce a breaking change?

  • Yes
  • No

This change is Reviewable

@enitrat
Copy link
Collaborator

enitrat commented Oct 2, 2024

Hi @DiegoB1911, thank you it is the right approach overall.

However, here are some indications on how to make it "better":

  1. I am not sure to understand what the MockEvent struct is for. You should be able to assert the emission like this:
        let contract_events = EventsFilterBuilderTrait::from_events(@spy.get_events())
            .with_contract_address(test_address())
            .build();

        for event in evm_events {
            let starknet_event = EventIntoStarknetEvent::into(event);
            contract_events.assert_emitted(@starknet_event);
        };
  1. your serialize_mock_events is a good idea, as when we check for events emitted, they are in serialized form. However, a more idiiomatic way would be to define an implementation of the Into trait:
    impl EventIntoStarknetEvent of Into<Event, StarknetEvent> {
       fn into(self: Event) -> StarknetEvent {
           let mut serialized_keys = array![];
           let mut serialized_data = array![];
           Serde::<Array<u256>>::serialize(@self.keys, ref serialized_keys);
           Serde::<Array<u8>>::serialize(@self.data, ref serialized_data);
           StarknetEvent { keys: serialized_keys, data: serialized_data }
       }
   } 

(see usage in example above)

Here is a full git diff of the changes I would make. As you see the logic is roughly the same.

I also modified a file under snforge_utils to avoid passing ownership when using assert_emitted that I pushed on your branch to avoid ownership issues.

crates/evm/src/model.cairo Outdated Show resolved Hide resolved
];

// Serialize events and store in mock_events
serialize_mock_events(events.clone(), ref mock_events);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer the implementation of Into, see main message (but same underlying idea)

#[test]
fn test_emit_events() {
let mut state: State = Default::default();
let mut mock_events = ArrayTrait::<(ContractAddress, MockEvent)>::new();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut mock_events = ArrayTrait::<(ContractAddress, MockEvent)>::new();
let mut mock_events = ArrayTrait::<(ContractAddress, MockEvent)>::new();

no longer required

crates/evm/src/backend/starknet_backend.cairo Outdated Show resolved Hide resolved
@DiegoB1911
Copy link
Contributor Author

@enitrat Thank you for your review and explanation. I hadn’t considered implementing the Into trait in that way, and I also thought about importing snforge_std::Event as you did ("snforge_std::Event as StarknetEvent"), but I wasn’t sure it was possible to rename imported elements like in other languages, which is why I created the mock event. Thanks for showing me that approach. I'm still learning how traits and implementations work, and how Cairo functions in general, so I really appreciate your help. I’ve made the requested changes. Please let me know if there’s anything else I need to adjust.

Copy link
Collaborator

@enitrat enitrat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, great job 💪

@enitrat enitrat merged commit f0013f7 into kkrt-labs:main Oct 3, 2024
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

dev: test emit_events
2 participants