1 module tests.ut.backend.binary;
2 
3 import reggae;
4 import unit_threaded;
5 import tests.utils;
6 
7 void testTargetSelection() {
8 
9     bool fooCalled;
10     bool barCalled;
11     void resetCalls() { fooCalled = false; barCalled = false;}
12 
13     auto foo = Target("foo", (in string[] i, in string[] o) { fooCalled = true; }, Target("foo.d"));
14     auto bar = Target("bar", (in string[] i, in string[] o) { barCalled = true; }, Target("bar.d"));
15     auto binary = Binary(Build(foo, bar), getOptions(["reggae", "--export"]));
16 
17     {
18         scope(exit) resetCalls;
19         binary.run(["prog", "--norerun"]);
20         fooCalled.shouldBeTrue;
21         barCalled.shouldBeTrue;
22     }
23 
24     {
25         scope(exit) resetCalls;
26         binary.run(["prog", "--norerun", "foo", "bar"]);
27         fooCalled.shouldBeTrue;
28         barCalled.shouldBeTrue;
29     }
30 
31     {
32         scope(exit) resetCalls;
33         binary.run(["prog", "--norerun", "foo"]);
34         fooCalled.shouldBeTrue;
35         barCalled.shouldBeFalse;
36     }
37 
38     {
39         scope(exit) resetCalls;
40         binary.run(["prog", "--norerun", "bar"]);
41         fooCalled.shouldBeFalse;
42         barCalled.shouldBeTrue;
43     }
44 
45     {
46         scope(exit) resetCalls;
47         binary.run(["prog", "--norerun", "nonexistent"]).shouldThrow;
48         fooCalled.shouldBeFalse;
49         barCalled.shouldBeFalse;
50     }
51 }
52 
53 void testTopLevelTargets() {
54     auto foo = Target("foo", "", Target("foo.d"));
55     auto bar = Target("bar", "", Target("bar.d"));
56     auto binary = Binary(Build(foo, bar), Options());
57     binary.topLevelTargets(["foo"]).shouldEqual([foo]);
58     binary.topLevelTargets(["bar"]).shouldEqual([bar]);
59     binary.topLevelTargets([]).shouldEqual([foo, bar]);
60     binary.topLevelTargets(["oops"]).shouldEqual([]);
61 }
62 
63 
64 private Build binaryBuild() {
65     mixin build!(Target("app", "dmd -of$out $in", [Target("foo.o"), Target("bar.o") ]),
66                  optional(Target.phony(`opt`, `echo Optional!`)));
67     return buildFunc();
68 }
69 
70 @("Listing targets") unittest {
71     import std.stdio: stdout, File;
72 
73     auto file = FakeFile();
74     auto binary = Binary(binaryBuild, getOptions(["./reggae", "-b", "binary"]), file);
75     binary.run(["./build", "--norerun", "-l"]);
76 
77     file.lines.shouldEqual(
78         ["List of available top-level targets:",
79          "- app",
80          "- opt (optional)"]);
81 }
82 
83 
84 @("Unknown target") unittest {
85     import std.stdio: stdout, File;
86 
87     auto binary = Binary(binaryBuild, getOptions(["./reggae", "-b", "binary"]));
88     binary.run(["./build", "--norerun", "oops"]).
89         shouldThrowWithMessage("Unknown target(s) 'oops'");
90 }
91 
92 @("Unknown targets") unittest {
93     import std.stdio: stdout, File;
94 
95     auto binary = Binary(binaryBuild, getOptions(["./reggae", "-b", "binary"]));
96     binary.run(["./build", "--norerun", "oops", "woopsie"]).
97         shouldThrowWithMessage("Unknown target(s) 'oops' 'woopsie'");
98 }
99 
100 
101 @("Non-phony target with no dependencies gets built if output doesn't exist")
102 unittest {
103     bool ran;
104     auto build = Build(Target("foo.txt",
105                               (in string[], in string[]) { ran = true; }));
106     auto binary = Binary(build, getOptions(["reggae", "-b", "binary"]));
107     binary.run(["./build", "--norerun"]);
108     ran.shouldBeTrue;
109 }