From 0e07e16dd63992f5f989dc99c891d53d930a2d5b Mon Sep 17 00:00:00 2001
From: Ryan Dahl <ry@tinyclouds.org>
Date: Mon, 11 Jun 2018 17:01:35 +0200
Subject: [PATCH] Add mock_runtime_test.

---
 deno2/BUILD.gn             | 46 +++++++++++++++++++++++---------------
 deno2/deno.cc              |  9 ++------
 deno2/deno_test.cc         | 17 --------------
 deno2/from_snapshot.cc     |  6 +++++
 deno2/include/deno.h       |  4 ++--
 deno2/js/mock_runtime.js   |  9 ++++++++
 deno2/mock_runtime_test.cc | 26 +++++++++++++++++++++
 7 files changed, 73 insertions(+), 44 deletions(-)
 delete mode 100644 deno2/deno_test.cc
 create mode 100644 deno2/js/mock_runtime.js
 create mode 100644 deno2/mock_runtime_test.cc

diff --git a/deno2/BUILD.gn b/deno2/BUILD.gn
index 16b1114c54..ef81a94d9d 100644
--- a/deno2/BUILD.gn
+++ b/deno2/BUILD.gn
@@ -11,21 +11,30 @@ executable("deno") {
   ]
 }
 
-executable("deno_test") {
+executable("mock_runtime_test") {
   testonly = true
   sources = [
-    "deno_test.cc",
+    "from_snapshot.cc",
+    "mock_runtime_test.cc",
   ]
   deps = [
-    ":libdeno",
+    ":create_snapshot_mock_runtime",
+    ":deno_nosnapshot",
     "//testing/gtest:gtest",
   ]
+  include_dirs = [ target_gen_dir ]
+  defines = [ "DENO_MOCK_RUNTIME" ]
 }
 
 component("libdeno") {
-  deps = [
-    ":deno_snapshot",
+  sources = [
+    "from_snapshot.cc",
   ]
+  deps = [
+    ":create_snapshot_deno",
+    ":deno_nosnapshot",
+  ]
+  include_dirs = [ target_gen_dir ]
 }
 
 source_set("deno_nosnapshot") {
@@ -44,17 +53,6 @@ source_set("deno_nosnapshot") {
   ]
 }
 
-source_set("deno_snapshot") {
-  sources = [
-    "from_snapshot.cc",
-  ]
-  deps = [
-    ":create_snapshot_deno",
-    ":deno_nosnapshot",
-  ]
-  include_dirs = [ target_gen_dir ]
-}
-
 executable("snapshot_creator") {
   sources = [
     "snapshot_creator.cc",
@@ -109,8 +107,13 @@ template("create_snapshot") {
   name = target_name
   suffix = "_$name"
   action("create_snapshot_" + name) {
+    forward_variables_from(invoker,
+                           [
+                             "testonly",
+                             "deps",
+                           ])
     visibility = [ ":*" ]  # Only targets in this file can depend on this.
-    deps = [ ":snapshot_creator" ] + invoker.deps
+    deps += [ ":snapshot_creator" ]
     script = "v8/tools/run.py"
     data = []
     exe = rebase_path(get_label_info(":snapshot_creator", "root_out_dir") +
@@ -140,10 +143,17 @@ template("create_snapshot") {
   }
 }
 
-# Generates $target_gen_dir/snapshot_bundle.cc
+# Generates $target_gen_dir/snapshot_deno.cc
 create_snapshot("deno") {
   js = "$target_gen_dir/main.js"
   deps = [
     ":run_parcel",
   ]
 }
+
+# Generates $target_gen_dir/snapshot_mock_runtime.cc
+create_snapshot("mock_runtime") {
+  testonly = true
+  js = "js/mock_runtime.js"
+  deps = []
+}
diff --git a/deno2/deno.cc b/deno2/deno.cc
index 60ee5cae5f..7bca590a70 100644
--- a/deno2/deno.cc
+++ b/deno2/deno.cc
@@ -46,7 +46,6 @@ static inline v8::Local<v8::String> v8_str(const char* x) {
       .ToLocalChecked();
 }
 
-// Exits the process.
 void HandleException(v8::Local<v8::Context> context,
                      v8::Local<v8::Value> exception) {
   auto* isolate = context->GetIsolate();
@@ -73,8 +72,6 @@ void HandleException(v8::Local<v8::Context> context,
     printf("Unhandled Exception %s\n", ToCString(exceptionStr));
     message->PrintCurrentStackTrace(isolate, stdout);
   }
-
-  exit(1);
 }
 
 /*
@@ -181,7 +178,6 @@ bool Load(v8::Local<v8::Context> context, const char* name_s,
   if (script.IsEmpty()) {
     assert(try_catch.HasCaught());
     HandleException(context, try_catch.Exception());
-    assert(false);
     return false;
   }
 
@@ -190,7 +186,6 @@ bool Load(v8::Local<v8::Context> context, const char* name_s,
   if (result.IsEmpty()) {
     assert(try_catch.HasCaught());
     HandleException(context, try_catch.Exception());
-    assert(false);
     return false;
   }
 
@@ -270,13 +265,13 @@ void deno_set_flags(int* argc, char** argv) {
 
 const char* deno_last_exception(Deno* d) { return d->last_exception.c_str(); }
 
-int deno_load(Deno* d, const char* name_s, const char* source_s) {
+bool deno_load(Deno* d, const char* name_s, const char* source_s) {
   auto* isolate = d->isolate;
   v8::Locker locker(isolate);
   v8::Isolate::Scope isolate_scope(isolate);
   v8::HandleScope handle_scope(isolate);
   auto context = d->context.Get(d->isolate);
-  return deno::Load(context, name_s, source_s) ? 0 : 1;
+  return deno::Load(context, name_s, source_s);
 }
 
 // Called from golang. Must route message to javascript lang.
diff --git a/deno2/deno_test.cc b/deno2/deno_test.cc
deleted file mode 100644
index 0b570a4b52..0000000000
--- a/deno2/deno_test.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
-// All rights reserved. MIT License.
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include "include/deno.h"
-
-TEST(DenoTest, InitializesCorrectly) {
-  deno_init();
-  Deno* d = deno_new(NULL, NULL);
-  int r = deno_load(d, "a.js", "1 + 2");
-  EXPECT_EQ(r, 0);
-}
-
-int main(int argc, char** argv) {
-  testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
diff --git a/deno2/from_snapshot.cc b/deno2/from_snapshot.cc
index db5b0fc8e9..3c15cdc77d 100644
--- a/deno2/from_snapshot.cc
+++ b/deno2/from_snapshot.cc
@@ -13,8 +13,13 @@
 
 namespace deno {
 
+#ifdef DENO_MOCK_RUNTIME
+#include "natives_mock_runtime.cc"
+#include "snapshot_mock_runtime.cc"
+#else
 #include "natives_deno.cc"
 #include "snapshot_deno.cc"
+#endif
 
 Deno* NewFromSnapshot(void* data, deno_recv_cb cb) {
   auto natives_blob = *StartupBlob_natives();
@@ -33,6 +38,7 @@ Deno* NewFromSnapshot(void* data, deno_recv_cb cb) {
   v8::Isolate* isolate = v8::Isolate::New(params);
   AddIsolate(d, isolate);
 
+  v8::Locker locker(isolate);
   v8::Isolate::Scope isolate_scope(isolate);
   {
     v8::HandleScope handle_scope(isolate);
diff --git a/deno2/include/deno.h b/deno2/include/deno.h
index fb00385492..1a42ec2b1e 100644
--- a/deno2/include/deno.h
+++ b/deno2/include/deno.h
@@ -27,9 +27,9 @@ void deno_set_flags(int* argc, char** argv);
 // Constructor
 Deno* deno_new(void* data, deno_recv_cb cb);
 
-// Returns nonzero on error.
+// Returns false on error.
 // Get error text with deno_last_exception().
-int deno_load(Deno* d, const char* name_s, const char* source_s);
+bool deno_load(Deno* d, const char* name_s, const char* source_s);
 
 // Returns nonzero on error.
 int deno_send(Deno* d, deno_buf buf);
diff --git a/deno2/js/mock_runtime.js b/deno2/js/mock_runtime.js
new file mode 100644
index 0000000000..a91546f859
--- /dev/null
+++ b/deno2/js/mock_runtime.js
@@ -0,0 +1,9 @@
+// A simple runtime that doesn't involve typescript or protobufs to test
+// libdeno.
+const globalEval = eval;
+const window = globalEval("this");
+window['foo'] = () => {
+  deno_print("Hello world from foo");
+  return "foo";
+}
+
diff --git a/deno2/mock_runtime_test.cc b/deno2/mock_runtime_test.cc
new file mode 100644
index 0000000000..951710fb92
--- /dev/null
+++ b/deno2/mock_runtime_test.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 Ryan Dahl <ry@tinyclouds.org>
+// All rights reserved. MIT License.
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "include/deno.h"
+
+TEST(MockRuntimeTest, InitializesCorrectly) {
+  Deno* d = deno_new(NULL, NULL);
+  EXPECT_TRUE(deno_load(d, "a.js", "1 + 2"));
+}
+
+TEST(MockRuntimeTest, CanCallFoo) {
+  Deno* d = deno_new(NULL, NULL);
+  EXPECT_TRUE(deno_load(d, "a.js", "if (foo() != 'foo') throw Error();"));
+}
+
+TEST(MockRuntimeTest, ErrorsCorrectly) {
+  Deno* d = deno_new(NULL, NULL);
+  EXPECT_FALSE(deno_load(d, "a.js", "throw Error()"));
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  deno_init();
+  return RUN_ALL_TESTS();
+}