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 }