googletest : TestWithParam 源码跟踪
来源:互联网 发布:518抽奖软件注册码 编辑:程序博客网 时间:2024/05/18 18:47
classCBaseConfParamTest : public CBaseConf,public::testing::TestWithParam<const char *>
{
};
CBaseConfParamTest类继承自 TestWithParam类,
template <typenameT>
class TestWithParam:public Test, public WithParamInterface<T> {
};
WithParamInterface 保存了T类的一个指针 static const ParamType* parameter_; GetParam()函数就是返回这个静态的 parameter_
template <typenameT>
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(constParamType* 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 <classTestClass> friendclass internal::ParameterizedTestFactory;
};
template <typenameT>
const T*WithParamInterface<T>::parameter_ =NULL;
三个参数的函数
testing::Values("CTest","CBaseConf", "CBaseConfParamTest")
函数匹配对应于
template <typenameT1, 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 <typenameT1, typename T2, typename T3>
class ValueArray3{
public:
ValueArray3(T1v1, T2 v2, T3 v3) :v1_(v1), v2_(v2), v3_(v3) {}
template <typenameT>
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=(constValueArray3& other);
const T1 v1_;
const T2 v2_;
const T3 v3_;
};
该函数返回一个ParamGenerator<T>
template <typenameT, size_t N>
internal::ParamGenerator<T>ValuesIn(constT (&array)[N]) {
return ValuesIn(array, array +N);
}
template <typenameForwardIterator>
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 <typenameT>
class ValuesInIteratorRangeGenerator:public ParamGeneratorInterface<T> {
public:
template <typenameForwardIterator>
ValuesInIteratorRangeGenerator(ForwardIteratorbegin,ForwardIteratorend)
: 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(constParamGeneratorInterface<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(newT(*iterator_));
return value_.get();
}
virtual bool Equals(constParamIteratorInterface<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<constIterator>(&other)->iterator_;
}
private:
Iterator(constIterator& 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>*constbase_;
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=(constValuesInIteratorRangeGenerator& 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(constParamGenerator&other) :impl_(other.impl_) {}
ParamGenerator&operator=(constParamGenerator&other){
impl_ = other.impl_;
return *this;
}
iterator begin() const { returniterator(impl_->Begin());}
iterator end() const { returniterator(impl_->End());}
private:
linked_ptr<constParamGeneratorInterface<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 <classTestCase>
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(conststring& instantiation_name,
GeneratorCreationFunc*func,
constchar* /* 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 (typenameTestInfoContainer::iteratortest_it = tests_.begin();
test_it!= tests_.end();++test_it) {
linked_ptr<TestInfo>test_info= *test_it;
for (typenameInstantiationContainer::iteratorgen_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 (typenameParamGenerator<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
- googletest : TestWithParam 源码跟踪
- googletest初探(一) 源码中的例子
- android源码跟踪调试
- nginx源码跟踪
- 跟踪源码思路小结
- 如何跟踪MFC源码
- 目标跟踪源码总结
- Cinder源码跟踪笔记
- 目标跟踪源码总结
- spring-@Profile源码跟踪
- GoogleTest项目
- googleTest linux
- Googletest使用
- googletest试用
- GoogleTest Primer
- GoogleTest安装
- meanshift跟踪算法及源码
- 调试时附加源码跟踪
- PHP处理后端&接口访问超时
- 兼容IE6~9的进度条
- java 获取系统时间
- JDBC 与Hibernate 区别
- 百度2016校园招聘-开发测试工程师-在线编程题2-比大小
- googletest : TestWithParam 源码跟踪
- jdbc中的日期类型问题
- 第8回哈哈,我会用PopupWindow啦
- java jolokia配置
- HTTP状态码和含义
- Android自定义效果 简易示波器 (1)
- 希尔排序-Java<二>
- qt 日志
- 点击一个Text切换旁边的图片