# Copyright (c) 2011 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # This file is meant to be included into an target to create a unittest that # invokes a set of no-compile tests. A no-compile test is a test that asserts # a particular construct will not compile. # # Also see: # http://dev.chromium.org/developers/testing/no-compile-tests # # To use this, create a gyp target with the following form: # # import("//build/nocompile.gni") # nocompile_test("my_module_nc_unittests") { # sources = [ # 'nc_testset_1.nc', # 'nc_testset_2.nc', # ] # } # # The .nc files are C++ files that contain code we wish to assert will not # compile. Each individual test case in the file should be put in its own # #ifdef section. The expected output should be appended with a C++-style # comment that has a python list of regular expressions. This will likely # be greater than 80-characters. Giving a solid expected output test is # important so that random compile failures do not cause the test to pass. # # Example .nc file: # # #if defined(TEST_NEEDS_SEMICOLON) // [r"expected ',' or ';' at end of input"] # # int a = 1 # # #elif defined(TEST_NEEDS_CAST) // [r"invalid conversion from 'void*' to 'char*'"] # # void* a = NULL; # char* b = a; # # #endif # # If we needed disable TEST_NEEDS_SEMICOLON, then change the define to: # # DISABLE_TEST_NEEDS_SEMICOLON # TEST_NEEDS_CAST # # The lines above are parsed by a regexp so avoid getting creative with the # formatting or ifdef logic; it will likely just not work. # # Implementation notes: # The .nc files are actually processed by a python script which executes the # compiler and generates a .cc file that is empty on success, or will have a # series of #error lines on failure, and a set of trivially passing gunit # TEST() functions on success. This allows us to fail at the compile step when # something goes wrong, and know during the unittest run that the test was at # least processed when things go right. import("//testing/test.gni") declare_args() { # TODO(crbug.com/105388): make sure no-compile test is not flaky. enable_nocompile_tests = (is_linux || is_mac || is_ios) && is_clang && host_cpu == target_cpu } if (enable_nocompile_tests) { import("//build/config/sysroot.gni") import("//build/config/c++/c++.gni") template("nocompile_test") { nocompile_target = target_name + "_run_nocompile" action_foreach(nocompile_target) { script = "//tools/nocompile_driver.py" sources = invoker.sources result_path = "$target_gen_dir/{{source_name_part}}_nc.cc" depfile = "${result_path}.d" outputs = [ result_path, ] args = [ "4", # number of compilers to invoke in parallel. "{{source}}", rebase_path(result_path, root_build_dir), "--", "-nostdinc++", "-isystem" + rebase_path("$libcxx_prefix/include", root_build_dir), "-isystem" + rebase_path("$libcxxabi_prefix/include", root_build_dir), "-isystem" + rebase_path("$libunwind_prefix/include", root_build_dir), "-std=c++14", "-Wall", "-Werror", "-Wfatal-errors", "-I" + rebase_path("//", root_build_dir), ] if (sysroot != "") { args += [ "--sysroot", rebase_path(sysroot, root_build_dir), ] } } test(target_name) { deps = invoker.deps + [ ":$nocompile_target" ] sources = get_target_outputs(":$nocompile_target") } } }