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 TypedExecutionResult, check result type #659

Merged
merged 3 commits into from
Jan 5, 2021
Merged

Conversation

chfast
Copy link
Collaborator

@chfast chfast commented Nov 23, 2020

  • Introduce TypedExecutionResult which takes the result type from the function type.
  • Adjust Result() matcher to expect TypedExecutionResult and perform type-safe value checks.
  • The Result() is more liberal comparing with TypedValue: it allows u64 - u32 and u64 - i32 if not negative compares.
  • Add Result() unit tests.

@codecov
Copy link

codecov bot commented Nov 23, 2020

Codecov Report

Merging #659 (603aca8) into master (12c0423) will increase coverage by 0.01%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master     #659      +/-   ##
==========================================
+ Coverage   99.28%   99.30%   +0.01%     
==========================================
  Files          72       72              
  Lines        9954    10067     +113     
==========================================
+ Hits         9883     9997     +114     
+ Misses         71       70       -1     
Flag Coverage Δ
spectests 91.50% <ø> (ø)
unittests 99.30% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
test/unittests/api_test.cpp 100.00% <100.00%> (ø)
test/unittests/execute_call_test.cpp 100.00% <100.00%> (ø)
test/unittests/execute_control_test.cpp 99.46% <100.00%> (ø)
test/unittests/execute_numeric_test.cpp 100.00% <100.00%> (ø)
test/unittests/execute_test.cpp 100.00% <100.00%> (ø)
test/unittests/test_utils_test.cpp 100.00% <100.00%> (ø)
test/utils/asserts.cpp 100.00% <100.00%> (ø)
test/utils/asserts.hpp 97.22% <100.00%> (+5.55%) ⬆️
test/utils/execute_helpers.hpp 100.00% <100.00%> (ø)
test/utils/typed_value.hpp 100.00% <100.00%> (ø)

@chfast chfast force-pushed the test_typed_result branch 3 times, most recently from 60eecdf to e586811 Compare November 23, 2020 12:28
@chfast chfast requested review from gumb0 and axic November 23, 2020 12:34
test/utils/asserts.cpp Outdated Show resolved Hide resolved
@chfast chfast force-pushed the test_typed_value branch 3 times, most recently from acdec1b to 678af2f Compare November 23, 2020 19:15
@chfast chfast force-pushed the test_typed_value branch 3 times, most recently from 4452038 to e0b7bd2 Compare November 27, 2020 14:47
@gumb0
Copy link
Collaborator

gumb0 commented Nov 30, 2020

Please rebase.

@chfast
Copy link
Collaborator Author

chfast commented Dec 1, 2020

Please rebase.

I'm not touching this PR until #655 is merged.

@gumb0
Copy link
Collaborator

gumb0 commented Dec 1, 2020

Please rebase.

I'm not touching this PR until #655 is merged.

Then I'm not reviewing it till then.

@chfast chfast force-pushed the test_typed_value branch 4 times, most recently from b96047f to 9c42204 Compare December 29, 2020 19:43
@axic
Copy link
Member

axic commented Dec 29, 2020

Needs rebase, and possibly merging #655 first.

Base automatically changed from test_typed_value to master December 30, 2020 09:04
@chfast
Copy link
Collaborator Author

chfast commented Dec 30, 2020

Rebased, without checking the implementation.

return false;
}

if (arg.trapped || !arg.has_value)
return false;
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps display a reason here too if you do that above?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is not needed because "trapped" execution is printed as "trapped", etc.

Random example:

Value of: execute(*instance, 0, {65534})
Expected: result 1
  Actual: trapped (of type fizzy::test::TypedExecutionResult)

switch (result.type)
{
case ValType::i32:
os << result.value.as<uint32_t>() << " [0x" << std::hex << result.value.as<uint32_t>()
Copy link
Member

Choose a reason for hiding this comment

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

Switch back to dec?

Copy link
Member

Choose a reason for hiding this comment

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

And/or switch to dec explicitly for the first part?

else
os << ExecutionResult{result};

os.flags(format_flags);
Copy link
Member

Choose a reason for hiding this comment

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

Ah this is the reset. So is decimal mode on by default according to the std?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No. It resets to what state it was before. So explicit dec is needed to the first part.

EXPECT_EQ(str_value_i32.str(), "result(42 [0x2a] (i32))");

std::stringstream str_value_i64;
str_value_i64 << TypedExecutionResult{ExecutionResult{Value{42_u64}}, ValType::i64};
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps have a second test with >2^32-1 value.

EXPECT_EQ(str_void.str(), "result()");

std::stringstream str_value_i32;
str_value_i32 << TypedExecutionResult{ExecutionResult{Value{42}}, ValType::i32};
Copy link
Member

Choose a reason for hiding this comment

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

Does this constructor verify that the input is <=2^32-? If not, can you put a test with a large value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here you mean the Value{} constructor. It currently has overloads for many integer types and maps them to wasm types. No additional check is required.


std::stringstream str_value_f32;
str_value_f32 << TypedExecutionResult{ExecutionResult{Value{1.125f}}, ValType::f32};
EXPECT_EQ(str_value_f32.str(), "result(1.125 (f32))");
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a test with negative floating point values?


std::stringstream str_value_i64;
str_value_i64 << TypedExecutionResult{ExecutionResult{Value{42_u64}}, ValType::i64};
EXPECT_EQ(str_value_i64.str(), "result(42 [0x2a] (i64))");
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a test with negative integer values?

@@ -31,13 +31,15 @@ inline ExecutionResult execute(
std::transform(std::cbegin(typed_args), std::cend(typed_args), std::begin(args),
[](const auto& typed_arg) { return typed_arg.value; });

return fizzy::execute(instance, func_idx, args.data());
const auto result = fizzy::execute(instance, func_idx, args.data(), depth);
const auto result_type = func_type.outputs.empty() ? ValType{} : func_type.outputs[0];
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps an assertion that outputs.size() <= 1?

// Require the arg to be TypedExecutionResult.
// This can be a static_assert, but just returning false and failing a test provides better
// location of the error.
using result_type = std::remove_cv_t<std::remove_reference_t<arg_type>>;
if constexpr (!std::is_same_v<result_type, test::TypedExecutionResult>)
{
*result_listener << "TypedExecutionResult expected";
Copy link
Member

Choose a reason for hiding this comment

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

Can the test for texts include this?

MATCHER_P(Result, value, "") // NOLINT(readability-redundant-string-init)
{
using namespace fizzy;

static_assert(is_any_of<value_type, uint32_t, int32_t, uint64_t, int64_t, float, double>);
Copy link
Member

Choose a reason for hiding this comment

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

Why remove this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not strictly needed now and the Result() will just return false.

@chfast chfast force-pushed the test_typed_result branch 2 times, most recently from d975992 to 57fcaf4 Compare January 4, 2021 08:53
using result_type = std::remove_cv_t<std::remove_reference_t<arg_type>>;
if constexpr (!std::is_same_v<result_type, test::TypedExecutionResult>)
{
if (result_listener->IsInterested())
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where is this part of google.test documented?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I found this in implementation of builtin matchers. This seems not to be strictly needed, but this is false e.q. when Not() is used.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems to be undocumented feature. The only mention of result_listener I found uses only operator<< https://github.com/google/googletest/blob/master/googlemock/docs/cheat_sheet.md#defining-matchers

{
return arg.value.i64 == static_cast<uint32_t>(value);
}
else if (arg.type == ValType::i64 && value >= 0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you plan to remove this and change the tests at some point?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not sure. Probably make sense to always use Result(0_u32) or Result(0_u64) only.


TEST(test_utils, result_value_matcher_explain_missing_result_type)
{
const auto result = testing::internal::MakePredicateFormatterFromMatcher(Result(1_u64))(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Well this is clearly something internal to google.mock, I'm not sure it's a good idea to use it. For coverage tests with Not above should be sufficient.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah for coverage you mentioned that tests wth Not don't print output... Ok fine, we can leave this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is to test the message output. Using Not() will get us coverage (if IsInterested() is not used) but we cannot test the message. This was the previous version. I can roll back to that one if preferred.

Copy link
Collaborator

@gumb0 gumb0 left a comment

Choose a reason for hiding this comment

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

Looks good, one minor test suggestion #659 (comment)

@chfast chfast merged commit 9a25602 into master Jan 5, 2021
@chfast chfast deleted the test_typed_result branch January 5, 2021 13:21
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.

3 participants