ASSERT_DOES_NOT_COMPILE是否可以使用GTest

Is it possible to ASSERT_DOES_NOT_COMPILE with GTest?

本文关键字:可以使 GTest 是否 COMPILE DOES NOT ASSERT      更新时间:2023-10-16

假设有一个模板类,在编译时声明整型模板实参必须大于零:

template<int N>
class A
{
public:
    A() {
        static_assert(N > 0, "N needs to be greater 0.");
    }
};
是否有可能创建一个googletest单元测试来编译,但是在运行时报告错误?例如:
TEST(TestA, ConstructionNotAllowedWithZero)
{
    ASSERT_DOES_NOT_COMPILE( 
        {
            A< 0 > a;
        }
    );
}

有一种方法,但遗憾的是它可能不是你想要的。

我的第一个想法是试图让SFINAE通过在未求值的上下文中展开无效的lambda来消除过载。不幸的是(在你的情况下),这是特别不允许的…

#define CODE { 
 utter garbage 
}
struct test
{
    template<class T>
    static std::false_type try_compile(...) { return{}; }
    template<class T>
    static auto try_compile(int)
    -> decltype([]() CODE, void(), std::true_type());
    { return {}; }
};
struct tag {};
using does_compile = decltype(test::try_compile<tag>(0));
输出:

./maybe_compile.cpp:88:17: error: lambda expression in an unevaluated operand
    -> decltype([]() CODE, void(), std::true_type());

所以它回到了绘图板和一个很好的老系统调用来调用编译器…

#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <sstream>
struct temp_file {
    temp_file()
    : filename(std::tmpnam(nullptr))
    {}
    ~temp_file() {
        std::remove(filename.c_str());
    }
    std::string filename;
};
bool compiles(const std::string code, std::ostream& reasons)
{
    using namespace std::string_literals;
    temp_file capture_file;
    temp_file cpp_file;
    std::ofstream of(cpp_file.filename);
    std::copy(std::begin(code), std::end(code), std::ostream_iterator<char>(of));
    of.flush();
    of.close();
    const auto cmd_line = "c++ -x c++ -o /dev/null "s + cpp_file.filename + " 2> " + capture_file.filename;
    auto val = system(cmd_line.c_str());
    std::ifstream ifs(capture_file.filename);
    reasons << ifs.rdbuf();
    ifs.close();
    return val == 0;
}
auto main() -> int
{
    std::stringstream reasons1;
    const auto code1 =
R"code(
    #include <iostream>
    int main() {
        return 0;
    }
)code";
    std::cout << "compiles: " << compiles(code1, reasons1) << std::endl;
    std::stringstream reasons2;
    const auto code2 =
R"code(
    #include <iostream>
    int main() {
        FOO!!!!XC@£$%^&*()VBNMYGHH
        return 0;
    }
)code";
    std::cout << "compiles: " << compiles(code2, reasons2) << std::endl;
    std::cout << "nAnd here's why...n";
    std::cout << reasons2.str() << std::endl;
    return 0;
}

在我的例子中给出如下示例输出:

compiles: 1
compiles: 0
And here's why...
/var/tmp/tmp.3.2dADZ7:4:9: error: use of undeclared identifier 'FOO'
        FOO!!!!XC@£$%^&*()VBNMYGHH
        ^
/var/tmp/tmp.3.2dADZ7:4:19: error: non-ASCII characters are not allowed outside of literals and identifiers
        FOO!!!!XC@£$%^&*()VBNMYGHH
                  ^
2 errors generated.
当然,您可以在compiles()调用周围添加所有必要的宏,以便对其进行gwitness。当然,您必须在c编译器调用中设置命令行选项,以设置正确的路径和定义。