| Index: runtime/vm/dart_api_impl_test.cc
|
| diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
|
| index 2bda3205765245de180e0814cb5f0ba69d1a73b3..6cbf9f304bcb0e9fffca1b619ae1ee4a76c99630 100644
|
| --- a/runtime/vm/dart_api_impl_test.cc
|
| +++ b/runtime/vm/dart_api_impl_test.cc
|
| @@ -3,6 +3,7 @@
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| #include "bin/builtin.h"
|
| +#include "vm/compiler.h"
|
| #include "include/dart_api.h"
|
| #include "include/dart_mirrors_api.h"
|
| #include "include/dart_native_api.h"
|
| @@ -9853,6 +9854,164 @@ TEST_CASE(Timeline_Dart_EmbedderTimelineStartStopRecording) {
|
| EXPECT(stop_called);
|
| }
|
|
|
| +
|
| +TEST_CASE(Dart_LoadLibraryPatch_1) {
|
| + const char* kScriptChars1 =
|
| + "class A {\n"
|
| + " int foo() { return 10; }\n"
|
| + " external int zoo();\n"
|
| + " external static int moo();\n"
|
| + "}\n"
|
| + "main() { new A().foo(); }\n"
|
| + "foozoo() { new A().zoo(); }\n"
|
| + "foomoo() { A.moo(); }\n";
|
| +
|
| + const char* kScriptChars2 =
|
| + "patch class A {\n"
|
| + " /* patch */ int zoo() { return 1; }\n"
|
| + " /* patch */ static int moo() { return 1; }\n"
|
| + "}\n";
|
| +
|
| + Dart_Handle lib = TestCase::LoadTestScript(kScriptChars1, NULL);
|
| + Dart_Handle result = Dart_Invoke(lib,
|
| + NewString("main"),
|
| + 0,
|
| + NULL);
|
| + EXPECT_VALID(result);
|
| + Dart_Handle url = NewString("test-lib-patch");
|
| + Dart_Handle source = NewString(kScriptChars2);
|
| + result = Dart_LibraryLoadPatch(lib, url, source);
|
| + EXPECT_VALID(result);
|
| + result = Dart_FinalizeLoading(false);
|
| + EXPECT_VALID(result);
|
| + result = Dart_Invoke(lib,
|
| + NewString("foozoo"),
|
| + 0,
|
| + NULL);
|
| + EXPECT_VALID(result);
|
| + result = Dart_Invoke(lib,
|
| + NewString("foomoo"),
|
| + 0,
|
| + NULL);
|
| + EXPECT_VALID(result);
|
| +}
|
| +
|
| +
|
| +TEST_CASE(Dart_LoadLibraryPatch_Error1) {
|
| + const char* kScriptChars1 =
|
| + "class A {\n"
|
| + " int foo() { return 10; }\n"
|
| + " external int zoo();\n"
|
| + "}\n"
|
| + "main() { new A().foo(); }\n"
|
| + "foozoo() { new A().zoo(); }\n";
|
| +
|
| + const char* kScriptChars2 =
|
| + "patch class A {\n"
|
| + " /* patch */ int zoo() { return 1; }\n"
|
| + " /* patch */ int fld1;\n"
|
| + "}\n";
|
| +
|
| + Dart_Handle lib = TestCase::LoadTestScript(kScriptChars1, NULL);
|
| + Dart_Handle result = Dart_Invoke(lib,
|
| + NewString("main"),
|
| + 0,
|
| + NULL);
|
| + EXPECT_VALID(result);
|
| + Dart_Handle url = NewString("test-lib-patch");
|
| + Dart_Handle source = NewString(kScriptChars2);
|
| + // We don't expect to be able to patch in this case as new fields
|
| + // are being added.
|
| + result = Dart_LibraryLoadPatch(lib, url, source);
|
| + EXPECT_VALID(result);
|
| + result = Dart_FinalizeLoading(false);
|
| + EXPECT_VALID(result);
|
| + result = Dart_Invoke(lib,
|
| + NewString("foozoo"),
|
| + 0,
|
| + NULL);
|
| + EXPECT(Dart_IsError(result));
|
| +}
|
| +
|
| +
|
| +TEST_CASE(Dart_LoadLibraryPatch_Error2) {
|
| + const char* kScriptChars1 =
|
| + "class A {\n"
|
| + " int foo() { return 10; }\n"
|
| + " int zoo() { return 20; }\n"
|
| + "}\n"
|
| + "main() { new A().foo(); }\n"
|
| + "foozoo() { new A().zoo(); }\n";
|
| +
|
| + const char* kScriptChars2 =
|
| + "patch class A {\n"
|
| + " /* patch */ int zoo() { return 1; }\n"
|
| + "}\n";
|
| +
|
| + Dart_Handle lib = TestCase::LoadTestScript(kScriptChars1, NULL);
|
| + Dart_Handle result = Dart_Invoke(lib,
|
| + NewString("main"),
|
| + 0,
|
| + NULL);
|
| + EXPECT_VALID(result);
|
| + Dart_Handle url = NewString("test-lib-patch");
|
| + Dart_Handle source = NewString(kScriptChars2);
|
| + // We don't expect to be able to patch in this case as a non external
|
| + // method is being patched.
|
| + result = Dart_LibraryLoadPatch(lib, url, source);
|
| + EXPECT_VALID(result);
|
| + result = Dart_FinalizeLoading(false);
|
| + EXPECT_VALID(result);
|
| + result = Dart_Invoke(lib,
|
| + NewString("foozoo"),
|
| + 0,
|
| + NULL);
|
| + EXPECT(Dart_IsError(result));
|
| + OS::Print("Patched class executed\n");
|
| +}
|
| +
|
| +
|
| +TEST_CASE(Dart_LoadLibraryPatch_Error3) {
|
| + const char* kScriptChars1 =
|
| + "class A {\n"
|
| + " int foo() { return 10; }\n"
|
| + " external int zoo();\n"
|
| + "}\n"
|
| + "main() { new A().foo(); }\n"
|
| + "foozoo() { new A().zoo(); }\n";
|
| +
|
| + const char* kScriptChars2 =
|
| + "patch class A {\n"
|
| + " /* patch */ int zoo() { return 1; }\n"
|
| + "}\n";
|
| +
|
| + Dart_Handle lib = TestCase::LoadTestScript(kScriptChars1, NULL);
|
| + Dart_Handle result = Dart_Invoke(lib,
|
| + NewString("main"),
|
| + 0,
|
| + NULL);
|
| + // We invoke the foozoo method to ensure that code for 'zoo' is generated
|
| + // which throws NoSuchMethod.
|
| + result = Dart_Invoke(lib,
|
| + NewString("foozoo"),
|
| + 0,
|
| + NULL);
|
| + EXPECT(Dart_IsError(result));
|
| + Dart_Handle url = NewString("test-lib-patch");
|
| + Dart_Handle source = NewString(kScriptChars2);
|
| + // We don't expect to be able to patch in this case as the function being
|
| + // patched has already executed.
|
| + result = Dart_LibraryLoadPatch(lib, url, source);
|
| + EXPECT_VALID(result);
|
| + result = Dart_FinalizeLoading(false);
|
| + EXPECT_VALID(result);
|
| + result = Dart_Invoke(lib,
|
| + NewString("foozoo"),
|
| + 0,
|
| + NULL);
|
| + EXPECT(Dart_IsError(result));
|
| +}
|
| +
|
| #endif // !PRODUCT
|
|
|
| } // namespace dart
|
|
|