/*
 * 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));
  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);
  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
