Bug 1271483 - p16. gtest for list-string functions - r?cpearce draft
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 26 May 2016 19:24:35 +1000
changeset 371291 89a24835ba7432bffb9c0c095a98a619a5750658
parent 371208 38a0f9808dc03c0997984b4713c370ec24f76070
child 521959 3c7a46a64f50e5224c44009c687c565416804012
push id19291
push usergsquelart@mozilla.com
push dateThu, 26 May 2016 09:33:37 +0000
reviewerscpearce
bugs1271483
milestone49.0a1
Bug 1271483 - p16. gtest for list-string functions - r?cpearce Because it is templated code inside a cpp, the test includes a copy of that code. When we make this more public, the test should then include the proper header instead. MozReview-Commit-ID: 3vOvaj5VVhm
dom/media/gtest/TestDecoderDoctor.cpp
dom/media/gtest/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/media/gtest/TestDecoderDoctor.cpp
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+#include "nsString.h"
+
+namespace mozilla {
+
+// Very ugly, but needed for now! It gives some confidence that the code works.
+// This is a copy of the template code in DecoderDoctorDiagnostics.cpp.
+// TODO:
+// When this gets moved to a more public place, we should just include the
+// appropriate headers and test the real code.
+
+template <typename String>
+class StringListRange
+{
+  typedef typename String::char_type CharType;
+  typedef const CharType* Pointer;
+
+public:
+  // Iterator into range, trims items and skips empty items.
+  class Iterator
+  {
+  public:
+    bool operator!=(const Iterator& a) const
+    {
+      return mStart != a.mStart || mEnd != a.mEnd;
+    }
+    Iterator& operator++()
+    {
+      SearchItemAt(mComma + 1);
+      return *this;
+    }
+    typedef decltype(Substring(Pointer(), Pointer())) DereferencedType;
+    DereferencedType operator*()
+    {
+      return Substring(mStart, mEnd);
+    }
+  private:
+    friend class StringListRange;
+    Iterator(const CharType* aRangeStart, uint32_t aLength)
+      : mRangeEnd(aRangeStart + aLength)
+    {
+      SearchItemAt(aRangeStart);
+    }
+    void SearchItemAt(Pointer start)
+    {
+      // First, skip leading whitespace.
+      for (Pointer p = start; ; ++p) {
+        if (p >= mRangeEnd) {
+          mStart = mEnd = mComma = mRangeEnd;
+          return;
+        }
+        auto c = *p;
+        if (c == CharType(',')) {
+          // Comma -> Empty item -> Skip.
+        } else if (c != CharType(' ')) {
+          mStart = p;
+          break;
+        }
+      }
+      // Find comma, recording start of trailing space.
+      Pointer trailingWhitespace = nullptr;
+      for (Pointer p = mStart + 1; ; ++p) {
+        if (p >= mRangeEnd) {
+          mEnd = trailingWhitespace ? trailingWhitespace : p;
+          mComma = p;
+          return;
+        }
+        auto c = *p;
+        if (c == CharType(',')) {
+          mEnd = trailingWhitespace ? trailingWhitespace : p;
+          mComma = p;
+          return;
+        }
+        if (c == CharType(' ')) {
+          // Found a whitespace -> Record as trailing if not first one.
+          if (!trailingWhitespace) {
+            trailingWhitespace = p;
+          }
+        } else {
+          // Found a non-whitespace -> Reset trailing whitespace if needed.
+          if (trailingWhitespace) {
+            trailingWhitespace = nullptr;
+          }
+        }
+      }
+    }
+    const Pointer mRangeEnd;
+    Pointer mStart;
+    Pointer mEnd;
+    Pointer mComma;
+  };
+
+  explicit StringListRange(const String& aList) : mList(aList) {}
+  Iterator begin()
+  {
+    return Iterator(mList.Data(), mList.Length());
+  }
+  Iterator end()
+  {
+    return Iterator(mList.Data() + mList.Length(), 0);
+  }
+private:
+  const String& mList;
+};
+
+template <typename String>
+StringListRange<String>
+MakeStringListRange(const String& aList)
+{
+  return StringListRange<String>(aList);
+}
+
+template <typename ListString, typename ItemString>
+static bool
+StringListContains(const ListString& aList, const ItemString& aItem)
+{
+  for (const auto& listItem : MakeStringListRange(aList)) {
+    if (listItem.Equals(aItem)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+};
+
+using namespace mozilla;
+
+TEST(StringListRange, MakeStringListRange)
+{
+  static const struct
+  {
+    const char* mList;
+    const char* mExpected;
+  } tests[] =
+  {
+    { "", "" },
+    { " ", "" },
+    { ",", "" },
+    { " , ", "" },
+    { "a", "a|" },
+    { "  a  ", "a|" },
+    { "aa,bb", "aa|bb|" },
+    { " a a ,  b b  ", "a a|b b|" },
+    { " , ,a 1,,  ,b  2,", "a 1|b  2|" }
+  };
+
+  for (const auto& test : tests) {
+    nsCString list(test.mList);
+    nsCString out;
+    for (const auto& item : MakeStringListRange(list)) {
+      out += item;
+      out += "|";
+    }
+    EXPECT_STREQ(test.mExpected, out.Data());
+  }
+}
+
+TEST(StringListRange, StringListContains)
+{
+  static const struct
+  {
+    const char* mList;
+    const char* mItemToSearch;
+    bool mExpected;
+  } tests[] =
+  {
+    { "", "", false },
+    { "", "a", false },
+    { " ", "a", false },
+    { ",", "a", false },
+    { " , ", "", false },
+    { " , ", "a", false },
+    { "a", "a", true },
+    { "a", "b", false },
+    { "  a  ", "a", true },
+    { "aa,bb", "aa", true },
+    { "aa,bb", "bb", true },
+    { "aa,bb", "cc", false },
+    { "aa,bb", " aa ", false },
+    { " a a ,  b b  ", "a a", true },
+    { " , ,a 1,,  ,b  2,", "a 1", true },
+    { " , ,a 1,,  ,b  2,", "b  2", true },
+    { " , ,a 1,,  ,b  2,", "", false },
+    { " , ,a 1,,  ,b  2,", " ", false },
+    { " , ,a 1,,  ,b  2,", "A 1", false },
+    { " , ,A 1,,  ,b  2,", "a 1", false }
+  };
+
+  for (const auto& test : tests) {
+    nsCString list(test.mList);
+    nsCString itemToSearch(test.mItemToSearch);
+    EXPECT_EQ(test.mExpected, StringListContains(list, itemToSearch))
+      << "trying to find \"" << itemToSearch.Data()
+      << "\" in \"" << list.Data() << "\"";
+  }
+}
--- a/dom/media/gtest/moz.build
+++ b/dom/media/gtest/moz.build
@@ -2,16 +2,17 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 UNIFIED_SOURCES += [
     'MockMediaResource.cpp',
     'TestAudioCompactor.cpp',
+    'TestDecoderDoctor.cpp',
     'TestGMPCrossOrigin.cpp',
     'TestGMPRemoveAndDelete.cpp',
     'TestGMPUtils.cpp',
     'TestIntervalSet.cpp',
     'TestMediaDataDecoder.cpp',
     'TestMediaEventSource.cpp',
     'TestMediaFormatReader.cpp',
     'TestMozPromise.cpp',