• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/common/task_runners.h"
6 #include "flutter/fml/paths.h"
7 #include "flutter/fml/synchronization/count_down_latch.h"
8 #include "flutter/fml/synchronization/waitable_event.h"
9 #include "flutter/runtime/dart_vm.h"
10 #include "flutter/runtime/dart_vm_lifecycle.h"
11 #include "flutter/runtime/runtime_test.h"
12 
13 namespace flutter {
14 namespace testing {
15 
16 using DartLifecycleTest = RuntimeTest;
17 
TEST_F(DartLifecycleTest,CanStartAndShutdownVM)18 TEST_F(DartLifecycleTest, CanStartAndShutdownVM) {
19   auto settings = CreateSettingsForFixture();
20   settings.leak_vm = false;
21   settings.enable_observatory = false;
22   ASSERT_FALSE(DartVMRef::IsInstanceRunning());
23   {
24     auto vm_ref = DartVMRef::Create(settings);
25     ASSERT_TRUE(DartVMRef::IsInstanceRunning());
26   }
27   ASSERT_FALSE(DartVMRef::IsInstanceRunning());
28 }
29 
TEST_F(DartLifecycleTest,CanStartAndShutdownVMOverAndOver)30 TEST_F(DartLifecycleTest, CanStartAndShutdownVMOverAndOver) {
31   auto settings = CreateSettingsForFixture();
32   settings.leak_vm = false;
33   settings.enable_observatory = false;
34   ASSERT_FALSE(DartVMRef::IsInstanceRunning());
35   auto count = DartVM::GetVMLaunchCount();
36   for (size_t i = 0; i < 10; i++) {
37     auto vm_ref = DartVMRef::Create(settings);
38     ASSERT_TRUE(DartVMRef::IsInstanceRunning());
39     ASSERT_EQ(DartVM::GetVMLaunchCount(), count + 1);
40     count = DartVM::GetVMLaunchCount();
41   }
42   ASSERT_FALSE(DartVMRef::IsInstanceRunning());
43 }
44 
CreateAndRunRootIsolate(const Settings & settings,const DartVMData & vm,fml::RefPtr<fml::TaskRunner> task_runner,std::string entrypoint)45 static std::shared_ptr<DartIsolate> CreateAndRunRootIsolate(
46     const Settings& settings,
47     const DartVMData& vm,
48     fml::RefPtr<fml::TaskRunner> task_runner,
49     std::string entrypoint) {
50   FML_CHECK(entrypoint.size() > 0);
51   TaskRunners runners("io.flutter.test", task_runner, task_runner, task_runner,
52                       task_runner);
53   auto isolate_weak = DartIsolate::CreateRootIsolate(
54       vm.GetSettings(),                   // settings
55       vm.GetIsolateSnapshot(),            // isolate_snapshot
56       vm.GetSharedSnapshot(),             // shared_snapshot
57       runners,                            // task_runners
58       {},                                 // window
59       {},                                 // io_manager
60       {},                                 // image_decoder
61       "main.dart",                        // advisory_script_uri
62       entrypoint.c_str(),                 // advisory_script_entrypoint
63       nullptr,                            // flags
64       settings.isolate_create_callback,   // isolate create callback
65       settings.isolate_shutdown_callback  // isolate shutdown callback
66   );
67 
68   auto isolate = isolate_weak.lock();
69 
70   if (!isolate) {
71     FML_LOG(ERROR) << "Could not create valid isolate.";
72     return nullptr;
73   }
74 
75   if (DartVM::IsRunningPrecompiledCode()) {
76     if (!isolate->PrepareForRunningFromPrecompiledCode()) {
77       FML_LOG(ERROR)
78           << "Could not prepare to run the isolate from precompiled code.";
79       return nullptr;
80     }
81 
82   } else {
83     if (!isolate->PrepareForRunningFromKernels(
84             settings.application_kernels())) {
85       FML_LOG(ERROR) << "Could not prepare isolate from application kernels.";
86       return nullptr;
87     }
88   }
89 
90   if (isolate->GetPhase() != DartIsolate::Phase::Ready) {
91     FML_LOG(ERROR) << "Isolate was not ready.";
92     return nullptr;
93   }
94 
95   if (!isolate->Run(entrypoint, {}, settings.root_isolate_create_callback)) {
96     FML_LOG(ERROR) << "Could not run entrypoint: " << entrypoint << ".";
97     return nullptr;
98   }
99 
100   if (isolate->GetPhase() != DartIsolate::Phase::Running) {
101     FML_LOG(ERROR) << "Isolate was not Running.";
102     return nullptr;
103   }
104 
105   return isolate;
106 }
107 
108 // TODO(chinmaygarde): This unit-test is flaky and indicates thread un-safety
109 // during shutdown. https://github.com/flutter/flutter/issues/36782
TEST_F(DartLifecycleTest,DISABLED_ShuttingDownTheVMShutsDownAllIsolates)110 TEST_F(DartLifecycleTest, DISABLED_ShuttingDownTheVMShutsDownAllIsolates) {
111   auto settings = CreateSettingsForFixture();
112   settings.leak_vm = false;
113   // Make sure the service protocol launches
114   settings.enable_observatory = true;
115 
116   for (size_t i = 0; i < 3; i++) {
117     ASSERT_FALSE(DartVMRef::IsInstanceRunning());
118 
119     const auto last_launch_count = DartVM::GetVMLaunchCount();
120 
121     auto vm_ref = DartVMRef::Create(settings);
122 
123     ASSERT_TRUE(DartVMRef::IsInstanceRunning());
124     ASSERT_EQ(last_launch_count + 1, DartVM::GetVMLaunchCount());
125 
126     const size_t isolate_count = 5;
127 
128     fml::CountDownLatch latch(isolate_count);
129     auto vm_data = vm_ref.GetVMData();
130     auto thread_task_runner = GetThreadTaskRunner();
131     for (size_t i = 0; i < isolate_count; ++i) {
132       thread_task_runner->PostTask(
133           [vm_data, &settings, &latch, thread_task_runner]() {
134             ASSERT_TRUE(CreateAndRunRootIsolate(settings, *vm_data.get(),
135                                                 thread_task_runner,
136                                                 "testIsolateShutdown"));
137             latch.CountDown();
138           });
139     }
140 
141     latch.Wait();
142   }
143   ASSERT_FALSE(DartVMRef::IsInstanceRunning());
144 }
145 
146 }  // namespace testing
147 }  // namespace flutter
148