1 /**
2    C++ tests that must run
3  */
4 module it.cpp.run;
5 
6 import it;
7 
8 @Tags("run")
9 @("ctor")
10 @safe unittest {
11     shouldCompileAndRun(
12         Cpp(
13             q{
14                 struct Struct {
15                     void *data;
16 
17                     Struct(int i);
18                     Struct(const Struct&);
19                     Struct(Struct&&);
20 
21                     int number() const;
22                 };
23             }
24         ),
25         Cpp(
26             `
27                 #include <stdio.h>
28                 Struct::Struct(int i) {
29                     printf("C++: int ctor\n");
30                     data = reinterpret_cast<int*>(new int(i));
31                 }
32                 Struct::Struct(const Struct& other) {
33                     printf("C++: copy ctor\n");
34                     data = new int(*reinterpret_cast<int*>(other.data));
35                 }
36                 Struct::Struct(Struct&& other) {
37                     printf("C++: move ctor\n");
38                     printf("other data: %p\n", other.data);
39                     printf("as int: %d\n", *((int*)other.data));
40                     data = new int(*reinterpret_cast<int*>(other.data));
41                 }
42                 int Struct::number() const { return *reinterpret_cast<int*>(data); }
43             `
44         ),
45         D(
46             q{
47                 import std.stdio;
48 
49                 writeln("D: Testing int ctor");
50                 auto s1 = const Struct(42);
51                 assert(s1.number() == 42);
52                 assert(*(cast(int*)s1.data) == 42);
53 
54                 writeln("D: Testing copy ctor");
55                 auto s2 = Struct(s1);
56                 assert(s2.number() == 42);
57                 assert(s1.data !is s2.data);
58 
59                 // can't test the move ctor since translating it
60                 // as taking by value would cause `Struct(s1)` above
61                 // to actually move!
62                 // writeln("D: Testing move ctor");
63                 // auto s3 = Struct(Struct(33));
64                 // assert(s3.number() == 33);
65             }
66          ),
67     );
68 }
69 
70 
71 @Tags("run")
72 @("dtor")
73 @safe unittest {
74     shouldCompileAndRun(
75         Cpp(
76             q{
77                 struct Struct {
78                     static int numStructs;
79                     Struct(int i);
80                     ~Struct();
81                 };
82             }
83         ),
84         Cpp(
85             q{
86                 int Struct::numStructs;
87                 // the i parameter is to force D to call a constructor,
88                 // since Struct() just blasts it with Struct.init
89                 Struct::Struct(int i)  { numStructs += i; }
90                 Struct::~Struct()      { --numStructs; }
91             }
92         ),
93         D(
94             q{
95                 import std.conv: text;
96                 assert(Struct.numStructs == 0, Struct.numStructs.text);
97                 {
98                     auto s1 = Struct(3);
99                     assert(Struct.numStructs == 3, Struct.numStructs.text);
100 
101                     {
102                         auto s2 = Struct(2);
103                         assert(Struct.numStructs == 5, Struct.numStructs.text);
104                     }
105 
106                     assert(Struct.numStructs == 4, Struct.numStructs.text);
107                 }
108 
109                 assert(Struct.numStructs == 3, Struct.numStructs.text);
110             }
111          ),
112     );
113 }
114 
115 
116 @Tags("run")
117 @("function")
118 @safe unittest {
119     shouldCompileAndRun(
120         Cpp(
121             q{
122                 int add(int i, int j);
123 
124                 struct Adder {
125                     int i;
126                     Adder(int i);
127                     int add(int j);
128                 };
129             }
130         ),
131         Cpp(
132             q{
133                 int add(int i, int j) { return i + j; }
134                 Adder::Adder(int i):i(i + 10) {}
135                 int Adder::add(int j) { return i + j; }
136             }
137         ),
138         D(
139             q{
140                 import std.conv: text;
141                 import std.exception: assertThrown;
142                 import core.exception: AssertError;
143 
144                 assert(add(2, 3) == 5, "add(2, 3) should be 5");
145 
146                 void func() {
147                     assert(add(2, 3) == 7);
148                 }
149                 assertThrown!AssertError(func(), "add(2, 3) should not be 7");
150 
151                 auto adder = Adder(3);
152                 assert(adder.add(4) == 17, "Adder(3).add(4) should be 17 not " ~ text(adder.add(4)));
153             }
154          ),
155     );
156 }
157 
158 @Tags("run", "collision")
159 @("collisions")
160 @safe unittest {
161     shouldRun(
162         Cpp(
163             q{
164                 struct foo {
165                     int i;
166                 };
167                 int foo(int i, int j);
168                 struct foo add_foo_ptrs(const struct foo* f1, const struct foo* f2);
169 
170                 union bar {
171                     int i;
172                     double d;
173                 };
174                 int bar(int i);
175 
176                 enum baz { one, two, three };
177                 int baz();
178 
179                 enum other { four, five };
180                 int other;
181             }
182         ),
183         Cpp(
184             q{
185                 int foo(int i, int j) { return i + j + 1; }
186                 struct foo add_foo_ptrs(const struct foo* f1, const struct foo* f2) {
187                     struct foo ret;
188                     ret.i = f1->i + f2->i;
189                     return ret;
190                 }
191                 int bar(int i) { return i * 2; }
192                 int baz() { return 42; }
193             }
194         ),
195         D(
196             q{
197                 assert(foo_(2, 3) == 6);
198                 assert(bar_(4) == 8);
199                 assert(baz_ == 42);
200 
201                 auto f1 = foo(2);
202                 auto f2 = foo(3);
203                 assert(add_foo_ptrs(&f1, &f2) == foo(5));
204 
205                 bar b;
206                 b.i = 42;
207                 b.d = 33.3;
208 
209                 baz z1 = two;
210                 baz z2 = baz.one;
211 
212                 other_ = 77;
213                 other o1 = other.four;
214                 other o2 = five;
215 
216                 import std.exception: assertThrown;
217                 import core.exception: AssertError;
218                 void func() {
219                     assert(foo_(2, 3) == 7);
220                 }
221                 assertThrown!AssertError(func());
222             }
223          ),
224     );
225 
226 }