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