1 module tests.ut.backend.binary; 2 3 import reggae; 4 import unit_threaded; 5 import tests.utils; 6 7 @("Target selection") unittest { 8 9 bool fooCalled; 10 bool barCalled; 11 void resetCalls() { fooCalled = false; barCalled = false;} 12 13 auto foo = Target("foo", (in string[] i, in string[] o) { fooCalled = true; }, Target("foo.d")); 14 auto bar = Target("bar", (in string[] i, in string[] o) { barCalled = true; }, Target("bar.d")); 15 auto binary = Binary(Build(foo, bar), getOptions(["reggae", "--export"])); 16 17 { 18 scope(exit) resetCalls; 19 binary.run(["prog", "--norerun"]); 20 fooCalled.shouldBeTrue; 21 barCalled.shouldBeTrue; 22 } 23 24 { 25 scope(exit) resetCalls; 26 binary.run(["prog", "--norerun", "foo", "bar"]); 27 fooCalled.shouldBeTrue; 28 barCalled.shouldBeTrue; 29 } 30 31 { 32 scope(exit) resetCalls; 33 binary.run(["prog", "--norerun", "foo"]); 34 fooCalled.shouldBeTrue; 35 barCalled.shouldBeFalse; 36 } 37 38 { 39 scope(exit) resetCalls; 40 binary.run(["prog", "--norerun", "bar"]); 41 fooCalled.shouldBeFalse; 42 barCalled.shouldBeTrue; 43 } 44 45 { 46 scope(exit) resetCalls; 47 binary.run(["prog", "--norerun", "nonexistent"]).shouldThrow; 48 fooCalled.shouldBeFalse; 49 barCalled.shouldBeFalse; 50 } 51 } 52 53 @("Top-level targets") unittest { 54 import reggae.path: buildPath; 55 56 auto foo = Target("foo", "", Target("foo.d")); 57 auto bar = Target("bar", "", Target("bar.d")); 58 auto binary = Binary(Build(foo, bar), Options()); 59 60 auto newFoo = Target("foo", "", Target(buildPath("$project/foo.d"))); 61 auto newBar = Target("bar", "", Target(buildPath("$project/bar.d"))); 62 63 binary.topLevelTargets(["foo"]).shouldEqual([newFoo]); 64 binary.topLevelTargets(["bar"]).shouldEqual([newBar]); 65 binary.topLevelTargets([]).shouldEqual([newFoo, newBar]); 66 binary.topLevelTargets(["oops"]).shouldBeEmpty; 67 } 68 69 70 private Build binaryBuild() { 71 mixin build!(Target("app", "dmd -of$out $in", [Target("foo.o"), Target("bar.o") ]), 72 optional(Target.phony(`opt`, `echo Optional!`))); 73 return buildFunc(); 74 } 75 76 @("Listing targets") unittest { 77 import std.stdio: stdout, File; 78 79 auto file = FakeFile(); 80 auto binary = Binary(binaryBuild, getOptions(["./reggae", "-b", "binary"]), file); 81 binary.run(["./build", "--norerun", "-l"]); 82 83 file.lines.shouldEqual( 84 ["List of available top-level targets:", 85 "- app", 86 "- opt (optional)"]); 87 } 88 89 90 @("Unknown target") unittest { 91 import std.stdio: stdout, File; 92 93 auto binary = Binary(binaryBuild, getOptions(["./reggae", "-b", "binary"])); 94 binary.run(["./build", "--norerun", "oops"]). 95 shouldThrowWithMessage("Unknown target(s) 'oops'"); 96 } 97 98 @("Unknown targets") unittest { 99 import std.stdio: stdout, File; 100 101 auto binary = Binary(binaryBuild, getOptions(["./reggae", "-b", "binary"])); 102 binary.run(["./build", "--norerun", "oops", "woopsie"]). 103 shouldThrowWithMessage("Unknown target(s) 'oops' 'woopsie'"); 104 } 105 106 107 @("Non-phony target with no dependencies gets built if output doesn't exist") 108 unittest { 109 bool ran; 110 auto build = Build(Target("foo.txt", 111 (in string[], in string[]) { ran = true; })); 112 auto binary = Binary(build, getOptions(["reggae", "-b", "binary"])); 113 binary.run(["./build", "--norerun"]); 114 ran.shouldBeTrue; 115 }