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 380489 a292b14b9e9664b64e1becd3f1ddc47e70bfd0cb
parent 380488 80f0b3cbff9e595922116fa384133c5d2c697860
child 523736 6820c9bbf27b14d1cb7dc373cec6e0762ecb089c
push id21230
push usergsquelart@mozilla.com
push dateWed, 22 Jun 2016 01:46:41 +0000
reviewerscpearce
bugs1271483
milestone50.0a1
Bug 1271483 - p16. gtest for list-string functions - r=cpearce Moved templated code to VideoUtils.h, so it can more easily be reused, and tested. MozReview-Commit-ID: 3vOvaj5VVhm
dom/media/DecoderDoctorDiagnostics.cpp
dom/media/VideoUtils.h
dom/media/gtest/TestVideoUtils.cpp
dom/media/gtest/moz.build
--- a/dom/media/DecoderDoctorDiagnostics.cpp
+++ b/dom/media/DecoderDoctorDiagnostics.cpp
@@ -12,16 +12,17 @@
 #include "nsContentUtils.h"
 #include "nsGkAtoms.h"
 #include "nsIDocument.h"
 #include "nsIObserverService.h"
 #include "nsIScriptError.h"
 #include "nsITimer.h"
 #include "nsIWeakReference.h"
 #include "nsPluginHost.h"
+#include "VideoUtils.h"
 
 static mozilla::LazyLogModule sDecoderDoctorLog("DecoderDoctor");
 #define DD_LOG(level, arg, ...) MOZ_LOG(sDecoderDoctorLog, level, (arg, ##__VA_ARGS__))
 #define DD_DEBUG(arg, ...) DD_LOG(mozilla::LogLevel::Debug, arg, ##__VA_ARGS__)
 #define DD_INFO(arg, ...) DD_LOG(mozilla::LogLevel::Info, arg, ##__VA_ARGS__)
 #define DD_WARN(arg, ...) DD_LOG(mozilla::LogLevel::Warning, arg, ##__VA_ARGS__)
 
 namespace mozilla {
@@ -237,129 +238,16 @@ DecoderDoctorDocumentWatcher::EnsureTime
     if (NS_WARN_IF(NS_FAILED(
           mTimer->InitWithCallback(
             this, sAnalysisPeriod_ms, nsITimer::TYPE_ONE_SHOT)))) {
       mTimer = nullptr;
     }
   }
 }
 
-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;
-}
-
 static const NotificationAndReportStringId sMediaWidevineNoWMFNoSilverlight =
   { dom::DecoderDoctorNotificationType::Platform_decoder_not_found,
     "MediaWidevineNoWMFNoSilverlight" };
 static const NotificationAndReportStringId sMediaWMFNeeded =
   { dom::DecoderDoctorNotificationType::Platform_decoder_not_found,
     "MediaWMFNeeded" };
 static const NotificationAndReportStringId sMediaPlatformDecoderNotFound =
   { dom::DecoderDoctorNotificationType::Platform_decoder_not_found,
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -329,11 +329,124 @@ bool
 IsH264ContentType(const nsAString& aContentType);
 
 bool
 IsAACContentType(const nsAString& aContentType);
 
 bool
 IsAACCodecString(const nsAString& aCodec);
 
+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;
+}
+
 } // end namespace mozilla
 
 #endif
new file mode 100644
--- /dev/null
+++ b/dom/media/gtest/TestVideoUtils.cpp
@@ -0,0 +1,80 @@
+/* -*- 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"
+#include "VideoUtils.h"
+
+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
@@ -15,16 +15,17 @@ UNIFIED_SOURCES += [
     'TestMediaEventSource.cpp',
     'TestMediaFormatReader.cpp',
     'TestMozPromise.cpp',
     'TestMP3Demuxer.cpp',
     'TestMP4Demuxer.cpp',
     # 'TestMP4Reader.cpp', disabled so we can turn check tests back on (bug 1175752)
     'TestTrackEncoder.cpp',
     'TestVideoSegment.cpp',
+    'TestVideoUtils.cpp',
     'TestVPXDecoding.cpp',
     'TestWebMBuffered.cpp',
 ]
 
 if CONFIG['MOZ_EME']:
     UNIFIED_SOURCES += [
         'TestEME.cpp',
     ]