From c7ce450ee97497944756b6af60034521953431fc Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Fri, 10 Aug 2018 15:09:28 -0400 Subject: Rename mock_runtime_test to libdeno_test Fixes #465 --- BUILD.gn | 18 ++--- js/libdeno_test.js | 147 ++++++++++++++++++++++++++++++++++ js/mock_runtime.js | 147 ---------------------------------- src/from_snapshot.cc | 6 +- src/libdeno_test.cc | 201 +++++++++++++++++++++++++++++++++++++++++++++++ src/mock_runtime_test.cc | 201 ----------------------------------------------- 6 files changed, 360 insertions(+), 360 deletions(-) create mode 100644 js/libdeno_test.js delete mode 100644 js/mock_runtime.js create mode 100644 src/libdeno_test.cc delete mode 100644 src/mock_runtime_test.cc diff --git a/BUILD.gn b/BUILD.gn index 32d1b527c..e989ed908 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -161,7 +161,7 @@ static_library("libdeno") { configs += [ ":deno_config" ] } -# Only functionality needed for mock_runtime_test and snapshot_creator +# Only functionality needed for libdeno_test and snapshot_creator # In particular no flatbuffers, no assets, no rust, no msg handlers. # Because snapshots are slow, it's important that snapshot_creator's # dependencies are minimal. @@ -184,17 +184,17 @@ v8_source_set("deno_base_test") { sources = [ "src/file_util_test.cc", "src/from_snapshot.cc", - "src/mock_runtime_test.cc", + "src/libdeno_test.cc", ] inputs = [ - "$target_gen_dir/snapshot_mock_runtime.bin", + "$target_gen_dir/snapshot_libdeno_test.bin", ] deps = [ - ":create_snapshot_mock_runtime", + ":create_snapshot_libdeno_test", ":deno_base", "//testing/gtest:gtest", ] - defines = [ "DENO_MOCK_RUNTIME" ] + defines = [ "LIBDENO_TEST" ] configs = [ ":deno_config" ] } @@ -353,7 +353,7 @@ rust_flatbuffer("msg_rs") { ] } -# Generates $target_gen_dir/snapshot_deno.cc +# Generates $target_gen_dir/snapshot_deno.bin create_snapshot("deno") { js = "$target_gen_dir/bundle/main.js" source_map = "$target_gen_dir/bundle/main.js.map" @@ -362,8 +362,8 @@ create_snapshot("deno") { ] } -# Generates $target_gen_dir/snapshot_mock_runtime.cc -create_snapshot("mock_runtime") { +# Generates $target_gen_dir/snapshot_libdeno_test.bin +create_snapshot("libdeno_test") { testonly = true - js = "js/mock_runtime.js" + js = "js/libdeno_test.js" } diff --git a/js/libdeno_test.js b/js/libdeno_test.js new file mode 100644 index 000000000..10905494c --- /dev/null +++ b/js/libdeno_test.js @@ -0,0 +1,147 @@ +// Copyright 2018 the Deno authors. All rights reserved. MIT license. + +// A simple runtime that doesn't involve typescript or protobufs to test +// libdeno. Invoked by libdeno_test.cc + +const global = this; + +function assert(cond) { + if (!cond) throw Error("libdeno_test.js assert failed"); +} + +global.CanCallFunction = () => { + libdeno.print("Hello world from foo"); + return "foo"; +}; + +// This object is created to test snapshotting. +// See DeserializeInternalFieldsCallback and SerializeInternalFieldsCallback. +const snapshotted = new Uint8Array([1, 3, 3, 7]); + +global.TypedArraySnapshots = () => { + assert(snapshotted[0] === 1); + assert(snapshotted[1] === 3); + assert(snapshotted[2] === 3); + assert(snapshotted[3] === 7); +}; + +global.SendSuccess = () => { + libdeno.recv(msg => { + libdeno.print("SendSuccess: ok"); + }); +}; + +global.SendWrongByteLength = () => { + libdeno.recv(msg => { + assert(msg.byteLength === 3); + }); +}; + +global.RecvReturnEmpty = () => { + const m1 = new Uint8Array("abc".split("").map(c => c.charCodeAt(0))); + const m2 = m1.slice(); + const r1 = libdeno.send(m1); + assert(r1 == null); + const r2 = libdeno.send(m2); + assert(r2 == null); +}; + +global.RecvReturnBar = () => { + const m = new Uint8Array("abc".split("").map(c => c.charCodeAt(0))); + const r = libdeno.send(m); + assert(r instanceof Uint8Array); + assert(r.byteLength === 3); + const rstr = String.fromCharCode(...r); + assert(rstr === "bar"); +}; + +global.DoubleRecvFails = () => { + // libdeno.recv is an internal function and should only be called once from the + // runtime. + libdeno.recv((channel, msg) => assert(false)); + libdeno.recv((channel, msg) => assert(false)); +}; + +global.SendRecvSlice = () => { + const abLen = 1024; + let buf = new Uint8Array(abLen); + for (let i = 0; i < 5; i++) { + // Set first and last byte, for verification by the native side. + buf[0] = 100 + i; + buf[buf.length - 1] = 100 - i; + // On the native side, the slice is shortened by 19 bytes. + buf = libdeno.send(buf); + assert(buf.byteOffset === i * 11); + assert(buf.byteLength === abLen - i * 30 - 19); + assert(buf.buffer.byteLength == abLen); + // Look for values written by the backend. + assert(buf[0] === 200 + i); + assert(buf[buf.length - 1] === 200 - i); + // On the JS side, the start of the slice is moved up by 11 bytes. + buf = buf.subarray(11); + assert(buf.byteOffset === (i + 1) * 11); + assert(buf.byteLength === abLen - (i + 1) * 30); + } +}; + +global.JSSendArrayBufferViewTypes = () => { + // Test that ArrayBufferView slices are transferred correctly. + // Send Uint8Array. + const ab1 = new ArrayBuffer(4321); + const u8 = new Uint8Array(ab1, 2468, 1000); + u8[0] = 1; + libdeno.send(u8); + // Send Uint32Array. + const ab2 = new ArrayBuffer(4321); + const u32 = new Uint32Array(ab2, 2468, 1000 / Uint32Array.BYTES_PER_ELEMENT); + u32[0] = 0x02020202; + libdeno.send(u32); + // Send DataView. + const ab3 = new ArrayBuffer(4321); + const dv = new DataView(ab3, 2468, 1000); + dv.setUint8(0, 3); + libdeno.send(dv); +}; + +global.JSSendNeutersBuffer = () => { + // Buffer should be neutered after transferring it to the native side. + const u8 = new Uint8Array([42]); + assert(u8.byteLength === 1); + assert(u8.buffer.byteLength === 1); + assert(u8[0] === 42); + const r = libdeno.send(u8); + assert(u8.byteLength === 0); + assert(u8.buffer.byteLength === 0); + assert(u8[0] === undefined); +}; + +// The following join has caused SnapshotBug to segfault when using kKeep. +[].join(""); + +global.SnapshotBug = () => { + assert("1,2,3" === String([1, 2, 3])); +}; + +global.ErrorHandling = () => { + global.onerror = (message, source, line, col, error) => { + libdeno.print(`line ${line} col ${col}`); + assert("ReferenceError: notdefined is not defined" === message); + assert(source === "helloworld.js"); + assert(line === 3); + assert(col === 1); + assert(error instanceof Error); + libdeno.send(new Uint8Array([42])); + }; + eval("\n\n notdefined()\n//# sourceURL=helloworld.js"); +}; + +global.SendNullAllocPtr = () => { + libdeno.recv(msg => { + assert(msg instanceof Uint8Array); + assert(msg.byteLength === 4); + assert(msg[0] === "a".charCodeAt(0)); + assert(msg[1] === "b".charCodeAt(0)); + assert(msg[2] === "c".charCodeAt(0)); + assert(msg[3] === "d".charCodeAt(0)); + }); +}; diff --git a/js/mock_runtime.js b/js/mock_runtime.js deleted file mode 100644 index 34f78479e..000000000 --- a/js/mock_runtime.js +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2018 the Deno authors. All rights reserved. MIT license. - -// A simple runtime that doesn't involve typescript or protobufs to test -// libdeno. Invoked by mock_runtime_test.cc - -const global = this; - -function assert(cond) { - if (!cond) throw Error("mock_runtime.js assert failed"); -} - -global.CanCallFunction = () => { - libdeno.print("Hello world from foo"); - return "foo"; -}; - -// This object is created to test snapshotting. -// See DeserializeInternalFieldsCallback and SerializeInternalFieldsCallback. -const snapshotted = new Uint8Array([1, 3, 3, 7]); - -global.TypedArraySnapshots = () => { - assert(snapshotted[0] === 1); - assert(snapshotted[1] === 3); - assert(snapshotted[2] === 3); - assert(snapshotted[3] === 7); -}; - -global.SendSuccess = () => { - libdeno.recv(msg => { - libdeno.print("SendSuccess: ok"); - }); -}; - -global.SendWrongByteLength = () => { - libdeno.recv(msg => { - assert(msg.byteLength === 3); - }); -}; - -global.RecvReturnEmpty = () => { - const m1 = new Uint8Array("abc".split("").map(c => c.charCodeAt(0))); - const m2 = m1.slice(); - const r1 = libdeno.send(m1); - assert(r1 == null); - const r2 = libdeno.send(m2); - assert(r2 == null); -}; - -global.RecvReturnBar = () => { - const m = new Uint8Array("abc".split("").map(c => c.charCodeAt(0))); - const r = libdeno.send(m); - assert(r instanceof Uint8Array); - assert(r.byteLength === 3); - const rstr = String.fromCharCode(...r); - assert(rstr === "bar"); -}; - -global.DoubleRecvFails = () => { - // libdeno.recv is an internal function and should only be called once from the - // runtime. - libdeno.recv((channel, msg) => assert(false)); - libdeno.recv((channel, msg) => assert(false)); -}; - -global.SendRecvSlice = () => { - const abLen = 1024; - let buf = new Uint8Array(abLen); - for (let i = 0; i < 5; i++) { - // Set first and last byte, for verification by the native side. - buf[0] = 100 + i; - buf[buf.length - 1] = 100 - i; - // On the native side, the slice is shortened by 19 bytes. - buf = libdeno.send(buf); - assert(buf.byteOffset === i * 11); - assert(buf.byteLength === abLen - i * 30 - 19); - assert(buf.buffer.byteLength == abLen); - // Look for values written by the backend. - assert(buf[0] === 200 + i); - assert(buf[buf.length - 1] === 200 - i); - // On the JS side, the start of the slice is moved up by 11 bytes. - buf = buf.subarray(11); - assert(buf.byteOffset === (i + 1) * 11); - assert(buf.byteLength === abLen - (i + 1) * 30); - } -}; - -global.JSSendArrayBufferViewTypes = () => { - // Test that ArrayBufferView slices are transferred correctly. - // Send Uint8Array. - const ab1 = new ArrayBuffer(4321); - const u8 = new Uint8Array(ab1, 2468, 1000); - u8[0] = 1; - libdeno.send(u8); - // Send Uint32Array. - const ab2 = new ArrayBuffer(4321); - const u32 = new Uint32Array(ab2, 2468, 1000 / Uint32Array.BYTES_PER_ELEMENT); - u32[0] = 0x02020202; - libdeno.send(u32); - // Send DataView. - const ab3 = new ArrayBuffer(4321); - const dv = new DataView(ab3, 2468, 1000); - dv.setUint8(0, 3); - libdeno.send(dv); -}; - -global.JSSendNeutersBuffer = () => { - // Buffer should be neutered after transferring it to the native side. - const u8 = new Uint8Array([42]); - assert(u8.byteLength === 1); - assert(u8.buffer.byteLength === 1); - assert(u8[0] === 42); - const r = libdeno.send(u8); - assert(u8.byteLength === 0); - assert(u8.buffer.byteLength === 0); - assert(u8[0] === undefined); -}; - -// The following join has caused SnapshotBug to segfault when using kKeep. -[].join(""); - -global.SnapshotBug = () => { - assert("1,2,3" === String([1, 2, 3])); -}; - -global.ErrorHandling = () => { - global.onerror = (message, source, line, col, error) => { - libdeno.print(`line ${line} col ${col}`); - assert("ReferenceError: notdefined is not defined" === message); - assert(source === "helloworld.js"); - assert(line === 3); - assert(col === 1); - assert(error instanceof Error); - libdeno.send(new Uint8Array([42])); - }; - eval("\n\n notdefined()\n//# sourceURL=helloworld.js"); -}; - -global.SendNullAllocPtr = () => { - libdeno.recv(msg => { - assert(msg instanceof Uint8Array); - assert(msg.byteLength === 4); - assert(msg[0] === "a".charCodeAt(0)); - assert(msg[1] === "b".charCodeAt(0)); - assert(msg[2] === "c".charCodeAt(0)); - assert(msg[3] === "d".charCodeAt(0)); - }); -}; diff --git a/src/from_snapshot.cc b/src/from_snapshot.cc index 2575ec32f..bcd215f82 100644 --- a/src/from_snapshot.cc +++ b/src/from_snapshot.cc @@ -12,9 +12,9 @@ extern const char deno_snapshot_start asm("deno_snapshot_start"); extern const char deno_snapshot_end asm("deno_snapshot_end"); -#ifdef DENO_MOCK_RUNTIME +#ifdef LIBDENO_TEST asm(".data\n" - "deno_snapshot_start: .incbin \"gen/snapshot_mock_runtime.bin\"\n" + "deno_snapshot_start: .incbin \"gen/snapshot_libdeno_test.bin\"\n" "deno_snapshot_end:\n" ".globl deno_snapshot_start;\n" ".globl deno_snapshot_end;"); @@ -24,7 +24,7 @@ asm(".data\n" "deno_snapshot_end:\n" ".globl deno_snapshot_start;\n" ".globl deno_snapshot_end;"); -#endif // DENO_MOCK_RUNTIME +#endif // LIBDENO_TEST namespace deno { diff --git a/src/libdeno_test.cc b/src/libdeno_test.cc new file mode 100644 index 000000000..4675e4d7b --- /dev/null +++ b/src/libdeno_test.cc @@ -0,0 +1,201 @@ +// Copyright 2018 the Deno authors. All rights reserved. MIT license. +#include "testing/gtest/include/gtest/gtest.h" + +#include "deno.h" + +TEST(LibDenoTest, InitializesCorrectly) { + Deno* d = deno_new(nullptr, nullptr); + EXPECT_TRUE(deno_execute(d, "a.js", "1 + 2")); + deno_delete(d); +} + +TEST(LibDenoTest, CanCallFunction) { + Deno* d = deno_new(nullptr, nullptr); + EXPECT_TRUE(deno_execute(d, "a.js", + "if (CanCallFunction() != 'foo') throw Error();")); + deno_delete(d); +} + +TEST(LibDenoTest, ErrorsCorrectly) { + Deno* d = deno_new(nullptr, nullptr); + EXPECT_FALSE(deno_execute(d, "a.js", "throw Error()")); + deno_delete(d); +} + +deno_buf strbuf(const char* str) { + auto len = strlen(str); + + deno_buf buf; + buf.alloc_ptr = reinterpret_cast(strdup(str)); + buf.alloc_len = len + 1; + buf.data_ptr = buf.alloc_ptr; + buf.data_len = len; + + return buf; +} + +// Same as strbuf but with null alloc_ptr. +deno_buf StrBufNullAllocPtr(const char* str) { + auto len = strlen(str); + deno_buf buf; + buf.alloc_ptr = nullptr; + buf.alloc_len = 0; + buf.data_ptr = reinterpret_cast(strdup(str)); + buf.data_len = len; + return buf; +} + +TEST(LibDenoTest, SendSuccess) { + Deno* d = deno_new(nullptr, nullptr); + EXPECT_TRUE(deno_execute(d, "a.js", "SendSuccess()")); + EXPECT_TRUE(deno_send(d, strbuf("abc"))); + deno_delete(d); +} + +TEST(LibDenoTest, SendWrongByteLength) { + Deno* d = deno_new(nullptr, nullptr); + EXPECT_TRUE(deno_execute(d, "a.js", "SendWrongByteLength()")); + // deno_send the wrong sized message, it should throw. + EXPECT_FALSE(deno_send(d, strbuf("abcd"))); + std::string exception = deno_last_exception(d); + EXPECT_GT(exception.length(), 1u); + EXPECT_NE(exception.find("assert"), std::string::npos); + deno_delete(d); +} + +TEST(LibDenoTest, SendNoCallback) { + Deno* d = deno_new(nullptr, nullptr); + // We didn't call deno.recv() in JS, should fail. + EXPECT_FALSE(deno_send(d, strbuf("abc"))); + deno_delete(d); +} + +TEST(LibDenoTest, RecvReturnEmpty) { + static int count = 0; + Deno* d = deno_new(nullptr, [](auto _, auto buf) { + count++; + EXPECT_EQ(static_cast(3), buf.data_len); + EXPECT_EQ(buf.data_ptr[0], 'a'); + EXPECT_EQ(buf.data_ptr[1], 'b'); + EXPECT_EQ(buf.data_ptr[2], 'c'); + }); + EXPECT_TRUE(deno_execute(d, "a.js", "RecvReturnEmpty()")); + EXPECT_EQ(count, 2); + deno_delete(d); +} + +TEST(LibDenoTest, RecvReturnBar) { + static int count = 0; + Deno* d = deno_new(nullptr, [](auto deno, auto buf) { + count++; + EXPECT_EQ(static_cast(3), buf.data_len); + EXPECT_EQ(buf.data_ptr[0], 'a'); + EXPECT_EQ(buf.data_ptr[1], 'b'); + EXPECT_EQ(buf.data_ptr[2], 'c'); + deno_set_response(deno, strbuf("bar")); + }); + EXPECT_TRUE(deno_execute(d, "a.js", "RecvReturnBar()")); + EXPECT_EQ(count, 1); + deno_delete(d); +} + +TEST(LibDenoTest, DoubleRecvFails) { + Deno* d = deno_new(nullptr, nullptr); + EXPECT_FALSE(deno_execute(d, "a.js", "DoubleRecvFails()")); + deno_delete(d); +} + +TEST(LibDenoTest, SendRecvSlice) { + static int count = 0; + Deno* d = deno_new(nullptr, [](auto deno, auto buf) { + static const size_t alloc_len = 1024; + size_t i = count++; + // Check the size and offset of the slice. + size_t data_offset = buf.data_ptr - buf.alloc_ptr; + EXPECT_EQ(data_offset, i * 11); + EXPECT_EQ(buf.data_len, alloc_len - i * 30); + EXPECT_EQ(buf.alloc_len, alloc_len); + // Check values written by the JS side. + EXPECT_EQ(buf.data_ptr[0], 100 + i); + EXPECT_EQ(buf.data_ptr[buf.data_len - 1], 100 - i); + // Make copy of the backing buffer -- this is currently necessary because + // deno_set_response() takes ownership over the buffer, but we are not given + // ownership of `buf` by our caller. + uint8_t* alloc_ptr = reinterpret_cast(malloc(alloc_len)); + memcpy(alloc_ptr, buf.alloc_ptr, alloc_len); + // Make a slice that is a bit shorter than the original. + deno_buf buf2{alloc_ptr, alloc_len, alloc_ptr + data_offset, + buf.data_len - 19}; + // Place some values into the buffer for the JS side to verify. + buf2.data_ptr[0] = 200 + i; + buf2.data_ptr[buf2.data_len - 1] = 200 - i; + // Send back. + deno_set_response(deno, buf2); + }); + EXPECT_TRUE(deno_execute(d, "a.js", "SendRecvSlice()")); + EXPECT_EQ(count, 5); + deno_delete(d); +} + +TEST(LibDenoTest, JSSendArrayBufferViewTypes) { + static int count = 0; + Deno* d = deno_new(nullptr, [](auto _, auto buf) { + count++; + size_t data_offset = buf.data_ptr - buf.alloc_ptr; + EXPECT_EQ(data_offset, 2468u); + EXPECT_EQ(buf.data_len, 1000u); + EXPECT_EQ(buf.alloc_len, 4321u); + EXPECT_EQ(buf.data_ptr[0], count); + }); + EXPECT_TRUE(deno_execute(d, "a.js", "JSSendArrayBufferViewTypes()")); + EXPECT_EQ(count, 3); + deno_delete(d); +} + +TEST(LibDenoTest, JSSendNeutersBuffer) { + static int count = 0; + Deno* d = deno_new(nullptr, [](auto _, auto buf) { + count++; + EXPECT_EQ(buf.data_len, 1u); + EXPECT_EQ(buf.data_ptr[0], 42); + }); + EXPECT_TRUE(deno_execute(d, "a.js", "JSSendNeutersBuffer()")); + EXPECT_EQ(count, 1); + deno_delete(d); +} + +TEST(LibDenoTest, TypedArraySnapshots) { + Deno* d = deno_new(nullptr, nullptr); + EXPECT_TRUE(deno_execute(d, "a.js", "TypedArraySnapshots()")); + deno_delete(d); +} + +TEST(LibDenoTest, SnapshotBug) { + Deno* d = deno_new(nullptr, nullptr); + EXPECT_TRUE(deno_execute(d, "a.js", "SnapshotBug()")); + deno_delete(d); +} + +TEST(LibDenoTest, ErrorHandling) { + static int count = 0; + Deno* d = deno_new(nullptr, [](auto deno, auto buf) { + count++; + EXPECT_EQ(static_cast(1), buf.data_len); + EXPECT_EQ(buf.data_ptr[0], 42); + }); + EXPECT_FALSE(deno_execute(d, "a.js", "ErrorHandling()")); + EXPECT_EQ(count, 1); + deno_delete(d); +} + +TEST(LibDenoTest, SendNullAllocPtr) { + static int count = 0; + Deno* d = deno_new(nullptr, [](auto _, auto buf) { count++; }); + EXPECT_TRUE(deno_execute(d, "a.js", "SendNullAllocPtr()")); + deno_buf buf = StrBufNullAllocPtr("abcd"); + EXPECT_EQ(buf.alloc_ptr, nullptr); + EXPECT_EQ(buf.data_len, 4u); + EXPECT_TRUE(deno_send(d, buf)); + EXPECT_EQ(count, 0); + deno_delete(d); +} diff --git a/src/mock_runtime_test.cc b/src/mock_runtime_test.cc deleted file mode 100644 index ac50913de..000000000 --- a/src/mock_runtime_test.cc +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2018 the Deno authors. All rights reserved. MIT license. -#include "testing/gtest/include/gtest/gtest.h" - -#include "deno.h" - -TEST(MockRuntimeTest, InitializesCorrectly) { - Deno* d = deno_new(nullptr, nullptr); - EXPECT_TRUE(deno_execute(d, "a.js", "1 + 2")); - deno_delete(d); -} - -TEST(MockRuntimeTest, CanCallFunction) { - Deno* d = deno_new(nullptr, nullptr); - EXPECT_TRUE(deno_execute(d, "a.js", - "if (CanCallFunction() != 'foo') throw Error();")); - deno_delete(d); -} - -TEST(MockRuntimeTest, ErrorsCorrectly) { - Deno* d = deno_new(nullptr, nullptr); - EXPECT_FALSE(deno_execute(d, "a.js", "throw Error()")); - deno_delete(d); -} - -deno_buf strbuf(const char* str) { - auto len = strlen(str); - - deno_buf buf; - buf.alloc_ptr = reinterpret_cast(strdup(str)); - buf.alloc_len = len + 1; - buf.data_ptr = buf.alloc_ptr; - buf.data_len = len; - - return buf; -} - -// Same as strbuf but with null alloc_ptr. -deno_buf StrBufNullAllocPtr(const char* str) { - auto len = strlen(str); - deno_buf buf; - buf.alloc_ptr = nullptr; - buf.alloc_len = 0; - buf.data_ptr = reinterpret_cast(strdup(str)); - buf.data_len = len; - return buf; -} - -TEST(MockRuntimeTest, SendSuccess) { - Deno* d = deno_new(nullptr, nullptr); - EXPECT_TRUE(deno_execute(d, "a.js", "SendSuccess()")); - EXPECT_TRUE(deno_send(d, strbuf("abc"))); - deno_delete(d); -} - -TEST(MockRuntimeTest, SendWrongByteLength) { - Deno* d = deno_new(nullptr, nullptr); - EXPECT_TRUE(deno_execute(d, "a.js", "SendWrongByteLength()")); - // deno_send the wrong sized message, it should throw. - EXPECT_FALSE(deno_send(d, strbuf("abcd"))); - std::string exception = deno_last_exception(d); - EXPECT_GT(exception.length(), 1u); - EXPECT_NE(exception.find("assert"), std::string::npos); - deno_delete(d); -} - -TEST(MockRuntimeTest, SendNoCallback) { - Deno* d = deno_new(nullptr, nullptr); - // We didn't call deno.recv() in JS, should fail. - EXPECT_FALSE(deno_send(d, strbuf("abc"))); - deno_delete(d); -} - -TEST(MockRuntimeTest, RecvReturnEmpty) { - static int count = 0; - Deno* d = deno_new(nullptr, [](auto _, auto buf) { - count++; - EXPECT_EQ(static_cast(3), buf.data_len); - EXPECT_EQ(buf.data_ptr[0], 'a'); - EXPECT_EQ(buf.data_ptr[1], 'b'); - EXPECT_EQ(buf.data_ptr[2], 'c'); - }); - EXPECT_TRUE(deno_execute(d, "a.js", "RecvReturnEmpty()")); - EXPECT_EQ(count, 2); - deno_delete(d); -} - -TEST(MockRuntimeTest, RecvReturnBar) { - static int count = 0; - Deno* d = deno_new(nullptr, [](auto deno, auto buf) { - count++; - EXPECT_EQ(static_cast(3), buf.data_len); - EXPECT_EQ(buf.data_ptr[0], 'a'); - EXPECT_EQ(buf.data_ptr[1], 'b'); - EXPECT_EQ(buf.data_ptr[2], 'c'); - deno_set_response(deno, strbuf("bar")); - }); - EXPECT_TRUE(deno_execute(d, "a.js", "RecvReturnBar()")); - EXPECT_EQ(count, 1); - deno_delete(d); -} - -TEST(MockRuntimeTest, DoubleRecvFails) { - Deno* d = deno_new(nullptr, nullptr); - EXPECT_FALSE(deno_execute(d, "a.js", "DoubleRecvFails()")); - deno_delete(d); -} - -TEST(MockRuntimeTest, SendRecvSlice) { - static int count = 0; - Deno* d = deno_new(nullptr, [](auto deno, auto buf) { - static const size_t alloc_len = 1024; - size_t i = count++; - // Check the size and offset of the slice. - size_t data_offset = buf.data_ptr - buf.alloc_ptr; - EXPECT_EQ(data_offset, i * 11); - EXPECT_EQ(buf.data_len, alloc_len - i * 30); - EXPECT_EQ(buf.alloc_len, alloc_len); - // Check values written by the JS side. - EXPECT_EQ(buf.data_ptr[0], 100 + i); - EXPECT_EQ(buf.data_ptr[buf.data_len - 1], 100 - i); - // Make copy of the backing buffer -- this is currently necessary because - // deno_set_response() takes ownership over the buffer, but we are not given - // ownership of `buf` by our caller. - uint8_t* alloc_ptr = reinterpret_cast(malloc(alloc_len)); - memcpy(alloc_ptr, buf.alloc_ptr, alloc_len); - // Make a slice that is a bit shorter than the original. - deno_buf buf2{alloc_ptr, alloc_len, alloc_ptr + data_offset, - buf.data_len - 19}; - // Place some values into the buffer for the JS side to verify. - buf2.data_ptr[0] = 200 + i; - buf2.data_ptr[buf2.data_len - 1] = 200 - i; - // Send back. - deno_set_response(deno, buf2); - }); - EXPECT_TRUE(deno_execute(d, "a.js", "SendRecvSlice()")); - EXPECT_EQ(count, 5); - deno_delete(d); -} - -TEST(MockRuntimeTest, JSSendArrayBufferViewTypes) { - static int count = 0; - Deno* d = deno_new(nullptr, [](auto _, auto buf) { - count++; - size_t data_offset = buf.data_ptr - buf.alloc_ptr; - EXPECT_EQ(data_offset, 2468u); - EXPECT_EQ(buf.data_len, 1000u); - EXPECT_EQ(buf.alloc_len, 4321u); - EXPECT_EQ(buf.data_ptr[0], count); - }); - EXPECT_TRUE(deno_execute(d, "a.js", "JSSendArrayBufferViewTypes()")); - EXPECT_EQ(count, 3); - deno_delete(d); -} - -TEST(MockRuntimeTest, JSSendNeutersBuffer) { - static int count = 0; - Deno* d = deno_new(nullptr, [](auto _, auto buf) { - count++; - EXPECT_EQ(buf.data_len, 1u); - EXPECT_EQ(buf.data_ptr[0], 42); - }); - EXPECT_TRUE(deno_execute(d, "a.js", "JSSendNeutersBuffer()")); - EXPECT_EQ(count, 1); - deno_delete(d); -} - -TEST(MockRuntimeTest, TypedArraySnapshots) { - Deno* d = deno_new(nullptr, nullptr); - EXPECT_TRUE(deno_execute(d, "a.js", "TypedArraySnapshots()")); - deno_delete(d); -} - -TEST(MockRuntimeTest, SnapshotBug) { - Deno* d = deno_new(nullptr, nullptr); - EXPECT_TRUE(deno_execute(d, "a.js", "SnapshotBug()")); - deno_delete(d); -} - -TEST(MockRuntimeTest, ErrorHandling) { - static int count = 0; - Deno* d = deno_new(nullptr, [](auto deno, auto buf) { - count++; - EXPECT_EQ(static_cast(1), buf.data_len); - EXPECT_EQ(buf.data_ptr[0], 42); - }); - EXPECT_FALSE(deno_execute(d, "a.js", "ErrorHandling()")); - EXPECT_EQ(count, 1); - deno_delete(d); -} - -TEST(MockRuntimeTest, SendNullAllocPtr) { - static int count = 0; - Deno* d = deno_new(nullptr, [](auto _, auto buf) { count++; }); - EXPECT_TRUE(deno_execute(d, "a.js", "SendNullAllocPtr()")); - deno_buf buf = StrBufNullAllocPtr("abcd"); - EXPECT_EQ(buf.alloc_ptr, nullptr); - EXPECT_EQ(buf.data_len, 4u); - EXPECT_TRUE(deno_send(d, buf)); - EXPECT_EQ(count, 0); - deno_delete(d); -} -- cgit v1.2.3