google / googletest

GoogleTest - Google Testing and Mocking Framework

Home Page:https://google.github.io/googletest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[FR]: Loosen restrictions on what types are considered containers for matchers

ChewyGumball opened this issue · comments

Does the feature exist in the most recent commit?

No.

Why do we need this feature?

There are many types that would be considered containers, but do not expose certain member types or functions that standard containers do.

For instance, std::ranges are not supported because they do not expose the value_type member type (see #3403, #3564, and #4512). Other custom containers do not expose this member type either (see #4375). I also have containers that do not expose begin() and end() member functions, but do expose begin(T) and end(T) free functions.

These types currently can't be used with matchers, which means test authors need to jump through hoops to express what they want.

Describe the proposal.

I propose three things:

  1. StlContainerView gain two additional member types (here type is the container type passed in as a template type):
typedef decltype(*begin(std::declval<type>()) value_type;
typedef decltype(std::distance(begin(std::declval<type>()), end(std::declval<type>()))) difference_type;
  1. All uses of ::value_type and ::difference_type on the direct container type passed in to the matcher would be changed to use the ones on the StlContainerView instead.
  2. All uses of .begin() and .end() member functions be replaced with begin(T), and end(T) free functions when the type is not known to be an STL container.

I also softly propose that StlContainerView be renamed to ContainerView since it no longer is tied so closely to the STL. The rest of this proposal does not depend on the renaming, and it could be considered separately, or not at all if that would be preferred.

There are some use of STL containers internally, and there is no need to change their use, though I would not be opposed to also using free functions for those if uniformity was valued.

For this to work, we would need to add using std::begin; and using std::end; to both the ::testing namespace in the matchers header and the ::internal namespace in the internal utils header, otherwise ADL would not work for both STL types and user defined ones.

I would be willing to submit a PR implementing these changes, including tests, if this proposal is accepted.

With the above changes, this test would compile and pass (custom::Array<T> does not define either member functions or types):

TEST(Containers, ElementsAreArray) {
    custom::Array<int> custom_array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::vector<int> stl_vector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    EXPECT_THAT(std::ranges::iota_view(0, 10), ::testing::ElementsAreArray(custom_array));
    EXPECT_THAT(std::ranges::iota_view(0, 10), ::testing::ElementsAreArray(stl_vector));
    EXPECT_THAT(std::ranges::iota_view(0, 10), ::testing::ElementsAreArray(std::ranges::iota_view(0, 10)));

    EXPECT_THAT(custom_array, ::testing::ElementsAreArray(custom_array));
    EXPECT_THAT(custom_array, ::testing::ElementsAreArray(stl_vector));
    EXPECT_THAT(custom_array, ::testing::ElementsAreArray(std::ranges::iota_view(0, 10)));

    EXPECT_THAT(stl_vector, ::testing::ElementsAreArray(custom_array));
    EXPECT_THAT(stl_vector, ::testing::ElementsAreArray(stl_vector));
    EXPECT_THAT(stl_vector, ::testing::ElementsAreArray(std::ranges::iota_view(0, 10)));
}

While I haven't done an exhaustive test suite yet, I fully expect the other matchers that take containers would similarly pass.

Is the feature specific to an operating system, compiler, or build system version?

N/A