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