| 3665 | } |
| 3666 | |
| 3667 | bool cmCTest::ConvertInstrumentationJSONFileToXML(std::string const& fpath, |
| 3668 | cmXMLWriter& xml) |
| 3669 | { |
| 3670 | bool verboseCommands = this->GetInstrumentation().HasOption( |
| 3671 | cmInstrumentationQuery::Option::CDashVerbose); |
| 3672 | Json::Value root; |
| 3673 | this->Impl->parseState = cmJSONState(fpath, &root); |
| 3674 | if (!this->Impl->parseState.errors.empty()) { |
| 3675 | cmCTestLog(this, ERROR_MESSAGE, |
| 3676 | this->Impl->parseState.GetErrorMessage(true) << std::endl); |
| 3677 | return false; |
| 3678 | } |
| 3679 | |
| 3680 | if (root.type() != Json::objectValue) { |
| 3681 | cmCTestLog(this, ERROR_MESSAGE, |
| 3682 | "Expected object, found " << root.type() << " for " |
| 3683 | << root.asString() << std::endl); |
| 3684 | return false; |
| 3685 | } |
| 3686 | |
| 3687 | std::vector<std::string> required_members = { |
| 3688 | "command", |
| 3689 | "role", |
| 3690 | "dynamicSystemInformation", |
| 3691 | }; |
| 3692 | for (std::string const& required_member : required_members) { |
| 3693 | if (!root.isMember(required_member)) { |
| 3694 | cmCTestLog(this, ERROR_MESSAGE, |
| 3695 | fpath << " is missing the '" << required_member << "' key" |
| 3696 | << std::endl); |
| 3697 | return false; |
| 3698 | } |
| 3699 | } |
| 3700 | |
| 3701 | // Do not record command-level data for Test.xml files because |
| 3702 | // it is redundant with information actually captured by CTest. |
| 3703 | bool generating_test_xml = root["role"] == "test"; |
| 3704 | if (!generating_test_xml) { |
| 3705 | std::string element_name = root["role"].asString(); |
| 3706 | element_name[0] = static_cast<char>(cmsysString_toupper(element_name[0])); |
| 3707 | xml.StartElement(element_name); |
| 3708 | std::vector<std::string> keys = root.getMemberNames(); |
| 3709 | for (auto const& key : keys) { |
| 3710 | auto key_type = root[key].type(); |
| 3711 | if (key_type == Json::objectValue || key_type == Json::arrayValue) { |
| 3712 | continue; |
| 3713 | } |
| 3714 | if (key == "role" || key == "target" || key == "targetType" || |
| 3715 | key == "targetLabels") { |
| 3716 | continue; |
| 3717 | } |
| 3718 | // Truncate the full command line if verbose instrumentation |
| 3719 | // was not requested. |
| 3720 | if (key == "command" && !verboseCommands) { |
| 3721 | std::string command_str = root[key].asString(); |
| 3722 | std::string truncated = command_str.substr(0, command_str.find(' ')); |
| 3723 | if (command_str != truncated) { |
| 3724 | truncated = cmStrCat(truncated, " (truncated)"); |
no test coverage detected