Skip to content

Commit

Permalink
Run API tests against the sandbox runtime (facebook#1248)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#1248

X-link: facebook/react-native#42264

Add a buck build for the sandbox, and run our existing API tests
against it.

Reviewed By: avp

Differential Revision: D48086019

fbshipit-source-id: 2ee2eca93e27557d2609eaaec2fce3218d8b873f
  • Loading branch information
neildhar authored and facebook-github-bot committed Jan 16, 2024
1 parent 7b554c7 commit 005897d
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 15 deletions.
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ jobs:
name: Build linux CLI
command: |
cmake -S hermes -B build_hdb -DHERMES_STATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DCMAKE_CXX_FLAGS=-s -DCMAKE_C_FLAGS=-s \
-DCMAKE_CXX_FLAGS=-s -DCMAKE_C_FLAGS=-s \
-DCMAKE_EXE_LINKER_FLAGS="-Wl,--whole-archive -lpthread -Wl,--no-whole-archive"
cmake -S hermes -B build -DHERMES_STATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DCMAKE_CXX_FLAGS=-s -DCMAKE_C_FLAGS=-s \
-DCMAKE_CXX_FLAGS=-s -DCMAKE_C_FLAGS=-s \
-DCMAKE_EXE_LINKER_FLAGS="-Wl,--whole-archive -lpthread -Wl,--no-whole-archive" \
-DHERMES_ENABLE_DEBUGGER=False
cmake --build build_hdb --target hdb
Expand Down
9 changes: 7 additions & 2 deletions API/jsi/jsi/test/testlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1444,8 +1444,13 @@ TEST_P(JSITest, ArrayBufferSizeTest) {
auto ab =
eval("var x = new ArrayBuffer(10); x").getObject(rt).getArrayBuffer(rt);
EXPECT_EQ(ab.size(rt), 10);
// Ensure we can safely write some data to the buffer.
memset(ab.data(rt), 0xab, 10);

try {
// Ensure we can safely write some data to the buffer.
memset(ab.data(rt), 0xab, 10);
} catch (const JSINativeException& ex) {
// data() is unimplemented by some runtimes, ignore such failures.
}

// Ensure that setting the byteLength property does not change the length.
eval("Object.defineProperty(x, 'byteLength', {value: 20})");
Expand Down
44 changes: 35 additions & 9 deletions unittests/API/APITest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <hermes/Public/JSOutOfMemoryError.h>
#include <hermes/VM/TimeLimitMonitor.h>
#include <hermes/hermes.h>
#include <hermes_sandbox/HermesSandboxRuntime.h>
#include <jsi/instrumentation.h>
#include <jsi/test/testlib.h>

Expand Down Expand Up @@ -61,6 +62,20 @@ class HermesRuntimeTest : public ::testing::TestWithParam<RuntimeFactory>,
public HermesRuntimeTestBase {
public:
HermesRuntimeTest() : HermesRuntimeTestBase(GetParam()()) {}

/// Evaluate the given buffer containing either source or bytecode in the
/// runtime and return the result.
Value evaluateSourceOrBytecode(
const std::shared_ptr<const Buffer> &buf,
const std::string &sourceURL) {
// HermesSandboxRuntime does not permit bytecode in evaluateJavaScript, so
// check for it and call the appropriate method.
if (auto *sbrt = dynamic_cast<HermesSandboxRuntime *>(rt.get()))
if (HermesSandboxRuntime::isHermesBytecode(buf->data(), buf->size()))
return sbrt->evaluateHermesBytecode(buf, sourceURL);

return rt->evaluateJavaScript(buf, sourceURL);
}
};

// In JSC there's a bug where host functions are always ran with a this in
Expand Down Expand Up @@ -109,9 +124,12 @@ TEST_P(HermesRuntimeTest, ArrayBufferTest) {
auto arrayBuffer = object.getArrayBuffer(*rt);
EXPECT_EQ(arrayBuffer.size(*rt), 16);

int32_t *buffer = reinterpret_cast<int32_t *>(arrayBuffer.data(*rt));
EXPECT_EQ(buffer[0], 1234);
EXPECT_EQ(buffer[1], 5678);
// HermesSandboxRuntime does not support getting the ArrayBuffer's data.
if (!dynamic_cast<HermesSandboxRuntime *>(rt.get())) {
int32_t *buffer = reinterpret_cast<int32_t *>(arrayBuffer.data(*rt));
EXPECT_EQ(buffer[0], 1234);
EXPECT_EQ(buffer[1], 5678);
}
}

class HermesRuntimeTestMethodsTest : public HermesRuntimeCustomConfigTest {
Expand Down Expand Up @@ -201,15 +219,16 @@ TEST_P(HermesRuntimeTest, BytecodeTest) {
ASSERT_TRUE(hermes::compileJS("x = 1", bytecode));
EXPECT_TRUE(HermesRuntime::isHermesBytecode(
reinterpret_cast<const uint8_t *>(bytecode.data()), bytecode.size()));
rt->evaluateJavaScript(
evaluateSourceOrBytecode(
std::unique_ptr<StringBuffer>(new StringBuffer(bytecode)), "");
EXPECT_EQ(rt->global().getProperty(*rt, "x").getNumber(), 1);

EXPECT_EQ(HermesRuntime::getBytecodeVersion(), hermes::hbc::BYTECODE_VERSION);
}

TEST_P(HermesRuntimeTest, PreparedJavaScriptBytecodeTest) {
eval("var q = 0;");
TEST(HermesRuntimePreparedJavaScriptTest, BytecodeTest) {
auto rt = makeHermesRuntime();
rt->evaluateJavaScript(std::make_unique<StringBuffer>("var q = 0;"), "");
std::string bytecode;
ASSERT_TRUE(hermes::compileJS("q++", bytecode));
auto prep =
Expand Down Expand Up @@ -270,7 +289,7 @@ c.doSomething(a, 15);
EXPECT_TRUE(HermesRuntime::isHermesBytecode(
reinterpret_cast<const uint8_t *>(bytecode.data()), bytecode.size()));
try {
rt->evaluateJavaScript(
evaluateSourceOrBytecode(
std::unique_ptr<StringBuffer>(new StringBuffer(bytecode)), "");
FAIL() << "Expected JSIException";
} catch (const facebook::jsi::JSIException &err) {
Expand Down Expand Up @@ -302,7 +321,7 @@ var i = 0;
std::string bytecode;
ASSERT_TRUE(hermes::compileJS(code, bytecode));
auto ret =
rt->evaluateJavaScript(std::make_unique<StringBuffer>(bytecode), "");
evaluateSourceOrBytecode(std::make_unique<StringBuffer>(bytecode), "");
ASSERT_EQ(ret.asNumber(), 5.0);
}

Expand Down Expand Up @@ -522,6 +541,13 @@ JSON.stringify(JSON.parse(out).callstack.map(x => x.SourceLocation));
}

TEST_P(HermesRuntimeTest, SpreadHostObjectWithOwnProperties) {
// TODO(T174477667): Understand why this test fails for the sandbox under
// MSVC.
#ifdef _MSC_VER
if (dynamic_cast<HermesSandboxRuntime *>(rt.get()))
return;
#endif

class HostObjectWithPropertyNames : public HostObject {
std::vector<PropNameID> getPropertyNames(Runtime &rt) override {
return PropNameID::names(rt, "prop1", "1", "2", "prop2", "3");
Expand Down Expand Up @@ -695,7 +721,7 @@ throws1();
for (const std::string &code : {sourceCode, bytecode}) {
bool caught = false;
try {
rt->evaluateJavaScript(std::make_unique<StringBuffer>(code), sourceURL);
evaluateSourceOrBytecode(std::make_unique<StringBuffer>(code), sourceURL);
} catch (facebook::jsi::JSError &err) {
caught = true;
EXPECT_TRUE(err.getStack().find(sourceURL) != std::string::npos)
Expand Down
4 changes: 3 additions & 1 deletion unittests/API/APITestFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <hermes/hermes.h>
#include <hermes_abi/HermesABIRuntimeWrapper.h>
#include <hermes_abi/hermes_vtable.h>
#include <hermes_sandbox/HermesSandboxRuntime.h>
#include <jsi/test/testlib.h>
#include <jsi/threadsafe.h>

Expand All @@ -20,7 +21,8 @@ std::vector<RuntimeFactory> runtimeGenerators() {
return {
[] { return makeHermesRuntime(); },
[] { return makeThreadSafeHermesRuntime(); },
[] { return makeHermesABIRuntimeWrapper(get_hermes_abi_vtable()); }};
[] { return makeHermesABIRuntimeWrapper(get_hermes_abi_vtable()); },
[] { return makeHermesSandboxRuntime(); }};
}

} // namespace jsi
Expand Down
3 changes: 2 additions & 1 deletion unittests/API/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ set(LLVM_ENABLE_RTTI ON)

add_hermes_unittest(APITests ${APITestsSources})

target_link_libraries(APITests libhermes compileJS SegmentTestCompile traceInterpreter timerStats hermesABIRuntimeWrapper hermesabi)
target_link_libraries(APITests libhermes compileJS SegmentTestCompile traceInterpreter
timerStats hermesABIRuntimeWrapper hermesabi hermesSandboxRuntime)

add_hermes_unittest(APILeanTests APILeanTest.cpp)
target_link_libraries(APILeanTests libhermes_lean jsi)

0 comments on commit 005897d

Please sign in to comment.