diff --git a/src/test/op_reversebytes_tests.cpp b/src/test/op_reversebytes_tests.cpp --- a/src/test/op_reversebytes_tests.cpp +++ b/src/test/op_reversebytes_tests.cpp @@ -88,10 +88,35 @@ {}); } +static void RunTestsForFlags(const uint32_t flags, + const std::vector &test_cases, + const std::vector &palindromes) { + // Empty stack. + CheckErrorIfEnabled(flags, {}, CScript() << OP_REVERSEBYTES, + ScriptError::INVALID_STACK_OPERATION); + + for (const ReverseTestCase &test_case : test_cases) { + CheckPassReverse(flags, test_case); + } + + for (const valtype &palindrome : palindromes) { + // Verify palindrome. + CheckPassIfEnabled( + flags, {palindrome}, + CScript() << OP_DUP << OP_REVERSEBYTES << OP_EQUALVERIFY, {}); + } + + // Verify non-palindrome fails. + CheckErrorIfEnabled(flags, {{0x01, 0x02, 0x03, 0x02, 0x02}}, + CScript() + << OP_DUP << OP_REVERSEBYTES << OP_EQUALVERIFY, + ScriptError::EQUALVERIFY); +} + BOOST_AUTO_TEST_CASE(op_reversebytes_tests) { MMIXLinearCongruentialGenerator lcg; // Manual tests. - std::vector test_cases({ + std::vector exhaustive_test_cases({ {{}, {}}, {{99}, {99}}, {{0xde, 0xad}, {0xad, 0xde}}, @@ -99,10 +124,20 @@ {{0xde, 0xad, 0xbe, 0xef}, {0xef, 0xbe, 0xad, 0xde}}, {{0x12, 0x34, 0x56}, {0x56, 0x34, 0x12}}, }); + std::vector curated_test_cases(exhaustive_test_cases); + + // Test cases for a few interesting script flag combinations. + std::vector curated_flags({0}); + for (uint32_t flagindex = 0; flagindex < 32; ++flagindex) { + curated_flags.push_back(1 << flagindex); + } + // Test cases for a few interesting stack item sizes. + std::set curated_datasizes( + {0, 1, 2, 10, 16, 32, 50, 128, 300, 400, 512, 519, 520}); // Palindrome tests, they are their own reverse. - std::vector palindromes; - palindromes.reserve(MAX_SCRIPT_ELEMENT_SIZE); + std::vector exhaustive_palindromes; + std::vector curated_palindromes; // Generated tests: // - for iota(n) mod 256, n = 0,..,520. @@ -119,37 +154,31 @@ palindrome.emplace_back( (item < (datasize + 1) / 2 ? item : datasize - item - 1) % 256); } - test_cases.push_back( - {iota_data, {iota_data.rbegin(), iota_data.rend()}}); - test_cases.push_back( - {random_data, {random_data.rbegin(), random_data.rend()}}); - palindromes.push_back(palindrome); + std::vector new_cases({ + {iota_data, {iota_data.rbegin(), iota_data.rend()}}, + {random_data, {random_data.rbegin(), random_data.rend()}}, + }); + std::copy(new_cases.begin(), new_cases.end(), + std::back_inserter(exhaustive_test_cases)); + exhaustive_palindromes.push_back(palindrome); + // Check if datasize is curated. + if (curated_datasizes.find(datasize) != curated_datasizes.end()) { + std::copy(new_cases.begin(), new_cases.end(), + std::back_inserter(curated_test_cases)); + curated_palindromes.push_back(palindrome); + } } + // Run flags exhaustively (somewhat), with curated set of test cases. for (int i = 0; i < 4096; i++) { // Generate random flags. uint32_t flags = lcg.next(); + RunTestsForFlags(flags, curated_test_cases, curated_palindromes); + } - // Empty stack. - CheckErrorIfEnabled(flags, {}, CScript() << OP_REVERSEBYTES, - ScriptError::INVALID_STACK_OPERATION); - - for (const ReverseTestCase &test_case : test_cases) { - CheckPassReverse(flags, test_case); - } - - for (const valtype &palindrome : palindromes) { - // Verify palindrome. - CheckPassIfEnabled( - flags, {palindrome}, - CScript() << OP_DUP << OP_REVERSEBYTES << OP_EQUALVERIFY, {}); - } - - // Verify non-palindrome fails. - CheckErrorIfEnabled(flags, {{0x01, 0x02, 0x03, 0x02, 0x02}}, - CScript() - << OP_DUP << OP_REVERSEBYTES << OP_EQUALVERIFY, - ScriptError::EQUALVERIFY); + // Run curated set of flags with exhaustive test cases. + for (uint32_t flags : curated_flags) { + RunTestsForFlags(flags, curated_test_cases, curated_palindromes); } }