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, \

                 &gtest_##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&parameterized_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_namefile,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

 

0 0
原创粉丝点击