Blame tests/gtest/common/tap.h

Packit 6d2c1b
/*
Packit 6d2c1b
 * The MIT License
Packit 6d2c1b
 *
Packit 6d2c1b
 * Copyright (c) 2011 Bruno P. Kinoshita <http://www.kinoshita.eti.br>
Packit 6d2c1b
 *
Packit 6d2c1b
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit 6d2c1b
 * of this software and associated documentation files (the "Software"), to deal
Packit 6d2c1b
 * in the Software without restriction, including without limitation the rights
Packit 6d2c1b
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Packit 6d2c1b
 * copies of the Software, and to permit persons to whom the Software is
Packit 6d2c1b
 * furnished to do so, subject to the following conditions:
Packit 6d2c1b
 *
Packit 6d2c1b
 * The above copyright notice and this permission notice shall be included in
Packit 6d2c1b
 * all copies or substantial portions of the Software.
Packit 6d2c1b
 *
Packit 6d2c1b
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit 6d2c1b
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit 6d2c1b
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit 6d2c1b
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit 6d2c1b
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Packit 6d2c1b
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Packit 6d2c1b
 * THE SOFTWARE.
Packit 6d2c1b
 *
Packit 6d2c1b
 * @author Bruno P. Kinoshita <http://www.kinoshita.eti.br>
Packit 6d2c1b
 * @since 0.1
Packit 6d2c1b
 */
Packit 6d2c1b
Packit 6d2c1b
#ifndef TAP_H_
Packit 6d2c1b
#define TAP_H_
Packit 6d2c1b
Packit 6d2c1b
#include <list>
Packit 6d2c1b
#include <iostream>
Packit 6d2c1b
#include <map>
Packit 6d2c1b
#include <fstream>
Packit 6d2c1b
#include <string>
Packit 6d2c1b
#include <algorithm>
Packit 6d2c1b
Packit 6d2c1b
namespace tap {
Packit 6d2c1b
Packit 6d2c1b
#ifdef GTEST_TAP_13_DIAGNOSTIC
Packit 6d2c1b
// based on http://stackoverflow.com/a/7724536/831180
Packit 6d2c1b
static std::string replace_all_copy(
Packit 6d2c1b
  std::string const& original,
Packit 6d2c1b
  std::string const& before,
Packit 6d2c1b
  std::string const& after
Packit 6d2c1b
) {
Packit 6d2c1b
  using namespace std;
Packit 6d2c1b
Packit 6d2c1b
  if (before == after) return string(original);
Packit 6d2c1b
Packit 6d2c1b
  string retval;
Packit 6d2c1b
  if (before.length() == after.length()) retval.reserve(original.size());
Packit 6d2c1b
Packit 6d2c1b
  basic_string <char>::const_iterator end = original.end();
Packit 6d2c1b
  basic_string <char>::const_iterator current = original.begin();
Packit 6d2c1b
  basic_string <char>::const_iterator next =
Packit 6d2c1b
    search(current, end, before.begin(), before.end());
Packit 6d2c1b
Packit 6d2c1b
  while ( next != end ) {
Packit 6d2c1b
    retval.append( current, next );
Packit 6d2c1b
    retval.append( after );
Packit 6d2c1b
    current = next + before.size();
Packit 6d2c1b
    next = search(current, end, before.begin(), before.end());
Packit 6d2c1b
  }
Packit 6d2c1b
  retval.append( current, next );
Packit 6d2c1b
  return retval;
Packit 6d2c1b
}
Packit 6d2c1b
#endif
Packit 6d2c1b
Packit 6d2c1b
class TestResult {
Packit 6d2c1b
Packit 6d2c1b
 private:
Packit 6d2c1b
  int number;
Packit 6d2c1b
  std::string status;
Packit 6d2c1b
  std::string name;
Packit 6d2c1b
  std::string comment;
Packit 6d2c1b
  bool skip;
Packit 6d2c1b
Packit 6d2c1b
 public:
Packit 6d2c1b
  std::string getComment() const {
Packit 6d2c1b
    std::stringstream ss;
Packit 6d2c1b
    if (this->skip) {
Packit 6d2c1b
      ss << "# SKIP " << this->comment;
Packit 6d2c1b
    } else if (!this->comment.empty()) {
Packit 6d2c1b
      ss << "# " << this->comment;
Packit 6d2c1b
    }
Packit 6d2c1b
    return ss.str();
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  const std::string& getName() const {
Packit 6d2c1b
    return name;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  int getNumber() const {
Packit 6d2c1b
    return number;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  const std::string& getStatus() const {
Packit 6d2c1b
    return status;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  bool getSkip() const {
Packit 6d2c1b
    return skip;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  void setComment(const std::string& value) {
Packit 6d2c1b
    this->comment = value;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  void setName(const std::string& value) {
Packit 6d2c1b
    this->name = value;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  void setNumber(int value) {
Packit 6d2c1b
    this->number = value;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  void setStatus(const std::string& value) {
Packit 6d2c1b
    this->status = value;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  void setSkip(bool value) {
Packit 6d2c1b
    this->skip = value;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  std::string toString() const {
Packit 6d2c1b
    std::stringstream ss;
Packit 6d2c1b
    ss << this->status << " " << this->number << " " << this->name;
Packit 6d2c1b
#ifdef GTEST_TAP_13_DIAGNOSTIC
Packit 6d2c1b
    std::string comment_text = this->getComment();
Packit 6d2c1b
    if (!comment_text.empty()) {
Packit 6d2c1b
      ss << std::endl
Packit 6d2c1b
       << "# Diagnostic" << std::endl
Packit 6d2c1b
       << "  ---" << std::endl
Packit 6d2c1b
       << "  " << replace_all_copy(this->getComment(), "\n", "\n  ");
Packit 6d2c1b
    }
Packit 6d2c1b
#endif
Packit 6d2c1b
    return ss.str();
Packit 6d2c1b
  }
Packit 6d2c1b
};
Packit 6d2c1b
Packit 6d2c1b
class TestSet {
Packit 6d2c1b
Packit 6d2c1b
 private:
Packit 6d2c1b
  std::list<TestResult> testResults;
Packit 6d2c1b
Packit 6d2c1b
 public:
Packit 6d2c1b
  const std::list<TestResult>& getTestResults() const {
Packit 6d2c1b
    return testResults;
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  void addTestResult(TestResult& testResult) {
Packit 6d2c1b
    testResult.setNumber((this->getNumberOfTests() + 1));
Packit 6d2c1b
    this->testResults.push_back(testResult);
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  int getNumberOfTests() const {
Packit 6d2c1b
    return this->testResults.size();
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  std::string toString() const {
Packit 6d2c1b
    std::stringstream ss;
Packit 6d2c1b
    ss << "1.." << this->getNumberOfTests() << std::endl;
Packit 6d2c1b
    for (std::list<TestResult>::const_iterator ci = this->testResults.begin();
Packit 6d2c1b
	 ci != this->testResults.end(); ++ci) {
Packit 6d2c1b
      TestResult testResult = *ci;
Packit 6d2c1b
      ss << testResult.toString() << std::endl;
Packit 6d2c1b
    }
Packit 6d2c1b
    return ss.str();
Packit 6d2c1b
  }
Packit 6d2c1b
};
Packit 6d2c1b
Packit 6d2c1b
class TapListener: public ::testing::EmptyTestEventListener {
Packit 6d2c1b
Packit 6d2c1b
 private:
Packit 6d2c1b
  std::map<std::string, tap::TestSet> testCaseTestResultMap;
Packit 6d2c1b
Packit 6d2c1b
  void addTapTestResult(const testing::TestInfo& testInfo) {
Packit 6d2c1b
    tap::TestResult tapResult;
Packit 6d2c1b
    tapResult.setName(testInfo.name());
Packit 6d2c1b
    tapResult.setSkip(!testInfo.should_run());
Packit 6d2c1b
Packit 6d2c1b
    const testing::TestResult *testResult = testInfo.result();
Packit 6d2c1b
    int number = testResult->total_part_count();
Packit 6d2c1b
    tapResult.setNumber(number-1);
Packit 6d2c1b
    if (testResult->HasFatalFailure()) {
Packit 6d2c1b
      tapResult.setStatus("Bail out!");
Packit 6d2c1b
    } else if (testResult->Failed()) {
Packit 6d2c1b
      tapResult.setStatus("not ok");
Packit 6d2c1b
      tapResult.setComment(testResult->GetTestPartResult(number-1).summary());
Packit 6d2c1b
    } else {
Packit 6d2c1b
      tapResult.setStatus("ok");
Packit 6d2c1b
    }
Packit 6d2c1b
Packit 6d2c1b
    this->addNewOrUpdate(testInfo.test_case_name(), tapResult);
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  std::string getCommentOrDirective(const std::string& comment, bool skip) {
Packit 6d2c1b
    std::stringstream commentText;
Packit 6d2c1b
Packit 6d2c1b
    if (skip) {
Packit 6d2c1b
      commentText << " # SKIP " << comment;
Packit 6d2c1b
    } else if (!comment.empty()) {
Packit 6d2c1b
      commentText << " # " << comment;
Packit 6d2c1b
    }
Packit 6d2c1b
Packit 6d2c1b
    return commentText.str();
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  void addNewOrUpdate(const std::string& testCaseName, tap::TestResult testResult) {
Packit 6d2c1b
    std::map<std::string, tap::TestSet>::const_iterator ci =
Packit 6d2c1b
      this->testCaseTestResultMap.find(testCaseName);
Packit 6d2c1b
    if (ci != this->testCaseTestResultMap.end()) {
Packit 6d2c1b
      tap::TestSet testSet = ci->second;
Packit 6d2c1b
      testSet.addTestResult(testResult);
Packit 6d2c1b
      this->testCaseTestResultMap[testCaseName] = testSet;
Packit 6d2c1b
    } else {
Packit 6d2c1b
      tap::TestSet testSet;
Packit 6d2c1b
      testSet.addTestResult(testResult);
Packit 6d2c1b
      this->testCaseTestResultMap[testCaseName] = testSet;
Packit 6d2c1b
    }
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
public:
Packit 6d2c1b
  virtual void OnTestEnd(const testing::TestInfo& testInfo) {
Packit 6d2c1b
    //printf("%s %d - %s\n", testInfo.result()->Passed() ? "ok" : "not ok", this->testNumber, testInfo.name());
Packit 6d2c1b
    this->addTapTestResult(testInfo);
Packit 6d2c1b
  }
Packit 6d2c1b
Packit 6d2c1b
  virtual void OnTestProgramEnd(const testing::UnitTest& unit_test) {
Packit 6d2c1b
    //--- Write the count and the word.
Packit 6d2c1b
    (void)unit_test;
Packit 6d2c1b
    std::map<std::string, tap::TestSet>::const_iterator ci;
Packit 6d2c1b
    for (ci = this->testCaseTestResultMap.begin();
Packit 6d2c1b
	 ci != this->testCaseTestResultMap.end(); ++ci) {
Packit 6d2c1b
      const tap::TestSet& testSet = ci->second;
Packit 6d2c1b
#ifdef GTEST_TAP_PRINT_TO_STDOUT
Packit 6d2c1b
      std::cout << "TAP version 13" << std::endl;
Packit 6d2c1b
      std::cout << testSet.toString();
Packit 6d2c1b
#else
Packit 6d2c1b
      std::string ext = ".tap";
Packit 6d2c1b
      std::ofstream tapFile;
Packit 6d2c1b
      tapFile.open((ci->first + ext).c_str());
Packit 6d2c1b
      tapFile << testSet.toString();
Packit 6d2c1b
      tapFile.close();
Packit 6d2c1b
#endif
Packit 6d2c1b
    }
Packit 6d2c1b
  }
Packit 6d2c1b
};
Packit 6d2c1b
Packit 6d2c1b
} // namespace tap
Packit 6d2c1b
Packit 6d2c1b
#endif // TAP_H_