| // 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 |