Index: media/webm/webm_parser_unittest.cc |
diff --git a/media/webm/webm_parser_unittest.cc b/media/webm/webm_parser_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5e74a94ebaf79f3157f939b9774732bea8cd9527 |
--- /dev/null |
+++ b/media/webm/webm_parser_unittest.cc |
@@ -0,0 +1,289 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/webm/cluster_builder.h" |
+#include "media/webm/webm_constants.h" |
+#include "media/webm/webm_parser.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using ::testing::InSequence; |
+using ::testing::Return; |
+using ::testing::StrictMock; |
+using ::testing::_; |
+ |
+namespace media { |
+ |
+class MockWebMParserClient : public WebMParserClient { |
+ public: |
+ virtual ~MockWebMParserClient() {} |
+ |
+ // WebMParserClient methods. |
+ MOCK_METHOD1(OnListStart, bool(int)); |
+ MOCK_METHOD1(OnListEnd, bool(int)); |
+ MOCK_METHOD2(OnUInt, bool(int, int64)); |
+ MOCK_METHOD2(OnFloat, bool(int, double)); |
+ MOCK_METHOD3(OnBinary, bool(int, const uint8*, int)); |
+ MOCK_METHOD2(OnString, bool(int, const std::string&)); |
+ MOCK_METHOD5(OnSimpleBlock, bool(int, int, int, const uint8*, int)); |
+}; |
+ |
+class WebMParserTest : public testing::Test { |
+ protected: |
+ struct SimpleBlockInfo { |
+ int track_num; |
+ int timestamp; |
+ }; |
+ |
+ static void AddSimpleBlock(ClusterBuilder* cb, int track_num, |
scherkus (not reviewing)
2011/12/09 21:36:03
nit: move all these static methods to outside the
acolwell GONE FROM CHROMIUM
2011/12/09 22:53:53
Done.
|
+ int64 timecode) { |
+ uint8 data[] = { 0x00 }; |
+ cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); |
+ } |
+ |
+ static Cluster* CreateCluster(int timecode, |
+ const SimpleBlockInfo* block_info, |
+ int block_count) { |
+ ClusterBuilder cb; |
+ cb.SetClusterTimecode(0); |
+ |
+ for (int i = 0; i < block_count; i++) |
+ AddSimpleBlock(&cb, block_info[i].track_num, block_info[i].timestamp); |
+ |
+ return cb.Finish(); |
+ } |
+ |
+ static void CreateClusterExpectations(int timecode, |
+ const SimpleBlockInfo* block_info, |
+ int block_count, |
+ MockWebMParserClient* client) { |
+ |
+ InSequence s; |
+ EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
+ EXPECT_CALL(*client, OnUInt(kWebMIdTimecode, 0)).WillOnce(Return(true)); |
+ |
+ for (int i = 0; i < block_count; i++) { |
+ EXPECT_CALL(*client, OnSimpleBlock(block_info[i].track_num, |
+ block_info[i].timestamp, |
+ _, _, _) |
+ ).WillOnce(Return(true)); |
scherkus (not reviewing)
2011/12/09 21:36:03
nit: move ) to previous line and have this .WillOn
acolwell GONE FROM CHROMIUM
2011/12/09 22:53:53
Done. Not sure why I did that in the first place.
|
+ } |
+ |
+ EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); |
+ } |
+}; |
+ |
+TEST_F(WebMParserTest, EmptyCluster) { |
+ const uint8 kEmptyCluster[] = { |
+ 0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0) |
+ }; |
+ int size = sizeof(kEmptyCluster); |
+ |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
scherkus (not reviewing)
2011/12/09 21:36:03
nit: does this need to be a pointer? Looks like st
acolwell GONE FROM CHROMIUM
2011/12/09 22:53:53
Done. Removed pointer and placed it in WebMParserT
|
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ InSequence s; |
+ EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
+ EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); |
+ |
+ WebMListParser parser(kWebMIdCluster); |
+ int result = parser.Parse(kEmptyCluster, size, client.get()); |
+ EXPECT_EQ(size, result); |
+ EXPECT_TRUE(parser.IsParsingComplete()); |
+} |
+ |
+TEST_F(WebMParserTest, EmptyClusterInSegment) { |
+ const uint8 kBuffer[] = { |
+ 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5) |
+ 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0) |
+ }; |
+ int size = sizeof(kBuffer); |
+ |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ InSequence s; |
+ EXPECT_CALL(*client, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); |
+ EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
+ EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); |
+ EXPECT_CALL(*client, OnListEnd(kWebMIdSegment)).WillOnce(Return(true)); |
+ |
+ WebMListParser parser(kWebMIdSegment); |
+ int result = parser.Parse(kBuffer, size, client.get()); |
+ EXPECT_EQ(size, result); |
+ EXPECT_TRUE(parser.IsParsingComplete()); |
+} |
+ |
+// Test the case where a non-list child element has a size |
+// that is beyond the end of the parent. |
+TEST_F(WebMParserTest, ChildNonListLargerThanParent) { |
+ const uint8 kBuffer[] = { |
+ 0x1F, 0x43, 0xB6, 0x75, 0x81, // CLUSTER (size = 1) |
+ 0xE7, 0x81, 0x01, // Timecode (size=1, value=1) |
scherkus (not reviewing)
2011/12/09 21:36:03
two space
acolwell GONE FROM CHROMIUM
2011/12/09 22:53:53
Done.
|
+ }; |
+ int size = sizeof(kBuffer); |
+ |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ InSequence s; |
+ EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
+ |
+ WebMListParser parser(kWebMIdCluster); |
+ int result = parser.Parse(kBuffer, size, client.get()); |
+ EXPECT_EQ(-1, result); |
+ EXPECT_FALSE(parser.IsParsingComplete()); |
+} |
+ |
+// Test the case where a list child element has a size |
+// that is beyond the end of the parent. |
+TEST_F(WebMParserTest, ChildListLargerThanParent) { |
+ const uint8 kBuffer[] = { |
+ 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5) |
+ 0x1F, 0x43, 0xB6, 0x75, 0x81, 0x11 // CLUSTER (size = 1) |
+ }; |
+ int size = sizeof(kBuffer); |
+ |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ InSequence s; |
+ EXPECT_CALL(*client, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); |
+ |
+ WebMListParser parser(kWebMIdSegment); |
+ int result = parser.Parse(kBuffer, size, client.get()); |
+ EXPECT_EQ(-1, result); |
+ EXPECT_FALSE(parser.IsParsingComplete()); |
+} |
+ |
+// Expecting to parse a Cluster, but get a Segment. |
+TEST_F(WebMParserTest, ListIdDoesNotMatch) { |
+ const uint8 kBuffer[] = { |
+ 0x18, 0x53, 0x80, 0x67, 0x80, // SEGMENT (size = 0) |
+ }; |
+ int size = sizeof(kBuffer); |
+ |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ WebMListParser parser(kWebMIdCluster); |
+ int result = parser.Parse(kBuffer, size, client.get()); |
+ EXPECT_EQ(-1, result); |
+ EXPECT_FALSE(parser.IsParsingComplete()); |
+} |
+ |
+TEST_F(WebMParserTest, InvalidElementInList) { |
+ const uint8 kBuffer[] = { |
+ 0x18, 0x53, 0x80, 0x67, 0x82, // SEGMENT (size = 2) |
+ 0xAE, 0x80, // TrackEntry (size = 0) |
+ }; |
+ int size = sizeof(kBuffer); |
+ |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ InSequence s; |
+ EXPECT_CALL(*client, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); |
+ |
+ WebMListParser parser(kWebMIdSegment); |
+ int result = parser.Parse(kBuffer, size, client.get()); |
+ EXPECT_EQ(-1, result); |
+ EXPECT_FALSE(parser.IsParsingComplete()); |
+} |
+ |
+TEST_F(WebMParserTest, VoidAndCRC32InList) { |
+ const uint8 kBuffer[] = { |
+ 0x18, 0x53, 0x80, 0x67, 0x99, // SEGMENT (size = 25) |
+ 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3) |
+ 0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3) |
+ 0x1F, 0x43, 0xB6, 0x75, 0x8A, // CLUSTER (size = 10) |
+ 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3) |
+ 0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3) |
+ }; |
+ int size = sizeof(kBuffer); |
+ |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ InSequence s; |
+ EXPECT_CALL(*client, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); |
+ EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
+ EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); |
+ EXPECT_CALL(*client, OnListEnd(kWebMIdSegment)).WillOnce(Return(true)); |
+ |
+ WebMListParser parser(kWebMIdSegment); |
+ int result = parser.Parse(kBuffer, size, client.get()); |
+ EXPECT_EQ(size, result); |
+ EXPECT_TRUE(parser.IsParsingComplete()); |
+} |
+ |
+ |
+TEST_F(WebMParserTest, ParseListElementWithSingleCall) { |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ const SimpleBlockInfo kBlockInfo[] = { |
+ { 0, 1 }, |
+ { 1, 2 }, |
+ { 0, 3 }, |
+ { 0, 4 }, |
+ { 1, 4 }, |
+ }; |
+ int block_count = arraysize(kBlockInfo); |
+ |
+ scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
+ CreateClusterExpectations(0, kBlockInfo, block_count, client.get()); |
+ |
+ WebMListParser parser(kWebMIdCluster); |
+ int result = parser.Parse(cluster->data(), cluster->size(), client.get()); |
+ EXPECT_EQ(cluster->size(), result); |
+ EXPECT_TRUE(parser.IsParsingComplete()); |
+} |
+ |
+TEST_F(WebMParserTest, ParseListElementWithMultipleCalls) { |
+ scoped_ptr<StrictMock<MockWebMParserClient> > client( |
+ new StrictMock<MockWebMParserClient>()); |
+ |
+ const SimpleBlockInfo kBlockInfo[] = { |
+ { 0, 1 }, |
+ { 1, 2 }, |
+ { 0, 3 }, |
+ { 0, 4 }, |
+ { 1, 4 }, |
+ }; |
+ int block_count = arraysize(kBlockInfo); |
+ |
+ scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
+ CreateClusterExpectations(0, kBlockInfo, block_count, client.get()); |
+ |
+ const uint8* data = cluster->data(); |
+ int size = cluster->size(); |
+ int default_parse_size = 3; |
+ WebMListParser parser(kWebMIdCluster); |
+ int parse_size = std::min(default_parse_size, size); |
+ |
+ while (size > 0) { |
+ int result = parser.Parse(data, parse_size, client.get()); |
+ EXPECT_GE(result, 0); |
+ EXPECT_LE(result, parse_size); |
+ |
+ if (result == 0) { |
+ // The parser needs more data so increase the parse_size a little. |
+ EXPECT_FALSE(parser.IsParsingComplete()); |
+ parse_size += default_parse_size; |
+ parse_size = std::min(parse_size, size); |
+ continue; |
+ } |
+ |
+ parse_size = default_parse_size; |
+ |
+ data += result; |
+ size -= result; |
+ |
+ EXPECT_EQ((size == 0), parser.IsParsingComplete()); |
+ } |
+ EXPECT_TRUE(parser.IsParsingComplete()); |
+} |
+ |
+} // namespace media |