1 module tests.it.runtime.dub;
2 
3 
4 import tests.it.runtime;
5 import reggae.reggae;
6 import reggae.path: deabsolutePath;
7 import std.path: buildPath;
8 
9 
10 @("dub project with no reggaefile ninja")
11 @Tags(["dub", "ninja"])
12 unittest {
13 
14     import std.string: join;
15 
16     with(immutable ReggaeSandbox("dub")) {
17         shouldNotExist("reggaefile.d");
18         writelnUt("\n\nReggae output:\n\n", runReggae("-b", "ninja", "--dflags=-g -debug").lines.join("\n"), "-----\n");
19         shouldExist("reggaefile.d");
20         auto output = ninja.shouldExecuteOk;
21         output.shouldContain("-g -debug");
22 
23         shouldSucceed("atest").shouldEqual(
24             ["Why hello!",
25              "",
26              "I'm immortal!"]
27         );
28 
29         // there's only one UT in main.d which always fails
30         shouldFail("ut");
31     }
32 }
33 
34 @("dub project with no reggaefile tup")
35 @Tags(["dub", "tup"])
36 unittest {
37     with(immutable ReggaeSandbox("dub")) {
38         runReggae("-b", "tup", "--dflags=-g -debug").
39             shouldThrowWithMessage("dub integration not supported with the tup backend");
40     }
41 }
42 
43 @ShouldFail("Weird linker errors")
44 @("dub project with no reggaefile and prebuild command")
45 @Tags(["dub", "ninja"])
46 unittest {
47     with(immutable ReggaeSandbox("dub_prebuild")) {
48         runReggae("-b", "ninja", "--dflags=-g -debug");
49         ninja.shouldExecuteOk;
50         shouldSucceed("ut");
51     }
52 }
53 
54 @("dub project with postbuild command")
55 @Tags(["dub", "ninja"])
56 unittest {
57     with(immutable ReggaeSandbox("dub_postbuild")) {
58         runReggae("-b", "ninja", "--dflags=-g -debug");
59         ninja.shouldExecuteOk;
60         shouldExist("foo.txt");
61         shouldSucceed("postbuild");
62     }
63 }
64 
65 
66 @("project with dependencies not on file system already no dub.selections.json")
67 @Tags(["dub", "ninja"])
68 unittest {
69 
70     import std.file: exists, rmdirRecurse;
71     import std.process: environment;
72     import std.path: buildPath;
73 
74     const cerealedDir = buildPath(environment["HOME"], ".dub/packages/cerealed-0.6.8");
75     if(cerealedDir.exists)
76         rmdirRecurse(cerealedDir);
77 
78     with(immutable ReggaeSandbox()) {
79         writeFile("dub.json", `
80         {
81           "name": "depends_on_cerealed",
82           "license": "MIT",
83           "targetType": "executable",
84           "dependencies": { "cerealed": "==0.6.8" }
85         }`);
86         writeFile("source/app.d", "void main() {}");
87 
88         runReggae("-b", "ninja");
89     }
90 }
91 
92 
93 @("simple dub project with no main function but with unit tests")
94 @Tags(["dub", "ninja"])
95 unittest {
96     import std.file: mkdirRecurse;
97     import std.path: buildPath;
98 
99     with(immutable ReggaeSandbox()) {
100         writeFile("dub.json", `
101             {
102               "name": "depends_on_cerealed",
103               "license": "MIT",
104               "targetType": "executable",
105               "dependencies": { "cerealed": "==0.6.8" }
106             }`);
107 
108         writeFile("reggaefile.d", q{
109             import reggae;
110             mixin build!(dubTestTarget!(CompilerFlags("-g -debug")));
111         });
112 
113         mkdirRecurse(buildPath(testPath, "source"));
114         writeFile("source/foo.d", `unittest { assert(false); }`);
115         runReggae("-b", "ninja");
116         ninja.shouldExecuteOk;
117 
118         shouldFail("ut");
119     }
120 }
121 
122 
123 @("reggae/dub build should rebuild if dub.selections.json changes")
124 @Tags(["dub", "make"])
125 unittest {
126 
127     import std.process: execute;
128     import std.path: buildPath;
129 
130     with(immutable ReggaeSandbox("dub")) {
131         runReggae("-b", "make", "--dflags=-g -debug");
132         make(["VERBOSE=1"]).shouldExecuteOk.shouldContain("-g -debug");
133         {
134             const ret = execute(["touch", buildPath(testPath, "dub.selections.json")]);
135             ret.status.shouldEqual(0);
136         }
137         {
138             const ret = execute(["make", "-C", testPath]);
139             ret.output.shouldContain("eggae");
140         }
141     }
142 }
143 
144 @("version from main package is used in dependent packages")
145 @Tags(["dub", "ninja"])
146 unittest {
147     with(immutable ReggaeSandbox()) {
148         writeFile("dub.sdl", `
149             name "foo"
150             versions "lefoo"
151             targetType "executable"
152             dependency "bar" path="bar"
153         `);
154         writeFile("source/app.d", q{
155             void main() {
156                 import bar;
157                 import std.stdio;
158                 writeln(lebar);
159             }
160         });
161         writeFile("bar/dub.sdl", `
162             name "bar"
163         `);
164         writeFile("bar/source/bar.d", q{
165             module bar;
166             version(lefoo)
167                 int lebar() { return 3; }
168             else
169                 int lebar() { return 42; }
170         });
171         runReggae("-b", "ninja");
172         ninja.shouldExecuteOk;
173         shouldSucceed("foo").shouldEqual(
174             [
175                 "3",
176             ]
177         );
178     }
179 }
180 
181 
182 @("sourceLibrary dependency")
183 @Tags(["dub", "ninja"])
184 unittest {
185     with(immutable ReggaeSandbox()) {
186         writeFile("dub.sdl", `
187             name "foo"
188             targetType "executable"
189             dependency "bar" path="bar"
190         `);
191         writeFile("source/app.d", q{
192             void main() {
193                 import bar;
194                 import std.stdio;
195                 writeln(lebar);
196             }
197         });
198         writeFile("bar/dub.sdl", `
199             name "bar"
200             targetType "sourceLibrary"
201         `);
202         writeFile("bar/source/bar.d", q{
203             module bar;
204             int lebar() { return 3; }
205         });
206         runReggae("-b", "ninja");
207         ninja.shouldExecuteOk;
208     }
209 }
210 
211 @("object source files")
212 @Tags(["dub", "ninja"])
213 unittest {
214     with(immutable ReggaeSandbox()) {
215         writeFile("dub.sdl", `
216             name "foo"
217             targetType "executable"
218             dependency "bar" path="bar"
219         `);
220         writeFile("source/app.d", q{
221             extern(C) int lebaz();
222             void main() {
223                 import bar;
224                 import std.stdio;
225                 writeln(lebar);
226                 writeln(lebaz);
227             }
228         });
229         writeFile("bar/dub.sdl", `
230             name "bar"
231             sourceFiles "../baz.o"
232         `);
233         writeFile("bar/source/bar.d", q{
234             module bar;
235             int lebar() { return 3; }
236         });
237         writeFile("baz.d", q{
238             module baz;
239             extern(C) int lebaz() { return 42; }
240         });
241 
242         ["dmd", "-c", "baz.d"].shouldExecuteOk;
243         runReggae("-b", "ninja");
244         ninja.shouldExecuteOk;
245     }
246 }
247 
248 
249 @("dub objs option path dependency")
250 @Tags("dub", "ninja", "dubObjsDir")
251 unittest {
252 
253     with(immutable ReggaeSandbox()) {
254 
255         writeFile("reggaefile.d", q{
256             import reggae;
257             mixin build!(dubDefaultTarget!());
258         });
259 
260         writeFile("dub.sdl",`
261             name "foo"
262             targetType "executable"
263             dependency "bar" path="bar"
264         `);
265 
266         writeFile("source/app.d", q{
267             import bar;
268             void main() { add(2, 3); }
269         });
270 
271         writeFile("bar/dub.sdl", `
272             name "bar"
273         `);
274 
275         writeFile("bar/source/bar.d", q{
276             module bar;
277             int add(int i, int j) { return i + j; }
278         });
279 
280         const dubObjsDir = buildPath(testPath, "objsdir");
281         const output = runReggae("-b", "ninja", "--dub-objs-dir=" ~ dubObjsDir);
282         writelnUt(output);
283         ninja.shouldExecuteOk;
284 
285         import std.path: buildPath;
286         shouldExist(buildPath("objsdir",
287                               testPath.deabsolutePath,
288                               "foo.objs",
289                               testPath.deabsolutePath,
290                               "bar",
291                               "source.o"));
292     }
293 }
294 
295 @("dub objs option registry dependency")
296 @Tags("dub", "ninja", "dubObjsDir")
297 unittest {
298 
299     import reggae.path: dubPackagesDir, deabsolutePath;
300 
301     with(immutable ReggaeSandbox()) {
302 
303         writeFile("reggaefile.d", q{
304             import reggae;
305             mixin build!(dubDefaultTarget!());
306         });
307 
308         writeFile("dub.sdl",`
309             name "foo"
310             targetType "executable"
311             dependency "dubnull" version="==0.0.1"
312         `);
313 
314         writeFile("source/app.d", q{
315             import dubnull;
316             void main() { dummy(); }
317         });
318 
319         const dubObjsDir = buildPath(testPath, "objsdir");
320         const output = runReggae("-b", "ninja", "--dub-objs-dir=" ~ dubObjsDir);
321         writelnUt(output);
322 
323         ninja.shouldExecuteOk;
324 
325         import std.path: buildPath;
326         const dubNullDir = buildPath(dubPackagesDir, "dubnull-0.0.1", "dubnull").deabsolutePath;
327         shouldExist(buildPath("objsdir",
328                               testPath.deabsolutePath,
329                               "foo.objs",
330                               dubNullDir,
331                               "source.o"));
332     }
333 }
334 
335 
336 @("object source files with dub objs option")
337 @Tags("dub", "ninja", "dubObjsDir")
338 unittest {
339     with(immutable ReggaeSandbox()) {
340         writeFile("dub.sdl", `
341             name "foo"
342             targetType "executable"
343             dependency "bar" path="bar"
344         `);
345         writeFile("source/app.d", q{
346             extern(C) int lebaz();
347             void main() {
348                 import bar;
349                 import std.stdio;
350                 writeln(lebar);
351                 writeln(lebaz);
352             }
353         });
354         writeFile("bar/dub.sdl", `
355             name "bar"
356             sourceFiles "../baz.o"
357         `);
358         writeFile("bar/source/bar.d", q{
359             module bar;
360             int lebar() { return 3; }
361         });
362         writeFile("baz.d", q{
363             module baz;
364             extern(C) int lebaz() { return 42; }
365         });
366 
367         ["dmd", "-c", "baz.d"].shouldExecuteOk;
368 
369         const output = runReggae("-b", "ninja", "--dub-objs-dir=" ~ testPath);
370         writelnUt(output);
371 
372         ninja.shouldExecuteOk;
373     }
374 }
375 
376 
377 @("dub project that depends on package with prebuild")
378 @Tags(["dub", "ninja"])
379 unittest {
380 
381     import std.path;
382 
383     with(immutable ReggaeSandbox("dub_depends_on_prebuild")) {
384 
385         copyProject("dub_prebuild", buildPath("..", "dub_prebuild"));
386 
387         runReggae("-b", "ninja", "--dflags=-g -debug");
388         ninja.shouldExecuteOk;
389         shouldSucceed("app");
390         shouldExist(inSandboxPath("../dub_prebuild/el_prebuildo.txt"));
391     }
392 }
393 
394 
395 @("static library")
396 @Tags(["dub", "ninja"])
397 unittest {
398 
399     with(immutable ReggaeSandbox()) {
400         writeFile("dub.sdl", `
401             name "foo"
402             targetType "executable"
403             targetName "d++"
404 
405             configuration "executable" {
406             }
407 
408             configuration "library" {
409                 targetType "library"
410                 targetName "dpp"
411                 excludedSourceFiles "source/main.d"
412             }
413         `);
414 
415         writeFile("reggaefile.d",
416                   q{
417                       import reggae;
418                       alias lib = dubConfigurationTarget!(Configuration("library"));
419                       enum mainObj = objectFile(SourceFile("source/main.d"));
420                       alias exe = link!(ExeName("d++"), targetConcat!(lib, mainObj));
421                       mixin build!(exe);
422                   });
423 
424         writeFile("source/main.d", "void main() {}");
425         writeFile("source/foo/bar/mod.d", "module foo.bar.mod; int add1(int i, int j) { return i + j + 1; }");
426 
427         runReggae("-b", "ninja");
428         ninja.shouldExecuteOk;
429         shouldSucceed("d++");
430     }
431 }