1 module tests.ut.cpprules;
2 
3 
4 import reggae;
5 import reggae.options;
6 import unit_threaded;
7 
8 
9 void testNoIncludePaths() {
10     auto build = Build(objectFile(SourceFile("path/to/src/foo.cpp")));
11     auto ninja = Ninja(build, "/tmp/myproject");
12     ninja.buildEntries.shouldEqual(
13         [NinjaEntry("build path/to/src/foo.o: _cppcompile /tmp/myproject/path/to/src/foo.cpp",
14                     ["DEPFILE = path/to/src/foo.o.dep"]),
15             ]);
16 }
17 
18 
19 void testIncludePaths() {
20     auto build = Build(objectFile(SourceFile("path/to/src/foo.cpp"), Flags(""),
21                                    IncludePaths(["path/to/src", "other/path"])));
22     auto ninja = Ninja(build, "/tmp/myproject");
23     ninja.buildEntries.shouldEqual(
24         [NinjaEntry("build path/to/src/foo.o: _cppcompile /tmp/myproject/path/to/src/foo.cpp",
25                     ["includes = -I/tmp/myproject/path/to/src -I/tmp/myproject/other/path",
26                      "DEPFILE = path/to/src/foo.o.dep"]),
27             ]);
28 }
29 
30 
31 void testFlagsCompileC() {
32     auto build = Build(objectFile(SourceFile("path/to/src/foo.c"), Flags("-m64 -fPIC -O3")));
33     auto ninja = Ninja(build, "/tmp/myproject");
34     ninja.buildEntries.shouldEqual(
35         [NinjaEntry("build path/to/src/foo.o: _ccompile /tmp/myproject/path/to/src/foo.c",
36                     ["flags = -m64 -fPIC -O3",
37                      "DEPFILE = path/to/src/foo.o.dep"]),
38             ]);
39 }
40 
41 void testFlagsCompileCpp() {
42     auto build = Build(objectFile(SourceFile("path/to/src/foo.cpp"), Flags("-m64 -fPIC -O3")));
43     auto ninja = Ninja(build, "/tmp/myproject");
44     ninja.buildEntries.shouldEqual(
45         [NinjaEntry("build path/to/src/foo.o: _cppcompile /tmp/myproject/path/to/src/foo.cpp",
46                     ["flags = -m64 -fPIC -O3",
47                      "DEPFILE = path/to/src/foo.o.dep"]),
48             ]);
49 }
50 
51 void testCppCompile() {
52     auto mathsObj = objectFile(SourceFile("src/cpp/maths.cpp"),
53                                 Flags("-m64 -fPIC -O3"),
54                                 IncludePaths(["headers"]));
55 
56     import reggae.config: gDefaultOptions;
57     mathsObj.shellCommand(gDefaultOptions.withProjectPath("/path/to")).shouldEqual(
58         "g++ -m64 -fPIC -O3 -I/path/to/headers -MMD -MT src/cpp/maths.o -MF src/cpp/maths.o.dep " ~
59         "-o src/cpp/maths.o -c /path/to/src/cpp/maths.cpp");
60 }
61 
62 void testCCompile() {
63     auto mathsObj = objectFile(SourceFile("src/c/maths.c"),
64                                 Flags("-m64 -fPIC -O3"),
65                                 IncludePaths(["headers"]));
66 
67     mathsObj.shellCommand(gDefaultOptions.withProjectPath("/path/to")).shouldEqual(
68         "gcc -m64 -fPIC -O3 -I/path/to/headers -MMD -MT src/c/maths.o -MF src/c/maths.o.dep " ~
69         "-o src/c/maths.o -c /path/to/src/c/maths.c");
70 }
71 
72 
73 void testUnityNoFiles() {
74     string[] files;
75     immutable projectPath = "";
76     unityFileContents(projectPath, files).shouldThrow;
77 }
78 
79 
80 private void shouldEqualLines(string actual, string[] expected,
81                               in string file = __FILE__, in ulong line = __LINE__) {
82     import std.string;
83     actual.split("\n").shouldEqual(expected, file, line);
84 }
85 
86 void testUnityCppFiles() {
87     auto files = ["src/foo.cpp", "src/bar.cpp"];
88     unityFileContents("/path/to/proj/", files).shouldEqualLines(
89         [`#include "/path/to/proj/src/foo.cpp"`,
90          `#include "/path/to/proj/src/bar.cpp"`]);
91 }
92 
93 
94 void testUnityCFiles() {
95     auto files = ["src/foo.c", "src/bar.c"];
96     unityFileContents("/foo/bar/", files).shouldEqualLines(
97         [`#include "/foo/bar/src/foo.c"`,
98          `#include "/foo/bar/src/bar.c"`]);
99 }
100 
101 void testUnityMixedLanguages() {
102     auto files = ["src/foo.cpp", "src/bar.c"];
103     unityFileContents("/project", files).shouldThrow;
104 }
105 
106 void testUnityDFiles() {
107     auto files = ["src/foo.d", "src/bar.d"];
108     unityFileContents("/project", files).shouldThrow;
109 }
110 
111 
112 void testUnityTargetCpp() @trusted {
113     import reggae.config: gDefaultOptions;
114 
115     enum files = ["src/foo.cpp", "src/bar.cpp", "src/baz.cpp"];
116     Target[] dependencies() @safe pure nothrow {
117         return [Target("$builddir/mylib.a")];
118     }
119 
120     immutable projectPath = "/path/to/proj";
121     auto target = unityTarget!(ExeName("leapp"),
122                                 projectPath,
123                                 files,
124                                 Flags("-g -O0"),
125                                 IncludePaths(["headers"]),
126                                 dependencies);
127     target.rawOutputs.shouldEqual(["leapp"]);
128     target.shellCommand(gDefaultOptions.withProjectPath(projectPath)).shouldEqual(
129         "g++ -g -O0 -I/path/to/proj/headers -MMD -MT leapp -MF leapp.dep -o leapp " ~
130         "objs/leapp.objs/unity.cpp mylib.a");
131     target.dependencyTargets.shouldEqual([Target.phony("$builddir/objs/leapp.objs/unity.cpp",
132                                                        "",
133                                                        [],
134                                                        [Target("src/foo.cpp"),
135                                                         Target("src/bar.cpp"),
136                                                         Target("src/baz.cpp")]),
137                                           Target("$builddir/mylib.a")]);
138 }
139 
140 void testUnityTargetC() @trusted {
141     import reggae.config: gDefaultOptions;
142 
143     enum files = ["src/foo.c", "src/bar.c", "src/baz.c"];
144     Target[] dependencies() @safe pure nothrow {
145         return [Target("$builddir/mylib.a")];
146     }
147 
148     immutable projectPath = "/path/to/proj";
149     auto target = unityTarget!(ExeName("leapp"),
150                                 projectPath,
151                                 files,
152                                 Flags("-g -O0"),
153                                 IncludePaths(["headers"]),
154                                 dependencies);
155     target.rawOutputs.shouldEqual(["leapp"]);
156     target.shellCommand(gDefaultOptions.withProjectPath(projectPath)).shouldEqual(
157         "gcc -g -O0 -I/path/to/proj/headers -MMD -MT leapp -MF leapp.dep -o leapp " ~
158         "objs/leapp.objs/unity.c mylib.a");
159     target.dependencyTargets.shouldEqual([Target.phony("$builddir/objs/leapp.objs/unity.c",
160                                                        "",
161                                                        [],
162                                                        [Target("src/foo.c"),
163                                                         Target("src/bar.c"),
164                                                         Target("src/baz.c")]),
165                                      Target("$builddir/mylib.a")]);
166 }