[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:
Martin Kustermann
2019-08-05 10:07:39 +00:00
committed by commit-bot@chromium.org
parent fd7baa4fd9
commit d3f3b46b87
6 changed files with 135 additions and 9 deletions
+7 -1
View File
@@ -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
View File
@@ -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;
+54 -5
View File
@@ -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;
+60
View File
@@ -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
+5 -1
View File
@@ -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);
}
+3
View File
@@ -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);