Skip to content

Commit d90fe11

Browse files
committed
[test] ConstructArray, DestructArray, Allocate and Deallocate
1 parent eb843f2 commit d90fe11

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
@@ -2047,6 +2047,49 @@ TEST(FunctionReflectionTest, Construct) {
20472047
clang_Interpreter_dispose(I);
20482048
}
20492049

2050+
// Test zero initialization of PODs and default initialization cases
2051+
TEST(FunctionReflectionTest, ConstructPOD) {
2052+
#ifdef EMSCRIPTEN
2053+
#if CLANG_VERSION_MAJOR < 20
2054+
GTEST_SKIP() << "Test fails for Emscipten builds";
2055+
#endif
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+
std::vector<const char*> interpreter_args = {"-include", "new"};
2063+
Cpp::CreateInterpreter(interpreter_args);
2064+
2065+
Interp->declare(R"(
2066+
namespace PODS {
2067+
struct SomePOD_B {
2068+
int fInt;
2069+
};
2070+
struct SomePOD_C {
2071+
int fInt;
2072+
double fDouble;
2073+
};
2074+
})");
2075+
2076+
auto *ns = Cpp::GetNamed("PODS");
2077+
Cpp::TCppScope_t scope = Cpp::GetNamed("SomePOD_B", ns);
2078+
EXPECT_TRUE(scope);
2079+
Cpp::TCppObject_t object = Cpp::Construct(scope);
2080+
EXPECT_TRUE(object != nullptr);
2081+
int* fInt = reinterpret_cast<int*>(reinterpret_cast<char*>(object));
2082+
EXPECT_TRUE(*fInt == 0);
2083+
2084+
scope = Cpp::GetNamed("SomePOD_C", ns);
2085+
EXPECT_TRUE(scope);
2086+
object = Cpp::Construct(scope);
2087+
EXPECT_TRUE(object);
2088+
auto* fDouble =
2089+
reinterpret_cast<double*>(reinterpret_cast<char*>(object) + sizeof(int));
2090+
EXPECT_EQ(*fDouble, 0.0);
2091+
}
2092+
20502093
// Test nested constructor calls
20512094
TEST(FunctionReflectionTest, ConstructNested) {
20522095
#ifdef EMSCRIPTEN
@@ -2110,6 +2153,61 @@ TEST(FunctionReflectionTest, ConstructNested) {
21102153
output.clear();
21112154
}
21122155

2156+
TEST(FunctionReflectionTest, ConstructArray) {
2157+
#if defined(EMSCRIPTEN)
2158+
GTEST_SKIP() << "Test fails for Emscripten builds";
2159+
#endif
2160+
if (llvm::sys::RunningOnValgrind())
2161+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2162+
#ifdef _WIN32
2163+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2164+
#endif
2165+
#if defined(__APPLE__) && (CLANG_VERSION_MAJOR == 16)
2166+
GTEST_SKIP() << "Test fails on Clang16 OS X";
2167+
#endif
2168+
2169+
Cpp::CreateInterpreter();
2170+
2171+
Interp->declare(R"(
2172+
#include <new>
2173+
extern "C" int printf(const char*,...);
2174+
class C {
2175+
int x;
2176+
C() {
2177+
x = 42;
2178+
printf("\nConstructor Executed\n");
2179+
}
2180+
};
2181+
)");
2182+
2183+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2184+
std::string output;
2185+
2186+
size_t a = 5; // Construct an array of 5 objects
2187+
void* where = Cpp::Allocate(scope, a); // operator new
2188+
2189+
testing::internal::CaptureStdout();
2190+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2191+
// Check for the value of x which should be at the start of the object.
2192+
EXPECT_TRUE(*(int*)where == 42);
2193+
// Check for the value of x in the second object
2194+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2195+
Cpp::SizeOf(scope));
2196+
EXPECT_TRUE(*obj == 42);
2197+
2198+
// Check for the value of x in the last object
2199+
obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2200+
(Cpp::SizeOf(scope) * 4));
2201+
EXPECT_TRUE(*obj == 42);
2202+
Cpp::Destruct(where, scope, /*withFree=*/false, 5);
2203+
Cpp::Deallocate(scope, where, 5);
2204+
output = testing::internal::GetCapturedStdout();
2205+
EXPECT_EQ(output,
2206+
"\nConstructor Executed\n\nConstructor Executed\n\nConstructor "
2207+
"Executed\n\nConstructor Executed\n\nConstructor Executed\n");
2208+
output.clear();
2209+
}
2210+
21132211
TEST(FunctionReflectionTest, Destruct) {
21142212
#ifdef EMSCRIPTEN
21152213
GTEST_SKIP() << "Test fails for Emscipten builds";
@@ -2167,6 +2265,85 @@ TEST(FunctionReflectionTest, Destruct) {
21672265
clang_Interpreter_dispose(I);
21682266
}
21692267

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

0 commit comments

Comments
 (0)