eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.22k stars 170 forks source link

Stubbing method returning the vector of unique_ptr's generates the compile error. #327

Closed wojweb closed 2 months ago

wojweb commented 5 months ago

Hi Everyone, I have discovered the following issue.

I have simple interface, which returns the vector of unique_ptr, but when I try to fake the return value, I got the compilation error.

usr/include/fakeit/catch/fakeit.hpp:7519:92: required from 'typename std::enable_if<(! std::is_reference::value), fakeit::MethodStubbingProgress<R, arglist>&>::type fakeit::MethodStubbingProgress<R, arglist>::Return(const R&) [with U = std::vector<std::unique_ptr >; R = std::vector<std::unique_ptr >; arglist = {}; typename std::enable_if<(! std::is_reference::value), fakeit::MethodStubbingProgress<R, arglist>&>::type = fakeit::MethodStubbingProgress<std::vector<std::unique_ptr > >&]'

Projects/update-controller/test/deviceManagerTest.cpp:273:59: required from here usr/include/c++/9.3.0/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range 127 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,

"error: static assertion failed: result type must be constructible from value type of input range".

The simplest example looks like the following:

`class A {};

class Interface { public: virtual std::vector<std::unique_ptr> getVectorOfA(); };

SCENARIO("Vector of A cannot be returned") { fakeit::Mock mock; std::vector<std::unique_ptr> vector; vector.push_back(std::make_unique()); fakeit::When(Method(mock, getVectorOfA)).Return(std::move(vector)); }`

I think that the problem is that the moving return call() in fakeit.h:7530 is enabled if type is not copy_constructible, but vector of pointers is marked as copy_constructible despite that it cannot be copied, as described here: https://devblogs.microsoft.com/oldnewthing/20190926-00/?p=102924.

The workaround is not to use the Return faking, and replace it by the Do, but I wanted to point out these issue.

FranckRJ commented 5 months ago

We already have a smart_is_copy_constructible that handles vector properly, we just need to use it more often, it should be easy to fix, thanks for notifying.

malcolmdavey commented 4 months ago

From memory I think I tried to handle unique_ptr, but maybe didn't handle things like vector<unique_ptr>, so the conditions might not be right ... for Return(), it should be default move or better(elide), in preference to copy. AlwaysReturn can't move though

FranckRJ commented 2 months ago

Should be fixed #330 which will be available in the next version.