156 lines
6 KiB
C++
156 lines
6 KiB
C++
// Copyright 2021 Google LLC
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#ifndef HWY_TESTS_HWY_GTEST_H_
|
|
#define HWY_TESTS_HWY_GTEST_H_
|
|
|
|
// Adapters for GUnit to run tests for all targets.
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string>
|
|
#include <tuple>
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "hwy/highway.h"
|
|
|
|
namespace hwy {
|
|
|
|
// googletest before 1.10 didn't define INSTANTIATE_TEST_SUITE_P() but instead
|
|
// used INSTANTIATE_TEST_CASE_P which is now deprecated.
|
|
#ifdef INSTANTIATE_TEST_SUITE_P
|
|
#define HWY_GTEST_INSTANTIATE_TEST_SUITE_P INSTANTIATE_TEST_SUITE_P
|
|
#else
|
|
#define HWY_GTEST_INSTANTIATE_TEST_SUITE_P INSTANTIATE_TEST_CASE_P
|
|
#endif
|
|
|
|
// Helper class to run parametric tests using the hwy target as parameter. To
|
|
// use this define the following in your test:
|
|
// class MyTestSuite : public TestWithParamTarget {
|
|
// ...
|
|
// };
|
|
// HWY_TARGET_INSTANTIATE_TEST_SUITE_P(MyTestSuite);
|
|
// TEST_P(MyTestSuite, MyTest) { ... }
|
|
class TestWithParamTarget : public testing::TestWithParam<int64_t> {
|
|
protected:
|
|
void SetUp() override { SetSupportedTargetsForTest(GetParam()); }
|
|
|
|
void TearDown() override {
|
|
// Check that the parametric test calls SupportedTargets() when the source
|
|
// was compiled with more than one target. In the single-target case only
|
|
// static dispatch will be used anyway.
|
|
#if (HWY_TARGETS & (HWY_TARGETS - 1)) != 0
|
|
EXPECT_TRUE(GetChosenTarget().IsInitialized())
|
|
<< "This hwy target parametric test doesn't use dynamic-dispatch and "
|
|
"doesn't need to be parametric.";
|
|
#endif
|
|
SetSupportedTargetsForTest(0);
|
|
}
|
|
};
|
|
|
|
// Function to convert the test parameter of a TestWithParamTarget for
|
|
// displaying it in the gtest test name.
|
|
static inline std::string TestParamTargetName(
|
|
const testing::TestParamInfo<int64_t>& info) {
|
|
return TargetName(info.param);
|
|
}
|
|
|
|
#define HWY_TARGET_INSTANTIATE_TEST_SUITE_P(suite) \
|
|
HWY_GTEST_INSTANTIATE_TEST_SUITE_P( \
|
|
suite##Group, suite, \
|
|
testing::ValuesIn(::hwy::SupportedAndGeneratedTargets()), \
|
|
::hwy::TestParamTargetName)
|
|
|
|
// Helper class similar to TestWithParamTarget to run parametric tests that
|
|
// depend on the target and another parametric test. If you need to use multiple
|
|
// extra parameters use a std::tuple<> of them and ::testing::Generate(...) as
|
|
// the generator. To use this class define the following in your test:
|
|
// class MyTestSuite : public TestWithParamTargetT<int> {
|
|
// ...
|
|
// };
|
|
// HWY_TARGET_INSTANTIATE_TEST_SUITE_P_T(MyTestSuite, ::testing::Range(0, 9));
|
|
// TEST_P(MyTestSuite, MyTest) { ... GetParam() .... }
|
|
template <typename T>
|
|
class TestWithParamTargetAndT
|
|
: public ::testing::TestWithParam<std::tuple<int64_t, T>> {
|
|
public:
|
|
// Expose the parametric type here so it can be used by the
|
|
// HWY_TARGET_INSTANTIATE_TEST_SUITE_P_T macro.
|
|
using HwyParamType = T;
|
|
|
|
protected:
|
|
void SetUp() override {
|
|
SetSupportedTargetsForTest(std::get<0>(
|
|
::testing::TestWithParam<std::tuple<int64_t, T>>::GetParam()));
|
|
}
|
|
|
|
void TearDown() override {
|
|
// Check that the parametric test calls SupportedTargets() when the source
|
|
// was compiled with more than one target. In the single-target case only
|
|
// static dispatch will be used anyway.
|
|
#if (HWY_TARGETS & (HWY_TARGETS - 1)) != 0
|
|
EXPECT_TRUE(GetChosenTarget().IsInitialized())
|
|
<< "This hwy target parametric test doesn't use dynamic-dispatch and "
|
|
"doesn't need to be parametric.";
|
|
#endif
|
|
SetSupportedTargetsForTest(0);
|
|
}
|
|
|
|
T GetParam() {
|
|
return std::get<1>(
|
|
::testing::TestWithParam<std::tuple<int64_t, T>>::GetParam());
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
std::string TestParamTargetNameAndT(
|
|
const testing::TestParamInfo<std::tuple<int64_t, T>>& info) {
|
|
return std::string(TargetName(std::get<0>(info.param))) + "_" +
|
|
::testing::PrintToString(std::get<1>(info.param));
|
|
}
|
|
|
|
#define HWY_TARGET_INSTANTIATE_TEST_SUITE_P_T(suite, generator) \
|
|
HWY_GTEST_INSTANTIATE_TEST_SUITE_P( \
|
|
suite##Group, suite, \
|
|
::testing::Combine( \
|
|
testing::ValuesIn(::hwy::SupportedAndGeneratedTargets()), \
|
|
generator), \
|
|
::hwy::TestParamTargetNameAndT<suite::HwyParamType>)
|
|
|
|
// Helper macro to export a function and define a test that tests it. This is
|
|
// equivalent to do a HWY_EXPORT of a void(void) function and run it in a test:
|
|
// class MyTestSuite : public TestWithParamTarget {
|
|
// ...
|
|
// };
|
|
// HWY_TARGET_INSTANTIATE_TEST_SUITE_P(MyTestSuite);
|
|
// HWY_EXPORT_AND_TEST_P(MyTestSuite, MyTest);
|
|
#define HWY_EXPORT_AND_TEST_P(suite, func_name) \
|
|
HWY_EXPORT(func_name); \
|
|
TEST_P(suite, func_name) { HWY_DYNAMIC_DISPATCH(func_name)(); } \
|
|
static_assert(true, "For requiring trailing semicolon")
|
|
|
|
#define HWY_EXPORT_AND_TEST_P_T(suite, func_name) \
|
|
HWY_EXPORT(func_name); \
|
|
TEST_P(suite, func_name) { HWY_DYNAMIC_DISPATCH(func_name)(GetParam()); } \
|
|
static_assert(true, "For requiring trailing semicolon")
|
|
|
|
#define HWY_BEFORE_TEST(suite) \
|
|
class suite : public hwy::TestWithParamTarget {}; \
|
|
HWY_TARGET_INSTANTIATE_TEST_SUITE_P(suite); \
|
|
static_assert(true, "For requiring trailing semicolon")
|
|
|
|
} // namespace hwy
|
|
|
|
#endif // HWY_TESTS_HWY_GTEST_H_
|