Skip to content

Commit 624bfb1

Browse files
committed
Add tests for ConstructArray, DestructArray, Allocate and Deallocate
1 parent 6c64011 commit 624bfb1

File tree

1 file changed

+130
-3
lines changed

1 file changed

+130
-3
lines changed

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 130 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,7 +1462,7 @@ TEST(FunctionReflectionTest, JitCallAdvanced) {
14621462
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
14631463
auto S = clang_getDefaultConstructor(make_scope(Decls[0], I));
14641464
void* object_c = nullptr;
1465-
clang_invoke(S, &object_c, nullptr, 0, nullptr);
1465+
clang_invoke(S, &object_c, nullptr, 0, 0UL, nullptr);
14661466
EXPECT_TRUE(object_c) << "Failed to call the ctor.";
14671467
clang_destruct(object_c, make_scope(Decls[1], I), true);
14681468
// Clean up resources
@@ -1874,7 +1874,7 @@ TEST(FunctionReflectionTest, Construct) {
18741874
testing::internal::CaptureStdout();
18751875
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
18761876
auto scope_c = make_scope(static_cast<clang::Decl*>(scope), I);
1877-
auto object_c = clang_construct(scope_c, nullptr);
1877+
auto object_c = clang_construct(scope_c, nullptr, 0UL);
18781878
EXPECT_TRUE(object_c != nullptr);
18791879
output = testing::internal::GetCapturedStdout();
18801880
EXPECT_EQ(output, "Constructor Executed");
@@ -1950,6 +1950,58 @@ TEST(FunctionReflectionTest, ConstructNested) {
19501950
output.clear();
19511951
}
19521952

1953+
TEST(FunctionReflectionTest, ConstructArray) {
1954+
#if defined(EMSCRIPTEN) && (CLANG_VERSION_MAJOR < 20)
1955+
GTEST_SKIP() << "Test fails for LLVM < 20 Emscripten builds";
1956+
#endif
1957+
if (llvm::sys::RunningOnValgrind())
1958+
GTEST_SKIP() << "XFAIL due to Valgrind report";
1959+
#ifdef _WIN32
1960+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
1961+
#endif
1962+
1963+
Cpp::CreateInterpreter();
1964+
1965+
Interp->declare(R"(
1966+
#include <new>
1967+
extern "C" int printf(const char*,...);
1968+
class C {
1969+
int x;
1970+
C() {
1971+
x = 42;
1972+
printf("\nConstructor Executed\n");
1973+
}
1974+
};
1975+
)");
1976+
1977+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
1978+
std::string output;
1979+
1980+
size_t a = 5; // Construct an array of 5 objects
1981+
void* where = Cpp::Allocate(scope, a); // operator new
1982+
1983+
testing::internal::CaptureStdout();
1984+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
1985+
// Check for the value of x which should be at the start of the object.
1986+
EXPECT_TRUE(*(int*)where == 42);
1987+
// Check for the value of x in the second object
1988+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
1989+
Cpp::SizeOf(scope));
1990+
EXPECT_TRUE(*obj == 42);
1991+
1992+
// Check for the value of x in the last object
1993+
obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
1994+
Cpp::SizeOf(scope) * 4);
1995+
EXPECT_TRUE(*obj == 42);
1996+
Cpp::Destruct(where, scope, /*withFree=*/false, 5);
1997+
Cpp::Deallocate(scope, where, 5);
1998+
output = testing::internal::GetCapturedStdout();
1999+
EXPECT_EQ(output,
2000+
"\nConstructor Executed\n\nConstructor Executed\n\nConstructor "
2001+
"Executed\n\nConstructor Executed\n\nConstructor Executed\n");
2002+
output.clear();
2003+
}
2004+
19532005
TEST(FunctionReflectionTest, Destruct) {
19542006
#ifdef EMSCRIPTEN
19552007
GTEST_SKIP() << "Test fails for Emscipten builds";
@@ -1997,7 +2049,7 @@ TEST(FunctionReflectionTest, Destruct) {
19972049
testing::internal::CaptureStdout();
19982050
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
19992051
auto scope_c = make_scope(static_cast<clang::Decl*>(scope), I);
2000-
auto object_c = clang_construct(scope_c, nullptr);
2052+
auto object_c = clang_construct(scope_c, nullptr, 0UL);
20012053
clang_destruct(object_c, scope_c, true);
20022054
output = testing::internal::GetCapturedStdout();
20032055
EXPECT_EQ(output, "Destructor Executed");
@@ -2007,6 +2059,81 @@ TEST(FunctionReflectionTest, Destruct) {
20072059
clang_Interpreter_dispose(I);
20082060
}
20092061

2062+
TEST(FunctionReflectionTest, DestructArray) {
2063+
#ifdef EMSCRIPTEN
2064+
GTEST_SKIP() << "Test fails for Emscipten builds";
2065+
#endif
2066+
if (llvm::sys::RunningOnValgrind())
2067+
GTEST_SKIP() << "XFAIL due to Valgrind report";
2068+
2069+
#ifdef _WIN32
2070+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
2071+
#endif
2072+
2073+
std::vector<const char*> interpreter_args = {"-include", "new"};
2074+
Cpp::CreateInterpreter(interpreter_args);
2075+
2076+
Interp->declare(R"(
2077+
#include <new>
2078+
extern "C" int printf(const char*,...);
2079+
class C {
2080+
int x;
2081+
C() {
2082+
x = 42;
2083+
}
2084+
~C() {
2085+
printf("\nDestructor Executed\n");
2086+
}
2087+
};
2088+
)");
2089+
2090+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
2091+
std::string output;
2092+
2093+
size_t a = 5; // Construct an array of 5 objects
2094+
void* where = Cpp::Allocate(scope, a); // operator new
2095+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
2096+
2097+
// verify the array of objects has been constructed
2098+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2099+
Cpp::SizeOf(scope) * 4);
2100+
EXPECT_TRUE(*obj == 42);
2101+
2102+
testing::internal::CaptureStdout();
2103+
// destruct 3 out of 5 objects
2104+
Cpp::Destruct(where, scope, false, 3);
2105+
output = testing::internal::GetCapturedStdout();
2106+
2107+
EXPECT_EQ(
2108+
output,
2109+
"\nDestructor Executed\n\nDestructor Executed\n\nDestructor Executed\n");
2110+
output.clear();
2111+
testing::internal::CaptureStdout();
2112+
2113+
// destruct the rest
2114+
auto new_head = reinterpret_cast<void*>(reinterpret_cast<char*>(where) +
2115+
Cpp::SizeOf(scope) * 3);
2116+
Cpp::Destruct(new_head, scope, false, 2);
2117+
2118+
output = testing::internal::GetCapturedStdout();
2119+
EXPECT_EQ(output, "\nDestructor Executed\n\nDestructor Executed\n");
2120+
output.clear();
2121+
2122+
// deallocate since we call the destructor withFree = false
2123+
Cpp::Deallocate(scope, where, 5);
2124+
2125+
// perform the same withFree=true
2126+
where = Cpp::Allocate(scope, a);
2127+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a));
2128+
testing::internal::CaptureStdout();
2129+
// FIXME : This should work with the array of objects as well
2130+
// Cpp::Destruct(where, scope, true, 5);
2131+
Cpp::Destruct(where, scope, true);
2132+
output = testing::internal::GetCapturedStdout();
2133+
EXPECT_EQ(output, "\nDestructor Executed\n");
2134+
output.clear();
2135+
}
2136+
20102137
TEST(FunctionReflectionTest, UndoTest) {
20112138
#ifdef _WIN32
20122139
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";

0 commit comments

Comments
 (0)