blob: a97cc3b9a672c5612bb2bd942bc712b14b1958d8 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ui/a11y/bin/a11y_tts_log_engine/log_engine.h"
#include <fuchsia/diagnostics/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/gtest/test_loop_fixture.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/sys/cpp/service_directory.h>
#include <list>
#include <memory>
#include <vector>
#include <gtest/gtest.h>
#include "macros.h"
#include "src/lib/diagnostics/accessor2logger/log_message.h"
#include "src/lib/testing/loop_fixture/real_loop_fixture.h"
#include "src/ui/a11y/lib/tts/tts_manager.h"
namespace a11y {
namespace {
using gtest::RealLoopFixture;
class LogEngineTest : public RealLoopFixture {
protected:
LogEngineTest() = default;
~LogEngineTest() override = default;
void SetUp() override {
startup_context_ = sys::ComponentContext::CreateAndServeOutgoingDirectory();
persistent_context_ = startup_context_.get();
tts_manager_ = std::make_unique<TtsManager>(startup_context_.get());
}
void Iterate(const std::shared_ptr<fuchsia::diagnostics::BatchIteratorPtr>& iterator) {
(*iterator)->GetNext([=](::fuchsia::diagnostics::BatchIterator_GetNext_Result result) {
auto content = std::move(result.response().batch);
for (auto& bot : content) {
auto values =
diagnostics::accessor2logger::ConvertFormattedContentToLogMessages(std::move(bot))
.value();
for (auto& msg : values) {
log_output_ << msg.value().msg;
}
}
std::vector<std::list<std::string>::iterator> to_delete;
for (auto it = expects_.begin(); it != expects_.end(); it++) {
if (log_output_.str().find(*it) != std::string::npos) {
to_delete.push_back(it);
}
}
for (auto i : to_delete) {
expects_.erase(i);
}
if (expects_.empty()) {
QuitLoop();
return;
}
Iterate(iterator);
});
}
// Initializes the global logger.
//
// This redirects the output to the socket pair |log_socket_local_| and |log_socket_remote_|
// so that we can capture it.
zx_status_t InitLogger() {
std::shared_ptr<fuchsia::diagnostics::BatchIteratorPtr> iterator =
std::make_shared<fuchsia::diagnostics::BatchIteratorPtr>();
auto res = persistent_context_->svc()->Connect(accessor_.NewRequest(dispatcher()));
::fuchsia::diagnostics::StreamParameters params;
params.set_data_type(fuchsia::diagnostics::DataType::LOGS);
params.set_stream_mode(fuchsia::diagnostics::StreamMode::SNAPSHOT_THEN_SUBSCRIBE);
params.set_format(fuchsia::diagnostics::Format::JSON);
accessor_->StreamDiagnostics(std::move(params), iterator->NewRequest(dispatcher()));
Iterate(iterator);
return ZX_OK;
}
void Expect(std::string&& log_message) { expects_.push_back(std::move(log_message)); }
bool GotExpected() { return expects_.empty(); }
bool LogContains(std::string&& msg) {
expects_.push_back(std::move(msg));
InitLogger();
RunLoop();
return expects_.empty();
}
fidl::InterfacePtr<fuchsia::logger::Log> log_service_;
fidl::InterfacePtr<fuchsia::diagnostics::ArchiveAccessor> accessor_;
std::list<std::string> expects_;
sys::ComponentContext* persistent_context_ = nullptr;
std::unique_ptr<sys::ComponentContext> startup_context_;
std::unique_ptr<TtsManager> tts_manager_;
std::stringstream log_output_;
};
TEST_F(LogEngineTest, OutputsLogs) {
fuchsia::accessibility::tts::EnginePtr speaker;
tts_manager_->OpenEngine(speaker.NewRequest(),
[](fuchsia::accessibility::tts::TtsManager_OpenEngine_Result result) {
EXPECT_TRUE(result.is_response());
});
RunLoopUntilIdle();
// Register the LogEngine.
LogEngine log_engine(std::move(startup_context_));
fidl::BindingSet<fuchsia::accessibility::tts::Engine> log_engine_bindings;
auto engine_handle = log_engine_bindings.AddBinding(&log_engine);
tts_manager_->RegisterEngine(
std::move(engine_handle),
[](fuchsia::accessibility::tts::EngineRegistry_RegisterEngine_Result result) {
EXPECT_TRUE(result.is_response());
});
RunLoopUntilIdle();
fuchsia::accessibility::tts::Utterance utterance;
utterance.set_message("hello world");
speaker->Enqueue(std::move(utterance), [](auto) {});
RunLoopUntilIdle();
EXPECT_TRUE(LogContains("Received utterance: hello world"));
speaker->Speak([](auto) {});
RunLoopUntilIdle();
EXPECT_TRUE(LogContains("Received a Speak. Dispatching the following utterances:"));
EXPECT_TRUE(LogContains(" - hello world"));
speaker->Cancel([]() {});
RunLoopUntilIdle();
EXPECT_TRUE(LogContains("Received a Cancel"));
// Print the logs out for debugging.
std::cerr << log_output_.str();
}
} // namespace
} // namespace a11y