diff options
author | alexv-smirnov <alex@ydb.tech> | 2023-03-16 13:59:59 +0300 |
---|---|---|
committer | alexv-smirnov <alex@ydb.tech> | 2023-03-16 13:59:59 +0300 |
commit | 648fc9d7949c88a6ebaaf110289b8b4536bb9a16 (patch) | |
tree | c46c89a2e46516c986af3e4ecb44d927bbdfcbac /library/cpp/testing/unittest/junit.cpp | |
parent | 4568fe3f6ddb72499ef17f5e0a1e7e2475a9570b (diff) | |
download | ydb-648fc9d7949c88a6ebaaf110289b8b4536bb9a16.tar.gz |
JUnitXML output for unittest
Diffstat (limited to 'library/cpp/testing/unittest/junit.cpp')
-rw-r--r-- | library/cpp/testing/unittest/junit.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/library/cpp/testing/unittest/junit.cpp b/library/cpp/testing/unittest/junit.cpp new file mode 100644 index 00000000000..f5fe84a937c --- /dev/null +++ b/library/cpp/testing/unittest/junit.cpp @@ -0,0 +1,104 @@ +#include "junit.h" + +#include <libxml/xmlwriter.h> +#include <util/system/fs.h> +#include <util/system/file.h> + +namespace NUnitTest { + +#define CHECK_CALL(expr) if ((expr) < 0) { \ + Cerr << "Faield to write to xml" << Endl; \ + return; \ +} + +#define XML_STR(s) ((const xmlChar*)(s)) + +void TJUnitProcessor::Save() { + TString path = FileName; + auto sz = path.size(); + TFile lockFile; + TFile reportFile; + TString lockFileName; + const int MaxReps = 200; +#if defined(_win_) + const char dirSeparator = '\\'; +#else + const char dirSeparator = '/'; +#endif + if ((sz == 0) or (path[sz - 1] == dirSeparator)) { + if (sz > 0) { + NFs::MakeDirectoryRecursive(path); + } + TString reportFileName; + for (int i = 0; i < MaxReps; i++) { + TString suffix = (i > 0) ? ("-" + std::to_string(i)) : ""; + lockFileName = path + ExecName + suffix + ".lock"; + try { + lockFile = TFile(lockFileName, EOpenModeFlag::CreateNew); + } catch (const TFileError&) {} + if (lockFile.IsOpen()) { + // Inside a lock, ensure the .xml file does not exist + reportFileName = path + ExecName + suffix + ".xml"; + try { + reportFile = TFile(reportFileName, EOpenModeFlag::OpenExisting | EOpenModeFlag::RdOnly); + } catch (const TFileError&) { + break; + } + reportFile.Close(); + lockFile.Close(); + NFs::Remove(lockFileName); + } + } + if (!lockFile.IsOpen()) { + Cerr << "Could not find a vacant file name to write report, maximum number of reports: " << MaxReps << Endl; + Y_FAIL("Cannot write report"); + } + path = reportFileName; + } + auto file = xmlNewTextWriterFilename(path.c_str(), 0); + if (!file) { + Cerr << "Failed to open xml file for writing: " << path.c_str() << Endl; + return; + } + + CHECK_CALL(xmlTextWriterStartDocument(file, nullptr, "UTF-8", nullptr)); + CHECK_CALL(xmlTextWriterStartElement(file, XML_STR("testsuites"))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("tests"), XML_STR(ToString(GetTestsCount()).c_str()))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("failures"), XML_STR(ToString(GetFailuresCount()).c_str()))); + + for (const auto& [suiteName, suite] : Suites) { + CHECK_CALL(xmlTextWriterStartElement(file, XML_STR("testsuite"))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("name"), XML_STR(suiteName.c_str()))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("id"), XML_STR(suiteName.c_str()))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("tests"), XML_STR(ToString(suite.GetTestsCount()).c_str()))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("failures"), XML_STR(ToString(suite.GetFailuresCount()).c_str()))); + + for (const auto& [testName, test] : suite.Cases) { + CHECK_CALL(xmlTextWriterStartElement(file, XML_STR("testcase"))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("name"), XML_STR(testName.c_str()))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("id"), XML_STR(testName.c_str()))); + + for (const auto& failure : test.Failures) { + CHECK_CALL(xmlTextWriterStartElement(file, XML_STR("failure"))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("message"), XML_STR(failure.c_str()))); + CHECK_CALL(xmlTextWriterWriteAttribute(file, XML_STR("type"), XML_STR("ERROR"))); + CHECK_CALL(xmlTextWriterEndElement(file)); + } + + CHECK_CALL(xmlTextWriterEndElement(file)); + } + + CHECK_CALL(xmlTextWriterEndElement(file)); + } + + CHECK_CALL(xmlTextWriterEndElement(file)); + CHECK_CALL(xmlTextWriterEndDocument(file)); + xmlFreeTextWriter(file); + + if (lockFile.IsOpen()) { + lockFile.Close(); + NFs::Remove(lockFileName.c_str()); + } +} + +} // namespace NUnitTest |