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

Add TOML cheatcode support #7317

Merged

Conversation

zerosnacks
Copy link
Member

@zerosnacks zerosnacks commented Mar 5, 2024

Motivation

Closes #4808

Implements TOML cheatcode support equivalent to JSON cheatcode support

Solution

The implementation is a thin serialisation / deserialisation layer to convert between TOML to JSON. Internally it re-uses the existing serialized_jsons state. Has feature parity with JSON cheatcodes people are already familiar with.

Implements the following new cheatcodes:

  • parseToml(string)
  • parseToml(string,key) (key support!)
  • All coercion cheatcodes (e.g. parseTomlUint(string,key)).
  • writeToml(string,path)
  • writeToml(string,path,key)

Re-uses JSON's non-prefixed serialize* methods as they operate on the serialized_jsons state.

Special case is: keyExistsToml(string,key) of which the equivalent is keyExists(string,key) in JSON (introduced in #5431). This was chosen to introduce no breaking changes.

Whilst this approach has some (minor) overhead it was chosen to limit complexity, increase maintainability, avoid breaking changes and achieve feature parity (including paths through jsonpath_lib of which no equivalent TOML library exists).

The test suite is a modified version of Json.t.sol. A possible improvement could be a shared abstraction of the two tests but I consider that to be out of scope for this PR.

At-merge PR:

Post-merge PR:

Known limitations:

  • Currently the conversion from JSON string to TOML datetime is not handled as it would require a Regex match in a likely hot path for something that is highly uncommon.


/// Checks if `key` exists in a TOML table.
#[cheatcode(group = Toml)]
function keyExistsToml(string calldata toml, string calldata key) external view returns (bool);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need a keyExistsToml instead of reusing the keyExists method? Assuming we can't reuse them, we can keep keyExists for backwards compatibility but probably should also add a keyExistsJson alias and deprecate/remove the ambiguous keyExists at some point

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point, I'm in favor.

I don't see an elegant way of reusing the keyExists method without introducing brittle complexity (like a Regex). Would rather opt for explicit naming.

I did do a brief search on Github to see the impact and it should be relatively limited: https://github.com/search?q=vm.keyExists&type=code but we would still need an elegant way of issuing a deprecation message and schedule a removal. I'm unfamiliar with that process.

Happy to add it to this PR or open a separate one.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd say we make the change in this PR. In the past we've used console.logs to surface warnings about cheats being deprecated. That was in forge-std though, presumably we can do the same thing here by inserting the required call to the console address in the cheat implementation. But will defer to @DaniPopes @klkvr and co. on how they prefer to do this

Copy link
Member

Choose a reason for hiding this comment

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

I don't think there is an easy way to log stuff directly from cheatcode impls rn, I've looked into it when working on native asserts. However, refactoring cheats/logging logic to support this is not hard but probably big enough to be out of scope for this PR

We already have cheat categories which should emit warnings, so we can probably just implement this logic and warn users about deprecated cheats (keyExists would be the only one for now I believe)

Copy link
Member Author

@zerosnacks zerosnacks Mar 6, 2024

Choose a reason for hiding this comment

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

I've opted for adding the keyExistsJson alias and marked keyExists with the Deprecated status. I've also added a comment in a few places marking the deprecation.

I've added a bug report for the emitting of warnings and errors here: #7323 so it can be picked up in a different PR.

Copy link
Member

@DaniPopes DaniPopes left a comment

Choose a reason for hiding this comment

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

Approach LGTM, just a few questions.

@zerosnacks zerosnacks changed the title WIP: Add TOML cheatcode support Add TOML cheatcode support Mar 6, 2024
@zerosnacks zerosnacks requested review from mds1, klkvr and DaniPopes March 6, 2024 18:43
Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

test look good!

ptal at cheatcode impl @DaniPopes @klkvr

Comment on lines +4 to +6
[c]
a = 123
b = "test"
Copy link
Member

Choose a reason for hiding this comment

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

do we have a test for this table?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes we do here, the test specifically covers the writing aspect:

function test_serializeNotSimpleToml() public {
string memory json3 = "json3";
string memory path = "fixtures/Toml/write_complex_test.toml";
vm.serializeUint(json3, "a", uint256(123));
string memory semiFinal = vm.serializeString(json3, "b", "test");
string memory finalJson = vm.serializeString(json3, "c", semiFinal);
console.log(finalJson);
vm.writeToml(finalJson, path);
string memory toml = vm.readFile(path);
bytes memory data = vm.parseToml(toml);
notSimpleJson memory decodedData = abi.decode(data, (notSimpleJson));
}

Copy link
Member

@DaniPopes DaniPopes left a comment

Choose a reason for hiding this comment

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

LGTM

@DaniPopes DaniPopes requested a review from mattsse March 7, 2024 21:35
Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

lgtm
send it @zerosnacks

@zerosnacks zerosnacks merged commit cab82fb into foundry-rs:master Mar 8, 2024
20 checks passed
@zerosnacks zerosnacks deleted the feat/add-toml-cheatcode-support branch March 8, 2024 07:59
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.

feat (cheatcode) TOML support
5 participants