Home | History | Annotate | Download | only in gif
      1 // Copyright 2017 PDFium 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 "core/fxcodec/gif/cfx_gifcontext.h"
      6 
      7 #include "core/fxcrt/unowned_ptr.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 class CFX_GifContextForTest : public CFX_GifContext {
     11  public:
     12   CFX_GifContextForTest(CCodec_GifModule* gif_module,
     13                         CCodec_GifModule::Delegate* delegate)
     14       : CFX_GifContext(gif_module, delegate) {}
     15   ~CFX_GifContextForTest() override {}
     16 
     17   using CFX_GifContext::ReadData;
     18   using CFX_GifContext::ReadGifSignature;
     19   using CFX_GifContext::ReadLogicalScreenDescriptor;
     20 };
     21 
     22 TEST(CFX_GifContext, SetInputBuffer) {
     23   CFX_GifContextForTest context(nullptr, nullptr);
     24 
     25   context.SetInputBuffer(nullptr, 0);
     26   EXPECT_EQ(nullptr, context.next_in_);
     27   EXPECT_EQ(0u, context.avail_in_);
     28   EXPECT_EQ(0u, context.skip_size_);
     29 
     30   context.SetInputBuffer(nullptr, 100);
     31   EXPECT_EQ(nullptr, context.next_in_);
     32   EXPECT_EQ(100u, context.avail_in_);
     33   EXPECT_EQ(0u, context.skip_size_);
     34 
     35   uint8_t buffer[] = {0x00, 0x01, 0x02};
     36   context.SetInputBuffer(buffer, 0);
     37   EXPECT_EQ(buffer, context.next_in_);
     38   EXPECT_EQ(0u, context.avail_in_);
     39   EXPECT_EQ(0u, context.skip_size_);
     40 
     41   context.SetInputBuffer(buffer, 3);
     42   EXPECT_EQ(buffer, context.next_in_);
     43   EXPECT_EQ(3u, context.avail_in_);
     44   EXPECT_EQ(0u, context.skip_size_);
     45 
     46   context.SetInputBuffer(buffer, 100);
     47   EXPECT_EQ(buffer, context.next_in_);
     48   EXPECT_EQ(100u, context.avail_in_);
     49   EXPECT_EQ(0u, context.skip_size_);
     50 }
     51 
     52 TEST(CFX_GifContext, ReadData) {
     53   CFX_GifContextForTest context(nullptr, nullptr);
     54 
     55   context.SetInputBuffer(nullptr, 0);
     56   EXPECT_EQ(nullptr, context.ReadData(nullptr, 0));
     57   EXPECT_EQ(nullptr, context.ReadData(nullptr, 10));
     58 
     59   uint8_t* dest_buffer = nullptr;
     60   EXPECT_EQ(nullptr,
     61             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 0));
     62   EXPECT_EQ(nullptr,
     63             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
     64 
     65   uint8_t src_buffer[] = {0x00, 0x01, 0x02, 0x03, 0x04,
     66                           0x05, 0x06, 0x07, 0x08, 0x09};
     67   context.SetInputBuffer(src_buffer, 0);
     68   EXPECT_EQ(nullptr,
     69             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
     70   EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), context.next_in_);
     71   EXPECT_EQ(0u, context.avail_in_);
     72   EXPECT_EQ(0u, context.skip_size_);
     73 
     74   dest_buffer = nullptr;
     75   context.SetInputBuffer(src_buffer, 10);
     76   EXPECT_EQ(src_buffer,
     77             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 10));
     78   EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), dest_buffer);
     79   EXPECT_EQ(src_buffer, context.next_in_);
     80   EXPECT_EQ(10u, context.avail_in_);
     81   EXPECT_EQ(10u, context.skip_size_);
     82 
     83   dest_buffer = nullptr;
     84   context.SetInputBuffer(src_buffer, 10);
     85   EXPECT_EQ(src_buffer,
     86             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
     87   EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer), dest_buffer);
     88   EXPECT_EQ(src_buffer, context.next_in_);
     89   EXPECT_EQ(10u, context.avail_in_);
     90   EXPECT_EQ(5u, context.skip_size_);
     91 
     92   dest_buffer = nullptr;
     93   EXPECT_EQ(src_buffer + 5,
     94             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
     95   EXPECT_EQ(reinterpret_cast<uint8_t*>(src_buffer + 5), dest_buffer);
     96   EXPECT_EQ(src_buffer, context.next_in_);
     97   EXPECT_EQ(10u, context.avail_in_);
     98   EXPECT_EQ(10u, context.skip_size_);
     99 
    100   dest_buffer = nullptr;
    101   EXPECT_EQ(nullptr,
    102             context.ReadData(reinterpret_cast<uint8_t**>(&dest_buffer), 5));
    103   EXPECT_EQ(nullptr, dest_buffer);
    104   EXPECT_EQ(src_buffer, context.next_in_);
    105   EXPECT_EQ(10u, context.avail_in_);
    106   EXPECT_EQ(10u, context.skip_size_);
    107 }
    108 
    109 TEST(CFX_GifContext, ReadGifSignature) {
    110   CFX_GifContextForTest context(nullptr, nullptr);
    111 
    112   {
    113     uint8_t data[1];
    114     context.SetInputBuffer(data, 0);
    115     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature());
    116     EXPECT_EQ(0u, context.skip_size_);
    117   }
    118   // Make sure testing the entire signature
    119   {
    120     uint8_t data[] = {'G', 'I', 'F'};
    121     context.SetInputBuffer(data, sizeof(data));
    122     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadGifSignature());
    123     EXPECT_EQ(0u, context.skip_size_);
    124   }
    125   {
    126     uint8_t data[] = {'N', 'O', 'T', 'G', 'I', 'F'};
    127     context.SetInputBuffer(data, sizeof(data));
    128     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
    129     EXPECT_EQ(6u, context.skip_size_);
    130   }
    131   // Make sure not matching GIF8*a
    132   {
    133     uint8_t data[] = {'G', 'I', 'F', '8', '0', 'a'};
    134     context.SetInputBuffer(data, sizeof(data));
    135     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
    136     EXPECT_EQ(6u, context.skip_size_);
    137   }
    138   // Make sure not matching GIF**a
    139   {
    140     uint8_t data[] = {'G', 'I', 'F', '9', '2', 'a'};
    141     context.SetInputBuffer(data, sizeof(data));
    142     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadGifSignature());
    143     EXPECT_EQ(6u, context.skip_size_);
    144   }
    145   // One valid signature
    146   {
    147     uint8_t data[] = {'G', 'I', 'F', '8', '7', 'a'};
    148     context.SetInputBuffer(data, sizeof(data));
    149     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature());
    150     EXPECT_EQ(6u, context.skip_size_);
    151   }
    152   // The other valid signature
    153   {
    154     uint8_t data[] = {'G', 'I', 'F', '8', '9', 'a'};
    155     context.SetInputBuffer(data, sizeof(data));
    156     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadGifSignature());
    157     EXPECT_EQ(6u, context.skip_size_);
    158   }
    159 }
    160 
    161 TEST(CFX_GifContext, ReadLocalScreenDescriptor) {
    162   CFX_GifContextForTest context(nullptr, nullptr);
    163   {
    164     uint8_t data[1];
    165     context.SetInputBuffer(data, 0);
    166     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished,
    167               context.ReadLogicalScreenDescriptor());
    168   }
    169   // LSD with all the values zero'd
    170   {
    171     uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
    172     memset(&lsd, 0, sizeof(CFX_GifLocalScreenDescriptor));
    173     context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor));
    174 
    175     EXPECT_EQ(CFX_GifDecodeStatus::Success,
    176               context.ReadLogicalScreenDescriptor());
    177 
    178     EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor), context.skip_size_);
    179     EXPECT_EQ(0, context.width_);
    180     EXPECT_EQ(0, context.height_);
    181     EXPECT_EQ(0u, context.bc_index_);
    182     EXPECT_EQ(0u, context.pixel_aspect_);
    183   }
    184   // LSD with no global palette
    185   {
    186     uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)] = {0x0A, 0x00, 0x00, 0x0F,
    187                                                          0x00, 0x01, 0x02};
    188     context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor));
    189 
    190     EXPECT_EQ(CFX_GifDecodeStatus::Success,
    191               context.ReadLogicalScreenDescriptor());
    192 
    193     EXPECT_EQ(sizeof(CFX_GifLocalScreenDescriptor), context.skip_size_);
    194     EXPECT_EQ(0x000A, context.width_);
    195     EXPECT_EQ(0x0F00, context.height_);
    196     EXPECT_EQ(0u, context.bc_index_);  // bc_index_ is 0 if no global palette
    197     EXPECT_EQ(2u, context.pixel_aspect_);
    198   }
    199   // LSD with global palette bit set, but no global palette
    200   {
    201     uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)] = {0x0A, 0x00, 0x00, 0x0F,
    202                                                          0x80, 0x01, 0x02};
    203     context.SetInputBuffer(lsd, sizeof(CFX_GifLocalScreenDescriptor));
    204 
    205     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished,
    206               context.ReadLogicalScreenDescriptor());
    207 
    208     EXPECT_EQ(0u, context.skip_size_);
    209   }
    210   // LSD with global palette
    211   {
    212     struct {
    213       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
    214       uint8_t palette[4 * sizeof(CFX_GifPalette)];
    215     } data = {{0x0A, 0x00, 0x00, 0x0F, 0xA9, 0x01, 0x02},
    216               {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1}};
    217     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
    218 
    219     EXPECT_EQ(CFX_GifDecodeStatus::Success,
    220               context.ReadLogicalScreenDescriptor());
    221 
    222     EXPECT_EQ(sizeof(data), context.skip_size_);
    223     EXPECT_EQ(0x000A, context.width_);
    224     EXPECT_EQ(0x0F00, context.height_);
    225     EXPECT_EQ(1u, context.bc_index_);
    226     EXPECT_EQ(2u, context.pixel_aspect_);
    227 
    228     EXPECT_EQ(1u, context.global_pal_exp_);
    229     EXPECT_EQ(1, context.global_sort_flag_);
    230     EXPECT_EQ(2, context.global_color_resolution_);
    231     EXPECT_TRUE(0 == memcmp(data.palette, context.global_palette_.data(),
    232                             sizeof(data.palette)));
    233   }
    234 }
    235 
    236 TEST(CFX_GifContext, ReadHeader) {
    237   CFX_GifContextForTest context(nullptr, nullptr);
    238   // Bad signature
    239   {
    240     struct {
    241       uint8_t signature[6];
    242       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
    243     } data = {{'N', 'O', 'T', 'G', 'I', 'F'},
    244               {0x0A, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x02}};
    245     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
    246 
    247     EXPECT_EQ(CFX_GifDecodeStatus::Error, context.ReadHeader());
    248 
    249     EXPECT_EQ(sizeof(data.signature), context.skip_size_);
    250   }
    251   // Short after signature
    252   {
    253     uint8_t signature[] = {'G', 'I', 'F', '8', '7', 'a'};
    254     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&signature),
    255                            sizeof(signature));
    256 
    257     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader());
    258 
    259     EXPECT_EQ(sizeof(signature), context.skip_size_);
    260   }
    261   // Success without global palette
    262   {
    263     struct {
    264       uint8_t signature[6];
    265       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
    266     } data = {{'G', 'I', 'F', '8', '7', 'a'},
    267               {0x0A, 0x00, 0x00, 0x0F, 0x00, 0x01, 0x02}};
    268     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
    269 
    270     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader());
    271 
    272     EXPECT_EQ(sizeof(data), context.skip_size_);
    273     EXPECT_EQ(0x000A, context.width_);
    274     EXPECT_EQ(0x0F00, context.height_);
    275     EXPECT_EQ(0u, context.bc_index_);  // bc_index_ is 0 if no global palette
    276     EXPECT_EQ(2u, context.pixel_aspect_);
    277   }
    278   // Missing Global Palette
    279   {
    280     struct {
    281       uint8_t signature[6];
    282       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
    283     } data = {{'G', 'I', 'F', '8', '7', 'a'},
    284               {0x0A, 0x00, 0x00, 0x0F, 0x80, 0x01, 0x02}};
    285     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
    286 
    287     EXPECT_EQ(CFX_GifDecodeStatus::Unfinished, context.ReadHeader());
    288 
    289     EXPECT_EQ(sizeof(data.signature), context.skip_size_);
    290   }
    291   // Success with global palette
    292   {
    293     struct {
    294       uint8_t signature[6];
    295       uint8_t lsd[sizeof(CFX_GifLocalScreenDescriptor)];
    296       uint8_t palette[4 * sizeof(CFX_GifPalette)];
    297     } data = {{'G', 'I', 'F', '8', '7', 'a'},
    298               {0x0A, 0x00, 0x00, 0x0F, 0xA9, 0x01, 0x02},
    299               {0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1}};
    300     context.SetInputBuffer(reinterpret_cast<uint8_t*>(&data), sizeof(data));
    301 
    302     EXPECT_EQ(CFX_GifDecodeStatus::Success, context.ReadHeader());
    303 
    304     EXPECT_EQ(sizeof(data), context.skip_size_);
    305     EXPECT_EQ(0x000A, context.width_);
    306     EXPECT_EQ(0x0F00, context.height_);
    307     EXPECT_EQ(1u, context.bc_index_);
    308     EXPECT_EQ(2u, context.pixel_aspect_);
    309     EXPECT_EQ(1u, context.global_pal_exp_);
    310     EXPECT_EQ(1, context.global_sort_flag_);
    311     EXPECT_EQ(2, context.global_color_resolution_);
    312     EXPECT_TRUE(0 == memcmp(data.palette, context.global_palette_.data(),
    313                             sizeof(data.palette)));
    314   }
    315 }
    316