Warn if oat file does end with expected extension

Change-Id: I17374fcb22193ef21fc5775be3a1e38c4b42da87
diff --git a/src/oat_file.cc b/src/oat_file.cc
index df81df8..a8b89a9 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -35,7 +35,7 @@
                        const std::string& location,
                        byte* requested_base,
                        bool writable) {
-  CHECK(!location.empty()) << filename;
+  CHECK(!filename.empty()) << location;
   UniquePtr<File> file(OS::OpenFile(filename.c_str(), writable, false));
   if (file.get() == NULL) {
     return NULL;
@@ -47,6 +47,10 @@
                        const std::string& location,
                        byte* requested_base,
                        bool writable) {
+  CHECK(!location.empty());
+  if (!IsValidOatFilename(location)) {
+    LOG(WARNING) << "Attempting to open dex file with unknown extension '" << location << "'";
+  }
   UniquePtr<OatFile> oat_file(new OatFile(location));
   bool success = oat_file->Map(file, requested_base, writable);
   if (!success) {
diff --git a/src/utils.cc b/src/utils.cc
index 03b6172..190cf4a 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -740,6 +740,16 @@
   return s.compare(0, strlen(prefix), prefix) == 0;
 }
 
+bool EndsWith(const std::string& s, const char* suffix) {
+  size_t suffix_length = strlen(suffix);
+  size_t string_length = s.size();
+  if (suffix_length > string_length) {
+    return false;
+  }
+  size_t offset = string_length - suffix_length;
+  return s.compare(offset, suffix_length, suffix) == 0;
+}
+
 void SetThreadName(const char* thread_name) {
   ANNOTATE_THREAD_NAME(thread_name); // For tsan.
 
@@ -888,11 +898,11 @@
 }
 
 bool IsValidDexFilename(const std::string& filename) {
-  if (filename.size() < 4) {
-    return false;
-  }
-  std::string suffix(filename.substr(filename.size() - 4));
-  return (suffix == ".dex");
+  return EndsWith(filename, ".dex");
+}
+
+bool IsValidOatFilename(const std::string& filename) {
+  return EndsWith(filename, ".oat");
 }
 
 }  // namespace art
diff --git a/src/utils.h b/src/utils.h
index b49d764..4bfd885 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -168,6 +168,9 @@
 // Tests whether 's' starts with 'prefix'.
 bool StartsWith(const std::string& s, const char* prefix);
 
+// Tests whether 's' starts with 'suffix'.
+bool EndsWith(const std::string& s, const char* suffix);
+
 // Used to implement PrettyClass, PrettyField, PrettyMethod, and PrettyTypeOf,
 // one of which is probably more useful to you.
 // Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
@@ -297,9 +300,10 @@
 // Returns the art-cache location for a DexFile or OatFile, or dies trying.
 std::string GetArtCacheFilenameOrDie(const std::string& location);
 
-// Check whether the given filename has a valid zip or dex extension
+// Check whether the given filename has a valid extension
 bool IsValidZipFilename(const std::string& filename);
 bool IsValidDexFilename(const std::string& filename);
+bool IsValidOatFilename(const std::string& filename);
 
 }  // namespace art
 
diff --git a/src/utils_test.cc b/src/utils_test.cc
index 3228bb6..3c93e4d 100644
--- a/src/utils_test.cc
+++ b/src/utils_test.cc
@@ -307,4 +307,18 @@
   EXPECT_EQ("foo:bar:baz", Join(strings, ':'));
 }
 
+TEST_F(UtilsTest, StartsWith) {
+  EXPECT_FALSE(StartsWith("foo", "bar"));
+  EXPECT_TRUE(StartsWith("foo", "foo"));
+  EXPECT_TRUE(StartsWith("food", "foo"));
+  EXPECT_FALSE(StartsWith("fo", "foo"));
+}
+
+TEST_F(UtilsTest, EndsWith) {
+  EXPECT_FALSE(EndsWith("foo", "bar"));
+  EXPECT_TRUE(EndsWith("foo", "foo"));
+  EXPECT_TRUE(EndsWith("foofoo", "foo"));
+  EXPECT_FALSE(EndsWith("oo", "foo"));
+}
+
 }  // namespace art