Skip to content

Commit 8429b98

Browse files
committed
[test] ConstructArray, DestructArray, Allocate and Deallocate
1 parent 97acb08 commit 8429b98

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,6 +2050,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
20502050
output.clear();
20512051
}
20522052

2053+
TEST(FunctionReflectionTest, ConstructArray) {
2054+
#if defined(EMSCRIPTEN) && (CLANG_VERSION_MAJOR < 20)
2055+
GTEST_SKIP() << "Test fails for LLVM < 20 Emscripten builds";
2056+
#endif
2057+
if (llvm::sys::RunningOnValgrind())
2058+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2059+
#ifdef _WIN32
2060+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2061+
#endif
2062+
#if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2063+
GTEST_SKIP() << "Test fails on Clang16 OS X";
2064+
#endif
2065+
2066+
Cpp::CreateInterpreter();
2067+
2068+
Interp->declare(R"(
2069+
#include <new>
2070+
extern "C" int printf(const char*,...);
2071+
class C {
2072+
int x;
2073+
C() {
2074+
x = 42;
2075+
printf("\nConstructor Executed\n");
2076+
}
2077+
};
2078+
)");
2079+
2080+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2081+
std::string output;
2082+
2083+
size_t a = 5; // Construct an array of 5 objects
2084+
void* where = Cpp::Allocate(scope, a); // operator new
2085+
2086+
testing::internal::CaptureStdout();
2087+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2088+
// Check for the value of x which should be at the start of the object.
2089+
EXPECT_TRUE(*(int*)where == 42);
2090+
// Check for the value of x in the second object
2091+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2092+
Cpp::SizeOf(scope));
2093+
EXPECT_TRUE(*obj == 42);
2094+
2095+
// Check for the value of x in the last object
2096+
obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2097+
(Cpp::SizeOf(scope) * 4));
2098+
EXPECT_TRUE(*obj == 42);
2099+
Cpp::Destruct(where, scope, /*withFree=*/false, 5);
2100+
Cpp::Deallocate(scope, where, 5);
2101+
output = testing::internal::GetCapturedStdout();
2102+
EXPECT_EQ(output,
2103+
"\nConstructor Executed\n\nConstructor Executed\n\nConstructor "
2104+
"Executed\n\nConstructor Executed\n\nConstructor Executed\n");
2105+
output.clear();
2106+
}
2107+
20532108
TEST(FunctionReflectionTest, Destruct) {
20542109
#ifdef EMSCRIPTEN
20552110
GTEST_SKIP() << "Test fails for Emscipten builds";
@@ -2107,6 +2162,85 @@ TEST(FunctionReflectionTest, Destruct) {
21072162
clang_Interpreter_dispose(I);
21082163
}
21092164

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

0 commit comments

Comments
 (0)