blob: f3e962c1929f09057b1805142f5a1fcbe07c91f0 [file] [log] [blame]
Patrick Williamsac70bc52024-07-09 17:11:28 -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) {
32 struct stat stat1;
33 if (fstat(fd1, &stat1) != 0) {
34 return false;
35 }
36 struct stat stat2;
37 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
45TEST(BufferReleaseChannelTest, MessageFlattenable) {
46 ReleaseCallbackId releaseCallbackId{1, 2};
47 sp<Fence> releaseFence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
48
49 std::vector<uint8_t> dataBuffer;
50 std::vector<int> fdBuffer;
51
52 // Verify that we can flatten a message
53 {
54 BufferReleaseChannel::Message message{releaseCallbackId, releaseFence};
55
56 dataBuffer.resize(message.getFlattenedSize());
57 void* dataPtr = dataBuffer.data();
58 size_t dataSize = dataBuffer.size();
59
60 fdBuffer.resize(message.getFdCount());
61 int* fdPtr = fdBuffer.data();
62 size_t fdSize = fdBuffer.size();
63
64 ASSERT_EQ(OK, message.flatten(dataPtr, dataSize, fdPtr, fdSize));
65
66 // Fence's unique_fd uses fdsan to check ownership of the file descriptor. Normally the file
67 // descriptor is passed through the Unix socket and duplicated (and sent to another process)
68 // so there's no problem with duplicate file descriptor ownership. For this unit test, we
69 // need to set up a duplicate file descriptor to avoid crashing due to duplicate ownership.
70 ASSERT_EQ(releaseFence->get(), fdBuffer[0]);
71 fdBuffer[0] = message.releaseFence->dup();
72 }
73
74 // Verify that we can unflatten a message
75 {
76 BufferReleaseChannel::Message message;
77
78 const void* dataPtr = dataBuffer.data();
79 size_t dataSize = dataBuffer.size();
80
81 const int* fdPtr = fdBuffer.data();
82 size_t fdSize = fdBuffer.size();
83
84 ASSERT_EQ(OK, message.unflatten(dataPtr, dataSize, fdPtr, fdSize));
85 ASSERT_EQ(releaseCallbackId, message.releaseCallbackId);
86 ASSERT_TRUE(is_same_file(releaseFence->get(), message.releaseFence->get()));
87 }
88}
89
90// Verify that the BufferReleaseChannel consume returns WOULD_BLOCK when there's no message
91// available.
92TEST(BufferReleaseChannelTest, ConsumerEndpointIsNonBlocking) {
93 std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
94 std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
95 ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));
96
97 ReleaseCallbackId releaseCallbackId;
98 sp<Fence> releaseFence;
99 ASSERT_EQ(WOULD_BLOCK, consumer->readReleaseFence(releaseCallbackId, releaseFence));
100}
101
102// Verify that we can write a message to the BufferReleaseChannel producer and read that message
103// using the BufferReleaseChannel consumer.
104TEST(BufferReleaseChannelTest, ProduceAndConsume) {
105 std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
106 std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
107 ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));
108
109 ReleaseCallbackId producerReleaseCallbackId{1, 2};
110 sp<Fence> producerReleaseFence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
111 ASSERT_EQ(OK, producer->writeReleaseFence(producerReleaseCallbackId, producerReleaseFence));
112
113 ReleaseCallbackId consumerReleaseCallbackId;
114 sp<Fence> consumerReleaseFence;
115 ASSERT_EQ(OK, consumer->readReleaseFence(consumerReleaseCallbackId, consumerReleaseFence));
116
117 ASSERT_EQ(producerReleaseCallbackId, consumerReleaseCallbackId);
118 ASSERT_TRUE(is_same_file(producerReleaseFence->get(), consumerReleaseFence->get()));
119}
120
121} // namespace android