1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h"
6 
7 #include <memory>
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/blink/renderer/platform/image-decoders/image_decoder_base_test.h"
10 #include "third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.h"
11 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
12 
13 namespace blink {
14 
15 namespace {
16 
CreateBMPDecoder()17 std::unique_ptr<ImageDecoder> CreateBMPDecoder() {
18   return std::make_unique<BMPImageDecoder>(
19       ImageDecoder::kAlphaNotPremultiplied, ColorBehavior::TransformToSRGB(),
20       ImageDecoder::kNoDecodedImageByteLimit);
21 }
22 
23 }  // anonymous namespace
24 
TEST(BMPImageDecoderTest,isSizeAvailable)25 TEST(BMPImageDecoderTest, isSizeAvailable) {
26   static constexpr char kBmpFile[] = "/images/resources/lenna.bmp";  // 256x256
27   scoped_refptr<SharedBuffer> data = ReadFile(kBmpFile);
28   ASSERT_TRUE(data.get());
29 
30   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
31   decoder->SetData(data.get(), true);
32   EXPECT_TRUE(decoder->IsSizeAvailable());
33   EXPECT_EQ(256, decoder->Size().Width());
34   EXPECT_EQ(256, decoder->Size().Height());
35 }
36 
TEST(BMPImageDecoderTest,parseAndDecode)37 TEST(BMPImageDecoderTest, parseAndDecode) {
38   static constexpr char kBmpFile[] = "/images/resources/lenna.bmp";  // 256x256
39   scoped_refptr<SharedBuffer> data = ReadFile(kBmpFile);
40   ASSERT_TRUE(data.get());
41 
42   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
43   decoder->SetData(data.get(), true);
44 
45   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
46   ASSERT_TRUE(frame);
47   EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
48   EXPECT_EQ(256, frame->Bitmap().width());
49   EXPECT_EQ(256, frame->Bitmap().height());
50   EXPECT_FALSE(decoder->Failed());
51 }
52 
53 // Test if a BMP decoder returns a proper error while decoding an empty image.
TEST(BMPImageDecoderTest,emptyImage)54 TEST(BMPImageDecoderTest, emptyImage) {
55   static constexpr char kBmpFile[] = "/images/resources/0x0.bmp";  // 0x0
56   scoped_refptr<SharedBuffer> data = ReadFile(kBmpFile);
57   ASSERT_TRUE(data.get());
58 
59   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
60   decoder->SetData(data.get(), true);
61 
62   ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(0);
63   ASSERT_TRUE(frame);
64   EXPECT_EQ(ImageFrame::kFrameEmpty, frame->GetStatus());
65   EXPECT_TRUE(decoder->Failed());
66 }
67 
TEST(BMPImageDecoderTest,int32MinHeight)68 TEST(BMPImageDecoderTest, int32MinHeight) {
69   static constexpr char kBmpFile[] =
70       "/images/resources/1xint32_min.bmp";  // 0xINT32_MIN
71   scoped_refptr<SharedBuffer> data = ReadFile(kBmpFile);
72   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
73   // Test when not all data is received.
74   decoder->SetData(data.get(), false);
75   EXPECT_FALSE(decoder->IsSizeAvailable());
76   EXPECT_TRUE(decoder->Failed());
77 }
78 
79 // This test verifies that calling SharedBuffer::MergeSegmentsIntoBuffer() does
80 // not break BMP decoding at a critical point: in between a call to decode the
81 // size (when BMPImageDecoder stops while it may still have input data to
82 // read) and a call to do a full decode.
TEST(BMPImageDecoderTest,mergeBuffer)83 TEST(BMPImageDecoderTest, mergeBuffer) {
84   static constexpr char kBmpFile[] = "/images/resources/lenna.bmp";
85   TestMergeBuffer(&CreateBMPDecoder, kBmpFile);
86 }
87 
88 // Verify that decoding this image does not crash.
TEST(BMPImageDecoderTest,crbug752898)89 TEST(BMPImageDecoderTest, crbug752898) {
90   static constexpr char kBmpFile[] = "/images/resources/crbug752898.bmp";
91   scoped_refptr<SharedBuffer> data = ReadFile(kBmpFile);
92   ASSERT_TRUE(data.get());
93 
94   std::unique_ptr<ImageDecoder> decoder = CreateBMPDecoder();
95   decoder->SetData(data.get(), true);
96   decoder->DecodeFrameBufferAtIndex(0);
97 }
98 
99 class BMPImageDecoderCorpusTest : public ImageDecoderBaseTest {
100  public:
BMPImageDecoderCorpusTest()101   BMPImageDecoderCorpusTest() : ImageDecoderBaseTest("bmp") {}
102 
103  protected:
CreateImageDecoder() const104   std::unique_ptr<ImageDecoder> CreateImageDecoder() const override {
105     return std::make_unique<BMPImageDecoder>(
106         ImageDecoder::kAlphaPremultiplied, ColorBehavior::TransformToSRGB(),
107         ImageDecoder::kNoDecodedImageByteLimit);
108   }
109 
110   // The BMPImageDecoderCorpusTest tests are really slow under Valgrind.
111   // Thus it is split into fast and slow versions. The threshold is
112   // set to 10KB because the fast test can finish under Valgrind in
113   // less than 30 seconds.
114   static const int64_t kThresholdSize = 10240;
115 };
116 
TEST_F(BMPImageDecoderCorpusTest,DecodingFast)117 TEST_F(BMPImageDecoderCorpusTest, DecodingFast) {
118   TestDecoding(FileSelection::kSmaller, kThresholdSize);
119 }
120 
121 #if defined(THREAD_SANITIZER)
122 // BMPImageDecoderCorpusTest.DecodingSlow always times out under ThreadSanitizer
123 // v2.
124 #define MAYBE_DecodingSlow DISABLED_DecodingSlow
125 #else
126 #define MAYBE_DecodingSlow DecodingSlow
127 #endif
TEST_F(BMPImageDecoderCorpusTest,MAYBE_DecodingSlow)128 TEST_F(BMPImageDecoderCorpusTest, MAYBE_DecodingSlow) {
129   TestDecoding(FileSelection::kBigger, kThresholdSize);
130 }
131 
132 }  // namespace blink
133