Skip to content

Commit 7596735

Browse files
committed
[test] ConstructArray, DestructArray, Allocate and Deallocate
1 parent 8c0c440 commit 7596735

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,58 @@ TEST(FunctionReflectionTest, ConstructNested) {
20402040
output.clear();
20412041
}
20422042

2043+
TEST(FunctionReflectionTest, ConstructArray) {
2044+
#if defined(EMSCRIPTEN) && (CLANG_VERSION_MAJOR < 20)
2045+
GTEST_SKIP() << "Test fails for LLVM < 20 Emscripten builds";
2046+
#endif
2047+
if (llvm::sys::RunningOnValgrind())
2048+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2049+
#ifdef _WIN32
2050+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2051+
#endif
2052+
2053+
Cpp::CreateInterpreter();
2054+
2055+
Interp->declare(R"(
2056+
#include <new>
2057+
extern "C" int printf(const char*,...);
2058+
class C {
2059+
int x;
2060+
C() {
2061+
x = 42;
2062+
printf("\nConstructor Executed\n");
2063+
}
2064+
};
2065+
)");
2066+
2067+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2068+
std::string output;
2069+
2070+
size_t a = 5; // Construct an array of 5 objects
2071+
void* where = Cpp::Allocate(scope, a); // operator new
2072+
2073+
testing::internal::CaptureStdout();
2074+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2075+
// Check for the value of x which should be at the start of the object.
2076+
EXPECT_TRUE(*(int*)where == 42);
2077+
// Check for the value of x in the second object
2078+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2079+
Cpp::SizeOf(scope));
2080+
EXPECT_TRUE(*obj == 42);
2081+
2082+
// Check for the value of x in the last object
2083+
obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2084+
Cpp::SizeOf(scope) * 4);
2085+
EXPECT_TRUE(*obj == 42);
2086+
Cpp::Destruct(where, scope, /*withFree=*/false, 5);
2087+
Cpp::Deallocate(scope, where, 5);
2088+
output = testing::internal::GetCapturedStdout();
2089+
EXPECT_EQ(output,
2090+
"\nConstructor Executed\n\nConstructor Executed\n\nConstructor "
2091+
"Executed\n\nConstructor Executed\n\nConstructor Executed\n");
2092+
output.clear();
2093+
}
2094+
20432095
TEST(FunctionReflectionTest, Destruct) {
20442096
#ifdef EMSCRIPTEN
20452097
GTEST_SKIP() << "Test fails for Emscipten builds";
@@ -2097,6 +2149,82 @@ TEST(FunctionReflectionTest, Destruct) {
20972149
clang_Interpreter_dispose(I);
20982150
}
20992151

2152+
TEST(FunctionReflectionTest, DestructArray) {
2153+
#ifdef EMSCRIPTEN
2154+
GTEST_SKIP() << "Test fails for Emscipten builds";
2155+
#endif
2156+
if (llvm::sys::RunningOnValgrind())
2157+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2158+
2159+
#ifdef _WIN32
2160+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2161+
#endif
2162+
2163+
std::vector<const char*> interpreter_args = {"-include", "new"};
2164+
Cpp::CreateInterpreter(interpreter_args);
2165+
2166+
Interp->declare(R"(
2167+
#include <new>
2168+
extern "C" int printf(const char*,...);
2169+
class C {
2170+
int x;
2171+
C() {
2172+
printf("\nCtor Executed\n");
2173+
x = 42;
2174+
}
2175+
~C() {
2176+
printf("\nDestructor Executed\n");
2177+
}
2178+
};
2179+
)");
2180+
2181+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2182+
std::string output;
2183+
2184+
size_t a = 5; // Construct an array of 5 objects
2185+
void* where = Cpp::Allocate(scope, a); // operator new
2186+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2187+
2188+
// verify the array of objects has been constructed
2189+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2190+
Cpp::SizeOf(scope) * 4);
2191+
EXPECT_TRUE(*obj == 42);
2192+
2193+
testing::internal::CaptureStdout();
2194+
// destruct 3 out of 5 objects
2195+
Cpp::Destruct(where, scope, false, 3);
2196+
output = testing::internal::GetCapturedStdout();
2197+
2198+
EXPECT_EQ(
2199+
output,
2200+
"\nDestructor Executed\n\nDestructor Executed\n\nDestructor Executed\n");
2201+
output.clear();
2202+
testing::internal::CaptureStdout();
2203+
2204+
// destruct the rest
2205+
auto new_head = reinterpret_cast<void*>(reinterpret_cast<char*>(where) +
2206+
Cpp::SizeOf(scope) * 3);
2207+
Cpp::Destruct(new_head, scope, false, 2);
2208+
2209+
output = testing::internal::GetCapturedStdout();
2210+
EXPECT_EQ(output, "\nDestructor Executed\n\nDestructor Executed\n");
2211+
output.clear();
2212+
2213+
// deallocate since we call the destructor withFree = false
2214+
Cpp::Deallocate(scope, where, 5);
2215+
2216+
// perform the same withFree=true
2217+
where = Cpp::Allocate(scope, a);
2218+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a));
2219+
testing::internal::CaptureStdout();
2220+
// FIXME : This should work with the array of objects as well
2221+
// Cpp::Destruct(where, scope, true, 5);
2222+
Cpp::Destruct(where, scope, true);
2223+
output = testing::internal::GetCapturedStdout();
2224+
EXPECT_EQ(output, "\nDestructor Executed\n");
2225+
output.clear();
2226+
}
2227+
21002228
TEST(FunctionReflectionTest, UndoTest) {
21012229
#ifdef _WIN32
21022230
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";

0 commit comments

Comments
 (0)