[VM] Add test for Dart_InvokeVMServiceMethod
This CL adds CC a test for Dart_InvokeVMServiceMethod. This requires also adding support for starting the service-isolate in run_vm_tests, which in return requires adding the vm_platform.dill (as well as a few other things). Furthermore this CL also adds a Service::WaitForLoadPortInternal, which does not require a current thread and makes Dart_InvokeVMServiceMethod use it. Original CL (not landed): https://dart-review.googlesource.com/c/sdk/+/67761 Closes https://github.com/dart-lang/sdk/issues/33977 Change-Id: Ife98b56043c26eb477825b05f8aaedaec508eeb8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/111726 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Clement Skau <cskau@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
fd7baa4fd9
commit
d3f3b46b87
@@ -2,7 +2,6 @@
|
||||
# for details. All rights reserved. Use of this source code is governed by a
|
||||
# BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
|
||||
import("../../build/config/gclient_args.gni")
|
||||
import("../../build/dart/dart_action.gni")
|
||||
import("../runtime_args.gni")
|
||||
@@ -931,6 +930,7 @@ executable("run_vm_tests") {
|
||||
include_dirs = [
|
||||
"..",
|
||||
"$target_gen_dir",
|
||||
"//third_party",
|
||||
]
|
||||
defines = [ "TESTING" ]
|
||||
|
||||
@@ -958,9 +958,15 @@ executable("run_vm_tests") {
|
||||
"dfe.h",
|
||||
"error_exit.cc",
|
||||
"error_exit.h",
|
||||
"gzip.cc",
|
||||
"gzip.h",
|
||||
"loader.cc",
|
||||
"loader.h",
|
||||
"run_vm_tests.cc",
|
||||
"snapshot_utils.cc",
|
||||
"snapshot_utils.h",
|
||||
"vmservice_impl.cc",
|
||||
"vmservice_impl.h",
|
||||
] + builtin_impl_tests + vm_tests + compiler_tests + heap_tests
|
||||
|
||||
if (!is_win) {
|
||||
|
||||
+6
-2
@@ -77,13 +77,17 @@ DFE::DFE()
|
||||
(defined(DART_PRECOMPILER) && defined(TARGET_ARCH_X64))
|
||||
kernel_service_dill_ = nullptr;
|
||||
kernel_service_dill_size_ = 0;
|
||||
#else
|
||||
kernel_service_dill_ = kKernelServiceDill;
|
||||
kernel_service_dill_size_ = kKernelServiceDillSize;
|
||||
#endif
|
||||
|
||||
#if defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
|
||||
platform_strong_dill_for_compilation_ = nullptr;
|
||||
platform_strong_dill_for_compilation_size_ = 0;
|
||||
platform_strong_dill_for_execution_ = nullptr;
|
||||
platform_strong_dill_for_execution_size_ = 0;
|
||||
#else
|
||||
kernel_service_dill_ = kKernelServiceDill;
|
||||
kernel_service_dill_size_ = kKernelServiceDillSize;
|
||||
platform_strong_dill_for_compilation_ = kPlatformStrongDill;
|
||||
platform_strong_dill_for_compilation_size_ = kPlatformStrongDillSize;
|
||||
platform_strong_dill_for_execution_ = kPlatformStrongDill;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "bin/snapshot_utils.h"
|
||||
#include "bin/thread.h"
|
||||
#include "bin/utils.h"
|
||||
#include "bin/vmservice_impl.h"
|
||||
#include "platform/assert.h"
|
||||
#include "vm/benchmark_test.h"
|
||||
#include "vm/dart.h"
|
||||
@@ -102,6 +103,56 @@ static void PrintUsage() {
|
||||
return nullptr; \
|
||||
}
|
||||
|
||||
static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
|
||||
const char* package_root,
|
||||
const char* packages_config,
|
||||
Dart_IsolateFlags* flags,
|
||||
char** error) {
|
||||
ASSERT(script_uri != nullptr);
|
||||
Dart_Isolate isolate = nullptr;
|
||||
auto isolate_group_data = new bin::IsolateGroupData(
|
||||
script_uri, package_root, packages_config, /*app_snapshot=*/nullptr,
|
||||
/*isolate_run_app_snapshot=*/false);
|
||||
|
||||
const uint8_t* kernel_buffer = nullptr;
|
||||
intptr_t kernel_buffer_size = 0;
|
||||
|
||||
bin::dfe.Init();
|
||||
bin::dfe.LoadPlatform(&kernel_buffer, &kernel_buffer_size);
|
||||
RELEASE_ASSERT(kernel_buffer != nullptr);
|
||||
|
||||
flags->load_vmservice_library = true;
|
||||
isolate_group_data->SetKernelBufferUnowned(
|
||||
const_cast<uint8_t*>(kernel_buffer), kernel_buffer_size);
|
||||
isolate = Dart_CreateIsolateGroupFromKernel(
|
||||
script_uri, DART_VM_SERVICE_ISOLATE_NAME, kernel_buffer,
|
||||
kernel_buffer_size, flags, isolate_group_data, /*isolate_data=*/nullptr,
|
||||
error);
|
||||
if (isolate == nullptr) {
|
||||
delete isolate_group_data;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Dart_EnterScope();
|
||||
|
||||
Dart_Handle result =
|
||||
Dart_SetLibraryTagHandler(bin::Loader::LibraryTagHandler);
|
||||
CHECK_RESULT(result);
|
||||
|
||||
// Load embedder specific bits and return.
|
||||
if (!bin::VmService::Setup("127.0.0.1", 0,
|
||||
/*dev_mode=*/false, /*auth_disabled=*/true,
|
||||
/*trace_loading=*/false, /*deterministic=*/true)) {
|
||||
*error = strdup(bin::VmService::GetErrorMessage());
|
||||
return nullptr;
|
||||
}
|
||||
result = Dart_SetEnvironmentCallback(bin::DartUtils::EnvironmentCallback);
|
||||
CHECK_RESULT(result);
|
||||
Dart_ExitScope();
|
||||
Dart_ExitIsolate();
|
||||
return isolate;
|
||||
}
|
||||
|
||||
static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
|
||||
const char* main,
|
||||
const char* package_root,
|
||||
@@ -110,11 +161,9 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
|
||||
void* data,
|
||||
char** error) {
|
||||
ASSERT(script_uri != nullptr);
|
||||
const bool is_service_isolate =
|
||||
strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0;
|
||||
if (is_service_isolate) {
|
||||
// We don't need service isolate for VM tests.
|
||||
return nullptr;
|
||||
if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
|
||||
return CreateAndSetupServiceIsolate(script_uri, package_root,
|
||||
packages_config, flags, error);
|
||||
}
|
||||
const bool is_kernel_isolate =
|
||||
strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0;
|
||||
|
||||
@@ -7936,6 +7936,66 @@ TEST_CASE(DartAPI_InvokeImportedFunction) {
|
||||
"NoSuchMethodError: No top-level method 'getCurrentTag' declared.");
|
||||
}
|
||||
|
||||
TEST_CASE(DartAPI_InvokeVMServiceMethod) {
|
||||
char buffer[1024];
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
R"({
|
||||
"jsonrpc": 2.0,
|
||||
"id": "foo",
|
||||
"method": "getVM",
|
||||
"params": { }
|
||||
})");
|
||||
uint8_t* response_json = nullptr;
|
||||
intptr_t response_json_length = 0;
|
||||
char* error = nullptr;
|
||||
const bool success = Dart_InvokeVMServiceMethod(
|
||||
reinterpret_cast<uint8_t*>(buffer), strlen(buffer), &response_json,
|
||||
&response_json_length, &error);
|
||||
EXPECT(success);
|
||||
EXPECT(error == nullptr);
|
||||
|
||||
Dart_Handle bytes = Dart_NewExternalTypedDataWithFinalizer(
|
||||
Dart_TypedData_kUint8, response_json, response_json_length, response_json,
|
||||
response_json_length,
|
||||
[](void* ignored, Dart_WeakPersistentHandle handle, void* peer) {
|
||||
free(peer);
|
||||
});
|
||||
EXPECT_VALID(bytes);
|
||||
|
||||
// We don't have a C++ JSON decoder so we'll invoke dart to validate the
|
||||
// result.
|
||||
const char* kScript =
|
||||
R"(
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
bool validate(bool condition) {
|
||||
if (!condition) {
|
||||
throw 'Failed to validate InvokeVMServiceMethod() response.';
|
||||
}
|
||||
}
|
||||
bool validateResult(Uint8List bytes) {
|
||||
final map = json.decode(utf8.decode(bytes));
|
||||
validate(map['jsonrpc'] == '2.0');
|
||||
validate(map['id'] == 'foo');
|
||||
validate(map['result']['name'] == 'vm');
|
||||
validate(map['result']['type'] == 'VM');
|
||||
validate(map['result'].containsKey('architectureBits'));
|
||||
validate(map['result'].containsKey('pid'));
|
||||
validate(map['result'].containsKey('startTime'));
|
||||
validate(map['result'].containsKey('hostCPU'));
|
||||
validate(map['result'].containsKey('targetCPU'));
|
||||
validate(map['result'].containsKey('version'));
|
||||
return true;
|
||||
}
|
||||
)";
|
||||
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
|
||||
EXPECT_VALID(lib);
|
||||
Dart_Handle result = Dart_Invoke(lib, NewString("validateResult"), 1, &bytes);
|
||||
EXPECT(Dart_IsBoolean(result));
|
||||
EXPECT(result == Dart_True());
|
||||
}
|
||||
|
||||
#endif // !PRODUCT
|
||||
|
||||
} // namespace dart
|
||||
|
||||
@@ -143,6 +143,10 @@ Dart_Port ServiceIsolate::Port() {
|
||||
|
||||
Dart_Port ServiceIsolate::WaitForLoadPort() {
|
||||
VMTagScope tagScope(Thread::Current(), VMTag::kLoadWaitTagId);
|
||||
return WaitForLoadPortInternal();
|
||||
}
|
||||
|
||||
Dart_Port ServiceIsolate::WaitForLoadPortInternal() {
|
||||
MonitorLocker ml(monitor_);
|
||||
while (state_ == kStarting && (load_port_ == ILLEGAL_PORT)) {
|
||||
ml.Wait();
|
||||
@@ -185,7 +189,7 @@ bool ServiceIsolate::SendServiceRpc(uint8_t* request_json,
|
||||
request.value.as_array.values = request_array;
|
||||
request.value.as_array.length = ARRAY_SIZE(request_array);
|
||||
|
||||
ServiceIsolate::WaitForLoadPort();
|
||||
ServiceIsolate::WaitForLoadPortInternal();
|
||||
return Dart_PostCObject(ServiceIsolate::Port(), &request);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@ class ServiceIsolate : public AllStatic {
|
||||
private:
|
||||
static void KillServiceIsolate();
|
||||
|
||||
// Does not need a current thread.
|
||||
static Dart_Port WaitForLoadPortInternal();
|
||||
|
||||
protected:
|
||||
static void SetServicePort(Dart_Port port);
|
||||
static void SetServiceIsolate(Isolate* isolate);
|
||||
|
||||
Reference in New Issue
Block a user