blob: 18baecafad73f676a3cd5b746585b18bc54963e8 [file] [log] [blame]
// Copyright 2019 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 "log_listener.h"
#include <lib/async/cpp/executor.h>
#include <lib/fit/bridge.h>
#include <lib/fit/promise.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/sys/cpp/testing/service_directory_provider.h>
#include <lib/sys/cpp/testing/test_with_environment.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "archive_accessor_stub.h"
#include "src/lib/testing/loop_fixture/test_loop_fixture.h"
using ::testing::ElementsAre;
constexpr char kMessage1Json[] = R"JSON(
[
{
"metadata": {
"timestamp": 1234000000000,
"severity": "INFO"
},
"payload": {
"root": {
"message": "Message 1",
"pid": 200,
"tid": 300,
"tag": "tag_1",
"tag": "tag_2"
}
}
}
]
)JSON";
constexpr char kMessage2Json[] = R"JSON(
[
{
"metadata": {
"timestamp": 1234000000000,
"severity": "INFO"
},
"payload": {
"root": {
"message": "Message 2",
"pid": 200,
"tid": 300,
"tag": "tag_2"
}
}
}
]
)JSON";
constexpr char kMessage3Json[] = R"JSON(
[
{
"metadata": {
"timestamp": 1234000000000,
"severity": "INFO"
},
"payload": {
"root": {
"message": "Message 3",
"pid": 200,
"tid": 300,
"tag": "tag_3"
}
}
}
]
)JSON";
class LogListenerTest : public gtest::TestLoopFixture {
public:
LogListenerTest()
: service_directory_provider_(sys::testing::ServiceDirectoryProvider()),
executor_(dispatcher()) {}
std::shared_ptr<sys::ServiceDirectory>& services() {
return service_directory_provider_.service_directory();
}
protected:
void SetupLogServer(std::unique_ptr<harvester::ArchiveAccessorStub> server) {
archive_ = std::move(server);
service_directory_provider_
.AddService<fuchsia::diagnostics::ArchiveAccessor>(
archive_bindings_.GetHandler(archive_.get()));
}
std::unique_ptr<harvester::ArchiveAccessorStub> archive_;
sys::testing::ServiceDirectoryProvider service_directory_provider_;
fidl::BindingSet<fuchsia::diagnostics::ArchiveAccessor> archive_bindings_;
async::Executor executor_;
};
TEST_F(LogListenerTest, TriggersCallbacks) {
SetupLogServer(std::make_unique<harvester::ArchiveAccessorStub>(
std::make_unique<harvester::BatchIteratorStub>(
std::vector<std::vector<std::string>>(
{{kMessage1Json, kMessage2Json}, {kMessage3Json}, {}}))));
harvester::LogListener listener(services());
int counter = 0;
listener.Listen([&counter](auto result) { counter++; });
RunLoopUntilIdle();
RunLoopFor(zx::sec(1));
EXPECT_EQ(counter, 2);
}
TEST_F(LogListenerTest, TriggersCallbackWithBatches) {
SetupLogServer(std::make_unique<harvester::ArchiveAccessorStub>(
std::make_unique<harvester::BatchIteratorStub>(
std::vector<std::vector<std::string>>(
{{kMessage1Json, kMessage2Json}, {kMessage3Json}, {}}))));
harvester::LogListener listener(services());
std::vector<std::string> logs = {};
listener.Listen([&logs](auto result) {
for (std::string json : result) {
logs.emplace_back(json);
}
});
RunLoopUntilIdle();
EXPECT_STREQ(logs[0].c_str(), kMessage1Json);
EXPECT_STREQ(logs[1].c_str(), kMessage2Json);
EXPECT_STREQ(logs[2].c_str(), kMessage3Json);
}
TEST_F(LogListenerTest, ClosesOnEmptyBatch) {
SetupLogServer(std::make_unique<harvester::ArchiveAccessorStub>(
std::make_unique<harvester::BatchIteratorStub>(
std::vector<std::vector<std::string>>(
{{kMessage1Json, kMessage2Json}, {}, {kMessage3Json}}))));
harvester::LogListener listener(services());
int counter = 0;
bool completed = false;
fit::promise<> promise =
listener.Listen([&counter](auto result) { counter++; })
.then([&completed](fit::result<>& result) {
if (result.is_ok()) {
completed = true;
}
});
executor_.schedule_task(std::move(promise));
RunLoopUntilIdle();
EXPECT_EQ(counter, 1);
EXPECT_TRUE(completed);
}
TEST_F(LogListenerTest, ClosesOnError) {
SetupLogServer(std::make_unique<harvester::ArchiveAccessorStub>(
std::make_unique<harvester::BatchIteratorReturnsErrorStub>()));
harvester::LogListener listener(services());
int counter = 0;
bool completedErr = false;
fit::promise<> promise =
listener.Listen([&counter](auto result) { counter++; })
.then([&completedErr](fit::result<>& result) {
if (result.is_error()) {
completedErr = true;
}
});
executor_.schedule_task(std::move(promise));
RunLoopUntilIdle();
EXPECT_EQ(counter, 0);
EXPECT_TRUE(completedErr);
}