1 #!/usr/bin/rdmd
2 
3 module unit_threaded.finder;
4 
5 /**
6  * Implements a program to search a list of directories
7  * for all .d files, then writes and executes a D program
8  * to run all tests contained in those files
9  */
10 
11 import std.stdio;
12 import std.file;
13 import std.exception;
14 import std.array;
15 import std.algorithm;
16 import std.path;
17 import std.conv;
18 import std.process;
19 
20 
21 /**
22  * args is a filename and a list of directories to search in
23  * the filename is the 1st element, the others are directories.
24  */
25 int main(string[] args) {
26     enforce(args.length >= 2, "Usage: finder.d <filename> <dir>...");
27     const fileName = args[1];
28     const dirs = args[2..$];
29     writeln("Finding all test cases in ", dirs);
30 
31     auto modules = findModuleNames(dirs);
32     auto file = writeFile(fileName, modules, dirs);
33     printFile(file);
34 
35     auto rdmdArgs = getRdmdArgs(fileName, dirs);
36     writeln("Executing rdmd like this: ", join(rdmdArgs, ", "));
37     auto rdmd = execute(rdmdArgs);
38 
39     writeln(rdmd.output);
40     return rdmd.status;
41 }
42 
43 
44 auto findModuleEntries(in string[] dirs) {
45     DirEntry[] modules;
46     foreach(dir; dirs) {
47         enforce(isDir(dir), dir ~ " is not a directory name");
48         modules ~= array(dirEntries(dir, "*.d", SpanMode.depth));
49     }
50     return modules;
51 }
52 
53 auto findModuleNames(in string[] dirs) {
54     //cut off extension
55     return array(map!(a => replace(a.name[0 .. $-2], dirSeparator, "."))(findModuleEntries(dirs)));
56 }
57 
58 private auto writeFile(in string fileName, string[] modules, in string[] dirs) {
59     auto file = File(fileName, "w");
60     file.writeln("import unit_threaded.runner;");
61     file.writeln("import std.stdio;");
62     file.writeln("");
63     file.writeln("int main(string[] args) {");
64     file.writeln(`    writeln("\nAutomatically generated file");`);
65     file.writeln("    writeln(`Running unit tests from dirs " ~ to!string(dirs) ~ "\n`);");
66     file.writeln("    return runTests!(" ~ join(map!(a => `"` ~ a ~ `"`)(modules), ", ") ~ ")(args);");
67     file.writeln("}");
68     file.close();
69 
70     return File(fileName, "r");
71 }
72 
73 private void printFile(File file) {
74     writeln("Executing this code:\n");
75     foreach(line; file.byLine()) {
76         writeln(line);
77     }
78     writeln();
79     file.rewind();
80 }
81 
82 private auto getRdmdArgs(in string fileName, in string[] dirs) {
83     return [ "rdmd" ] ~ join(map!(a => "-I" ~ a)(dirs), ", ") ~ fileName;
84 }