1 // Integration tests for the binary backend
2 module tests.it.backend.binary;
3 
4 import reggae;
5 import unit_threaded;
6 import std.file;
7 import std..string;
8 
9 
10 enum origFileName = "original.txt";
11 enum copyFileName = "copy.txt";
12 
13 
14 private Build binaryBuild() {
15     version(Windows)
16         enum cmd = `copy $in $out`;
17     else
18         enum cmd = `cp $in $out`;
19 
20     mixin build!(Target(copyFileName, cmd, Target(origFileName)),
21                  optional(Target.phony(`opt`, `echo Optional!`)));
22 
23     return buildFunc();
24 }
25 
26 private void writeOrigFile() {
27     import std.stdio: File;
28     auto file = File(origFileName, "w");
29     file.writeln("See the little goblin");
30 }
31 
32 private struct FakeFile {
33     string[] lines;
34     void writeln(T...)(T args) {
35         import std.conv;
36         lines ~= text(args);
37     }
38 }
39 
40 
41 @("Do nothing after build") unittest {
42     scope(exit) {
43         remove(copyFileName);
44         remove(origFileName);
45     }
46 
47     writeOrigFile;
48 
49     auto file = FakeFile();
50     auto binary = Binary(binaryBuild, getOptions(["./reggae", "-b", "binary"]), file);
51     auto args = ["./build", "--norerun"];
52     binary.run(args);
53 
54     copyFileName.exists.shouldBeTrue;
55 
56     file.lines = [];
57     binary.run(args);
58     file.lines.shouldEqual(["[build] Nothing to do"]);
59 }
60 
61 
62 version(Windows) {}
63 else {
64     @("Targets should only be built once") unittest {
65         import std.process;
66         import std.stdio: File;
67         import std.range;
68         import std.algorithm: map;
69         import std.conv: to;
70         import std..string: splitLines, stripRight;
71 
72         enum fooSrcName = "foo.txt";
73         enum barSrcName = "bar.txt";
74 
75         scope(exit) {
76             foreach(name; [fooSrcName, barSrcName, "foo", "bar"])
77                 remove(name);
78             executeShell("rm -rf objs");
79         }
80 
81         {
82             // create the src files so the rule fires
83             auto fooSrc = File(fooSrcName, "w");
84             auto barSrc = File(barSrcName, "w");
85         }
86 
87         auto foo = Target("$project/foo", "echo foo >> $out", [], [Target(fooSrcName)]);
88         auto bar = Target("$project/bar", "echo bar >> $out", [], [Target(barSrcName)]);
89         auto mids = 10.iota
90             .map!(a => Target.phony("$project/" ~a.to!string, "echo " ~ a.to!string, [foo, bar]))
91             .array
92             ;
93         auto top = Target.phony("top", "echo top", mids);
94 
95         auto binary = Binary(Build(top), getOptions(["reggae", "--export", "-b", "binary"]));
96         binary.run(["./build"]);
97 
98         // only one line -> rule only called once
99         readText("foo").splitLines.map!stripRight.shouldEqual(["foo"]);
100         readText("bar").splitLines.map!stripRight.shouldEqual(["bar"]);
101     }
102 }
103 
104 @("List of targets") unittest {
105     auto file = FakeFile();
106     auto binary = Binary(binaryBuild, getOptions(["reggae", "-b", "binary"]), file);
107     binary.run(["./build", "-l"]);
108     file.lines.shouldEqual(
109         ["List of available top-level targets:",
110          "- copy.txt",
111          "- opt (optional)"]);
112 }
113 
114 @("List of targets with $project in the name") unittest {
115     import reggae.path: buildPath;
116 
117     version(Windows)
118         enum cmd = `copy $in $out`;
119     else
120         enum cmd = `cp $in $out`;
121 
122     auto build = Build(optional(Target(buildPath("$project/../druntime", copyFileName), cmd, Target(origFileName))),
123                        Target.phony(`opt`, `echo Optional!`));
124     auto file = FakeFile();
125     auto binary = Binary(build, getOptions(["reggae", "-b", "binary"]), file);
126     binary.run(["./build", "-l"]);
127     file.lines.shouldEqual(
128         [
129             "List of available top-level targets:",
130             "- opt",
131             "- " ~ buildPath(getcwd(), "../druntime/copy.txt") ~ " (optional)",
132         ]
133     );
134 }