blob: 74f69e1ff0250a327ae6471894f9e997b6fc7633 [file] [log] [blame]
Patrick Williamsf693bcf2024-08-02 09:55:23 -05001/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <string>
18#include <vector>
19
20#include <gtest/gtest.h>
21#include <gui/BufferReleaseChannel.h>
22
23using namespace std::string_literals;
24using android::gui::BufferReleaseChannel;
25
26namespace android {
27
28namespace {
29
30// Helper function to check if two file descriptors point to the same file.
31bool is_same_file(int fd1, int fd2) {
Patrick Williams603c2ea2024-10-28 15:25:47 -050032 struct stat stat1 {};
Patrick Williamsf693bcf2024-08-02 09:55:23 -050033 if (fstat(fd1, &stat1) != 0) {
34 return false;
35 }
Patrick Williams603c2ea2024-10-28 15:25:47 -050036 struct stat stat2 {};
Patrick Williamsf693bcf2024-08-02 09:55:23 -050037 if (fstat(fd2, &stat2) != 0) {
38 return false;
39 }
40 return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
41}
42
43} // namespace
44
Patrick Williams603c2ea2024-10-28 15:25:47 -050045class BufferReleaseChannelTest : public testing::Test {
46protected:
47 std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> mConsumer;
48 std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> mProducer;
49
50 void SetUp() override {
51 ASSERT_EQ(OK,
52 BufferReleaseChannel::open("BufferReleaseChannelTest"s, mConsumer, mProducer));
53 }
54};
55
56TEST_F(BufferReleaseChannelTest, MessageFlattenable) {
Patrick Williamsf693bcf2024-08-02 09:55:23 -050057 ReleaseCallbackId releaseCallbackId{1, 2};
58 sp<Fence> releaseFence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
59 uint32_t maxAcquiredBufferCount = 5;
60
61 std::vector<uint8_t> dataBuffer;
62 std::vector<int> fdBuffer;
63
64 // Verify that we can flatten a message
65 {
66 BufferReleaseChannel::Message message{releaseCallbackId, releaseFence,
67 maxAcquiredBufferCount};
68
69 dataBuffer.resize(message.getFlattenedSize());
70 void* dataPtr = dataBuffer.data();
71 size_t dataSize = dataBuffer.size();
72
73 fdBuffer.resize(message.getFdCount());
74 int* fdPtr = fdBuffer.data();
75 size_t fdSize = fdBuffer.size();
76
77 ASSERT_EQ(OK, message.flatten(dataPtr, dataSize, fdPtr, fdSize));
78
79 // Fence's unique_fd uses fdsan to check ownership of the file descriptor. Normally the file
80 // descriptor is passed through the Unix socket and duplicated (and sent to another process)
81 // so there's no problem with duplicate file descriptor ownership. For this unit test, we
82 // need to set up a duplicate file descriptor to avoid crashing due to duplicate ownership.
83 ASSERT_EQ(releaseFence->get(), fdBuffer[0]);
84 fdBuffer[0] = message.releaseFence->dup();
85 }
86
87 // Verify that we can unflatten a message
88 {
89 BufferReleaseChannel::Message message;
90
91 const void* dataPtr = dataBuffer.data();
92 size_t dataSize = dataBuffer.size();
93
94 const int* fdPtr = fdBuffer.data();
95 size_t fdSize = fdBuffer.size();
96
97 ASSERT_EQ(OK, message.unflatten(dataPtr, dataSize, fdPtr, fdSize));
98 ASSERT_EQ(releaseCallbackId, message.releaseCallbackId);
99 ASSERT_TRUE(is_same_file(releaseFence->get(), message.releaseFence->get()));
100 ASSERT_EQ(maxAcquiredBufferCount, message.maxAcquiredBufferCount);
101 }
102}
103
104// Verify that the BufferReleaseChannel consume returns WOULD_BLOCK when there's no message
105// available.
Patrick Williams603c2ea2024-10-28 15:25:47 -0500106TEST_F(BufferReleaseChannelTest, ConsumerEndpointIsNonBlocking) {
Patrick Williamsf693bcf2024-08-02 09:55:23 -0500107 ReleaseCallbackId releaseCallbackId;
108 sp<Fence> releaseFence;
109 uint32_t maxAcquiredBufferCount;
110 ASSERT_EQ(WOULD_BLOCK,
Patrick Williams603c2ea2024-10-28 15:25:47 -0500111 mConsumer->readReleaseFence(releaseCallbackId, releaseFence, maxAcquiredBufferCount));
Patrick Williamsf693bcf2024-08-02 09:55:23 -0500112}
113
114// Verify that we can write a message to the BufferReleaseChannel producer and read that message
115// using the BufferReleaseChannel consumer.
Patrick Williams603c2ea2024-10-28 15:25:47 -0500116TEST_F(BufferReleaseChannelTest, ProduceAndConsume) {
Patrick Williamsf693bcf2024-08-02 09:55:23 -0500117 sp<Fence> fence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
118
119 for (uint64_t i = 0; i < 64; i++) {
120 ReleaseCallbackId producerId{i, i + 1};
121 uint32_t maxAcquiredBufferCount = i + 2;
Patrick Williams603c2ea2024-10-28 15:25:47 -0500122 ASSERT_EQ(OK, mProducer->writeReleaseFence(producerId, fence, maxAcquiredBufferCount));
Patrick Williamsf693bcf2024-08-02 09:55:23 -0500123 }
124
125 for (uint64_t i = 0; i < 64; i++) {
126 ReleaseCallbackId expectedId{i, i + 1};
127 uint32_t expectedMaxAcquiredBufferCount = i + 2;
128
129 ReleaseCallbackId consumerId;
130 sp<Fence> consumerFence;
131 uint32_t maxAcquiredBufferCount;
132 ASSERT_EQ(OK,
Patrick Williams603c2ea2024-10-28 15:25:47 -0500133 mConsumer->readReleaseFence(consumerId, consumerFence, maxAcquiredBufferCount));
Patrick Williamsf693bcf2024-08-02 09:55:23 -0500134
135 ASSERT_EQ(expectedId, consumerId);
136 ASSERT_TRUE(is_same_file(fence->get(), consumerFence->get()));
137 ASSERT_EQ(expectedMaxAcquiredBufferCount, maxAcquiredBufferCount);
138 }
139}
140
Patrick Williams603c2ea2024-10-28 15:25:47 -0500141// Verify that BufferReleaseChannel::ConsumerEndpoint's socket can't be written to.
142TEST_F(BufferReleaseChannelTest, ConsumerSocketReadOnly) {
143 uint64_t data = 0;
144 ASSERT_EQ(-1, write(mConsumer->getFd().get(), &data, sizeof(uint64_t)));
145 ASSERT_EQ(errno, EPIPE);
146}
147
148// Verify that BufferReleaseChannel::ProducerEndpoint's socket can't be read from.
149TEST_F(BufferReleaseChannelTest, ProducerSocketWriteOnly) {
150 ASSERT_EQ(0, read(mProducer->getFd().get(), nullptr, sizeof(uint64_t)));
151}
152
Patrick Williamsf693bcf2024-08-02 09:55:23 -0500153} // namespace android