8000 Serde regression tests by tcharding · Pull Request #724 · rust-bitcoin/rust-bitcoin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Serde regression tests #724

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

Merged
merged 1 commit into from
Dec 1, 2022
Merged

Conversation

tcharding
Copy link
Member
@tcharding tcharding commented Nov 25, 2021

Attempts to add regression tests for all types defined in rust-bitcoin that implement Serialize/Deserialize.

  • Add a tests directory and implement regression tests in there
  • Use files for input hex and output bincode to reduce source file clutter
  • Copy test block and include_bytes! usage from RCasatta's PR
  • Uses Kixunil's macro suggested below
  • Adds a single regression test to util/taproot.rs for private types

Note to reviewers

  • Uses JSON for opcodes in a separate file (tests/regression_opcodes.rs), for all other tests uses bincode.
  • Bypasses the order issue for maps by only serializing maps with a single element - is this correct?

Fixes #723

@apoelstra
Copy link
Member

Cool! concept ACK.

Copy link
Collaborator
@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

Concept ACK

@tcharding tcharding force-pushed the serde-tests branch 4 times, most recently from 100b5d5 to ac6552f Compare January 10, 2022 03:55
@tcharding
Copy link
Member Author

There are a few private types in util/taproot.rs and I'm not sure if we need to explicitly test them or if the hex used to create a ControlBlock is enough. I wrote the following test but Rust 1.29 build fails for some reason (cannot compare an array with a vector) even though all the integration tests are like this?

Do we need this one?


    // FIXME: Is this redundant because of serde_regression_taproot_builder() in tests/regression.rs?
    // TaprootMerkleBranch and NodeInfo are private and cannot be explicitly created in regression.rs.
    #[test]
    #[cfg(feature = "serde")]
    fn serde_regression_node_info() {
        use bincode::serialize;

        let s1 = Script::from(vec![0u8, 1u8, 2u8]);
        let s2 = Script::from(vec![3u8, 6u8, 9u8]);
        let ver = LeafVersion::from_consensus(0).unwrap();
        let mut l1 = LeafInfo::new(s1, ver);
        let mut l2 = LeafInfo::new(s2, ver);

        let h1 = sha256::Hash::from_str("cafec44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852babe").unwrap();
        let h2 = sha256::Hash::from_str("deadc44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852beef").unwrap();
        let b1 = TaprootMerkleBranch(vec![h1, h2]);
        let b2 = TaprootMerkleBranch(vec![h2, h1]);
        l1.merkle_branch = b1;
        l2.merkle_branch = b2;


        let info = NodeInfo {
            hash: sha256::Hash::from_str("cafeccafe8fc1c149afbf4c8996fb92427ae41e4649b934ca495991bbabebabe").unwrap(),
            leaves: vec![l1, l2],
        };

        let got = serialize(&info).unwrap();
        let want = [32, 0, 0, 0, 0, 0, 0, 0, 202, 254, 204, 175, 232, 252, 28, 20, 154, 251, 244, 200, 153, 111, 185, 36, 39, 174, 65, 228, 100, 155, 147, 76, 164, 149, 153, 27, 186, 190, 186, 190, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 202, 254, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 153, 111, 185, 36, 39, 174, 65, 228,100, 155, 147, 76, 164, 149, 153, 27, 120, 82, 186, 190, 32, 0, 0, 0, 0, 0, 0, 0, 222, 173, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 153, 111, 185, 36, 39, 174, 65, 228, 100, 155, 147, 76,164, 149, 153, 27, 120, 82, 190, 239, 3, 0, 0, 0, 0, 0, 0, 0, 3, 6, 9, 0, 2, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 222, 173, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 153, 111, 185,36, 39, 174, 65, 228, 100, 155, 147, 76, 164, 149, 153, 27, 120, 82, 190, 239, 32, 0, 0, 0, 0, 0, 0, 0, 202, 254, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 153, 111, 185, 36, 39, 174, 65, 228, 100, 155, 147, 76, 164, 149, 153, 27, 120, 82, 186, 190];
        assert_eq!(got, want)
    }

@tcharding tcharding marked this pull request as ready for review January 10, 2022 04:07
@tcharding tcharding requested review from Kixunil and RCasatta January 10, 2022 04:07
@Kixunil
Copy link
Collaborator
Kixunil commented Jan 10, 2022

Private types shouldn't need serde impls. If they do (because something in the crate uses them inside) then tests are useful to pinpoint the source of problem if something goes wrong.

Change the array to slice to fix compile issue:

let want = &[32, 0 ...] as &[_];

Copy link
Collaborator
@RCasatta RCasatta left a comment

Choose a reason for hiding this comment

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

I think we need one of the following:

  • move tests/bincode and tests/hex inside test_data
  • create tests/data and move test_data, tests/bincode and tests/hex inside it

@tcharding
Copy link
Member Author

Private types shouldn't need serde impls. If they do (because something in the crate uses them inside) then tests are useful to pinpoint the source of problem if something goes wrong.

Cool, I think I'll leave this one out. Since we cannot guarantee that the regression tests test all the serde impls I think its probably better to just keep the public API tests, then they are all in one place. Also this test, as its written, won't help pin point any errors that much more than the ControlBlock test. Unless anyone thinks otherwise ...

Change the array to slice to fix compile issue:

let want = &[32, 0 ...] as &[_];

Oh nice, thanks.

@tcharding
Copy link
Member Author

I think we need one of the following:

* move `tests/bincode` and `tests/hex` inside `test_data`

* create `tests/data` and move `test_data`, `tests/bincode` and `tests/hex` inside it

Good suggestion, I elected to move the files from test_data to a newly created tests/data/ directory.

Copy link
Collaborator
@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

Did only a light review. Since this is not very urgent we can afford a bit of bikesheding, right?

@tcharding
Copy link
Member Author

Since this is not very urgent we can afford a bit of bikesheding, right?

Bikeshed all day! Thanks for the review, I learned a bunch from this review.

@tcharding tcharding force-pushed the serde-tests branch 5 times, most recently from 7db1726 to 95356d1 Compare January 12, 2022 08:47
@tcharding tcharding force-pushed the serde-tests branch 2 times, most recently from 9a86e87 to ac33d08 Compare January 13, 2022 03:10
@tcharding tcharding force-pushed the serde-tests branch 2 times, most recently from 35eba47 to 80d9879 Compare January 19, 2022 03:48
apoelstra
apoelstra previously approved these changes Aug 26, 2022
Copy link
Member
@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 3ef6935149892e6ab7c6320606f4fbe593d262bc

Copy link
Collaborator
@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

Can't do a full review RN just note that I'd prefer having short test strings (e.g. hex public key) inline in tests. At least unless they are some shared canonical test vectors. Wouldn't block the PR for that though.

Files here contain hex strings and binary data representing types used for
regression testing.

- *_hex: consensus encoded types represented as hex strings
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 _hex files? Shouldn't we test hex decoding separately?

Copy link
Member

Choose a reason for hiding this comment

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

TBH I'd rather drop the binary vectors than the hex ones.

Agreed that they're pretty-much redundant and we shouldn't duplicate everything.

Copy link
Member Author

Choose a reason for hiding this comment

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

hmm, I can't really remember why I put some in hex (I did the bulk of this work in November last year) but my guess was that I was lazy and just used hex strings when they appeared elsewhere in the codebase (the binary stuff I generated for each type manually). I do remember going through at the end and moving the hex stuff to files instead of inline. My reasoning was that the data is not meaningful so better to conceal it in a file and keep the test source code clean. I can't remember why I used binary instead of hex for the manually generated types, perhaps because we have the two blocks there in tests/data that are in binary - if we move to hex we should be uniform. We exclude the tests/ directory in Cargo.toml so data size is not a consideration. I do not know what other trade offs there are between the two?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hex helps reviewers see the data without using hexdump and on github. But is it worth complicating the test code that now has to parse hex too? Maybe with my hex_lit macro it wouldn't be so bad but still, if someone makes a mistake in hex parsing impl he'll get tons of unrelated errors.

Copy link
Member

Choose a reason for hiding this comment

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

I think it's fine -- usually they'll just be "parsing" the hex to a Vec<u8> then parsing from there as though it were binary data. And hex->byte vector is write-once code.

Copy link
Member

Choose a reason for hiding this comment

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

We should never need the hex crate.

We should probably add a deserialize_hex method analogous to serialize_hex which uses the bitcoin_hashes::hex module.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't get it, we are explicitly trying to test the serde implementations, we have to use a crate serializes using serde to do so, right?

Copy link
Member

Choose a reason for hiding this comment

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

I was not aware that hex uses serde. What serialization format does it use?

Copy link
Member Author

Choose a reason for hiding this comment

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

Looks like it just serializes as ascii chars: https://docs.rs/hex/latest/hex/serde/fn.serialize.html

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's simple enough for us to NIH it.

sanket1729
sanket1729 previously approved these changes Sep 1, 2022
Copy link
Member
@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

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

reACK 3ef6935149892e6ab7c6320606f4fbe593d262bc

@apoelstra
Copy link
Member

We have two ACKs but I'm not clear whether we want to modify this PR to answer "what should we be doing about hex vs binary" question here.

@tcharding
Copy link
Member Author

I'm not clear whether we want to modify this PR to answer "what should we be doing about hex vs binary" question here.

I am unclear also.

@Kixunil
Copy link
Collaborator
Kixunil commented Sep 14, 2022

When in doubt I usually prefer "make some progress unless this affects API". This already improves things from previous state of the code and we can resolve the remaining issues later.

Unfortunately this needs rebase.

@tcharding
Copy link
Member Author

Rebased and used qualified path for LockTime and PackedLockTime.

apoelstra
apoelstra previously approved these changes Sep 15, 2022
Copy link
Member
@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 9a4c79a390bcedcb78c65a5688f269c36f090823

@tcharding
Copy link
Member Author

Rebased and added tests for Work, Target, relative::LockTime types (Height and Time incl.)

@tcharding
Copy link
Member Author

FTR I have no clue if this covers all types since its been open for so long, I'm not super enthusiastic about auditing again while the PR is open, if/when it merges I can re-audit the whole codebase though.

@tcharding tcharding force-pushed the serde-tests branch 2 times, most recently from 458add6 to 16fd5f6 Compare October 25, 2022 03:06
apoelstra
apoelstra previously approved these changes Oct 25, 2022
Copy link
Member
@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 16fd5f6e8160317b7053b74dc12a1692f1d94475

In order that we can safely change/maintain de/serialization code we
need to have regression tests with hard coded serializations for each
type that implements serde.

It is enough to test a single serde data format, use JSON for `opcodes`
and bincode for other types.

Do regression testing in a newly added `tests` module.
@tcharding
Copy link
Member Author

Re-base and remove the patch to move test data since its on master already.

Copy link
Member
@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 962abcc

Copy link
Member
@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

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

ACK 962abcc. This has been open for a long time. Merging this in the interest of progress.

@sanket1729 sanket1729 merged commit df57a19 into rust-bitcoin:master Dec 1, 2022
@tcharding tcharding deleted the serde-tests branch December 4, 2022 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no release notes mention one ack PRs that have one ACK, so one more can progress them Tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add regression tests for all serde serializations
5 participants
0