tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestDecodeToSurface.cpp (5772B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "gtest/gtest.h"
      6 
      7 #include "Common.h"
      8 #include "imgIContainer.h"
      9 #include "ImageOps.h"
     10 #include "mozilla/gfx/2D.h"
     11 #include "nsComponentManagerUtils.h"
     12 #include "nsCOMPtr.h"
     13 #include "nsIInputStream.h"
     14 #include "nsIRunnable.h"
     15 #include "nsIThread.h"
     16 #include "mozilla/RefPtr.h"
     17 #include "nsString.h"
     18 #include "nsThreadUtils.h"
     19 
     20 using namespace mozilla;
     21 using namespace mozilla::gfx;
     22 using namespace mozilla::image;
     23 
     24 class DecodeToSurfaceRunnable : public Runnable {
     25 public:
     26  DecodeToSurfaceRunnable(RefPtr<SourceSurface>& aSurface,
     27                          nsIInputStream* aInputStream,
     28                          ImageOps::ImageBuffer* aImageBuffer,
     29                          const ImageTestCase& aTestCase)
     30      : mozilla::Runnable("DecodeToSurfaceRunnable"),
     31        mSurface(aSurface),
     32        mInputStream(aInputStream),
     33        mImageBuffer(aImageBuffer),
     34        mTestCase(aTestCase) {}
     35 
     36  NS_IMETHOD Run() override {
     37    Go();
     38    return NS_OK;
     39  }
     40 
     41  void Go() {
     42    Maybe<IntSize> outputSize;
     43    if (mTestCase.mOutputSize != mTestCase.mSize) {
     44      outputSize.emplace(mTestCase.mOutputSize);
     45    }
     46 
     47    uint32_t flags = FromSurfaceFlags(mTestCase.mSurfaceFlags);
     48 
     49    if (mImageBuffer) {
     50      mSurface = ImageOps::DecodeToSurface(
     51          mImageBuffer, nsDependentCString(mTestCase.mMimeType), flags,
     52          outputSize);
     53    } else {
     54      mSurface = ImageOps::DecodeToSurface(
     55          mInputStream.forget(), nsDependentCString(mTestCase.mMimeType), flags,
     56          outputSize);
     57    }
     58    ASSERT_TRUE(mSurface != nullptr);
     59 
     60    EXPECT_TRUE(mSurface->IsDataSourceSurface());
     61    EXPECT_TRUE(mSurface->GetFormat() == SurfaceFormat::OS_RGBX ||
     62                mSurface->GetFormat() == SurfaceFormat::OS_RGBA);
     63 
     64    if (outputSize) {
     65      EXPECT_EQ(*outputSize, mSurface->GetSize());
     66    } else {
     67      EXPECT_EQ(mTestCase.mSize, mSurface->GetSize());
     68    }
     69 
     70    EXPECT_TRUE(IsSolidColor(mSurface, mTestCase.Color(), mTestCase.Fuzz()));
     71  }
     72 
     73 private:
     74  RefPtr<SourceSurface>& mSurface;
     75  nsCOMPtr<nsIInputStream> mInputStream;
     76  RefPtr<ImageOps::ImageBuffer> mImageBuffer;
     77  ImageTestCase mTestCase;
     78 };
     79 
     80 static void RunDecodeToSurface(const ImageTestCase& aTestCase,
     81                               ImageOps::ImageBuffer* aImageBuffer = nullptr) {
     82  nsCOMPtr<nsIInputStream> inputStream;
     83  if (!aImageBuffer) {
     84    inputStream = LoadFile(aTestCase.mPath);
     85    ASSERT_TRUE(inputStream != nullptr);
     86  }
     87 
     88  nsCOMPtr<nsIThread> thread;
     89  nsresult rv =
     90      NS_NewNamedThread("DecodeToSurface", getter_AddRefs(thread), nullptr);
     91  ASSERT_NS_SUCCEEDED(rv);
     92 
     93  // We run the DecodeToSurface tests off-main-thread to ensure that
     94  // DecodeToSurface doesn't require any main-thread-only code.
     95  RefPtr<SourceSurface> surface;
     96  nsCOMPtr<nsIRunnable> runnable = new DecodeToSurfaceRunnable(
     97      surface, inputStream, aImageBuffer, aTestCase);
     98  NS_DispatchAndSpinEventLoopUntilComplete("RunDecodeToSurface"_ns, thread,
     99                                           do_AddRef(runnable));
    100 
    101  thread->Shutdown();
    102 
    103  // Explicitly release the SourceSurface on the main thread.
    104  surface = nullptr;
    105 }
    106 
    107 class ImageDecodeToSurface : public ::testing::Test {
    108 protected:
    109  AutoInitializeImageLib mInit;
    110 };
    111 
    112 TEST_F(ImageDecodeToSurface, PNG) { RunDecodeToSurface(GreenPNGTestCase()); }
    113 TEST_F(ImageDecodeToSurface, GIF) { RunDecodeToSurface(GreenGIFTestCase()); }
    114 TEST_F(ImageDecodeToSurface, JPG) { RunDecodeToSurface(GreenJPGTestCase()); }
    115 TEST_F(ImageDecodeToSurface, BMP) { RunDecodeToSurface(GreenBMPTestCase()); }
    116 TEST_F(ImageDecodeToSurface, ICO) { RunDecodeToSurface(GreenICOTestCase()); }
    117 TEST_F(ImageDecodeToSurface, Icon) { RunDecodeToSurface(GreenIconTestCase()); }
    118 TEST_F(ImageDecodeToSurface, WebP) { RunDecodeToSurface(GreenWebPTestCase()); }
    119 
    120 TEST_F(ImageDecodeToSurface, AnimatedGIF) {
    121  RunDecodeToSurface(GreenFirstFrameAnimatedGIFTestCase());
    122 }
    123 
    124 TEST_F(ImageDecodeToSurface, AnimatedPNG) {
    125  RunDecodeToSurface(GreenFirstFrameAnimatedPNGTestCase());
    126 }
    127 
    128 TEST_F(ImageDecodeToSurface, Corrupt) {
    129  ImageTestCase testCase = CorruptTestCase();
    130 
    131  nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
    132  ASSERT_TRUE(inputStream != nullptr);
    133 
    134  RefPtr<SourceSurface> surface = ImageOps::DecodeToSurface(
    135      inputStream.forget(), nsDependentCString(testCase.mMimeType),
    136      imgIContainer::DECODE_FLAGS_DEFAULT);
    137  EXPECT_TRUE(surface == nullptr);
    138 }
    139 
    140 TEST_F(ImageDecodeToSurface, ICOMultipleSizes) {
    141  ImageTestCase testCase = GreenMultipleSizesICOTestCase();
    142 
    143  nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
    144  ASSERT_TRUE(inputStream != nullptr);
    145 
    146  RefPtr<ImageOps::ImageBuffer> buffer =
    147      ImageOps::CreateImageBuffer(inputStream.forget());
    148  ASSERT_TRUE(buffer != nullptr);
    149 
    150  ImageMetadata metadata;
    151  nsresult rv = ImageOps::DecodeMetadata(
    152      buffer, nsDependentCString(testCase.mMimeType), metadata);
    153  EXPECT_NS_SUCCEEDED(rv);
    154  ASSERT_TRUE(metadata.HasSize());
    155  EXPECT_EQ(testCase.mSize, metadata.GetSize().ToUnknownSize());
    156 
    157  const nsTArray<OrientedIntSize>& nativeSizes = metadata.GetNativeSizes();
    158  ASSERT_EQ(6u, nativeSizes.Length());
    159 
    160  OrientedIntSize expectedSizes[] = {
    161      OrientedIntSize(16, 16),   OrientedIntSize(32, 32),
    162      OrientedIntSize(64, 64),   OrientedIntSize(128, 128),
    163      OrientedIntSize(256, 256), OrientedIntSize(256, 128),
    164  };
    165 
    166  for (int i = 0; i < 6; ++i) {
    167    EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
    168 
    169    // Request decoding at native size
    170    testCase.mOutputSize = nativeSizes[i].ToUnknownSize();
    171    RunDecodeToSurface(testCase, buffer);
    172  }
    173 }