살군의 보조기억 장치

Another memory device…

TEST() {…} 매크로

leave a comment »

Google test 에서 실제 테스트를 사용하는 것을 살펴보자. opencv_test_core 의 test_eigen.cpp 을 기준으로 찾아보겠다.

TEST(Core_Eigen, scalar_32) {Core_EigenTest_Scalar_32 test; test.safe_run(); }

와 같이 사용한다. 이 TEST() 매크로는 뭘 하는 것일까? 역시 하나씩 파고 들어가보자.

// Define this macro to 1 to omit the definition of TEST(), which
// is a generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_TEST
# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
#endif

라고 되어있다. 위 코드에 있는 GTEST_TEST 매크로는 뭐냐하면,

#define GTEST_TEST(test_case_name, test_name)\
  GTEST_TEST_(test_case_name, test_name, \
              ::testing::Test, ::testing::internal::GetTestTypeId())

이다. 또 매크로다.

// Helper macro for defining tests.
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
 public:\
  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
 private:\
  virtual void TestBody();\
  static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
  GTEST_DISALLOW_COPY_AND_ASSIGN_(\
      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
};\
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
  ::test_info_ =\
    ::testing::internal::MakeAndRegisterTestInfo(\
        #test_case_name, #test_name, NULL, NULL, \
        (parent_id), \
        parent_class::SetUpTestCase, \
        parent_class::TearDownTestCase, \
        new ::testing::internal::TestFactoryImpl<\             
            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()

이건 어마어마하다. 도데체 어떻게 이런 생각을 했는지 모르겠다. line:16 에 있는 # 은 그대로 스트링으로 만들어주는 것이다. 사용 예는 여기에서 볼 수 있다. 위의 코드에 있는 또 다른 매크로들을 살펴보자.

// Expands to the name of the class that implements the given test.
#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
  test_case_name##_##test_name##_Test

// GTEST_ATTRIBUTE_UNUSED_
# define GTEST_ATTRIBUTE_UNUSED_

// GTEST_DISALLOW_COPY_AND_ASSIGN_
// A macro to disallow copy constructor and operator=
// This should be used in the private: declarations for a class.
#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
  type(type const &);\
  GTEST_DISALLOW_ASSIGN_(type)

위에서 본 ## 은 매크로에서 사용하는 것으로 지난번 포스팅에서도 한번 언급을 했는데, 빈 칸을 붙여주는 것이다.
자… 이제 대충 다 찾은거 같다. 이제 맨 처음으로 가서 TEST() 매크로를 하나씩 풀어보자. 이건 정말로 대단히 대단하고 굉장히 굉장한 매크로다. 이런 복잡한 매크로는 본적이 없다. 클래스 선언을 통째로 매크로로 만들어버리는 어마어마한 놈들이다. 거기에 클래스 생성은 팩토리 패턴으로 생성해버린다. 입이 딱 벌어지는 구현이다. 아래 코드가 모든 매크로를 다 풀어쓴 것이다. 제일 위에 있는 한줄의 코드를 풀어쓰면 아래와 같이 된다.

class Core_Eigen_scalar_32_Test : public ::testing::Test {
 public:
  Core_Eigen_scalar_32_Test() {}
 private:
  virtual void TestBody();
  static ::testing::TestInfo* const test_info_ ;
  Core_Eigen_scalar_32_Test(Core_Eigen_scalar_32_Test const &);
  void operator=(Core_Eigen_scalar_32_Test const &);
};

::testing::TestInfo* const Core_Eigen_scalar_32_Test::test_info_ =
    ::testing::internal::MakeAndRegisterTestInfo(
        "Core_Eigen", "scalar_32", NULL, NULL,
        (::testing::internal::GetTestTypeId()),
        ::testing::Test::SetUpTestCase,
        ::testing::Test::TearDownTestCase,
        new ::testing::internal::TestFactoryImpl<Core_Eigen_scalar_32_Test>);
void Core_Eigen_scalar_32_Test::TestBody() { Core_EigenTest_Scalar_32 test; test.safe_run(); }
참고
Advertisements

Written by gomiski

2014/02/17 at 12:08 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: