blob: dd965e59002737c397e333ba3bd1ef92589b3265 [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/ledger/cloud_provider_in_memory/lib/diff_tree.h"
#include <fuchsia/ledger/cloud/cpp/fidl.h>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "src/ledger/bin/fidl/include/types.h"
using testing::IsEmpty;
using testing::UnorderedElementsAre;
namespace ledger {
namespace {
TEST(DiffTreeTest, SmallestDiff) {
DiffTree tree;
tree.AddDiff("commit1", std::nullopt,
{{"entry0", cloud_provider::Operation::INSERTION, "data0"}});
tree.AddDiff("commit2", "commit1", {{"entry1", cloud_provider::Operation::INSERTION, "data1_A"}});
tree.AddDiff("commit3", "commit2", {{"entry1", cloud_provider::Operation::DELETION, "data1_B"}});
// There are two possible diffs:
// - from the empty page to commit1, with one entry.
// - from commit3 to commit1, with zero entries.
// Check that we select the smallest diff.
auto [base_state, diff] = tree.GetSmallestDiff("commit1", {"commit3"});
EXPECT_EQ(base_state, "commit3");
EXPECT_THAT(diff, IsEmpty());
}
TEST(DiffTreeTest, SmallestDiffFromEmpty) {
DiffTree tree;
tree.AddDiff("commit1", std::nullopt,
{{"entry0", cloud_provider::Operation::INSERTION, "data0"}});
tree.AddDiff("commit2", "commit1",
{{"entry0", cloud_provider::Operation::DELETION, "data0"},
{"entry1", cloud_provider::Operation::INSERTION, "data1_A"}});
// There are two possible diffs:
// - from the empty page to commit1, with one entry.
// - from commit2 to commit1, with two entries.
// Check that we select the smallest diff.
auto [base_state, diff] = tree.GetSmallestDiff("commit1", {"commit3"});
EXPECT_EQ(base_state, std::nullopt);
EXPECT_EQ(
diff,
(std::vector<CloudDiffEntry>{{"entry0", cloud_provider::Operation::INSERTION, "data0"}}));
}
TEST(DiffTreeTest, ComplexDiff) {
// The diff tree is the following:
// (origin)
// | (size = 4)
// (ancestor)
// / \ (sizes = 2, one common deletion)
// (A) (B)
// | | (sizes = 1)
// (C) (D)
// If we ask for (D) with (C) as a possible base, we should get the diff from (C) to (D).
DiffTree tree;
tree.AddDiff("ancestor", "origin",
{{"e0", cloud_provider::Operation::INSERTION, "data_e0"},
{"e1", cloud_provider::Operation::DELETION, "data_e1"},
{"e2", cloud_provider::Operation::INSERTION, "data_e2"},
{"e3", cloud_provider::Operation::INSERTION, "data_e3"}});
tree.AddDiff("A", "ancestor",
{{"e0", cloud_provider::Operation::DELETION, "data_e0"},
{"f0", cloud_provider::Operation::INSERTION, "data_f0"}});
tree.AddDiff("B", "ancestor",
{{"e0", cloud_provider::Operation::DELETION, "data_e0"},
{"g0", cloud_provider::Operation::INSERTION, "data_g0"}});
tree.AddDiff("C", "A", {{"f1", cloud_provider::Operation::INSERTION, "data_f1"}});
tree.AddDiff("D", "B", {{"g1", cloud_provider::Operation::INSERTION, "data_g1"}});
// We can get a diff from the origin.
{
auto [base_state, diff] = tree.GetSmallestDiff("D", {});
EXPECT_EQ(base_state, "origin");
EXPECT_THAT(diff, UnorderedElementsAre(
CloudDiffEntry{"e1", cloud_provider::Operation::DELETION, "data_e1"},
CloudDiffEntry{"e2", cloud_provider::Operation::INSERTION, "data_e2"},
CloudDiffEntry{"e3", cloud_provider::Operation::INSERTION, "data_e3"},
CloudDiffEntry{"g0", cloud_provider::Operation::INSERTION, "data_g0"},
CloudDiffEntry{"g1", cloud_provider::Operation::INSERTION, "data_g1"}));
}
// If we have C, we can get a smaller diff.
{
auto [base_state, diff] = tree.GetSmallestDiff("D", {"C"});
EXPECT_EQ(base_state, "C");
EXPECT_THAT(diff, UnorderedElementsAre(
CloudDiffEntry{"f0", cloud_provider::Operation::DELETION, "data_f0"},
CloudDiffEntry{"f1", cloud_provider::Operation::DELETION, "data_f1"},
CloudDiffEntry{"g0", cloud_provider::Operation::INSERTION, "data_g0"},
CloudDiffEntry{"g1", cloud_provider::Operation::INSERTION, "data_g1"}));
}
}
} // namespace
} // namespace ledger