Home | History | Annotate | Download | only in webm
      1 // Copyright (c) 2012 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 "media/webm/cluster_builder.h"
      6 #include "media/webm/webm_constants.h"
      7 #include "media/webm/webm_parser.h"
      8 #include "testing/gmock/include/gmock/gmock.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 
     11 using ::testing::InSequence;
     12 using ::testing::Return;
     13 using ::testing::ReturnNull;
     14 using ::testing::StrictMock;
     15 using ::testing::_;
     16 
     17 namespace media {
     18 
     19 enum { kBlockCount = 5 };
     20 
     21 class MockWebMParserClient : public WebMParserClient {
     22  public:
     23   virtual ~MockWebMParserClient() {}
     24 
     25   // WebMParserClient methods.
     26   MOCK_METHOD1(OnListStart, WebMParserClient*(int));
     27   MOCK_METHOD1(OnListEnd, bool(int));
     28   MOCK_METHOD2(OnUInt, bool(int, int64));
     29   MOCK_METHOD2(OnFloat, bool(int, double));
     30   MOCK_METHOD3(OnBinary, bool(int, const uint8*, int));
     31   MOCK_METHOD2(OnString, bool(int, const std::string&));
     32 };
     33 
     34 class WebMParserTest : public testing::Test {
     35  protected:
     36   StrictMock<MockWebMParserClient> client_;
     37 };
     38 
     39 static scoped_ptr<Cluster> CreateCluster(int block_count) {
     40   ClusterBuilder cb;
     41   cb.SetClusterTimecode(0);
     42 
     43   for (int i = 0; i < block_count; i++) {
     44     uint8 data[] = { 0x00 };
     45     cb.AddSimpleBlock(0, i, 0, data, sizeof(data));
     46   }
     47 
     48   return cb.Finish();
     49 }
     50 
     51 static void CreateClusterExpectations(int block_count,
     52                                       bool is_complete_cluster,
     53                                       MockWebMParserClient* client) {
     54 
     55   InSequence s;
     56   EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(client));
     57   EXPECT_CALL(*client, OnUInt(kWebMIdTimecode, 0))
     58       .WillOnce(Return(true));
     59 
     60   for (int i = 0; i < block_count; i++) {
     61     EXPECT_CALL(*client, OnBinary(kWebMIdSimpleBlock, _, _))
     62         .WillOnce(Return(true));
     63   }
     64 
     65   if (is_complete_cluster)
     66     EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true));
     67 }
     68 
     69 TEST_F(WebMParserTest, EmptyCluster) {
     70   const uint8 kEmptyCluster[] = {
     71     0x1F, 0x43, 0xB6, 0x75, 0x80  // CLUSTER (size = 0)
     72   };
     73   int size = sizeof(kEmptyCluster);
     74 
     75   InSequence s;
     76   EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(&client_));
     77   EXPECT_CALL(client_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true));
     78 
     79   WebMListParser parser(kWebMIdCluster, &client_);
     80   int result = parser.Parse(kEmptyCluster, size);
     81   EXPECT_EQ(size, result);
     82   EXPECT_TRUE(parser.IsParsingComplete());
     83 }
     84 
     85 TEST_F(WebMParserTest, EmptyClusterInSegment) {
     86   const uint8 kBuffer[] = {
     87     0x18, 0x53, 0x80, 0x67, 0x85,  // SEGMENT (size = 5)
     88     0x1F, 0x43, 0xB6, 0x75, 0x80,  // CLUSTER (size = 0)
     89   };
     90   int size = sizeof(kBuffer);
     91 
     92   InSequence s;
     93   EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(&client_));
     94   EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(&client_));
     95   EXPECT_CALL(client_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true));
     96   EXPECT_CALL(client_, OnListEnd(kWebMIdSegment)).WillOnce(Return(true));
     97 
     98   WebMListParser parser(kWebMIdSegment, &client_);
     99   int result = parser.Parse(kBuffer, size);
    100   EXPECT_EQ(size, result);
    101   EXPECT_TRUE(parser.IsParsingComplete());
    102 }
    103 
    104 // Test the case where a non-list child element has a size
    105 // that is beyond the end of the parent.
    106 TEST_F(WebMParserTest, ChildNonListLargerThanParent) {
    107   const uint8 kBuffer[] = {
    108     0x1F, 0x43, 0xB6, 0x75, 0x81,  // CLUSTER (size = 1)
    109     0xE7, 0x81, 0x01,  // Timecode (size=1, value=1)
    110   };
    111   int size = sizeof(kBuffer);
    112 
    113   InSequence s;
    114   EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(&client_));
    115 
    116   WebMListParser parser(kWebMIdCluster, &client_);
    117   int result = parser.Parse(kBuffer, size);
    118   EXPECT_EQ(-1, result);
    119   EXPECT_FALSE(parser.IsParsingComplete());
    120 }
    121 
    122 // Test the case where a list child element has a size
    123 // that is beyond the end of the parent.
    124 TEST_F(WebMParserTest, ChildListLargerThanParent) {
    125   const uint8 kBuffer[] = {
    126     0x18, 0x53, 0x80, 0x67, 0x85,  // SEGMENT (size = 5)
    127     0x1F, 0x43, 0xB6, 0x75, 0x81, 0x11  // CLUSTER (size = 1)
    128   };
    129   int size = sizeof(kBuffer);
    130 
    131   InSequence s;
    132   EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(&client_));
    133 
    134   WebMListParser parser(kWebMIdSegment, &client_);
    135   int result = parser.Parse(kBuffer, size);
    136   EXPECT_EQ(-1, result);
    137   EXPECT_FALSE(parser.IsParsingComplete());
    138 }
    139 
    140 // Expecting to parse a Cluster, but get a Segment.
    141 TEST_F(WebMParserTest, ListIdDoesNotMatch) {
    142   const uint8 kBuffer[] = {
    143     0x18, 0x53, 0x80, 0x67, 0x80,  // SEGMENT (size = 0)
    144   };
    145   int size = sizeof(kBuffer);
    146 
    147   WebMListParser parser(kWebMIdCluster, &client_);
    148   int result = parser.Parse(kBuffer, size);
    149   EXPECT_EQ(-1, result);
    150   EXPECT_FALSE(parser.IsParsingComplete());
    151 }
    152 
    153 TEST_F(WebMParserTest, InvalidElementInList) {
    154   const uint8 kBuffer[] = {
    155     0x18, 0x53, 0x80, 0x67, 0x82,  // SEGMENT (size = 2)
    156     0xAE, 0x80,  // TrackEntry (size = 0)
    157   };
    158   int size = sizeof(kBuffer);
    159 
    160   InSequence s;
    161   EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(&client_));
    162 
    163   WebMListParser parser(kWebMIdSegment, &client_);
    164   int result = parser.Parse(kBuffer, size);
    165   EXPECT_EQ(-1, result);
    166   EXPECT_FALSE(parser.IsParsingComplete());
    167 }
    168 
    169 TEST_F(WebMParserTest, VoidAndCRC32InList) {
    170   const uint8 kBuffer[] = {
    171     0x18, 0x53, 0x80, 0x67, 0x99,  // SEGMENT (size = 25)
    172     0xEC, 0x83, 0x00, 0x00, 0x00,  // Void (size = 3)
    173     0xBF, 0x83, 0x00, 0x00, 0x00,  // CRC32 (size = 3)
    174     0x1F, 0x43, 0xB6, 0x75, 0x8A,  // CLUSTER (size = 10)
    175     0xEC, 0x83, 0x00, 0x00, 0x00,  // Void (size = 3)
    176     0xBF, 0x83, 0x00, 0x00, 0x00,  // CRC32 (size = 3)
    177   };
    178   int size = sizeof(kBuffer);
    179 
    180   InSequence s;
    181   EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(&client_));
    182   EXPECT_CALL(client_, OnListStart(kWebMIdCluster)).WillOnce(Return(&client_));
    183   EXPECT_CALL(client_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true));
    184   EXPECT_CALL(client_, OnListEnd(kWebMIdSegment)).WillOnce(Return(true));
    185 
    186   WebMListParser parser(kWebMIdSegment, &client_);
    187   int result = parser.Parse(kBuffer, size);
    188   EXPECT_EQ(size, result);
    189   EXPECT_TRUE(parser.IsParsingComplete());
    190 }
    191 
    192 
    193 TEST_F(WebMParserTest, ParseListElementWithSingleCall) {
    194   scoped_ptr<Cluster> cluster(CreateCluster(kBlockCount));
    195   CreateClusterExpectations(kBlockCount, true, &client_);
    196 
    197   WebMListParser parser(kWebMIdCluster, &client_);
    198   int result = parser.Parse(cluster->data(), cluster->size());
    199   EXPECT_EQ(cluster->size(), result);
    200   EXPECT_TRUE(parser.IsParsingComplete());
    201 }
    202 
    203 TEST_F(WebMParserTest, ParseListElementWithMultipleCalls) {
    204   scoped_ptr<Cluster> cluster(CreateCluster(kBlockCount));
    205   CreateClusterExpectations(kBlockCount, true, &client_);
    206 
    207   const uint8* data = cluster->data();
    208   int size = cluster->size();
    209   int default_parse_size = 3;
    210   WebMListParser parser(kWebMIdCluster, &client_);
    211   int parse_size = std::min(default_parse_size, size);
    212 
    213   while (size > 0) {
    214     int result = parser.Parse(data, parse_size);
    215     ASSERT_GE(result, 0);
    216     ASSERT_LE(result, parse_size);
    217 
    218     if (result == 0) {
    219       // The parser needs more data so increase the parse_size a little.
    220       EXPECT_FALSE(parser.IsParsingComplete());
    221       parse_size += default_parse_size;
    222       parse_size = std::min(parse_size, size);
    223       continue;
    224     }
    225 
    226     parse_size = default_parse_size;
    227 
    228     data += result;
    229     size -= result;
    230 
    231     EXPECT_EQ((size == 0), parser.IsParsingComplete());
    232   }
    233   EXPECT_TRUE(parser.IsParsingComplete());
    234 }
    235 
    236 TEST_F(WebMParserTest, Reset) {
    237   InSequence s;
    238   scoped_ptr<Cluster> cluster(CreateCluster(kBlockCount));
    239 
    240   // First expect all but the last block.
    241   CreateClusterExpectations(kBlockCount - 1, false, &client_);
    242 
    243   // Now expect all blocks.
    244   CreateClusterExpectations(kBlockCount, true, &client_);
    245 
    246   WebMListParser parser(kWebMIdCluster, &client_);
    247 
    248   // Send slightly less than the full cluster so all but the last block is
    249   // parsed.
    250   int result = parser.Parse(cluster->data(), cluster->size() - 1);
    251   EXPECT_GT(result, 0);
    252   EXPECT_LT(result, cluster->size());
    253   EXPECT_FALSE(parser.IsParsingComplete());
    254 
    255   parser.Reset();
    256 
    257   // Now parse a whole cluster to verify that all the blocks will get parsed.
    258   result = parser.Parse(cluster->data(), cluster->size());
    259   EXPECT_EQ(result, cluster->size());
    260   EXPECT_TRUE(parser.IsParsingComplete());
    261 }
    262 
    263 // Test the case where multiple clients are used for different lists.
    264 TEST_F(WebMParserTest, MultipleClients) {
    265   const uint8 kBuffer[] = {
    266     0x18, 0x53, 0x80, 0x67, 0x94,  // SEGMENT (size = 20)
    267     0x16, 0x54, 0xAE, 0x6B, 0x85,  //   TRACKS (size = 5)
    268     0xAE, 0x83,                    //     TRACKENTRY (size = 3)
    269     0xD7, 0x81, 0x01,              //       TRACKNUMBER (size = 1)
    270     0x1F, 0x43, 0xB6, 0x75, 0x85,  //   CLUSTER (size = 5)
    271     0xEC, 0x83, 0x00, 0x00, 0x00,  //     Void (size = 3)
    272   };
    273   int size = sizeof(kBuffer);
    274 
    275   StrictMock<MockWebMParserClient> c1_;
    276   StrictMock<MockWebMParserClient> c2_;
    277   StrictMock<MockWebMParserClient> c3_;
    278 
    279   InSequence s;
    280   EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(Return(&c1_));
    281   EXPECT_CALL(c1_, OnListStart(kWebMIdTracks)).WillOnce(Return(&c2_));
    282   EXPECT_CALL(c2_, OnListStart(kWebMIdTrackEntry)).WillOnce(Return(&c3_));
    283   EXPECT_CALL(c3_, OnUInt(kWebMIdTrackNumber, 1)).WillOnce(Return(true));
    284   EXPECT_CALL(c2_, OnListEnd(kWebMIdTrackEntry)).WillOnce(Return(true));
    285   EXPECT_CALL(c1_, OnListEnd(kWebMIdTracks)).WillOnce(Return(true));
    286   EXPECT_CALL(c1_, OnListStart(kWebMIdCluster)).WillOnce(Return(&c2_));
    287   EXPECT_CALL(c1_, OnListEnd(kWebMIdCluster)).WillOnce(Return(true));
    288   EXPECT_CALL(client_, OnListEnd(kWebMIdSegment)).WillOnce(Return(true));
    289 
    290   WebMListParser parser(kWebMIdSegment, &client_);
    291   int result = parser.Parse(kBuffer, size);
    292   EXPECT_EQ(size, result);
    293   EXPECT_TRUE(parser.IsParsingComplete());
    294 }
    295 
    296 // Test the case where multiple clients are used for different lists.
    297 TEST_F(WebMParserTest, InvalidClient) {
    298   const uint8 kBuffer[] = {
    299     0x18, 0x53, 0x80, 0x67, 0x85,  // SEGMENT (size = 20)
    300     0x16, 0x54, 0xAE, 0x6B, 0x80,  //   TRACKS (size = 5)
    301   };
    302   int size = sizeof(kBuffer);
    303 
    304   InSequence s;
    305   EXPECT_CALL(client_, OnListStart(kWebMIdSegment)).WillOnce(ReturnNull());
    306 
    307   WebMListParser parser(kWebMIdSegment, &client_);
    308   int result = parser.Parse(kBuffer, size);
    309   EXPECT_EQ(-1, result);
    310   EXPECT_FALSE(parser.IsParsingComplete());
    311 }
    312 
    313 TEST_F(WebMParserTest, ReservedIds) {
    314   const uint8 k1ByteReservedId[] = { 0xFF, 0x81 };
    315   const uint8 k2ByteReservedId[] = { 0x7F, 0xFF, 0x81 };
    316   const uint8 k3ByteReservedId[] = { 0x3F, 0xFF, 0xFF, 0x81 };
    317   const uint8 k4ByteReservedId[] = { 0x1F, 0xFF, 0xFF, 0xFF, 0x81 };
    318   const uint8* kBuffers[] = {
    319     k1ByteReservedId,
    320     k2ByteReservedId,
    321     k3ByteReservedId,
    322     k4ByteReservedId
    323   };
    324 
    325   for (size_t i = 0; i < arraysize(kBuffers); i++) {
    326     int id;
    327     int64 element_size;
    328     int buffer_size = 2 + i;
    329     EXPECT_EQ(buffer_size, WebMParseElementHeader(kBuffers[i], buffer_size,
    330                                                   &id, &element_size));
    331     EXPECT_EQ(id, kWebMReservedId);
    332     EXPECT_EQ(element_size, 1);
    333   }
    334 }
    335 
    336 TEST_F(WebMParserTest, ReservedSizes) {
    337   const uint8 k1ByteReservedSize[] = { 0xA3, 0xFF };
    338   const uint8 k2ByteReservedSize[] = { 0xA3, 0x7F, 0xFF };
    339   const uint8 k3ByteReservedSize[] = { 0xA3, 0x3F, 0xFF, 0xFF };
    340   const uint8 k4ByteReservedSize[] = { 0xA3, 0x1F, 0xFF, 0xFF, 0xFF };
    341   const uint8 k5ByteReservedSize[] = { 0xA3, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF };
    342   const uint8 k6ByteReservedSize[] = { 0xA3, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,
    343                                        0xFF };
    344   const uint8 k7ByteReservedSize[] = { 0xA3, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    345                                        0xFF };
    346   const uint8 k8ByteReservedSize[] = { 0xA3, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    347                                        0xFF, 0xFF };
    348   const uint8* kBuffers[] = {
    349     k1ByteReservedSize,
    350     k2ByteReservedSize,
    351     k3ByteReservedSize,
    352     k4ByteReservedSize,
    353     k5ByteReservedSize,
    354     k6ByteReservedSize,
    355     k7ByteReservedSize,
    356     k8ByteReservedSize
    357   };
    358 
    359   for (size_t i = 0; i < arraysize(kBuffers); i++) {
    360     int id;
    361     int64 element_size;
    362     int buffer_size = 2 + i;
    363     EXPECT_EQ(buffer_size, WebMParseElementHeader(kBuffers[i], buffer_size,
    364                                                   &id, &element_size));
    365     EXPECT_EQ(id, 0xA3);
    366     EXPECT_EQ(element_size, kWebMUnknownSize);
    367   }
    368 }
    369 
    370 TEST_F(WebMParserTest, ZeroPaddedStrings) {
    371   const uint8 kBuffer[] = {
    372     0x1A, 0x45, 0xDF, 0xA3, 0x91,  // EBMLHEADER (size = 17)
    373     0x42, 0x82, 0x80,  // DocType (size = 0)
    374     0x42, 0x82, 0x81, 0x00,  // DocType (size = 1) ""
    375     0x42, 0x82, 0x81, 'a',  // DocType (size = 1) "a"
    376     0x42, 0x82, 0x83, 'a', 0x00, 0x00  // DocType (size = 3) "a"
    377   };
    378   int size = sizeof(kBuffer);
    379 
    380   InSequence s;
    381   EXPECT_CALL(client_, OnListStart(kWebMIdEBMLHeader))
    382       .WillOnce(Return(&client_));
    383   EXPECT_CALL(client_, OnString(kWebMIdDocType, "")).WillOnce(Return(true));
    384   EXPECT_CALL(client_, OnString(kWebMIdDocType, "")).WillOnce(Return(true));
    385   EXPECT_CALL(client_, OnString(kWebMIdDocType, "a")).WillOnce(Return(true));
    386   EXPECT_CALL(client_, OnString(kWebMIdDocType, "a")).WillOnce(Return(true));
    387   EXPECT_CALL(client_, OnListEnd(kWebMIdEBMLHeader)).WillOnce(Return(true));
    388 
    389   WebMListParser parser(kWebMIdEBMLHeader, &client_);
    390   int result = parser.Parse(kBuffer, size);
    391   EXPECT_EQ(size, result);
    392   EXPECT_TRUE(parser.IsParsingComplete());
    393 }
    394 
    395 }  // namespace media
    396