blob: e76844d2513d8c086baa6f6524b473a7954909b0 [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 "src/developer/feedback/feedback_agent/attachments/inspect_ptr.h"
#include <fuchsia/feedback/cpp/fidl.h>
#include <fuchsia/mem/cpp/fidl.h>
#include <lib/async/cpp/executor.h>
#include <lib/fit/result.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/zx/time.h>
#include <memory>
#include <string>
#include <vector>
#include "src/developer/feedback/feedback_agent/tests/stub_inspect_archive.h"
#include "src/developer/feedback/feedback_agent/tests/stub_inspect_batch_iterator.h"
#include "src/developer/feedback/feedback_agent/tests/stub_inspect_reader.h"
#include "src/developer/feedback/testing/cobalt_test_fixture.h"
#include "src/developer/feedback/testing/stubs/stub_cobalt_logger_factory.h"
#include "src/developer/feedback/testing/unit_test_fixture.h"
#include "src/developer/feedback/utils/cobalt_metrics.h"
#include "src/lib/fsl/vmo/strings.h"
#include "third_party/googletest/googlemock/include/gmock/gmock.h"
#include "third_party/googletest/googletest/include/gtest/gtest.h"
namespace feedback {
namespace {
using testing::IsEmpty;
using testing::UnorderedElementsAreArray;
class CollectInspectDataTest : public UnitTestFixture, public CobaltTestFixture {
public:
CollectInspectDataTest()
: CobaltTestFixture(/*unit_test_fixture=*/this), executor_(dispatcher()) {}
protected:
void SetUpInspect(std::unique_ptr<StubInspectArchive> inspect_archive) {
inspect_archive_ = std::move(inspect_archive);
if (inspect_archive_) {
InjectServiceProvider(inspect_archive_.get());
}
}
fit::result<fuchsia::mem::Buffer> CollectInspectData(const zx::duration timeout = zx::sec(1)) {
Cobalt cobalt(dispatcher(), services());
fit::result<fuchsia::mem::Buffer> result;
executor_.schedule_task(
feedback::CollectInspectData(dispatcher(), services(), timeout, &cobalt)
.then([&result](fit::result<fuchsia::mem::Buffer>& res) { result = std::move(res); }));
RunLoopFor(timeout);
return result;
}
void CheckNoTimeout() { EXPECT_THAT(ReceivedCobaltEvents(), IsEmpty()); }
void CheckTimeout() {
EXPECT_THAT(ReceivedCobaltEvents(), UnorderedElementsAreArray({
CobaltEvent(TimedOutData::kInspect),
}));
}
async::Executor executor_;
private:
std::unique_ptr<StubInspectArchive> inspect_archive_;
};
TEST_F(CollectInspectDataTest, Succeed_AllInspectData) {
SetUpInspect(std::make_unique<StubInspectArchive>(std::make_unique<StubInspectReader>(
std::make_unique<StubInspectBatchIterator>(std::vector<std::vector<std::string>>({
{"foo1", "foo2"},
{"bar1"},
{},
})))));
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_ok());
const fuchsia::mem::Buffer& inspect = result.value();
std::string inspect_json;
ASSERT_TRUE(fsl::StringFromVmo(inspect, &inspect_json));
ASSERT_STREQ(inspect_json.c_str(), R"([
foo1,
foo2,
bar1
])");
CheckNoTimeout();
}
TEST_F(CollectInspectDataTest, Succeed_PartialInspectData) {
SetUpInspect(std::make_unique<StubInspectArchive>(std::make_unique<StubInspectReader>(
std::make_unique<StubInspectBatchIteratorNeverRespondsAfterOneBatch>(
std::vector<std::string>({"foo1", "foo2"})))));
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_ok());
const fuchsia::mem::Buffer& inspect = result.value();
std::string inspect_json;
ASSERT_TRUE(fsl::StringFromVmo(inspect, &inspect_json));
ASSERT_STREQ(inspect_json.c_str(), R"([
foo1,
foo2
])");
CheckTimeout();
}
TEST_F(CollectInspectDataTest, Fail_NoInspectData) {
SetUpInspect(std::make_unique<StubInspectArchive>(std::make_unique<StubInspectReader>(
std::make_unique<StubInspectBatchIterator>(std::vector<std::vector<std::string>>({{}})))));
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckNoTimeout();
}
TEST_F(CollectInspectDataTest, Fail_BatchIteratorClosesConnection) {
SetUpInspect(std::make_unique<StubInspectArchive>(
std::make_unique<StubInspectReaderClosesBatchIteratorConnection>(
std::make_unique<StubInspectBatchIterator>())));
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckNoTimeout();
}
TEST_F(CollectInspectDataTest, Fail_BatchIteratorReturnsError) {
SetUpInspect(std::make_unique<StubInspectArchive>(std::make_unique<StubInspectReader>(
std::make_unique<StubInspectBatchIteratorReturnsError>())));
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckNoTimeout();
}
TEST_F(CollectInspectDataTest, Fail_BatchIteratorNeverResponds) {
SetUpInspect(std::make_unique<StubInspectArchive>(std::make_unique<StubInspectReader>(
std::make_unique<StubInspectBatchIteratorNeverResponds>())));
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckTimeout();
}
TEST_F(CollectInspectDataTest, Fail_ReaderClosesConnection) {
SetUpInspect(std::make_unique<StubInspectArchiveClosesReaderConnection>());
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckNoTimeout();
}
TEST_F(CollectInspectDataTest, Fail_ReaderReturnsError) {
SetUpInspect(
std::make_unique<StubInspectArchive>(std::make_unique<StubInspectReaderReturnsError>()));
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckNoTimeout();
}
TEST_F(CollectInspectDataTest, Fail_ReaderNeverResponds) {
SetUpInspect(
std::make_unique<StubInspectArchive>(std::make_unique<StubInspectReaderNeverResponds>()));
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckTimeout();
}
TEST_F(CollectInspectDataTest, Fail_ArchiveClosesConnection) {
SetUpInspect(std::make_unique<StubInspectArchiveClosesArchiveConnection>());
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckNoTimeout();
}
TEST_F(CollectInspectDataTest, Fail_ArchiveReturnsError) {
SetUpInspect(std::make_unique<StubInspectArchiveReturnsError>());
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckNoTimeout();
}
TEST_F(CollectInspectDataTest, Fail_ArchiveNeverResponds) {
SetUpInspect(std::make_unique<StubInspectArchiveNeverResponds>());
SetUpCobaltLoggerFactory(std::make_unique<StubCobaltLoggerFactory>());
fit::result<fuchsia::mem::Buffer> result = CollectInspectData();
ASSERT_TRUE(result.is_error());
CheckTimeout();
}
TEST_F(CollectInspectDataTest, Fail_CallCollectTwice) {
Cobalt cobalt(dispatcher(), services());
const zx::duration unused_timeout = zx::sec(1);
Inspect inspect(dispatcher(), services(), &cobalt);
executor_.schedule_task(inspect.Collect(unused_timeout));
ASSERT_DEATH(inspect.Collect(unused_timeout),
testing::HasSubstr("Collect() is not intended to be called twice"));
}
} // namespace
} // namespace feedback