Skip to content

Commit 4218a88

Browse files
committed
[test] ConstructArray, DestructArray, Allocate and Deallocate
1 parent 253ae7f commit 4218a88

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,49 @@ TEST(FunctionReflectionTest, Construct) {
19871987
clang_Interpreter_dispose(I);
19881988
}
19891989

1990+
// Test zero initialization of PODs and default initialization cases
1991+
TEST(FunctionReflectionTest, ConstructPOD) {
1992+
#ifdef EMSCRIPTEN
1993+
#if CLANG_VERSION_MAJOR < 20
1994+
GTEST_SKIP() << "Test fails for Emscipten builds";
1995+
#endif
1996+
#endif
1997+
if (llvm::sys::RunningOnValgrind())
1998+
GTEST_SKIP() << "XFAIL due to Valgrind report";
1999+
#ifdef _WIN32
2000+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2001+
#endif
2002+
std::vector<const char*> interpreter_args = {"-include", "new"};
2003+
Cpp::CreateInterpreter(interpreter_args);
2004+
2005+
Interp->declare(R"(
2006+
namespace PODS {
2007+
struct SomePOD_B {
2008+
int fInt;
2009+
};
2010+
struct SomePOD_C {
2011+
int fInt;
2012+
double fDouble;
2013+
};
2014+
})");
2015+
2016+
auto *ns = Cpp::GetNamed("PODS");
2017+
Cpp::TCppScope_t scope = Cpp::GetNamed("SomePOD_B", ns);
2018+
EXPECT_TRUE(scope);
2019+
Cpp::TCppObject_t object = Cpp::Construct(scope);
2020+
EXPECT_TRUE(object != nullptr);
2021+
int* fInt = reinterpret_cast<int*>(reinterpret_cast<char*>(object));
2022+
EXPECT_TRUE(*fInt == 0);
2023+
2024+
scope = Cpp::GetNamed("SomePOD_C", ns);
2025+
EXPECT_TRUE(scope);
2026+
object = Cpp::Construct(scope);
2027+
EXPECT_TRUE(object);
2028+
auto* fDouble =
2029+
reinterpret_cast<double*>(reinterpret_cast<char*>(object) + sizeof(int));
2030+
EXPECT_EQ(*fDouble, 0.0);
2031+
}
2032+
19902033
// Test nested constructor calls
19912034
TEST(FunctionReflectionTest, ConstructNested) {
19922035
#ifdef EMSCRIPTEN
@@ -2050,6 +2093,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
20502093
output.clear();
20512094
}
20522095

2096+
TEST(FunctionReflectionTest, ConstructArray) {
2097+
#if defined(EMSCRIPTEN)
2098+
GTEST_SKIP() << "Test fails for Emscripten builds";
2099+
#endif
2100+
if (llvm::sys::RunningOnValgrind())
2101+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2102+
#ifdef _WIN32
2103+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2104+
#endif
2105+
#if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2106+
GTEST_SKIP() << "Test fails on Clang16 OS X";
2107+
#endif
2108+
2109+
Cpp::CreateInterpreter();
2110+
2111+
Interp->declare(R"(
2112+
#include <new>
2113+
extern "C" int printf(const char*,...);
2114+
class C {
2115+
int x;
2116+
C() {
2117+
x = 42;
2118+
printf("\nConstructor Executed\n");
2119+
}
2120+
};
2121+
)");
2122+
2123+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2124+
std::string output;
2125+
2126+
size_t a = 5; // Construct an array of 5 objects
2127+
void* where = Cpp::Allocate(scope, a); // operator new
2128+
2129+
testing::internal::CaptureStdout();
2130+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2131+
// Check for the value of x which should be at the start of the object.
2132+
EXPECT_TRUE(*(int*)where == 42);
2133+
// Check for the value of x in the second object
2134+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2135+
Cpp::SizeOf(scope));
2136+
EXPECT_TRUE(*obj == 42);
2137+
2138+
// Check for the value of x in the last object
2139+
obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2140+
(Cpp::SizeOf(scope) * 4));
2141+
EXPECT_TRUE(*obj == 42);
2142+
Cpp::Destruct(where, scope, /*withFree=*/false, 5);
2143+
Cpp::Deallocate(scope, where, 5);
2144+
output = testing::internal::GetCapturedStdout();
2145+
EXPECT_EQ(output,
2146+
"\nConstructor Executed\n\nConstructor Executed\n\nConstructor "
2147+
"Executed\n\nConstructor Executed\n\nConstructor Executed\n");
2148+
output.clear();
2149+
}
2150+
20532151
TEST(FunctionReflectionTest, Destruct) {
20542152
#ifdef EMSCRIPTEN
20552153
GTEST_SKIP() << "Test fails for Emscipten builds";
@@ -2107,6 +2205,85 @@ TEST(FunctionReflectionTest, Destruct) {
21072205
clang_Interpreter_dispose(I);
21082206
}
21092207

2208+
TEST(FunctionReflectionTest, DestructArray) {
2209+
#ifdef EMSCRIPTEN
2210+
GTEST_SKIP() << "Test fails for Emscipten builds";
2211+
#endif
2212+
if (llvm::sys::RunningOnValgrind())
2213+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2214+
2215+
#ifdef _WIN32
2216+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2217+
#endif
2218+
#if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2219+
GTEST_SKIP() << "Test fails on Clang16 OS X";
2220+
#endif
2221+
2222+
std::vector<const char*> interpreter_args = {"-include", "new"};
2223+
Cpp::CreateInterpreter(interpreter_args);
2224+
2225+
Interp->declare(R"(
2226+
#include <new>
2227+
extern "C" int printf(const char*,...);
2228+
class C {
2229+
int x;
2230+
C() {
2231+
printf("\nCtor Executed\n");
2232+
x = 42;
2233+
}
2234+
~C() {
2235+
printf("\nDestructor Executed\n");
2236+
}
2237+
};
2238+
)");
2239+
2240+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2241+
std::string output;
2242+
2243+
size_t a = 5; // Construct an array of 5 objects
2244+
void* where = Cpp::Allocate(scope, a); // operator new
2245+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2246+
2247+
// verify the array of objects has been constructed
2248+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2249+
Cpp::SizeOf(scope) * 4);
2250+
EXPECT_TRUE(*obj == 42);
2251+
2252+
testing::internal::CaptureStdout();
2253+
// destruct 3 out of 5 objects
2254+
Cpp::Destruct(where, scope, false, 3);
2255+
output = testing::internal::GetCapturedStdout();
2256+
2257+
EXPECT_EQ(
2258+
output,
2259+
"\nDestructor Executed\n\nDestructor Executed\n\nDestructor Executed\n");
2260+
output.clear();
2261+
testing::internal::CaptureStdout();
2262+
2263+
// destruct the rest
2264+
auto *new_head = reinterpret_cast<void*>(reinterpret_cast<char*>(where) +
2265+
(Cpp::SizeOf(scope) * 3));
2266+
Cpp::Destruct(new_head, scope, false, 2);
2267+
2268+
output = testing::internal::GetCapturedStdout();
2269+
EXPECT_EQ(output, "\nDestructor Executed\n\nDestructor Executed\n");
2270+
output.clear();
2271+
2272+
// deallocate since we call the destructor withFree = false
2273+
Cpp::Deallocate(scope, where, 5);
2274+
2275+
// perform the same withFree=true
2276+
where = Cpp::Allocate(scope, a);
2277+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a));
2278+
testing::internal::CaptureStdout();
2279+
// FIXME : This should work with the array of objects as well
2280+
// Cpp::Destruct(where, scope, true, 5);
2281+
Cpp::Destruct(where, scope, true);
2282+
output = testing::internal::GetCapturedStdout();
2283+
EXPECT_EQ(output, "\nDestructor Executed\n");
2284+
output.clear();
2285+
}
2286+
21102287
TEST(FunctionReflectionTest, UndoTest) {
21112288
#ifdef _WIN32
21122289
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";

0 commit comments

Comments
 (0)