Skip to content

Commit b6d01ac

Browse files
committed
[test] ConstructArray, DestructArray, Allocate and Deallocate
1 parent 822a38a commit b6d01ac

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,58 @@ TEST(FunctionReflectionTest, ConstructNested) {
19591959
output.clear();
19601960
}
19611961

1962+
TEST(FunctionReflectionTest, ConstructArray) {
1963+
#if defined(EMSCRIPTEN) && (CLANG_VERSION_MAJOR < 20)
1964+
GTEST_SKIP() << "Test fails for LLVM < 20 Emscripten builds";
1965+
#endif
1966+
if (llvm::sys::RunningOnValgrind())
1967+
GTEST_SKIP() << "XFAIL due to Valgrind report";
1968+
#ifdef _WIN32
1969+
GTEST_SKIP() << "Disabled on Windows. Needs fixing.";
1970+
#endif
1971+
1972+
Cpp::CreateInterpreter();
1973+
1974+
Interp->declare(R"(
1975+
#include <new>
1976+
extern "C" int printf(const char*,...);
1977+
class C {
1978+
int x;
1979+
C() {
1980+
x = 42;
1981+
printf("\nConstructor Executed\n");
1982+
}
1983+
};
1984+
)");
1985+
1986+
Cpp::TCppScope_t scope = Cpp::GetNamed("C");
1987+
std::string output;
1988+
1989+
size_t a = 5; // Construct an array of 5 objects
1990+
void* where = Cpp::Allocate(scope, a); // operator new
1991+
1992+
testing::internal::CaptureStdout();
1993+
EXPECT_TRUE(where == Cpp::Construct(scope, where, a)); // placement new
1994+
// Check for the value of x which should be at the start of the object.
1995+
EXPECT_TRUE(*(int*)where == 42);
1996+
// Check for the value of x in the second object
1997+
int* obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
1998+
Cpp::SizeOf(scope));
1999+
EXPECT_TRUE(*obj == 42);
2000+
2001+
// Check for the value of x in the last object
2002+
obj = reinterpret_cast<int*>(reinterpret_cast<char*>(where) +
2003+
Cpp::SizeOf(scope) * 4);
2004+
EXPECT_TRUE(*obj == 42);
2005+
Cpp::Destruct(where, scope, /*withFree=*/false, 5);
2006+
Cpp::Deallocate(scope, where, 5);
2007+
output = testing::internal::GetCapturedStdout();
2008+
EXPECT_EQ(output,
2009+
"\nConstructor Executed\n\nConstructor Executed\n\nConstructor "
2010+
"Executed\n\nConstructor Executed\n\nConstructor Executed\n");
2011+
output.clear();
2012+
}
2013+
19622014
TEST(FunctionReflectionTest, Destruct) {
19632015
#ifdef EMSCRIPTEN
19642016
GTEST_SKIP() << "Test fails for Emscipten builds";
@@ -2016,6 +2068,82 @@ TEST(FunctionReflectionTest, Destruct) {
20162068
clang_Interpreter_dispose(I);
20172069
}
20182070

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

0 commit comments

Comments
 (0)