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 |