1 module driver.dsunit;
2 
3 import source.context;
4 
5 immutable string[2] ResultStr = ["FAIL", "PASS"];
6 
7 int main(string[] args) {
8 	auto context = new Context();
9 
10 	import std.getopt, source.exception;
11 	try {
12 		return context.run(args);
13 	} catch (GetOptException ex) {
14 		import std.stdio;
15 		writefln("%s", ex.msg);
16 		writeln("Please use -h to get a list of valid options.");
17 		return 1;
18 	} catch (CompileException e) {
19 		import util.terminal;
20 		outputCaretDiagnostics(e.getFullLocation(context), e.msg);
21 
22 		// Rethrow in debug, so we have the stack trace.
23 		debug {
24 			throw e;
25 		} else {
26 			return 1;
27 		}
28 	}
29 
30 	// This is unreachable, but dmd can't figure this out.
31 	assert(0);
32 }
33 
34 int run(Context context, string[] args) {
35 	import sdc.config;
36 	Config conf;
37 
38 	import config.build;
39 	conf.buildGlobalConfig("sdconfig", context);
40 
41 	conf.enableUnittest = true;
42 
43 	string[] includePaths, linkerPaths;
44 
45 	import std.getopt;
46 	auto help_info = getopt(
47 		// sdfmt off
48 		args, std.getopt.config.caseSensitive,
49 		"I",         "Include path",        &includePaths,
50 		"L",         "Library path",        &linkerPaths,
51 		"O",         "Optimization level",  &conf.optLevel,
52 		// sdfmt on
53 	);
54 
55 	if (help_info.helpWanted || args.length == 1) {
56 		import std.stdio;
57 		writeln("The Snazzy D Compiler - Unit test JIT");
58 		writeln("Usage: sdunit [options] file.d");
59 		writeln("Options:");
60 
61 		foreach (option; help_info.options) {
62 			writefln("  %-16s %s",
63 			         // bug : optShort is empty if there is no long version
64 			         option.optShort.length
65 				         ? option.optShort
66 				         : (option.optLong.length == 3)
67 					         ? option.optLong[1 .. $]
68 					         : option.optLong,
69 			         option.help);
70 		}
71 
72 		return 0;
73 	}
74 
75 	conf.includePaths = includePaths ~ conf.includePaths;
76 	conf.linkerPaths = linkerPaths ~ conf.linkerPaths;
77 
78 	auto files = args[1 .. $];
79 
80 	// Cannot call the variable "sdc" or DMD complains about name clash
81 	// with the sdc package from the import.
82 	import sdc.sdc;
83 	auto c = new SDC(context, files[0], conf);
84 
85 	foreach (file; files) {
86 		c.compile(file);
87 	}
88 
89 	import d.ir.symbol;
90 	Module m = null;
91 
92 	bool returnCode = 0;
93 	auto results = c.runUnittests();
94 	if (results.length == 0) {
95 		import std.stdio;
96 		writeln("No test to run");
97 		return 0;
98 	}
99 
100 	import std.stdio;
101 	write("Test results:");
102 
103 	foreach (r; results) {
104 		if (!r.pass) {
105 			returnCode = 1;
106 		}
107 
108 		auto testModule = r.test.getModule();
109 		if (m != testModule) {
110 			m = testModule;
111 
112 			import source.context;
113 			static void printModule(P)(Context c, P p) {
114 				if (p.parent is null) {
115 					import std.stdio;
116 					write("\nModule ", p.toString(c));
117 					return;
118 				}
119 
120 				printModule(c, p.parent);
121 
122 				import std.stdio;
123 				write(".", p.toString(c));
124 
125 				static if (is(P : Module)) {
126 					writeln(":");
127 				}
128 			}
129 
130 			printModule(c.context, m);
131 		}
132 
133 		auto name = r.test.name.toString(c.context);
134 
135 		import std.stdio;
136 		writefln("\t%-24s %s", name, ResultStr[r.pass]);
137 	}
138 
139 	return returnCode;
140 }