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 }