blob: f84e5924b8879760c90538c73816922a6166ed23 [file]
// Copyright 2026 The Fuchsia 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 <lib/zx/vmo.h>
#include <zircon/syscalls.h>
#include <gtest/gtest.h>
#include "lib/media/codec_impl/codec_buffer.h"
#include "lib/media/codec_impl/codec_vmo_range.h"
class CodecBufferForTest : public CodecBuffer {
public:
CodecBufferForTest(CodecBuffer::Info buffer_info, CodecVmoRange vmo_range)
: CodecBuffer(nullptr, buffer_info, std::move(vmo_range)) {}
using CodecBuffer::Info;
using CodecBuffer::Map;
};
namespace {
CodecBufferForTest::Info MakeDefaultBufferInfo(CodecPort port = kOutputPort) {
return CodecBufferForTest::Info{
.port = port,
.lifetime_ordinal = 1,
.index = 0,
.is_secure = false,
};
}
TEST(CodecBufferTest, SizeVsRawVmoSize) {
const size_t page_size = zx_system_get_page_size();
const size_t content_size = page_size;
const size_t raw_vmo_size = 4 * page_size;
zx::vmo vmo;
ASSERT_EQ(ZX_OK, zx::vmo::create(raw_vmo_size, 0, &vmo));
CodecVmoRange vmo_range(std::move(vmo), 0, content_size);
CodecBufferForTest buffer(MakeDefaultBufferInfo(), std::move(vmo_range));
EXPECT_EQ(0u, buffer.vmo_offset());
EXPECT_EQ(content_size, buffer.size());
EXPECT_EQ(raw_vmo_size, buffer.raw_vmo_size());
}
TEST(CodecBufferTest, MapCoversTrailingPaddingPagesUpToRawVmoSize) {
const size_t page_size = zx_system_get_page_size();
const size_t content_size = page_size;
const size_t raw_vmo_size = 4 * page_size;
zx::vmo vmo;
ASSERT_EQ(ZX_OK, zx::vmo::create(raw_vmo_size, 0, &vmo));
zx::vmo dup_vmo;
ASSERT_EQ(ZX_OK, vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_vmo));
{
CodecVmoRange vmo_range(std::move(vmo), 0, content_size);
CodecBufferForTest buffer(MakeDefaultBufferInfo(), std::move(vmo_range));
ASSERT_TRUE(buffer.Map());
ASSERT_NE(nullptr, buffer.base());
EXPECT_EQ(content_size, buffer.size());
EXPECT_EQ(raw_vmo_size, buffer.raw_vmo_size());
// Write to the last byte of valid content and the last byte of trailing padding pages
// (in page 3, beyond round_up(vmo_offset + size(), page_size)).
constexpr uint8_t kContentLastByte = 0x5a;
constexpr uint8_t kPaddingLastByte = 0xa5;
buffer.base()[content_size - 1] = kContentLastByte;
buffer.base()[raw_vmo_size - 1] = kPaddingLastByte;
uint8_t read_content_byte = 0;
uint8_t read_padding_byte = 0;
ASSERT_EQ(ZX_OK, dup_vmo.read(&read_content_byte, content_size - 1, 1));
ASSERT_EQ(ZX_OK, dup_vmo.read(&read_padding_byte, raw_vmo_size - 1, 1));
EXPECT_EQ(kContentLastByte, read_content_byte);
EXPECT_EQ(kPaddingLastByte, read_padding_byte);
}
}
TEST(CodecBufferTest, MapWithNonZeroVmoOffsetAndTrailingPadding) {
const size_t page_size = zx_system_get_page_size();
constexpr uint64_t kVmoOffset = 128;
const size_t content_size = page_size;
const size_t raw_vmo_size = 4 * page_size;
zx::vmo vmo;
ASSERT_EQ(ZX_OK, zx::vmo::create(raw_vmo_size, 0, &vmo));
zx::vmo dup_vmo;
ASSERT_EQ(ZX_OK, vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup_vmo));
{
CodecVmoRange vmo_range(std::move(vmo), kVmoOffset, content_size);
CodecBufferForTest buffer(MakeDefaultBufferInfo(), std::move(vmo_range));
ASSERT_TRUE(buffer.Map());
ASSERT_NE(nullptr, buffer.base());
EXPECT_EQ(kVmoOffset, buffer.vmo_offset());
EXPECT_EQ(content_size, buffer.size());
EXPECT_EQ(raw_vmo_size, buffer.raw_vmo_size());
EXPECT_EQ(kVmoOffset, reinterpret_cast<uintptr_t>(buffer.base()) % page_size);
constexpr uint8_t kFirstByte = 0x11;
constexpr uint8_t kLastVmoByte = 0x22;
buffer.base()[0] = kFirstByte;
buffer.base()[raw_vmo_size - kVmoOffset - 1] = kLastVmoByte;
uint8_t read_first_byte = 0;
uint8_t read_last_vmo_byte = 0;
ASSERT_EQ(ZX_OK, dup_vmo.read(&read_first_byte, kVmoOffset, 1));
ASSERT_EQ(ZX_OK, dup_vmo.read(&read_last_vmo_byte, raw_vmo_size - 1, 1));
EXPECT_EQ(kFirstByte, read_first_byte);
EXPECT_EQ(kLastVmoByte, read_last_vmo_byte);
}
}
} // namespace