blob: 6c41ffa29ed83210a6ccd1b25bf6cdc29f650501 [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 <fuchsia/diagnostics/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/spawn.h>
#include <algorithm>
#include <rapidjson/document.h>
#include <rapidjson/pointer.h>
#include <src/lib/fsl/vmo/strings.h>
#include "src/lib/testing/loop_fixture/test_loop_fixture.h"
namespace {
class LogBinaryTest : public gtest::TestLoopFixture {
protected:
LogBinaryTest() = default;
static void RunBinary(const char** args) {
ASSERT_EQ(ZX_OK,
fdio_spawn(ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, "/pkg/bin/log", args, nullptr));
}
};
struct TagMessagePair {
std::string tag;
std::string message;
bool operator==(const TagMessagePair& other) const {
return tag == other.tag && message == other.message;
}
};
std::vector<TagMessagePair> GetNextMessagePairs(
fuchsia::diagnostics::BatchIteratorSyncPtr* iterator) {
fuchsia::diagnostics::BatchIterator_GetNext_Result result;
if ((*iterator)->GetNext(&result) != ZX_OK || !result.is_response()) {
std::cout << "Failed to get next batch" << std::endl;
return {};
}
std::vector<TagMessagePair> ret;
for (const auto& entry : result.response().batch) {
std::string content;
if (!fsl::StringFromVmo(entry.json(), &content)) {
std::cout << "Failed to load JSON from a VMO" << std::endl;
return {};
}
std::cerr << "Received a log entry:\n" << content << std::endl;
rapidjson::Document document;
document.Parse(content);
for (const auto& value : document.GetArray()) {
auto* tag = rapidjson::Pointer("/metadata/tags/0").Get(value)->GetString();
auto* message = rapidjson::Pointer("/payload/root/message/value").Get(value)->GetString();
if (tag == nullptr) {
std::cout << "Missing tag" << std::endl;
return {};
}
if (message == nullptr) {
std::cout << "Missing message" << std::endl;
return {};
}
ret.emplace_back(TagMessagePair{.tag = tag, .message = message});
}
}
return ret;
}
// Log some values using the log binary, then check that those values can be read from the
// Archivist.
TEST_F(LogBinaryTest, LogValues) {
const char* args[] = {"log", "test", "hello", nullptr};
RunBinary(args);
const char* args2[] = {"log", "another_test", "hello again", nullptr};
RunBinary(args2);
std::string path = std::string("/svc/") + fuchsia::diagnostics::ArchiveAccessor::Name_;
fuchsia::diagnostics::ArchiveAccessorSyncPtr accessor;
ASSERT_EQ(ZX_OK,
fdio_service_connect(path.c_str(), accessor.NewRequest().TakeChannel().release()));
fuchsia::diagnostics::ClientSelectorConfiguration client_selector_config;
client_selector_config.set_select_all(true);
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);
params.set_client_selector_configuration(std::move(client_selector_config));
fuchsia::diagnostics::BatchIteratorSyncPtr iterator;
ASSERT_EQ(ZX_OK, accessor->StreamDiagnostics(std::move(params), iterator.NewRequest()));
std::vector<TagMessagePair> expected = {
TagMessagePair{.tag = "test", .message = "hello"},
TagMessagePair{.tag = "another_test", .message = "hello again"},
};
while (!expected.empty()) {
auto next = GetNextMessagePairs(&iterator);
ASSERT_FALSE(next.empty())
<< "Ran out of results from the iterator before all expected entries were found.";
while (!next.empty() && !expected.empty()) {
auto it = std::find(expected.begin(), expected.end(), next[0]);
if (it != expected.end()) {
expected.erase(it);
}
next.erase(next.begin());
}
}
}
} // namespace