blob: 92172c8ae473a259587988eb1ff71507833f1151 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/cpp/application/application_test_base.h"
#include "services/media/framework/parts/sparse_byte_buffer.h"
namespace mojo {
namespace media {
class SparseByteBufferTest : public test::ApplicationTestBase {
public:
static const size_t kSize = 1000u;
SparseByteBufferTest() { under_test_.Initialize(kSize); }
void ExpectNullRegion(SparseByteBuffer::Region region) {
EXPECT_EQ(under_test_.null_region(), region);
}
void ExpectRegion(size_t position,
size_t size,
SparseByteBuffer::Region region) {
EXPECT_NE(under_test_.null_region(), region);
EXPECT_EQ(position, region.position());
EXPECT_EQ(size, region.size());
uint8_t* data = region.data();
EXPECT_NE(nullptr, data);
for (size_t i = 0; i < size; i++) {
EXPECT_EQ(data[i], ByteForPosition(position + i));
}
}
void ExpectNullHole(SparseByteBuffer::Hole hole) {
EXPECT_EQ(under_test_.null_hole(), hole);
}
void ExpectHole(size_t position, size_t size, SparseByteBuffer::Hole hole) {
EXPECT_NE(under_test_.null_hole(), hole);
EXPECT_EQ(position, hole.position());
EXPECT_EQ(size, hole.size());
}
uint8_t ByteForPosition(size_t position) {
return static_cast<uint8_t>(position ^ (position >> 8) ^ (position >> 16) ^
(position >> 24));
}
std::vector<uint8_t> CreateBuffer(size_t position, size_t size) {
std::vector<uint8_t> buffer(size);
for (size_t i = 0; i < size; i++) {
buffer[i] = ByteForPosition(i + position);
}
return buffer;
}
// See HoleHints test.
void VerifyHoleHint(size_t hole_count, size_t hint_position) {
under_test_.Initialize(kSize);
size_t hole_size = kSize / hole_count;
// Create the holes.
for (size_t position = 0; position < kSize; position += hole_size) {
SparseByteBuffer::Hole hole =
under_test_.FindOrCreateHole(position, under_test_.null_hole());
ExpectHole(position, kSize - position, hole);
}
// Use the indicated hole as a hint.
SparseByteBuffer::Hole hint = under_test_.FindHoleContaining(hint_position);
// Run FindOrCreateHole against every position for each hint.
for (size_t position = 0; position < kSize; position++) {
SparseByteBuffer::Hole hole =
under_test_.FindOrCreateHole(position, hint);
size_t expected_size = hole_size - position % hole_size;
if (position + expected_size > kSize) {
expected_size = kSize - position;
}
ExpectHole(position, expected_size, hole);
}
}
SparseByteBuffer under_test_;
};
// Tests that the buffer behaves as expected immediately after initialization.
TEST_F(SparseByteBufferTest, InitialState) {
// Null comparison works for regions.
ExpectNullRegion(under_test_.null_region());
// No regions anywhere.
for (size_t position = 0; position < kSize; position++) {
ExpectNullRegion(
under_test_.FindRegionContaining(position, under_test_.null_region()));
}
// Null comparison works for holes.
ExpectNullHole(under_test_.null_hole());
// One hole everywhere.
for (size_t position = 0; position < kSize; position++) {
ExpectHole(0, kSize, under_test_.FindHoleContaining(position));
}
// FindOrCreateHole finds the hole.
ExpectHole(0, kSize,
under_test_.FindOrCreateHole(0, under_test_.null_hole()));
}
// Creates a second hole.
TEST_F(SparseByteBufferTest, TwoHoles) {
// Create a hole from kSize/2 to the end.
SparseByteBuffer::Hole created_hole =
under_test_.FindOrCreateHole(kSize / 2, under_test_.null_hole());
// One hole covers the first half.
for (size_t position = 0; position < kSize / 2; position++) {
ExpectHole(0, kSize / 2, under_test_.FindHoleContaining(position));
}
// Created hole covers the second half.
for (size_t position = kSize / 2; position < kSize; position++) {
EXPECT_EQ(created_hole, under_test_.FindHoleContaining(position));
}
// No regions anywhere.
for (size_t position = 0; position < kSize; position++) {
ExpectNullRegion(
under_test_.FindRegionContaining(position, under_test_.null_region()));
}
}
// Creates a single region that covers the entire buffer.
TEST_F(SparseByteBufferTest, BigRegion) {
// Fill the whole buffer. No hole should be returned, because there are no
// holes anymore.
ExpectNullHole(under_test_.Fill(under_test_.FindHoleContaining(0),
CreateBuffer(0, kSize)));
// Find the new region.
SparseByteBuffer::Region big_region =
under_test_.FindRegionContaining(0, under_test_.null_region());
ExpectRegion(0, kSize, big_region);
// Same region everywhere.
for (size_t position = 0; position < kSize; position++) {
EXPECT_EQ(big_region, under_test_.FindRegionContaining(
position, under_test_.null_region()));
}
// No holes anywhere.
for (size_t position = 0; position < kSize; position++) {
ExpectNullHole(under_test_.FindHoleContaining(position));
}
}
// Creates a region for every other byte, then fills in the holes.
TEST_F(SparseByteBufferTest, TinyRegions) {
// Create the regions.
for (size_t position = 0; position < kSize; position += 2) {
SparseByteBuffer::Hole hole =
under_test_.FindOrCreateHole(position, under_test_.null_hole());
ExpectHole(position, kSize - position, hole);
ExpectHole(position + 1, kSize - position - 1,
under_test_.Fill(hole, CreateBuffer(position, 1)));
}
// Find them again.
for (size_t position = 0; position < kSize; position += 2) {
ExpectRegion(position, 1, under_test_.FindRegionContaining(
position, under_test_.null_region()));
}
// Find the holes.
for (size_t position = 1; position < kSize; position += 2) {
ExpectHole(position, 1, under_test_.FindHoleContaining(position));
}
// Fill in the holes.
for (size_t position = 1; position < kSize; position += 2) {
SparseByteBuffer::Hole hole = under_test_.FindHoleContaining(position);
ExpectHole(position, 1, hole);
hole = under_test_.Fill(hole, CreateBuffer(position, 1));
if (position + 2 < kSize) {
ExpectHole(position + 2, 1, hole);
} else {
ExpectNullHole(hole);
}
}
// Tiny regions everywhere.
for (size_t position = 0; position < kSize; position++) {
ExpectRegion(position, 1, under_test_.FindRegionContaining(
position, under_test_.null_region()));
}
// No holes anywhere.
for (size_t position = 0; position < kSize; position++) {
ExpectNullHole(under_test_.FindHoleContaining(position));
}
}
// Verifies that FindRegionContaining works regardless of the hints it's given.
TEST_F(SparseByteBufferTest, RegionHints) {
static const size_t region_count = 11u;
size_t region_size = kSize / region_count;
// Create the regions.
for (size_t position = 0; position < kSize; position += region_size) {
SparseByteBuffer::Hole hole =
under_test_.FindOrCreateHole(position, under_test_.null_hole());
ExpectHole(position, kSize - position, hole);
if (position + region_size >= kSize) {
ExpectNullHole(
under_test_.Fill(hole, CreateBuffer(position, kSize - position)));
} else {
ExpectHole(position + region_size, kSize - position - region_size,
under_test_.Fill(hole, CreateBuffer(position, region_size)));
}
}
// Use each region as a hint.
for (size_t hint_position = 0; hint_position < kSize;
hint_position += region_size) {
SparseByteBuffer::Region hint = under_test_.FindRegionContaining(
hint_position, under_test_.null_region());
// Run FindRegionContaining against every position for each hint.
for (size_t position = 0; position < kSize; position++) {
SparseByteBuffer::Region region =
under_test_.FindRegionContaining(position, hint);
size_t region_position = position - (position % region_size);
ExpectRegion(region_position, region_position + region_size > kSize
? kSize - region_position
: region_size,
region);
}
}
// Make sure null_region works as a hint.
for (size_t position = 0; position < kSize; position++) {
SparseByteBuffer::Region region =
under_test_.FindRegionContaining(position, under_test_.null_region());
size_t region_position = position - (position % region_size);
ExpectRegion(region_position,
region_position + region_size > kSize ? kSize - region_position
: region_size,
region);
}
}
// Verifies that FindOrCreateHole works regardless of the hints it's given.
TEST_F(SparseByteBufferTest, HoleHints) {
static const size_t hole_count = 11u;
size_t hole_size = kSize / hole_count;
for (size_t hint_position = 0; hint_position < kSize;
hint_position += hole_size) {
VerifyHoleHint(hole_count, hint_position);
}
}
} // namespace media
} // namespace mojo