13
13
#include " Representation.h"
14
14
#include < mrdox/Config.hpp>
15
15
#include < mrdox/XML.hpp>
16
+ #include < clang/tooling/CompilationDatabase.h>
16
17
#include < clang/tooling/Tooling.h>
17
18
#include < llvm/ADT/StringRef.h>
18
19
#include < llvm/Support/Signals.h>
@@ -34,39 +35,220 @@ extern void force_xml_generator_linkage();
34
35
namespace clang {
35
36
namespace mrdox {
36
37
37
- namespace {
38
+ namespace fs = llvm::sys::fs;
39
+ namespace path = llvm::sys::path;
38
40
39
- void
40
- testDir ()
41
+ // ------------------------------------------------
42
+ //
43
+ // Generally Helpful Utilties
44
+ //
45
+ // ------------------------------------------------
46
+
47
+ /* * Used to check and report errors uniformly.
48
+ */
49
+ struct Reporter
50
+ {
51
+ bool failed = false ;
52
+
53
+ bool
54
+ success (
55
+ llvm::StringRef what,
56
+ std::error_code const & ec)
57
+ {
58
+ if (! ec)
59
+ return true ;
60
+ llvm::errs () <<
61
+ what << " : " << ec.message () << " \n " ;
62
+ failed = true ;
63
+ return false ;
64
+ }
65
+
66
+ bool
67
+ success (
68
+ llvm::StringRef what,
69
+ llvm::Error& err)
70
+ {
71
+ if (! err)
72
+ return true ;
73
+ llvm::errs () <<
74
+ what << " : " << toString (std::move (err)) << " \n " ;
75
+ failed = true ;
76
+ return false ;
77
+ }
78
+ };
79
+
80
+ /* * Return command line arguments as a vector of strings.
81
+ */
82
+ std::vector<std::string>
83
+ makeVectorOfArgs (int argc, const char ** argv)
84
+ {
85
+ std::vector<std::string> result;
86
+ result.reserve (argc);
87
+ for (int i = 0 ; i < argc; ++i)
88
+ result.push_back (argv[i]);
89
+ return result;
90
+ }
91
+
92
+ /* * Return an executor from a vector of arguments.
93
+ */
94
+ llvm::Expected<std::unique_ptr<ToolExecutor>>
95
+ createExecutor (
96
+ std::vector<std::string> const & args,
97
+ llvm::cl::OptionCategory& category,
98
+ char const * overview)
41
99
{
100
+ std::vector<const char *> argv;
101
+ argv.reserve (args.size ());
102
+ for (auto const & arg : args)
103
+ argv.push_back (arg.data ());
104
+ int argc = static_cast <int >(argv.size ());
105
+ return clang::tooling::createExecutorFromCommandLineArgs (
106
+ argc, argv.data (), category, overview);
42
107
}
43
108
44
109
// ------------------------------------------------
45
110
111
+ /* * Compilation database where files come in pairs of C++ and XML.
112
+ */
113
+ class TestCompilationDatabase
114
+ : public clang::tooling::CompilationDatabase
115
+ {
116
+ std::vector<CompileCommand> cc_;
117
+
118
+ public:
119
+ TestCompilationDatabase () = default ;
120
+
121
+ bool
122
+ addDirectory (
123
+ llvm::StringRef path,
124
+ Reporter& R)
125
+ {
126
+ std::error_code ec;
127
+ llvm::SmallString<256 > dir (path);
128
+ path::remove_dots (dir, true );
129
+ fs::directory_iterator const end{};
130
+ fs::directory_iterator iter (dir, ec, false );
131
+ if (! R.success (" addDirectory" , ec))
132
+ return false ;
133
+ while (iter != end)
134
+ {
135
+ if (iter->type () == fs::file_type::directory_file)
136
+ {
137
+ addDirectory (iter->path (), R);
138
+ }
139
+ else if (
140
+ iter->type () == fs::file_type::regular_file &&
141
+ path::extension (iter->path ()).equals_insensitive (" .cpp" ))
142
+ {
143
+ llvm::SmallString<256 > output (iter->path ());
144
+ path::replace_extension (output, " xml" );
145
+ std::vector<std::string> commandLine = {
146
+ " clang" ,
147
+ iter->path ()
148
+ };
149
+ cc_.emplace_back (
150
+ dir,
151
+ iter->path (),
152
+ std::move (commandLine),
153
+ output);
154
+ cc_.back ().Heuristic = " unit test" ;
155
+
156
+ }
157
+ else
158
+ {
159
+ // we don't handle this type
160
+ }
161
+ iter.increment (ec);
162
+ if (! R.success (" increment" , ec))
163
+ return false ;
164
+ }
165
+ return true ;
166
+ }
167
+
168
+ std::vector<CompileCommand>
169
+ getCompileCommands (
170
+ llvm::StringRef FilePath) const override
171
+ {
172
+ std::vector<CompileCommand> result;
173
+ for (auto const & cc : cc_)
174
+ if (FilePath.equals (cc.Filename ))
175
+ result.push_back (cc);
176
+ return result;
177
+ }
178
+
179
+ virtual
180
+ std::vector<std::string>
181
+ getAllFiles () const override
182
+ {
183
+ std::vector<std::string> result;
184
+ result.reserve (cc_.size ());
185
+ for (auto const & cc : cc_)
186
+ result.push_back (cc.Filename );
187
+ return result;
188
+ }
189
+
190
+ std::vector<CompileCommand>
191
+ getAllCompileCommands () const override
192
+ {
193
+ return cc_;
194
+ }
195
+ };
196
+
197
+ // ------------------------------------------------
198
+
199
+ static
200
+ const char * toolOverview =
201
+ R"( Runs tests on input files and checks the results,
202
+
203
+ Example:
204
+ $ mrdox_tests *( DIR | FILE.cpp )
205
+ )" ;
206
+
207
+ static
208
+ llvm::cl::extrahelp
209
+ commonHelp (
210
+ tooling::CommonOptionsParser::HelpMessage);
211
+
212
+ static
213
+ llvm::cl::OptionCategory
214
+ toolCategory (" mrdox_tests options" );
215
+
216
+ // ------------------------------------------------
217
+
46
218
int
47
- do_main (int argc, const char ** argv)
219
+ testMain (int argc, const char ** argv)
48
220
{
221
+ llvm::sys::PrintStackTraceOnErrorSignal (argv[0 ]);
222
+
49
223
// VFALCO GARBAGE
50
224
force_xml_generator_linkage ();
51
225
52
- namespace fs = llvm::sys::fs;
53
- namespace path = llvm::sys::path;
226
+ Reporter R;
227
+
228
+ TestCompilationDatabase db;
229
+ for (int i = 1 ; i < argc; ++i)
230
+ db.addDirectory (argv[i], R);
231
+
232
+ auto args = makeVectorOfArgs (argc, argv);
233
+ args.push_back (" --executor=all-TUs" );
234
+ std::unique_ptr<ToolExecutor> executor;
235
+ if (llvm::Error err = createExecutor (
236
+ args, toolCategory, toolOverview).moveInto (executor))
237
+ {
238
+ return EXIT_FAILURE;
239
+ }
54
240
55
241
std::vector<std::string> Args;
56
242
for (auto i = 0 ; i < argc; ++i)
57
243
Args.push_back (argv[i]);
58
244
59
- llvm::sys::PrintStackTraceOnErrorSignal (argv[0 ]);
60
-
61
245
Config cfg;
62
246
if (llvm::Error err = setupContext (cfg, argc, argv))
63
247
{
64
248
llvm::errs () << " test failure: " << err << " \n " ;
65
249
return EXIT_FAILURE;
66
250
}
67
251
68
- std::atomic<bool > gotFailure = false ;
69
-
70
252
std::string xml;
71
253
for (int i = 1 ; i < argc; ++i)
72
254
{
@@ -152,7 +334,7 @@ do_main(int argc, const char** argv)
152
334
153
335
if (xml != expectedXml)
154
336
{
155
- gotFailure = true ;
337
+ R. failed = true ;
156
338
llvm::errs () <<
157
339
" Failed: \" " << xmlPath << " \" , got\n " <<
158
340
xml;
@@ -163,18 +345,16 @@ do_main(int argc, const char** argv)
163
345
}
164
346
}
165
347
166
- if (gotFailure )
348
+ if (R. failed )
167
349
return EXIT_FAILURE;
168
350
return EXIT_SUCCESS;
169
351
}
170
352
171
- } // (anon)
172
-
173
353
} // mrdox
174
354
} // clang
175
355
176
356
int
177
357
main (int argc, const char ** argv)
178
358
{
179
- return clang::mrdox::do_main (argc, argv);
359
+ return clang::mrdox::testMain (argc, argv);
180
360
}
0 commit comments