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 }