tgoop.com/cxx95/106
Last Update:
#compiler
Простые тесты для C++ кода на Python
Часто хочется покрыть тестами код на C++ в проекте - не логику, которую описывает код, а сам исходный код. Сейчас для этого есть приличное количество чекеров в clang-tidy. Можно написать свой чекер, который все равно будут ревьюить много месяцев и КПД всего этого занятия близок к нулю. Для специфических проверок надо что-то колхозить самому.
Примерных проверок может быть много:typeid(x).name(), потому что он дает mangled имя, с советом использовать костыль, который отдаст demangled имя.
Можно придумать проверку на примере лямбд
int counter = 15;В этом примере лямбда использует внешнюю переменную, которая влияет на логику.
const auto addEvent = [&counter](int number) {
if (counter > 0) {
// do something...
--counter;
}
};
// ... call the lambda
addEvent(1337);
Если переменная используется только внутри лямбды, то ее можно вкостылить прямо в capture list. Тогда вместо двух верхних строк примера будет такая строка, дающая аналогичный результат:
auto addEvent = [counter = 15](int number) mutable {
Такой же подход работает для переменных любых типов. Если интересно, что происходит внутри лямбд, то можно почитать целую книгу про них.Попробуем сделать тест на такие кейсы
LambdaExpr.VarDecl.DeclRefExpr.LambdaExpr, а "объявление переменной" находится вне этого LambdaExpr, то тест должен упасть, потому что данную переменную можно всунуть в capture list лямбды.Этот тест можно сделать на
Поддерживается libclang в Python, и после просмотра примеров можно поставить его себе:
pip install pytestи сделать такой простой тест, где реализуется описанная проверка для лямбд. Можно в директории рядом сохранить тестовый файл source.cpp и проверить, что тест падает:
pip install clang
pip install libclang
python3 -m pytest test.pyВывод:
E Failed: These variables can be declared in lambda capture:libclang на Python выглядит нормально, но неприятно то, что для понятия "нода AST" не к месту придумали новый термин "курсор".
E "counter" (at source.cpp:3:44), to lambda at source.cpp:4:88
Также не хватает некоторых очевидных фичей, например получения родительской ноды: в курсорах есть пара ссылок на другие курсоры (типа родительские, двух видов), но они работают неправильно.
Кроме тестов можно писать другие тулзы, например "кодогенераторы" - которые сгенерируют какой-нибудь исходник на основе существующего кода. Про кодогенераторы можно почитать лонгрид.
Еще можно делать "исправляторы" исходников - которые берут AST, что-то туда дописывают и сохраняют в другой файл, а компилятор имеет дело с уже поправленным AST (то есть с этим другим файлом).
