1 module tests.it.runtime.dub;
2 
3 
4 import tests.it.runtime;
5 import reggae.reggae;
6 
7 
8 @("dub project with no reggaefile ninja")
9 @Tags(["dub", "ninja"])
10 unittest {
11 
12     import std.string: join;
13 
14     with(immutable ReggaeSandbox("dub")) {
15         shouldNotExist("reggaefile.d");
16         writelnUt("\n\nReggae output:\n\n", runReggae("-b", "ninja", "--dflags=-g -debug").lines.join("\n"), "-----\n");
17         shouldExist("reggaefile.d");
18         auto output = ninja.shouldExecuteOk;
19         output.shouldContain("-g -debug");
20 
21         shouldSucceed("atest").shouldEqual(
22             ["Why hello!",
23              "",
24              "I'm immortal!"]
25         );
26 
27         // there's only one UT in main.d which always fails
28         shouldFail("ut");
29     }
30 }
31 
32 @("dub project with no reggaefile tup")
33 @Tags(["dub", "tup"])
34 unittest {
35     with(immutable ReggaeSandbox("dub")) {
36         runReggae("-b", "tup", "--dflags=-g -debug").
37             shouldThrowWithMessage("dub integration not supported with the tup backend");
38     }
39 }
40 
41 @("dub project with no reggaefile and prebuild command")
42 @Tags(["dub", "ninja"])
43 unittest {
44     with(immutable ReggaeSandbox("dub_prebuild")) {
45         runReggae("-b", "ninja", "--dflags=-g -debug");
46         ninja.shouldExecuteOk;
47         shouldSucceed("ut");
48     }
49 }
50 
51 @("dub project with postbuild command")
52 @Tags(["dub", "ninja"])
53 unittest {
54     with(immutable ReggaeSandbox("dub_postbuild")) {
55         runReggae("-b", "ninja", "--dflags=-g -debug");
56         ninja.shouldExecuteOk;
57         shouldExist("foo.txt");
58         shouldSucceed("postbuild");
59     }
60 }
61 
62 
63 @("project with dependencies not on file system already no dub.selections.json")
64 @Tags(["dub", "ninja"])
65 unittest {
66 
67     import std.file: exists, rmdirRecurse;
68     import std.process: environment;
69     import std.path: buildPath;
70 
71     const cerealedDir = buildPath(environment["HOME"], ".dub/packages/cerealed-0.6.8");
72     if(cerealedDir.exists)
73         rmdirRecurse(cerealedDir);
74 
75     with(immutable ReggaeSandbox()) {
76         writeFile("dub.json", `
77         {
78           "name": "depends_on_cerealed",
79           "license": "MIT",
80           "targetType": "executable",
81           "dependencies": { "cerealed": "==0.6.8" }
82         }`);
83         writeFile("source/app.d", "void main() {}");
84 
85         runReggae("-b", "ninja");
86     }
87 }
88 
89 
90 @("simple dub project with no main function but with unit tests")
91 @Tags(["dub", "ninja"])
92 unittest {
93     import std.file: mkdirRecurse;
94     import std.path: buildPath;
95 
96     with(immutable ReggaeSandbox()) {
97         writeFile("dub.json", `
98             {
99               "name": "depends_on_cerealed",
100               "license": "MIT",
101               "targetType": "executable",
102               "dependencies": { "cerealed": "==0.6.8" }
103             }`);
104 
105         writeFile("reggaefile.d", q{
106             import reggae;
107             mixin build!(dubTestTarget!(CompilerFlags("-g -debug")));
108         });
109 
110         mkdirRecurse(buildPath(testPath, "source"));
111         writeFile("source/foo.d", `unittest { assert(false); }`);
112         runReggae("-b", "ninja");
113         ninja.shouldExecuteOk;
114 
115         shouldFail("ut");
116     }
117 }
118 
119 @("issue #23 - reggae/dub build should rebuild if dub.json/sdl change")
120 @Tags(["dub", "make"])
121 unittest {
122 
123     import std.process: execute;
124     import std.path: buildPath;
125 
126     with(immutable ReggaeSandbox("dub")) {
127         runReggae("-b", "make", "--dflags=-g -debug");
128         make(["VERBOSE=1"]).shouldExecuteOk.shouldContain("-g -debug");
129         {
130             const ret = execute(["touch", buildPath(testPath, "dub.json")]);
131             ret.status.shouldEqual(0);
132         }
133         {
134             const ret = execute(["make", "-C", testPath]);
135             // don't assert on the status of ret - it requires rerunning reggae
136             // and that can fail if the reggae binary isn't built yet.
137             // Either way make should run
138             ret.output.shouldNotContain("Nothing to be done");
139         }
140     }
141 }
142 
143 @("reggae/dub build should rebuild if dub.selections.json changes")
144 @Tags(["dub", "make"])
145 unittest {
146 
147     import std.process: execute;
148     import std.path: buildPath;
149 
150     with(immutable ReggaeSandbox("dub")) {
151         runReggae("-b", "make", "--dflags=-g -debug");
152         make(["VERBOSE=1"]).shouldExecuteOk.shouldContain("-g -debug");
153         {
154             const ret = execute(["touch", buildPath(testPath, "dub.selections.json")]);
155             ret.status.shouldEqual(0);
156         }
157         {
158             const ret = execute(["make", "-C", testPath]);
159             ret.output.shouldContain("eggae");
160         }
161     }
162 }
163 
164 @("version from main package is used in dependent packages")
165 @Tags(["dub", "ninja"])
166 unittest {
167     with(immutable ReggaeSandbox()) {
168         writeFile("dub.sdl", `
169             name "foo"
170             versions "lefoo"
171             targetType "executable"
172             dependency "bar" path="bar"
173         `);
174         writeFile("source/app.d", q{
175             void main() {
176                 import bar;
177                 import std.stdio;
178                 writeln(lebar);
179             }
180         });
181         writeFile("bar/dub.sdl", `
182             name "bar"
183         `);
184         writeFile("bar/source/bar.d", q{
185             module bar;
186             version(lefoo)
187                 int lebar() { return 3; }
188             else
189                 int lebar() { return 42; }
190         });
191         runReggae("-b", "ninja");
192         ninja.shouldExecuteOk;
193         shouldSucceed("foo").shouldEqual(
194             [
195                 "3",
196             ]
197         );
198     }
199 }
200 
201 
202 @("sourceLibrary dependency")
203 @Tags(["dub", "ninja"])
204 unittest {
205     with(immutable ReggaeSandbox()) {
206         writeFile("dub.sdl", `
207             name "foo"
208             targetType "executable"
209             dependency "bar" path="bar"
210         `);
211         writeFile("source/app.d", q{
212             void main() {
213                 import bar;
214                 import std.stdio;
215                 writeln(lebar);
216             }
217         });
218         writeFile("bar/dub.sdl", `
219             name "bar"
220             targetType "sourceLibrary"
221         `);
222         writeFile("bar/source/bar.d", q{
223             module bar;
224             int lebar() { return 3; }
225         });
226         runReggae("-b", "ninja");
227         ninja.shouldExecuteOk;
228     }
229 }
230 
231 @("object source files")
232 @Tags(["dub", "ninja"])
233 unittest {
234     with(immutable ReggaeSandbox()) {
235         writeFile("dub.sdl", `
236             name "foo"
237             targetType "executable"
238             dependency "bar" path="bar"
239         `);
240         writeFile("source/app.d", q{
241             extern(C) int lebaz();
242             void main() {
243                 import bar;
244                 import std.stdio;
245                 writeln(lebar);
246                 writeln(lebaz);
247             }
248         });
249         writeFile("bar/dub.sdl", `
250             name "bar"
251             sourceFiles "../baz.o"
252         `);
253         writeFile("bar/source/bar.d", q{
254             module bar;
255             int lebar() { return 3; }
256         });
257         writeFile("baz.d", q{
258             module baz;
259             extern(C) int lebaz() { return 42; }
260         });
261 
262         ["dmd", "-c", "baz.d"].shouldExecuteOk;
263         runReggae("-b", "ninja");
264         ninja.shouldExecuteOk;
265     }
266 }
267 
268 
269 @("dub objs option")
270 @Tags("dub", "ninja")
271 unittest {
272 
273     import std.format;
274 
275     with(immutable ReggaeSandbox()) {
276 
277         writeFile("reggaefile.d", q{
278             import reggae;
279             mixin build!(dubDefaultTarget!());
280         });
281 
282         writeFile("dub.sdl",`
283             name "foo"
284             targetType "executable"
285             dependency "bar" path="bar"
286         `);
287 
288         writeFile("source/app.d", q{
289             import bar;
290             void main() { add(2, 3); }
291         });
292 
293         writeFile("bar/dub.sdl", `
294             name "bar"
295         `);
296 
297         writeFile("bar/source/bar.d", q{
298             module bar;
299             int add(int i, int j) { return i + j; }
300         });
301 
302         runReggae("-b", "ninja", "--dub-objs-dir=" ~ testPath);
303         ninja.shouldExecuteOk;
304 
305         import std.path: buildPath;
306         shouldExist(buildPath(testPath.deabsolutePath,
307                               "bar",
308                               "foo.objs",
309                               "source.o"));
310     }
311 }
312 
313 private string deabsolutePath(in string path) {
314     version(Windows) throw new Exception("not implemented yet");
315     return path[1..$];
316 }