Bug 1181863 (Part 3) - Add tests for DecodeToSurface(). r=tn
authorSeth Fowler <mark.seth.fowler@gmail.com>
Fri, 31 Jul 2015 18:10:34 -0700
changeset 282419 4d7cd400d799e73e54c7d81d8379df7c097fb3c4
parent 282418 44dc3228c00b1f809629d7d88c9df7749186d734
child 282420 20d502d64ba5878eee66688076928e0f57c54bd7
push id4000
push usercykesiopka.bmo@gmail.com
push dateMon, 03 Aug 2015 10:16:16 +0000
reviewerstn
bugs1181863
milestone42.0a1
Bug 1181863 (Part 3) - Add tests for DecodeToSurface(). r=tn
image/ImageOps.cpp
image/ImageOps.h
image/moz.build
image/test/gtest/Common.cpp
image/test/gtest/Common.h
image/test/gtest/TestDecodeToSurface.cpp
image/test/gtest/corrupt.jpg
image/test/gtest/first-frame-green.gif
image/test/gtest/first-frame-green.png
image/test/gtest/green.bmp
image/test/gtest/green.gif
image/test/gtest/green.ico
image/test/gtest/green.jpg
image/test/gtest/green.png
image/test/gtest/moz.build
--- a/image/ImageOps.cpp
+++ b/image/ImageOps.cpp
@@ -1,26 +1,25 @@
 /* -*- 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 "ImageOps.h"
 
-#include "mozilla/gfx/2D.h"
-
 #include "ClippedImage.h"
 #include "DecodePool.h"
 #include "Decoder.h"
 #include "DecoderFactory.h"
 #include "DynamicImage.h"
 #include "FrozenImage.h"
 #include "Image.h"
 #include "imgIContainer.h"
+#include "mozilla/gfx/2D.h"
 #include "nsStreamUtils.h"
 #include "OrientedImage.h"
 #include "SourceBuffer.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace image {
--- a/image/ImageOps.h
+++ b/image/ImageOps.h
@@ -74,17 +74,17 @@ public:
    * off-main-thread.
    *
    * @param aInputStream An input stream containing an encoded image.
    * @param aMimeType The MIME type of the image.
    * @param aFlags Flags of the imgIContainer::FLAG_DECODE_* variety.
    * @return A SourceSurface containing the first frame of the image at its
    *         intrinsic size, or nullptr if the image cannot be decoded.
    */
-  already_AddRefed<gfx::SourceSurface>
+  static already_AddRefed<gfx::SourceSurface>
   DecodeToSurface(nsIInputStream* aInputStream,
                   const nsACString& aMimeType,
                   uint32_t aFlags);
 
 private:
   // This is a static utility class, so disallow instantiation.
   virtual ~ImageOps() = 0;
 };
--- a/image/moz.build
+++ b/image/moz.build
@@ -1,15 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # 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/.
 
 DIRS += ['build', 'decoders', 'encoders']
+if CONFIG['ENABLE_TESTS']:
+    DIRS += ['test/gtest']
 
 with Files('**'):
     BUG_COMPONENT = ('Core', 'ImageLib')
 
 BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
 
 MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
 
new file mode 100644
--- /dev/null
+++ b/image/test/gtest/Common.cpp
@@ -0,0 +1,157 @@
+/* -*- 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 "Common.h"
+
+#include <cstdlib>
+#include "gtest/gtest.h"
+
+#include "nsDirectoryServiceDefs.h"
+#include "nsIDirectoryService.h"
+#include "nsIFile.h"
+#include "nsIInputStream.h"
+#include "nsIProperties.h"
+#include "nsNetUtil.h"
+#include "nsRefPtr.h"
+#include "nsString.h"
+
+namespace mozilla {
+
+using namespace gfx;
+
+using std::abs;
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+///////////////////////////////////////////////////////////////////////////////
+
+// These macros work like gtest's ASSERT_* macros, except that they can be used
+// in functions that return values.
+#define ASSERT_TRUE_OR_RETURN(e, rv) \
+  EXPECT_TRUE(e);                    \
+  if (!(e)) {                        \
+    return rv;                       \
+  }
+
+#define ASSERT_EQ_OR_RETURN(a, b, rv) \
+  EXPECT_EQ(a, b);                    \
+  if ((a) != (b)) {                   \
+    return rv;                        \
+  }
+
+#define ASSERT_LE_OR_RETURN(a, b, rv) \
+  EXPECT_LE(a, b);                    \
+  if (!((a) <= (b))) {                 \
+    return rv;                        \
+  }
+
+already_AddRefed<nsIInputStream>
+LoadFile(const char* aRelativePath)
+{
+  nsresult rv;
+
+  nsCOMPtr<nsIProperties> dirService =
+    do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
+  ASSERT_TRUE_OR_RETURN(dirService != nullptr, nullptr);
+
+  // Retrieve the current working directory.
+  nsCOMPtr<nsIFile> file;
+  rv = dirService->Get(NS_OS_CURRENT_WORKING_DIR,
+                       NS_GET_IID(nsIFile), getter_AddRefs(file));
+  ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
+
+  // Construct the final path by appending the working path to the current
+  // working directory.
+  file->AppendNative(nsAutoCString(aRelativePath));
+
+  // Construct an input stream for the requested file.
+  nsCOMPtr<nsIInputStream> inputStream;
+  rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), file);
+  ASSERT_TRUE_OR_RETURN(NS_SUCCEEDED(rv), nullptr);
+
+  return inputStream.forget();
+}
+
+bool
+IsSolidColor(SourceSurface* aSurface, BGRAColor aColor, bool aFuzzy)
+{
+  nsRefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
+  ASSERT_TRUE_OR_RETURN(dataSurface != nullptr, false);
+
+  ASSERT_EQ_OR_RETURN(dataSurface->Stride(), aSurface->GetSize().width * 4,
+                      false);
+
+  DataSourceSurface::ScopedMap mapping(dataSurface,
+                                       DataSourceSurface::MapType::READ);
+  ASSERT_TRUE_OR_RETURN(mapping.IsMapped(), false);
+
+  uint8_t* data = dataSurface->GetData();
+  ASSERT_TRUE_OR_RETURN(data != nullptr, false);
+
+  int32_t length = dataSurface->Stride() * aSurface->GetSize().height;
+  for (int32_t i = 0 ; i < length ; i += 4) {
+    if (aFuzzy) {
+      ASSERT_LE_OR_RETURN(abs(aColor.mBlue - data[i + 0]), 1, false);
+      ASSERT_LE_OR_RETURN(abs(aColor.mGreen - data[i + 1]), 1, false);
+      ASSERT_LE_OR_RETURN(abs(aColor.mRed - data[i + 2]), 1, false);
+      ASSERT_LE_OR_RETURN(abs(aColor.mAlpha - data[i + 3]), 1, false);
+    } else {
+      ASSERT_EQ_OR_RETURN(aColor.mBlue,  data[i + 0], false);
+      ASSERT_EQ_OR_RETURN(aColor.mGreen, data[i + 1], false);
+      ASSERT_EQ_OR_RETURN(aColor.mRed,   data[i + 2], false);
+      ASSERT_EQ_OR_RETURN(aColor.mAlpha, data[i + 3], false);
+    }
+  }
+
+  return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Test Data
+///////////////////////////////////////////////////////////////////////////////
+
+ImageTestCase GreenPNGTestCase()
+{
+  return ImageTestCase("green.png", "image/png", IntSize(100, 100));
+}
+
+ImageTestCase GreenGIFTestCase()
+{
+  return ImageTestCase("green.gif", "image/gif", IntSize(100, 100));
+}
+
+ImageTestCase GreenJPGTestCase()
+{
+  return ImageTestCase("green.jpg", "image/jpeg", IntSize(100, 100),
+                       /* aFuzzy = */ true);
+}
+
+ImageTestCase GreenBMPTestCase()
+{
+  return ImageTestCase("green.bmp", "image/bmp", IntSize(100, 100));
+}
+
+ImageTestCase GreenICOTestCase()
+{
+  return ImageTestCase("green.ico", "image/x-icon", IntSize(100, 100));
+}
+
+ImageTestCase GreenFirstFrameAnimatedGIFTestCase()
+{
+  return ImageTestCase("first-frame-green.gif", "image/gif", IntSize(100, 100));
+}
+
+ImageTestCase GreenFirstFrameAnimatedPNGTestCase()
+{
+  return ImageTestCase("first-frame-green.png", "image/png", IntSize(100, 100));
+}
+
+ImageTestCase CorruptTestCase()
+{
+  return ImageTestCase("corrupt.jpg", "image/jpeg", IntSize(100, 100));
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/image/test/gtest/Common.h
@@ -0,0 +1,91 @@
+/* -*- 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/. */
+
+#ifndef mozilla_image_test_gtest_Common_h
+#define mozilla_image_test_gtest_Common_h
+
+#include "mozilla/gfx/2D.h"
+#include "nsCOMPtr.h"
+
+class nsIInputStream;
+
+namespace mozilla {
+
+///////////////////////////////////////////////////////////////////////////////
+// Types
+///////////////////////////////////////////////////////////////////////////////
+
+struct ImageTestCase
+{
+  ImageTestCase(const char* aPath,
+                const char* aMimeType,
+                gfx::IntSize aSize,
+                bool aFuzzy = false)
+    : mPath(aPath)
+    , mMimeType(aMimeType)
+    , mSize(aSize)
+    , mFuzzy(aFuzzy)
+  { }
+
+  const char* mPath;
+  const char* mMimeType;
+  gfx::IntSize mSize;
+  bool mFuzzy;
+};
+
+struct BGRAColor
+{
+  BGRAColor(uint8_t aBlue, uint8_t aGreen, uint8_t aRed, uint8_t aAlpha)
+    : mBlue(aBlue)
+    , mGreen(aGreen)
+    , mRed(aRed)
+    , mAlpha(aAlpha)
+  { }
+
+  static BGRAColor Green() { return BGRAColor(0x00, 0xFF, 0x00, 0xFF); }
+
+  uint8_t mBlue;
+  uint8_t mGreen;
+  uint8_t mRed;
+  uint8_t mAlpha;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+///////////////////////////////////////////////////////////////////////////////
+
+/// Loads a file from the current directory. @return an nsIInputStream for it.
+already_AddRefed<nsIInputStream> LoadFile(const char* aRelativePath);
+
+/**
+ * @returns true if every pixel of @aSurface is @aColor.
+ * 
+ * If @aFuzzy is true, a tolerance of 1 is allowed in each color component. This
+ * may be necessary for tests that involve JPEG images.
+ */
+bool IsSolidColor(gfx::SourceSurface* aSurface,
+                  BGRAColor aColor,
+                  bool aFuzzy = false);
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Test Data
+///////////////////////////////////////////////////////////////////////////////
+
+ImageTestCase GreenPNGTestCase();
+ImageTestCase GreenGIFTestCase();
+ImageTestCase GreenJPGTestCase();
+ImageTestCase GreenBMPTestCase();
+ImageTestCase GreenICOTestCase();
+
+ImageTestCase GreenFirstFrameAnimatedGIFTestCase();
+ImageTestCase GreenFirstFrameAnimatedPNGTestCase();
+
+ImageTestCase CorruptTestCase();
+
+} // namespace mozilla
+
+#endif // mozilla_image_test_gtest_Common_h
new file mode 100644
--- /dev/null
+++ b/image/test/gtest/TestDecodeToSurface.cpp
@@ -0,0 +1,119 @@
+/* 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 "Common.h"
+#include "imgIContainer.h"
+#include "imgITools.h"
+#include "ImageOps.h"
+#include "mozilla/gfx/2D.h"
+#include "nsComponentManagerUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIInputStream.h"
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+#include "nsRefPtr.h"
+#include "nsString.h"
+#include "nsThreadUtils.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+using namespace mozilla::image;
+
+
+TEST(ImageDecodeToSurface, ImageModuleAvailable)
+{
+  // We can run into problems if XPCOM modules get initialized in the wrong
+  // order. It's important that this test run first, both as a sanity check and
+  // to ensure we get the module initialization order we want.
+  nsCOMPtr<imgITools> imgTools =
+    do_CreateInstance("@mozilla.org/image/tools;1");
+  EXPECT_TRUE(imgTools != nullptr);
+}
+
+class DecodeToSurfaceRunnable : public nsRunnable
+{
+public:
+  DecodeToSurfaceRunnable(nsIInputStream* aInputStream,
+                          const ImageTestCase& aTestCase)
+    : mInputStream(aInputStream)
+    , mTestCase(aTestCase)
+  { }
+
+  NS_IMETHOD Run()
+  {
+    Go();
+    return NS_OK;
+  }
+
+  void Go()
+  {
+    nsRefPtr<SourceSurface> surface =
+      ImageOps::DecodeToSurface(mInputStream,
+                                nsAutoCString(mTestCase.mMimeType),
+                                imgIContainer::DECODE_FLAGS_DEFAULT);
+    ASSERT_TRUE(surface != nullptr);
+
+    EXPECT_EQ(SurfaceType::DATA, surface->GetType());
+    EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::B8G8R8X8 ||
+                surface->GetFormat() == SurfaceFormat::B8G8R8A8);
+    EXPECT_EQ(mTestCase.mSize, surface->GetSize());
+
+    EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(), mTestCase.mFuzzy));
+  }
+
+private:
+  nsCOMPtr<nsIInputStream> mInputStream;
+  ImageTestCase mTestCase;
+};
+
+static void
+RunDecodeToSurface(const ImageTestCase& aTestCase)
+{
+  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
+  ASSERT_TRUE(inputStream != nullptr);
+
+  nsCOMPtr<nsIThread> thread;
+  nsresult rv = NS_NewThread(getter_AddRefs(thread), nullptr);
+  ASSERT_TRUE(NS_SUCCEEDED(rv));
+
+  // We run the DecodeToSurface tests off-main-thread to ensure that
+  // DecodeToSurface doesn't require any main-thread-only code.
+  nsCOMPtr<nsIRunnable> runnable =
+    new DecodeToSurfaceRunnable(inputStream, aTestCase);
+  thread->Dispatch(runnable, nsIThread::DISPATCH_SYNC);
+
+  thread->Shutdown();
+}
+
+TEST(ImageDecodeToSurface, PNG) { RunDecodeToSurface(GreenPNGTestCase()); }
+TEST(ImageDecodeToSurface, GIF) { RunDecodeToSurface(GreenGIFTestCase()); }
+TEST(ImageDecodeToSurface, JPG) { RunDecodeToSurface(GreenJPGTestCase()); }
+TEST(ImageDecodeToSurface, BMP) { RunDecodeToSurface(GreenBMPTestCase()); }
+TEST(ImageDecodeToSurface, ICO) { RunDecodeToSurface(GreenICOTestCase()); }
+
+TEST(ImageDecodeToSurface, AnimatedGIF)
+{
+  RunDecodeToSurface(GreenFirstFrameAnimatedGIFTestCase());
+}
+
+TEST(ImageDecodeToSurface, AnimatedPNG)
+{
+  RunDecodeToSurface(GreenFirstFrameAnimatedPNGTestCase());
+}
+
+TEST(ImageDecodeToSurface, Corrupt)
+{
+  ImageTestCase testCase = CorruptTestCase();
+
+  nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
+  ASSERT_TRUE(inputStream != nullptr);
+
+  nsRefPtr<SourceSurface> surface =
+    ImageOps::DecodeToSurface(inputStream,
+                              nsAutoCString(testCase.mMimeType),
+                              imgIContainer::DECODE_FLAGS_DEFAULT);
+  EXPECT_TRUE(surface == nullptr);
+}
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..555a416d7d8e6c0f835a756994a8efca17c55cd8
GIT binary patch
literal 2477
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
G1pWd#D4b{j
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cd3c7d3db89085bbdbcb41247792bfc5fde9c492
GIT binary patch
literal 317
zc${<hbhEHbOkqf2_`txx@E?d76o0ZXaDnLm+<vYh!Oo5Wu10zW%#1)G9gsXoF#}U^
zOaIE#Z}}I`*>bCU^SwR4`P&|OOncV3?A57l@3@bD^11%4_xZ1L-~aLRaJ3&<^s&Q7
zYx<dGpE-NImS0)*wd-uw_B-pobMti{f3oRkkKgL+Z?^sB?LYne%dWqD=U;#Sv+qB@
kgocGjL`Fr&j1@ah+<5VWBQpZwG`Kq&>g($n2Ff+o0RC>C`Tzg`
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..115f035d897859b9ad8e47cb158d252e621096c2
GIT binary patch
literal 364
zc%17D@N?(olHy`uVBq!ia0vp^DIm<j3?$ucQqzDGM`Ch_50GX8VusJXlM8?pXMj(L
zD-#nF!+(bQ`uf)2X6Zmd#*!evU<QY0H$b|i(jdARU`8^)Knn8<28QVe`;~!gTTd6q
zkc@k8&oXi{Fz_%hSX=*ctA)&#hL?>VDngwuN)vHYpX?={8L10C=x=?9WE~@R>v%S$
zeh0E0(^4EmKwd$za^t^+*B=#JU|PnG&o(f1@_)*b|9*-Re#S9CL!?VwBT9nv(@M${
ni&7aJfg!2jSX`W%o0OAUq+qOP5a+5R19E_;tDnm{r-UW|#oJ$m
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f79dd672adfd43be0906e2ce5bb600b215517d27
GIT binary patch
literal 30138
zc%1Fbp$<WD6bImI%!YVplT0uZjVhQTDY78g{{>7FZc!BZHjiPVm+%m>%-zM9EPlUz
zzi`gk&UkuSM|pNxH(8gj7NSPJ?`8M6_UtG3w|p2+W~=0U>n@JXdTV<vj0S@^386Cz
zp?pZw%CLGVw&(l)_lHvSlRE$a000000000000000000000000000000006*$JOE67
B0m1+P
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ef215dfc94751a15cca5909a443632f5468041b1
GIT binary patch
literal 156
zc${<hbhEHbOkqf2_`txx@E?d76o0aSC<Yx60g_>0DsJgtdHOB?;yGJxb#K16=Qn@b
zBadm%I+wjVwe21E@lQV2zx6)<b?*B=ejcv&Ba1$E_-IW(v+Ofxuh;S`tG;%f&Dwrv
z-FI%j?&D83{p|5uef`b0-@N^&pMTl)x9|Mx?|=6F=a<m1@QBE$=$Nr$$B7#+esE+)
IFfdpH0Q_Q3xc~qF
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c5dfa8b5383c534df2f5e633e7d94d32cfd3b76a
GIT binary patch
literal 41662
zc%1FXp$&jg5JbU6BT3Lm%AlBE779fvbOlF9egWutlRL4=P+Cj<CFhaMN!GfWa^>6K
zwmq4~?|L@?0000000000000000000000000000000000000000000000MJR2^rHu<
C>)Sj4
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..48c454d27c9c46574597f80fdd64ecd4d254577d
GIT binary patch
literal 361
zc$}S%Jr2S!427SY62(c{IxR3UaS;ZjN^lMi!+jW87&rt!3pWYQNSWZXWLZz|+0M88
zg6zlL2%-urE#xP*Fjb*+qtv!8IBRE?o%igRee9wSZD4Lv({>_BeC&r_2A!oWp^`MU
z)1U+n@-z8@<Z!^j&>B@DlPF)Y&{y$^Re3H`6{;?Yrf$c@oxa@<L_>PVBy4b|?sS}5
I{)F=V4K5EK<NyEw
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7df25f33bdb26cc7f41138501ab399059839137d
GIT binary patch
literal 255
zc%17D@N?(olHy`uVBq!ia0vp^DIm<j1SJ1AFfjuu&H|6fVg?3oVGw3ym^DWND9B#o
z>FdgVmrY2>Os;yW$XlS$JWm(LkcwMxFBmd1FmNz0$ozjU>fm{HrGS|QSGZD6PEz%r
zro*}k!eEMoFdB8hjHM3Kz>FXTZ!kl1f-0CHassR?l5*|8wspoc9#?7J!~=9GgQu&X
J%Q~loCICH_Rq+4-
new file mode 100644
--- /dev/null
+++ b/image/test/gtest/moz.build
@@ -0,0 +1,31 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# 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/.
+
+Library('imagetest')
+
+FAIL_ON_WARNINGS = True
+
+UNIFIED_SOURCES = [
+    'Common.cpp',
+    'TestDecodeToSurface.cpp',
+]
+
+TEST_HARNESS_FILES.gtest += [
+    'corrupt.jpg',
+    'first-frame-green.gif',
+    'first-frame-green.png',
+    'green.bmp',
+    'green.gif',
+    'green.ico',
+    'green.jpg',
+    'green.png',
+]
+
+LOCAL_INCLUDES += [
+    '/image',
+]
+
+FINAL_LIBRARY = 'xul-gtest'