Initial release
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
// 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.
|
||||
#ifndef TEST_UTILS_ELEMENT_PARSER_TEST_H_
|
||||
#define TEST_UTILS_ELEMENT_PARSER_TEST_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "test_utils/limited_reader.h"
|
||||
#include "test_utils/parser_test.h"
|
||||
#include "webm/buffer_reader.h"
|
||||
#include "webm/reader.h"
|
||||
#include "webm/status.h"
|
||||
|
||||
namespace webm {
|
||||
|
||||
// Base class for unit tests that test an instance of the ElementParser
|
||||
// inteface. The template parameter T is the parser class being tested, and the
|
||||
// optional id is the element ID associated with elements from the parser.
|
||||
template <typename T, Id id = static_cast<Id>(0)>
|
||||
class ElementParserTest : public ParserTest<T> {
|
||||
public:
|
||||
// Sets the reader's internal buffer to the given buffer and metadata_ to
|
||||
// data.size().
|
||||
void SetReaderData(std::vector<std::uint8_t> data) override {
|
||||
metadata_.size = data.size();
|
||||
ParserTest<T>::SetReaderData(std::move(data));
|
||||
}
|
||||
|
||||
// Sets metadata_.size to size and then calls Init() on the parser, ensuring
|
||||
// that it returns the expected status code.
|
||||
void TestInit(std::uint64_t size, Status::Code expected) {
|
||||
metadata_.size = size;
|
||||
const Status status = parser_.Init(metadata_, metadata_.size);
|
||||
ASSERT_EQ(expected, status.code);
|
||||
}
|
||||
|
||||
// Similar to the base class implementation, but with the difference that
|
||||
// Init() is also called (after setting metadata_.size to size).
|
||||
void ParseAndVerify(std::uint64_t size) override {
|
||||
TestInit(size, Status::kOkCompleted);
|
||||
|
||||
std::uint64_t num_bytes_read = 0;
|
||||
const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
|
||||
ASSERT_EQ(Status::kOkCompleted, status.code);
|
||||
|
||||
if (size != kUnknownElementSize) {
|
||||
ASSERT_EQ(size, num_bytes_read);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseAndVerify() override { ParseAndVerify(metadata_.size); }
|
||||
|
||||
void IncrementalParseAndVerify() override {
|
||||
TestInit(metadata_.size, Status::kOkCompleted);
|
||||
|
||||
webm::LimitedReader limited_reader(
|
||||
std::unique_ptr<webm::Reader>(new BufferReader(std::move(reader_))));
|
||||
|
||||
Status status;
|
||||
std::uint64_t num_bytes_read = 0;
|
||||
do {
|
||||
limited_reader.set_total_read_skip_limit(1);
|
||||
std::uint64_t local_num_bytes_read = 0;
|
||||
status = parser_.Feed(&callback_, &limited_reader, &local_num_bytes_read);
|
||||
num_bytes_read += local_num_bytes_read;
|
||||
ASSERT_GE(static_cast<std::uint64_t>(1), local_num_bytes_read);
|
||||
} while (status.code == Status::kWouldBlock ||
|
||||
status.code == Status::kOkPartial);
|
||||
|
||||
ASSERT_EQ(Status::kOkCompleted, status.code);
|
||||
|
||||
if (metadata_.size != kUnknownElementSize) {
|
||||
ASSERT_EQ(metadata_.size, num_bytes_read);
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes the parser (after setting metadata_.size to size), ensures it
|
||||
// succeeds, and then calls Feed() on the parser, making sure it returns the
|
||||
// expected status code.
|
||||
void ParseAndExpectResult(Status::Code expected, std::uint64_t size) {
|
||||
TestInit(size, Status::kOkCompleted);
|
||||
|
||||
std::uint64_t num_bytes_read = 0;
|
||||
const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
|
||||
ASSERT_EQ(expected, status.code);
|
||||
}
|
||||
|
||||
// Initializes the parser, ensures it succeeds, and then calls Feed() on the
|
||||
// parser, making sure it returns the expected status code.
|
||||
void ParseAndExpectResult(Status::Code expected) override {
|
||||
ParseAndExpectResult(expected, metadata_.size);
|
||||
}
|
||||
|
||||
protected:
|
||||
using ParserTest<T>::callback_;
|
||||
using ParserTest<T>::parser_;
|
||||
using ParserTest<T>::reader_;
|
||||
|
||||
// Element metadata associated with the element parsed by parser_. This is
|
||||
// passed to Init() when initializing the parser.
|
||||
ElementMetadata metadata_ = {id, 0, 0, 0};
|
||||
};
|
||||
|
||||
} // namespace webm
|
||||
|
||||
#endif // TEST_UTILS_ELEMENT_PARSER_TEST_H_
|
||||
@@ -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 "test_utils/limited_reader.h"
|
||||
|
||||
namespace webm {
|
||||
|
||||
LimitedReader::LimitedReader(std::unique_ptr<Reader> impl)
|
||||
: impl_(std::move(impl)) {}
|
||||
|
||||
Status LimitedReader::Read(std::size_t num_to_read, std::uint8_t* buffer,
|
||||
std::uint64_t* num_actually_read) {
|
||||
assert(num_to_read > 0);
|
||||
assert(buffer != nullptr);
|
||||
assert(num_actually_read != nullptr);
|
||||
|
||||
*num_actually_read = 0;
|
||||
std::size_t expected = num_to_read;
|
||||
|
||||
num_to_read = std::min({num_to_read, single_read_limit_, total_read_limit_});
|
||||
|
||||
// Handle total_read_skip_limit_ separately since std::size_t can be
|
||||
// smaller than std::uint64_t.
|
||||
if (num_to_read > total_read_skip_limit_) {
|
||||
num_to_read = static_cast<std::size_t>(total_read_skip_limit_);
|
||||
}
|
||||
|
||||
if (num_to_read == 0) {
|
||||
return return_status_when_blocked_;
|
||||
}
|
||||
|
||||
Status status = impl_->Read(num_to_read, buffer, num_actually_read);
|
||||
assert(*num_actually_read <= num_to_read);
|
||||
|
||||
if (status.code == Status::kOkCompleted && *num_actually_read < expected) {
|
||||
status.code = Status::kOkPartial;
|
||||
}
|
||||
|
||||
if (total_read_limit_ != std::numeric_limits<std::size_t>::max()) {
|
||||
total_read_limit_ -= static_cast<std::size_t>(*num_actually_read);
|
||||
}
|
||||
|
||||
if (total_read_skip_limit_ != std::numeric_limits<std::uint64_t>::max()) {
|
||||
total_read_skip_limit_ -= *num_actually_read;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Status LimitedReader::Skip(std::uint64_t num_to_skip,
|
||||
std::uint64_t* num_actually_skipped) {
|
||||
assert(num_to_skip > 0);
|
||||
assert(num_actually_skipped != nullptr);
|
||||
|
||||
*num_actually_skipped = 0;
|
||||
std::uint64_t expected = num_to_skip;
|
||||
|
||||
num_to_skip = std::min({num_to_skip, single_skip_limit_, total_skip_limit_,
|
||||
total_read_skip_limit_});
|
||||
|
||||
if (num_to_skip == 0) {
|
||||
return return_status_when_blocked_;
|
||||
}
|
||||
|
||||
Status status = impl_->Skip(num_to_skip, num_actually_skipped);
|
||||
assert(*num_actually_skipped <= num_to_skip);
|
||||
|
||||
if (status.code == Status::kOkCompleted && *num_actually_skipped < expected) {
|
||||
status.code = Status::kOkPartial;
|
||||
}
|
||||
|
||||
if (total_skip_limit_ != std::numeric_limits<std::uint64_t>::max()) {
|
||||
total_skip_limit_ -= *num_actually_skipped;
|
||||
}
|
||||
|
||||
if (total_read_skip_limit_ != std::numeric_limits<std::uint64_t>::max()) {
|
||||
total_read_skip_limit_ -= *num_actually_skipped;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
std::uint64_t LimitedReader::Position() const { return impl_->Position(); }
|
||||
|
||||
void LimitedReader::set_return_status_when_blocked(Status status) {
|
||||
return_status_when_blocked_ = status;
|
||||
}
|
||||
|
||||
void LimitedReader::set_single_read_limit(std::size_t max_num_bytes) {
|
||||
single_read_limit_ = max_num_bytes;
|
||||
}
|
||||
|
||||
void LimitedReader::set_single_skip_limit(std::uint64_t max_num_bytes) {
|
||||
single_skip_limit_ = max_num_bytes;
|
||||
}
|
||||
|
||||
void LimitedReader::set_total_read_limit(std::size_t max_num_bytes) {
|
||||
total_read_limit_ = max_num_bytes;
|
||||
}
|
||||
|
||||
void LimitedReader::set_total_skip_limit(std::uint64_t max_num_bytes) {
|
||||
total_skip_limit_ = max_num_bytes;
|
||||
}
|
||||
|
||||
void LimitedReader::set_total_read_skip_limit(std::uint64_t max_num_bytes) {
|
||||
total_read_skip_limit_ = max_num_bytes;
|
||||
}
|
||||
|
||||
} // namespace webm
|
||||
@@ -0,0 +1,115 @@
|
||||
// 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.
|
||||
#ifndef TEST_UTILS_LIMITED_READER_H_
|
||||
#define TEST_UTILS_LIMITED_READER_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#include "webm/reader.h"
|
||||
#include "webm/status.h"
|
||||
|
||||
namespace webm {
|
||||
|
||||
// An adapter that uses an underlying reader to read data, but with added
|
||||
// limitations on how much data can be read/skipped. Its primary use is for
|
||||
// testing APIs that consume a reader to make sure they gracefully handle
|
||||
// arbitrary reading failures.
|
||||
class LimitedReader : public Reader {
|
||||
public:
|
||||
LimitedReader() = delete;
|
||||
LimitedReader(const LimitedReader&) = delete;
|
||||
LimitedReader& operator=(const LimitedReader&) = delete;
|
||||
|
||||
LimitedReader(LimitedReader&&) = default;
|
||||
LimitedReader& operator=(LimitedReader&&) = default;
|
||||
|
||||
explicit LimitedReader(std::unique_ptr<Reader> impl);
|
||||
|
||||
// Reads data using the internal reader, but limits the number of bytes that
|
||||
// can be read based on the settings of this LimitedReader. If this reader has
|
||||
// reached its cap of maximum number of bytes allowed to be read, the chosen
|
||||
// status will be returned.
|
||||
Status Read(std::size_t num_to_read, std::uint8_t* buffer,
|
||||
std::uint64_t* num_actually_read) override;
|
||||
|
||||
// Skips data using the internal reader, but limits the number of bytes that
|
||||
// can be skipped based on the settings of this LimitedReader. If this reader
|
||||
// has reached its cap of maximum number of bytes allowed to be skipped, the
|
||||
// chosen status will be returned.
|
||||
Status Skip(std::uint64_t num_to_skip,
|
||||
std::uint64_t* num_actually_skipped) override;
|
||||
|
||||
std::uint64_t Position() const override;
|
||||
|
||||
// Sets the status that should be returned when the reader reaches its cap of
|
||||
// maximum number of bytes that can be read/skipped and cannot read/skip any
|
||||
// more bytes. By default, this reader will return Status::kWouldBlock when
|
||||
// this maximum limit is hit.
|
||||
void set_return_status_when_blocked(Status status);
|
||||
|
||||
// Sets the total number of bytes that can be read in a single call to Read.
|
||||
void set_single_read_limit(std::size_t max_num_bytes);
|
||||
|
||||
// Sets the total number of bytes that can be skipped in a single call to
|
||||
// Skip.
|
||||
void set_single_skip_limit(std::uint64_t max_num_bytes);
|
||||
|
||||
// Sets the total number of bytes that can be read by the reader with Read.
|
||||
// This total is considered to be cumulative for reads, but not skips.
|
||||
// Setting this to std::numeric_limits<std::size_t>::max() will result in no
|
||||
// extra limitation being imposed on reads.
|
||||
void set_total_read_limit(std::size_t max_num_bytes);
|
||||
|
||||
// Sets the total number of bytes that can be skipped by the reader with Skip.
|
||||
// This total is considered to be cumulative for skips, but not reads.
|
||||
// Setting this to std::numeric_limits<std::uint64_t>::max() will result in no
|
||||
// extra limitation being imposed on skips.
|
||||
void set_total_skip_limit(std::uint64_t max_num_bytes);
|
||||
|
||||
// Sets the total number of bytes that can be read/skipped by the reader.
|
||||
// This total is considered to be cumulative between reads and skips.
|
||||
// Setting this to std::numeric_limits<std::uint64_t>::max() will result in no
|
||||
// extra limitation being imposed on reads/skips.
|
||||
void set_total_read_skip_limit(std::uint64_t max_num_bytes);
|
||||
|
||||
private:
|
||||
// The maximum number of bytes to let a single call to Read return.
|
||||
std::size_t single_read_limit_ = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
// The maximum number of bytes to let a single call to Skip return.
|
||||
std::uint64_t single_skip_limit_ = std::numeric_limits<std::uint64_t>::max();
|
||||
|
||||
// The total maximum number of bytes that can be read with multiple calls to
|
||||
// Read.
|
||||
std::size_t total_read_limit_ = std::numeric_limits<std::size_t>::max();
|
||||
|
||||
// The total maximum number of bytes that can be skipped with multiple calls
|
||||
// to Skip.
|
||||
std::uint64_t total_skip_limit_ = std::numeric_limits<std::uint64_t>::max();
|
||||
|
||||
// The total maximum number of bytes that can be read or skipped with multiple
|
||||
// calls to Read and/or Skip.
|
||||
std::uint64_t total_read_skip_limit_ =
|
||||
std::numeric_limits<std::uint64_t>::max();
|
||||
|
||||
// The status to return when the reader has reached is maximum limit for
|
||||
// Read/Skip and cannot read or skip any data.
|
||||
Status return_status_when_blocked_ = Status(Status::kWouldBlock);
|
||||
|
||||
// The actual reader that does the real reading/skipping.
|
||||
std::unique_ptr<Reader> impl_;
|
||||
};
|
||||
|
||||
} // namespace webm
|
||||
|
||||
#endif // TEST_UTILS_LIMITED_READER_H_
|
||||
@@ -0,0 +1,247 @@
|
||||
// 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.
|
||||
#ifndef TEST_UTILS_MOCK_CALLBACK_H_
|
||||
#define TEST_UTILS_MOCK_CALLBACK_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include "webm/callback.h"
|
||||
#include "webm/dom_types.h"
|
||||
#include "webm/reader.h"
|
||||
#include "webm/status.h"
|
||||
|
||||
namespace webm {
|
||||
|
||||
// A simple version of Callback that can be used with Google Mock. By default,
|
||||
// the mocked methods will call through to the corresponding Callback methods.
|
||||
class MockCallback : public Callback {
|
||||
public:
|
||||
MockCallback() {
|
||||
using testing::_;
|
||||
using testing::Invoke;
|
||||
|
||||
ON_CALL(*this, OnElementBegin(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnElementBeginConcrete));
|
||||
ON_CALL(*this, OnUnknownElement(_, _, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnUnknownElementConcrete));
|
||||
ON_CALL(*this, OnEbml(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnEbmlConcrete));
|
||||
ON_CALL(*this, OnVoid(_, _, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnVoidConcrete));
|
||||
ON_CALL(*this, OnSegmentBegin(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnSegmentBeginConcrete));
|
||||
ON_CALL(*this, OnSeek(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnSeekConcrete));
|
||||
ON_CALL(*this, OnInfo(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnInfoConcrete));
|
||||
ON_CALL(*this, OnClusterBegin(_, _, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnClusterBeginConcrete));
|
||||
ON_CALL(*this, OnSimpleBlockBegin(_, _, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnSimpleBlockBeginConcrete));
|
||||
ON_CALL(*this, OnSimpleBlockEnd(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnSimpleBlockEndConcrete));
|
||||
ON_CALL(*this, OnBlockGroupBegin(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnBlockGroupBeginConcrete));
|
||||
ON_CALL(*this, OnBlockBegin(_, _, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnBlockBeginConcrete));
|
||||
ON_CALL(*this, OnBlockEnd(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnBlockEndConcrete));
|
||||
ON_CALL(*this, OnBlockGroupEnd(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnBlockGroupEndConcrete));
|
||||
ON_CALL(*this, OnFrame(_, _, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnFrameConcrete));
|
||||
ON_CALL(*this, OnClusterEnd(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnClusterEndConcrete));
|
||||
ON_CALL(*this, OnTrackEntry(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnTrackEntryConcrete));
|
||||
ON_CALL(*this, OnCuePoint(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnCuePointConcrete));
|
||||
ON_CALL(*this, OnEditionEntry(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnEditionEntryConcrete));
|
||||
ON_CALL(*this, OnTag(_, _))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnTagConcrete));
|
||||
ON_CALL(*this, OnSegmentEnd(_))
|
||||
.WillByDefault(Invoke(this, &MockCallback::OnSegmentEndConcrete));
|
||||
}
|
||||
|
||||
// Mocks for methods from Callback.
|
||||
MOCK_METHOD2(OnElementBegin,
|
||||
Status(const ElementMetadata& metadata, Action* action));
|
||||
|
||||
MOCK_METHOD3(OnUnknownElement,
|
||||
Status(const ElementMetadata& metadata, Reader* reader,
|
||||
std::uint64_t* bytes_remaining));
|
||||
|
||||
MOCK_METHOD2(OnEbml,
|
||||
Status(const ElementMetadata& metadata, const Ebml& ebml));
|
||||
|
||||
MOCK_METHOD3(OnVoid, Status(const ElementMetadata& metadata, Reader* reader,
|
||||
std::uint64_t* bytes_remaining));
|
||||
|
||||
MOCK_METHOD2(OnSegmentBegin,
|
||||
Status(const ElementMetadata& metadata, Action* action));
|
||||
|
||||
MOCK_METHOD2(OnSeek,
|
||||
Status(const ElementMetadata& metadata, const Seek& seek));
|
||||
|
||||
MOCK_METHOD2(OnInfo,
|
||||
Status(const ElementMetadata& metadata, const Info& info));
|
||||
|
||||
MOCK_METHOD3(OnClusterBegin, Status(const ElementMetadata& metadata,
|
||||
const Cluster& cluster, Action* action));
|
||||
|
||||
MOCK_METHOD3(OnSimpleBlockBegin,
|
||||
Status(const ElementMetadata& metadata,
|
||||
const SimpleBlock& simple_block, Action* action));
|
||||
|
||||
MOCK_METHOD2(OnSimpleBlockEnd, Status(const ElementMetadata& metadata,
|
||||
const SimpleBlock& simple_block));
|
||||
|
||||
MOCK_METHOD2(OnBlockGroupBegin,
|
||||
Status(const ElementMetadata& metadata, Action* action));
|
||||
|
||||
MOCK_METHOD3(OnBlockBegin, Status(const ElementMetadata& metadata,
|
||||
const Block& block, Action* action));
|
||||
|
||||
MOCK_METHOD2(OnBlockEnd,
|
||||
Status(const ElementMetadata& metadata, const Block& block));
|
||||
|
||||
MOCK_METHOD2(OnBlockGroupEnd, Status(const ElementMetadata& metadata,
|
||||
const BlockGroup& block_group));
|
||||
|
||||
MOCK_METHOD3(OnFrame, Status(const FrameMetadata& metadata, Reader* reader,
|
||||
std::uint64_t* bytes_remaining));
|
||||
|
||||
MOCK_METHOD2(OnClusterEnd,
|
||||
Status(const ElementMetadata& metadata, const Cluster& cluster));
|
||||
|
||||
MOCK_METHOD2(OnTrackEntry, Status(const ElementMetadata& metadata,
|
||||
const TrackEntry& track_entry));
|
||||
|
||||
MOCK_METHOD2(OnCuePoint, Status(const ElementMetadata& metadata,
|
||||
const CuePoint& cue_point));
|
||||
|
||||
MOCK_METHOD2(OnEditionEntry, Status(const ElementMetadata& metadata,
|
||||
const EditionEntry& edition_entry));
|
||||
|
||||
MOCK_METHOD2(OnTag, Status(const ElementMetadata& metadata, const Tag& tag));
|
||||
|
||||
MOCK_METHOD1(OnSegmentEnd, Status(const ElementMetadata& metadata));
|
||||
|
||||
// Concrete implementations that the corresponding mocked method may call,
|
||||
// provided for convenience. These methods just call through to the
|
||||
// corrensponding methods in Callback, and provide an convenient way for the
|
||||
// MockCallback to exhibit the same behavior as Callback.
|
||||
Status OnElementBeginConcrete(const ElementMetadata& metadata,
|
||||
Action* action) {
|
||||
return Callback::OnElementBegin(metadata, action);
|
||||
}
|
||||
|
||||
Status OnUnknownElementConcrete(const ElementMetadata& metadata,
|
||||
Reader* reader,
|
||||
std::uint64_t* bytes_remaining) {
|
||||
return Callback::OnUnknownElement(metadata, reader, bytes_remaining);
|
||||
}
|
||||
|
||||
Status OnEbmlConcrete(const ElementMetadata& metadata, const Ebml& ebml) {
|
||||
return Callback::OnEbml(metadata, ebml);
|
||||
}
|
||||
|
||||
Status OnVoidConcrete(const ElementMetadata& metadata, Reader* reader,
|
||||
std::uint64_t* bytes_remaining) {
|
||||
return Callback::OnVoid(metadata, reader, bytes_remaining);
|
||||
}
|
||||
|
||||
Status OnSegmentBeginConcrete(const ElementMetadata& metadata,
|
||||
Action* action) {
|
||||
return Callback::OnSegmentBegin(metadata, action);
|
||||
}
|
||||
|
||||
Status OnSeekConcrete(const ElementMetadata& metadata, const Seek& seek) {
|
||||
return Callback::OnSeek(metadata, seek);
|
||||
}
|
||||
|
||||
Status OnInfoConcrete(const ElementMetadata& metadata, const Info& info) {
|
||||
return Callback::OnInfo(metadata, info);
|
||||
}
|
||||
|
||||
Status OnClusterBeginConcrete(const ElementMetadata& metadata,
|
||||
const Cluster& cluster, Action* action) {
|
||||
return Callback::OnClusterBegin(metadata, cluster, action);
|
||||
}
|
||||
|
||||
Status OnSimpleBlockBeginConcrete(const ElementMetadata& metadata,
|
||||
const SimpleBlock& simple_block,
|
||||
Action* action) {
|
||||
return Callback::OnSimpleBlockBegin(metadata, simple_block, action);
|
||||
}
|
||||
|
||||
Status OnSimpleBlockEndConcrete(const ElementMetadata& metadata,
|
||||
const SimpleBlock& simple_block) {
|
||||
return Callback::OnSimpleBlockEnd(metadata, simple_block);
|
||||
}
|
||||
|
||||
Status OnBlockGroupBeginConcrete(const ElementMetadata& metadata,
|
||||
Action* action) {
|
||||
return Callback::OnBlockGroupBegin(metadata, action);
|
||||
}
|
||||
|
||||
Status OnBlockBeginConcrete(const ElementMetadata& metadata,
|
||||
const Block& block, Action* action) {
|
||||
return Callback::OnBlockBegin(metadata, block, action);
|
||||
}
|
||||
|
||||
Status OnBlockEndConcrete(const ElementMetadata& metadata,
|
||||
const Block& block) {
|
||||
return Callback::OnBlockEnd(metadata, block);
|
||||
}
|
||||
|
||||
Status OnBlockGroupEndConcrete(const ElementMetadata& metadata,
|
||||
const BlockGroup& block_group) {
|
||||
return Callback::OnBlockGroupEnd(metadata, block_group);
|
||||
}
|
||||
|
||||
Status OnFrameConcrete(const FrameMetadata& metadata, Reader* reader,
|
||||
std::uint64_t* bytes_remaining) {
|
||||
return Callback::OnFrame(metadata, reader, bytes_remaining);
|
||||
}
|
||||
|
||||
Status OnClusterEndConcrete(const ElementMetadata& metadata,
|
||||
const Cluster& cluster) {
|
||||
return Callback::OnClusterEnd(metadata, cluster);
|
||||
}
|
||||
|
||||
Status OnTrackEntryConcrete(const ElementMetadata& metadata,
|
||||
const TrackEntry& track_entry) {
|
||||
return Callback::OnTrackEntry(metadata, track_entry);
|
||||
}
|
||||
|
||||
Status OnCuePointConcrete(const ElementMetadata& metadata,
|
||||
const CuePoint& cue_point) {
|
||||
return Callback::OnCuePoint(metadata, cue_point);
|
||||
}
|
||||
|
||||
Status OnEditionEntryConcrete(const ElementMetadata& metadata,
|
||||
const EditionEntry& edition_entry) {
|
||||
return Callback::OnEditionEntry(metadata, edition_entry);
|
||||
}
|
||||
|
||||
Status OnTagConcrete(const ElementMetadata& metadata, const Tag& tag) {
|
||||
return Callback::OnTag(metadata, tag);
|
||||
}
|
||||
|
||||
Status OnSegmentEndConcrete(const ElementMetadata& metadata) {
|
||||
return Callback::OnSegmentEnd(metadata);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace webm
|
||||
|
||||
#endif // TEST_UTILS_MOCK_CALLBACK_H_
|
||||
@@ -0,0 +1,108 @@
|
||||
// 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.
|
||||
#ifndef TEST_UTILS_PARSER_TEST_H_
|
||||
#define TEST_UTILS_PARSER_TEST_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "test_utils/limited_reader.h"
|
||||
#include "test_utils/mock_callback.h"
|
||||
#include "webm/buffer_reader.h"
|
||||
#include "webm/reader.h"
|
||||
#include "webm/status.h"
|
||||
|
||||
namespace webm {
|
||||
|
||||
// Base class for unit tests that test an instance of the Parser inteface. The
|
||||
// template parameter T is the parser class being tested.
|
||||
template <typename T>
|
||||
class ParserTest : public testing::Test {
|
||||
public:
|
||||
// Sets the reader's internal buffer to the given buffer.
|
||||
virtual void SetReaderData(std::vector<std::uint8_t> data) {
|
||||
reader_ = BufferReader(std::move(data));
|
||||
}
|
||||
|
||||
// Destroys and recreates the parser, forwarding the arguments to the
|
||||
// constructor. This is primarily useful for tests that require the parser to
|
||||
// have different constructor parameters.
|
||||
template <typename... Args>
|
||||
void ResetParser(Args&&... args) {
|
||||
parser_.~T();
|
||||
new (&parser_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Calls Feed() on the parser, making sure it completes successfully and reads
|
||||
// size number of bytes.
|
||||
virtual void ParseAndVerify(std::uint64_t size) {
|
||||
std::uint64_t num_bytes_read = 0;
|
||||
const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
|
||||
ASSERT_EQ(Status::kOkCompleted, status.code);
|
||||
ASSERT_EQ(size, num_bytes_read);
|
||||
}
|
||||
|
||||
// Calls Feed() on the parser, making sure it completes successfully and reads
|
||||
// all the data available in the reader.
|
||||
virtual void ParseAndVerify() { ParseAndVerify(reader_.size()); }
|
||||
|
||||
// Similar to ParseAndVerify(), but instead artificially limits the reader to
|
||||
// providing one byte per call to Feed(). If Feed() returns
|
||||
// Status::kWouldBlock or Status::kOkPartial, Feed() will be called again
|
||||
// (feeding it another byte).
|
||||
virtual void IncrementalParseAndVerify() {
|
||||
const std::uint64_t expected_num_bytes_read = reader_.size();
|
||||
|
||||
webm::LimitedReader limited_reader(
|
||||
std::unique_ptr<webm::Reader>(new BufferReader(std::move(reader_))));
|
||||
|
||||
Status status;
|
||||
std::uint64_t num_bytes_read = 0;
|
||||
do {
|
||||
limited_reader.set_total_read_skip_limit(1);
|
||||
std::uint64_t local_num_bytes_read = 0;
|
||||
status = parser_.Feed(&callback_, &limited_reader, &local_num_bytes_read);
|
||||
num_bytes_read += local_num_bytes_read;
|
||||
const std::uint64_t kMinBytesRead = 1;
|
||||
ASSERT_GE(kMinBytesRead, local_num_bytes_read);
|
||||
} while (status.code == Status::kWouldBlock ||
|
||||
status.code == Status::kOkPartial);
|
||||
|
||||
ASSERT_EQ(Status::kOkCompleted, status.code);
|
||||
ASSERT_EQ(expected_num_bytes_read, num_bytes_read);
|
||||
}
|
||||
|
||||
// Calls Feed() on the parser, making sure it returns the expected status
|
||||
// code.
|
||||
virtual void ParseAndExpectResult(Status::Code expected) {
|
||||
std::uint64_t num_bytes_read = 0;
|
||||
const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
|
||||
ASSERT_EQ(expected, status.code);
|
||||
}
|
||||
|
||||
protected:
|
||||
// These members are protected (not private) so unit tests have access to
|
||||
// them. This is intentional.
|
||||
|
||||
// The parser that the unit tests will be testing.
|
||||
T parser_;
|
||||
|
||||
// The callback that is used during parsing.
|
||||
testing::NiceMock<MockCallback> callback_;
|
||||
|
||||
// The reader used for feeding data into the parser.
|
||||
BufferReader reader_;
|
||||
};
|
||||
|
||||
} // namespace webm
|
||||
|
||||
#endif // TEST_UTILS_PARSER_TEST_H_
|
||||
Reference in New Issue
Block a user