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 <iostream>
28                 using namespace std;
29                 Struct::Struct(int i) {
30                     cout << "C++: int ctor" << endl;
31                     data = new int(i);
32                 }
33                 Struct::Struct(const Struct& other) {
34                     cout << "C++: copy ctor" << endl;
35                     data = new int(*reinterpret_cast<int*>(other.data) - 1);
36                 }
37                 Struct::Struct(Struct&& other) {
38                     cout << "C++: move ctor" << endl;
39                     data = other.data;
40                     *reinterpret_cast<int*>(data) = number() + 1;
41                 }
42                 int Struct::number() const { return *reinterpret_cast<int*>(data); }
43             `
44         ),
45         D(
46             q{
47                 import std.stdio;
48                 import std.process;
49 
50                 const dCompiler = environment.get("DC", "dmd");
51 
52                 writeln("D: Testing int ctor");
53                 auto cs = const Struct(42);
54                 assert(cs.number() == 42);
55                 assert(*(cast(int*)cs.data) == 42);
56                 auto ms = Struct(7);
57 
58                 writeln("D: Testing copy ctor");
59                 {
60                     auto s = Struct(cs);
61                     assert(s.number() == 41);
62                     assert(cs.data !is s.data);
63                 }
64                 {
65                     auto s = Struct(ms);
66                     assert(s.number() == 6);
67                     assert(cs.data !is s.data);
68                 }
69 
70                 writeln("D: Testing move ctor");
71                 auto tmp = Struct(33);
72                 const oldTmpData = tmp.data;
73                 auto mv1 = Struct(dpp.move(tmp));
74                 assert(mv1.number() == 34);
75                 assert(mv1.data is oldTmpData);
76                 assert(tmp.data is null);
77 
78                 static assert(!__traits(compiles, Struct(dpp.move(cs))));
79 
80                 if(dCompiler != "dmd") {
81                     auto mv2 = Struct(Struct(77));
82                     assert(mv2.number() == 78);
83                 }
84 
85                 static assert(!__traits(compiles, Struct()));
86             }
87          ),
88     );
89 }
90 
91 
92 @Tags("run")
93 @("dtor")
94 @safe unittest {
95     shouldCompileAndRun(
96         Cpp(
97             q{
98                 struct Struct {
99                     static int numStructs;
100                     Struct(int i);
101                     ~Struct();
102                 };
103 
104                 struct DeletedDtor {
105                     ~DeletedDtor() = delete;
106                 };
107             }
108         ),
109         Cpp(
110             q{
111                 int Struct::numStructs;
112                 // the i parameter is to force D to call a constructor,
113                 // since Struct() just blasts it with Struct.init
114                 Struct::Struct(int i)  { numStructs += i; }
115                 Struct::~Struct()      { --numStructs; }
116             }
117         ),
118         D(
119             q{
120                 import std.conv: text;
121                 assert(Struct.numStructs == 0, Struct.numStructs.text);
122                 {
123                     auto s1 = Struct(3);
124                     assert(Struct.numStructs == 3, Struct.numStructs.text);
125 
126                     {
127                         auto s2 = Struct(2);
128                         assert(Struct.numStructs == 5, Struct.numStructs.text);
129                     }
130 
131                     assert(Struct.numStructs == 4, Struct.numStructs.text);
132                 }
133 
134                 assert(Struct.numStructs == 3, Struct.numStructs.text);
135             }
136          ),
137     );
138 }
139 
140 
141 @Tags("run")
142 @("function")
143 @safe unittest {
144     shouldCompileAndRun(
145         Cpp(
146             q{
147                 int add(int i, int j);
148 
149                 struct Adder {
150                     int i;
151                     Adder(int i);
152                     int add(int j);
153                 };
154             }
155         ),
156         Cpp(
157             q{
158                 int add(int i, int j) { return i + j; }
159                 Adder::Adder(int i):i(i + 10) {}
160                 int Adder::add(int j) { return i + j; }
161             }
162         ),
163         D(
164             q{
165                 import std.conv: text;
166                 import std.exception: assertThrown;
167                 import core.exception: AssertError;
168 
169                 assert(add(2, 3) == 5, "add(2, 3) should be 5");
170 
171                 void func() {
172                     assert(add(2, 3) == 7);
173                 }
174                 assertThrown!AssertError(func(), "add(2, 3) should not be 7");
175 
176                 auto adder = Adder(3);
177                 assert(adder.add(4) == 17, "Adder(3).add(4) should be 17 not " ~ text(adder.add(4)));
178             }
179          ),
180     );
181 }
182 
183 @Tags("run", "collision")
184 @("collisions")
185 @safe unittest {
186     shouldRun(
187         Cpp(
188             q{
189                 struct foo {
190                     int i;
191                 };
192                 int foo(int i, int j);
193                 struct foo add_foo_ptrs(const struct foo* f1, const struct foo* f2);
194 
195                 union bar {
196                     int i;
197                     double d;
198                 };
199                 int bar(int i);
200 
201                 enum baz { one, two, three };
202                 int baz();
203 
204                 enum other { four, five };
205                 int other;
206             }
207         ),
208         Cpp(
209             q{
210                 int foo(int i, int j) { return i + j + 1; }
211                 struct foo add_foo_ptrs(const struct foo* f1, const struct foo* f2) {
212                     struct foo ret;
213                     ret.i = f1->i + f2->i;
214                     return ret;
215                 }
216                 int bar(int i) { return i * 2; }
217                 int baz() { return 42; }
218             }
219         ),
220         D(
221             q{
222                 assert(foo_(2, 3) == 6);
223                 assert(bar_(4) == 8);
224                 assert(baz_ == 42);
225 
226                 auto f1 = foo(2);
227                 auto f2 = foo(3);
228                 assert(add_foo_ptrs(&f1, &f2) == foo(5));
229 
230                 bar b;
231                 b.i = 42;
232                 b.d = 33.3;
233 
234                 baz z1 = two;
235                 baz z2 = baz.one;
236 
237                 other_ = 77;
238                 other o1 = other.four;
239                 other o2 = five;
240 
241                 import std.exception: assertThrown;
242                 import core.exception: AssertError;
243                 void func() {
244                     assert(foo_(2, 3) == 7);
245                 }
246                 assertThrown!AssertError(func());
247             }
248          ),
249     );
250 }
251 
252 
253 @ShouldFail
254 @Tags("run")
255 @("operators")
256 @safe unittest {
257     shouldRun(
258         Cpp(
259             q{
260                 struct Struct {
261                     int i;
262                     Struct(int i);
263 
264                     // Unary operators
265                     Struct operator+ ()    const;
266                     Struct operator- ()    const;
267                     Struct operator* ()    const;
268                     Struct operator& ()    const;
269                     Struct operator->()    const;
270                     Struct operator~ ()    const;
271                     bool   operator! ()    const;
272                     Struct operator++()    const;
273                     Struct operator--()    const;
274                     Struct operator++(int) const; // not defined on purpose
275                     Struct operator--(int) const; // not defined on purpose
276 
277                     // Binary operators
278                     Struct operator+  (const Struct& other) const;
279                     Struct operator-  (const Struct& other) const;
280                     Struct operator*  (const Struct& other) const;
281                     Struct operator/  (const Struct& other) const;
282                     Struct operator%  (const Struct& other) const;
283                     Struct operator^  (const Struct& other) const;
284                     Struct operator&  (const Struct& other) const;
285                     Struct operator|  (const Struct& other) const;
286                     Struct operator>> (const Struct& other) const;
287                     Struct operator<< (const Struct& other) const;
288                     Struct operator&& (const Struct& other) const;
289                     Struct operator|| (const Struct& other) const;
290                     Struct operator->*(const Struct& other) const;
291                     Struct operator,  (const Struct& other) const;
292 
293                     // assignment
294                     void operator=  (const Struct& other);
295                     void operator+= (int j);
296                     void operator-= (int j);
297                     void operator*= (int j);
298                     void operator/= (int j);
299                     void operator%= (int j);
300                     void operator^= (int j);
301                     void operator&= (int j);
302                     void operator|= (int j);
303                     void operator>>=(int j);
304                     void operator<<=(int j);
305 
306                     // special
307                     int operator()(int j) const;
308                     int operator[](int j) const;
309 
310                     // comparison
311                     bool operator==(int j) const;
312                     bool operator!=(const Struct& other) const; // not defined on purpose
313                     bool operator>=(const Struct& other) const; // not defined on purpose
314                     bool operator<=(const Struct& other) const; // not defined on purpose
315                     bool operator> (const Struct& other) const;
316                     bool operator< (const Struct& other) const;
317 
318                     // conversion
319                     operator int() const;
320 
321                     // allocation
322                     static void* operator new(unsigned long);
323                     static void* operator new[](unsigned long);
324                     static void operator delete(void*);
325                     static void operator delete[](void*);
326                 };
327 
328                 struct Stream {};
329                 Stream& operator<<(Stream& stream, const Struct& s);
330             }
331         ),
332         Cpp(
333             q{
334                 Struct::Struct(int i):i{i} {}
335                 Struct Struct::operator+ () const { return { +i };    }
336                 Struct Struct::operator- () const { return { -i };    }
337                 Struct Struct::operator* () const { return { i * 3 }; }
338                 Struct Struct::operator& () const { return { i / 4 }; }
339                 Struct Struct::operator->() const { return { i / 3 }; }
340                 Struct Struct::operator~ () const { return { i + 9 }; }
341                 bool   Struct::operator! () const { return i != 7;    }
342                 Struct Struct::operator++() const { return { i + 1 }; }
343                 Struct Struct::operator--() const { return { i - 1 }; }
344 
345                 Struct Struct::operator+  (const Struct& other) const { return { i + other.i }; }
346                 Struct Struct::operator-  (const Struct& other) const { return { i - other.i }; }
347                 Struct Struct::operator*  (const Struct& other) const { return { i * other.i }; }
348                 Struct Struct::operator/  (const Struct& other) const { return { i / other.i }; }
349                 Struct Struct::operator%  (const Struct& other) const { return { i % other.i }; }
350                 Struct Struct::operator^  (const Struct& other) const { return { i + other.i + 2 }; }
351                 Struct Struct::operator&  (const Struct& other) const { return { i * other.i + 1 }; }
352                 Struct Struct::operator|  (const Struct& other) const { return { i + other.i + 1 }; }
353                 Struct Struct::operator<< (const Struct& other) const { return { i + other.i }; }
354                 Struct Struct::operator>> (const Struct& other) const { return { i - other.i }; }
355                 Struct Struct::operator&& (const Struct& other) const { return { i && other.i }; }
356                 Struct Struct::operator|| (const Struct& other) const { return { i || other.i }; }
357                 Struct Struct::operator->*(const Struct& other) const { return { i - other.i }; }
358                 Struct Struct::operator,  (const Struct& other) const { return { i - other.i - 1 }; }
359 
360                 void Struct::operator= (const Struct& other)  { i = other.i + 10; };
361                 void Struct::operator+=(int j)                { i += j;           };
362                 void Struct::operator-=(int j)                { i -= j;           };
363                 void Struct::operator*=(int j)                { i *= j;           };
364                 void Struct::operator/=(int j)                { i /= j;           };
365                 void Struct::operator%=(int j)                { i %= j;           };
366                 void Struct::operator^=(int j)                { i ^= j;           };
367                 void Struct::operator&=(int j)                { i &= j;           };
368                 void Struct::operator|=(int j)                { i |= j;           };
369                 void Struct::operator>>=(int j)               { i >>= j;          };
370                 void Struct::operator<<=(int j)               { i <<= j;          };
371 
372                 int Struct::operator()(int j) const { return i * j; }
373                 int Struct::operator[](int j) const { return i / j; }
374 
375                 bool Struct::operator==(int j) const { return i == j; }
376                 bool Struct::operator<(const Struct& other) const { return i < other.i; }
377                 bool Struct::operator>(const Struct& other) const { return i > other.i; }
378 
379                 Struct::operator int() const { return i + 1; }
380 
381                 void* Struct::operator new(unsigned long count) { return new int{static_cast<int>(count)}; }
382                 void* Struct::operator new[](unsigned long count) { return new int{static_cast<int>(count + 1)}; }
383                 void Struct::operator delete(void*) {}
384                 void Struct::operator delete[](void*) {}
385 
386                 Stream& operator<<(Stream& stream, const Struct& s) { return stream; }
387             }
388         ),
389         D(
390             q{
391                 import std.conv: text;
392 
393                 // unary
394                 assert(+Struct(-4) == -4);
395                 assert(-Struct(4)  == -4);
396                 assert(-Struct(-5) == 5);
397                 assert(*Struct(2) == 6);
398                 assert(Struct(8).opCppAmpersand == 2);
399                 assert(Struct(9).opCppArrow == 3);
400                 assert(~Struct(7) == 16);
401                 assert(Struct(9).opCppBang);
402 
403                 assert(++Struct(2) == 3);
404                 assert(--Struct(5) == 4);
405 
406                 // binary
407                 auto s0 = const Struct(0);
408                 auto s2 = const Struct(2);
409                 auto s3 = const Struct(3);
410 
411                 assert(s2 + s3 == 5);
412                 assert(s3 - s2 == 1);
413                 assert(Struct(5) - s2 == 3);
414                 assert(s2 * s3 == 6);
415                 assert(Struct(11) / s3 == 3) ;
416 
417                 assert(Struct(5) % s2 == 1);
418                 assert(Struct(6) % s2 == 0);
419 
420                 assert((Struct(4) ^ s2) == 8);
421                 assert((Struct(4) & s2) == 9);
422                 assert((Struct(4) | s2) == 7);
423 
424                 assert(Struct(7) >> s2 == 5);
425                 assert(Struct(3) << s3 == 6);
426 
427                 assert(Struct(5).opCppArrowStar(s2) == 3);
428                 assert(Struct(5).opCppComma(s2) == 2);
429 
430                 // assignment
431                 {
432                     auto s = Struct(5);
433                     s = s2; assert(s == 12);
434                 }
435 
436                 {
437                     auto s = Struct(2);
438                     s += 3; assert(s == 5);
439                     s -= 2; assert(s == 3);
440                     s *= 2; assert(s == 6);
441                     s /= 3; assert(s == 2);
442                     s = s3;
443                     s %= 2; assert(s == 1);
444                     s ^= 1; assert(s == 0);
445                     s &= 1; assert(s == 0);
446                     s |= 1; assert(s == 1);
447                     s.i = 8;
448                     s >>= 2; assert(s == 2);
449                     s <<= 1; assert(s == 4);
450                 }
451 
452                 // special
453                 assert(Struct(2)(3) == 6);
454                 assert(Struct(7)[2] == 3);
455 
456                 // comparison (== already done everywhere above)
457                 assert(Struct(3) <  Struct(5));
458                 assert(Struct(5) >  Struct(3));
459                 assert(Struct(3) <= Struct(5));
460                 assert(Struct(3) <= Struct(3));
461                 assert(Struct(5) >  Struct(3));
462                 assert(Struct(5) >= Struct(5));
463 
464                 // conversion
465                 assert(cast(int) Struct(7) == 8);
466                 assert( cast(bool) Struct(7));
467                 assert(!cast(bool) Struct(3));
468 
469                 // allocation
470                 assert(*(cast(int*) Struct.opCppNew(5)) == 5);
471                 assert(*(cast(int*) Struct.opCppNewArray(5)) == 6);
472                 Struct.opCppDelete(null);
473                 Struct.opCppDeleteArray(null);
474 
475                 // free function
476                 Stream stream;
477                 stream.opCppLShift(s2);
478             }
479          ),
480     );
481 }
482 
483 @ShouldFail
484 @Tags("run")
485 @("templates")
486 @safe unittest {
487     shouldRun(
488         Cpp(
489             q{
490                 template<typename T>
491                 class vector {
492                     T _values[10];
493                     int _numValues = 0;
494 
495                 public:
496                     void push_back(T value) {
497                         _values[_numValues++] = value;
498                     }
499 
500                     int numValues() { return _numValues; }
501                     T value(int i) { return _values[i]; }
502                 };
503             }
504         ),
505         Cpp(
506             `
507                 #if __clang__
508                     [[clang::optnone]]
509                 #elif __GNUC__
510                     __attribute__((optimize("O0")))
511                 #endif
512                     __attribute((used, noinline))
513                 static void instantiate() {
514                     vector<int> v;
515                     v.push_back(42);
516                     v.value(0);
517                     v.numValues();
518                 }
519             `
520         ),
521         D(
522             q{
523                 vector!int v;
524                 assert(v.numValues == 0);
525 
526                 v.push_back(4);
527                 assert(v.numValues == 1);
528                 assert(v.value(0) == 4);
529 
530                 v.push_back(2);
531                 assert(v.numValues == 2);
532                 assert(v.value(0) == 4);
533                 assert(v.value(1) == 2);
534 
535                 foreach(i; 2 .. v.numValues)
536                     assert(v.value(i) == 0);
537             }
538          ),
539     );
540 }
541 
542 
543 @Tags("run")
544 @("namespaces")
545 @safe unittest {
546     shouldRun(
547         Cpp(
548             q{
549                 namespace ns0 {
550                     int foo();
551                     int bar();
552                     namespace ns1 {
553                         int baz();
554                     }
555                 }
556 
557                 namespace other {
558                     int quux();
559                 }
560 
561                 // can reopen namespace
562                 namespace ns0 {
563                     int toto();
564                 }
565             }
566         ),
567         Cpp(
568             q{
569                 namespace ns0 {
570                     int foo() { return 1; }
571                     int bar() { return 2; }
572                     namespace ns1 {
573                         int baz() { return 3; }
574                     }
575                 }
576 
577                 namespace other {
578                     int quux() { return 4; }
579                 }
580 
581                 // can reopen namespace
582                 namespace ns0 {
583                     int toto() { return 5; }
584                 }
585             }
586         ),
587         D(
588             q{
589                 assert(foo == 1);
590                 assert(bar == 2);
591                 assert(baz == 3);
592                 assert(quux == 4);
593                 assert(toto == 5);
594             }
595          ),
596     );
597 }