Skip to content

Commit b7bf501

Browse files
committed
tests main() work
1 parent 0fc0c82 commit b7bf501

File tree

2 files changed

+197
-15
lines changed

2 files changed

+197
-15
lines changed

include/mrdox/Corpus.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ struct Corpus
2525
Corpus(Corpus const&) = delete;
2626
Corpus& operator=(Corpus const&) = delete;
2727

28+
std::unique_ptr<tooling::ToolExecutor> executor;
29+
2830
Index Idx;
2931

3032
/** Table of Info keyed on USR.

source/tests/TestMain.cpp

Lines changed: 195 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "Representation.h"
1414
#include <mrdox/Config.hpp>
1515
#include <mrdox/XML.hpp>
16+
#include <clang/tooling/CompilationDatabase.h>
1617
#include <clang/tooling/Tooling.h>
1718
#include <llvm/ADT/StringRef.h>
1819
#include <llvm/Support/Signals.h>
@@ -34,39 +35,220 @@ extern void force_xml_generator_linkage();
3435
namespace clang {
3536
namespace mrdox {
3637

37-
namespace {
38+
namespace fs = llvm::sys::fs;
39+
namespace path = llvm::sys::path;
3840

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)
4199
{
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);
42107
}
43108

44109
//------------------------------------------------
45110

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+
46218
int
47-
do_main(int argc, const char** argv)
219+
testMain(int argc, const char** argv)
48220
{
221+
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
222+
49223
// VFALCO GARBAGE
50224
force_xml_generator_linkage();
51225

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+
}
54240

55241
std::vector<std::string> Args;
56242
for(auto i = 0; i < argc; ++i)
57243
Args.push_back(argv[i]);
58244

59-
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
60-
61245
Config cfg;
62246
if(llvm::Error err = setupContext(cfg, argc, argv))
63247
{
64248
llvm::errs() << "test failure: " << err << "\n";
65249
return EXIT_FAILURE;
66250
}
67251

68-
std::atomic<bool> gotFailure = false;
69-
70252
std::string xml;
71253
for(int i = 1; i < argc; ++i)
72254
{
@@ -152,7 +334,7 @@ do_main(int argc, const char** argv)
152334

153335
if(xml != expectedXml)
154336
{
155-
gotFailure = true;
337+
R.failed = true;
156338
llvm::errs() <<
157339
"Failed: \"" << xmlPath << "\", got\n" <<
158340
xml;
@@ -163,18 +345,16 @@ do_main(int argc, const char** argv)
163345
}
164346
}
165347

166-
if(gotFailure)
348+
if(R.failed)
167349
return EXIT_FAILURE;
168350
return EXIT_SUCCESS;
169351
}
170352

171-
} // (anon)
172-
173353
} // mrdox
174354
} // clang
175355

176356
int
177357
main(int argc, const char** argv)
178358
{
179-
return clang::mrdox::do_main(argc, argv);
359+
return clang::mrdox::testMain(argc, argv);
180360
}

0 commit comments

Comments
 (0)