Skip to content

Commit d4b8475

Browse files
committed
[test] ConstructArray, DestructArray, Allocate and Deallocate
1 parent ef73c8f commit d4b8475

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
@@ -2027,6 +2027,49 @@ TEST(FunctionReflectionTest, Construct) {
20272027
clang_Interpreter_dispose(I);
20282028
}
20292029

2030+
// Test zero initialization of PODs and default initialization cases
2031+
TEST(FunctionReflectionTest, ConstructPOD) {
2032+
#ifdef EMSCRIPTEN
2033+
#if CLANG_VERSION_MAJOR < 20
2034+
GTEST_SKIP() << "Test fails for Emscipten builds";
2035+
#endif
2036+
#endif
2037+
if (llvm::sys::RunningOnValgrind())
2038+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2039+
#ifdef _WIN32
2040+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2041+
#endif
2042+
std::vector<const char*> interpreter_args = {"-include", "new"};
2043+
Cpp::CreateInterpreter(interpreter_args);
2044+
2045+
Interp->declare(R"(
2046+
namespace PODS {
2047+
struct SomePOD_B {
2048+
int fInt;
2049+
};
2050+
struct SomePOD_C {
2051+
int fInt;
2052+
double fDouble;
2053+
};
2054+
})");
2055+
2056+
auto *ns = Cpp::GetNamed("PODS");
2057+
Cpp::TCppScope_t scope = Cpp::GetNamed("SomePOD_B", ns);
2058+
EXPECT_TRUE(scope);
2059+
Cpp::TCppObject_t object = Cpp::Construct(scope);
2060+
EXPECT_TRUE(object != nullptr);
2061+
int* fInt = reinterpret_cast<int*>(reinterpret_cast<char*>(object));
2062+
EXPECT_TRUE(*fInt == 0);
2063+
2064+
scope = Cpp::GetNamed("SomePOD_C", ns);
2065+
EXPECT_TRUE(scope);
2066+
object = Cpp::Construct(scope);
2067+
EXPECT_TRUE(object);
2068+
auto* fDouble =
2069+
reinterpret_cast<double*>(reinterpret_cast<char*>(object) + sizeof(int));
2070+
EXPECT_EQ(*fDouble, 0.0);
2071+
}
2072+
20302073
// Test nested constructor calls
20312074
TEST(FunctionReflectionTest, ConstructNested) {
20322075
#ifdef EMSCRIPTEN
@@ -2090,6 +2133,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
20902133
output.clear();
20912134
}
20922135

2136+
TEST(FunctionReflectionTest, ConstructArray) {
2137+
#if defined(EMSCRIPTEN)
2138+
GTEST_SKIP() << "Test fails for Emscripten builds";
2139+
#endif
2140+
if (llvm::sys::RunningOnValgrind())
2141+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2142+
#ifdef _WIN32
2143+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2144+
#endif
2145+
#if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2146+
GTEST_SKIP() << "Test fails on Clang16 OS X";
2147+
#endif
2148+
2149+
Cpp::CreateInterpreter();
2150+
2151+
Interp->declare(R"(
2152+
#include <new>
2153+
extern "C" int printf(const char*,...);
2154+
class C {
2155+
int x;
2156+
C() {
2157+
x = 42;
2158+
printf("\nConstructor Executed\n");
2159+
}
2160+
};
2161+
)");
2162+
2163+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2164+
std::string output;
2165+
2166+
size_t a = 5; // Construct an array of 5 objects
2167+
void* where = Cpp::Allocate(scope, a); // operator new
2168+
2169+
testing::internal::CaptureStdout();
2170+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2171+
// Check for the value of x which should be at the start of the object.
2172+
EXPECT_TRUE(*(int*)where == 42);
2173+
// Check for the value of x in the second object
2174+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2175+
Cpp::SizeOf(scope));
2176+
EXPECT_TRUE(*obj == 42);
2177+
2178+
// Check for the value of x in the last object
2179+
obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2180+
(Cpp::SizeOf(scope) * 4));
2181+
EXPECT_TRUE(*obj == 42);
2182+
Cpp::Destruct(where, scope, /*withFree=*/false, 5);
2183+
Cpp::Deallocate(scope, where, 5);
2184+
output = testing::internal::GetCapturedStdout();
2185+
EXPECT_EQ(output,
2186+
"\nConstructor Executed\n\nConstructor Executed\n\nConstructor "
2187+
"Executed\n\nConstructor Executed\n\nConstructor Executed\n");
2188+
output.clear();
2189+
}
2190+
20932191
TEST(FunctionReflectionTest, Destruct) {
20942192
#ifdef EMSCRIPTEN
20952193
GTEST_SKIP() << "Test fails for Emscipten builds";
@@ -2147,6 +2245,85 @@ TEST(FunctionReflectionTest, Destruct) {
21472245
clang_Interpreter_dispose(I);
21482246
}
21492247

2248+
TEST(FunctionReflectionTest, DestructArray) {
2249+
#ifdef EMSCRIPTEN
2250+
GTEST_SKIP() << "Test fails for Emscipten builds";
2251+
#endif
2252+
if (llvm::sys::RunningOnValgrind())
2253+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2254+
2255+
#ifdef _WIN32
2256+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2257+
#endif
2258+
#if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2259+
GTEST_SKIP() << "Test fails on Clang16 OS X";
2260+
#endif
2261+
2262+
std::vector<const char*> interpreter_args = {"-include", "new"};
2263+
Cpp::CreateInterpreter(interpreter_args);
2264+
2265+
Interp->declare(R"(
2266+
#include <new>
2267+
extern "C" int printf(const char*,...);
2268+
class C {
2269+
int x;
2270+
C() {
2271+
printf("\nCtor Executed\n");
2272+
x = 42;
2273+
}
2274+
~C() {
2275+
printf("\nDestructor Executed\n");
2276+
}
2277+
};
2278+
)");
2279+
2280+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2281+
std::string output;
2282+
2283+
size_t a = 5; // Construct an array of 5 objects
2284+
void* where = Cpp::Allocate(scope, a); // operator new
2285+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2286+
2287+
// verify the array of objects has been constructed
2288+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2289+
Cpp::SizeOf(scope) * 4);
2290+
EXPECT_TRUE(*obj == 42);
2291+
2292+
testing::internal::CaptureStdout();
2293+
// destruct 3 out of 5 objects
2294+
Cpp::Destruct(where, scope, false, 3);
2295+
output = testing::internal::GetCapturedStdout();
2296+
2297+
EXPECT_EQ(
2298+
output,
2299+
"\nDestructor Executed\n\nDestructor Executed\n\nDestructor Executed\n");
2300+
output.clear();
2301+
testing::internal::CaptureStdout();
2302+
2303+
// destruct the rest
2304+
auto *new_head = reinterpret_cast<void*>(reinterpret_cast<char*>(where) +
2305+
(Cpp::SizeOf(scope) * 3));
2306+
Cpp::Destruct(new_head, scope, false, 2);
2307+
2308+
output = testing::internal::GetCapturedStdout();
2309+
EXPECT_EQ(output, "\nDestructor Executed\n\nDestructor Executed\n");
2310+
output.clear();
2311+
2312+
// deallocate since we call the destructor withFree = false
2313+
Cpp::Deallocate(scope, where, 5);
2314+
2315+
// perform the same withFree=true
2316+
where = Cpp::Allocate(scope, a);
2317+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a));
2318+
testing::internal::CaptureStdout();
2319+
// FIXME : This should work with the array of objects as well
2320+
// Cpp::Destruct(where, scope, true, 5);
2321+
Cpp::Destruct(where, scope, true);
2322+
output = testing::internal::GetCapturedStdout();
2323+
EXPECT_EQ(output, "\nDestructor Executed\n");
2324+
output.clear();
2325+
}
2326+
21502327
TEST(FunctionReflectionTest, UndoTest) {
21512328
#ifdef _WIN32
21522329
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";

0 commit comments

Comments
 (0)