instrumentation: Store CDash settings in query files

Adds new `cdashSubmit` and `cdashVerbose` options to allow enabling
instrumentation in CDash submissions using query files or the
`cmake_instrumentation` command.

Fixes: #26783, #26727
This commit is contained in:
Martin Duffy
2025-07-08 10:31:39 -04:00
parent afa94bae1e
commit 9dec460c8c
12 changed files with 155 additions and 96 deletions

View File

@@ -100,7 +100,7 @@ Enabling Instrumentation for CDash Submissions
You can enable instrumentation when using CTest in :ref:`Dashboard Client` You can enable instrumentation when using CTest in :ref:`Dashboard Client`
mode by setting the :envvar:`CTEST_USE_INSTRUMENTATION` environment variable mode by setting the :envvar:`CTEST_USE_INSTRUMENTATION` environment variable
to the current UUID for the ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` feature. to the current UUID for the ``CMAKE_EXPERIMENTAL_INSTRUMENTATION`` feature.
Doing so automatically enables the ``dynamicSystemInformation`` query. Doing so automatically enables the ``dynamicSystemInformation`` option.
The following table shows how each type of instrumented command gets mapped The following table shows how each type of instrumented command gets mapped
to a corresponding type of CTest XML file. to a corresponding type of CTest XML file.
@@ -125,6 +125,9 @@ By default the command line reported to CDash is truncated at the first space.
You can instead choose to report the full command line (including arguments) You can instead choose to report the full command line (including arguments)
by setting :envvar:`CTEST_USE_VERBOSE_INSTRUMENTATION` to 1. by setting :envvar:`CTEST_USE_VERBOSE_INSTRUMENTATION` to 1.
Alternatively, you can use the `v1 Query Files`_ to enable instrumentation for
CDash using the ``cdashSubmit`` and ``cdashVerbose`` options.
.. _`cmake-instrumentation API v1`: .. _`cmake-instrumentation API v1`:
API v1 API v1
@@ -146,8 +149,9 @@ subdirectories:
``query/generated/`` ``query/generated/``
Holds query files generated by a CMake project with the Holds query files generated by a CMake project with the
:command:`cmake_instrumentation` command. These files are owned by CMake and :command:`cmake_instrumentation` command or the
are deleted and regenerated automatically during the CMake configure step. :envvar:`CTEST_USE_INSTRUMENTATION` variable. These files are owned by CMake
and are deleted and regenerated automatically during the CMake configure step.
``data/`` ``data/``
Holds instrumentation data collected on the project. CMake owns all data Holds instrumentation data collected on the project. CMake owns all data
@@ -193,8 +197,9 @@ key is required, but all other fields are optional.
* ``postTest`` * ``postTest``
``options`` ``options``
A list of strings specifying additional optional data to collect during A list of strings used to enable certain optional behavior, including the
instrumentation. Elements in this list should be one of the following: collection of certain additional data. Elements in this list should be one of
the following:
``staticSystemInformation`` ``staticSystemInformation``
Enables collection of the static information about the host machine CMake Enables collection of the static information about the host machine CMake
@@ -207,13 +212,26 @@ key is required, but all other fields are optional.
generated by CMake, and includes information from immediately before and generated by CMake, and includes information from immediately before and
after the command is executed. after the command is executed.
``cdashSubmit``
Enables including instrumentation data in CDash. This does not
automatically enable ``dynamicSystemInformation``, but is otherwise
equivalent to having the :envvar:`CTEST_USE_INSTRUMENTATION` environment
variable enabled.
``cdashVerbose``
Enables including the full untruncated commands in data submitted to
CDash. Equivalent to having the
:envvar:`CTEST_USE_VERBOSE_INSTRUMENTATION` environment variable enabled.
The ``callbacks`` listed will be invoked during the specified hooks The ``callbacks`` listed will be invoked during the specified hooks
*at a minimum*. When there are multiple query files, the ``callbacks``, *at a minimum*. When there are multiple query files, the ``callbacks``,
``hooks`` and ``options`` between them will be merged. Therefore, if any query ``hooks`` and ``options`` between them will be merged. Therefore, if any query
file includes any ``hooks``, every ``callback`` across all query files will be file includes any ``hooks``, every ``callback`` across all query files will be
executed at every ``hook`` across all query files. Additionally, if any query executed at every ``hook`` across all query files. Additionally, if any query
file includes any optional ``options``, the optional query data will be present file requests optional data using the ``options`` field, any related data will
in all data files. be present in all snippet files. User written ``callbacks`` should be able to
handle the presence of this optional data, since it may be requested by an
unrelated query.
Example: Example:
@@ -231,7 +249,8 @@ Example:
], ],
"options": [ "options": [
"staticSystemInformation", "staticSystemInformation",
"dynamicSystemInformation" "dynamicSystemInformation",
"cdashSubmit"
] ]
} }
@@ -240,12 +259,14 @@ invocation, an index file ``index-<timestamp>.json`` will be generated in
``<build>/.cmake/instrumentation/v1/data`` containing a list of data snippet ``<build>/.cmake/instrumentation/v1/data`` containing a list of data snippet
files created since the previous indexing. The commands files created since the previous indexing. The commands
``/usr/bin/python callback.py index-<timestamp>.json`` and ``/usr/bin/python callback.py index-<timestamp>.json`` and
``/usr/bin/cmake -P callback.cmake arg index-<timestamp>.json`` will be executed in ``/usr/bin/cmake -P callback.cmake arg index-<timestamp>.json`` will be executed
that order. The index file will contain the ``staticSystemInformation`` data and in that order. The index file will contain the ``staticSystemInformation`` data
each snippet file listed in the index will contain the and each snippet file listed in the index will contain the
``dynamicSystemInformation`` data. Once both callbacks have completed, the index ``dynamicSystemInformation`` data. Once both callbacks have completed, the index
file and all snippet files listed by it will be deleted from the project build file and all snippet files listed by it will be deleted from the project build
tree. tree. The instrumentation data will be present in the XML files submitted to
CDash, but with truncated command strings because ``cdashVerbose`` was not
enabled.
.. _`cmake-instrumentation Data v1`: .. _`cmake-instrumentation Data v1`:

View File

@@ -114,7 +114,6 @@ struct cmCTest::Private
bool UseHTTP10 = false; bool UseHTTP10 = false;
bool PrintLabels = false; bool PrintLabels = false;
bool Failover = false; bool Failover = false;
bool UseVerboseInstrumentation = false;
cmJSONState parseState; cmJSONState parseState;
bool FlushTestProgressLine = false; bool FlushTestProgressLine = false;
@@ -320,10 +319,6 @@ cmCTest::cmCTest()
this->Impl->TestProgressOutput = !cmIsOff(envValue); this->Impl->TestProgressOutput = !cmIsOff(envValue);
} }
envValue.clear(); envValue.clear();
if (cmSystemTools::GetEnv("CTEST_USE_VERBOSE_INSTRUMENTATION", envValue)) {
this->Impl->UseVerboseInstrumentation = !cmIsOff(envValue);
}
envValue.clear();
this->Impl->Parts[PartStart].SetName("Start"); this->Impl->Parts[PartStart].SetName("Start");
this->Impl->Parts[PartUpdate].SetName("Update"); this->Impl->Parts[PartUpdate].SetName("Update");
@@ -3629,11 +3624,6 @@ cmInstrumentation& cmCTest::GetInstrumentation()
return *this->Impl->Instrumentation; return *this->Impl->Instrumentation;
} }
bool cmCTest::GetUseVerboseInstrumentation() const
{
return this->Impl->UseVerboseInstrumentation;
}
void cmCTest::ConvertInstrumentationSnippetsToXML(cmXMLWriter& xml, void cmCTest::ConvertInstrumentationSnippetsToXML(cmXMLWriter& xml,
std::string const& subdir) std::string const& subdir)
{ {
@@ -3662,6 +3652,8 @@ void cmCTest::ConvertInstrumentationSnippetsToXML(cmXMLWriter& xml,
bool cmCTest::ConvertInstrumentationJSONFileToXML(std::string const& fpath, bool cmCTest::ConvertInstrumentationJSONFileToXML(std::string const& fpath,
cmXMLWriter& xml) cmXMLWriter& xml)
{ {
bool verboseCommands = this->GetInstrumentation().HasOption(
cmInstrumentationQuery::Option::CDashVerbose);
Json::Value root; Json::Value root;
this->Impl->parseState = cmJSONState(fpath, &root); this->Impl->parseState = cmJSONState(fpath, &root);
if (!this->Impl->parseState.errors.empty()) { if (!this->Impl->parseState.errors.empty()) {
@@ -3710,7 +3702,7 @@ bool cmCTest::ConvertInstrumentationJSONFileToXML(std::string const& fpath,
} }
// Truncate the full command line if verbose instrumentation // Truncate the full command line if verbose instrumentation
// was not requested. // was not requested.
if (key == "command" && !this->GetUseVerboseInstrumentation()) { if (key == "command" && !verboseCommands) {
std::string command_str = root[key].asString(); std::string command_str = root[key].asString();
std::string truncated = command_str.substr(0, command_str.find(' ')); std::string truncated = command_str.substr(0, command_str.find(' '));
if (command_str != truncated) { if (command_str != truncated) {

View File

@@ -436,7 +436,6 @@ public:
std::vector<std::string> GetCommandLineHttpHeaders() const; std::vector<std::string> GetCommandLineHttpHeaders() const;
cmInstrumentation& GetInstrumentation(); cmInstrumentation& GetInstrumentation();
bool GetUseVerboseInstrumentation() const;
private: private:
int GenerateNotesFile(cmake* cm, std::string const& files); int GenerateNotesFile(cmake* cm, std::string const& files);

View File

@@ -29,6 +29,53 @@
using LoadQueriesAfter = cmInstrumentation::LoadQueriesAfter; using LoadQueriesAfter = cmInstrumentation::LoadQueriesAfter;
std::map<std::string, std::string> cmInstrumentation::cdashSnippetsMap = {
{
"configure",
"configure",
},
{
"generate",
"configure",
},
{
"compile",
"build",
},
{
"link",
"build",
},
{
"custom",
"build",
},
{
"build",
"skip",
},
{
"cmakeBuild",
"build",
},
{
"cmakeInstall",
"build",
},
{
"install",
"build",
},
{
"ctest",
"build",
},
{
"test",
"test",
}
};
cmInstrumentation::cmInstrumentation(std::string const& binary_dir, cmInstrumentation::cmInstrumentation(std::string const& binary_dir,
LoadQueriesAfter loadQueries) LoadQueriesAfter loadQueries)
{ {
@@ -38,6 +85,7 @@ cmInstrumentation::cmInstrumentation(std::string const& binary_dir,
this->binaryDir = binary_dir; this->binaryDir = binary_dir;
this->timingDirv1 = this->timingDirv1 =
cmStrCat(this->binaryDir, "/.cmake/instrumentation-", uuid, "/v1"); cmStrCat(this->binaryDir, "/.cmake/instrumentation-", uuid, "/v1");
this->cdashDir = cmStrCat(this->timingDirv1, "/cdash");
if (cm::optional<std::string> configDir = if (cm::optional<std::string> configDir =
cmSystemTools::GetCMakeConfigDirectory()) { cmSystemTools::GetCMakeConfigDirectory()) {
this->userTimingDirv1 = this->userTimingDirv1 =
@@ -60,7 +108,10 @@ void cmInstrumentation::LoadQueries()
this->hasQuery = this->hasQuery || this->hasQuery = this->hasQuery ||
this->ReadJSONQueries(cmStrCat(this->userTimingDirv1, "/query")); this->ReadJSONQueries(cmStrCat(this->userTimingDirv1, "/query"));
} }
}
void cmInstrumentation::CheckCDashVariable()
{
std::string envVal; std::string envVal;
if (cmSystemTools::GetEnv("CTEST_USE_INSTRUMENTATION", envVal) && if (cmSystemTools::GetEnv("CTEST_USE_INSTRUMENTATION", envVal) &&
!cmIsOff(envVal)) { !cmIsOff(envVal)) {
@@ -69,63 +120,23 @@ void cmInstrumentation::LoadQueries()
cmExperimental::Feature::Instrumentation) cmExperimental::Feature::Instrumentation)
.Uuid; .Uuid;
if (envVal == uuid) { if (envVal == uuid) {
std::set<cmInstrumentationQuery::Option> options_ = {
cmInstrumentationQuery::Option::CDashSubmit,
cmInstrumentationQuery::Option::DynamicSystemInformation
};
if (cmSystemTools::GetEnv("CTEST_USE_VERBOSE_INSTRUMENTATION",
envVal) &&
!cmIsOff(envVal)) {
options_.insert(cmInstrumentationQuery::Option::CDashVerbose);
}
for (auto const& option : options_) {
this->AddOption(option);
}
std::set<cmInstrumentationQuery::Hook> hooks_ = {
cmInstrumentationQuery::Hook::PrepareForCDash
};
this->AddHook(cmInstrumentationQuery::Hook::PrepareForCDash); this->AddHook(cmInstrumentationQuery::Hook::PrepareForCDash);
this->AddOption( this->WriteJSONQuery(options_, hooks_, {});
cmInstrumentationQuery::Option::DynamicSystemInformation);
this->cdashDir = cmStrCat(this->timingDirv1, "/cdash");
cmSystemTools::MakeDirectory(this->cdashDir);
cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/configure"));
cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/build"));
cmSystemTools::MakeDirectory(
cmStrCat(this->cdashDir, "/build/commands"));
cmSystemTools::MakeDirectory(
cmStrCat(this->cdashDir, "/build/targets"));
cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/test"));
this->cdashSnippetsMap = { {
"configure",
"configure",
},
{
"generate",
"configure",
},
{
"compile",
"build",
},
{
"link",
"build",
},
{
"custom",
"build",
},
{
"build",
"skip",
},
{
"cmakeBuild",
"build",
},
{
"cmakeInstall",
"build",
},
{
"install",
"build",
},
{
"ctest",
"build",
},
{
"test",
"test",
} };
this->hasQuery = true;
} }
} }
} }
@@ -192,13 +203,9 @@ void cmInstrumentation::WriteJSONQuery(
for (auto const& callback : callbacks_) { for (auto const& callback : callbacks_) {
root["callbacks"].append(cmInstrumentation::GetCommandStr(callback)); root["callbacks"].append(cmInstrumentation::GetCommandStr(callback));
} }
cmsys::Directory d; this->WriteInstrumentationJson(
int n = 0; root, "query/generated",
if (d.Load(cmStrCat(this->timingDirv1, "/query/generated"))) { cmStrCat("query-", this->writtenJsonQueries++, ".json"));
n = (int)d.GetNumberOfFiles() - 2; // Don't count '.' or '..'
}
this->WriteInstrumentationJson(root, "query/generated",
cmStrCat("query-", n, ".json"));
} }
void cmInstrumentation::ClearGeneratedQueries() void cmInstrumentation::ClearGeneratedQueries()
@@ -306,7 +313,7 @@ int cmInstrumentation::CollectTimingData(cmInstrumentationQuery::Hook hook)
} }
// Special case for CDash collation // Special case for CDash collation
if (this->HasHook(cmInstrumentationQuery::Hook::PrepareForCDash)) { if (this->HasOption(cmInstrumentationQuery::Option::CDashSubmit)) {
this->PrepareDataForCDash(directory, index_path); this->PrepareDataForCDash(directory, index_path);
} }
@@ -676,6 +683,13 @@ std::string const& cmInstrumentation::GetCDashDir()
void cmInstrumentation::PrepareDataForCDash(std::string const& data_dir, void cmInstrumentation::PrepareDataForCDash(std::string const& data_dir,
std::string const& index_path) std::string const& index_path)
{ {
cmSystemTools::MakeDirectory(this->cdashDir);
cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/configure"));
cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/build"));
cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/build/commands"));
cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/build/targets"));
cmSystemTools::MakeDirectory(cmStrCat(this->cdashDir, "/test"));
Json::Value root; Json::Value root;
std::string error_msg; std::string error_msg;
cmJSONState parseState = cmJSONState(index_path, &root); cmJSONState parseState = cmJSONState(index_path, &root);

View File

@@ -33,6 +33,7 @@ public:
cmInstrumentation(std::string const& binary_dir, cmInstrumentation(std::string const& binary_dir,
LoadQueriesAfter loadQueries = LoadQueriesAfter::Yes); LoadQueriesAfter loadQueries = LoadQueriesAfter::Yes);
void LoadQueries(); void LoadQueries();
void CheckCDashVariable();
int InstrumentCommand( int InstrumentCommand(
std::string command_type, std::vector<std::string> const& command, std::string command_type, std::vector<std::string> const& command,
std::function<int()> const& callback, std::function<int()> const& callback,
@@ -91,7 +92,7 @@ private:
std::set<cmInstrumentationQuery::Hook> hooks; std::set<cmInstrumentationQuery::Hook> hooks;
std::vector<std::string> callbacks; std::vector<std::string> callbacks;
std::vector<std::string> queryFiles; std::vector<std::string> queryFiles;
std::map<std::string, std::string> cdashSnippetsMap; static std::map<std::string, std::string> cdashSnippetsMap;
Json::Value preTestStats; Json::Value preTestStats;
std::string errorMsg; std::string errorMsg;
bool hasQuery = false; bool hasQuery = false;
@@ -101,4 +102,5 @@ private:
std::unique_ptr<cmsys::SystemInformation> systemInformation; std::unique_ptr<cmsys::SystemInformation> systemInformation;
cmsys::SystemInformation& GetSystemInformation(); cmsys::SystemInformation& GetSystemInformation();
#endif #endif
int writtenJsonQueries = 0;
}; };

View File

@@ -16,7 +16,8 @@
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"
std::vector<std::string> const cmInstrumentationQuery::OptionString{ std::vector<std::string> const cmInstrumentationQuery::OptionString{
"staticSystemInformation", "dynamicSystemInformation" "staticSystemInformation", "dynamicSystemInformation", "cdashSubmit",
"cdashVerbose"
}; };
std::vector<std::string> const cmInstrumentationQuery::HookString{ std::vector<std::string> const cmInstrumentationQuery::HookString{
"postGenerate", "preBuild", "postBuild", "postGenerate", "preBuild", "postBuild",

View File

@@ -15,7 +15,9 @@ public:
enum Option enum Option
{ {
StaticSystemInformation, StaticSystemInformation,
DynamicSystemInformation DynamicSystemInformation,
CDashSubmit,
CDashVerbose
}; };
static std::vector<std::string> const OptionString; static std::vector<std::string> const OptionString;

View File

@@ -2644,6 +2644,7 @@ int cmake::ActualConfigure()
cmStrCat(this->GetHomeOutputDirectory(), "/CMakeFiles"_s), cmStrCat(this->GetHomeOutputDirectory(), "/CMakeFiles"_s),
this->FileAPI->GetConfigureLogVersions()); this->FileAPI->GetConfigureLogVersions());
this->Instrumentation->LoadQueries(); this->Instrumentation->LoadQueries();
this->Instrumentation->CheckCDashVariable();
} }
#endif #endif

View File

@@ -8,6 +8,7 @@
API_VERSION 1 API_VERSION 1
DATA_VERSION 1 DATA_VERSION 1
HOOKS postGenerate HOOKS postGenerate
OPTIONS cdashSubmit cdashVerbose
CALLBACK ${CMAKE_COMMAND} -E echo callback1 CALLBACK ${CMAKE_COMMAND} -E echo callback1
) )
# Query 2 # Query 2

View File

@@ -7,6 +7,9 @@
[ [
"postGenerate" "postGenerate"
], ],
"options" : [], "options" : [
"cdashSubmit",
"cdashVerbose"
],
"version" : 1 "version" : 1
} }

View File

@@ -1,3 +1,12 @@
set(timingDir "${RunCMake_TEST_BINARY_DIR}/.cmake/instrumentation-a37d1069-1972-4901-b9c9-f194aaf2b6e0/v1")
file(READ "${timingDir}/query/generated/query-0.json" jsonData)
string(JSON options GET "${jsonData}" options)
if (options MATCHES cdashVerbose AND NOT ${RunCMake_USE_VERBOSE_INSTRUMENTATION})
set(RunCMake_TEST_FAILED "cdashVerbose option not found in generated query despite environment variable")
elseif (NOT options MATCHES cdashVerbose AND ${RunCMake_USE_VERBOSE_INSTRUMENTATION})
set(RunCMake_TEST_FAILED "cdashVerbose option found in generated query despite environment variable")
endif()
foreach(xml_type Configure Build Test) foreach(xml_type Configure Build Test)
file(GLOB xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/${xml_type}.xml") file(GLOB xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/${xml_type}.xml")
if(xml_file) if(xml_file)
@@ -29,6 +38,12 @@ foreach(xml_type Configure Build Test)
if(NOT xml_content MATCHES "<CmakeBuild") if(NOT xml_content MATCHES "<CmakeBuild")
set(RunCMake_TEST_FAILED "<CmakeBuild> element not found in Build.xml") set(RunCMake_TEST_FAILED "<CmakeBuild> element not found in Build.xml")
endif() endif()
if(NOT RunCMake_USE_VERBOSE_INSTRUMENTATION AND NOT xml_content MATCHES "(truncated)")
set(RunCMake_TEST_FAILED "Commands not truncated despite cdashVerbose option")
endif()
if(verbose AND xml_content MATCHES "(truncated)")
set(RunCMake_TEST_FAILED "Commands truncated despite cdashVerbose option")
endif()
endif() endif()
else() else()
set(RunCMake_TEST_FAILED "${xml_type}.xml not found") set(RunCMake_TEST_FAILED "${xml_type}.xml not found")
@@ -37,7 +52,7 @@ endforeach()
foreach(dir_to_check "configure" "test" "build/targets" "build/commands") foreach(dir_to_check "configure" "test" "build/targets" "build/commands")
file(GLOB leftover_cdash_snippets file(GLOB leftover_cdash_snippets
"${RunCMake_TEST_BINARY_DIR}/.cmake/instrumentation-a37d1069-1972-4901-b9c9-f194aaf2b6e0/v1/cdash/${dir_to_check}/*") "${timingDir}/cdash/${dir_to_check}/*")
if(leftover_cdash_snippets) if(leftover_cdash_snippets)
set(RunCMake_TEST_FAILED "Leftover snippets found in cdash dir: ${leftover_cdash_snippets}") set(RunCMake_TEST_FAILED "Leftover snippets found in cdash dir: ${leftover_cdash_snippets}")
endif() endif()

View File

@@ -1,6 +1,13 @@
include(RunCTest) include(RunCTest)
function(run_InstrumentationInCTestXML USE_INSTRUMENTATION) function(run_InstrumentationInCTestXML CASE_NAME USE_INSTRUMENTATION USE_VERBOSE_INSTRUMENTATION)
if(USE_VERBOSE_INSTRUMENTATION)
set(ENV{CTEST_USE_VERBOSE_INSTRUMENTATION} "1")
set(RunCMake_USE_VERBOSE_INSTRUMENTATION TRUE)
else()
set(ENV{CTEST_USE_VERBOSE_INSTRUMENTATION} "0")
set(RunCMake_USE_VERBOSE_INSTRUMENTATION FALSE)
endif()
if(USE_INSTRUMENTATION) if(USE_INSTRUMENTATION)
set(ENV{CTEST_USE_INSTRUMENTATION} "1") set(ENV{CTEST_USE_INSTRUMENTATION} "1")
set(ENV{CTEST_EXPERIMENTAL_INSTRUMENTATION} "a37d1069-1972-4901-b9c9-f194aaf2b6e0") set(ENV{CTEST_EXPERIMENTAL_INSTRUMENTATION} "a37d1069-1972-4901-b9c9-f194aaf2b6e0")
@@ -18,5 +25,6 @@ function(run_InstrumentationInCTestXML USE_INSTRUMENTATION)
unset(RunCMake_USE_LAUNCHERS) unset(RunCMake_USE_LAUNCHERS)
unset(RunCMake_USE_INSTRUMENTATION) unset(RunCMake_USE_INSTRUMENTATION)
endfunction() endfunction()
run_InstrumentationInCTestXML(ON) run_InstrumentationInCTestXML(InstrumentationInCTestXML ON OFF)
run_InstrumentationInCTestXML(OFF) run_InstrumentationInCTestXML(VerboseInstrumentationInCTestXML ON ON)
run_InstrumentationInCTestXML(NoInstrumentationInCTestXML OFF OFF)