NCBI C++ ToolKit
teamcity_boost.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* Copyright 2011 JetBrains s.r.o.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * $Revision: 86899 $
16 */
17 
18 #include <sstream>
19 
20 #include <boost/test/results_collector.hpp>
21 #include <boost/test/utils/basic_cstring/io.hpp>
22 #include <boost/test/unit_test_log.hpp>
23 #include <boost/test/execution_monitor.hpp>
24 #include <boost/test/unit_test_log_formatter.hpp>
25 #include <boost/test/unit_test.hpp>
26 
27 // In 1.59.0, they changed the name of this enum value, so we have to this hacky thing...
28 #include <boost/version.hpp>
29 #if BOOST_VERSION >= 105900
30  #define TUT_CASE_IDENTIFIER boost::unit_test::TUT_CASE
31  #define CURRENT_TEST_NAME boost::unit_test_framework::framework::current_test_case().full_name()
32 #else
33  #define TUT_CASE_IDENTIFIER boost::unit_test::tut_case
34  #define CURRENT_TEST_NAME boost::unit_test_framework::framework::current_test_case().p_name
35 #endif
36 
38 
39 namespace jetbrains { namespace teamcity {
40 const std::string ASSERT_CTX = "Assertion occurred in a following context:";
41 const std::string FAILURE_CTX = "Failure occurred in a following context:";
42 
43 // Custom formatter for TeamCity messages
44 class TeamcityBoostLogFormatter: public boost::unit_test::unit_test_log_formatter {
49 
50 public:
51  TeamcityBoostLogFormatter(const std::string &_flowId);
53 
55 
56  virtual void log_start(std::ostream&, boost::unit_test::counter_t test_cases_amount);
57  virtual void log_finish(std::ostream&);
58 #if BOOST_VERSION >= 107000
59  virtual void log_build_info(std::ostream&, bool = true);
60 #else
61  virtual void log_build_info(std::ostream&);
62 #endif
63 
64  virtual void test_unit_start(std::ostream&, boost::unit_test::test_unit const& tu);
65  virtual void test_unit_finish(std::ostream&,
66  boost::unit_test::test_unit const& tu,
67  unsigned long elapsed);
68  virtual void test_unit_skipped(std::ostream&, boost::unit_test::test_unit const& tu);
69  virtual void test_unit_skipped(std::ostream&,
70  boost::unit_test::test_unit const& tu,
71  boost::unit_test::const_string reason);
72 
73  virtual void log_exception(std::ostream&,
74  boost::unit_test::log_checkpoint_data const&,
75  boost::unit_test::const_string explanation);
76  virtual void log_exception_start(std::ostream&,
77  boost::unit_test::log_checkpoint_data const&,
78  const boost::execution_exception&);
79  virtual void log_exception_finish(std::ostream&);
80 
81  virtual void log_entry_start(std::ostream & out,
82  boost::unit_test::log_entry_data const & entry_data,
83  log_entry_types let);
84  virtual void log_entry_value(std::ostream&, boost::unit_test::const_string value);
85  virtual void log_entry_finish(std::ostream&);
86 
87  virtual void entry_context_start(std::ostream&, boost::unit_test::log_level);
88  virtual void log_entry_context(std::ostream&, boost::unit_test::const_string);
89  virtual void entry_context_finish(std::ostream&);
90 
91 #if BOOST_VERSION >= 106500
92  // Since v1.65.0 the log level is passed to the formatters for the contexts
93  // See boostorg/test.git:fcb302b66ea09c25f0682588d22fbfdf59eac0f7
94  void log_entry_context(std::ostream& os, boost::unit_test::log_level, boost::unit_test::const_string ctx) {
96  }
97  void entry_context_finish(std::ostream& os, boost::unit_test::log_level) {
99  }
100 #endif
101 };
102 
103 // Fake fixture to register formatter
106  if (underTeamcity()) {
107  boost::unit_test::unit_test_log.set_formatter(new TeamcityBoostLogFormatter());
108  boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::log_test_units);
109  }
110  }
111 };
112 
114 
115 // Dummy method used to keep object file in case of static library linking
116 // See README.md and https://github.com/JetBrains/teamcity-cpp/pull/19
118 
119 // Formatter implementation
120 static std::string toString(boost::unit_test::const_string bstr) {
121  std::stringstream ss;
122 
123  ss << bstr;
124 
125  return ss.str();
126 }
127 
129 : flowId(_flowId)
130 {}
131 
133 : flowId(getFlowIdFromEnvironment())
134 {}
135 
136 void TeamcityBoostLogFormatter::log_start(std::ostream &/*out*/, boost::unit_test::counter_t /*test_cases_amount*/)
137 {}
138 
139 void TeamcityBoostLogFormatter::log_finish(std::ostream &/*out*/)
140 {}
141 
142 #if BOOST_VERSION >= 107000
143 void TeamcityBoostLogFormatter::log_build_info(std::ostream &/*out*/,
144  bool /*log_build_info*/)
145 {}
146 #else
147 void TeamcityBoostLogFormatter::log_build_info(std::ostream &/*out*/)
148 {}
149 #endif
150 
151 void TeamcityBoostLogFormatter::test_unit_start(std::ostream &out, boost::unit_test::test_unit const& tu) {
153 
154  if (tu.p_type == TUT_CASE_IDENTIFIER) {
155  messages.testStarted(tu.p_name, flowId);
156  } else {
157  messages.suiteStarted(tu.p_name, flowId);
158  }
159 
160  currentDetails.clear();
161 }
162 
163 void TeamcityBoostLogFormatter::test_unit_finish(std::ostream &out, boost::unit_test::test_unit const& tu, unsigned long elapsed) {
165 
166  boost::unit_test::test_results const& tr = boost::unit_test::results_collector.results(tu.p_id);
167  if (tu.p_type == TUT_CASE_IDENTIFIER) {
168  if(!tr.passed()) {
169  if(tr.p_skipped) {
170  messages.testIgnored(tu.p_name, "ignored", flowId);
171  } else if (tr.p_aborted) {
172  messages.testFailed(tu.p_name, "aborted", currentDetails, flowId);
173  } else {
174  messages.testFailed(tu.p_name, "failed", currentDetails, flowId);
175  }
176  }
177 
178  messages.testFinished(tu.p_name, int(elapsed / 1000), flowId);
179  } else {
180  messages.suiteFinished(tu.p_name, flowId);
181  }
182 }
183 
184 void TeamcityBoostLogFormatter::test_unit_skipped(std::ostream &/*out*/, boost::unit_test::test_unit const& /*tu*/)
185 {}
186 
187 void TeamcityBoostLogFormatter::test_unit_skipped(std::ostream &out, boost::unit_test::test_unit const& tu, boost::unit_test::const_string reason)
188 {
189  messages.testIgnored(tu.p_name, toString(reason), flowId);
190 }
191 
192 void TeamcityBoostLogFormatter::log_exception(std::ostream &out, boost::unit_test::log_checkpoint_data const &, boost::unit_test::const_string explanation) {
193  std::string what = toString(explanation);
194 
195  out << what << std::endl;
196  currentDetails += what + "\n";
197 }
198 
199 void TeamcityBoostLogFormatter::log_exception_start(std::ostream &out, boost::unit_test::log_checkpoint_data const &data, const boost::execution_exception& excpt) {
200  log_exception(out, data, excpt.what());
201 }
202 
204 
205 
206 void TeamcityBoostLogFormatter::log_entry_start(std::ostream & out, boost::unit_test::log_entry_data const & entry_data, log_entry_types /*let*/)
207 {
208  std::stringstream ss(std::ios_base::out);
209 
210  out << entry_data.m_file_name << "(" << entry_data.m_line_num << "): ";
211  ss << entry_data.m_file_name << "(" << entry_data.m_line_num << "): ";
212 
213  currentDetails += ss.str();
214 }
215 
216 void TeamcityBoostLogFormatter::log_entry_value(std::ostream &out, boost::unit_test::const_string value) {
217  out << value;
219 }
220 
222  out << std::endl;
223  currentDetails += "\n";
224 }
225 
226 void TeamcityBoostLogFormatter::entry_context_start(std::ostream &out, boost::unit_test::log_level l) {
227  const std::string& initial_msg = (l == boost::unit_test::log_successful_tests ? ASSERT_CTX : FAILURE_CTX);
228  out << initial_msg;
229  currentContextDetails = initial_msg;
230 }
231 
232 void TeamcityBoostLogFormatter::log_entry_context(std::ostream &out, boost::unit_test::const_string ctx) {
233  out << "\n " << ctx;
234  currentContextDetails += "\n " + toString(ctx);
235 }
236 
238  out.flush();
240 }
241 
242 }} // namespace teamcity, jetbrains
virtual void log_entry_context(std::ostream &, boost::unit_test::const_string)
virtual void entry_context_finish(std::ostream &)
virtual void log_exception_start(std::ostream &, boost::unit_test::log_checkpoint_data const &, const boost::execution_exception &)
virtual void test_unit_finish(std::ostream &, boost::unit_test::test_unit const &tu, unsigned long elapsed)
virtual void test_unit_skipped(std::ostream &, boost::unit_test::test_unit const &tu)
virtual void entry_context_start(std::ostream &, boost::unit_test::log_level)
virtual void log_entry_value(std::ostream &, boost::unit_test::const_string value)
virtual void log_exception_finish(std::ostream &)
virtual void log_start(std::ostream &, boost::unit_test::counter_t test_cases_amount)
virtual void log_entry_start(std::ostream &out, boost::unit_test::log_entry_data const &entry_data, log_entry_types let)
virtual void log_exception(std::ostream &, boost::unit_test::log_checkpoint_data const &, boost::unit_test::const_string explanation)
virtual void test_unit_start(std::ostream &, boost::unit_test::test_unit const &tu)
void testFailed(const std::string &name, const std::string &message, const std::string &details, const std::string &flowid=std::string())
void suiteStarted(const std::string &name, const std::string &flowid=std::string())
void testOutput(const std::string &name, const std::string &output, const std::string &flowid, bool isStdErr=StdOut)
void testFinished(const std::string &name, int durationMs=-1, const std::string &flowid=std::string())
void suiteFinished(const std::string &name, const std::string &flowid=std::string())
void testIgnored(const std::string &name, const std::string &message, const std::string &flowid=std::string())
void testStarted(const std::string &name, const std::string &flowid=std::string(), bool captureStandardOutput=false)
char value[7]
Definition: config.c:431
CS_CONTEXT * ctx
Definition: t0006.c:12
std::ofstream out("events_result.xml")
main entry point for tests
string
Definition: cgiapp.hpp:687
std::string getFlowIdFromEnvironment()
BOOST_GLOBAL_FIXTURE(TeamcityFormatterRegistrar)
static std::string toString(boost::unit_test::const_string bstr)
const std::string ASSERT_CTX
const std::string FAILURE_CTX
#define CURRENT_TEST_NAME
#define TUT_CASE_IDENTIFIER
Modified on Fri Dec 08 08:19:01 2023 by modify_doxy.py rev. 669887