classCBaseConfParamTest : public CBaseConf,public::testing::TestWithParam<const char *>
{
};
CBaseConfParamTest类继承自 TestWithParam类,
template <typename T>
class TestWithParam: public Test, public WithParamInterface<T> {
};
WithParamInterface 保存了T类的一个指针 static const ParamType* parameter_; GetParam()函数就是返回这个静态的 parameter_
template <typename T>
class WithParamInterface{
public:
typedef T ParamType;
virtual ~WithParamInterface() {}
// The currentparameter value. Is also available in the test fixture's
// constructor.This member function is non-static, even though it only
// referencesstatic data, to reduce the opportunity for incorrect uses
// like writing'WithParamInterface<bool>::GetParam()' for a test that
// uses a fixturewhose parameter type is int.
const ParamType& GetParam()const {
GTEST_CHECK_(parameter_ != NULL)
<< "GetParam()can only be called inside a value-parameterized test "
<< "--did you intend to write TEST_P instead of TEST_F?";
return *parameter_;
}
private:
// Sets parametervalue. The caller is responsible for making sure the value
// remains aliveand unchanged throughout the current test.
static void SetParam(const ParamType* parameter) {
parameter_= parameter;
}
// Static valueused for accessing parameter during a test lifetime.
static const ParamType* parameter_;
// TestClass mustbe a subclass of WithParamInterface<T> and Test.
template <class TestClass> friend class internal::ParameterizedTestFactory;
};
template <typename T>
const T*WithParamInterface<T>::parameter_ = NULL;
三个参数的函数
testing::Values("CTest","CBaseConf", "CBaseConfParamTest")
函数匹配对应于
template <typename T1, typename T2, typename T3>
internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
}
ValueArray3的operator() 函数调用ValuesIn函数,返回一个ParamGenerator<T>类的对象。
template <typename T1, typename T2, typename T3>
class ValueArray3{
public:
ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
template <typename T>
operator ParamGenerator<T>()const {
const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
static_cast<T>(v3_)};
return ValuesIn(array);
}
private:
// Noimplementation - assignment is unsupported.
void operator=(const ValueArray3& other);
const T1 v1_;
const T2 v2_;
const T3 v3_;
};
该函数返回一个ParamGenerator<T>
template <typename T, size_t N>
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
return ValuesIn(array, array + N);
}
template <typename ForwardIterator>
internal::ParamGenerator<
typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
ValuesIn(ForwardIteratorbegin, ForwardIteratorend) {
typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
::value_typeParamType;
return internal::ParamGenerator<ParamType>(
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
}
创建一个 ValuesInIteratorRangeGenerator类的对象。该对象里面有个vector<const char *> container_, 构造函数中初始化该container_的内容。
template <typename T>
class ValuesInIteratorRangeGenerator: public ParamGeneratorInterface<T> {
public:
template <typename ForwardIterator>
ValuesInIteratorRangeGenerator(ForwardIterator begin,ForwardIterator end)
: container_(begin, end) {}
virtual ~ValuesInIteratorRangeGenerator() {}
virtual ParamIteratorInterface<T>*Begin() const{
return new Iterator(this, container_.begin());
}
virtual ParamIteratorInterface<T>*End() const{
return new Iterator(this, container_.end());
}
private:
typedef typename ::std::vector<T> ContainerType;
class Iterator : public ParamIteratorInterface<T>{
public:
Iterator(const ParamGeneratorInterface<T>* base,
typenameContainerType::const_iteratoriterator)
: base_(base), iterator_(iterator) {}
virtual ~Iterator() {}
virtual const ParamGeneratorInterface<T>* BaseGenerator()const {
return base_;
}
virtual void Advance() {
++iterator_;
value_.reset();
}
virtual ParamIteratorInterface<T>*Clone() const{
return new Iterator(*this);
}
// We need to usecached value referenced by iterator_ because *iterator_
// can return atemporary object (and of type other then T), so just
// having"return &*iterator_;" doesn't work.
// value_ isupdated here and not in Advance() because Advance()
// can advanceiterator_ beyond the end of the range, and we cannot
// detect thatfact. The client code, on the other hand, is
// responsiblefor not calling Current() on an out-of-range iterator.
virtual const T* Current() const {
if (value_.get() == NULL)
value_.reset(new T(*iterator_));
return value_.get();
}
virtual bool Equals(const ParamIteratorInterface<T>& other) const {
// Having thesame base generator guarantees that the other
// iterator isof the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
<< "Theprogram attempted to compare iterators "
<< "fromdifferent generators." << std::endl;
return iterator_ ==
CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
}
private:
Iterator(const Iterator& other)
// Theexplicit constructor call suppresses a false warning
// emittedby gcc when supplied with the -Wextra option.
: ParamIteratorInterface<T>(),
base_(other.base_),
iterator_(other.iterator_) {}
const ParamGeneratorInterface<T>*const base_;
typename ContainerType::const_iteratoriterator_;
// A cached valueof *iterator_. We keep it here to allow access by
// pointer in thewrapping iterator's operator->().
// value_ needsto be mutable to be accessed in Current().
// Use ofscoped_ptr helps manage cached value's lifetime,
// which is boundby the lifespan of the iterator itself.
mutable scoped_ptr<const T> value_;
}; // class ValuesInIteratorRangeGenerator::Iterator
// Noimplementation - assignment is unsupported.
void operator=(const ValuesInIteratorRangeGenerator& other);
const ContainerType container_;
}; // classValuesInIteratorRangeGenerator
INSTANTIATE_TEST_CASE_P定义了一个全局函数,返回第三个参数,也就是ParamGenerator<constchar *>对象。同时通过初始化全局的int类型的dummy变量,来调用AddTestCaseInstantiation函数,将全局函数加入到待调用列表。
# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name,generator) \
::testing::internal::ParamGenerator<test_case_name::ParamType>\
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
intgtest_##prefix##test_case_name##_dummy_ = \
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
GetTestCasePatternHolder<test_case_name>(\
#test_case_name, __FILE__,__LINE__)->AddTestCaseInstantiation(\
#prefix, \
>est_##prefix##test_case_name##_EvalGenerator_, \
__FILE__, __LINE__)
ParamGenerator对象会调用ParamGeneratorInterface<T>*impl_的begin和end函数。
在ValuesIn函数中初始化的时候,ValuesInIteratorRangeGenerator就是impl_
template<typenameT>
class ParamGenerator{
public:
typedef ParamIterator<T>iterator;
explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
ParamGenerator(const ParamGenerator&other) : impl_(other.impl_) {}
ParamGenerator&operator=(constParamGenerator& other){
impl_ = other.impl_;
return *this;
}
iterator begin() const { return iterator(impl_->Begin());}
iterator end() const { return iterator(impl_->End());}
private:
linked_ptr<const ParamGeneratorInterface<T> > impl_;
};
UnitTest类的parameterized_test_registry 函数调用UnitTestImpl
类的parameterized_test_registry函数,返回internal::ParameterizedTestCaseRegistry 类型的变量parameterized_test_registry_;
internal::ParameterizedTestCaseRegistry¶meterized_test_registry() {
return parameterized_test_registry_;
}
GetTestCasePatternHolder函数会将创建一个ParameterizedTestCaseInfo<TestCase>*类型的变量,将该变量加入到::std::vector<ParameterizedTestCaseInfoBase*> test_case_infos_中。
TestCaseInfoContainer
class ParameterizedTestCaseRegistry{
public:
ParameterizedTestCaseRegistry(){}
~ParameterizedTestCaseRegistry(){
for (TestCaseInfoContainer::iteratorit = test_case_infos_.begin();
it != test_case_infos_.end();++it) {
delete *it;
}
}
// Looks up orcreates and returns a structure containing information about
// tests andinstantiations of a particular test case.
template <class TestCase>
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
const char* test_case_name,
const char* file,
int line) {
ParameterizedTestCaseInfo<TestCase>* typed_test_info= NULL;
for (TestCaseInfoContainer::iteratorit = test_case_infos_.begin();
it != test_case_infos_.end();++it) {
if ((*it)->GetTestCaseName()== test_case_name) {
if ((*it)->GetTestCaseTypeId()!= GetTypeId<TestCase>()){
// Complainabout incorrect usage of Google Test facilities
// andterminate the program since we cannot guaranty correct
// testcase setup and tear-down in this case.
ReportInvalidTestCaseType(test_case_name, file, line);
posix::Abort();
} else{
// At thispoint we are sure that the object we found is of the same
// type weare looking for, so we downcast it to that type
// withoutfurther checks.
typed_test_info= CheckedDowncastToActualType<
ParameterizedTestCaseInfo<TestCase> >(*it);
}
break;
}
}
if (typed_test_info == NULL){
typed_test_info= new ParameterizedTestCaseInfo<TestCase>(test_case_name);
test_case_infos_.push_back(typed_test_info);
}
return typed_test_info;
}
void RegisterTests() {
for (TestCaseInfoContainer::iteratorit = test_case_infos_.begin();
it != test_case_infos_.end();++it) {
(*it)->RegisterTests();
}
}
private:
typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
TestCaseInfoContainertest_case_infos_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
};
ParameterizedTestCaseInfo类的AddTestCaseInstantiation函数将实例类名对应的创建函数加入到::std::vector<std::pair<string, GeneratorCreationFunc*>>类型的变量instantiations_中。
int AddTestCaseInstantiation(const string& instantiation_name,
GeneratorCreationFunc* func,
const char* /* file */,
int /* line */) {
instantiations_.push_back(::std::make_pair(instantiation_name,func));
return0; // Returnvalue used only to run this method in namespace scope.
}
UnitTest类的Run() 函数会调用UnitTestImpl类的RunAllTest函数。
return internal::HandleExceptionsInMethodIfSupported(
impl(),
&internal::UnitTestImpl::RunAllTests,
"auxiliarytest code (environments or event listeners)") ? 0 : 1;
RunAllTests函数会调用PostFlagParsingInit()函数。PostFlagParsingInit()函数会调用RegisterParameterizedTests来进行注册
void UnitTestImpl::PostFlagParsingInit() {
// Ensures thatthis function does not execute more than once.
if (!post_flag_parse_init_performed_) {
post_flag_parse_init_performed_= true;
#if GTEST_HAS_DEATH_TEST
InitDeathTestSubprocessControlInfo();
SuppressTestEventsIfInSubprocess();
#endif //GTEST_HAS_DEATH_TEST
// Registersparameterized tests. This makes parameterized tests
// available tothe UnitTest reflection API without running
// RUN_ALL_TESTS.
RegisterParameterizedTests();
// Configureslisteners for XML output. This makes it possible for users
// to shut downthe default XML output before invoking RUN_ALL_TESTS.
ConfigureXmlOutput();
#if GTEST_CAN_STREAM_RESULTS_
// Configureslisteners for streaming test results to the specified server.
ConfigureStreamingOutput();
#endif // GTEST_CAN_STREAM_RESULTS_
}
}
RegisterParameterizedTests会调用parameterized_test_registry_类的RegisterTests函数,依次创建TestInfo类的对象。
void UnitTestImpl::RegisterParameterizedTests() {
#if GTEST_HAS_PARAM_TEST
if (!parameterized_tests_registered_) {
parameterized_test_registry_.RegisterTests();
parameterized_tests_registered_= true;
}
#endif
}
ParameterizedTestCaseRegistry类的RegisterTests函数,会依次调用test_case_infos_的每个RegisterTests函数
void RegisterTests() {
for (TestCaseInfoContainer::iteratorit = test_case_infos_.begin();
it != test_case_infos_.end();++it) {
(*it)->RegisterTests();
}
}
ParameterizedTestCaseInfo<TestCase>类的RegisterTests函数,依次调用GeneratorCreationFunc* func函数,也就是gtest_##prefix##test_case_name##_EvalGenerator_() 函数,返回一个ParamGenerator对象generator数组,遍历generator数组中的每个元素,依次调用MakeAndRegisterTestInfo创建和注册TestInfo对象。
virtual void RegisterTests(){
for (typename TestInfoContainer::iterator test_it = tests_.begin();
test_it!= tests_.end();++test_it) {
linked_ptr<TestInfo> test_info= *test_it;
for (typename InstantiationContainer::iterator gen_it =
instantiations_.begin(); gen_it !=instantiations_.end();
++gen_it){
const string& instantiation_name= gen_it->first;
ParamGenerator<ParamType> generator((*gen_it->second)());
string test_case_name;
if ( !instantiation_name.empty())
test_case_name= instantiation_name + "/";
test_case_name+= test_info->test_case_base_name;
int i = 0;
for (typename ParamGenerator<ParamType>::iteratorparam_it =
generator.begin();
param_it!= generator.end();++param_it, ++i){
Messagetest_name_stream;
test_name_stream<< test_info->test_base_name<< "/" << i;
MakeAndRegisterTestInfo(
test_case_name.c_str(),
test_name_stream.GetString().c_str(),
NULL, // No typeparameter.
PrintToString(*param_it).c_str(),
GetTestCaseTypeId(),
TestCase::SetUpTestCase,
TestCase::TearDownTestCase,
test_info->test_meta_factory->CreateTestFactory(*param_it));
} // for param_it
} // for gen_it
} // for test_it
} // RegisterTests