12
12
13
13
#include < iostream>
14
14
#include < fstream>
15
+ #include < boost/thread/mutex.hpp>
16
+ #include < boost/thread/condition.hpp>
15
17
#include < boost/test/unit_test.hpp>
18
+ #include < boost/test/unit_test_log.hpp>
19
+ #include < boost/test/output/xml_log_formatter.hpp>
16
20
#include < boost/test/test_case_template.hpp>
17
21
#include < pion/logger.hpp>
18
22
31
35
32
36
namespace pion { // begin namespace pion
33
37
namespace test { // begin namespace test
34
-
38
+
39
+ // / thread-safe wrapper for Boost.Tests's XML log formatter
40
+ class safe_xml_log_formatter
41
+ : public boost::unit_test::output::xml_log_formatter
42
+ {
43
+ public:
44
+
45
+ // / default constructor
46
+ safe_xml_log_formatter ()
47
+ : m_entry_in_progress(false )
48
+ {}
49
+
50
+ // / virtual destructor
51
+ virtual ~safe_xml_log_formatter () {}
52
+
53
+ // / wrapper to flush output for xml_log_formatter::log_start
54
+ virtual void log_start (std::ostream& ostr,
55
+ boost::unit_test::counter_t test_cases_amount )
56
+ {
57
+ xml_log_formatter::log_start (ostr, test_cases_amount);
58
+ ostr << std::endl;
59
+ }
60
+
61
+ // / wrapper to flush output for xml_log_formatter::log_finish
62
+ virtual void log_finish (std::ostream& ostr)
63
+ {
64
+ xml_log_formatter::log_finish (ostr);
65
+ ostr << std::endl;
66
+ }
67
+
68
+ // / wrapper to flush output for xml_log_formatter::log_build_info
69
+ virtual void log_build_info (std::ostream& ostr)
70
+ {
71
+ xml_log_formatter::log_build_info (ostr);
72
+ ostr << std::endl;
73
+ }
74
+
75
+ // / wrapper to flush output for xml_log_formatter::test_unit_start
76
+ virtual void test_unit_start (std::ostream& ostr,
77
+ boost::unit_test::test_unit const & tu )
78
+ {
79
+ xml_log_formatter::test_unit_start (ostr, tu);
80
+ ostr << std::endl;
81
+ }
82
+
83
+ // / wrapper to flush output for xml_log_formatter::test_unit_finish
84
+ virtual void test_unit_finish (std::ostream& ostr,
85
+ boost::unit_test::test_unit const & tu,
86
+ unsigned long elapsed )
87
+ {
88
+ xml_log_formatter::test_unit_finish (ostr, tu, elapsed);
89
+ ostr << std::endl;
90
+ }
91
+
92
+ // / wrapper to flush output for xml_log_formatter::test_unit_skipped
93
+ virtual void test_unit_skipped (std::ostream& ostr,
94
+ boost::unit_test::test_unit const & tu )
95
+ {
96
+ xml_log_formatter::test_unit_skipped (ostr, tu);
97
+ ostr << std::endl;
98
+ }
99
+
100
+ // / wrapper to flush output for xml_log_formatter::log_exception
101
+ virtual void log_exception (std::ostream& ostr,
102
+ boost::unit_test::log_checkpoint_data const & d,
103
+ boost::execution_exception const & ex )
104
+ {
105
+ xml_log_formatter::log_exception (ostr, d, ex);
106
+ ostr << std::endl;
107
+ }
108
+
109
+ // / thread-safe wrapper for xml_log_formatter::log_entry_start
110
+ virtual void log_entry_start ( std::ostream& ostr,
111
+ boost::unit_test::log_entry_data const & entry_data,
112
+ log_entry_types let )
113
+ {
114
+ boost::mutex::scoped_lock entry_lock (m_mutex);
115
+ while (m_entry_in_progress) {
116
+ m_entry_complete.wait (entry_lock);
117
+ }
118
+ m_entry_in_progress = true ;
119
+ xml_log_formatter::log_entry_start (ostr, entry_data, let);
120
+ ostr.flush ();
121
+ }
122
+
123
+ // / thread-safe wrapper for xml_log_formatter::log_entry_value
124
+ // / ensures that an entry is in progress
125
+ virtual void log_entry_value ( std::ostream& ostr, boost::unit_test::const_string value )
126
+ {
127
+ boost::mutex::scoped_lock entry_lock (m_mutex);
128
+ if (m_entry_in_progress) {
129
+ xml_log_formatter::log_entry_value (ostr, value);
130
+ ostr.flush ();
131
+ }
132
+ }
133
+
134
+ // / thread-safe wrapper for xml_log_formatter::log_entry_finish
135
+ // / assumes the current thread has control via call to log_entry_start()
136
+ virtual void log_entry_finish ( std::ostream& ostr )
137
+ {
138
+ boost::mutex::scoped_lock entry_lock (m_mutex);
139
+ if (m_entry_in_progress) {
140
+ xml_log_formatter::log_entry_finish (ostr);
141
+ ostr << std::endl;
142
+ m_entry_in_progress = false ;
143
+ m_entry_complete.notify_one ();
144
+ }
145
+ }
146
+
147
+ private:
148
+
149
+ // / true if a log entry is in progress
150
+ volatile bool m_entry_in_progress;
151
+
152
+ // / condition used to signal the completion of a log entry
153
+ boost::condition m_entry_complete;
154
+
155
+ // / mutex used to prevent multiple threads from interleaving entries
156
+ boost::mutex m_mutex;
157
+ };
158
+
35
159
36
160
// / config is intended for use as a global fixture. By including the
37
161
// / following line in one source code file of a unit test project, the constructor will
@@ -45,24 +169,38 @@ namespace test { // begin namespace test
45
169
// argc and argv do not include parameters handled by the boost unit test framework, such as --log_level.
46
170
int argc = boost::unit_test::framework::master_test_suite ().argc ;
47
171
char ** argv = boost::unit_test::framework::master_test_suite ().argv ;
48
-
49
172
bool verbose = false ;
173
+
50
174
if (argc > 1 ) {
51
175
if (argv[1 ][0 ] == ' -' && argv[1 ][1 ] == ' v' ) {
52
176
verbose = true ;
177
+ } else if (strlen (argv[1 ]) > 13 && strncmp (argv[1 ], " --log_output=" , 13 ) == 0 ) {
178
+ const char * const test_log_filename = argv[1 ] + 13 ;
179
+ m_test_log_file.open (test_log_filename);
180
+ if (m_test_log_file.is_open ()) {
181
+ boost::unit_test::unit_test_log.set_stream (m_test_log_file);
182
+ boost::unit_test::unit_test_log.set_formatter (new safe_xml_log_formatter);
183
+ } else {
184
+ std::cerr << " unable to open " << test_log_filename << std::endl;
185
+ }
53
186
}
54
187
}
188
+
55
189
if (verbose) {
56
190
PION_LOG_CONFIG_BASIC;
57
191
} else {
58
192
std::cout << " Use '-v' to enable logging of errors and warnings from pion.\n " ;
59
193
}
194
+
60
195
pion::logger log_ptr = PION_GET_LOGGER (" pion" );
61
196
PION_LOG_SETLEVEL_WARN (log_ptr);
62
197
}
63
198
virtual ~config () {
64
199
std::cout << " global teardown for all pion unit tests\n " ;
65
200
}
201
+
202
+ // / xml log results output stream (needs to be global)
203
+ static std::ofstream m_test_log_file;
66
204
};
67
205
68
206
0 commit comments