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

test: Add a few more corner cases to the base58 test suite #30035

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

paplorinc
Copy link
Contributor

@paplorinc paplorinc commented May 3, 2024

Split out the additional tests from the base58 optimization PR as suggested #29473 (comment)

@DrahtBot
Copy link
Contributor

DrahtBot commented May 3, 2024

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
Concept ACK edilmedeiros
Stale ACK tdb3

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

@DrahtBot DrahtBot added the Tests label May 3, 2024
Copy link
Contributor

@tdb3 tdb3 left a comment

Choose a reason for hiding this comment

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

ACK for 9431bc9
Built and ran unit tests (all passed).
Left one nit, but the nit is outside the scope of this PR, so is probably better left to a separate PR.

Comment on lines +95 to +97
auto leadingSpaces = InsecureRandBool() ? std::string(InsecureRandRange(10), ' ') : "";
auto trailingSpaces = InsecureRandBool() ? std::string(InsecureRandRange(10), ' ') : "";
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Probably outside the scope of this PR (this PR is adding tests, so business logic changes are extraneous), but at first glance, seems like these statements could be simplified, since InsecureRandRange() can return 0, the std::string constructor can handle 0 count, and string operator+ can handle empty string addition. Maybe I'm missing something?

For example:

diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 49ef9ff5b5..beb5ef3335 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -92,8 +92,8 @@ BOOST_AUTO_TEST_CASE(base58_random_encode_decode_with_optional_spaces)
         auto zeroes = InsecureRandBool() ? InsecureRandRange(len + 1) : 0;
         auto data = Cat(std::vector<unsigned char>(zeroes, '\000'), g_insecure_rand_ctx.randbytes(len - zeroes));
 
-        auto leadingSpaces = InsecureRandBool() ? std::string(InsecureRandRange(10), ' ') : "";
-        auto trailingSpaces = InsecureRandBool() ? std::string(InsecureRandRange(10), ' ') : "";
+        auto leadingSpaces = std::string(InsecureRandRange(10), ' ');
+        auto trailingSpaces = std::string(InsecureRandRange(10), ' ');
         auto encoded = leadingSpaces + EncodeBase58Check(data) + trailingSpaces;
 
         std::vector<unsigned char> decoded;

Copy link
Contributor Author

@paplorinc paplorinc May 5, 2024

Choose a reason for hiding this comment

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

Thanks for checking @tdb3, the results would be similar, but since I assumed the spaces are rare in reality, I gave it different odds.
In my impl the probability that we won't have any leading (or trailing) spaces was 50% + 50%*10%, in your impl it's 10%, so spaces would be in most samples.
I'm fine with both.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, that's right (higher probability of no spaces over rand range alone). I don't have a preference, just an observation.

Copy link
Contributor

Choose a reason for hiding this comment

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

I like all this, but it would be better to explain in the PR description why it is important/beneficial to include this change since this increases the test complexity.

Probably would be even better to have a separate test case to check for leading and trailing spaces. This test case is intended to check for leading zeros and now it checks for three concerns (leading zeros, leading spaces, and trailing spaces) instead of one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it checks for three concerns

That's a property based test, i.e. for random valid inputs it checks that certain conditions hold - in this case a roundtrip, that decoding an encoded results in the original trimmed value.
It's meant to find corner cases that we haven't though of, that's its single concern, we have separate tests for each corner case we know about.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added short explanations to the commit message

Copy link
Contributor

@edilmedeiros edilmedeiros 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

Built and ran the unit tests.

The new messages seem to be the opposite of what the tests do, tough.

src/test/base58_tests.cpp Show resolved Hide resolved
src/test/base58_tests.cpp Outdated Show resolved Hide resolved
src/test/base58_tests.cpp Outdated Show resolved Hide resolved
src/test/base58_tests.cpp Outdated Show resolved Hide resolved
@paplorinc
Copy link
Contributor Author

Thanks for the review @edilmedeiros, some of the existing BOOST_CHECK_MESSAGE messages are either in indicative or subjunctive grammatical moods (even in the same file, as you can see).
I'm fine with both, but if you think the subjunctive is more readable, I'll rephrase.

@edilmedeiros
Copy link
Contributor

Thanks for the review @edilmedeiros, some of the existing BOOST_CHECK_MESSAGE messages are either in indicative or subjunctive grammatical moods (even in the same file, as you can see). I'm fine with both, but if you think the subjunctive is more readable, I'll rephrase.

I have no personal preference about it, but this is not my point.

Take for instance Mismatch for test #2: expected 626262, got 626262' has passed.

How can (expected) 626262 not match (got) 626262?

Copy link
Contributor

@edilmedeiros edilmedeiros left a comment

Choose a reason for hiding this comment

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

Gave another deep look at this, thanks again for submitting this PR.

Beside the specific code comments, please add to the commit message why are you adding new test cases, what they improve in the test logic (and how they help the work on #29473).

src/test/base58_tests.cpp Outdated Show resolved Hide resolved
}

BOOST_CHECK(!DecodeBase58("invalid"s, result, 100));
BOOST_CHECK(!DecodeBase58("invalid\0"s, result, 100));
BOOST_CHECK(!DecodeBase58("\0invalid"s, result, 100));

BOOST_CHECK(DecodeBase58("good"s, result, 100));
BOOST_CHECK( DecodeBase58("good"s, result, 100));
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
BOOST_CHECK( DecodeBase58("good"s, result, 100));
BOOST_CHECK(DecodeBase58("good"s, result, 100));

I understand the rational of aligning this with surrounding context, but does seem against guidelines and will look like a typo for others.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks more like a typo, see lines 67 and 78.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't feel strongly about either, removed the space

src/test/base58_tests.cpp Outdated Show resolved Hide resolved
EncodeBase58(sourcedata) == base58string,
strTest);
EncodeBase58(sourcedata) == base58string,
strTest << "\nEncoding `" << HexStr(Span(sourcedata)) << "` as `" << EncodeBase58(sourcedata) << "` should match `" << base58string << "`"
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
strTest << "\nEncoding `" << HexStr(Span(sourcedata)) << "` as `" << EncodeBase58(sourcedata) << "` should match `" << base58string << "`"
strTest << ": got \"" << EncodeBase58(sourcedata) << "\""

What about a little less verbose and taking advantage of the strTest string that has both input and expected outcome?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Didn't realize this, thanks!

test/base58_tests.cpp:40: info: check '["271F359E","zzzzy"]: got "zzzzy"' has passed

BOOST_CHECK(DecodeBase58(base58string, result, 256));
BOOST_CHECK_MESSAGE(
result == expected,
strTest << "\nDecoding `" << base58string << "` as `" << HexStr(result) << "` should match `" << HexStr(expected) << "`"
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
strTest << "\nDecoding `" << base58string << "` as `" << HexStr(result) << "` should match `" << HexStr(expected) << "`"
strTest << ": got \"" << EncodeBase58(sourcedata) << "\""

Same suggestion as above.

Copy link
Contributor Author

@paplorinc paplorinc May 11, 2024

Choose a reason for hiding this comment

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

test/base58_tests.cpp:65: info: check '["271F35A1","211112"]: got XXX "271f35a1"' has passed

src/test/base58_tests.cpp Outdated Show resolved Hide resolved
Comment on lines +95 to +97
auto leadingSpaces = InsecureRandBool() ? std::string(InsecureRandRange(10), ' ') : "";
auto trailingSpaces = InsecureRandBool() ? std::string(InsecureRandRange(10), ' ') : "";
Copy link
Contributor

Choose a reason for hiding this comment

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

I like all this, but it would be better to explain in the PR description why it is important/beneficial to include this change since this increases the test complexity.

Probably would be even better to have a separate test case to check for leading and trailing spaces. This test case is intended to check for leading zeros and now it checks for three concerns (leading zeros, leading spaces, and trailing spaces) instead of one.

auto ok = DecodeBase58Check(encoded, decoded, len + InsecureRandRange(257 - len));
BOOST_CHECK(ok);
BOOST_CHECK(data == decoded);
BOOST_CHECK_MESSAGE(!DecodeBase58Check(encoded, decoded, InsecureRandRange(len)), "Decoding should fail for smaller max_ret_len");
Copy link
Contributor

Choose a reason for hiding this comment

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

Another place where there's a random parameter that's not reported making potential debugging impossible.

Also, the text is no good since max_ret_len is the maximum return size. Better something like Decoding exceeds xxx length. where xxx prints the random parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, added the values to the error message:

test/base58_tests.cpp:102: error: in "base58_tests/base58_random_encode_decode_with_optional_spaces": Decoding should fail for `invalidSmallResultLength` (61)
test/base58_tests.cpp:104: error: in "base58_tests/base58_random_encode_decode_with_optional_spaces": Decoding should succeed within sufficiently large result length (134)

BOOST_CHECK(ok);
BOOST_CHECK(data == decoded);
BOOST_CHECK_MESSAGE(!DecodeBase58Check(encoded, decoded, InsecureRandRange(len)), "Decoding should fail for smaller max_ret_len");
BOOST_CHECK_MESSAGE( DecodeBase58Check(encoded, decoded, len + InsecureRandRange(257 - len)), "Decoding should succeed within valid length range");
Copy link
Contributor

Choose a reason for hiding this comment

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

Same thing about unreported random parameter in the test. This is worse yet since there's a weird logic to get the param. It's good that you submitted this PR, the original test deserved a better look already.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

Please explain in the PR first comment and in the commit message why are you adding these specific test cases, what do they improve in the existing test logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your detailed review, will do that this week

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, done

@paplorinc paplorinc force-pushed the paplorinc/base58-tests branch 4 times, most recently from aae9616 to b1142e3 Compare May 11, 2024 20:37
Add better errors for base58_EncodeBase58 and base58_DecodeBase58 to see the differing value in case of failure.

Extended the base58_random_encode_decode_with_optional_spaces property based test - containing a simple roundtrip with decoding validation - to stress the leading and trailing space parsing as well.

Also extended the base58_encode_decode.json file with a few corner cases - e.g. on a transition of power of 58 to check the boundaries.

Co-authored-by: Edil Medeiros <jose.edil@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants