Merge "Add --testdata flag for easier testing"
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 6837f25..d18cb8f 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -28,6 +28,7 @@
     Config_test.cpp \
     ConfigLocale_test.cpp \
     Idmap_test.cpp \
+    Main.cpp \
     ResTable_test.cpp \
     Split_test.cpp \
     TestHelpers.cpp \
@@ -59,7 +60,8 @@
     libutils \
     libcutils \
     liblog \
-    libz \
+    libz
+LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
 
 include $(BUILD_HOST_NATIVE_TEST)
 
@@ -80,7 +82,8 @@
     libbase \
     libcutils \
     libutils \
-    libui \
+    libui
+LOCAL_PICKUP_FILES := $(LOCAL_PATH)/data
 
 include $(BUILD_NATIVE_TEST)
 endif # Not SDK_ONLY
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index 7fbe6d3..d6d7890 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -15,24 +15,27 @@
  */
 
 #include "androidfw/AttributeResolution.h"
+
+#include "android-base/file.h"
+#include "android-base/logging.h"
+#include "android-base/macros.h"
+
 #include "TestHelpers.h"
 #include "data/styles/R.h"
 
-#include <android-base/file.h>
-#include <android-base/macros.h>
-
-using namespace android;
-using android::base::ReadFileToString;
 using com::android::app::R;
 
+namespace android {
+
 class AttributeResolutionTest : public ::testing::Test {
  public:
   virtual void SetUp() override {
-    std::string test_source_dir = TestSourceDir();
+    std::string test_source_dir = GetTestDataPath();
     std::string contents;
-    LOG_ALWAYS_FATAL_IF(!ReadFileToString(test_source_dir + "/styles/resources.arsc", &contents));
-    LOG_ALWAYS_FATAL_IF(
-        table_.add(contents.data(), contents.size(), 1 /*cookie*/, true /*copyData*/) != NO_ERROR);
+    CHECK(base::ReadFileToString(test_source_dir + "/styles/resources.arsc",
+                                 &contents));
+    CHECK(table_.add(contents.data(), contents.size(), 1 /*cookie*/,
+                     true /*copyData*/) == NO_ERROR);
   }
 
  protected:
@@ -43,11 +46,12 @@
  public:
   virtual void SetUp() override {
     AttributeResolutionTest::SetUp();
-    std::string test_source_dir = TestSourceDir();
+    std::string test_source_dir = GetTestDataPath();
     std::string contents;
-    LOG_ALWAYS_FATAL_IF(!ReadFileToString(test_source_dir + "/styles/layout.xml", &contents));
-    LOG_ALWAYS_FATAL_IF(xml_parser_.setTo(contents.data(), contents.size(), true /*copyData*/) !=
-                        NO_ERROR);
+    CHECK(base::ReadFileToString(test_source_dir + "/styles/layout.xml",
+                                 &contents));
+    CHECK(xml_parser_.setTo(contents.data(), contents.size(),
+                            true /*copyData*/) == NO_ERROR);
 
     // Skip to the first tag.
     while (xml_parser_.next() != ResXMLParser::START_TAG) {
@@ -68,8 +72,9 @@
   values.resize(arraysize(attrs) * 6);
 
   ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
-                           nullptr /*src_values*/, 0 /*src_values_length*/, attrs, arraysize(attrs),
-                           values.data(), nullptr /*out_indices*/));
+                           nullptr /*src_values*/, 0 /*src_values_length*/,
+                           attrs, arraysize(attrs), values.data(),
+                           nullptr /*out_indices*/));
 
   const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
 
@@ -111,8 +116,8 @@
   std::vector<uint32_t> values;
   values.resize(arraysize(attrs) * 6);
 
-  ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs, arraysize(attrs), values.data(),
-                                 nullptr /*out_indices*/));
+  ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs, arraysize(attrs),
+                                 values.data(), nullptr /*out_indices*/));
 
   uint32_t* values_cursor = values.data();
   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
@@ -151,13 +156,14 @@
   ResTable::Theme theme(table_);
   ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
 
-  uint32_t attrs[] = {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four,
-                      R::attr::attr_five};
+  uint32_t attrs[] = {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
+                      R::attr::attr_four, R::attr::attr_five};
   std::vector<uint32_t> values;
   values.resize(arraysize(attrs) * 6);
 
-  ASSERT_TRUE(ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs,
-                         arraysize(attrs), values.data(), nullptr /*out_indices*/));
+  ASSERT_TRUE(ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/,
+                         0 /*def_style_res*/, attrs, arraysize(attrs),
+                         values.data(), nullptr /*out_indices*/));
 
   const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
 
@@ -199,3 +205,5 @@
   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
 }
+
+}  // namespace android
diff --git a/libs/androidfw/tests/Main.cpp b/libs/androidfw/tests/Main.cpp
new file mode 100644
index 0000000..6a50691
--- /dev/null
+++ b/libs/androidfw/tests/Main.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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 <libgen.h>
+
+#include <iostream>
+#include <memory>
+#include <string>
+
+#include "android-base/file.h"
+#include "android-base/strings.h"
+#include "gtest/gtest.h"
+
+#include "TestHelpers.h"
+
+// Extract the directory of the current executable path.
+static std::string GetExecutableDir() {
+  const std::string path = android::base::GetExecutablePath();
+  std::unique_ptr<char, decltype(&std::free)> mutable_path = {
+      strdup(path.c_str()), std::free};
+  std::string executable_dir = dirname(mutable_path.get());
+  return executable_dir;
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  // Set the default test data path to be the executable path directory.
+  android::SetTestDataPath(GetExecutableDir());
+
+  const char* command = argv[0];
+  ++argv;
+  --argc;
+
+  while (argc > 0) {
+    const std::string arg = *argv;
+    if (android::base::StartsWith(arg, "--testdata=")) {
+      android::SetTestDataPath(arg.substr(strlen("--testdata=")));
+    } else if (arg == "-h" || arg == "--help") {
+      std::cerr
+          << "\nAdditional options specific to this test:\n"
+             "  --testdata=[PATH]\n"
+             "      Specify the location of test data used within the tests.\n";
+      return 1;
+    } else {
+      std::cerr << command << ": Unrecognized argument '" << *argv << "'.\n";
+      return 1;
+    }
+
+    --argc;
+    ++argv;
+  }
+
+  std::cerr << "using --testdata=" << android::GetTestDataPath() << "\n";
+  return RUN_ALL_TESTS();
+}
diff --git a/libs/androidfw/tests/TestHelpers.cpp b/libs/androidfw/tests/TestHelpers.cpp
index 3d1d5f5..702ee5c 100644
--- a/libs/androidfw/tests/TestHelpers.cpp
+++ b/libs/androidfw/tests/TestHelpers.cpp
@@ -16,26 +16,23 @@
 
 #include "TestHelpers.h"
 
-#include <androidfw/ResourceTypes.h>
-#include <gtest/gtest.h>
 #include <unistd.h>
-#include <utils/String8.h>
 
-std::string TestSourceDir() {
-  const char* dir = getenv("ANDROID_BUILD_TOP");
-  LOG_ALWAYS_FATAL_IF(dir == nullptr, "Environment variable ANDROID_BUILD_TOP must be set");
-  std::string testdir = std::string(dir) + "/frameworks/base/libs/androidfw/tests/data";
-
-  // Check that the directory exists.
-  struct stat filestat;
-  LOG_ALWAYS_FATAL_IF(stat(testdir.c_str(), &filestat) != 0, "test data path '%s' does not exist",
-                      testdir.c_str());
-  return testdir;
-}
+#include "android-base/logging.h"
 
 namespace android {
 
-::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
+static std::string sTestDataPath;
+
+void SetTestDataPath(const std::string& path) { sTestDataPath = path; }
+
+const std::string& GetTestDataPath() {
+  CHECK(!sTestDataPath.empty()) << "no test data path set.";
+  return sTestDataPath;
+}
+
+::testing::AssertionResult IsStringEqual(const ResTable& table,
+                                         uint32_t resource_id,
                                          const char* expected_str) {
   Res_value val;
   ssize_t block = table.getResource(resource_id, &val, MAY_NOT_BE_BAG);
@@ -49,7 +46,8 @@
 
   const ResStringPool* pool = table.getTableStringBlock(block);
   if (pool == NULL) {
-    return ::testing::AssertionFailure() << "table has no string pool for block " << block;
+    return ::testing::AssertionFailure()
+           << "table has no string pool for block " << block;
   }
 
   const String8 actual_str = pool->string8ObjectAt(val.data);
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index 5f0c4552..c1e349f 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-#ifndef __TEST_HELPERS_H
-#define __TEST_HELPERS_H
-
-#include <androidfw/ResourceTypes.h>
-#include <gtest/gtest.h>
-#include <utils/String16.h>
-#include <utils/String8.h>
+#ifndef TEST_HELPERS_H_
+#define TEST_HELPERS_H_
 
 #include <ostream>
 #include <string>
 
-std::string TestSourceDir();
+#include "androidfw/ResourceTypes.h"
+#include "gtest/gtest.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
 
-static inline ::std::ostream& operator<<(::std::ostream& out, const android::String8& str) {
+static inline ::std::ostream& operator<<(::std::ostream& out,
+                                         const android::String8& str) {
   return out << str.string();
 }
 
-static inline ::std::ostream& operator<<(::std::ostream& out, const android::String16& str) {
+static inline ::std::ostream& operator<<(::std::ostream& out,
+                                         const android::String16& str) {
   return out << android::String8(str).string();
 }
 
@@ -39,18 +39,24 @@
 
 enum { MAY_NOT_BE_BAG = false };
 
-static inline bool operator==(const android::ResTable_config& a,
-                              const android::ResTable_config& b) {
+void SetTestDataPath(const std::string& path);
+
+const std::string& GetTestDataPath();
+
+static inline bool operator==(const ResTable_config& a,
+                              const ResTable_config& b) {
   return a.compare(b) == 0;
 }
 
-static inline ::std::ostream& operator<<(::std::ostream& out, const android::ResTable_config& c) {
+static inline ::std::ostream& operator<<(::std::ostream& out,
+                                         const ResTable_config& c) {
   return out << c.toString().string();
 }
 
-::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resource_id,
+::testing::AssertionResult IsStringEqual(const ResTable& table,
+                                         uint32_t resource_id,
                                          const char* expected_str);
 
 }  // namespace android
 
-#endif  // __TEST_HELPERS_H
+#endif  // TEST_HELPERS_H_