0

Я пытаюсь установить зависимости в Структуре тестирования модулей Boost. Я нашел this thread У tbat есть пример использования метода test_unit :: depends_on(). Пока что так хорошо, я могу написать некоторую магию вокруг этого, чтобы сгладить ее. Однако UTF не соблюдает тестовые зависимости во время выполнения.Порядок выполнения зависимостей в блоке тестирования модуля расширения Boost Unit

Сценарий: BOOST_AUTO_TEST_CASE А объявлены до другого (В), и А depends_on() B Excpected (по желанию) Результат: Структура определяет зависимость и запускает B, а затем А, если Б удалось. Фактический результат: A пропущен, потому что B, который еще не запущен, «провалился» (т. Е. Нет/ложный результат).

Теперь, моя идея состояла в том, чтобы сделать топологический вид в тестовых случаях/наборах, а затем запустить их в отсортированном порядке. Для этого я создал test_tree_visitor для того, чтобы ходить по наборам и определять порядок члена m_members test_suite.

Однако m_members защищен и недоступен с помощью методов. Поскольку я не могу изменить заголовки, (более сложный переход к более новой версии и т. Д.) И макрокоманды BOOST_ * «hardcode» класса как test_suite, я думал о следующем хакере:

class member_accessible_test_suite : public test_suite 
{ 
public: 
    const std::vector<test_unit_id> *get_members() const { return &m_members; } 
}; 

class dependency_order_visitor : public test_tree_visitor 
{ 
public: 
    virtual void visit(test_case const& tu) 
    {} 

    virtual bool test_suite_start(test_suite const& tu) 
    { 
     const member_accessible_test_suite *psuite(reinterpret_cast<const member_accessible_test_suite*>(&tu)); 
     const std::vector<test_unit_id> *pmembers(psuite->get_members()); 
     /* do something with pmembers */ 
     return true; 
    } 

    virtual void test_suite_finish(test_suite const& tu) 
    {} 

}; 

См watered down version на Coliru

Так что теперь мои вопросы:

  1. Буст библиотеки, как правило, хорошо продуманы - я делаю фундаментальную ошибку из-за недоразумения о конструкции установки тестирования по Requ ирония этой функции?

  2. Поскольку member_accessible_test_suite не имеет данных и добавляет только функции, является ли reinterpret_cast() безопасным или скоростной полосой в землю UB? В любом случае, я боюсь использовать такой ужасный взлом в производстве.

  3. Есть ли лучший способ, и если да, то в какой момент это превратилось в проблему XY?

+1

Мне нечего сказать об этой ускорительной библиотеке, но актер в порядке. См., Например, [Тип сглаживания раздел в cppreference] (http://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing): 'результирующий указатель или ссылка могут быть доступны, если ... T2 является (возможно cv-qualified) динамический тип объекта ... '. И вы можете напрямую использовать ссылку - 'reinterpret_cast (tu)' – dewaffled

+0

Спасибо за ссылку. Я думаю, что «T2 является (возможно, cv-квалифицированным) базовым классом динамического типа объекта» будет применяться, поскольку указатель фактически является test_suite, а не member_accessible_test_suite. Я просто хотел узнать из стандартных свистов, если компилятору разрешено делать неловкие вещи, например, перестраивать или хранить скрытые/внутренние элементы данных с производным классом. – namezero

+0

То, что вы описываете, скорее всего, является уровнем ошибки ('boost.test' выполняет топологическую сортировку и все такое). Не могли бы вы опубликовать код? Я считаю, что это можно легко исправить, а не реализовать то, что уже существует. – Raffi

ответ

-1

следующий образ кажется наиболее подходящим при работе с членами базового класса, которые не подвергаются воздействию с помощью какого-либо механизма (но они должны быть доступны для некоторой близкой функциональности, и базовый класс не должен быть изменен):

Ссылка: Access to private member variables

Смысл этой идеи, почему это работает, можно найти в 14.7.2p8 стандарта:

Обычные правила проверки доступа не применяются к именам, используемым для указания явных экземпляров. В частности, аргументы шаблона и имена, используемые в деклараторе функций (включая типы параметров, типы возвращаемых данных и спецификации исключений), могут быть частными типами или объектами, которые обычно не доступны, и шаблон может быть шаблоном-членом или членом которая обычно не была бы доступна.]

Я взял на себя смелость передать это на два макроса, которые могут пригодиться снова в один прекрасный день.

Как и все эти обходные пути - используйте мудро!

/* The ROB_PRIVATE_MEMBER_INST() macro should be used for explicit instantiation of the template at the appropriate source/compilation unit 
    The ROB_PRIVATE_MEMBER_ACCESS() macro should be used for access to the variable where required 
*/ 
#define ROB_PRIVATE_MEMBER_INST(CLASS, TYPE, MEMBER) \ 
template<typename T>         \ 
struct CLASS##_##MEMBER##_rob_tag {      \ 
    typedef T CLASS::*type;        \ 
    friend type get(CLASS##_##MEMBER##_rob_tag);   \ 
};              \ 
template<typename Tag, typename Tag::type M>   \ 
struct CLASS##_##MEMBER##_rob_private     \ 
{              \ 
    friend typename Tag::type get(Tag) { return M; } \ 
};              \ 
template struct CLASS##_##MEMBER##_rob_private<   \ 
CLASS##_##MEMBER##_rob_tag<TYPE> , &CLASS::MEMBER>;  \ 
/**/ 

#define ROB_PRIVATE_MEMBER_ACCESS(CLASS, INSTANCE, TYPE, MEMBER) \ 
    (INSTANCE.*get(CLASS##_##MEMBER##_rob_tag<TYPE>()))   \ 
/**/