art: Refactor RuntimeOptions/ParsedOptions

Refactor the RuntimeOptions to be a
type-safe map (VariantMap, see runtime_options.h) and the ParsedOptions
to delegate the parsing to CmdlineParser (see cmdline/cmdline_parser.h).

This is the start of a command line parsing refactor, and may include
more in the future (dex2oat, patchoat, etc).

For more details of the command line parsing generator usage see cmdline/README.md

Change-Id: Ic67c6bca5e1f33bf2ec60e2e3ff8c366bab91563
diff --git a/runtime/base/variant_map_test.cc b/runtime/base/variant_map_test.cc
new file mode 100644
index 0000000..827de46
--- /dev/null
+++ b/runtime/base/variant_map_test.cc
@@ -0,0 +1,168 @@
+/*
+ * 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), \
+                                        reinterpret_cast<void*>(NULL));
+
+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;
+  };
+
+  const FruitMap::Key<int> FruitMap::Apple;
+  const FruitMap::Key<double> FruitMap::Orange;
+}  // 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());
+
+  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, 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);
+  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