Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | Private Member Functions | List of all members
dart_runner::DartTestComponentController Class Reference

#include <dart_test_component_controller.h>

Inheritance diagram for dart_runner::DartTestComponentController:

Public Member Functions

 DartTestComponentController (fuchsia::component::runner::ComponentStartInfo start_info, std::shared_ptr< sys::ServiceDirectory > runner_incoming_services, fidl::InterfaceRequest< fuchsia::component::runner::ComponentController > controller, DoneCallback done_callback)
 
 ~DartTestComponentController () override
 
void SetUp ()
 
void GetTests (fidl::InterfaceRequest< fuchsia::test::CaseIterator > iterator) override
 |Suite| protocol implementation.
 
void Run (std::vector< fuchsia::test::Invocation > tests, fuchsia::test::RunOptions options, fidl::InterfaceHandle< fuchsia::test::RunListener > listener) override
 |Suite| protocol implementation.
 
fidl::InterfaceRequestHandler< fuchsia::test::Suite > GetHandler ()
 

Private Member Functions

void Kill () override
 
void Stop () override
 

Detailed Description

Starts a Dart test component written in CFv2. It's different from DartComponentController in that it must implement the |fuchsia.test.Suite| protocol. It was forked to avoid a naming clash between the two classes' methods as the Suite protocol requires a Run() method for the test_manager to call on. This way, we avoid an extra layer between the test_manager and actual test execution. TODO(fxb/98369): Look into combining the two component classes once dart testing is stable.

Definition at line 35 of file dart_test_component_controller.h.

Constructor & Destructor Documentation

◆ DartTestComponentController()

dart_runner::DartTestComponentController::DartTestComponentController ( fuchsia::component::runner::ComponentStartInfo  start_info,
std::shared_ptr< sys::ServiceDirectory >  runner_incoming_services,
fidl::InterfaceRequest< fuchsia::component::runner::ComponentController >  controller,
DoneCallback  done_callback 
)

Definition at line 102 of file dart_test_component_controller.cc.

108 : loop_(new async::Loop(&kLoopConfig)),
109 executor_(loop_->dispatcher()),
110 label_(GetLabelFromUrl(start_info.resolved_url())),
111 url_(std::move(start_info.resolved_url())),
112 runner_incoming_services_(runner_incoming_services),
113 start_info_(std::move(start_info)),
114 binding_(this),
115 done_callback_(std::move(done_callback)) {
116 // TODO(fxb/84537): This data path is configured based how we build Flutter
117 // applications in tree currently, but the way we build the Flutter
118 // application may change. We should avoid assuming the data path and let the
119 // CML file specify this data path instead.
120 test_component_name_ = GetComponentNameFromUrl(url_);
121 data_path_ = "pkg/data/" + test_component_name_;
122
123 if (controller.is_valid()) {
124 binding_.Bind(std::move(controller));
125 binding_.set_error_handler([this](zx_status_t status) { Kill(); });
126 } else {
127 FML_LOG(ERROR) << "Fuchsia component controller endpoint is not valid.";
128 }
129
130 zx_status_t idle_timer_status =
131 zx::timer::create(ZX_TIMER_SLACK_LATE, ZX_CLOCK_MONOTONIC, &idle_timer_);
132 if (idle_timer_status != ZX_OK) {
133 FML_LOG(INFO) << "Idle timer creation failed: "
134 << zx_status_get_string(idle_timer_status);
135 } else {
136 idle_wait_.set_object(idle_timer_.get());
137 idle_wait_.set_trigger(ZX_TIMER_SIGNALED);
138 idle_wait_.Begin(async_get_default_dispatcher());
139 }
140
141 // Close the runtime_dir channel if we don't intend to serve it. Otherwise any
142 // access to the runtime_dir will hang forever.
143 start_info_.clear_runtime_dir();
144}
#define FML_LOG(severity)
Definition logging.h:82
#define ERROR(message)

◆ ~DartTestComponentController()

dart_runner::DartTestComponentController::~DartTestComponentController ( )
override

Definition at line 146 of file dart_test_component_controller.cc.

146 {
147 if (namespace_) {
148 fdio_ns_destroy(namespace_);
149 namespace_ = nullptr;
150 }
151 close(stdout_fd_);
152 close(stderr_fd_);
153}

Member Function Documentation

◆ GetHandler()

fidl::InterfaceRequestHandler< fuchsia::test::Suite > dart_runner::DartTestComponentController::GetHandler ( )
inline

Definition at line 64 of file dart_test_component_controller.h.

64 {
65 return suite_bindings_.GetHandler(this, loop_->dispatcher());
66 }

◆ GetTests()

void dart_runner::DartTestComponentController::GetTests ( fidl::InterfaceRequest< fuchsia::test::CaseIterator >  iterator)
override

|Suite| protocol implementation.

Definition at line 408 of file dart_test_component_controller.cc.

409 {
410 auto case_iterator = std::make_unique<CaseIterator>(
411 std::move(iterator), loop_->dispatcher(), test_component_name_,
412 [this](CaseIterator* case_iterator) {
413 RemoveCaseInterator(case_iterator);
414 });
415 case_iterators_.emplace(case_iterator.get(), std::move(case_iterator));
416}

◆ Kill()

void dart_runner::DartTestComponentController::Kill ( )
overrideprivate

Definition at line 587 of file dart_test_component_controller.cc.

587 {
588 done_callback_(this);
589 close(stdout_fd_);
590 close(stderr_fd_);
591 suite_bindings_.CloseAll();
592 if (Dart_CurrentIsolate()) {
595 if (queue) {
596 queue->Destroy();
597 }
598
599 loop_->Quit();
600
601 // TODO(rosswang): The docs warn of threading issues if doing this again,
602 // but without this, attempting to shut down the isolate finalizes app
603 // contexts that can't tell a shutdown is in progress and so fatal.
605
607 }
608}
static DartMicrotaskQueue * GetForCurrentThread()
DART_EXPORT void Dart_ShutdownIsolate(void)
DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void)
DART_EXPORT void Dart_SetMessageNotifyCallback(Dart_MessageNotifyCallback message_notify_callback)
VkQueue queue
Definition main.cc:55

◆ Run()

void dart_runner::DartTestComponentController::Run ( std::vector< fuchsia::test::Invocation >  tests,
fuchsia::test::RunOptions  options,
fidl::InterfaceHandle< fuchsia::test::RunListener >  listener 
)
override

|Suite| protocol implementation.

Definition at line 419 of file dart_test_component_controller.cc.

422 {
423 std::vector<std::string> args;
424 if (options.has_arguments()) {
425 args = std::move(*options.mutable_arguments());
426 }
427
428 auto listener_proxy = listener.Bind();
429
430 // We expect 1 test that will run all other tests in the test suite (i.e. a
431 // single main.dart that calls out to all of the dart tests). If the dart
432 // implementation in-tree changes, iterating over the invocations like so
433 // will be able to handle that.
434 for (auto it = tests.begin(); it != tests.end(); it++) {
435 auto invocation = std::move(*it);
436 std::string test_case_name;
437 if (invocation.has_name()) {
438 test_case_name = invocation.name();
439 }
440
441 // Create and out/err sockets and pass file descriptor for each to the
442 // dart process so that logging can be forwarded to the test_manager.
443 auto status = zx::socket::create(0, &out_, &out_client_);
444 if (status != ZX_OK) {
445 FML_LOG(FATAL) << "cannot create out socket: "
446 << zx_status_get_string(status);
447 }
448
449 status = fdio_fd_create(out_.release(), &stdout_fd_);
450 if (status != ZX_OK) {
451 FML_LOG(FATAL) << "failed to extract output fd: "
452 << zx_status_get_string(status);
453 }
454
455 status = zx::socket::create(0, &err_, &err_client_);
456 if (status != ZX_OK) {
457 FML_LOG(FATAL) << "cannot create error socket: "
458 << zx_status_get_string(status);
459 }
460
461 status = fdio_fd_create(err_.release(), &stderr_fd_);
462 if (status != ZX_OK) {
463 FML_LOG(FATAL) << "failed to extract error fd: "
464 << zx_status_get_string(status);
465 }
466
467 // Pass client end of out and err socket for test_manager to stream logs to
468 // current terminal, via |fuchsia::test::StdHandles|.
469 fuchsia::test::StdHandles std_handles;
470 std_handles.set_out(std::move(out_client_));
471 std_handles.set_err(std::move(err_client_));
472
473 listener_proxy->OnTestCaseStarted(std::move(invocation),
474 std::move(std_handles),
475 case_listener_.NewRequest());
476
477 // Run dart main and wait until exit code has been set before notifying of
478 // test completion.
479 auto dart_main_promise = fpromise::make_promise([&] { RunDartMain(); });
480 auto dart_state = tonic::DartState::Current();
481 executor_.schedule_task(std::move(dart_main_promise));
482 while (!dart_state->has_set_return_code()) {
483 loop_->Run(zx::deadline_after(kTestTimeout), true);
484 }
485
486 // Notify the test_manager that the test has completed.
487 listener_proxy->OnFinished();
488 }
489
490 if (binding_.is_bound()) {
491 // From the documentation for ComponentController, ZX_OK should be sent when
492 // the ComponentController receives a termination request. However, if the
493 // component exited with a non-zero return code, we indicate this by sending
494 // an INTERNAL epitaph instead.
495 //
496 // TODO(fxb/86666): Communicate return code from the ComponentController
497 // once v2 has support.
498 if (return_code_ == 0) {
499 binding_.Close(ZX_OK);
500 } else {
501 binding_.Close(zx_status_t(fuchsia::component::Error::INTERNAL));
502 }
503 }
504
505 // Stop and kill the test component.
506 Stop();
507}
static BlurTest tests[]
Definition BlurTest.cpp:84
const char * options
static DartState * Current()
Definition dart_state.cc:56
#define FATAL(error)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args

◆ SetUp()

void dart_runner::DartTestComponentController::SetUp ( )

Sets up the controller.

This should be called before |Run|.

Definition at line 155 of file dart_test_component_controller.cc.

155 {
156 // Name the thread after the url of the component being launched.
157 zx::thread::self()->set_property(ZX_PROP_NAME, label_.c_str(), label_.size());
158 Dart_SetThreadName(label_.c_str());
159
160 if (!CreateAndBindNamespace()) {
161 return;
162 }
163
164 if (SetUpFromAppSnapshot()) {
165 FML_LOG(INFO) << url_ << " is running from an app snapshot";
166 } else if (SetUpFromKernel()) {
167 FML_LOG(INFO) << url_ << " is running from kernel";
168 } else {
169 FML_LOG(ERROR) << "Failed to set up component controller for " << url_;
170 return;
171 }
172
173 // Serve |fuchsia::test::Suite| on outgoing directory.
174 suite_context_ = sys::ComponentContext::Create();
175 suite_context_->outgoing()->AddPublicService(this->GetHandler());
176 suite_context_->outgoing()->Serve(
177 std::move(*start_info_.mutable_outgoing_dir()), loop_->dispatcher());
178
179 loop_->Run();
180}
fidl::InterfaceRequestHandler< fuchsia::test::Suite > GetHandler()
DART_EXPORT void Dart_SetThreadName(const char *name)

◆ Stop()

void dart_runner::DartTestComponentController::Stop ( )
overrideprivate

Definition at line 637 of file dart_test_component_controller.cc.

637 {
638 Kill();
639}

The documentation for this class was generated from the following files: