// Copyright 2024 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "explanations.h"

#include "test.h"

namespace {

const void* MakeItem(size_t v) {
  return reinterpret_cast<const void*>(v);
}

}  // namespace

TEST(Explanations, Explanations) {
  Explanations exp;

  exp.Record(MakeItem(1), "first explanation");
  exp.Record(MakeItem(1), "second explanation");
  exp.Record(MakeItem(2), "third explanation");
  exp.Record(MakeItem(2), "fourth %s", "explanation");

  std::vector<std::string> list;

  exp.LookupAndAppend(MakeItem(0), &list);
  ASSERT_TRUE(list.empty());

  exp.LookupAndAppend(MakeItem(1), &list);
  ASSERT_EQ(2u, list.size());
  EXPECT_EQ(list[0], "first explanation");
  EXPECT_EQ(list[1], "second explanation");

  exp.LookupAndAppend(MakeItem(2), &list);
  ASSERT_EQ(4u, list.size());
  EXPECT_EQ(list[0], "first explanation");
  EXPECT_EQ(list[1], "second explanation");
  EXPECT_EQ(list[2], "third explanation");
  EXPECT_EQ(list[3], "fourth explanation");
}

TEST(Explanations, OptionalExplanationsNonNull) {
  Explanations parent;
  OptionalExplanations exp(&parent);

  exp.Record(MakeItem(1), "first explanation");
  exp.Record(MakeItem(1), "second explanation");
  exp.Record(MakeItem(2), "third explanation");
  exp.Record(MakeItem(2), "fourth %s", "explanation");

  std::vector<std::string> list;

  exp.LookupAndAppend(MakeItem(0), &list);
  ASSERT_TRUE(list.empty());

  exp.LookupAndAppend(MakeItem(1), &list);
  ASSERT_EQ(2u, list.size());
  EXPECT_EQ(list[0], "first explanation");
  EXPECT_EQ(list[1], "second explanation");

  exp.LookupAndAppend(MakeItem(2), &list);
  ASSERT_EQ(4u, list.size());
  EXPECT_EQ(list[0], "first explanation");
  EXPECT_EQ(list[1], "second explanation");
  EXPECT_EQ(list[2], "third explanation");
  EXPECT_EQ(list[3], "fourth explanation");
}

TEST(Explanations, OptionalExplanationsWithNullPointer) {
  OptionalExplanations exp(nullptr);

  exp.Record(MakeItem(1), "first explanation");
  exp.Record(MakeItem(1), "second explanation");
  exp.Record(MakeItem(2), "third explanation");
  exp.Record(MakeItem(2), "fourth %s", "explanation");

  std::vector<std::string> list;
  exp.LookupAndAppend(MakeItem(0), &list);
  ASSERT_TRUE(list.empty());

  exp.LookupAndAppend(MakeItem(1), &list);
  ASSERT_TRUE(list.empty());

  exp.LookupAndAppend(MakeItem(2), &list);
  ASSERT_TRUE(list.empty());
}
