/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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 "variant_map.h"
#include "gtest/gtest.h"

#define EXPECT_NULL(expected) EXPECT_EQ(reinterpret_cast<const void*>(expected), \
                                        static_cast<void*>(nullptr));

namespace art {

namespace {
template <typename TValue>
struct FruitMapKey : VariantMapKey<TValue> {
  FruitMapKey() {}
};

struct FruitMap : VariantMap<FruitMap, FruitMapKey> {
  // This 'using' line is necessary to inherit the variadic constructor.
  using VariantMap<FruitMap, FruitMapKey>::VariantMap;

  // Make the next '4' usages of Key slightly shorter to type.
  template <typename TValue>
  using Key = FruitMapKey<TValue>;

  static const Key<int> Apple;
  static const Key<double> Orange;
  static const Key<std::string> Label;
};

const FruitMap::Key<int> FruitMap::Apple;
const FruitMap::Key<double> FruitMap::Orange;
const FruitMap::Key<std::string> FruitMap::Label;
}  // namespace

TEST(VariantMaps, BasicReadWrite) {
  FruitMap fm;

  EXPECT_NULL(fm.Get(FruitMap::Apple));
  EXPECT_FALSE(fm.Exists(FruitMap::Apple));
  EXPECT_NULL(fm.Get(FruitMap::Orange));
  EXPECT_FALSE(fm.Exists(FruitMap::Orange));

  fm.Set(FruitMap::Apple, 1);
  EXPECT_NULL(fm.Get(FruitMap::Orange));
  EXPECT_EQ(1, *fm.Get(FruitMap::Apple));
  EXPECT_TRUE(fm.Exists(FruitMap::Apple));

  fm.Set(FruitMap::Apple, 5);
  EXPECT_NULL(fm.Get(FruitMap::Orange));
  EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
  EXPECT_TRUE(fm.Exists(FruitMap::Apple));

  fm.Set(FruitMap::Orange, 555.0);
  EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
  EXPECT_DOUBLE_EQ(555.0, *fm.Get(FruitMap::Orange));
  EXPECT_EQ(size_t(2), fm.Size());

  // Simple remove
  fm.Remove(FruitMap::Apple);
  EXPECT_FALSE(fm.Exists(FruitMap::Apple));

  fm.Clear();
  EXPECT_EQ(size_t(0), fm.Size());
  EXPECT_FALSE(fm.Exists(FruitMap::Orange));
}

TEST(VariantMaps, SetPreviousValue) {
  FruitMap fm;

  // Indirect remove by setting yourself again
  fm.Set(FruitMap::Label, std::string("hello_world"));
  auto* ptr = fm.Get(FruitMap::Label);
  ASSERT_TRUE(ptr != nullptr);
  *ptr = "foobar";

  // Set the value to the same exact pointer which we got out of the map.
  // This should cleanly 'just work' and not try to delete the value too early.
  fm.Set(FruitMap::Label, *ptr);

  auto* new_ptr = fm.Get(FruitMap::Label);
  ASSERT_TRUE(ptr != nullptr);
  EXPECT_EQ(std::string("foobar"), *new_ptr);
}

TEST(VariantMaps, RuleOfFive) {
  // Test empty constructor
  FruitMap fmEmpty;
  EXPECT_EQ(size_t(0), fmEmpty.Size());

  // Test empty constructor
  FruitMap fmFilled;
  fmFilled.Set(FruitMap::Apple, 1);
  fmFilled.Set(FruitMap::Orange, 555.0);
  EXPECT_EQ(size_t(2), fmFilled.Size());

  // Test copy constructor
  FruitMap fmEmptyCopy(fmEmpty);  // NOLINT
  EXPECT_EQ(size_t(0), fmEmptyCopy.Size());

  // Test copy constructor
  FruitMap fmFilledCopy(fmFilled);
  EXPECT_EQ(size_t(2), fmFilledCopy.Size());
  EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy.Get(FruitMap::Apple));
  EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy.Get(FruitMap::Orange));

  // Test operator=
  FruitMap fmFilledCopy2;
  fmFilledCopy2 = fmFilled;
  EXPECT_EQ(size_t(2), fmFilledCopy2.Size());
  EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy2.Get(FruitMap::Apple));
  EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy2.Get(FruitMap::Orange));

  // Test move constructor
  FruitMap fmMoved(std::move(fmFilledCopy));
  // NOLINTNEXTLINE - checking underlying storage has been freed
  EXPECT_EQ(size_t(0), fmFilledCopy.Size());
  EXPECT_EQ(size_t(2), fmMoved.Size());
  EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved.Get(FruitMap::Apple));
  EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved.Get(FruitMap::Orange));

  // Test operator= move
  FruitMap fmMoved2;
  fmMoved2.Set(FruitMap::Apple, 12345);  // This value will be clobbered after the move

  fmMoved2 = std::move(fmFilledCopy2);
  // NOLINTNEXTLINE - checking underlying storage has been freed
  EXPECT_EQ(size_t(0), fmFilledCopy2.Size());
  EXPECT_EQ(size_t(2), fmMoved2.Size());
  EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved2.Get(FruitMap::Apple));
  EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved2.Get(FruitMap::Orange));
}

TEST(VariantMaps, VariadicConstructors) {
  // Variadic constructor, 1 kv/pair
  FruitMap fmApple(FruitMap::Apple, 12345);
  EXPECT_EQ(size_t(1), fmApple.Size());
  EXPECT_EQ(12345, *fmApple.Get(FruitMap::Apple));

  // Variadic constructor, 2 kv/pair
  FruitMap fmAppleAndOrange(FruitMap::Apple,   12345,
                            FruitMap::Orange,  100.0);
  EXPECT_EQ(size_t(2), fmAppleAndOrange.Size());
  EXPECT_EQ(12345, *fmAppleAndOrange.Get(FruitMap::Apple));
  EXPECT_DOUBLE_EQ(100.0, *fmAppleAndOrange.Get(FruitMap::Orange));
}

TEST(VariantMaps, ReleaseOrDefault) {
  FruitMap fmAppleAndOrange(FruitMap::Apple,   12345,
                            FruitMap::Orange,  100.0);

  int apple = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
  EXPECT_EQ(12345, apple);

  // Releasing will also remove the Apple key.
  EXPECT_EQ(size_t(1), fmAppleAndOrange.Size());

  // Releasing again yields a default value.
  int apple2 = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
  EXPECT_EQ(0, apple2);
}

TEST(VariantMaps, GetOrDefault) {
  FruitMap fm(FruitMap::Apple,   12345);

  // Apple gives the expected value we set.
  int apple = fm.GetOrDefault(FruitMap::Apple);
  EXPECT_EQ(12345, apple);

  // Map is still 1.
  EXPECT_EQ(size_t(1), fm.Size());

  // Orange gives back a default value, since it's not in the map.
  double orange = fm.GetOrDefault(FruitMap::Orange);
  EXPECT_DOUBLE_EQ(0.0, orange);
}

}  // namespace art
