Skip to content

Commit 0160cf1

Browse files
committed
Add tests for ConstructArray, DestructArray, Allocate and Deallocate
1 parent bfedc8e commit 0160cf1

File tree

1 file changed

+123
-3
lines changed

1 file changed

+123
-3
lines changed

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 123 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,55 @@ 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 =
1989+
reinterpret_cast<int*>(reinterpret_cast<char*>(where) + 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) + Cpp::SizeOf(scope) * 4);
1994+
EXPECT_TRUE(*obj == 42);
1995+
Cpp::Destruct(where, scope, /*withFree=*/false, 5);
1996+
Cpp::Deallocate(scope, where, 5);
1997+
output = testing::internal::GetCapturedStdout();
1998+
EXPECT_EQ(output, "\nConstructor Executed\n\nConstructor Executed\n\nConstructor Executed\n\nConstructor Executed\n\nConstructor Executed\n");
1999+
output.clear();
2000+
}
2001+
19532002
TEST(FunctionReflectionTest, Destruct) {
19542003
#ifdef EMSCRIPTEN
19552004
GTEST_SKIP() << "Test fails for Emscipten builds";
@@ -1997,7 +2046,7 @@ TEST(FunctionReflectionTest, Destruct) {
19972046
testing::internal::CaptureStdout();
19982047
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
19992048
auto scope_c = make_scope(static_cast<clang::Decl*>(scope), I);
2000-
auto object_c = clang_construct(scope_c, nullptr);
2049+
auto object_c = clang_construct(scope_c, nullptr, 0UL);
20012050
clang_destruct(object_c, scope_c, true);
20022051
output = testing::internal::GetCapturedStdout();
20032052
EXPECT_EQ(output, "Destructor Executed");
@@ -2007,6 +2056,77 @@ TEST(FunctionReflectionTest, Destruct) {
20072056
clang_Interpreter_dispose(I);
20082057
}
20092058

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

0 commit comments

Comments
 (0)