mirror of
https://github.com/google/googletest.git
synced 2025-11-08 22:33:51 -05:00
Add a testing::ConvertGenerator overload that accepts a converting functor. This allows the use of classes that do not have a converting ctor to the desired type.
PiperOrigin-RevId: 733383835 Change-Id: I6fbf79db0509b3d4fe8305a83ed47fceaa820e47
This commit is contained in:
committed by
Copybara-Service
parent
24a9e940d4
commit
e88cb95b92
@@ -110,7 +110,7 @@ namespace:
|
||||
| `ValuesIn(container)` or `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)`. |
|
||||
| `Bool()` | Yields sequence `{false, true}`. |
|
||||
| `Combine(g1, g2, ..., gN)` | Yields as `std::tuple` *n*-tuples all combinations (Cartesian product) of the values generated by the given *n* generators `g1`, `g2`, ..., `gN`. |
|
||||
| `ConvertGenerator<T>(g)` | Yields values generated by generator `g`, `static_cast` to `T`. |
|
||||
| `ConvertGenerator<T>(g)` or `ConvertGenerator(g, func)` | Yields values generated by generator `g`, `static_cast` from `T`. (Note: `T` might not be what you expect. See [*Using ConvertGenerator*](#using-convertgenerator) below.) The second overload uses `func` to perform the conversion. |
|
||||
|
||||
The optional last argument *`name_generator`* is a function or functor that
|
||||
generates custom test name suffixes based on the test parameters. The function
|
||||
@@ -137,6 +137,103 @@ For more information, see
|
||||
See also
|
||||
[`GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST`](#GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST).
|
||||
|
||||
###### Using `ConvertGenerator`
|
||||
|
||||
The functions listed in the table above appear to return generators that create
|
||||
values of the desired types, but this is not generally the case. Rather, they
|
||||
typically return factory objects that convert to the the desired generators.
|
||||
This affords some flexibility in allowing you to specify values of types that
|
||||
are different from, yet implicitly convertible to, the actual parameter type
|
||||
required by your fixture class.
|
||||
|
||||
For example, you can do the following with a fixture that requires an `int`
|
||||
parameter:
|
||||
|
||||
```cpp
|
||||
INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
|
||||
testing::Values(1, 1.2)); // Yes, Values() supports heterogeneous argument types.
|
||||
```
|
||||
|
||||
It might seem obvious that `1.2` — a `double` — will be converted to
|
||||
an `int` but in actuality it requires some template gymnastics involving the
|
||||
indirection described in the previous paragraph.
|
||||
|
||||
What if your parameter type is not implicitly convertible from the generated
|
||||
type but is *explicitly* convertible? There will be no automatic conversion, but
|
||||
you can force it by applying `ConvertGenerator<T>`. The compiler can
|
||||
automatically deduce the target type (your fixture's parameter type), but
|
||||
because of the aforementioned indirection it cannot decide what the generated
|
||||
type should be. You need to tell it, by providing the type `T` explicitly. Thus
|
||||
`T` should not be your fixture's parameter type, but rather an intermediate type
|
||||
that is supported by the factory object, and which can be `static_cast` to the
|
||||
fixture's parameter type:
|
||||
|
||||
```cpp
|
||||
// The fixture's parameter type.
|
||||
class MyParam {
|
||||
public:
|
||||
// Explicit converting ctor.
|
||||
explicit MyParam(const std::tuple<int, bool>& t);
|
||||
...
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
|
||||
ConvertGenerator<std::tuple<int, bool>>(Combine(Values(0.1, 1.2), Bool())));
|
||||
```
|
||||
|
||||
In this example `Combine` supports the generation of `std::tuple<int, bool>>`
|
||||
objects (even though the provided values for the first tuple element are
|
||||
`double`s) and those `tuple`s get converted into `MyParam` objects by virtue of
|
||||
the call to `ConvertGenerator`.
|
||||
|
||||
For parameter types that are not convertible from the generated types you can
|
||||
provide a callable that does the conversion. The callable accepts an object of
|
||||
the generated type and returns an object of the fixture's parameter type. The
|
||||
generated type can often be deduced by the compiler from the callable's call
|
||||
signature so you do not usually need specify it explicitly (but see a caveat
|
||||
below).
|
||||
|
||||
```cpp
|
||||
// The fixture's parameter type.
|
||||
class MyParam {
|
||||
public:
|
||||
MyParam(int, bool);
|
||||
...
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
|
||||
ConvertGenerator(Combine(Values(1, 1.2), Bool()),
|
||||
[](const std::tuple<int i, bool>& t){
|
||||
const auto [i, b] = t;
|
||||
return MyParam(i, b);
|
||||
}));
|
||||
```
|
||||
|
||||
The callable may be anything that can be used to initialize a `std::function`
|
||||
with the appropriate call signature. Note the callable's return object gets
|
||||
`static_cast` to the fixture's parameter type, so it does not have to be of that
|
||||
exact type, only convertible to it.
|
||||
|
||||
**Caveat:** Consider the following example.
|
||||
|
||||
```cpp
|
||||
INSTANTIATE_TEST_SUITE_P(MyInstantiation, MyTestSuite,
|
||||
ConvertGenerator(Values(std::string("s")), [](std::string_view s) { ... }));
|
||||
```
|
||||
|
||||
The `string` argument gets copied into the factory object returned by `Values`.
|
||||
Then, because the generated type deduced from the lambda is `string_view`, the
|
||||
factory object spawns a generator that holds a `string_view` referencing that
|
||||
`string`. Unfortunately, by the time this generator gets invoked, the factory
|
||||
object is gone and the `string_view` is dangling.
|
||||
|
||||
To overcome this problem you can specify the generated type explicitly:
|
||||
`ConvertGenerator<std::string>(Values(std::string("s")), [](std::string_view s)
|
||||
{ ... })`. Alternatively, you can change the lambda's signature to take a
|
||||
`std::string` or a `const std::string&` (the latter will not leave you with a
|
||||
dangling reference because the type deduction strips off the reference and the
|
||||
`const`).
|
||||
|
||||
### TYPED_TEST_SUITE {#TYPED_TEST_SUITE}
|
||||
|
||||
`TYPED_TEST_SUITE(`*`TestFixtureName`*`,`*`Types`*`)`
|
||||
|
||||
Reference in New Issue
Block a user