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

report_mismatch doesn't handle parameter conversions #138

Open
reddwarf69 opened this issue May 15, 2019 · 3 comments
Open

report_mismatch doesn't handle parameter conversions #138

reddwarf69 opened this issue May 15, 2019 · 3 comments

Comments

@reddwarf69
Copy link
Contributor

I am mocking a function which takes an error_code as a parameter (boost::system, but I guess it would be the same with std::error_code)

TROMPELOEIL_MAKE_MOCK1(Functor, void(const error_code&));

And I'm setting a REQUIRE_CALL expectation as Functor(error::invalid_validate_reply). error being the enum which is implicitly convertible into error_code via std::is_error_code_enum magic.

When the expectation fails trompeloeil outputs something like:
Expected _1 == 4-byte object={ 0x50 0x00 0x00 0x00 }

If instead I set the expectation as Functor(make_error_code(error::invalid_validate_reply)) then I get a better
Expected _1 == <my_error_type>:5

Trompeloeil does know the function expects an error_code, but tries to print the parameter with the type of the function call instead of that of the function argument. No idea if it's even possible, but I would say that ideally it should never be printing Expected _1 == 4-byte object={ 0x50 0x00 0x00 0x00 } when it does know that 5 is converted into an error_code in the function call.

@rollbear
Copy link
Owner

I don't think I understand. Can you provide a concrete example and what you see, and what you'd like to see?

@reddwarf69
Copy link
Contributor Author

reddwarf69 commented May 16, 2019

Actually the problem is not what I though it was. Now I'm not really sure what's going on. But it can be seen here:

#include <trompeloeil.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>

namespace example {

enum class error
{
    myerror = 1,
    myerror2 = 2
};

class error_category_impl final : public boost::system::error_category
{
  public:
    std::string message(int code) const override {
        return "";
    }

    const char* name() const noexcept override {
        return "myerrorcat";
    }
};

boost::system::error_code
make_error_code(error e) {
    static error_category_impl cat;
    return { static_cast<int>(e), cat };
}

}

namespace boost {
namespace system {

template<>
struct is_error_code_enum<example::error> : public std::true_type
{};

}
}

#if 1
namespace std {

template<>
struct is_error_code_enum<example::error> : public std::true_type
{};

}
#endif

class mock
{
  public:
    MAKE_MOCK1(Functor, void(const boost::system::error_code&));
};

int main() {
    mock my_mock;
    REQUIRE_CALL(my_mock, Functor(example::error::myerror));

    my_mock.Functor(example::error::myerror2);
}

If you run it as it is it outputs:

Tried my_mock.Functor(example::error::myerror) at example4.cpp:61
  Expected  _1 == myerrorcat:1

which is what I am expecting, all fine.

But if you change the #if 1 for #if 0 then it outputs:

Tried my_mock.Functor(example::error::myerror) at example4.cpp:61
  Expected  _1 == 4-byte object={ 0x10 0x00 0x00 0x00 }

which is what I was complaining about.

Functor takes a boost::system::error_code, not a std::error_code. So I have absolutely no idea why std::is_error_code_enum has any effect in the output.

@rollbear
Copy link
Owner

Just to let you know I haven't forgotten about this issue. I can reduce it quite a lot, and actually short-circuit Trompeloeil out of it completely.

If you just write std:::cout << example::error::myerror << '\n';, it'll only compile if you have the specialization std::is_error_code_enum<example::error>. Trompeloeil does a compile-time check if ostream& << T is a valid expression, and uses it if it is, otherwise it does a hex-dump, as you have seen.

Now, why it fails to compile if std::is_error_code_enum<example::error> is not specialized, I do not yet know, although I'm guessing it has something to do with ADL. I'll keep trying.

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

No branches or pull requests

2 participants