Add a new incremental parsing API

Change-Id: I6b921766836d58df0281fb23b2add3f62a478e14
This commit is contained in:
Michael Bradshaw
2016-06-14 16:53:56 -07:00
parent 900d322cc8
commit cb8ce0b4b5
752 changed files with 21329 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/audio_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::Audio;
using webm::AudioParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class AudioParserTest : public ElementParserTest<AudioParser, Id::kAudio> {};
TEST_F(AudioParserTest, DefaultParse) {
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_FALSE(audio.sampling_frequency.is_present());
EXPECT_EQ(8000, audio.sampling_frequency.value());
EXPECT_FALSE(audio.output_frequency.is_present());
EXPECT_EQ(8000, audio.output_frequency.value());
EXPECT_FALSE(audio.channels.is_present());
EXPECT_EQ(1, audio.channels.value());
EXPECT_FALSE(audio.bit_depth.is_present());
EXPECT_EQ(0, audio.bit_depth.value());
}
TEST_F(AudioParserTest, DefaultValues) {
SetReaderData({
0xB5, // ID = 0x85 (SamplingFrequency).
0x40, 0x00, // Size = 0.
0x78, 0xB5, // ID = 0x78B5 (OutputSamplingFrequency).
0x80, // Size = 0.
0x9F, // ID = 0x9F (Channels).
0x40, 0x00, // Size = 0.
0x62, 0x64, // ID = 0x6264 (BitDepth).
0x80, // Size = 0.
});
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_TRUE(audio.sampling_frequency.is_present());
EXPECT_EQ(8000, audio.sampling_frequency.value());
EXPECT_TRUE(audio.output_frequency.is_present());
EXPECT_EQ(8000, audio.output_frequency.value());
EXPECT_TRUE(audio.channels.is_present());
EXPECT_EQ(1, audio.channels.value());
EXPECT_TRUE(audio.bit_depth.is_present());
EXPECT_EQ(0, audio.bit_depth.value());
}
TEST_F(AudioParserTest, CustomValues) {
SetReaderData({
0xB5, // ID = 0x85 (SamplingFrequency).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1.0f).
0x78, 0xB5, // ID = 0x78B5 (OutputSamplingFrequency).
0x84, // Size = 4.
0x3F, 0xDD, 0xB3, 0xD7, // Body (value = 1.73205077648162841796875f).
0x9F, // ID = 0x9F (Channels).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x62, 0x64, // ID = 0x6264 (BitDepth).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_TRUE(audio.sampling_frequency.is_present());
EXPECT_EQ(1, audio.sampling_frequency.value());
EXPECT_TRUE(audio.output_frequency.is_present());
EXPECT_EQ(1.73205077648162841796875, audio.output_frequency.value());
EXPECT_TRUE(audio.channels.is_present());
EXPECT_EQ(2, audio.channels.value());
EXPECT_TRUE(audio.bit_depth.is_present());
EXPECT_EQ(1, audio.bit_depth.value());
}
TEST_F(AudioParserTest, AbsentOutputSamplingFrequency) {
SetReaderData({
0xB5, // ID = 0x85 (SamplingFrequency).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1.0f).
});
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_TRUE(audio.sampling_frequency.is_present());
EXPECT_EQ(1, audio.sampling_frequency.value());
EXPECT_FALSE(audio.output_frequency.is_present());
EXPECT_EQ(1, audio.output_frequency.value());
EXPECT_FALSE(audio.channels.is_present());
EXPECT_EQ(1, audio.channels.value());
EXPECT_FALSE(audio.bit_depth.is_present());
EXPECT_EQ(0, audio.bit_depth.value());
}
TEST_F(AudioParserTest, DefaultOutputSamplingFrequency) {
SetReaderData({
0xB5, // ID = 0x85 (SamplingFrequency).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1.0f).
0x78, 0xB5, // ID = 0x78B5 (OutputSamplingFrequency).
0x10, 0x00, 0x00, 0x00, // Size = 0.
});
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_TRUE(audio.sampling_frequency.is_present());
EXPECT_EQ(1, audio.sampling_frequency.value());
EXPECT_TRUE(audio.output_frequency.is_present());
EXPECT_EQ(1, audio.output_frequency.value());
EXPECT_FALSE(audio.channels.is_present());
EXPECT_EQ(1, audio.channels.value());
EXPECT_FALSE(audio.bit_depth.is_present());
EXPECT_EQ(0, audio.bit_depth.value());
}
} // namespace

View File

@@ -0,0 +1,24 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/bit_utils.h"
#include "gtest/gtest.h"
using webm::CountLeadingZeros;
namespace {
class BitUtilsTest : public testing::Test {};
TEST_F(BitUtilsTest, CountLeadingZeros) {
EXPECT_EQ(8, CountLeadingZeros(0x00));
EXPECT_EQ(4, CountLeadingZeros(0x0f));
EXPECT_EQ(0, CountLeadingZeros(0xf0));
}
} // namespace

View File

@@ -0,0 +1,81 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_additions_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::BlockAdditions;
using webm::BlockAdditionsParser;
using webm::BlockMore;
using webm::ElementParserTest;
using webm::Id;
namespace {
class BlockAdditionsParserTest
: public ElementParserTest<BlockAdditionsParser, Id::kBlockAdditions> {};
TEST_F(BlockAdditionsParserTest, DefaultParse) {
ParseAndVerify();
const BlockAdditions block_additions = parser_.value();
EXPECT_EQ(0, block_additions.block_mores.size());
}
TEST_F(BlockAdditionsParserTest, DefaultValues) {
SetReaderData({
0xA6, // ID = 0xA6 (BlockMore).
0x80, // Size = 0.
});
ParseAndVerify();
const BlockAdditions block_additions = parser_.value();
ASSERT_EQ(1, block_additions.block_mores.size());
EXPECT_TRUE(block_additions.block_mores[0].is_present());
EXPECT_EQ(BlockMore{}, block_additions.block_mores[0].value());
}
TEST_F(BlockAdditionsParserTest, CustomValues) {
SetReaderData({
0xA6, // ID = 0xA6 (BlockMore).
0x83, // Size = 3.
0xEE, // ID = 0xEE (BlockAddID).
0x81, // Size = 1.
0x02, // Body (value = 2).
0xA6, // ID = 0xA6 (BlockMore).
0x83, // Size = 3.
0xEE, // ID = 0xEE (BlockAddID).
0x81, // Size = 1.
0x03, // Body (value = 3).
});
ParseAndVerify();
const BlockAdditions block_additions = parser_.value();
BlockMore expected;
ASSERT_EQ(2, block_additions.block_mores.size());
expected.id.Set(2, true);
EXPECT_TRUE(block_additions.block_mores[0].is_present());
EXPECT_EQ(expected, block_additions.block_mores[0].value());
expected.id.Set(3, true);
EXPECT_TRUE(block_additions.block_mores[1].is_present());
EXPECT_EQ(expected, block_additions.block_mores[1].value());
}
} // namespace

View File

@@ -0,0 +1,219 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_group_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::InSequence;
using testing::NotNull;
using webm::Block;
using webm::BlockAdditions;
using webm::BlockGroup;
using webm::BlockGroupParser;
using webm::BlockMore;
using webm::ElementParserTest;
using webm::Id;
using webm::Slices;
using webm::Status;
using webm::TimeSlice;
using webm::VirtualBlock;
namespace {
class BlockGroupParserTest
: public ElementParserTest<BlockGroupParser, Id::kBlockGroup> {};
TEST_F(BlockGroupParserTest, InvalidBlock) {
SetReaderData({
0xA1, // ID = 0xA1 (Block).
0x80, // Size = 0.
});
EXPECT_CALL(callback_, OnBlockGroupBegin(_, _)).Times(1);
EXPECT_CALL(callback_, OnBlockGroupEnd(_, _)).Times(0);
ParseAndExpectResult(Status::kInvalidElementSize);
}
TEST_F(BlockGroupParserTest, InvalidVirtualBlock) {
SetReaderData({
0xA2, // ID = 0xA2 (BlockVirtual).
0x80, // Size = 0.
});
EXPECT_CALL(callback_, OnBlockGroupBegin(_, _)).Times(1);
EXPECT_CALL(callback_, OnBlockGroupEnd(_, _)).Times(0);
ParseAndExpectResult(Status::kInvalidElementSize);
}
TEST_F(BlockGroupParserTest, DefaultParse) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnBlockGroupBegin(metadata_, NotNull())).Times(1);
EXPECT_CALL(callback_, OnBlockGroupEnd(metadata_, BlockGroup{})).Times(1);
}
ParseAndVerify();
}
TEST_F(BlockGroupParserTest, DefaultValues) {
SetReaderData({
0xA1, // ID = 0xA1 (Block).
0x85, // Size = 5.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA2, // ID = 0xA2 (BlockVirtual).
0x84, // Size = 4.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x75, 0xA1, // ID = 0x75A1 (BlockAdditions).
0x80, // Size = 0.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x00, // Size = 0.
0xFB, // ID = 0xFB (ReferenceBlock).
0x40, 0x00, // Size = 0.
0x75, 0xA2, // ID = 0x75A2 (DiscardPadding).
0x80, // Size = 0.
0x8E, // ID = 0x8E (Slices).
0x40, 0x00, // Size = 0.
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnBlockGroupBegin(metadata_, NotNull())).Times(1);
BlockGroup block_group;
// Blocks and VirtualBlocks don't have any kind of default defined, so they
// can't have an element state of kPresentAsDefault.
Block block{};
block.track_number = 1;
block.num_frames = 1;
block.is_visible = true;
block_group.block.Set(block, true);
EXPECT_CALL(callback_, OnBlockBegin(_, block, NotNull())).Times(1);
EXPECT_CALL(callback_, OnFrame(_, NotNull(), NotNull())).Times(1);
EXPECT_CALL(callback_, OnBlockEnd(_, block_group.block.value())).Times(1);
VirtualBlock virtual_block{};
virtual_block.track_number = 1;
block_group.virtual_block.Set(virtual_block, true);
block_group.additions.Set({}, true);
block_group.duration.Set(0, true);
block_group.references.emplace_back(0, true);
block_group.discard_padding.Set(0, true);
block_group.slices.Set({}, true);
EXPECT_CALL(callback_, OnBlockGroupEnd(metadata_, block_group)).Times(1);
}
ParseAndVerify();
}
TEST_F(BlockGroupParserTest, CustomValues) {
SetReaderData({
0xA1, // ID = 0xA1 (Block).
0x85, // Size = 5.
0x82, // Track number = 2.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA2, // ID = 0xA2 (BlockVirtual).
0x84, // Size = 4.
0x83, // Track number = 3.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x75, 0xA1, // ID = 0x75A1 (BlockAdditions).
0x83, // Size = 3.
0xA6, // ID = 0xA6 (BlockMore).
0x40, 0x00, // Size = 0.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xFB, // ID = 0xFB (ReferenceBlock).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xFB, // ID = 0xFB (ReferenceBlock).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x75, 0xA2, // ID = 0x75A2 (DiscardPadding).
0x81, // Size = 1.
0xFF, // Body (value = -1).
0x8E, // ID = 0x8E (Slices).
0x40, 0x03, // Size = 3.
0xE8, // ID = 0xE8 (TimeSlice).
0x40, 0x00, // Size = 0.
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnBlockGroupBegin(metadata_, NotNull())).Times(1);
BlockGroup block_group;
// Blocks and VirtualBlocks don't have any kind of default defined, so they
// can't have an element state of kPresentAsDefault.
Block block{};
block.track_number = 2;
block.num_frames = 1;
block.is_visible = true;
block_group.block.Set(block, true);
VirtualBlock virtual_block{};
virtual_block.track_number = 3;
block_group.virtual_block.Set(virtual_block, true);
BlockAdditions block_additions;
block_additions.block_mores.emplace_back(BlockMore{}, true);
block_group.additions.Set(block_additions, true);
block_group.duration.Set(1, true);
block_group.references.emplace_back(1, true);
block_group.references.emplace_back(2, true);
block_group.discard_padding.Set(-1, true);
Slices slices;
slices.slices.emplace_back(TimeSlice{}, true);
block_group.slices.Set(slices, true);
EXPECT_CALL(callback_, OnBlockGroupEnd(metadata_, block_group)).Times(1);
}
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_header_parser.h"
#include "gtest/gtest.h"
#include "test_utils/parser_test.h"
#include "webm/status.h"
using webm::BlockHeader;
using webm::BlockHeaderParser;
using webm::ParserTest;
namespace {
class BlockHeaderParserTest : public ParserTest<BlockHeaderParser> {};
TEST_F(BlockHeaderParserTest, ValidBlock) {
SetReaderData({
0x81, // Track number = 1.
0x12, 0x34, // Timecode = 4660.
0x00, // Flags.
});
ParseAndVerify();
const BlockHeader& block_header = parser_.value();
EXPECT_EQ(1, block_header.track_number);
EXPECT_EQ(0x1234, block_header.timecode);
EXPECT_EQ(0x00, block_header.flags);
}
TEST_F(BlockHeaderParserTest, IncrementalParse) {
SetReaderData({
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // Track number = 2.
0xFF, 0xFE, // Timecode = -2.
0xFF, // Flags.
});
IncrementalParseAndVerify();
const BlockHeader& block_header = parser_.value();
EXPECT_EQ(2, block_header.track_number);
EXPECT_EQ(-2, block_header.timecode);
EXPECT_EQ(0xFF, block_header.flags);
}
} // namespace

View File

@@ -0,0 +1,79 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_more_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::BlockMore;
using webm::BlockMoreParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class BlockMoreParserTest
: public ElementParserTest<BlockMoreParser, Id::kBlockMore> {};
TEST_F(BlockMoreParserTest, DefaultParse) {
ParseAndVerify();
const BlockMore block_more = parser_.value();
EXPECT_FALSE(block_more.id.is_present());
EXPECT_EQ(1, block_more.id.value());
EXPECT_FALSE(block_more.data.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, block_more.data.value());
}
TEST_F(BlockMoreParserTest, DefaultValues) {
SetReaderData({
0xEE, // ID = 0xEE (BlockAddID).
0x80, // Size = 0.
0xA5, // ID = 0xA5 (BlockAdditional).
0x80, // Size = 0.
});
ParseAndVerify();
const BlockMore block_more = parser_.value();
EXPECT_TRUE(block_more.id.is_present());
EXPECT_EQ(1, block_more.id.value());
EXPECT_TRUE(block_more.data.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, block_more.data.value());
}
TEST_F(BlockMoreParserTest, CustomValues) {
SetReaderData({
0xEE, // ID = 0xEE (BlockAddID).
0x81, // Size = 1.
0x02, // Body (value = 2).
0xA5, // ID = 0xA5 (BlockAdditional).
0x81, // Size = 1.
0x00, // Body.
});
ParseAndVerify();
const BlockMore block_more = parser_.value();
EXPECT_TRUE(block_more.id.is_present());
EXPECT_EQ(2, block_more.id.value());
EXPECT_TRUE(block_more.data.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{0x00}, block_more.data.value());
}
} // namespace

View File

@@ -0,0 +1,831 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_parser.h"
#include <cstdint>
#include <memory>
#include <type_traits>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/parser_utils.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::Between;
using testing::DoAll;
using testing::Exactly;
using testing::InSequence;
using testing::Invoke;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::Block;
using webm::BlockParser;
using webm::ElementParserTest;
using webm::FrameMetadata;
using webm::Id;
using webm::kUnknownElementSize;
using webm::Lacing;
using webm::ReadByte;
using webm::Reader;
using webm::SimpleBlock;
using webm::SimpleBlockParser;
using webm::Status;
namespace {
// Represents a single block and its expected parsing results for use in tests.
struct TestData {
// Block data.
std::vector<std::uint8_t> data;
// Expected results.
std::uint64_t expected_track_number;
std::int16_t expected_timecode;
Lacing expected_lacing;
bool expected_is_visible;
bool expected_is_key_frame;
bool expected_is_discardable;
int expected_num_frames;
std::uint64_t expected_frame_start_position;
std::vector<std::uint64_t> expected_frame_sizes;
};
// Test data for an EBML-laced block containing only one frame.
const TestData ebml_lacing_one_frame = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x86, // Flags = key_frame | ebml_lacing.
0x00, // Lace count - 1 = 0 (1 frame).
// Lace data (1 frame).
// Frame 0.
0x00,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kEbml, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for a Xiph-laced block containing only one frame.
const TestData xiph_lacing_one_frame = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x82, // Flags = key_frame | xiph_lacing.
0x00, // Lace count - 1 = 0 (1 frame).
// Lace data (1 frame).
// Frame 0.
0x00,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kXiph, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for a fixed-laced block containing only one frame.
const TestData fixed_lacing_one_frame = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x84, // Flags = key_frame | fixed_lacing.
0x00, // Lace count - 1 = 0 (1 frame).
// Lace data (1 frame).
0x00,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kFixed, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for an EBML-laced block.
const TestData ebml_lacing = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x86, // Flags = key_frame | ebml_lacing.
0x05, // Lace count - 1 = 5 (6 frames).
// Lace data (6 frames).
0xFF, // Lace 0 size = 127.
0x5F, 0x81, // Lace 1 size = 1.
0xC0, // Lace 2 size = 2.
0xFF, // Lace 3 size = 66.
0x81, // Lace 4 size = 4.
// Lace 5 size inferred to be 5.
// Lace data (6 frames).
// Frame 0.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Frame 1.
0x01,
// Frame 2.
0x02, 0x02,
// Frame 3.
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
// Frame 4.
0x04, 0x04, 0x04, 0x04,
// Frame 5.
0x05, 0x05, 0x05, 0x05, 0x05,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kEbml, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
6, // expected_num_frames
11, // expected_frame_start_position
// expected_frame_sizes
{127, 1, 2, 66, 4, 5},
};
// Test data for a Xiph-laced block.
const TestData xiph_lacing = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x82, // Flags = key_frame | xiph_lacing.
0x03, // Lace count - 1 = 3 (4 frames).
// Lace sizes.
0xFF, 0xFF, 0x00, // Lace 0 size = 510.
0xFF, 0x01, // Lace 1 size = 256.
0x02, // Lace 2 size = 2.
// Lace 3 size inferred to be 3.
// Lace data (4 frames).
// Frame 0.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Frame 1.
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
// Frame 2.
0x02, 0x02,
// Frame 3.
0x03, 0x03, 0x03,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kXiph, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
4, // expected_num_frames
11, // expected_frame_start_position
// expected_frame_sizes
{510, 256, 2, 3},
};
// Test data for a fixed-laced block.
const TestData fixed_lacing = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x84, // Flags = key_frame | fixed_lacing.
0x03, // Lace count - 1 = 3 (4 frames).
// Lace data (4 frames).
0x00, 0x00, // Frame 0.
0x01, 0x01, // Frame 1.
0x02, 0x02, // Frame 2.
0x03, 0x03, // Frame 3.
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kFixed, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
4, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{2, 2, 2, 2},
};
// Test data for a block that has no lacing.
const TestData no_lacing = {
// Data.
{
0x40, 0x01, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x80, // Flags = key_frame.
// Lace data (1 frame).
0x00, 0x00, 0x00, // Frame 0.
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kNone, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{3},
};
// Test data for a block that has no flags set in the header.
const TestData no_flags = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
// Lace data (1 frame).
0x00,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kNone, // expected_lacing
true, // expected_is_visible
false, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
4, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for a block that has all Block (ID = Id::kBlock (0xA1)) flags set
// in the header (and no other flags).
const TestData block_flags = {
// Data.
{
0x82, // Track number = 2.
0xFE, 0xDC, // Timecode = -292.
0x08, // Flags = invisible.
// Lace data (1 frame).
0x00,
},
// Expected results.
2, // expected_track_number
-292, // expected_timecode
Lacing::kNone, // expected_lacing
false, // expected_is_visible
false, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
4, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for a block that has all SimpleBlock (ID = Id::kSimpleBlock (0xA3))
// flags set in the header.
const TestData simple_block_flags = {
// Data.
{
0x41, 0x23, // Track number = 291.
0x12, 0x34, // Timecode = 4660.
0x89, // Flags = key_frame | invisible | discardable.
// Lace data (1 frame).
0x00,
},
// Expected results.
291, // expected_track_number
4660, // expected_timecode
Lacing::kNone, // expected_lacing
false, // expected_is_visible
true, // expected_is_key_frame
true, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Checks that the Block matches the expected results in the TestData.
void ValidateBlock(const TestData& test_data, const Block& actual) {
EXPECT_EQ(test_data.expected_track_number, actual.track_number);
EXPECT_EQ(test_data.expected_timecode, actual.timecode);
EXPECT_EQ(test_data.expected_is_visible, actual.is_visible);
EXPECT_EQ(test_data.expected_lacing, actual.lacing);
EXPECT_EQ(test_data.expected_num_frames, actual.num_frames);
}
// Checks that the SimpleBlock matches the expected results in the TestData.
void ValidateBlock(const TestData& test_data, const SimpleBlock& actual) {
ValidateBlock(test_data, static_cast<const Block&>(actual));
EXPECT_EQ(test_data.expected_is_key_frame, actual.is_key_frame);
EXPECT_EQ(test_data.expected_is_discardable, actual.is_discardable);
}
// Constructs a SimpleBlock populated with the expected results for this test.
SimpleBlock ExpectedSimpleBlock(const TestData& test_data) {
SimpleBlock expected;
expected.track_number = test_data.expected_track_number;
expected.timecode = test_data.expected_timecode;
expected.lacing = test_data.expected_lacing;
expected.is_visible = test_data.expected_is_visible;
expected.is_key_frame = test_data.expected_is_key_frame;
expected.is_discardable = test_data.expected_is_discardable;
expected.num_frames = test_data.expected_num_frames;
return expected;
}
// Simple functor that can be used for Callback::OnFrame() that will validate
// the frame metadata and frame byte values.
struct FrameHandler {
// The expected value for the frame metadata.
FrameMetadata expected_metadata;
// The expected value for each byte in the frame.
std::uint8_t expected_frame_byte_value;
// Can be used for Callback::OnFrame() to consume data from the reader and
// validate the results.
Status operator()(const FrameMetadata& metadata, Reader* reader,
std::uint64_t* bytes_remaining) const {
EXPECT_EQ(expected_metadata, metadata);
std::uint8_t frame_byte_value;
Status status;
do {
status = ReadByte(reader, &frame_byte_value);
if (!status.completed_ok()) {
break;
}
EXPECT_EQ(expected_frame_byte_value, frame_byte_value);
--*bytes_remaining;
} while (*bytes_remaining > 0);
return status;
}
};
template <typename T, Id id>
class BasicBlockParserTest : public ElementParserTest<T, id> {
public:
// Sets expectations for a normal (i.e. successful parse) test.
void SetExpectations(const TestData& test_data, bool incremental) {
InSequence dummy;
const SimpleBlock expected_simple_block = ExpectedSimpleBlock(test_data);
const Block expected_block = ExpectedSimpleBlock(test_data);
FrameMetadata metadata = FirstFrameMetadata(test_data);
if (std::is_same<T, SimpleBlockParser>::value) {
EXPECT_CALL(callback_,
OnSimpleBlockBegin(metadata.parent_element,
expected_simple_block, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnBlockBegin(_, _, _)).Times(0);
} else {
EXPECT_CALL(callback_, OnBlockBegin(metadata.parent_element,
expected_block, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnSimpleBlockBegin(_, _, _)).Times(0);
}
std::uint8_t expected_frame_byte_value = 0;
for (const std::uint64_t frame_size : test_data.expected_frame_sizes) {
metadata.size = frame_size;
const FrameHandler frame_handler = {metadata, expected_frame_byte_value};
// Incremental parsing will call OnFrame once for every byte, plus
// maybe one more time if the first call reads zero bytes (if the reader
// is
// blocked).
EXPECT_CALL(callback_, OnFrame(metadata, NotNull(), NotNull()))
.Times(incremental ? Between(frame_size, frame_size + 1) : Exactly(1))
.WillRepeatedly(Invoke(frame_handler));
metadata.position += metadata.size;
++expected_frame_byte_value;
}
if (std::is_same<T, SimpleBlockParser>::value) {
EXPECT_CALL(callback_, OnSimpleBlockEnd(metadata.parent_element,
expected_simple_block))
.Times(1);
EXPECT_CALL(callback_, OnBlockEnd(_, _)).Times(0);
} else {
EXPECT_CALL(callback_,
OnBlockEnd(metadata.parent_element, expected_block))
.Times(1);
EXPECT_CALL(callback_, OnSimpleBlockEnd(_, _)).Times(0);
}
}
// Runs a single test using the provided test data.
void RunTest(const TestData& test_data) {
SetReaderData(test_data.data);
SetExpectations(test_data, false);
ParseAndVerify();
ValidateBlock(test_data, parser_.value());
}
// Same as RunTest(), except it forces parsers to parse one byte at a time.
void RunIncrementalTest(const TestData& test_data) {
SetReaderData(test_data.data);
SetExpectations(test_data, true);
IncrementalParseAndVerify();
ValidateBlock(test_data, parser_.value());
}
// Tests invalid element sizes.
void TestInvalidElementSize() {
TestInit(0, Status::kInvalidElementSize);
TestInit(4, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
// Tests invalid blocks by feeding only the header of the block into the
// parser.
void TestInvalidHeaderOnly(const TestData& test_data) {
EXPECT_CALL(callback_, OnFrame(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnBlockEnd(_, _)).Times(0);
EXPECT_CALL(callback_, OnSimpleBlockEnd(_, _)).Times(0);
SetReaderData(test_data.data);
ParseAndExpectResult(Status::kInvalidElementValue,
test_data.expected_frame_start_position);
}
// Tests an invalid fixed-lace block that has inconsistent frame sizes.
void TestInvalidFixedLaceSizes() {
SetReaderData({
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x84, // Flags = key_frame | fixed_lacing.
0x01, // Lace count - 1 = 1 (2 frames).
// Lace data (2 frames).
0x00, 0x00, // Frame 0.
0x01, // Frame 1 (invalid: inconsistent frame size).
});
EXPECT_CALL(callback_, OnFrame(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnBlockEnd(_, _)).Times(0);
EXPECT_CALL(callback_, OnSimpleBlockEnd(_, _)).Times(0);
ParseAndExpectResult(Status::kInvalidElementValue);
}
// Tests setting the action to Action::kSkip in Callback::OnSimpleBlockBegin
// for the SimpleBlockParser.
void TestSimpleBlockSkip(const TestData& test_data) {
SetReaderData(test_data.data);
const SimpleBlock expected_simple_block = ExpectedSimpleBlock(test_data);
const FrameMetadata metadata = FirstFrameMetadata(test_data);
EXPECT_CALL(callback_, OnSimpleBlockBegin(metadata.parent_element,
expected_simple_block, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnFrame(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnBlockEnd(_, _)).Times(0);
EXPECT_CALL(callback_, OnSimpleBlockEnd(_, _)).Times(0);
IncrementalParseAndVerify();
}
protected:
using ElementParserTest<T, id>::callback_;
using ElementParserTest<T, id>::IncrementalParseAndVerify;
using ElementParserTest<T, id>::metadata_;
using ElementParserTest<T, id>::ParseAndExpectResult;
using ElementParserTest<T, id>::ParseAndVerify;
using ElementParserTest<T, id>::parser_;
using ElementParserTest<T, id>::SetReaderData;
using ElementParserTest<T, id>::TestInit;
private:
// Gets the FrameMetadata for the very first frame in the test data.
FrameMetadata FirstFrameMetadata(const TestData& test_data) {
FrameMetadata metadata;
metadata.parent_element = metadata_;
metadata.parent_element.size = test_data.data.size();
metadata.position = test_data.expected_frame_start_position +
metadata.parent_element.position +
metadata.parent_element.header_size;
metadata.size = test_data.expected_frame_sizes[0];
return metadata;
}
};
class BlockParserTest : public BasicBlockParserTest<BlockParser, Id::kBlock> {};
TEST_F(BlockParserTest, InvalidElementSize) { TestInvalidElementSize(); }
TEST_F(BlockParserTest, InvalidHeaderOnlyNoLacing) {
TestInvalidHeaderOnly(no_lacing);
}
TEST_F(BlockParserTest, InvalidHeaderOnlyFixedLacing) {
TestInvalidHeaderOnly(fixed_lacing);
}
TEST_F(BlockParserTest, InvalidFixedLaceSizes) { TestInvalidFixedLaceSizes(); }
TEST_F(BlockParserTest, BlockNoFlags) { RunTest(no_flags); }
TEST_F(BlockParserTest, BlockFlags) { RunTest(block_flags); }
TEST_F(BlockParserTest, EbmlLacingOneFrame) { RunTest(ebml_lacing_one_frame); }
TEST_F(BlockParserTest, EbmlLacing) { RunTest(ebml_lacing); }
TEST_F(BlockParserTest, XiphLacingOneFrame) { RunTest(xiph_lacing_one_frame); }
TEST_F(BlockParserTest, XiphLacing) { RunTest(xiph_lacing); }
TEST_F(BlockParserTest, FixedLacingOneFrame) {
RunTest(fixed_lacing_one_frame);
}
TEST_F(BlockParserTest, FixedLacing) { RunTest(fixed_lacing); }
TEST_F(BlockParserTest, NoLacing) { RunTest(no_lacing); }
TEST_F(BlockParserTest, BlockWithPositionAndHeaderSize) {
metadata_.position = 15;
metadata_.header_size = 3;
RunTest(no_lacing);
}
TEST_F(BlockParserTest, IncrementalBlockFlags) {
RunIncrementalTest(block_flags);
}
TEST_F(BlockParserTest, IncrementalEbmlLacingOneFrame) {
RunIncrementalTest(ebml_lacing_one_frame);
}
TEST_F(BlockParserTest, IncrementalEbmlLacing) {
RunIncrementalTest(ebml_lacing);
}
TEST_F(BlockParserTest, IncrementalXiphLacingOneFrame) {
RunIncrementalTest(xiph_lacing_one_frame);
}
TEST_F(BlockParserTest, IncrementalXiphLacing) {
RunIncrementalTest(xiph_lacing);
}
TEST_F(BlockParserTest, IncrementalFixedLacingOneFrame) {
RunIncrementalTest(fixed_lacing_one_frame);
}
TEST_F(BlockParserTest, IncrementalFixedLacing) {
RunIncrementalTest(fixed_lacing);
}
TEST_F(BlockParserTest, IncrementalNoLacing) { RunIncrementalTest(no_lacing); }
class SimpleBlockParserTest
: public BasicBlockParserTest<SimpleBlockParser, Id::kSimpleBlock> {};
TEST_F(SimpleBlockParserTest, InvalidElementSize) { TestInvalidElementSize(); }
TEST_F(SimpleBlockParserTest, InvalidHeaderOnlyNoLacing) {
TestInvalidHeaderOnly(no_lacing);
}
TEST_F(SimpleBlockParserTest, InvalidHeaderOnlyFixedLacing) {
TestInvalidHeaderOnly(fixed_lacing);
}
TEST_F(SimpleBlockParserTest, InvalidFixedLaceSizes) {
TestInvalidFixedLaceSizes();
}
TEST_F(SimpleBlockParserTest, SimpleBlockSkip) {
TestSimpleBlockSkip(no_flags);
}
TEST_F(SimpleBlockParserTest, SimpleBlockNoFlags) { RunTest(no_flags); }
TEST_F(SimpleBlockParserTest, SimpleBlockFlags) { RunTest(simple_block_flags); }
TEST_F(SimpleBlockParserTest, EbmlLacingOneFrame) {
RunTest(ebml_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, EbmlLacing) { RunTest(ebml_lacing); }
TEST_F(SimpleBlockParserTest, XiphLacingOneFrame) {
RunTest(xiph_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, XiphLacing) { RunTest(xiph_lacing); }
TEST_F(SimpleBlockParserTest, FixedLacingOneFrame) {
RunTest(fixed_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, FixedLacing) { RunTest(fixed_lacing); }
TEST_F(SimpleBlockParserTest, NoLacing) { RunTest(no_lacing); }
TEST_F(BlockParserTest, SimpleBlockWithPositionAndHeaderSize) {
metadata_.position = 16;
metadata_.header_size = 4;
RunTest(no_lacing);
}
TEST_F(SimpleBlockParserTest, IncrementalSimpleBlockFlags) {
RunIncrementalTest(simple_block_flags);
}
TEST_F(SimpleBlockParserTest, IncrementalEbmlLacingOneFrame) {
RunIncrementalTest(ebml_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, IncrementalEbmlLacing) {
RunIncrementalTest(ebml_lacing);
}
TEST_F(SimpleBlockParserTest, IncrementalXiphLacingOneFrame) {
RunIncrementalTest(xiph_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, IncrementalXiphLacing) {
RunIncrementalTest(xiph_lacing);
}
TEST_F(SimpleBlockParserTest, IncrementalFixedLacingOneFrame) {
RunIncrementalTest(fixed_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, IncrementalFixedLacing) {
RunIncrementalTest(fixed_lacing);
}
TEST_F(SimpleBlockParserTest, IncrementalNoLacing) {
RunIncrementalTest(no_lacing);
}
} // namespace

View File

@@ -0,0 +1,70 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/bool_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::BoolParser;
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::Status;
namespace {
class BoolParserTest : public ElementParserTest<BoolParser> {};
TEST_F(BoolParserTest, InvalidSize) {
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(BoolParserTest, InvalidValue) {
SetReaderData({0x02});
ParseAndExpectResult(Status::kInvalidElementValue);
SetReaderData({0xFF, 0xFF});
ParseAndExpectResult(Status::kInvalidElementValue);
}
TEST_F(BoolParserTest, CustomDefault) {
ResetParser(true);
ParseAndVerify();
EXPECT_EQ(true, parser_.value());
}
TEST_F(BoolParserTest, ValidBool) {
ParseAndVerify();
EXPECT_EQ(false, parser_.value());
SetReaderData({0x00, 0x00, 0x01});
ParseAndVerify();
EXPECT_EQ(true, parser_.value());
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x00});
ParseAndVerify();
EXPECT_EQ(false, parser_.value());
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
ParseAndVerify();
EXPECT_EQ(true, parser_.value());
}
TEST_F(BoolParserTest, IncrementalParse) {
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
IncrementalParseAndVerify();
EXPECT_EQ(false, parser_.value());
}
} // namespace

View File

@@ -0,0 +1,164 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/buffer_reader.h"
#include <array>
#include <cstdint>
#include "gtest/gtest.h"
using webm::BufferReader;
using webm::Status;
namespace {
class BufferReaderTest : public testing::Test {};
TEST_F(BufferReaderTest, Assignment) {
// Test the reader to make sure it resets correctly when assigned.
std::array<std::uint8_t, 4> buffer;
std::uint64_t count;
Status status;
BufferReader reader({});
EXPECT_EQ(0, reader.size());
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0, count);
reader = {1, 2, 3, 4};
EXPECT_EQ(4, reader.size());
status = reader.Read(2, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(2, count);
reader = {5, 6, 7, 8};
status = reader.Read(2, buffer.data() + 2, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(2, count);
std::array<std::uint8_t, 4> expected = {{1, 2, 5, 6}};
EXPECT_EQ(expected, buffer);
}
TEST_F(BufferReaderTest, Empty) {
// Test the reader to make sure it reports EOF on empty inputs.
std::array<std::uint8_t, 1> buffer;
std::uint64_t count;
Status status;
BufferReader reader({});
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0, count);
status = reader.Skip(1, &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0, count);
}
TEST_F(BufferReaderTest, Read) {
// Test the Read method to make sure it reads data correctly.
std::array<std::uint8_t, 15> buffer{};
std::uint64_t count;
Status status;
BufferReader reader({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(5, count);
status = reader.Read(10, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(5, count);
std::array<std::uint8_t, 15> expected = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
EXPECT_EQ(expected, buffer);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0, count);
}
TEST_F(BufferReaderTest, Skip) {
// Test the Skip method to make sure it skips data correctly.
std::uint64_t count;
Status status;
BufferReader reader({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(3, count);
status = reader.Skip(10, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(7, count);
status = reader.Skip(1, &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0, count);
}
TEST_F(BufferReaderTest, ReadAndSkip) {
// Test the Read and Skip methods together to make sure they interact
// correclty.
std::array<std::uint8_t, 10> buffer = {};
std::uint64_t count;
Status status;
BufferReader reader({9, 8, 7, 6, 5, 4, 3, 2, 1, 0});
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(5, count);
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(3, count);
status = reader.Read(5, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(2, count);
std::array<std::uint8_t, 10> expected = {{9, 8, 7, 6, 5, 1, 0, 0, 0, 0}};
EXPECT_EQ(expected, buffer);
}
TEST_F(BufferReaderTest, Position) {
std::array<std::uint8_t, 10> buffer = {};
std::uint64_t count;
Status status;
BufferReader reader({9, 8, 7, 6, 5, 4, 3, 2, 1, 0});
EXPECT_EQ(0, reader.Position());
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(5, count);
EXPECT_EQ(5, reader.Position());
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(3, count);
EXPECT_EQ(8, reader.Position());
status = reader.Read(5, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(2, count);
EXPECT_EQ(10, reader.Position());
std::array<std::uint8_t, 10> expected = {{9, 8, 7, 6, 5, 1, 0, 0, 0, 0}};
EXPECT_EQ(expected, buffer);
}
} // namespace

View File

@@ -0,0 +1,117 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/byte_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::BinaryParser;
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::Status;
using webm::StringParser;
namespace {
class StringParserTest : public ElementParserTest<StringParser> {};
TEST_F(StringParserTest, StringInvalidSize) {
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(StringParserTest, StringCustomDefault) {
ResetParser("foobar");
ParseAndVerify();
EXPECT_EQ("foobar", parser_.value());
}
TEST_F(StringParserTest, StringValidValue) {
ParseAndVerify();
EXPECT_EQ("", parser_.value());
SetReaderData({'!'});
ParseAndVerify();
EXPECT_EQ("!", parser_.value());
SetReaderData({'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd'});
ParseAndVerify();
EXPECT_EQ("Hello, world", parser_.value());
}
TEST_F(StringParserTest, StringTrailingNulCharacters) {
// The trailing NUL characters should be trimmed.
SetReaderData({'H', 'i', '\0', '\0'});
ParseAndVerify();
EXPECT_EQ("Hi", parser_.value());
SetReaderData({'\0'});
ParseAndVerify();
EXPECT_EQ("", parser_.value());
}
TEST_F(StringParserTest, StringIncrementalParse) {
SetReaderData({'M', 'a', 't', 'r', 'o', 's', 'k', 'a'});
IncrementalParseAndVerify();
EXPECT_EQ("Matroska", parser_.value());
}
class BinaryParserTest : public ElementParserTest<BinaryParser> {};
TEST_F(BinaryParserTest, BinaryInvalidSize) {
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(BinaryParserTest, BinaryCustomDefault) {
std::vector<std::uint8_t> expected = {0x00, 0x02, 0x04, 0x06, 0x08};
ResetParser(expected);
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
}
TEST_F(BinaryParserTest, BinaryValidValue) {
std::vector<std::uint8_t> expected;
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
expected = {0x00};
SetReaderData(expected);
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
expected = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
SetReaderData(expected);
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
// Unlike StringParser, the BinaryParser should not trim trailing 0-bytes.
expected = {'H', 'i', '\0', '\0'};
SetReaderData(expected);
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
}
TEST_F(BinaryParserTest, BinaryIncrementalParse) {
const std::vector<std::uint8_t> expected = {
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
SetReaderData(expected);
IncrementalParseAndVerify();
EXPECT_EQ(expected, parser_.value());
}
} // namespace

View File

@@ -0,0 +1,148 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/callback.h"
#include <cstdint>
#include "gtest/gtest.h"
#include "webm/buffer_reader.h"
#include "webm/element.h"
#include "webm/status.h"
using webm::Action;
using webm::BufferReader;
using webm::Callback;
using webm::ElementMetadata;
using webm::Reader;
using webm::Status;
namespace {
void TestCompletedOk(Status (Callback::*function)(const ElementMetadata&)) {
Callback callback;
ElementMetadata metadata{};
Status status = (callback.*function)(metadata);
EXPECT_EQ(Status::kOkCompleted, status.code);
}
template <typename T>
void TestCompletedOk(Status (Callback::*function)(const ElementMetadata&,
const T&)) {
Callback callback;
ElementMetadata metadata{};
T object{};
Status status = (callback.*function)(metadata, object);
EXPECT_EQ(Status::kOkCompleted, status.code);
}
void TestAction(Status (Callback::*function)(const ElementMetadata&, Action*),
Action expected) {
Callback callback;
ElementMetadata metadata{};
Action action;
Status status = (callback.*function)(metadata, &action);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(expected, action);
}
template <typename T>
void TestAction(Status (Callback::*function)(const ElementMetadata&, const T&,
Action*),
Action expected) {
Callback callback;
ElementMetadata metadata{};
T t{};
Action action;
Status status = (callback.*function)(metadata, t, &action);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(expected, action);
}
template <typename T>
void TestRead(Status (Callback::*function)(const T&, Reader*, std::uint64_t*)) {
Callback callback;
Status status;
T metadata{};
BufferReader reader = {0x00, 0x01, 0x02, 0x03};
std::uint64_t bytes_remaining = 4;
status = (callback.*function)(metadata, &reader, &bytes_remaining);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0, bytes_remaining);
}
class CallbackTest : public testing::Test {};
TEST_F(CallbackTest, OnElementBegin) {
TestAction(&Callback::OnElementBegin, Action::kRead);
}
TEST_F(CallbackTest, OnUnknownElement) {
TestRead(&Callback::OnUnknownElement);
}
TEST_F(CallbackTest, OnEbml) { TestCompletedOk(&Callback::OnEbml); }
TEST_F(CallbackTest, OnVoid) { TestRead(&Callback::OnVoid); }
TEST_F(CallbackTest, OnSegmentBegin) {
TestAction(&Callback::OnSegmentBegin, Action::kRead);
}
TEST_F(CallbackTest, OnSeek) { TestCompletedOk(&Callback::OnSeek); }
TEST_F(CallbackTest, OnInfo) { TestCompletedOk(&Callback::OnInfo); }
TEST_F(CallbackTest, OnClusterBegin) {
TestAction(&Callback::OnClusterBegin, Action::kRead);
}
TEST_F(CallbackTest, OnSimpleBlockBegin) {
TestAction(&Callback::OnSimpleBlockBegin, Action::kRead);
}
TEST_F(CallbackTest, OnSimpleBlockEnd) {
TestCompletedOk(&Callback::OnSimpleBlockEnd);
}
TEST_F(CallbackTest, OnBlockGroupBegin) {
TestAction(&Callback::OnBlockGroupBegin, Action::kRead);
}
TEST_F(CallbackTest, OnBlockBegin) {
TestAction(&Callback::OnBlockBegin, Action::kRead);
}
TEST_F(CallbackTest, OnBlockEnd) { TestCompletedOk(&Callback::OnBlockEnd); }
TEST_F(CallbackTest, OnBlockGroupEnd) {
TestCompletedOk(&Callback::OnBlockGroupEnd);
}
TEST_F(CallbackTest, OnFrame) { TestRead(&Callback::OnFrame); }
TEST_F(CallbackTest, OnClusterEnd) { TestCompletedOk(&Callback::OnClusterEnd); }
TEST_F(CallbackTest, OnTrackEntry) { TestCompletedOk(&Callback::OnTrackEntry); }
TEST_F(CallbackTest, OnCuePoint) { TestCompletedOk(&Callback::OnCuePoint); }
TEST_F(CallbackTest, OnEditionEntry) {
TestCompletedOk(&Callback::OnEditionEntry);
}
TEST_F(CallbackTest, OnTag) { TestCompletedOk(&Callback::OnTag); }
TEST_F(CallbackTest, OnSegmentEnd) { TestCompletedOk(&Callback::OnSegmentEnd); }
} // namespace

View File

@@ -0,0 +1,188 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/chapter_atom_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ChapterAtom;
using webm::ChapterAtomParser;
using webm::ChapterDisplay;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ChapterAtomParserTest
: public ElementParserTest<ChapterAtomParser, Id::kChapterAtom> {};
TEST_F(ChapterAtomParserTest, DefaultParse) {
ParseAndVerify();
const ChapterAtom chapter_atom = parser_.value();
EXPECT_FALSE(chapter_atom.uid.is_present());
EXPECT_EQ(0, chapter_atom.uid.value());
EXPECT_FALSE(chapter_atom.string_uid.is_present());
EXPECT_EQ("", chapter_atom.string_uid.value());
EXPECT_FALSE(chapter_atom.time_start.is_present());
EXPECT_EQ(0, chapter_atom.time_start.value());
EXPECT_FALSE(chapter_atom.time_end.is_present());
EXPECT_EQ(0, chapter_atom.time_end.value());
EXPECT_EQ(0, chapter_atom.displays.size());
EXPECT_EQ(0, chapter_atom.atoms.size());
}
TEST_F(ChapterAtomParserTest, DefaultValues) {
SetReaderData({
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x80, // Size = 0.
0x56, 0x54, // ID = 0x73C4 (ChapterStringUID).
0x80, // Size = 0.
0x91, // ID = 0x91 (ChapterTimeStart).
0x40, 0x00, // Size = 0.
0x92, // ID = 0x91 (ChapterTimeEnd).
0x40, 0x00, // Size = 0.
0x80, // ID = 0x80 (ChapterDisplay).
0x40, 0x00, // Size = 0.
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x00, // Size = 0.
});
ParseAndVerify();
const ChapterAtom chapter_atom = parser_.value();
EXPECT_TRUE(chapter_atom.uid.is_present());
EXPECT_EQ(0, chapter_atom.uid.value());
EXPECT_TRUE(chapter_atom.string_uid.is_present());
EXPECT_EQ("", chapter_atom.string_uid.value());
EXPECT_TRUE(chapter_atom.time_start.is_present());
EXPECT_EQ(0, chapter_atom.time_start.value());
EXPECT_TRUE(chapter_atom.time_end.is_present());
EXPECT_EQ(0, chapter_atom.time_end.value());
ASSERT_EQ(1, chapter_atom.displays.size());
EXPECT_TRUE(chapter_atom.displays[0].is_present());
EXPECT_EQ(ChapterDisplay{}, chapter_atom.displays[0].value());
ASSERT_EQ(1, chapter_atom.atoms.size());
EXPECT_TRUE(chapter_atom.atoms[0].is_present());
EXPECT_EQ(ChapterAtom{}, chapter_atom.atoms[0].value());
}
TEST_F(ChapterAtomParserTest, CustomValues) {
SetReaderData({
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x56, 0x54, // ID = 0x73C4 (ChapterStringUID).
0x81, // Size = 1.
0x41, // Body (value = "A").
0x91, // ID = 0x91 (ChapterTimeStart).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x92, // ID = 0x91 (ChapterTimeEnd).
0x40, 0x01, // Size = 1.
0x03, // Body (value = 3).
0x80, // ID = 0x80 (ChapterDisplay).
0x40, 0x04, // Size = 4.
0x85, // ID = 0x85 (ChapString).
0x40, 0x01, // Size = 1.
0x42, // Body (value = "B").
0x80, // ID = 0x80 (ChapterDisplay).
0x40, 0x04, // Size = 4.
0x85, // ID = 0x85 (ChapString).
0x40, 0x01, // Size = 1.
0x43, // Body (value = "C").
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x12, // Size = 18.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x04, // Body (value = 4).
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x04, // Size = 4.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x05, // Body (value = 5).
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x04, // Size = 4.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x06, // Body (value = 6).
});
ParseAndVerify();
const ChapterAtom chapter_atom = parser_.value();
EXPECT_TRUE(chapter_atom.uid.is_present());
EXPECT_EQ(1, chapter_atom.uid.value());
EXPECT_TRUE(chapter_atom.string_uid.is_present());
EXPECT_EQ("A", chapter_atom.string_uid.value());
EXPECT_TRUE(chapter_atom.time_start.is_present());
EXPECT_EQ(2, chapter_atom.time_start.value());
EXPECT_TRUE(chapter_atom.time_end.is_present());
EXPECT_EQ(3, chapter_atom.time_end.value());
ChapterDisplay expected_chapter_display;
ASSERT_EQ(2, chapter_atom.displays.size());
expected_chapter_display.string.Set("B", true);
EXPECT_TRUE(chapter_atom.displays[0].is_present());
EXPECT_EQ(expected_chapter_display, chapter_atom.displays[0].value());
expected_chapter_display.string.Set("C", true);
EXPECT_TRUE(chapter_atom.displays[1].is_present());
EXPECT_EQ(expected_chapter_display, chapter_atom.displays[1].value());
ChapterAtom expected_chapter_atom;
expected_chapter_atom.uid.Set(4, true);
ChapterAtom tmp_atom{};
tmp_atom.uid.Set(5, true);
expected_chapter_atom.atoms.emplace_back(tmp_atom, true);
tmp_atom.uid.Set(6, true);
expected_chapter_atom.atoms.emplace_back(tmp_atom, true);
ASSERT_EQ(1, chapter_atom.atoms.size());
EXPECT_TRUE(chapter_atom.atoms[0].is_present());
EXPECT_EQ(expected_chapter_atom, chapter_atom.atoms[0].value());
}
} // namespace

View File

@@ -0,0 +1,117 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/chapter_display_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ChapterDisplay;
using webm::ChapterDisplayParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ChapterDisplayParserTest
: public ElementParserTest<ChapterDisplayParser, Id::kChapterDisplay> {};
TEST_F(ChapterDisplayParserTest, DefaultParse) {
ParseAndVerify();
const ChapterDisplay chapter_display = parser_.value();
EXPECT_FALSE(chapter_display.string.is_present());
EXPECT_EQ("", chapter_display.string.value());
ASSERT_EQ(1, chapter_display.languages.size());
EXPECT_FALSE(chapter_display.languages[0].is_present());
EXPECT_EQ("eng", chapter_display.languages[0].value());
EXPECT_EQ(0, chapter_display.countries.size());
}
TEST_F(ChapterDisplayParserTest, DefaultValues) {
SetReaderData({
0x85, // ID = 0x85 (ChapString).
0x40, 0x00, // Size = 0.
0x43, 0x7C, // ID = 0x437C (ChapLanguage).
0x80, // Size = 0.
0x43, 0x7E, // ID = 0x437E (ChapCountry).
0x80, // Size = 0.
});
ParseAndVerify();
const ChapterDisplay chapter_display = parser_.value();
EXPECT_TRUE(chapter_display.string.is_present());
EXPECT_EQ("", chapter_display.string.value());
ASSERT_EQ(1, chapter_display.languages.size());
EXPECT_TRUE(chapter_display.languages[0].is_present());
EXPECT_EQ("eng", chapter_display.languages[0].value());
ASSERT_EQ(1, chapter_display.countries.size());
EXPECT_TRUE(chapter_display.countries[0].is_present());
EXPECT_EQ("", chapter_display.countries[0].value());
}
TEST_F(ChapterDisplayParserTest, CustomValues) {
SetReaderData({
0x85, // ID = 0x85 (ChapString).
0x40, 0x05, // Size = 5.
0x68, 0x65, 0x6C, 0x6C, 0x6F, // Body (value = "hello").
0x43, 0x7C, // ID = 0x437C (ChapLanguage).
0x85, // Size = 5.
0x6C, 0x61, 0x6E, 0x67, 0x30, // body (value = "lang0").
0x43, 0x7E, // ID = 0x437E (ChapCountry).
0x85, // Size = 5.
0x61, 0x72, 0x65, 0x61, 0x30, // Body (value = "area0").
0x43, 0x7C, // ID = 0x437C (ChapLanguage).
0x85, // Size = 5.
0x6C, 0x61, 0x6E, 0x67, 0x31, // body (value = "lang1").
0x43, 0x7C, // ID = 0x437C (ChapLanguage).
0x85, // Size = 5.
0x6C, 0x61, 0x6E, 0x67, 0x32, // body (value = "lang2").
0x43, 0x7E, // ID = 0x437E (ChapCountry).
0x85, // Size = 5.
0x61, 0x72, 0x65, 0x61, 0x31, // Body (value = "area1").
});
ParseAndVerify();
const ChapterDisplay chapter_display = parser_.value();
EXPECT_TRUE(chapter_display.string.is_present());
EXPECT_EQ("hello", chapter_display.string.value());
ASSERT_EQ(3, chapter_display.languages.size());
EXPECT_TRUE(chapter_display.languages[0].is_present());
EXPECT_EQ("lang0", chapter_display.languages[0].value());
EXPECT_TRUE(chapter_display.languages[1].is_present());
EXPECT_EQ("lang1", chapter_display.languages[1].value());
EXPECT_TRUE(chapter_display.languages[2].is_present());
EXPECT_EQ("lang2", chapter_display.languages[2].value());
ASSERT_EQ(2, chapter_display.countries.size());
EXPECT_TRUE(chapter_display.countries[0].is_present());
EXPECT_EQ("area0", chapter_display.countries[0].value());
EXPECT_TRUE(chapter_display.countries[1].is_present());
EXPECT_EQ("area1", chapter_display.countries[1].value());
}
} // namespace

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/chapters_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ChaptersParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ChaptersParserTest
: public ElementParserTest<ChaptersParser, Id::kChapters> {};
TEST_F(ChaptersParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(ChaptersParserTest, RepeatedValues) {
SetReaderData({
0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
0x84, // Size = 4.
0x45, 0xBC, // ID = 0x45BC (EditionUID).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
0x84, // Size = 4.
0x45, 0xBC, // ID = 0x45BC (EditionUID).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,252 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/cluster_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::Ancestory;
using webm::BlockGroup;
using webm::Cluster;
using webm::ClusterParser;
using webm::ElementMetadata;
using webm::ElementParserTest;
using webm::Id;
using webm::SimpleBlock;
using webm::Status;
namespace {
class ClusterParserTest
: public ElementParserTest<ClusterParser, Id::kCluster> {};
TEST_F(ClusterParserTest, DefaultParse) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnClusterBegin(metadata_, Cluster{}, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, Cluster{})).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, DefaultValues) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x40, 0x00, // Size = 0.
0xAB, // ID = 0xAB (PrevSize).
0x40, 0x00, // Size = 0.
0xA3, // ID = 0xA3 (SimpleBlock).
0x85, // Size = 5.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA0, // ID = 0xA0 (BlockGroup).
0x40, 0x00, // Size = 0.
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(0, true);
cluster.previous_size.Set(0, true);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
SimpleBlock simple_block{};
simple_block.track_number = 1;
simple_block.num_frames = 1;
simple_block.is_visible = true;
cluster.simple_blocks.emplace_back(simple_block, true);
BlockGroup block_group{};
cluster.block_groups.emplace_back(block_group, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, CustomValues) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xAB, // ID = 0xAB (PrevSize).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0xA3, // ID = 0xA3 (SimpleBlock).
0x85, // Size = 5.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA3, // ID = 0xA3 (SimpleBlock).
0x85, // Size = 5.
0x82, // Track number = 2.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA0, // ID = 0xA0 (BlockGroup).
0x40, 0x04, // Size = 4.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xA0, // ID = 0xA0 (BlockGroup).
0x40, 0x04, // Size = 4.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(1, true);
cluster.previous_size.Set(2, true);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
SimpleBlock simple_block{};
simple_block.num_frames = 1;
simple_block.is_visible = true;
simple_block.track_number = 1;
cluster.simple_blocks.emplace_back(simple_block, true);
simple_block.track_number = 2;
cluster.simple_blocks.emplace_back(simple_block, true);
BlockGroup block_group{};
block_group.duration.Set(1, true);
cluster.block_groups.emplace_back(block_group, true);
block_group.duration.Set(2, true);
cluster.block_groups.emplace_back(block_group, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, SkipOnClusterBegin) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnClusterBegin(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnBlockGroupBegin(_, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(1);
}
ElementMetadata child_metadata = {Id::kBlockGroup, 0, 0, 0};
Ancestory ancestory;
ASSERT_TRUE(Ancestory::ById(child_metadata.id, &ancestory));
// Skip the Segment and Cluster ancestors.
ancestory = ancestory.next().next();
parser_.InitAfterSeek(ancestory, child_metadata);
std::uint64_t num_bytes_read = 0;
const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader_.size(), num_bytes_read);
}
TEST_F(ClusterParserTest, SkipSimpleBlock) {
SetReaderData({
0xA3, // ID = 0xA3 (SimpleBlock).
0x85, // Size = 5.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
});
{
InSequence dummy;
Cluster cluster{};
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
SimpleBlock simple_block{};
simple_block.num_frames = 1;
simple_block.is_visible = true;
simple_block.track_number = 1;
EXPECT_CALL(callback_, OnSimpleBlockBegin(_, simple_block, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, SkipBlockGroup) {
SetReaderData({
0xA0, // ID = 0xA0 (BlockGroup).
0x40, 0x04, // Size = 4.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
{
InSequence dummy;
Cluster cluster{};
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnBlockGroupBegin(_, NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,285 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/colour_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::Colour;
using webm::ColourParser;
using webm::ElementParserTest;
using webm::Id;
using webm::MasteringMetadata;
using webm::MatrixCoefficients;
using webm::Primaries;
using webm::Range;
using webm::TransferCharacteristics;
namespace {
class ColourParserTest : public ElementParserTest<ColourParser, Id::kColour> {};
TEST_F(ColourParserTest, DefaultParse) {
ParseAndVerify();
const Colour colour = parser_.value();
EXPECT_FALSE(colour.matrix_coefficients.is_present());
EXPECT_EQ(MatrixCoefficients::kUnspecified,
colour.matrix_coefficients.value());
EXPECT_FALSE(colour.bits_per_channel.is_present());
EXPECT_EQ(0, colour.bits_per_channel.value());
EXPECT_FALSE(colour.chroma_subsampling_x.is_present());
EXPECT_EQ(0, colour.chroma_subsampling_x.value());
EXPECT_FALSE(colour.chroma_subsampling_y.is_present());
EXPECT_EQ(0, colour.chroma_subsampling_y.value());
EXPECT_FALSE(colour.cb_subsampling_x.is_present());
EXPECT_EQ(0, colour.cb_subsampling_x.value());
EXPECT_FALSE(colour.cb_subsampling_y.is_present());
EXPECT_EQ(0, colour.cb_subsampling_y.value());
EXPECT_FALSE(colour.chroma_siting_x.is_present());
EXPECT_EQ(0, colour.chroma_siting_x.value());
EXPECT_FALSE(colour.chroma_siting_y.is_present());
EXPECT_EQ(0, colour.chroma_siting_y.value());
EXPECT_FALSE(colour.range.is_present());
EXPECT_EQ(Range::kUnspecified, colour.range.value());
EXPECT_FALSE(colour.transfer_characteristics.is_present());
EXPECT_EQ(TransferCharacteristics::kUnspecified,
colour.transfer_characteristics.value());
EXPECT_FALSE(colour.primaries.is_present());
EXPECT_EQ(Primaries::kUnspecified, colour.primaries.value());
EXPECT_FALSE(colour.max_cll.is_present());
EXPECT_EQ(0, colour.max_cll.value());
EXPECT_FALSE(colour.max_fall.is_present());
EXPECT_EQ(0, colour.max_fall.value());
EXPECT_FALSE(colour.mastering_metadata.is_present());
EXPECT_EQ(MasteringMetadata{}, colour.mastering_metadata.value());
}
TEST_F(ColourParserTest, DefaultValues) {
SetReaderData({
0x55, 0xB1, // ID = 0x55B1 (MatrixCoefficients).
0x80, // Size = 0.
0x55, 0xB2, // ID = 0x55B2 (BitsPerChannel).
0x80, // Size = 0.
0x55, 0xB3, // ID = 0x55B3 (ChromaSubsamplingHorz).
0x80, // Size = 0.
0x55, 0xB4, // ID = 0x55B4 (ChromaSubsamplingVert).
0x80, // Size = 0.
0x55, 0xB5, // ID = 0x55B5 (CbSubsamplingHorz).
0x80, // Size = 0.
0x55, 0xB6, // ID = 0x55B6 (CbSubsamplingVert).
0x80, // Size = 0.
0x55, 0xB7, // ID = 0x55B7 (ChromaSitingHorz).
0x80, // Size = 0.
0x55, 0xB8, // ID = 0x55B8 (ChromaSitingVert).
0x80, // Size = 0.
0x55, 0xB9, // ID = 0x55B9 (Range).
0x80, // Size = 0.
0x55, 0xBA, // ID = 0x55BA (TransferCharacteristics).
0x80, // Size = 0.
0x55, 0xBB, // ID = 0x55BB (Primaries).
0x80, // Size = 0.
0x55, 0xBC, // ID = 0x55BC (MaxCLL).
0x80, // Size = 0.
0x55, 0xBD, // ID = 0x55BD (MaxFALL).
0x80, // Size = 0.
0x55, 0xD0, // ID = 0x55D0 (MasteringMetadata).
0x80, // Size = 0.
});
ParseAndVerify();
const Colour colour = parser_.value();
EXPECT_TRUE(colour.matrix_coefficients.is_present());
EXPECT_EQ(MatrixCoefficients::kUnspecified,
colour.matrix_coefficients.value());
EXPECT_TRUE(colour.bits_per_channel.is_present());
EXPECT_EQ(0, colour.bits_per_channel.value());
EXPECT_TRUE(colour.chroma_subsampling_x.is_present());
EXPECT_EQ(0, colour.chroma_subsampling_x.value());
EXPECT_TRUE(colour.chroma_subsampling_y.is_present());
EXPECT_EQ(0, colour.chroma_subsampling_y.value());
EXPECT_TRUE(colour.cb_subsampling_x.is_present());
EXPECT_EQ(0, colour.cb_subsampling_x.value());
EXPECT_TRUE(colour.cb_subsampling_y.is_present());
EXPECT_EQ(0, colour.cb_subsampling_y.value());
EXPECT_TRUE(colour.chroma_siting_x.is_present());
EXPECT_EQ(0, colour.chroma_siting_x.value());
EXPECT_TRUE(colour.chroma_siting_y.is_present());
EXPECT_EQ(0, colour.chroma_siting_y.value());
EXPECT_TRUE(colour.range.is_present());
EXPECT_EQ(Range::kUnspecified, colour.range.value());
EXPECT_TRUE(colour.transfer_characteristics.is_present());
EXPECT_EQ(TransferCharacteristics::kUnspecified,
colour.transfer_characteristics.value());
EXPECT_TRUE(colour.primaries.is_present());
EXPECT_EQ(Primaries::kUnspecified, colour.primaries.value());
EXPECT_TRUE(colour.max_cll.is_present());
EXPECT_EQ(0, colour.max_cll.value());
EXPECT_TRUE(colour.max_fall.is_present());
EXPECT_EQ(0, colour.max_fall.value());
EXPECT_TRUE(colour.mastering_metadata.is_present());
EXPECT_EQ(MasteringMetadata{}, colour.mastering_metadata.value());
}
TEST_F(ColourParserTest, CustomValues) {
SetReaderData({
0x55, 0xB1, // ID = 0x55B1 (MatrixCoefficients).
0x81, // Size = 1.
0x01, // Body (value = BT.709).
0x55, 0xB2, // ID = 0x55B2 (BitsPerChannel).
0x81, // Size = 1.
0x02, // Body (value = 2).
0x55, 0xB3, // ID = 0x55B3 (ChromaSubsamplingHorz).
0x81, // Size = 1.
0x03, // Body (value = 3).
0x55, 0xB4, // ID = 0x55B4 (ChromaSubsamplingVert).
0x81, // Size = 1.
0x04, // Body (value = 4).
0x55, 0xB5, // ID = 0x55B5 (CbSubsamplingHorz).
0x81, // Size = 1.
0x05, // Body (value = 5).
0x55, 0xB6, // ID = 0x55B6 (CbSubsamplingVert).
0x81, // Size = 1.
0x06, // Body (value = 6).
0x55, 0xB7, // ID = 0x55B7 (ChromaSitingHorz).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x55, 0xB8, // ID = 0x55B8 (ChromaSitingVert).
0x81, // Size = 1.
0x02, // Body (value = 2).
0x55, 0xB9, // ID = 0x55B9 (Range).
0x81, // Size = 1.
0x03, // Body (value = 3 (derived)).
0x55, 0xBA, // ID = 0x55BA (TransferCharacteristics).
0x81, // Size = 1.
0x04, // Body (value = BT.4706 System M with display gamma 2.2).
0x55, 0xBB, // ID = 0x55BB (Primaries).
0x81, // Size = 1.
0x05, // Body (value = BT.4706 System B, G).
0x55, 0xBC, // ID = 0x55BC (MaxCLL).
0x81, // Size = 1.
0x06, // Body (value = 6).
0x55, 0xBD, // ID = 0x55BD (MaxFALL).
0x81, // Size = 1.
0x07, // Body (value = 7).
0x55, 0xD0, // ID = 0x55D0 (MasteringMetadata).
0x87, // Size = 7.
0x55, 0xD1, // ID = 0x55D1 (PrimaryRChromaticityX).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1).
});
ParseAndVerify();
const Colour colour = parser_.value();
EXPECT_TRUE(colour.matrix_coefficients.is_present());
EXPECT_EQ(MatrixCoefficients::kBt709, colour.matrix_coefficients.value());
EXPECT_TRUE(colour.bits_per_channel.is_present());
EXPECT_EQ(2, colour.bits_per_channel.value());
EXPECT_TRUE(colour.chroma_subsampling_x.is_present());
EXPECT_EQ(3, colour.chroma_subsampling_x.value());
EXPECT_TRUE(colour.chroma_subsampling_y.is_present());
EXPECT_EQ(4, colour.chroma_subsampling_y.value());
EXPECT_TRUE(colour.cb_subsampling_x.is_present());
EXPECT_EQ(5, colour.cb_subsampling_x.value());
EXPECT_TRUE(colour.cb_subsampling_y.is_present());
EXPECT_EQ(6, colour.cb_subsampling_y.value());
EXPECT_TRUE(colour.chroma_siting_x.is_present());
EXPECT_EQ(1, colour.chroma_siting_x.value());
EXPECT_TRUE(colour.chroma_siting_y.is_present());
EXPECT_EQ(2, colour.chroma_siting_y.value());
EXPECT_TRUE(colour.range.is_present());
EXPECT_EQ(Range::kDerived, colour.range.value());
EXPECT_TRUE(colour.transfer_characteristics.is_present());
EXPECT_EQ(TransferCharacteristics::kGamma22curve,
colour.transfer_characteristics.value());
EXPECT_TRUE(colour.primaries.is_present());
EXPECT_EQ(Primaries::kBt470Bg, colour.primaries.value());
EXPECT_TRUE(colour.max_cll.is_present());
EXPECT_EQ(6, colour.max_cll.value());
EXPECT_TRUE(colour.max_fall.is_present());
EXPECT_EQ(7, colour.max_fall.value());
MasteringMetadata mastering_metadata{};
mastering_metadata.primary_r_chromaticity_x.Set(1.0, true);
EXPECT_TRUE(colour.mastering_metadata.is_present());
EXPECT_EQ(mastering_metadata, colour.mastering_metadata.value());
}
} // namespace

View File

@@ -0,0 +1,68 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/content_enc_aes_settings_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::AesSettingsCipherMode;
using webm::ContentEncAesSettings;
using webm::ContentEncAesSettingsParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ContentEncAesSettingsParserTest
: public ElementParserTest<ContentEncAesSettingsParser,
Id::kContentEncAesSettings> {};
TEST_F(ContentEncAesSettingsParserTest, DefaultParse) {
ParseAndVerify();
const ContentEncAesSettings content_enc_aes_settings = parser_.value();
EXPECT_FALSE(content_enc_aes_settings.aes_settings_cipher_mode.is_present());
EXPECT_EQ(AesSettingsCipherMode::kCtr,
content_enc_aes_settings.aes_settings_cipher_mode.value());
}
TEST_F(ContentEncAesSettingsParserTest, DefaultValues) {
SetReaderData({
0x47, 0xE8, // ID = 0x47E8 (AESSettingsCipherMode).
0x80, // Size = 0.
});
ParseAndVerify();
const ContentEncAesSettings content_enc_aes_settings = parser_.value();
EXPECT_TRUE(content_enc_aes_settings.aes_settings_cipher_mode.is_present());
EXPECT_EQ(AesSettingsCipherMode::kCtr,
content_enc_aes_settings.aes_settings_cipher_mode.value());
}
TEST_F(ContentEncAesSettingsParserTest, CustomValues) {
SetReaderData({
0x47, 0xE8, // ID = 0x47E8 (AESSettingsCipherMode).
0x81, // Size = 1.
0x00, // Body (value = 0).
});
ParseAndVerify();
const ContentEncAesSettings content_enc_aes_settings = parser_.value();
EXPECT_TRUE(content_enc_aes_settings.aes_settings_cipher_mode.is_present());
EXPECT_EQ(static_cast<AesSettingsCipherMode>(0),
content_enc_aes_settings.aes_settings_cipher_mode.value());
}
} // namespace

View File

@@ -0,0 +1,120 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/content_encoding_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ContentEncAlgo;
using webm::ContentEncoding;
using webm::ContentEncodingParser;
using webm::ContentEncodingType;
using webm::ContentEncryption;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ContentEncodingParserTest
: public ElementParserTest<ContentEncodingParser, Id::kContentEncoding> {};
TEST_F(ContentEncodingParserTest, DefaultParse) {
ParseAndVerify();
const ContentEncoding content_encoding = parser_.value();
EXPECT_FALSE(content_encoding.order.is_present());
EXPECT_EQ(0, content_encoding.order.value());
EXPECT_FALSE(content_encoding.scope.is_present());
EXPECT_EQ(1, content_encoding.scope.value());
EXPECT_FALSE(content_encoding.type.is_present());
EXPECT_EQ(ContentEncodingType::kCompression, content_encoding.type.value());
EXPECT_FALSE(content_encoding.encryption.is_present());
EXPECT_EQ(ContentEncryption{}, content_encoding.encryption.value());
}
TEST_F(ContentEncodingParserTest, DefaultValues) {
SetReaderData({
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x80, // Size = 0.
0x50, 0x32, // ID = 0x5032 (ContentEncodingScope).
0x80, // Size = 0.
0x50, 0x33, // ID = 0x5033 (ContentEncodingType).
0x80, // Size = 0.
0x50, 0x35, // ID = 0x5035 (ContentEncryption).
0x80, // Size = 0.
});
ParseAndVerify();
const ContentEncoding content_encoding = parser_.value();
EXPECT_TRUE(content_encoding.order.is_present());
EXPECT_EQ(0, content_encoding.order.value());
EXPECT_TRUE(content_encoding.scope.is_present());
EXPECT_EQ(1, content_encoding.scope.value());
EXPECT_TRUE(content_encoding.type.is_present());
EXPECT_EQ(ContentEncodingType::kCompression, content_encoding.type.value());
EXPECT_TRUE(content_encoding.encryption.is_present());
EXPECT_EQ(ContentEncryption{}, content_encoding.encryption.value());
}
TEST_F(ContentEncodingParserTest, CustomValues) {
SetReaderData({
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x50, 0x32, // ID = 0x5032 (ContentEncodingScope).
0x81, // Size = 1.
0x02, // Body (value = 2).
0x50, 0x33, // ID = 0x5033 (ContentEncodingType).
0x81, // Size = 1.
0x01, // Body (value = encryption).
0x50, 0x35, // ID = 0x5035 (ContentEncryption).
0x84, // Size = 4.
0x47, 0xE1, // ID = 0x47E1 (ContentEncAlgo).
0x81, // Size = 1.
0x05, // Body (value = AES).
});
ParseAndVerify();
const ContentEncoding content_encoding = parser_.value();
EXPECT_TRUE(content_encoding.order.is_present());
EXPECT_EQ(1, content_encoding.order.value());
EXPECT_TRUE(content_encoding.scope.is_present());
EXPECT_EQ(2, content_encoding.scope.value());
EXPECT_TRUE(content_encoding.type.is_present());
EXPECT_EQ(ContentEncodingType::kEncryption, content_encoding.type.value());
ContentEncryption expected;
expected.algorithm.Set(ContentEncAlgo::kAes, true);
EXPECT_TRUE(content_encoding.encryption.is_present());
EXPECT_EQ(expected, content_encoding.encryption.value());
}
} // namespace

View File

@@ -0,0 +1,82 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/content_encodings_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ContentEncoding;
using webm::ContentEncodings;
using webm::ContentEncodingsParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ContentEncodingsParserTest
: public ElementParserTest<ContentEncodingsParser, Id::kContentEncodings> {
};
TEST_F(ContentEncodingsParserTest, DefaultParse) {
ParseAndVerify();
const ContentEncodings content_encodings = parser_.value();
EXPECT_EQ(0, content_encodings.encodings.size());
}
TEST_F(ContentEncodingsParserTest, DefaultValues) {
SetReaderData({
0x62, 0x40, // ID = 0x6240 (ContentEncoding).
0x80, // Size = 0.
});
ParseAndVerify();
const ContentEncodings content_encodings = parser_.value();
ASSERT_EQ(1, content_encodings.encodings.size());
EXPECT_TRUE(content_encodings.encodings[0].is_present());
EXPECT_EQ(ContentEncoding{}, content_encodings.encodings[0].value());
}
TEST_F(ContentEncodingsParserTest, CustomValues) {
SetReaderData({
0x62, 0x40, // ID = 0x6240 (ContentEncoding).
0x84, // Size = 4.
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x62, 0x40, // ID = 0x6240 (ContentEncoding).
0x84, // Size = 4.
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
const ContentEncodings content_encodings = parser_.value();
ContentEncoding expected;
ASSERT_EQ(2, content_encodings.encodings.size());
expected.order.Set(1, true);
EXPECT_TRUE(content_encodings.encodings[0].is_present());
EXPECT_EQ(expected, content_encodings.encodings[0].value());
expected.order.Set(2, true);
EXPECT_TRUE(content_encodings.encodings[1].is_present());
EXPECT_EQ(expected, content_encodings.encodings[1].value());
}
} // namespace

View File

@@ -0,0 +1,107 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/content_encryption_parser.h"
#include <cstdint>
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::AesSettingsCipherMode;
using webm::ContentEncAesSettings;
using webm::ContentEncAlgo;
using webm::ContentEncryption;
using webm::ContentEncryptionParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ContentEncryptionParserTest
: public ElementParserTest<ContentEncryptionParser,
Id::kContentEncryption> {};
TEST_F(ContentEncryptionParserTest, DefaultParse) {
ParseAndVerify();
const ContentEncryption content_encryption = parser_.value();
EXPECT_FALSE(content_encryption.algorithm.is_present());
EXPECT_EQ(ContentEncAlgo::kOnlySigned, content_encryption.algorithm.value());
EXPECT_FALSE(content_encryption.key_id.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, content_encryption.key_id.value());
EXPECT_FALSE(content_encryption.aes_settings.is_present());
EXPECT_EQ(ContentEncAesSettings{}, content_encryption.aes_settings.value());
}
TEST_F(ContentEncryptionParserTest, DefaultValues) {
SetReaderData({
0x47, 0xE1, // ID = 0x47E1 (ContentEncAlgo).
0x80, // Size = 0.
0x47, 0xE2, // ID = 0x47E2 (ContentEncKeyID).
0x80, // Size = 0.
0x47, 0xE7, // ID = 0x47E7 (ContentEncAESSettings).
0x80, // Size = 0.
});
ParseAndVerify();
const ContentEncryption content_encryption = parser_.value();
EXPECT_TRUE(content_encryption.algorithm.is_present());
EXPECT_EQ(ContentEncAlgo::kOnlySigned, content_encryption.algorithm.value());
EXPECT_TRUE(content_encryption.key_id.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, content_encryption.key_id.value());
EXPECT_TRUE(content_encryption.aes_settings.is_present());
EXPECT_EQ(ContentEncAesSettings{}, content_encryption.aes_settings.value());
}
TEST_F(ContentEncryptionParserTest, CustomValues) {
SetReaderData({
0x47, 0xE1, // ID = 0x47E1 (ContentEncAlgo).
0x81, // Size = 1.
0x05, // Body (value = AES).
0x47, 0xE2, // ID = 0x47E2 (ContentEncKeyID).
0x81, // Size = 1.
0x00, // Body.
0x47, 0xE7, // ID = 0x47E7 (ContentEncAESSettings).
0x84, // Size = 4.
0x47, 0xE8, // ID = 0x47E8 (AESSettingsCipherMode).
0x81, // Size = 1.
0x00, // Body (value = 0).
});
ParseAndVerify();
const ContentEncryption content_encryption = parser_.value();
EXPECT_TRUE(content_encryption.algorithm.is_present());
EXPECT_EQ(ContentEncAlgo::kAes, content_encryption.algorithm.value());
EXPECT_TRUE(content_encryption.key_id.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{0x00}, content_encryption.key_id.value());
ContentEncAesSettings expected;
expected.aes_settings_cipher_mode.Set(static_cast<AesSettingsCipherMode>(0),
true);
EXPECT_TRUE(content_encryption.aes_settings.is_present());
EXPECT_EQ(expected, content_encryption.aes_settings.value());
}
} // namespace

View File

@@ -0,0 +1,87 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/cue_point_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::CuePoint;
using webm::CuePointParser;
using webm::CueTrackPositions;
using webm::ElementParserTest;
using webm::Id;
namespace {
class CuePointParserTest
: public ElementParserTest<CuePointParser, Id::kCuePoint> {};
TEST_F(CuePointParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnCuePoint(metadata_, CuePoint{})).Times(1);
ParseAndVerify();
}
TEST_F(CuePointParserTest, DefaultValues) {
SetReaderData({
0xB3, // ID = 0xB3 (CueTime).
0x80, // Size = 0.
0xB7, // ID = 0xB7 (CueTrackPositions).
0x80, // Size = 0.
});
CuePoint cue_point;
cue_point.time.Set(0, true);
cue_point.cue_track_positions.emplace_back();
cue_point.cue_track_positions[0].Set({}, true);
EXPECT_CALL(callback_, OnCuePoint(metadata_, cue_point)).Times(1);
ParseAndVerify();
}
TEST_F(CuePointParserTest, CustomValues) {
SetReaderData({
0xB3, // ID = 0xB3 (CueTime).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xB7, // ID = 0xB7 (CueTrackPositions).
0x83, // Size = 3.
0xF1, // ID = 0xF1 (CueClusterPosition).
0x81, // Size = 1.
0x02, // Body (value = 2).
0xB7, // ID = 0xB7 (CueTrackPositions).
0x83, // Size = 3.
0xF7, // ID = 0xF7 (CueTrack).
0x81, // Size = 1.
0x03, // Body (value = 3).
});
CuePoint cue_point;
cue_point.time.Set(1, true);
CueTrackPositions cue_track_positions;
cue_track_positions.cluster_position.Set(2, true);
cue_point.cue_track_positions.emplace_back(cue_track_positions, true);
cue_track_positions = {};
cue_track_positions.track.Set(3, true);
cue_point.cue_track_positions.emplace_back(cue_track_positions, true);
EXPECT_CALL(callback_, OnCuePoint(metadata_, cue_point)).Times(1);
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,128 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/cue_track_positions_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::CueTrackPositions;
using webm::CueTrackPositionsParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class CueTrackPositionsParserTest
: public ElementParserTest<CueTrackPositionsParser,
Id::kCueTrackPositions> {};
TEST_F(CueTrackPositionsParserTest, DefaultParse) {
ParseAndVerify();
const CueTrackPositions cue_track_positions = parser_.value();
EXPECT_FALSE(cue_track_positions.track.is_present());
EXPECT_EQ(0, cue_track_positions.track.value());
EXPECT_FALSE(cue_track_positions.cluster_position.is_present());
EXPECT_EQ(0, cue_track_positions.cluster_position.value());
EXPECT_FALSE(cue_track_positions.relative_position.is_present());
EXPECT_EQ(0, cue_track_positions.relative_position.value());
EXPECT_FALSE(cue_track_positions.duration.is_present());
EXPECT_EQ(0, cue_track_positions.duration.value());
EXPECT_FALSE(cue_track_positions.block_number.is_present());
EXPECT_EQ(1, cue_track_positions.block_number.value());
}
TEST_F(CueTrackPositionsParserTest, DefaultValues) {
SetReaderData({
0xF7, // ID = 0xF7 (CueTrack).
0x40, 0x00, // Size = 0.
0xF1, // ID = 0xF1 (CueClusterPosition).
0x40, 0x00, // Size = 0.
0xF0, // ID = 0xF0 (CueRelativePosition).
0x40, 0x00, // Size = 0.
0xB2, // ID = 0xB2 (CueDuration).
0x40, 0x00, // Size = 0.
0x53, 0x78, // ID = 0x5378 (CueBlockNumber).
0x80, // Size = 0.
});
ParseAndVerify();
const CueTrackPositions cue_track_positions = parser_.value();
EXPECT_TRUE(cue_track_positions.track.is_present());
EXPECT_EQ(0, cue_track_positions.track.value());
EXPECT_TRUE(cue_track_positions.cluster_position.is_present());
EXPECT_EQ(0, cue_track_positions.cluster_position.value());
EXPECT_TRUE(cue_track_positions.relative_position.is_present());
EXPECT_EQ(0, cue_track_positions.relative_position.value());
EXPECT_TRUE(cue_track_positions.duration.is_present());
EXPECT_EQ(0, cue_track_positions.duration.value());
EXPECT_TRUE(cue_track_positions.block_number.is_present());
EXPECT_EQ(1, cue_track_positions.block_number.value());
}
TEST_F(CueTrackPositionsParserTest, CustomValues) {
SetReaderData({
0xF7, // ID = 0xF7 (CueTrack).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xF1, // ID = 0xF1 (CueClusterPosition).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0xF0, // ID = 0xF0 (CueRelativePosition).
0x40, 0x01, // Size = 1.
0x03, // Body (value = 3).
0xB2, // ID = 0xB2 (CueDuration).
0x40, 0x01, // Size = 1.
0x04, // Body (value = 4).
0x53, 0x78, // ID = 0x5378 (CueBlockNumber).
0x81, // Size = 1.
0x05, // Body (value = 5).
});
ParseAndVerify();
const CueTrackPositions cue_track_positions = parser_.value();
EXPECT_TRUE(cue_track_positions.track.is_present());
EXPECT_EQ(1, cue_track_positions.track.value());
EXPECT_TRUE(cue_track_positions.cluster_position.is_present());
EXPECT_EQ(2, cue_track_positions.cluster_position.value());
EXPECT_TRUE(cue_track_positions.relative_position.is_present());
EXPECT_EQ(3, cue_track_positions.relative_position.value());
EXPECT_TRUE(cue_track_positions.duration.is_present());
EXPECT_EQ(4, cue_track_positions.duration.value());
EXPECT_TRUE(cue_track_positions.block_number.is_present());
EXPECT_EQ(5, cue_track_positions.block_number.value());
}
} // namespace

View File

@@ -0,0 +1,53 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/cues_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::CuesParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class CuesParserTest : public ElementParserTest<CuesParser, Id::kCues> {};
TEST_F(CuesParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0xBB, // ID = 0xBB (CuePoint).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(CuesParserTest, RepeatedValues) {
SetReaderData({
0xBB, // ID = 0xBB (CuePoint).
0x83, // Size = 3.
0xB3, // ID = 0xB3 (CueTime).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xBB, // ID = 0xBB (CuePoint).
0x83, // Size = 3.
0xB3, // ID = 0xB3 (CueTime).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/date_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::DateParser;
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::Status;
namespace {
class DateParserTest : public ElementParserTest<DateParser> {};
TEST_F(DateParserTest, InvalidSize) {
TestInit(4, Status::kInvalidElementSize);
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(DateParserTest, CustomDefault) {
ResetParser(-1);
ParseAndVerify();
EXPECT_EQ(-1, parser_.value());
}
TEST_F(DateParserTest, ValidDate) {
ParseAndVerify();
EXPECT_EQ(0, parser_.value());
SetReaderData({0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0});
ParseAndVerify();
EXPECT_EQ(0x123456789ABCDEF0, parser_.value());
}
TEST_F(DateParserTest, IncrementalParse) {
SetReaderData({0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10});
IncrementalParseAndVerify();
EXPECT_EQ(0xFEDCBA9876543210, parser_.value());
}
} // namespace

View File

@@ -0,0 +1,128 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/ebml_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::Ebml;
using webm::EbmlParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class EbmlParserTest : public ElementParserTest<EbmlParser, Id::kEbml> {};
TEST_F(EbmlParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnEbml(metadata_, Ebml{})).Times(1);
ParseAndVerify();
}
TEST_F(EbmlParserTest, DefaultValues) {
SetReaderData({
0x42, 0x86, // ID = 0x4286 (EBMLVersion).
0x80, // Size = 0.
0x42, 0xF7, // ID = 0x42F7 (EBMLReadVersion).
0x80, // Size = 0.
0x42, 0xF2, // ID = 0x42F2 (EBMLMaxIDLength).
0x40, 0x00, // Size = 0.
0x42, 0xF3, // ID = 0x42F3 (EBMLMaxSizeLength).
0x80, // Size = 0.
0xEC, // ID = 0xEC (Void).
0x40, 0x00, // Size = 0.
0x42, 0x82, // ID = 0x4282 (DocType).
0x40, 0x00, // Size = 0.
0x42, 0x87, // ID = 0x4287 (DocTypeVersion).
0x80, // Size = 0.
0x42, 0x85, // ID = 0x4285 (DocTypeReadVersion).
0x80, // Size = 0.
0xEC, // ID = 0xEC (Void).
0x82, // Size = 2.
0x01, 0x02, // Body.
});
Ebml ebml;
ebml.ebml_version.Set(1, true);
ebml.ebml_read_version.Set(1, true);
ebml.ebml_max_id_length.Set(4, true);
ebml.ebml_max_size_length.Set(8, true);
ebml.doc_type.Set("matroska", true);
ebml.doc_type_version.Set(1, true);
ebml.doc_type_read_version.Set(1, true);
EXPECT_CALL(callback_, OnEbml(metadata_, ebml)).Times(1);
ParseAndVerify();
}
TEST_F(EbmlParserTest, CustomValues) {
SetReaderData({
0x42, 0x86, // ID = 0x4286 (EBMLVersion).
0x81, // Size = 1.
0x02, // Body (value = 2).
0x42, 0xF7, // ID = 0x42F7 (EBMLReadVersion).
0x81, // Size = 1.
0x04, // Body (value = 4).
0x42, 0xF2, // ID = 0x42F2 (EBMLMaxIDLength).
0x40, 0x02, // Size = 2.
0x00, 0x02, // Body (value = 2).
0x42, 0xF3, // ID = 0x42F3 (EBMLMaxSizeLength).
0x81, // Size = 1.
0x04, // Body (value = 4).
0xEC, // ID = 0xEC (Void).
0x40, 0x00, // Size = 0.
0x42, 0x82, // ID = 0x4282 (DocType).
0x40, 0x02, // Size = 2.
0x48, 0x69, // Body (value = "Hi").
0x42, 0x87, // ID = 0x4287 (DocTypeVersion).
0x81, // Size = 1.
0xFF, // Body (value = 255).
0x42, 0x85, // ID = 0x4285 (DocTypeReadVersion).
0x81, // Size = 1.
0x02, // Body (value = 2).
0xEC, // ID = 0xEC (Void).
0x82, // Size = 2.
0x01, 0x02, // Body.
});
Ebml ebml;
ebml.ebml_version.Set(2, true);
ebml.ebml_read_version.Set(4, true);
ebml.ebml_max_id_length.Set(2, true);
ebml.ebml_max_size_length.Set(4, true);
ebml.doc_type.Set("Hi", true);
ebml.doc_type_version.Set(255, true);
ebml.doc_type_read_version.Set(2, true);
EXPECT_CALL(callback_, OnEbml(metadata_, ebml)).Times(1);
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,77 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/edition_entry_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ChapterAtom;
using webm::EditionEntry;
using webm::EditionEntryParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class EditionEntryParserTest
: public ElementParserTest<EditionEntryParser, Id::kEditionEntry> {};
TEST_F(EditionEntryParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnEditionEntry(metadata_, EditionEntry{})).Times(1);
ParseAndVerify();
}
TEST_F(EditionEntryParserTest, DefaultValues) {
SetReaderData({
0xB6, // ID = 0xB6 (ChapterAtom).
0x80, // Size = 0.
});
EditionEntry edition_entry;
edition_entry.atoms.emplace_back();
edition_entry.atoms[0].Set({}, true);
EXPECT_CALL(callback_, OnEditionEntry(metadata_, edition_entry)).Times(1);
ParseAndVerify();
}
TEST_F(EditionEntryParserTest, CustomValues) {
SetReaderData({
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x04, // Size = 4.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x04, // Size = 4.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
EditionEntry edition_entry;
ChapterAtom chapter_atom;
chapter_atom.uid.Set(1, true);
edition_entry.atoms.emplace_back(chapter_atom, true);
chapter_atom.uid.Set(2, true);
edition_entry.atoms.emplace_back(chapter_atom, true);
EXPECT_CALL(callback_, OnEditionEntry(metadata_, edition_entry)).Times(1);
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,47 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/element.h"
#include <string>
#include <utility>
#include "gtest/gtest.h"
using webm::Element;
namespace {
class ElementTest : public testing::Test {};
TEST_F(ElementTest, Construction) {
Element<int> value_initialized;
EXPECT_EQ(false, value_initialized.is_present());
EXPECT_EQ(0, value_initialized.value());
Element<int> absent_custom_default(1);
EXPECT_EQ(false, absent_custom_default.is_present());
EXPECT_EQ(1, absent_custom_default.value());
Element<int> present(2, true);
EXPECT_EQ(true, present.is_present());
EXPECT_EQ(2, present.value());
}
TEST_F(ElementTest, Assignment) {
Element<int> e;
e.Set(42, true);
EXPECT_EQ(true, e.is_present());
EXPECT_EQ(42, e.value());
*e.mutable_value() = 0;
EXPECT_EQ(true, e.is_present());
EXPECT_EQ(0, e.value());
}
} // namespace

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/float_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::FloatParser;
using webm::kUnknownElementSize;
using webm::Status;
namespace {
class FloatParserTest : public ElementParserTest<FloatParser> {};
TEST_F(FloatParserTest, InvalidSize) {
TestInit(1, Status::kInvalidElementSize);
TestInit(5, Status::kInvalidElementSize);
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(FloatParserTest, CustomDefault) {
const double sqrt2 = 1.4142135623730951454746218587388284504413604736328125;
ResetParser(sqrt2);
ParseAndVerify();
EXPECT_EQ(sqrt2, parser_.value());
}
TEST_F(FloatParserTest, ValidFloat) {
ParseAndVerify();
EXPECT_EQ(0, parser_.value());
SetReaderData({0x40, 0xC9, 0x0F, 0xDB});
ParseAndVerify();
EXPECT_EQ(6.283185482025146484375, parser_.value());
SetReaderData({0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69});
ParseAndVerify();
EXPECT_EQ(2.718281828459045090795598298427648842334747314453125,
parser_.value());
}
TEST_F(FloatParserTest, IncrementalParse) {
SetReaderData({0x3F, 0xF9, 0xE3, 0x77, 0x9B, 0x97, 0xF4, 0xA8});
IncrementalParseAndVerify();
EXPECT_EQ(1.6180339887498949025257388711906969547271728515625,
parser_.value());
}
} // namespace

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/id_element_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::Id;
using webm::IdElementParser;
using webm::kUnknownElementSize;
using webm::Status;
namespace {
class IdElementParserTest : public ElementParserTest<IdElementParser> {};
TEST_F(IdElementParserTest, InvalidSize) {
TestInit(0, Status::kInvalidElementSize);
TestInit(5, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(IdElementParserTest, ValidId) {
SetReaderData({0xEC});
ParseAndVerify();
EXPECT_EQ(Id::kVoid, parser_.value());
SetReaderData({0x1F, 0x43, 0xB6, 0x75});
ParseAndVerify();
EXPECT_EQ(Id::kCluster, parser_.value());
}
TEST_F(IdElementParserTest, IncrementalParse) {
SetReaderData({0x2A, 0xD7, 0xB1});
IncrementalParseAndVerify();
EXPECT_EQ(Id::kTimecodeScale, parser_.value());
}
} // namespace

View File

@@ -0,0 +1,56 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/id_parser.h"
#include "gtest/gtest.h"
#include "test_utils/parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using webm::Id;
using webm::IdParser;
using webm::ParserTest;
using webm::Status;
namespace {
class IdParserTest : public ParserTest<IdParser> {};
TEST_F(IdParserTest, InvalidId) {
SetReaderData({0x00});
ParseAndExpectResult(Status::kInvalidElementId);
ResetParser();
SetReaderData({0x0F});
ParseAndExpectResult(Status::kInvalidElementId);
}
TEST_F(IdParserTest, EarlyEndOfFile) {
SetReaderData({0x40});
ParseAndExpectResult(Status::kEndOfFile);
}
TEST_F(IdParserTest, ValidId) {
SetReaderData({0x80});
ParseAndVerify();
EXPECT_EQ(static_cast<Id>(0x80), parser_.id());
ResetParser();
SetReaderData({0x1F, 0xFF, 0xFF, 0xFF});
ParseAndVerify();
EXPECT_EQ(static_cast<Id>(0x1FFFFFFF), parser_.id());
}
TEST_F(IdParserTest, IncrementalParse) {
SetReaderData({0x1A, 0x45, 0xDF, 0xA3});
IncrementalParseAndVerify();
EXPECT_EQ(Id::kEbml, parser_.id());
}
} // namespace

View File

@@ -0,0 +1,105 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/info_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Info;
using webm::InfoParser;
namespace {
class InfoParserTest : public ElementParserTest<InfoParser, Id::kInfo> {};
TEST_F(InfoParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnInfo(metadata_, Info{})).Times(1);
ParseAndVerify();
}
TEST_F(InfoParserTest, DefaultValues) {
SetReaderData({
0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
0x80, // Size = 0.
0x44, 0x89, // ID = 0x4489 (Duration).
0x20, 0x00, 0x00, // Size = 0.
0x44, 0x61, // ID = 0x4461 (DateUTC).
0x20, 0x00, 0x00, // Size = 0.
0x7B, 0xA9, // ID = 0x7BA9 (Title).
0x20, 0x00, 0x00, // Size = 0.
0x4D, 0x80, // ID = 0x4D80 (MuxingApp).
0x20, 0x00, 0x00, // Size = 0.
0x57, 0x41, // ID = 0x5741 (WritingApp).
0x20, 0x00, 0x00, // Size = 0.
});
Info info;
info.timecode_scale.Set(1000000, true);
info.duration.Set(0, true);
info.date_utc.Set(0, true);
info.title.Set("", true);
info.muxing_app.Set("", true);
info.writing_app.Set("", true);
EXPECT_CALL(callback_, OnInfo(metadata_, info)).Times(1);
ParseAndVerify();
}
TEST_F(InfoParserTest, CustomValues) {
SetReaderData({
0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x44, 0x89, // ID = 0x4489 (Duration).
0x84, // Size = 4.
0x4D, 0x8E, 0xF3, 0xC2, // Body (value = 299792448.0f).
0x44, 0x61, // ID = 0x4461 (DateUTC).
0x88, // Size = 8.
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Body (value = -1).
0x7B, 0xA9, // ID = 0x7BA9 (Title).
0x10, 0x00, 0x00, 0x03, // Size = 3.
0x66, 0x6F, 0x6F, // Body (value = "foo").
0x4D, 0x80, // ID = 0x4D80 (MuxingApp).
0x10, 0x00, 0x00, 0x03, // Size = 3.
0x62, 0x61, 0x72, // Body (value = "bar").
0x57, 0x41, // ID = 0x5741 (WritingApp).
0x10, 0x00, 0x00, 0x03, // Size = 3.
0x62, 0x61, 0x7A, // Body (value = "baz").
});
Info info;
info.timecode_scale.Set(1, true);
info.duration.Set(299792448.0f, true);
info.date_utc.Set(-1, true);
info.title.Set("foo", true);
info.muxing_app.Set("bar", true);
info.writing_app.Set("baz", true);
EXPECT_CALL(callback_, OnInfo(metadata_, info)).Times(1);
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,113 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/int_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::SignedIntParser;
using webm::Status;
using webm::UnsignedIntParser;
namespace {
class UnsignedIntParserTest : public ElementParserTest<UnsignedIntParser> {};
TEST_F(UnsignedIntParserTest, UnsignedInvalidSize) {
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(UnsignedIntParserTest, UnsignedCustomDefault) {
ResetParser(1);
ParseAndVerify();
EXPECT_EQ(1, parser_.value());
}
TEST_F(UnsignedIntParserTest, UnsignedValidInt) {
ParseAndVerify();
EXPECT_EQ(0, parser_.value());
SetReaderData({0x01, 0x02, 0x03});
ParseAndVerify();
EXPECT_EQ(0x010203, parser_.value());
SetReaderData({0xFF, 0xFF, 0xFF, 0xFF, 0xFF});
ParseAndVerify();
EXPECT_EQ(0xFFFFFFFFFF, parser_.value());
SetReaderData({0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0});
ParseAndVerify();
EXPECT_EQ(0x123456789ABCDEF0, parser_.value());
}
TEST_F(UnsignedIntParserTest, UnsignedIncrementalParse) {
SetReaderData({0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10});
IncrementalParseAndVerify();
EXPECT_EQ(0xFEDCBA9876543210, parser_.value());
}
class SignedIntParserTest : public ElementParserTest<SignedIntParser> {};
TEST_F(SignedIntParserTest, SignedInvalidSize) {
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(SignedIntParserTest, SignedCustomDefault) {
ResetParser(-1);
ParseAndVerify();
EXPECT_EQ(-1, parser_.value());
}
TEST_F(SignedIntParserTest, SignedValidPositiveInt) {
ParseAndVerify();
EXPECT_EQ(0, parser_.value());
SetReaderData({0x7f});
ParseAndVerify();
EXPECT_EQ(0x7f, parser_.value());
SetReaderData({0x12, 0xD6, 0x87});
ParseAndVerify();
EXPECT_EQ(1234567, parser_.value());
SetReaderData({0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0});
ParseAndVerify();
EXPECT_EQ(0x123456789ABCDEF0, parser_.value());
}
TEST_F(SignedIntParserTest, SignedValidNegativeInt) {
SetReaderData({0xFF});
ParseAndVerify();
EXPECT_EQ(-1, parser_.value());
SetReaderData({0xF8, 0xA4, 0x32, 0xEB});
ParseAndVerify();
EXPECT_EQ(-123456789, parser_.value());
}
TEST_F(SignedIntParserTest, SignedIncrementalParse) {
SetReaderData({0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11});
IncrementalParseAndVerify();
EXPECT_EQ(-81985529216486895, parser_.value());
}
} // namespace

View File

@@ -0,0 +1,131 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/istream_reader.h"
#include <algorithm>
#include <array>
#include <cstdint>
#include <sstream>
#include <type_traits>
#include "gtest/gtest.h"
using webm::IstreamReader;
using webm::Status;
namespace {
// Creates a std::array from a string literal (and omits the trailing
// NUL-character).
template <std::size_t N>
std::array<std::uint8_t, N - 1> ArrayFromString(const char (&string)[N]) {
std::array<std::uint8_t, N - 1> array;
std::copy_n(string, N - 1, array.begin());
return array;
}
class IstreamReaderTest : public testing::Test {};
TEST_F(IstreamReaderTest, Read) {
std::array<std::uint8_t, 15> buffer{};
std::uint64_t count;
Status status;
IstreamReader reader =
IstreamReader::Emplace<std::istringstream>("abcdefghij");
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(5, count);
status = reader.Read(10, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(5, count);
std::array<std::uint8_t, 15> expected =
ArrayFromString("abcdefghij\0\0\0\0\0");
EXPECT_EQ(expected, buffer);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0, count);
}
TEST_F(IstreamReaderTest, Skip) {
std::uint64_t count;
Status status;
IstreamReader reader =
IstreamReader::Emplace<std::istringstream>("abcdefghij");
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(3, count);
status = reader.Skip(10, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(7, count);
status = reader.Skip(1, &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0, count);
}
TEST_F(IstreamReaderTest, ReadAndSkip) {
std::array<std::uint8_t, 10> buffer = {};
std::uint64_t count;
Status status;
IstreamReader reader =
IstreamReader::Emplace<std::istringstream>("AaBbCcDdEe");
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(5, count);
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(3, count);
status = reader.Read(5, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(2, count);
std::array<std::uint8_t, 10> expected = ArrayFromString("AaBbCEe\0\0\0");
EXPECT_EQ(expected, buffer);
}
TEST_F(IstreamReaderTest, Position) {
std::array<std::uint8_t, 10> buffer = {};
std::uint64_t count;
Status status;
IstreamReader reader =
IstreamReader::Emplace<std::istringstream>("AaBbCcDdEe");
EXPECT_EQ(0, reader.Position());
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(5, count);
EXPECT_EQ(5, reader.Position());
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(3, count);
EXPECT_EQ(8, reader.Position());
status = reader.Read(5, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(2, count);
EXPECT_EQ(10, reader.Position());
std::array<std::uint8_t, 10> expected = ArrayFromString("AaBbCEe\0\0\0");
EXPECT_EQ(expected, buffer);
}
} // namespace

View File

@@ -0,0 +1,249 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "test_utils/limited_reader.h"
#include <array>
#include <cstdint>
#include <memory>
#include "gtest/gtest.h"
#include "webm/buffer_reader.h"
#include "webm/reader.h"
#include "webm/status.h"
using webm::BufferReader;
using webm::LimitedReader;
using webm::Reader;
using webm::Status;
namespace {
class LimitedReaderTest : public testing::Test {};
TEST_F(LimitedReaderTest, UnlimitedRead) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(4, count);
std::array<std::uint8_t, 4> expected_buffer = {{1, 2, 3, 4}};
EXPECT_EQ(expected_buffer, buffer);
}
TEST_F(LimitedReaderTest, UnlimitedSkip) {
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
status = reader.Skip(4, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(4, count);
}
TEST_F(LimitedReaderTest, Position) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
EXPECT_EQ(0, reader.Position());
status = reader.Read(2, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(2, count);
status = reader.Skip(2, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(2, count);
EXPECT_EQ(4, reader.Position());
std::array<std::uint8_t, 4> expected_buffer = {{1, 2, 0, 0}};
EXPECT_EQ(expected_buffer, buffer);
}
TEST_F(LimitedReaderTest, LimitIndividualRead) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_single_read_limit(1);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(1, count);
status = reader.Read(buffer.size() + 1, buffer.data() + 1, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(1, count);
reader.set_single_read_limit(2);
status = reader.Read(buffer.size() - 2, buffer.data() + 2, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(2, count);
std::array<std::uint8_t, 4> expected_buffer = {{1, 2, 3, 4}};
EXPECT_EQ(expected_buffer, buffer);
}
TEST_F(LimitedReaderTest, LimitIndividualSkip) {
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_single_skip_limit(1);
status = reader.Skip(4, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(1, count);
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(1, count);
reader.set_single_skip_limit(2);
status = reader.Skip(2, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(2, count);
}
TEST_F(LimitedReaderTest, LimitRepeatedRead) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_total_read_limit(1);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(1, count);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(0, count);
reader.set_total_read_limit(2);
status = reader.Read(buffer.size() - 1, buffer.data() + 1, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(2, count);
reader.set_total_read_limit(1);
status = reader.Read(buffer.size() - 3, buffer.data() + 3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(1, count);
std::array<std::uint8_t, 4> expected_buffer = {{1, 2, 3, 4}};
EXPECT_EQ(expected_buffer, buffer);
}
TEST_F(LimitedReaderTest, LimitRepeatedSkip) {
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_total_skip_limit(1);
status = reader.Skip(4, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(1, count);
status = reader.Skip(4, &count);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(0, count);
reader.set_total_skip_limit(2);
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(2, count);
reader.set_total_skip_limit(1);
status = reader.Skip(1, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(1, count);
}
TEST_F(LimitedReaderTest, LimitReadsAndSkips) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_total_read_skip_limit(1);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(1, count);
status = reader.Skip(buffer.size(), &count);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(0, count);
reader.set_total_read_skip_limit(2);
status = reader.Skip(buffer.size() - 1, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(2, count);
reader.set_total_read_skip_limit(1);
status = reader.Read(buffer.size() - 3, buffer.data() + 3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(1, count);
std::array<std::uint8_t, 4> expected = {{1, 0, 0, 4}};
EXPECT_EQ(expected, buffer);
}
TEST_F(LimitedReaderTest, CustomStatusWhenBlocked) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
Status expected_status = Status(-123);
reader.set_single_read_limit(0);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(0, count);
reader.set_return_status_when_blocked(expected_status);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(0, count);
reader.set_single_read_limit(std::numeric_limits<std::size_t>::max());
reader.set_total_read_limit(0);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(0, count);
reader.set_total_read_limit(std::numeric_limits<std::size_t>::max());
reader.set_single_skip_limit(0);
status = reader.Skip(buffer.size(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(0, count);
reader.set_single_skip_limit(std::numeric_limits<std::uint64_t>::max());
reader.set_total_skip_limit(0);
status = reader.Skip(buffer.size(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(0, count);
reader.set_total_skip_limit(std::numeric_limits<std::uint64_t>::max());
reader.set_total_read_skip_limit(0);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(0, count);
status = reader.Skip(buffer.size(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(0, count);
std::array<std::uint8_t, 4> expected_buffer = {{0, 0, 0, 0}};
EXPECT_EQ(expected_buffer, buffer);
}
} // namespace

View File

@@ -0,0 +1,361 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/master_parser.h"
#include <cstdint>
#include <memory>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/byte_parser.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::BinaryParser;
using webm::ElementMetadata;
using webm::ElementParser;
using webm::ElementParserTest;
using webm::Id;
using webm::kUnknownElementSize;
using webm::LimitedReader;
using webm::MasterParser;
using webm::Status;
namespace {
// Simple helper method that just takes an Id and ElementParser* and returns
// them in a std::pair<Id, std::unique_ptr<ElementParser>>. Provided just for
// simplifying some statements.
std::pair<Id, std::unique_ptr<ElementParser>> ParserForId(
Id id, ElementParser* parser) {
return {id, std::unique_ptr<ElementParser>(parser)};
}
class MasterParserTest : public ElementParserTest<MasterParser> {};
// Errors parsing an ID should be returned to the caller.
TEST_F(MasterParserTest, BadId) {
SetReaderData({
0x00, // Invalid ID.
0x80, // ID = 0x80 (unknown).
0x80, // Size = 0.
});
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
ParseAndExpectResult(Status::kInvalidElementId);
}
// Errors from a child parser's Init should be returned to the caller.
TEST_F(MasterParserTest, ChildInitFails) {
SetReaderData({
0xEC, // ID = 0xEC (Void).
0xFF, // Size = unknown.
});
const ElementMetadata metadata = {Id::kVoid, 2, kUnknownElementSize, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
ParseAndExpectResult(Status::kInvalidElementSize);
}
// Indefinite unknown children should result in an error.
TEST_F(MasterParserTest, IndefiniteUnknownChild) {
SetReaderData({
0x80, // ID = 0x80 (unknown).
0xFF, // Size = unknown.
0x00, 0x00, // Body.
});
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
ParseAndExpectResult(Status::kIndefiniteUnknownElement);
}
// Child elements that overflow the master element's size should be detected.
TEST_F(MasterParserTest, ChildOverflow) {
SetReaderData({
0xEC, // ID = 0xEC (Void).
0x82, // Size = 2.
0x00, 0x00, // Body.
});
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
EXPECT_CALL(callback_, OnVoid(_, _, _)).Times(0);
ParseAndExpectResult(Status::kElementOverflow, reader_.size() - 1);
}
// Child elements with an unknown size can't be naively checked to see if they
// overflow the master element's size. Make sure the overflow is still detected.
TEST_F(MasterParserTest, ChildOverflowWithUnknownSize) {
SetReaderData({
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x12, // Body.
});
{
InSequence dummy;
ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
}
ResetParser(ParserForId(Id::kBlock, new MasterParser));
ParseAndExpectResult(Status::kElementOverflow, 4);
}
// An element with an unknown size should be terminated by its parents bounds.
TEST_F(MasterParserTest, ChildWithUnknownSizeBoundedByParentSize) {
SetReaderData({
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x12, // Body.
0x00, // Invalid ID. This should not be read.
});
{
InSequence dummy;
ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kVoid, 2, 1, 2};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ResetParser(ParserForId(Id::kBlock, new MasterParser));
ParseAndVerify(reader_.size() - 1);
}
// An empty master element is okay.
TEST_F(MasterParserTest, Empty) {
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
ParseAndVerify();
}
// Unrecognized children should be skipped over.
TEST_F(MasterParserTest, UnknownChildren) {
SetReaderData({
0x40, 0x00, // ID = 0x4000 (unknown).
0x80, // Size = 0.
0x80, // ID = 0x80 (unknown).
0x40, 0x00, // Size = 0.
});
EXPECT_CALL(callback_, OnVoid(_, _, _)).Times(0);
{
InSequence dummy;
ElementMetadata metadata = {static_cast<Id>(0x4000), 3, 0, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {static_cast<Id>(0x80), 3, 0, 3};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
}
ParseAndVerify();
}
// A master element with unknown size is terminated by the first element that is
// not a valid child.
TEST_F(MasterParserTest, UnknownSize) {
SetReaderData({
// Void elements may appear anywhere in a master element and should not
// terminate the parse for a master element with an unknown size. In other
// words, they're always valid children.
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
// This element marks the end for the parser since this is the first
// unrecognized element. The ID and size should be read (which the parser
// uses to determine the end has been reached), but nothing more.
0x80, // ID = 0x80 (unknown).
0x81, // Size = 1.
0x12, // Body.
});
{
InSequence dummy;
const ElementMetadata metadata = {Id::kVoid, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ParseAndVerify(kUnknownElementSize);
EXPECT_EQ(5, reader_.Position());
}
// Consecutive elements with unknown size should parse without issues, despite
// the internal parsers having to read ahead into the next (non-child) element.
TEST_F(MasterParserTest, MultipleUnknownChildSize) {
SetReaderData({
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x12, // Body.
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x13, // Body.
});
{
InSequence dummy;
ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kVoid, 2, 1, 2};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
metadata = {Id::kBlock, 2, kUnknownElementSize, 5};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kVoid, 2, 1, 7};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ResetParser(ParserForId(Id::kBlock, new MasterParser));
ParseAndVerify();
}
// Reaching the end of the file while reading an element with unknown size
// should return Status::kOkCompleted instead of Status::kEndOfFile.
TEST_F(MasterParserTest, UnknownSizeToFileEnd) {
SetReaderData({
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
});
{
InSequence dummy;
const ElementMetadata metadata = {Id::kVoid, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ParseAndVerify();
}
// Parsing one byte at a time is okay.
TEST_F(MasterParserTest, IncrementalParse) {
SetReaderData({
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x08, 0x00, 0x00, 0x00, 0x06, // Size = 6.
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Body.
});
const ElementMetadata metadata = {Id::kEbml, 9, 6, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
BinaryParser* binary_parser = new BinaryParser;
ResetParser(ParserForId(Id::kEbml, binary_parser));
IncrementalParseAndVerify();
std::vector<std::uint8_t> expected = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
EXPECT_EQ(expected, binary_parser->value());
}
// Alternating actions between skip and read is okay. The parser should remember
// the requested action between repeated calls to Feed.
TEST_F(MasterParserTest, IncrementalSkipThenReadThenSkip) {
SetReaderData({
0xA1, // ID = 0xA1 (Block) (master).
0x83, // Size = 3.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x12, // Body.
0xA1, // ID = 0xA1 (Block) (master).
0x83, // Size = 3.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x13, // Body.
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x14, // Body.
});
{
InSequence dummy;
ElementMetadata metadata = {Id::kBlock, 2, 3, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
metadata = {Id::kBlock, 2, 3, 5};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kVoid, 2, 1, 7};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
// Expect to get called twice because we'll cap the LimitedReader to 1-byte
// reads. The first attempt to read will fail because we'll have already
// reached the 1-byte max.
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(2);
metadata = {Id::kBlock, 2, kUnknownElementSize, 10};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
}
ResetParser(ParserForId(Id::kBlock, new MasterParser));
IncrementalParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,366 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/master_value_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/int_parser.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::Callback;
using webm::Cluster;
using webm::ElementMetadata;
using webm::ElementParserTest;
using webm::Id;
using webm::MasterValueParser;
using webm::Status;
using webm::UnsignedIntParser;
namespace {
// An instance of MasterValueParser that can actually be used in the tests to
// parse Cluster structures.
class FakeClusterParser : public MasterValueParser<Cluster> {
public:
FakeClusterParser()
: MasterValueParser(
MakeChild<UnsignedIntParser>(Id::kTimecode, &Cluster::timecode),
MakeChild<UnsignedIntParser>(Id::kPrevSize, &Cluster::previous_size)
.UseAsStartEvent()) {}
protected:
Status OnParseStarted(Callback* callback, Action* action) override {
return callback->OnClusterBegin(metadata(Id::kCluster), value(), action);
}
Status OnParseCompleted(Callback* callback) override {
return callback->OnClusterEnd(metadata(Id::kCluster), value());
}
};
class MasterValueParserTest
: public ElementParserTest<FakeClusterParser, Id::kCluster> {};
TEST_F(MasterValueParserTest, InvalidId) {
SetReaderData({
0x00, // Invalid ID.
});
ParseAndExpectResult(Status::kInvalidElementId);
}
TEST_F(MasterValueParserTest, InvalidSize) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0xFF, // Size = unknown.
});
ParseAndExpectResult(Status::kInvalidElementSize);
}
TEST_F(MasterValueParserTest, DefaultParse) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnClusterBegin(metadata_, Cluster{}, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, Cluster{})).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, DefaultValues) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x80, // Size = 0.
0xAB, // ID = 0xAB (PrevSize).
0x80, // Size = 0.
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(0, true);
ElementMetadata child_metadata = {Id::kTimecode, 2, 0, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
child_metadata = {Id::kPrevSize, 2, 0, 2};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
cluster.previous_size.Set(0, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, CustomValues) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x82, // Size = 2.
0x04, 0x00, // Body (value = 1024).
0xAB, // ID = 0xAB (PrevSize).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(1024, true);
ElementMetadata child_metadata = {Id::kTimecode, 2, 2, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
child_metadata = {Id::kPrevSize, 3, 1, 4};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
cluster.previous_size.Set(1, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, IncrementalParse) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x40, 0x02, // Size = 2.
0x04, 0x00, // Body (value = 1024).
0x40, 0x00, // ID = 0x4000 (Unknown).
0x40, 0x02, // Size = 2.
0x00, 0x00, // Body.
0xAB, // ID = 0xAB (PrevSize).
0x40, 0x02, // Size = 2.
0x00, 0x01, // Body (value = 1).
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(1024, true);
ElementMetadata child_metadata = {Id::kTimecode, 3, 2, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
child_metadata = {static_cast<Id>(0x4000), 4, 2, 5};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_,
OnUnknownElement(child_metadata, NotNull(), NotNull()))
.Times(3);
child_metadata = {Id::kPrevSize, 3, 2, 11};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
cluster.previous_size.Set(1, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
IncrementalParseAndVerify();
}
TEST_F(MasterValueParserTest, StartEventWithoutPreviousSize) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x80, // Size = 0.
});
{
InSequence dummy;
Cluster cluster{};
const ElementMetadata child_metadata = {Id::kTimecode, 2, 0, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
cluster.timecode.Set(0, true);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, StartEventWithPreviousSize) {
SetReaderData({
0xAB, // ID = 0xAB (PrevSize).
0x80, // Size = 0.
0xE7, // ID = 0xE7 (Timecode).
0x80, // Size = 0.
});
{
InSequence dummy;
Cluster cluster{};
ElementMetadata child_metadata = {Id::kPrevSize, 2, 0, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
child_metadata = {Id::kTimecode, 2, 0, 2};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
cluster.previous_size.Set(0, true);
cluster.timecode.Set(0, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, PartialStartThenRead) {
SetReaderData({
0xAB, // ID = 0xAB (PrevSize).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xE7, // ID = 0xE7 (Timecode).
0x81, // Size = 1.
0x01, // Body (value = 1).
});
{
InSequence dummy;
Cluster cluster{};
ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<2>(Action::kRead),
Return(Status(Status::kOkCompleted))));
child_metadata = {Id::kTimecode, 2, 1, 3};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
cluster.previous_size.Set(1, true);
cluster.timecode.Set(1, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
IncrementalParseAndVerify();
}
TEST_F(MasterValueParserTest, EmptySkip) {
const Cluster cluster{};
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
ParseAndVerify();
EXPECT_EQ(cluster, parser_.value());
}
TEST_F(MasterValueParserTest, Skip) {
SetReaderData({
0xAB, // ID = 0xAB (PrevSize).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xE7, // ID = 0xE7 (Timecode).
0x81, // Size = 1.
0x01, // Body (value = 1).
});
const Cluster cluster{};
{
InSequence dummy;
const ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
}
ParseAndVerify();
EXPECT_EQ(cluster, parser_.value());
}
TEST_F(MasterValueParserTest, PartialStartThenSkip) {
SetReaderData({
0xAB, // ID = 0xAB (PrevSize).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xE7, // ID = 0xE7 (Timecode).
0x81, // Size = 1.
0x01, // Body (value = 1).
});
const Cluster cluster{};
{
InSequence dummy;
const ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
}
IncrementalParseAndVerify();
EXPECT_EQ(cluster, parser_.value());
}
} // namespace

View File

@@ -0,0 +1,208 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/mastering_metadata_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::MasteringMetadata;
using webm::MasteringMetadataParser;
namespace {
class MasteringMetadataParserTest
: public ElementParserTest<MasteringMetadataParser,
Id::kMasteringMetadata> {};
TEST_F(MasteringMetadataParserTest, DefaultParse) {
ParseAndVerify();
const MasteringMetadata mastering_metadata = parser_.value();
EXPECT_FALSE(mastering_metadata.primary_r_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_r_chromaticity_x.value());
EXPECT_FALSE(mastering_metadata.primary_r_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_r_chromaticity_y.value());
EXPECT_FALSE(mastering_metadata.primary_g_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_g_chromaticity_x.value());
EXPECT_FALSE(mastering_metadata.primary_g_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_g_chromaticity_y.value());
EXPECT_FALSE(mastering_metadata.primary_b_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_b_chromaticity_x.value());
EXPECT_FALSE(mastering_metadata.primary_b_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_b_chromaticity_y.value());
EXPECT_FALSE(mastering_metadata.white_point_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.white_point_chromaticity_x.value());
EXPECT_FALSE(mastering_metadata.white_point_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.white_point_chromaticity_y.value());
EXPECT_FALSE(mastering_metadata.luminance_max.is_present());
EXPECT_EQ(0, mastering_metadata.luminance_max.value());
EXPECT_FALSE(mastering_metadata.luminance_min.is_present());
EXPECT_EQ(0, mastering_metadata.luminance_min.value());
}
TEST_F(MasteringMetadataParserTest, DefaultValues) {
SetReaderData({
0x55, 0xD1, // ID = 0x55D1 (PrimaryRChromaticityX).
0x80, // Size = 0.
0x55, 0xD2, // ID = 0x55D2 (PrimaryRChromaticityY).
0x80, // Size = 0.
0x55, 0xD3, // ID = 0x55D3 (PrimaryGChromaticityX).
0x80, // Size = 0.
0x55, 0xD4, // ID = 0x55D4 (PrimaryGChromaticityY).
0x80, // Size = 0.
0x55, 0xD5, // ID = 0x55D5 (PrimaryBChromaticityX).
0x80, // Size = 0.
0x55, 0xD6, // ID = 0x55D6 (PrimaryBChromaticityY).
0x80, // Size = 0.
0x55, 0xD7, // ID = 0x55D7 (WhitePointChromaticityX).
0x80, // Size = 0.
0x55, 0xD8, // ID = 0x55D8 (WhitePointChromaticityY).
0x80, // Size = 0.
0x55, 0xD9, // ID = 0x55D9 (LuminanceMax).
0x80, // Size = 0.
0x55, 0xDA, // ID = 0x55DA (LuminanceMin).
0x80, // Size = 0.
});
ParseAndVerify();
const MasteringMetadata mastering_metadata = parser_.value();
EXPECT_TRUE(mastering_metadata.primary_r_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_r_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_r_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_r_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.primary_g_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_g_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_g_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_g_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.primary_b_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_b_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_b_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_b_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.white_point_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.white_point_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.white_point_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.white_point_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.luminance_max.is_present());
EXPECT_EQ(0, mastering_metadata.luminance_max.value());
EXPECT_TRUE(mastering_metadata.luminance_min.is_present());
EXPECT_EQ(0, mastering_metadata.luminance_min.value());
}
TEST_F(MasteringMetadataParserTest, CustomValues) {
SetReaderData({
0x55, 0xD1, // ID = 0x55D1 (PrimaryRChromaticityX).
0x84, // Size = 4.
0x3E, 0x00, 0x00, 0x00, // Body (value = 0.125).
0x55, 0xD2, // ID = 0x55D2 (PrimaryRChromaticityY).
0x84, // Size = 4.
0x3E, 0x80, 0x00, 0x00, // Body (value = 0.25).
0x55, 0xD3, // ID = 0x55D3 (PrimaryGChromaticityX).
0x84, // Size = 4.
0x3E, 0xC0, 0x00, 0x00, // Body (value = 0.375).
0x55, 0xD4, // ID = 0x55D4 (PrimaryGChromaticityY).
0x84, // Size = 4.
0x3F, 0x00, 0x00, 0x00, // Body (value = 0.5).
0x55, 0xD5, // ID = 0x55D5 (PrimaryBChromaticityX).
0x84, // Size = 4.
0x3F, 0x20, 0x00, 0x00, // Body (value = 0.625).
0x55, 0xD6, // ID = 0x55D6 (PrimaryBChromaticityY).
0x84, // Size = 4.
0x3F, 0x40, 0x00, 0x00, // Body (value = 0.75).
0x55, 0xD7, // ID = 0x55D7 (WhitePointChromaticityX).
0x84, // Size = 4.
0x3F, 0x60, 0x00, 0x00, // Body (value = 0.875).
0x55, 0xD8, // ID = 0x55D8 (WhitePointChromaticityY).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1).
0x55, 0xD9, // ID = 0x55D9 (LuminanceMax).
0x84, // Size = 4.
0x40, 0x00, 0x00, 0x00, // Body (value = 2).
0x55, 0xDA, // ID = 0x55DA (LuminanceMin).
0x84, // Size = 4.
0x40, 0x40, 0x00, 0x00, // Body (value = 3).
});
ParseAndVerify();
const MasteringMetadata mastering_metadata = parser_.value();
EXPECT_TRUE(mastering_metadata.primary_r_chromaticity_x.is_present());
EXPECT_EQ(0.125, mastering_metadata.primary_r_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_r_chromaticity_y.is_present());
EXPECT_EQ(0.25, mastering_metadata.primary_r_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.primary_g_chromaticity_x.is_present());
EXPECT_EQ(0.375, mastering_metadata.primary_g_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_g_chromaticity_y.is_present());
EXPECT_EQ(0.5, mastering_metadata.primary_g_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.primary_b_chromaticity_x.is_present());
EXPECT_EQ(0.625, mastering_metadata.primary_b_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_b_chromaticity_y.is_present());
EXPECT_EQ(0.75, mastering_metadata.primary_b_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.white_point_chromaticity_x.is_present());
EXPECT_EQ(0.875, mastering_metadata.white_point_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.white_point_chromaticity_y.is_present());
EXPECT_EQ(1.0, mastering_metadata.white_point_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.luminance_max.is_present());
EXPECT_EQ(2.0, mastering_metadata.luminance_max.value());
EXPECT_TRUE(mastering_metadata.luminance_min.is_present());
EXPECT_EQ(3.0, mastering_metadata.luminance_min.value());
}
} // namespace

View File

@@ -0,0 +1,100 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/parser_utils.h"
#include <cstdint>
#include <limits>
#include <memory>
#include "gtest/gtest.h"
#include "test_utils/limited_reader.h"
#include "webm/buffer_reader.h"
#include "webm/reader.h"
#include "webm/status.h"
using webm::BufferReader;
using webm::LimitedReader;
using webm::Reader;
using webm::Status;
namespace {
class ParserUtilsTest : public testing::Test {};
TEST_F(ParserUtilsTest, ReadByte) {
LimitedReader reader(
std::unique_ptr<Reader>(new BufferReader({0x12, 0x34, 0x56, 0x78})));
Status status;
std::uint8_t byte;
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0x12, byte);
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0x34, byte);
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0x56, byte);
reader.set_total_read_limit(0);
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(0x56, byte);
reader.set_total_read_limit(std::numeric_limits<std::size_t>::max());
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0x78, byte);
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0x78, byte);
}
TEST_F(ParserUtilsTest, AccumulateIntegerBytes) {
LimitedReader reader(
std::unique_ptr<Reader>(new BufferReader({0x12, 0x34, 0x56, 0x78})));
std::uint32_t integer = 0;
Status status;
std::uint64_t num_bytes_actually_read;
reader.set_total_read_limit(1);
status =
AccumulateIntegerBytes(4, &reader, &integer, &num_bytes_actually_read);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(1, num_bytes_actually_read);
EXPECT_EQ(0x12, integer);
reader.set_total_read_limit(std::numeric_limits<std::size_t>::max());
status =
AccumulateIntegerBytes(3, &reader, &integer, &num_bytes_actually_read);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(3, num_bytes_actually_read);
EXPECT_EQ(0x12345678, integer);
// Make sure calling with num_bytes_remaining == 0 is a no-op.
status =
AccumulateIntegerBytes(0, &reader, &integer, &num_bytes_actually_read);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0, num_bytes_actually_read);
EXPECT_EQ(0x12345678, integer);
status =
AccumulateIntegerBytes(4, &reader, &integer, &num_bytes_actually_read);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0, num_bytes_actually_read);
EXPECT_EQ(0x12345678, integer);
}
} // namespace

View File

@@ -0,0 +1,70 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/recursive_parser.h"
#include <cstdint>
#include "gtest/gtest.h"
#include "src/byte_parser.h"
#include "src/element_parser.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/status.h"
using webm::Callback;
using webm::ElementMetadata;
using webm::ElementParser;
using webm::ElementParserTest;
using webm::Reader;
using webm::RecursiveParser;
using webm::Status;
using webm::StringParser;
namespace {
class FailParser : public ElementParser {
public:
FailParser() { EXPECT_FALSE(true); }
Status Init(const ElementMetadata& metadata,
std::uint64_t max_size) override {
return Status(Status::kInvalidElementSize);
}
Status Feed(Callback* callback, Reader* reader,
std::uint64_t* num_bytes_read) override {
*num_bytes_read = 0;
return Status(Status::kInvalidElementSize);
}
int value() const { return 0; }
int* mutable_value() { return nullptr; }
};
class RecursiveFailParserTest
: public ElementParserTest<RecursiveParser<FailParser>> {};
TEST_F(RecursiveFailParserTest, NoConstruction) {
RecursiveParser<FailParser> parser;
}
class RecursiveStringParserTest
: public ElementParserTest<RecursiveParser<StringParser>> {};
TEST_F(RecursiveStringParserTest, ParsesOkay) {
ParseAndVerify();
EXPECT_EQ("", parser_.value());
SetReaderData({0x48, 0x69}); // "Hi".
ParseAndVerify();
EXPECT_EQ("Hi", parser_.value());
}
} // namespace

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/seek_head_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/buffer_reader.h"
using webm::ElementParserTest;
using webm::Id;
using webm::SeekHeadParser;
namespace {
class SeekHeadParserTest
: public ElementParserTest<SeekHeadParser, Id::kSeekHead> {};
TEST_F(SeekHeadParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(SeekHeadParserTest, RepeatedValues) {
SetReaderData({
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x84, // Size = 4.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x84, // Size = 4.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,67 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/seek_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Seek;
using webm::SeekParser;
namespace {
class SeekParserTest : public ElementParserTest<SeekParser, Id::kSeek> {};
TEST_F(SeekParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnSeek(metadata_, Seek{})).Times(1);
ParseAndVerify();
}
TEST_F(SeekParserTest, DefaultValues) {
SetReaderData({
// A SeekID element with a length of 0 isn't valid, so we don't test it.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x80, // Size = 0.
});
Seek seek;
seek.position.Set(0, true);
EXPECT_CALL(callback_, OnSeek(metadata_, seek)).Times(1);
ParseAndVerify();
}
TEST_F(SeekParserTest, CustomValues) {
SetReaderData({
0x53, 0xAB, // ID = 0x53AB (SeekID).
0x81, // Size = 1.
0x01, // Body.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
Seek seek;
seek.id.Set(static_cast<Id>(0x01), true);
seek.position.Set(2, true);
EXPECT_CALL(callback_, OnSeek(metadata_, seek)).Times(1);
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,355 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/segment_parser.h"
#include <cstdint>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::Ancestory;
using webm::ElementMetadata;
using webm::ElementParserTest;
using webm::Id;
using webm::SegmentParser;
using webm::Status;
namespace {
class SegmentParserTest
: public ElementParserTest<SegmentParser, Id::kSegment> {};
TEST_F(SegmentParserTest, EmptyParse) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
ParseAndVerify();
}
TEST_F(SegmentParserTest, EmptyParseWithDelayedStart) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<1>(Action::kRead),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
IncrementalParseAndVerify();
}
TEST_F(SegmentParserTest, DefaultValues) {
SetReaderData({
0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
0x80, // Size = 0.
0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
0x80, // Size = 0.
0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
0x80, // Size = 0.
0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
0x80, // Size = 0.
0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
0x80, // Size = 0.
0x10, 0x43, 0xA7, 0x70, // ID = 0x1043A770 (Chapters).
0x80, // Size = 0.
0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
0x80, // Size = 0.
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
ElementMetadata metadata = {Id::kInfo, 5, 0, 5};
EXPECT_CALL(callback_, OnInfo(metadata, _)).Times(1);
metadata = {Id::kCluster, 5, 0, 10};
EXPECT_CALL(callback_, OnClusterBegin(metadata, _, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterEnd(metadata, _)).Times(1);
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
ParseAndVerify();
}
TEST_F(SegmentParserTest, RepeatedValues) {
SetReaderData({
// Mutliple SeekHead elements.
0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
0x8D, // Size = 13.
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
0x8D, // Size = 13.
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
// Multiple Info elements.
0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
0x88, // Size = 8.
0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
0x88, // Size = 8.
0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
// Multiple Cluster elements.
0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
0x86, // Size = 6.
0xE7, // ID = 0xE7 (Timecode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
0x86, // Size = 6.
0xE7, // ID = 0xE7 (Timecode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
// Multiple Tracks elements.
0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
0x8B, // Size = 11.
0xAE, // ID = 0xAE (TrackEntry).
0x10, 0x00, 0x00, 0x06, // Size = 6.
0xD7, // ID = 0xD7 (TrackNumber).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
0x8B, // Size = 11.
0xAE, // ID = 0xAE (TrackEntry).
0x10, 0x00, 0x00, 0x06, // Size = 6.
0xD7, // ID = 0xD7 (TrackNumber).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
// Single Cues element.
0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
0x8B, // Size = 11.
0xBB, // ID = 0xBB (CuePoint).
0x10, 0x00, 0x00, 0x06, // Size = 6.
0xB3, // ID = 0xB3 (CueTime).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
// Single Chapters element.
0x10, 0x43, 0xA7, 0x70, // ID = 0x1043A770 (Chapters).
0x8D, // Size = 13.
0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x45, 0xBC, // ID = 0x45BC (EditionUID).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
// Multiple Tags elements.
0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
0x93, // Size = 19.
0x73, 0x73, // ID = 0x7373 (Tag).
0x10, 0x00, 0x00, 0x0D, // Size = 13.
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
0x93, // Size = 19.
0x73, 0x73, // ID = 0x7373 (Tag).
0x10, 0x00, 0x00, 0x0D, // Size = 13.
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
EXPECT_CALL(callback_, OnSeek(_, _)).Times(2);
EXPECT_CALL(callback_, OnInfo(_, _)).Times(2);
EXPECT_CALL(callback_, OnClusterBegin(_, _, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(_, _, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(1);
EXPECT_CALL(callback_, OnTrackEntry(_, _)).Times(2);
EXPECT_CALL(callback_, OnCuePoint(_, _)).Times(1);
EXPECT_CALL(callback_, OnEditionEntry(_, _)).Times(1);
EXPECT_CALL(callback_, OnTag(_, _)).Times(2);
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
ParseAndVerify();
}
TEST_F(SegmentParserTest, Skip) {
SetReaderData({
0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
0x80, // Size = 0.
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterBegin(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
EXPECT_CALL(callback_, OnSegmentEnd(_)).Times(0);
}
IncrementalParseAndVerify();
}
TEST_F(SegmentParserTest, Seek) {
SetReaderData({
// We start the reader at the beginning of a FlagInterlaced element
// (skipping its ID and size, as they're passed into InitAfterSeek).
// FlagInterlaced, StereoMode, and AlphaMode are all part of the Video
// element, with the ancestory: Segment -> Tracks -> TrackEntry -> Video.
0x01, // Body (value = 1).
0x53, 0xB8, // ID = 0x53B8 (StereoMode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x53, 0xC0, // ID = 0x53C0 (AlphaMode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x03, // Body (value = 3).
// Single Cues element.
0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
0x8B, // Size = 11.
0xBB, // ID = 0xBB (CuePoint).
0x10, 0x00, 0x00, 0x06, // Size = 6.
0xB3, // ID = 0xB3 (CueTime).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
const ElementMetadata flag_interlaced_metadata = {Id::kFlagInterlaced, 0, 1,
0};
EXPECT_CALL(callback_, OnSegmentBegin(_, _)).Times(0);
{
InSequence dummy;
EXPECT_CALL(callback_, OnElementBegin(flag_interlaced_metadata, NotNull()))
.Times(1);
ElementMetadata metadata = {Id::kStereoMode, 6, 1, 1};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kAlphaMode, 6, 1, 8};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnTrackEntry(_, _)).Times(1);
metadata = {Id::kCues, 5, 11, 15};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kCuePoint, 5, 6, 20};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kCueTime, 5, 1, 25};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnCuePoint(_, _)).Times(1);
EXPECT_CALL(callback_, OnSegmentEnd(_)).Times(1);
}
Ancestory ancestory;
ASSERT_TRUE(Ancestory::ById(flag_interlaced_metadata.id, &ancestory));
ancestory = ancestory.next(); // Skip the Segment ancestor.
parser_.InitAfterSeek(ancestory, flag_interlaced_metadata);
std::uint64_t num_bytes_read = 0;
const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader_.size(), num_bytes_read);
}
} // namespace

View File

@@ -0,0 +1,184 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/simple_tag_parser.h"
#include <cstdint>
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::SimpleTag;
using webm::SimpleTagParser;
namespace {
class SimpleTagParserTest
: public ElementParserTest<SimpleTagParser, Id::kSimpleTag> {};
TEST_F(SimpleTagParserTest, DefaultParse) {
ParseAndVerify();
const SimpleTag simple_tag = parser_.value();
EXPECT_FALSE(simple_tag.name.is_present());
EXPECT_EQ("", simple_tag.name.value());
EXPECT_FALSE(simple_tag.language.is_present());
EXPECT_EQ("und", simple_tag.language.value());
EXPECT_FALSE(simple_tag.is_default.is_present());
EXPECT_EQ(true, simple_tag.is_default.value());
EXPECT_FALSE(simple_tag.string.is_present());
EXPECT_EQ("", simple_tag.string.value());
EXPECT_FALSE(simple_tag.binary.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, simple_tag.binary.value());
EXPECT_EQ(0, simple_tag.tags.size());
}
TEST_F(SimpleTagParserTest, DefaultValues) {
SetReaderData({
0x45, 0xA3, // ID = 0x45A3 (TagName).
0x80, // Size = 0.
0x44, 0x7A, // ID = 0x447A (TagLanguage).
0x80, // Size = 0.
0x44, 0x84, // ID = 0x4484 (TagDefault).
0x80, // Size = 0.
0x44, 0x87, // ID = 0x4487 (TagString).
0x80, // Size = 0.
0x44, 0x85, // ID = 0x4485 (TagBinary).
0x80, // Size = 0.
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x80, // Size = 0.
});
ParseAndVerify();
const SimpleTag simple_tag = parser_.value();
EXPECT_TRUE(simple_tag.name.is_present());
EXPECT_EQ("", simple_tag.name.value());
EXPECT_TRUE(simple_tag.language.is_present());
EXPECT_EQ("und", simple_tag.language.value());
EXPECT_TRUE(simple_tag.is_default.is_present());
EXPECT_EQ(true, simple_tag.is_default.value());
EXPECT_TRUE(simple_tag.string.is_present());
EXPECT_EQ("", simple_tag.string.value());
EXPECT_TRUE(simple_tag.binary.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, simple_tag.binary.value());
ASSERT_EQ(1, simple_tag.tags.size());
EXPECT_TRUE(simple_tag.tags[0].is_present());
EXPECT_EQ(SimpleTag{}, simple_tag.tags[0].value());
}
TEST_F(SimpleTagParserTest, CustomValues) {
SetReaderData({
0x45, 0xA3, // ID = 0x45A3 (TagName).
0x81, // Size = 1.
0x61, // Body (value = "a").
0x44, 0x7A, // ID = 0x447A (TagLanguage).
0x81, // Size = 1.
0x62, // Body (value = "b").
0x44, 0x84, // ID = 0x4484 (TagDefault).
0x81, // Size = 1.
0x00, // Body (value = 0).
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x63, // Body (value = "c").
0x44, 0x85, // ID = 0x4485 (TagBinary).
0x81, // Size = 1.
0x01, // Body.
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x99, // Size = 25.
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x64, // Body (value = "d").
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x8B, // Size = 11.
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x65, // Body (value = "e").
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x84, // Size = 4.
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x66, // Body (value = "f").
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x84, // Size = 4.
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x67, // Body (value = "g").
});
ParseAndVerify();
const SimpleTag simple_tag = parser_.value();
EXPECT_TRUE(simple_tag.name.is_present());
EXPECT_EQ("a", simple_tag.name.value());
EXPECT_TRUE(simple_tag.language.is_present());
EXPECT_EQ("b", simple_tag.language.value());
EXPECT_TRUE(simple_tag.is_default.is_present());
EXPECT_EQ(false, simple_tag.is_default.value());
EXPECT_TRUE(simple_tag.string.is_present());
EXPECT_EQ("c", simple_tag.string.value());
EXPECT_TRUE(simple_tag.binary.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{0x01}, simple_tag.binary.value());
SimpleTag expected;
expected.string.Set("d", true);
SimpleTag temp{};
temp.string.Set("e", true);
expected.tags.emplace_back(temp, true);
temp.string.Set("f", true);
expected.tags[0].mutable_value()->tags.emplace_back(temp, true);
temp.string.Set("g", true);
expected.tags.emplace_back(temp, true);
ASSERT_EQ(1, simple_tag.tags.size());
EXPECT_TRUE(simple_tag.tags[0].is_present());
EXPECT_EQ(expected, simple_tag.tags[0].value());
}
} // namespace

View File

@@ -0,0 +1,61 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/size_parser.h"
#include "gtest/gtest.h"
#include "test_utils/parser_test.h"
#include "webm/status.h"
using webm::ParserTest;
using webm::SizeParser;
using webm::Status;
namespace {
class SizeParserTest : public ParserTest<SizeParser> {};
TEST_F(SizeParserTest, InvalidSize) {
SetReaderData({0x00});
ParseAndExpectResult(Status::kInvalidElementSize);
}
TEST_F(SizeParserTest, EarlyEndOfFile) {
SetReaderData({0x01});
ParseAndExpectResult(Status::kEndOfFile);
}
TEST_F(SizeParserTest, ValidSize) {
SetReaderData({0x80});
ParseAndVerify();
EXPECT_EQ(0, parser_.size());
ResetParser();
SetReaderData({0x01, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE});
ParseAndVerify();
EXPECT_EQ(0x123456789ABCDE, parser_.size());
}
TEST_F(SizeParserTest, UnknownSize) {
SetReaderData({0xFF});
ParseAndVerify();
EXPECT_EQ(0xFFFFFFFFFFFFFFFF, parser_.size());
ResetParser();
SetReaderData({0x1F, 0xFF, 0xFF, 0xFF});
ParseAndVerify();
EXPECT_EQ(0xFFFFFFFFFFFFFFFF, parser_.size());
}
TEST_F(SizeParserTest, IncrementalParse) {
SetReaderData({0x11, 0x23, 0x45, 0x67});
IncrementalParseAndVerify();
EXPECT_EQ(0x01234567, parser_.size());
}
} // namespace

View File

@@ -0,0 +1,42 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/skip_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::SkipParser;
using webm::Status;
namespace {
class SkipParserTest : public ElementParserTest<SkipParser> {};
TEST_F(SkipParserTest, InvalidSize) {
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(SkipParserTest, Skip) {
ParseAndVerify();
SetReaderData({0x00, 0x01, 0x02, 0x04});
ParseAndVerify();
}
TEST_F(SkipParserTest, IncrementalSkip) {
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10});
IncrementalParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,80 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/slices_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Slices;
using webm::SlicesParser;
using webm::TimeSlice;
namespace {
class SlicesParserTest : public ElementParserTest<SlicesParser, Id::kSlices> {};
TEST_F(SlicesParserTest, DefaultParse) {
ParseAndVerify();
const Slices slices = parser_.value();
EXPECT_EQ(0, slices.slices.size());
}
TEST_F(SlicesParserTest, DefaultValues) {
SetReaderData({
0xE8, // ID = 0xE8 (TimeSlice).
0x80, // Size = 0.
});
ParseAndVerify();
const Slices slices = parser_.value();
ASSERT_EQ(1, slices.slices.size());
EXPECT_TRUE(slices.slices[0].is_present());
EXPECT_EQ(TimeSlice{}, slices.slices[0].value());
}
TEST_F(SlicesParserTest, CustomValues) {
SetReaderData({
0xE8, // ID = 0xE8 (TimeSlice).
0x83, // Size = 3.
0xCC, // ID = 0xCC (LaceNumber).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xE8, // ID = 0xE8 (TimeSlice).
0x83, // Size = 3.
0xCC, // ID = 0xCC (LaceNumber).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
const Slices slices = parser_.value();
TimeSlice expected;
ASSERT_EQ(2, slices.slices.size());
expected.lace_number.Set(1, true);
EXPECT_TRUE(slices.slices[0].is_present());
EXPECT_EQ(expected, slices.slices[0].value());
expected.lace_number.Set(2, true);
EXPECT_TRUE(slices.slices[1].is_present());
EXPECT_EQ(expected, slices.slices[1].value());
}
} // namespace

View File

@@ -0,0 +1,92 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/tag_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::SimpleTag;
using webm::Tag;
using webm::TagParser;
using webm::Targets;
namespace {
class TagParserTest : public ElementParserTest<TagParser, Id::kTag> {};
TEST_F(TagParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnTag(metadata_, Tag{})).Times(1);
ParseAndVerify();
}
TEST_F(TagParserTest, DefaultValues) {
SetReaderData({
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x80, // Size = 0.
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x80, // Size = 0.
});
Tag tag;
tag.targets.Set({}, true);
tag.tags.emplace_back();
tag.tags[0].Set({}, true);
EXPECT_CALL(callback_, OnTag(metadata_, tag)).Times(1);
ParseAndVerify();
}
TEST_F(TagParserTest, CustomValues) {
SetReaderData({
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x84, // Size = 4.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x81, // Size = 1.
0x00, // Body (value = 0).
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x84, // Size = 4.
0x45, 0xA3, // ID = 0x45A3 (TagName).
0x81, // Size = 1.
0x61, // Body (value = "a").
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x84, // Size = 4.
0x44, 0x7A, // ID = 0x447A (TagLanguage).
0x81, // Size = 1.
0x62, // Body (value = "b").
});
Tag tag;
Targets targets;
targets.type_value.Set(0, true);
tag.targets.Set(targets, true);
SimpleTag simple_tag;
simple_tag.name.Set("a", true);
tag.tags.emplace_back(simple_tag, true);
simple_tag = {};
simple_tag.language.Set("b", true);
tag.tags.emplace_back(simple_tag, true);
EXPECT_CALL(callback_, OnTag(metadata_, tag)).Times(1);
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,61 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/tags_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/buffer_reader.h"
using webm::ElementParserTest;
using webm::Id;
using webm::TagsParser;
namespace {
class TagsParserTest : public ElementParserTest<TagsParser, Id::kTags> {};
// TODO(mjbshaw): validate results via Callback.
TEST_F(TagsParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0x73, 0x73, // ID = 0x7373 (Tag).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(TagsParserTest, RepeatedValues) {
SetReaderData({
0x73, 0x73, // ID = 0x7373 (Tag).
0x87, // Size = 7.
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x84, // Size = 4.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x73, 0x73, // ID = 0x7373 (Tag).
0x87, // Size = 7.
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x84, // Size = 4.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,102 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/targets_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Targets;
using webm::TargetsParser;
namespace {
class TargetsParserTest
: public ElementParserTest<TargetsParser, Id::kTargets> {};
TEST_F(TargetsParserTest, DefaultParse) {
ParseAndVerify();
const Targets targets = parser_.value();
EXPECT_FALSE(targets.type_value.is_present());
EXPECT_EQ(50, targets.type_value.value());
EXPECT_FALSE(targets.type.is_present());
EXPECT_EQ("", targets.type.value());
EXPECT_EQ(0, targets.track_uids.size());
}
TEST_F(TargetsParserTest, DefaultValues) {
SetReaderData({
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x80, // Size = 0.
0x63, 0xCA, // ID = 0x63CA (TargetType).
0x80, // Size = 0.
0x63, 0xC5, // ID = 0x63C5 (TagTrackUID).
0x80, // Size = 0.
});
ParseAndVerify();
const Targets targets = parser_.value();
EXPECT_TRUE(targets.type_value.is_present());
EXPECT_EQ(50, targets.type_value.value());
EXPECT_TRUE(targets.type.is_present());
EXPECT_EQ("", targets.type.value());
ASSERT_EQ(1, targets.track_uids.size());
EXPECT_TRUE(targets.track_uids[0].is_present());
EXPECT_EQ(0, targets.track_uids[0].value());
}
TEST_F(TargetsParserTest, CustomValues) {
SetReaderData({
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x81, // Size = 1.
0x00, // Body (value = 0).
0x63, 0xCA, // ID = 0x63CA (TargetType).
0x82, // Size = 2.
0x48, 0x69, // Body (value = "Hi").
0x63, 0xC5, // ID = 0x63C5 (TagTrackUID).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x63, 0xC5, // ID = 0x63C5 (TagTrackUID).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
const Targets targets = parser_.value();
EXPECT_TRUE(targets.type_value.is_present());
EXPECT_EQ(0, targets.type_value.value());
EXPECT_TRUE(targets.type.is_present());
EXPECT_EQ("Hi", targets.type.value());
ASSERT_EQ(2, targets.track_uids.size());
EXPECT_TRUE(targets.track_uids[0].is_present());
EXPECT_EQ(1, targets.track_uids[0].value());
EXPECT_TRUE(targets.track_uids[1].is_present());
EXPECT_EQ(2, targets.track_uids[1].value());
}
} // namespace

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/time_slice_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::TimeSlice;
using webm::TimeSliceParser;
namespace {
class TimeSliceParserTest
: public ElementParserTest<TimeSliceParser, Id::kTimeSlice> {};
TEST_F(TimeSliceParserTest, DefaultParse) {
ParseAndVerify();
const TimeSlice time_slice = parser_.value();
EXPECT_FALSE(time_slice.lace_number.is_present());
EXPECT_EQ(0, time_slice.lace_number.value());
}
TEST_F(TimeSliceParserTest, DefaultValues) {
SetReaderData({
0xCC, // ID = 0xCC (LaceNumber).
0x80, // Size = 0.
});
ParseAndVerify();
const TimeSlice time_slice = parser_.value();
EXPECT_TRUE(time_slice.lace_number.is_present());
EXPECT_EQ(0, time_slice.lace_number.value());
}
TEST_F(TimeSliceParserTest, CustomValues) {
SetReaderData({
0xCC, // ID = 0xCC (LaceNumber).
0x81, // Size = 1.
0x01, // Body (value = 1).
});
ParseAndVerify();
const TimeSlice time_slice = parser_.value();
EXPECT_TRUE(time_slice.lace_number.is_present());
EXPECT_EQ(1, time_slice.lace_number.value());
}
} // namespace

View File

@@ -0,0 +1,245 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/track_entry_parser.h"
#include <cstdint>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::Audio;
using webm::ContentEncoding;
using webm::ContentEncodings;
using webm::DisplayUnit;
using webm::ElementParserTest;
using webm::Id;
using webm::TrackEntry;
using webm::TrackEntryParser;
using webm::TrackType;
using webm::Video;
namespace {
class TrackEntryParserTest
: public ElementParserTest<TrackEntryParser, Id::kTrackEntry> {};
TEST_F(TrackEntryParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnTrackEntry(metadata_, TrackEntry{})).Times(1);
ParseAndVerify();
}
TEST_F(TrackEntryParserTest, DefaultValues) {
SetReaderData({
0xD7, // ID = 0xD7 (TrackNumber).
0x20, 0x00, 0x00, // Size = 0.
0x73, 0xC5, // ID = 0x73C5 (TrackUID).
0x20, 0x00, 0x00, // Size = 0.
0x83, // ID = 0x83 (TrackType).
0x20, 0x00, 0x00, // Size = 0.
0xB9, // ID = 0xB9 (FlagEnabled).
0x20, 0x00, 0x00, // Size = 0.
0x88, // ID = 0x88 (FlagDefault).
0x20, 0x00, 0x00, // Size = 0.
0x55, 0xAA, // ID = 0x55AA (FlagForced).
0x20, 0x00, 0x00, // Size = 0.
0x9C, // ID = 0x9C (FlagLacing).
0x20, 0x00, 0x00, // Size = 0.
0x23, 0xE3, 0x83, // ID = 0x23E383 (DefaultDuration).
0x80, // Size = 0.
0x53, 0x6E, // ID = 0x536E (Name).
0x20, 0x00, 0x00, // Size = 0.
0x22, 0xB5, 0x9C, // ID = 0x22B59C (Language).
0x80, // Size = 0.
0x86, // ID = 0x86 (CodecID).
0x20, 0x00, 0x00, // Size = 0.
0x63, 0xA2, // ID = 0x63A2 (CodecPrivate).
0x20, 0x00, 0x00, // Size = 0.
0x25, 0x86, 0x88, // ID = 0x258688 (CodecName).
0x80, // Size = 0.
0x56, 0xAA, // ID = 0x56AA (CodecDelay).
0x20, 0x00, 0x00, // Size = 0.
0x56, 0xBB, // ID = 0x56BB (SeekPreRoll).
0x20, 0x00, 0x00, // Size = 0.
0xE0, // ID = 0xE0 (Video).
0x20, 0x00, 0x00, // Size = 0.
0xE1, // ID = 0xE1 (Audio).
0x20, 0x00, 0x00, // Size = 0.
0x6D, 0x80, // ID = 0x6D80 (ContentEncodings).
0x20, 0x00, 0x00, // Size = 0.
});
TrackEntry track_entry;
track_entry.track_number.Set(0, true);
track_entry.track_uid.Set(0, true);
track_entry.track_type.Set(TrackType{}, true);
track_entry.is_enabled.Set(true, true);
track_entry.is_default.Set(true, true);
track_entry.is_forced.Set(false, true);
track_entry.uses_lacing.Set(true, true);
track_entry.default_duration.Set(0, true);
track_entry.name.Set("", true);
track_entry.language.Set("eng", true);
track_entry.codec_id.Set("", true);
track_entry.codec_private.Set(std::vector<std::uint8_t>{}, true);
track_entry.codec_name.Set("", true);
track_entry.codec_delay.Set(0, true);
track_entry.seek_pre_roll.Set(0, true);
track_entry.video.Set(Video{}, true);
track_entry.audio.Set(Audio{}, true);
track_entry.content_encodings.Set(ContentEncodings{}, true);
EXPECT_CALL(callback_, OnTrackEntry(metadata_, track_entry)).Times(1);
ParseAndVerify();
}
TEST_F(TrackEntryParserTest, CustomValues) {
SetReaderData({
0xD7, // ID = 0xD7 (TrackNumber).
0x20, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x73, 0xC5, // ID = 0x73C5 (TrackUID).
0x20, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x83, // ID = 0x83 (TrackType).
0x20, 0x00, 0x01, // Size = 1.
0x03, // Body (value = complex).
0xB9, // ID = 0xB9 (FlagEnabled).
0x20, 0x00, 0x01, // Size = 1.
0x00, // Body (value = 0).
0x88, // ID = 0x88 (FlagDefault).
0x20, 0x00, 0x01, // Size = 1.
0x00, // Body (value = 0).
0x55, 0xAA, // ID = 0x55AA (FlagForced).
0x20, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x9C, // ID = 0x9C (FlagLacing).
0x20, 0x00, 0x01, // Size = 1.
0x00, // Body (value = 0).
0x23, 0xE3, 0x83, // ID = 0x23E383 (DefaultDuration).
0x81, // Size = 1.
0x04, // Body (value = 4).
0x53, 0x6E, // ID = 0x536E (Name).
0x20, 0x00, 0x01, // Size = 1.
0x41, // Body (value = "A").
0x22, 0xB5, 0x9C, // ID = 0x22B59C (Language).
0x81, // Size = 1.
0x42, // Body (value = "B").
0x86, // ID = 0x86 (CodecID).
0x20, 0x00, 0x01, // Size = 1.
0x43, // Body (value = "C").
0x63, 0xA2, // ID = 0x63A2 (CodecPrivate).
0x20, 0x00, 0x01, // Size = 1.
0x00, // Body.
0x25, 0x86, 0x88, // ID = 0x258688 (CodecName).
0x81, // Size = 1.
0x44, // Body (value = "D").
0x56, 0xAA, // ID = 0x56AA (CodecDelay).
0x20, 0x00, 0x01, // Size = 1.
0x05, // Body (value = 5).
0x56, 0xBB, // ID = 0x56BB (SeekPreRoll).
0x20, 0x00, 0x01, // Size = 1.
0x06, // Body (value = 6).
0xE0, // ID = 0xE0 (Video).
0x20, 0x00, 0x06, // Size = 6.
0x54, 0xB2, // ID = 0x54B2 (DisplayUnit).
0x20, 0x00, 0x01, // Size = 1.
0x03, // Body (value = display aspect ratio).
0xE1, // ID = 0xE1 (Audio).
0x20, 0x00, 0x05, // Size = 5.
0x9F, // ID = 0x9F (Channels).
0x20, 0x00, 0x01, // Size = 1.
0x08, // Body (value = 8).
0x6D, 0x80, // ID = 0x6D80 (ContentEncodings).
0x20, 0x00, 0x0B, // Size = 11.
0x62, 0x40, // ID = 0x6240 (ContentEncoding).
0x20, 0x00, 0x06, // Size = 6.
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x20, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
TrackEntry track_entry;
track_entry.track_number.Set(1, true);
track_entry.track_uid.Set(2, true);
track_entry.track_type.Set(TrackType::kComplex, true);
track_entry.is_enabled.Set(false, true);
track_entry.is_default.Set(false, true);
track_entry.is_forced.Set(true, true);
track_entry.uses_lacing.Set(false, true);
track_entry.default_duration.Set(4, true);
track_entry.name.Set("A", true);
track_entry.language.Set("B", true);
track_entry.codec_id.Set("C", true);
track_entry.codec_private.Set(std::vector<std::uint8_t>{0x00}, true);
track_entry.codec_name.Set("D", true);
track_entry.codec_delay.Set(5, true);
track_entry.seek_pre_roll.Set(6, true);
Video expected_video;
expected_video.display_unit.Set(DisplayUnit::kDisplayAspectRatio, true);
track_entry.video.Set(expected_video, true);
Audio expected_audio;
expected_audio.channels.Set(8, true);
track_entry.audio.Set(expected_audio, true);
ContentEncoding expected_encoding;
expected_encoding.order.Set(1, true);
ContentEncodings expected_encodings;
expected_encodings.encodings.emplace_back(expected_encoding, true);
track_entry.content_encodings.Set(expected_encodings, true);
EXPECT_CALL(callback_, OnTrackEntry(metadata_, track_entry)).Times(1);
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/tracks_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/buffer_reader.h"
using webm::ElementParserTest;
using webm::Id;
using webm::TracksParser;
namespace {
class TracksParserTest : public ElementParserTest<TracksParser, Id::kTracks> {};
// TODO(mjbshaw): validate results via Callback.
TEST_F(TracksParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0xAE, // ID = 0xAE (TrackEntry).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(TracksParserTest, RepeatedValues) {
SetReaderData({
0xAE, // ID = 0xAE (TrackEntry).
0x83, // Size = 3.
0xD7, // ID = 0xD7 (TrackNumber).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xAE, // ID = 0xAE (TrackEntry).
0x83, // Size = 3.
0xD7, // ID = 0xD7 (TrackNumber).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,57 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/unknown_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/status.h"
using testing::NotNull;
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::Status;
using webm::UnknownParser;
namespace {
class UnknownParserTest : public ElementParserTest<UnknownParser> {};
TEST_F(UnknownParserTest, InvalidSize) {
TestInit(kUnknownElementSize, Status::kIndefiniteUnknownElement);
}
TEST_F(UnknownParserTest, Empty) {
EXPECT_CALL(callback_, OnUnknownElement(metadata_, NotNull(), NotNull()))
.Times(1);
ParseAndVerify();
}
TEST_F(UnknownParserTest, Valid) {
SetReaderData({0x00, 0x01, 0x02, 0x04});
EXPECT_CALL(callback_, OnUnknownElement(metadata_, NotNull(), NotNull()))
.Times(1);
ParseAndVerify();
}
TEST_F(UnknownParserTest, IncrementalSkip) {
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10});
EXPECT_CALL(callback_, OnUnknownElement(metadata_, NotNull(), NotNull()))
.Times(8);
IncrementalParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,53 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/var_int_parser.h"
#include "gtest/gtest.h"
#include "test_utils/parser_test.h"
#include "webm/status.h"
using webm::ParserTest;
using webm::Status;
using webm::VarIntParser;
namespace {
class VarIntParserTest : public ParserTest<VarIntParser> {};
TEST_F(VarIntParserTest, NoMarkerBit) {
SetReaderData({0x00});
ParseAndExpectResult(Status::kInvalidElementValue);
}
TEST_F(VarIntParserTest, EarlyEndOfFile) {
SetReaderData({0x01});
ParseAndExpectResult(Status::kEndOfFile);
}
TEST_F(VarIntParserTest, ValidValue) {
SetReaderData({0x80});
ParseAndVerify();
EXPECT_EQ(0, parser_.value());
EXPECT_EQ(1, parser_.encoded_length());
ResetParser();
SetReaderData({0x01, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE});
ParseAndVerify();
EXPECT_EQ(0x123456789ABCDE, parser_.value());
EXPECT_EQ(8, parser_.encoded_length());
}
TEST_F(VarIntParserTest, IncrementalParse) {
SetReaderData({0x11, 0x23, 0x45, 0x67});
IncrementalParseAndVerify();
EXPECT_EQ(0x01234567, parser_.value());
EXPECT_EQ(4, parser_.encoded_length());
}
} // namespace

View File

@@ -0,0 +1,423 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/video_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::AspectRatioType;
using webm::Colour;
using webm::DisplayUnit;
using webm::ElementParserTest;
using webm::FlagInterlaced;
using webm::Id;
using webm::StereoMode;
using webm::Video;
using webm::VideoParser;
namespace {
class VideoParserTest : public ElementParserTest<VideoParser, Id::kVideo> {};
TEST_F(VideoParserTest, DefaultParse) {
ParseAndVerify();
const Video video = parser_.value();
EXPECT_FALSE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kUnspecified, video.interlaced.value());
EXPECT_FALSE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kMono, video.stereo_mode.value());
EXPECT_FALSE(video.alpha_mode.is_present());
EXPECT_EQ(0, video.alpha_mode.value());
EXPECT_FALSE(video.pixel_width.is_present());
EXPECT_EQ(0, video.pixel_width.value());
EXPECT_FALSE(video.pixel_height.is_present());
EXPECT_EQ(0, video.pixel_height.value());
EXPECT_FALSE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(0, video.pixel_crop_bottom.value());
EXPECT_FALSE(video.pixel_crop_top.is_present());
EXPECT_EQ(0, video.pixel_crop_top.value());
EXPECT_FALSE(video.pixel_crop_left.is_present());
EXPECT_EQ(0, video.pixel_crop_left.value());
EXPECT_FALSE(video.pixel_crop_right.is_present());
EXPECT_EQ(0, video.pixel_crop_right.value());
EXPECT_FALSE(video.display_width.is_present());
EXPECT_EQ(video.pixel_width.value(), video.display_width.value());
EXPECT_FALSE(video.display_height.is_present());
EXPECT_EQ(video.pixel_height.value(), video.display_height.value());
EXPECT_FALSE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kPixels, video.display_unit.value());
EXPECT_FALSE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kFreeResizing, video.aspect_ratio_type.value());
EXPECT_FALSE(video.frame_rate.is_present());
EXPECT_EQ(0, video.frame_rate.value());
EXPECT_FALSE(video.colour.is_present());
EXPECT_EQ(Colour{}, video.colour.value());
}
TEST_F(VideoParserTest, DefaultValues) {
SetReaderData({
0x9A, // ID = 0x9A (FlagInterlaced).
0x20, 0x00, 0x00, // Size = 0.
0x53, 0xB8, // ID = 0x53B8 (StereoMode).
0x20, 0x00, 0x00, // Size = 0.
0x53, 0xC0, // ID = 0x53C0 (AlphaMode).
0x20, 0x00, 0x00, // Size = 0.
0xB0, // ID = 0xB0 (PixelWidth).
0x20, 0x00, 0x00, // Size = 0.
0xBA, // ID = 0xBA (PixelHeight).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xAA, // ID = 0x54AA (PixelCropBottom).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xBB, // ID = 0x54BB (PixelCropTop).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xCC, // ID = 0x54CC (PixelCropLeft).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xDD, // ID = 0x54DD (PixelCropRight).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xB0, // ID = 0x54B0 (DisplayWidth).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xBA, // ID = 0x54BA (DisplayHeight).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xB2, // ID = 0x54B2 (DisplayUnit).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xB3, // ID = 0x54B3 (AspectRatioType).
0x20, 0x00, 0x00, // Size = 0.
0x23, 0x83, 0xE3, // ID = 0x2383E3 (FrameRate).
0x80, // Size = 0.
0x55, 0xB0, // ID = 0x55B0 (Colour).
0x20, 0x00, 0x00, // Size = 0.
});
ParseAndVerify();
const Video video = parser_.value();
EXPECT_TRUE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kUnspecified, video.interlaced.value());
EXPECT_TRUE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kMono, video.stereo_mode.value());
EXPECT_TRUE(video.alpha_mode.is_present());
EXPECT_EQ(0, video.alpha_mode.value());
EXPECT_TRUE(video.pixel_width.is_present());
EXPECT_EQ(0, video.pixel_width.value());
EXPECT_TRUE(video.pixel_height.is_present());
EXPECT_EQ(0, video.pixel_height.value());
EXPECT_TRUE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(0, video.pixel_crop_bottom.value());
EXPECT_TRUE(video.pixel_crop_top.is_present());
EXPECT_EQ(0, video.pixel_crop_top.value());
EXPECT_TRUE(video.pixel_crop_left.is_present());
EXPECT_EQ(0, video.pixel_crop_left.value());
EXPECT_TRUE(video.pixel_crop_right.is_present());
EXPECT_EQ(0, video.pixel_crop_right.value());
EXPECT_TRUE(video.display_width.is_present());
EXPECT_EQ(video.pixel_width.value(), video.display_width.value());
EXPECT_TRUE(video.display_height.is_present());
EXPECT_EQ(video.pixel_height.value(), video.display_height.value());
EXPECT_TRUE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kPixels, video.display_unit.value());
EXPECT_TRUE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kFreeResizing, video.aspect_ratio_type.value());
EXPECT_TRUE(video.frame_rate.is_present());
EXPECT_EQ(0, video.frame_rate.value());
EXPECT_TRUE(video.colour.is_present());
EXPECT_EQ(Colour{}, video.colour.value());
}
TEST_F(VideoParserTest, CustomValues) {
SetReaderData({
0x9A, // ID = 0x9A (FlagInterlaced).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = progressive).
0x53, 0xB8, // ID = 0x53B8 (StereoMode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = top-bottom (right eye first)).
0x53, 0xC0, // ID = 0x53C0 (AlphaMode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x03, // Body (value = 3).
0xB0, // ID = 0xB0 (PixelWidth).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x04, // Body (value = 4).
0xBA, // ID = 0xBA (PixelHeight).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x05, // Body (value = 5).
0x54, 0xAA, // ID = 0x54AA (PixelCropBottom).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x06, // Body (value = 6).
0x54, 0xBB, // ID = 0x54BB (PixelCropTop).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x07, // Body (value = 7).
0x54, 0xCC, // ID = 0x54CC (PixelCropLeft).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x08, // Body (value = 8).
0x54, 0xDD, // ID = 0x54DD (PixelCropRight).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x09, // Body (value = 9).
0x54, 0xB0, // ID = 0x54B0 (DisplayWidth).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x0A, // Body (value = 10).
0x54, 0xBA, // ID = 0x54BA (DisplayHeight).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x0B, // Body (value = 11).
0x54, 0xB2, // ID = 0x54B2 (DisplayUnit).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = inches).
0x54, 0xB3, // ID = 0x54B3 (AspectRatioType).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = keep aspect ratio).
0x23, 0x83, 0xE3, // ID = 0x2383E3 (FrameRate).
0x84, // Size = 4.
0x40, 0x0F, 0x1B, 0xBD, // Body (value = 2.2360680103302001953125f).
0x55, 0xB0, // ID = 0x55B0 (Colour).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x55, 0xB2, // ID = 0x55B2 (BitsPerChannel).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
ParseAndVerify();
const Video video = parser_.value();
EXPECT_TRUE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kProgressive, video.interlaced.value());
EXPECT_TRUE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kTopBottomRightFirst, video.stereo_mode.value());
EXPECT_TRUE(video.alpha_mode.is_present());
EXPECT_EQ(3, video.alpha_mode.value());
EXPECT_TRUE(video.pixel_width.is_present());
EXPECT_EQ(4, video.pixel_width.value());
EXPECT_TRUE(video.pixel_height.is_present());
EXPECT_EQ(5, video.pixel_height.value());
EXPECT_TRUE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(6, video.pixel_crop_bottom.value());
EXPECT_TRUE(video.pixel_crop_top.is_present());
EXPECT_EQ(7, video.pixel_crop_top.value());
EXPECT_TRUE(video.pixel_crop_left.is_present());
EXPECT_EQ(8, video.pixel_crop_left.value());
EXPECT_TRUE(video.pixel_crop_right.is_present());
EXPECT_EQ(9, video.pixel_crop_right.value());
EXPECT_TRUE(video.display_width.is_present());
EXPECT_EQ(10, video.display_width.value());
EXPECT_TRUE(video.display_height.is_present());
EXPECT_EQ(11, video.display_height.value());
EXPECT_TRUE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kInches, video.display_unit.value());
EXPECT_TRUE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kKeep, video.aspect_ratio_type.value());
EXPECT_TRUE(video.frame_rate.is_present());
EXPECT_EQ(2.2360680103302001953125, video.frame_rate.value());
EXPECT_TRUE(video.colour.is_present());
EXPECT_TRUE(video.colour.value().bits_per_channel.is_present());
EXPECT_EQ(1, video.colour.value().bits_per_channel.value());
}
TEST_F(VideoParserTest, AbsentDisplaySize) {
SetReaderData({
0xB0, // ID = 0xB0 (PixelWidth).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xBA, // ID = 0xBA (PixelHeight).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
const Video video = parser_.value();
EXPECT_FALSE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kUnspecified, video.interlaced.value());
EXPECT_FALSE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kMono, video.stereo_mode.value());
EXPECT_FALSE(video.alpha_mode.is_present());
EXPECT_EQ(0, video.alpha_mode.value());
EXPECT_TRUE(video.pixel_width.is_present());
EXPECT_EQ(1, video.pixel_width.value());
EXPECT_TRUE(video.pixel_height.is_present());
EXPECT_EQ(2, video.pixel_height.value());
EXPECT_FALSE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(0, video.pixel_crop_bottom.value());
EXPECT_FALSE(video.pixel_crop_top.is_present());
EXPECT_EQ(0, video.pixel_crop_top.value());
EXPECT_FALSE(video.pixel_crop_left.is_present());
EXPECT_EQ(0, video.pixel_crop_left.value());
EXPECT_FALSE(video.pixel_crop_right.is_present());
EXPECT_EQ(0, video.pixel_crop_right.value());
EXPECT_FALSE(video.display_width.is_present());
EXPECT_EQ(1, video.display_width.value());
EXPECT_FALSE(video.display_height.is_present());
EXPECT_EQ(2, video.display_height.value());
EXPECT_FALSE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kPixels, video.display_unit.value());
EXPECT_FALSE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kFreeResizing, video.aspect_ratio_type.value());
EXPECT_FALSE(video.frame_rate.is_present());
EXPECT_EQ(0, video.frame_rate.value());
EXPECT_FALSE(video.colour.is_present());
EXPECT_EQ(Colour{}, video.colour.value());
}
TEST_F(VideoParserTest, DefaultDisplaySize) {
SetReaderData({
0xB0, // ID = 0xB0 (PixelWidth).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xBA, // ID = 0xBA (PixelHeight).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x54, 0xB0, // ID = 0x54B0 (DisplayWidth).
0x40, 0x00, // Size = 0.
0x54, 0xBA, // ID = 0x54BA (DisplayHeight).
0x40, 0x00, // Size = 0.
});
ParseAndVerify();
const Video video = parser_.value();
EXPECT_FALSE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kUnspecified, video.interlaced.value());
EXPECT_FALSE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kMono, video.stereo_mode.value());
EXPECT_FALSE(video.alpha_mode.is_present());
EXPECT_EQ(0, video.alpha_mode.value());
EXPECT_TRUE(video.pixel_width.is_present());
EXPECT_EQ(1, video.pixel_width.value());
EXPECT_TRUE(video.pixel_height.is_present());
EXPECT_EQ(2, video.pixel_height.value());
EXPECT_FALSE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(0, video.pixel_crop_bottom.value());
EXPECT_FALSE(video.pixel_crop_top.is_present());
EXPECT_EQ(0, video.pixel_crop_top.value());
EXPECT_FALSE(video.pixel_crop_left.is_present());
EXPECT_EQ(0, video.pixel_crop_left.value());
EXPECT_FALSE(video.pixel_crop_right.is_present());
EXPECT_EQ(0, video.pixel_crop_right.value());
EXPECT_TRUE(video.display_width.is_present());
EXPECT_EQ(1, video.display_width.value());
EXPECT_TRUE(video.display_height.is_present());
EXPECT_EQ(2, video.display_height.value());
EXPECT_FALSE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kPixels, video.display_unit.value());
EXPECT_FALSE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kFreeResizing, video.aspect_ratio_type.value());
EXPECT_FALSE(video.frame_rate.is_present());
EXPECT_EQ(0, video.frame_rate.value());
EXPECT_FALSE(video.colour.is_present());
EXPECT_EQ(Colour{}, video.colour.value());
}
} // namespace

View File

@@ -0,0 +1,74 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/virtual_block_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::Id;
using webm::kUnknownElementSize;
using webm::Status;
using webm::VirtualBlock;
using webm::VirtualBlockParser;
namespace {
class VirtualBlockParserTest
: public ElementParserTest<VirtualBlockParser, Id::kBlockVirtual> {};
TEST_F(VirtualBlockParserTest, InvalidSize) {
TestInit(3, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(VirtualBlockParserTest, InvalidBlock) {
SetReaderData({
0x40, 0x01, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags.
});
// Initialize with 1 byte short.
ParseAndExpectResult(Status::kInvalidElementValue, reader_.size() - 1);
}
TEST_F(VirtualBlockParserTest, ValidBlock) {
SetReaderData({
0x81, // Track number = 1.
0x12, 0x34, // Timecode = 4660.
0x00, // Flags.
});
ParseAndVerify();
const VirtualBlock virtual_block = parser_.value();
EXPECT_EQ(1, virtual_block.track_number);
EXPECT_EQ(0x1234, virtual_block.timecode);
}
TEST_F(VirtualBlockParserTest, IncrementalParse) {
SetReaderData({
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // Track number = 2.
0xFF, 0xFE, // Timecode = -2.
0x00, // Flags.
});
IncrementalParseAndVerify();
const VirtualBlock virtual_block = parser_.value();
EXPECT_EQ(2, virtual_block.track_number);
EXPECT_EQ(-2, virtual_block.timecode);
}
} // namespace

View File

@@ -0,0 +1,56 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/void_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::NotNull;
using webm::ElementParserTest;
using webm::Id;
using webm::kUnknownElementSize;
using webm::Status;
using webm::VoidParser;
namespace {
class VoidParserTest : public ElementParserTest<VoidParser, Id::kVoid> {};
TEST_F(VoidParserTest, InvalidSize) {
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(VoidParserTest, Empty) {
EXPECT_CALL(callback_, OnVoid(metadata_, NotNull(), NotNull())).Times(1);
ParseAndVerify();
}
TEST_F(VoidParserTest, Valid) {
SetReaderData({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07});
EXPECT_CALL(callback_, OnVoid(metadata_, NotNull(), NotNull())).Times(1);
ParseAndVerify();
}
TEST_F(VoidParserTest, IncrementalParse) {
SetReaderData({0x00, 0x01, 0x02, 0x03});
EXPECT_CALL(callback_, OnVoid(metadata_, NotNull(), NotNull())).Times(4);
IncrementalParseAndVerify();
}
} // namespace

View File

@@ -0,0 +1,293 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/webm_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/mock_callback.h"
#include "webm/buffer_reader.h"
#include "webm/status.h"
using testing::_;
using testing::DoDefault;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using webm::BufferReader;
using webm::Ebml;
using webm::ElementMetadata;
using webm::Id;
using webm::Info;
using webm::kUnknownElementPosition;
using webm::kUnknownElementSize;
using webm::kUnknownHeaderSize;
using webm::MockCallback;
using webm::Status;
using webm::WebmParser;
namespace {
class WebmParserTest : public testing::Test {};
TEST_F(WebmParserTest, InvalidId) {
BufferReader reader = {
0x00, // IDs cannot start with 0x00.
};
MockCallback callback;
{
InSequence dummy;
EXPECT_CALL(callback, OnEbml(_, _)).Times(0);
EXPECT_CALL(callback, OnSegmentBegin(_, NotNull())).Times(0);
EXPECT_CALL(callback, OnSegmentEnd(_)).Times(0);
}
WebmParser parser;
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kInvalidElementId, status.code);
}
TEST_F(WebmParserTest, InvalidSize) {
BufferReader reader = {
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x00, // Size must have 1+ bits set in the first byte.
};
MockCallback callback;
{
InSequence dummy;
EXPECT_CALL(callback, OnEbml(_, _)).Times(0);
EXPECT_CALL(callback, OnSegmentBegin(_, NotNull())).Times(0);
EXPECT_CALL(callback, OnSegmentEnd(_)).Times(0);
}
WebmParser parser;
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kInvalidElementSize, status.code);
}
TEST_F(WebmParserTest, DefaultParse) {
BufferReader reader = {
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x80, // Size = 0.
0x18, 0x53, 0x80, 0x67, // ID = 0x18538067 (Segment).
0x80, // Size = 0.
};
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kEbml, 5, 0, 0};
const Ebml ebml{};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnEbml(metadata, ebml)).Times(1);
metadata = {Id::kSegment, 5, 0, 5};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnSegmentBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnSegmentEnd(metadata)).Times(1);
}
WebmParser parser;
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
}
TEST_F(WebmParserTest, SeekEbml) {
BufferReader reader = {
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x87, // Size = 7.
0x42, 0x86, // ID = 0x4286 (EBMLVersion).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
};
std::uint64_t num_to_skip = 5; // Skip the starting EBML element metadata.
std::uint64_t num_actually_skipped = 0;
reader.Skip(num_to_skip, &num_actually_skipped);
EXPECT_EQ(num_to_skip, num_actually_skipped);
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kEbmlVersion, 6, 1, num_to_skip};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kEbml, kUnknownHeaderSize, kUnknownElementSize,
kUnknownElementPosition};
Ebml ebml{};
ebml.ebml_version.Set(2, true);
EXPECT_CALL(callback, OnEbml(metadata, ebml)).Times(1);
}
WebmParser parser;
parser.DidSeek();
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
TEST_F(WebmParserTest, SeekSegment) {
BufferReader reader = {
0x18, 0x53, 0x80, 0x67, // ID = 0x18538067 (Segment).
0x85, // Size = 5.
0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
0x80, // Size = 0.
};
std::uint64_t num_to_skip = 5; // Skip the starting Segment element metadata.
std::uint64_t num_actually_skipped = 0;
reader.Skip(num_to_skip, &num_actually_skipped);
EXPECT_EQ(num_to_skip, num_actually_skipped);
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kInfo, 5, 0, num_to_skip};
const Info info{};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnInfo(metadata, info)).Times(1);
metadata = {Id::kSegment, kUnknownHeaderSize, kUnknownElementSize,
kUnknownElementPosition};
EXPECT_CALL(callback, OnSegmentEnd(metadata)).Times(1);
}
WebmParser parser;
parser.DidSeek();
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
TEST_F(WebmParserTest, SeekVoid) {
BufferReader reader = {
0xEC, // ID = 0xEC (Void).
0x81, // Size = 0.
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x80, // Size = 0.
};
std::uint64_t num_to_skip = 2; // Skip the first Void element.
std::uint64_t num_actually_skipped = 0;
reader.Skip(num_to_skip, &num_actually_skipped);
EXPECT_EQ(num_to_skip, num_actually_skipped);
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kVoid, 2, 1, num_to_skip};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnVoid(metadata, &reader, NotNull())).Times(1);
metadata = {Id::kEbml, 5, 0, 5};
const Ebml ebml{};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnEbml(metadata, ebml)).Times(1);
}
WebmParser parser;
parser.DidSeek();
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
TEST_F(WebmParserTest, SwapAfterFailedParse) {
BufferReader reader = {
0x00, // Invalid ID.
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
};
MockCallback expect_nothing;
EXPECT_CALL(expect_nothing, OnElementBegin(_, _)).Times(0);
MockCallback expect_void;
{
InSequence dummy;
ElementMetadata metadata = {Id::kVoid, 2, 1, 1};
EXPECT_CALL(expect_void, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(expect_void, OnVoid(metadata, &reader, NotNull())).Times(1);
}
WebmParser parser1;
Status status = parser1.Feed(&expect_nothing, &reader);
EXPECT_EQ(Status::kInvalidElementId, status.code);
EXPECT_EQ(1, reader.Position());
// After swapping, the parser should retain its failed state and not consume
// more data.
WebmParser parser2;
parser2.Swap(&parser1);
status = parser2.Feed(&expect_nothing, &reader);
EXPECT_EQ(Status::kInvalidElementId, status.code);
EXPECT_EQ(1, reader.Position());
// parser1 should be a fresh/new parser after the swap, so parsing should
// succeed.
status = parser1.Feed(&expect_void, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
TEST_F(WebmParserTest, Swap) {
BufferReader reader = {
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x80, // Size = 0.
};
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kVoid, 2, 1, 0};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnVoid(metadata, &reader, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoDefault());
metadata = {Id::kEbml, 5, 0, 3};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnEbml(metadata, Ebml{})).Times(1);
}
WebmParser parser1;
Status status = parser1.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkPartial, status.code);
WebmParser parser2;
swap(parser1, parser2);
status = parser2.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
} // namespace