dart_isolate_unittests.cc 15.3 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

C
Chris Bracken 已提交
5 6
#include "flutter/runtime/dart_isolate.h"

7
#include "flutter/fml/mapping.h"
8
#include "flutter/fml/synchronization/count_down_latch.h"
9
#include "flutter/fml/synchronization/waitable_event.h"
10 11
#include "flutter/fml/thread.h"
#include "flutter/runtime/dart_vm.h"
12
#include "flutter/runtime/dart_vm_lifecycle.h"
13
#include "flutter/runtime/isolate_configuration.h"
D
Dan Field 已提交
14
#include "flutter/testing/dart_isolate_runner.h"
15
#include "flutter/testing/fixture_test.h"
16
#include "flutter/testing/testing.h"
17
#include "third_party/tonic/converter/dart_converter.h"
18
#include "third_party/tonic/scopes/dart_isolate_scope.h"
19

20
namespace flutter {
21
namespace testing {
22

Z
Zachary Anderson 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35
class DartIsolateTest : public FixtureTest {
 public:
  DartIsolateTest() {}

  void Wait() { latch_.Wait(); }

  void Signal() { latch_.Signal(); }

 private:
  fml::AutoResetWaitableEvent latch_;

  FML_DISALLOW_COPY_AND_ASSIGN(DartIsolateTest);
};
36 37

TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) {
38
  ASSERT_FALSE(DartVMRef::IsInstanceRunning());
39
  auto settings = CreateSettingsForFixture();
40 41 42 43
  auto vm_ref = DartVMRef::Create(settings);
  ASSERT_TRUE(vm_ref);
  auto vm_data = vm_ref.GetVMData();
  ASSERT_TRUE(vm_data);
44 45 46 47 48
  TaskRunners task_runners(GetCurrentTestName(),    //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner()   //
49
  );
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

  auto isolate_configuration =
      IsolateConfiguration::InferFromSettings(settings);

  auto weak_isolate = DartIsolate::CreateRunningRootIsolate(
      vm_data->GetSettings(),              // settings
      vm_data->GetIsolateSnapshot(),       // isolate snapshot
      std::move(task_runners),             // task runners
      nullptr,                             // window
      {},                                  // snapshot delegate
      {},                                  // hint freed delegate
      {},                                  // io manager
      {},                                  // unref queue
      {},                                  // image decoder
      "main.dart",                         // advisory uri
      "main",                              // advisory entrypoint,
      DartIsolate::Flags{},                // flags
      settings.isolate_create_callback,    // isolate create callback
      settings.isolate_shutdown_callback,  // isolate shutdown callback
      "main",                              // dart entrypoint
      std::nullopt,                        // dart entrypoint library
      std::move(isolate_configuration)     // isolate configuration
72
  );
73
  auto root_isolate = weak_isolate.lock();
74
  ASSERT_TRUE(root_isolate);
75
  ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Running);
76 77 78
  ASSERT_TRUE(root_isolate->Shutdown());
}

79
TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) {
80
  ASSERT_FALSE(DartVMRef::IsInstanceRunning());
81
  auto settings = CreateSettingsForFixture();
82 83 84 85
  auto vm_ref = DartVMRef::Create(settings);
  ASSERT_TRUE(vm_ref);
  auto vm_data = vm_ref.GetVMData();
  ASSERT_TRUE(vm_data);
86 87 88 89 90
  TaskRunners task_runners(GetCurrentTestName(),    //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner()   //
91
  );
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
  auto isolate_configuration =
      IsolateConfiguration::InferFromSettings(settings);
  auto weak_isolate = DartIsolate::CreateRunningRootIsolate(
      vm_data->GetSettings(),              // settings
      vm_data->GetIsolateSnapshot(),       // isolate snapshot
      std::move(task_runners),             // task runners
      nullptr,                             // window
      {},                                  // snapshot delegate
      {},                                  // hint freed delegate
      {},                                  // io manager
      {},                                  // unref queue
      {},                                  // image decoder
      "main.dart",                         // advisory uri
      "main",                              // advisory entrypoint
      DartIsolate::Flags{},                // flags
      settings.isolate_create_callback,    // isolate create callback
      settings.isolate_shutdown_callback,  // isolate shutdown callback
      "main",                              // dart entrypoint
      std::nullopt,                        // dart entrypoint library
      std::move(isolate_configuration)     // isolate configuration
112 113 114
  );
  auto root_isolate = weak_isolate.lock();
  ASSERT_TRUE(root_isolate);
115
  ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Running);
116 117 118 119 120 121 122 123 124
  size_t destruction_callback_count = 0;
  root_isolate->AddIsolateShutdownCallback([&destruction_callback_count]() {
    ASSERT_NE(Dart_CurrentIsolate(), nullptr);
    destruction_callback_count++;
  });
  ASSERT_TRUE(root_isolate->Shutdown());
  ASSERT_EQ(destruction_callback_count, 1u);
}

125
TEST_F(DartIsolateTest, IsolateCanLoadAndRunDartCode) {
126 127 128
  ASSERT_FALSE(DartVMRef::IsInstanceRunning());
  const auto settings = CreateSettingsForFixture();
  auto vm_ref = DartVMRef::Create(settings);
D
Dan Field 已提交
129 130 131 132 133 134 135 136
  TaskRunners task_runners(GetCurrentTestName(),    //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner()   //
  );
  auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners, "main",
                                      {}, GetFixturesPath());
137 138 139 140 141
  ASSERT_TRUE(isolate);
  ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
}

TEST_F(DartIsolateTest, IsolateCannotLoadAndRunUnknownDartEntrypoint) {
142 143 144
  ASSERT_FALSE(DartVMRef::IsInstanceRunning());
  const auto settings = CreateSettingsForFixture();
  auto vm_ref = DartVMRef::Create(settings);
D
Dan Field 已提交
145 146 147 148 149 150 151 152 153
  TaskRunners task_runners(GetCurrentTestName(),    //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner()   //
  );
  auto isolate =
      RunDartCodeInIsolate(vm_ref, settings, task_runners, "thisShouldNotExist",
                           {}, GetFixturesPath());
154 155 156
  ASSERT_FALSE(isolate);
}

157
TEST_F(DartIsolateTest, CanRunDartCodeCodeSynchronously) {
158 159 160
  ASSERT_FALSE(DartVMRef::IsInstanceRunning());
  const auto settings = CreateSettingsForFixture();
  auto vm_ref = DartVMRef::Create(settings);
D
Dan Field 已提交
161 162 163 164 165 166 167 168
  TaskRunners task_runners(GetCurrentTestName(),    //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner()   //
  );
  auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners, "main",
                                      {}, GetFixturesPath());
169 170

  ASSERT_TRUE(isolate);
171
  ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
172 173 174 175 176 177 178 179 180
  ASSERT_TRUE(isolate->RunInIsolateScope([]() -> bool {
    if (tonic::LogIfError(::Dart_Invoke(Dart_RootLibrary(),
                                        tonic::ToDart("sayHi"), 0, nullptr))) {
      return false;
    }
    return true;
  }));
}

181
TEST_F(DartIsolateTest, CanRegisterNativeCallback) {
182
  ASSERT_FALSE(DartVMRef::IsInstanceRunning());
183
  AddNativeCallback("NotifyNative",
Z
Zachary Anderson 已提交
184
                    CREATE_NATIVE_ENTRY(([this](Dart_NativeArguments args) {
185
                      FML_LOG(ERROR) << "Hello from Dart!";
Z
Zachary Anderson 已提交
186
                      Signal();
187
                    })));
188 189
  const auto settings = CreateSettingsForFixture();
  auto vm_ref = DartVMRef::Create(settings);
D
Dan Field 已提交
190 191 192 193 194 195 196 197 198 199
  auto thread = CreateNewThread();
  TaskRunners task_runners(GetCurrentTestName(),  //
                           thread,                //
                           thread,                //
                           thread,                //
                           thread                 //
  );
  auto isolate =
      RunDartCodeInIsolate(vm_ref, settings, task_runners,
                           "canRegisterNativeCallback", {}, GetFixturesPath());
200 201
  ASSERT_TRUE(isolate);
  ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
Z
Zachary Anderson 已提交
202
  Wait();
203 204
}

205 206 207 208 209 210 211
TEST_F(DartIsolateTest, CanSaveCompilationTrace) {
  if (DartVM::IsRunningPrecompiledCode()) {
    // Can only save compilation traces in JIT modes.
    GTEST_SKIP();
    return;
  }
  AddNativeCallback("NotifyNative",
Z
Zachary Anderson 已提交
212
                    CREATE_NATIVE_ENTRY(([this](Dart_NativeArguments args) {
213 214
                      ASSERT_TRUE(tonic::DartConverter<bool>::FromDart(
                          Dart_GetNativeArgument(args, 0)));
Z
Zachary Anderson 已提交
215
                      Signal();
216 217 218 219
                    })));

  const auto settings = CreateSettingsForFixture();
  auto vm_ref = DartVMRef::Create(settings);
D
Dan Field 已提交
220 221 222 223 224 225 226 227 228 229
  auto thread = CreateNewThread();
  TaskRunners task_runners(GetCurrentTestName(),  //
                           thread,                //
                           thread,                //
                           thread,                //
                           thread                 //
  );
  auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
                                      "testCanSaveCompilationTrace", {},
                                      GetFixturesPath());
230 231 232
  ASSERT_TRUE(isolate);
  ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);

Z
Zachary Anderson 已提交
233
  Wait();
234 235
}

Z
Zachary Anderson 已提交
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
class DartSecondaryIsolateTest : public FixtureTest {
 public:
  DartSecondaryIsolateTest() : latch_(3) {}

  void LatchCountDown() { latch_.CountDown(); }

  void LatchWait() { latch_.Wait(); }

  void ChildShutdownSignal() { child_shutdown_latch_.Signal(); }

  void ChildShutdownWait() { child_shutdown_latch_.Wait(); }

  void RootIsolateShutdownSignal() { root_isolate_shutdown_latch_.Signal(); }

  bool RootIsolateIsSignaled() {
    return root_isolate_shutdown_latch_.IsSignaledForTest();
  }

 private:
  fml::CountDownLatch latch_;
  fml::AutoResetWaitableEvent child_shutdown_latch_;
  fml::AutoResetWaitableEvent root_isolate_shutdown_latch_;

  FML_DISALLOW_COPY_AND_ASSIGN(DartSecondaryIsolateTest);
};

TEST_F(DartSecondaryIsolateTest, CanLaunchSecondaryIsolates) {
263
  AddNativeCallback("NotifyNative",
Z
Zachary Anderson 已提交
264 265
                    CREATE_NATIVE_ENTRY(([this](Dart_NativeArguments args) {
                      LatchCountDown();
266 267
                    })));
  AddNativeCallback(
Z
Zachary Anderson 已提交
268
      "PassMessage", CREATE_NATIVE_ENTRY(([this](Dart_NativeArguments args) {
269 270 271
        auto message = tonic::DartConverter<std::string>::FromDart(
            Dart_GetNativeArgument(args, 0));
        ASSERT_EQ("Hello from code is secondary isolate.", message);
Z
Zachary Anderson 已提交
272
        LatchCountDown();
273
      })));
274
  auto settings = CreateSettingsForFixture();
Z
Zachary Anderson 已提交
275 276
  settings.root_isolate_shutdown_callback = [this]() {
    RootIsolateShutdownSignal();
277
  };
Z
Zachary Anderson 已提交
278
  settings.isolate_shutdown_callback = [this]() { ChildShutdownSignal(); };
279
  auto vm_ref = DartVMRef::Create(settings);
D
Dan Field 已提交
280 281 282 283 284 285 286 287 288 289
  auto thread = CreateNewThread();
  TaskRunners task_runners(GetCurrentTestName(),  //
                           thread,                //
                           thread,                //
                           thread,                //
                           thread                 //
  );
  auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
                                      "testCanLaunchSecondaryIsolate", {},
                                      GetFixturesPath());
290 291
  ASSERT_TRUE(isolate);
  ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);
Z
Zachary Anderson 已提交
292 293 294
  ChildShutdownWait();  // wait for child isolate to shutdown first
  ASSERT_FALSE(RootIsolateIsSignaled());
  LatchWait();  // wait for last NotifyNative called by main isolate
295
  // root isolate will be auto-shutdown
296 297 298 299
}

TEST_F(DartIsolateTest, CanRecieveArguments) {
  AddNativeCallback("NotifyNative",
Z
Zachary Anderson 已提交
300
                    CREATE_NATIVE_ENTRY(([this](Dart_NativeArguments args) {
301 302
                      ASSERT_TRUE(tonic::DartConverter<bool>::FromDart(
                          Dart_GetNativeArgument(args, 0)));
Z
Zachary Anderson 已提交
303
                      Signal();
304 305 306 307
                    })));

  const auto settings = CreateSettingsForFixture();
  auto vm_ref = DartVMRef::Create(settings);
D
Dan Field 已提交
308 309 310 311 312 313 314 315 316 317
  auto thread = CreateNewThread();
  TaskRunners task_runners(GetCurrentTestName(),  //
                           thread,                //
                           thread,                //
                           thread,                //
                           thread                 //
  );
  auto isolate = RunDartCodeInIsolate(vm_ref, settings, task_runners,
                                      "testCanRecieveArguments", {"arg1"},
                                      GetFixturesPath());
318 319 320
  ASSERT_TRUE(isolate);
  ASSERT_EQ(isolate->get()->GetPhase(), DartIsolate::Phase::Running);

Z
Zachary Anderson 已提交
321
  Wait();
322 323
}

324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
TEST_F(DartIsolateTest, CanCreateServiceIsolate) {
#if (FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_DEBUG) && \
    (FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_PROFILE)
  GTEST_SKIP();
#endif
  ASSERT_FALSE(DartVMRef::IsInstanceRunning());
  fml::AutoResetWaitableEvent service_isolate_latch;
  auto settings = CreateSettingsForFixture();
  settings.enable_observatory = true;
  settings.observatory_port = 0;
  settings.observatory_host = "127.0.0.1";
  settings.enable_service_port_fallback = true;
  settings.service_isolate_create_callback = [&service_isolate_latch]() {
    service_isolate_latch.Signal();
  };
  auto vm_ref = DartVMRef::Create(settings);
  ASSERT_TRUE(vm_ref);
  auto vm_data = vm_ref.GetVMData();
  ASSERT_TRUE(vm_data);
  TaskRunners task_runners(GetCurrentTestName(),    //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner(),  //
                           GetCurrentTaskRunner()   //
  );

  auto isolate_configuration =
      IsolateConfiguration::InferFromSettings(settings);
  auto weak_isolate = DartIsolate::CreateRunningRootIsolate(
      vm_data->GetSettings(),              // settings
      vm_data->GetIsolateSnapshot(),       // isolate snapshot
      std::move(task_runners),             // task runners
      nullptr,                             // window
      {},                                  // snapshot delegate
      {},                                  // hint freed delegate
      {},                                  // io manager
      {},                                  // unref queue
      {},                                  // image decoder
      "main.dart",                         // advisory uri
      "main",                              // advisory entrypoint,
      DartIsolate::Flags{},                // flags
      settings.isolate_create_callback,    // isolate create callback
      settings.isolate_shutdown_callback,  // isolate shutdown callback
      "main",                              // dart entrypoint
      std::nullopt,                        // dart entrypoint library
      std::move(isolate_configuration)     // isolate configuration
  );
  auto root_isolate = weak_isolate.lock();
  ASSERT_TRUE(root_isolate);
  ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Running);
  service_isolate_latch.Wait();
  ASSERT_TRUE(root_isolate->Shutdown());
}

378
}  // namespace testing
379
}  // namespace flutter