1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17
18 #include "KumquatInstance.h"
19
20 #include <unistd.h>
21
22 #include <filesystem>
23
24 #include "aemu/base/Path.h"
25
26 using testing::Eq;
27
28 namespace gfxstream {
29 namespace tests {
30
KumquatInstance()31 KumquatInstance::KumquatInstance() {}
32
SetUp(bool withGl,bool withVk,std::string features)33 void KumquatInstance::SetUp(bool withGl, bool withVk, std::string features) {
34 const std::filesystem::path testDirectory = gfxstream::guest::getProgramDirectory();
35 const std::string kumquatCommand = (testDirectory / "kumquat").string();
36 const std::string renderer_features = "--renderer-features=" + features;
37
38 std::string capset_names = "--capset-names=";
39 if (withGl) {
40 capset_names.append("gfxstream-gles:");
41 }
42 if (withVk) {
43 capset_names.append("gfxstream-vulkan:");
44 }
45
46 int fds[2];
47 ASSERT_THAT(pipe(fds), Eq(0));
48
49 // VirtGpuKumquatDevice.cpp by default connects to "/tmp/kumquat-gpu-0". If this changes,
50 // the correct socket path must be plumbed through to VirtGpuKumquatDevice.cpp
51 const std::string gpu_socket_path = "/tmp/kumquat-gpu-" + std::to_string(0);
52
53 const std::string gpu_socket_cmd = "--gpu-socket-path=" + gpu_socket_path;
54
55 const std::string pipe_descriptor = "--pipe-descriptor=" + std::to_string(fds[1]);
56
57 pid_t pid = fork();
58 if (pid == 0) {
59 close(fds[0]);
60 execl(kumquatCommand.c_str(), kumquatCommand.c_str(), gpu_socket_cmd.c_str(),
61 capset_names.c_str(), renderer_features.c_str(), pipe_descriptor.c_str(), nullptr);
62 exit(0);
63 } else {
64 close(fds[1]);
65 uint64_t count = 0;
66 ssize_t bytes_read = read(fds[0], &count, sizeof(count));
67 // Kumquat writes [uint64_t](1) to the write end of the pipe..
68 ASSERT_THAT(bytes_read, Eq(8));
69 close(fds[0]);
70 ASSERT_THAT(virtgpu_kumquat_init(&mVirtGpu, gpu_socket_path.c_str()), Eq(0));
71 mKumquatPid = pid;
72 }
73 }
74
~KumquatInstance()75 KumquatInstance::~KumquatInstance() {
76 virtgpu_kumquat_finish(&mVirtGpu);
77 kill(mKumquatPid, SIGKILL);
78 int status = 0;
79 pid_t pid = waitpid(mKumquatPid, &status, WNOHANG);
80 while (!pid) {
81 pid = waitpid(mKumquatPid, &status, WNOHANG);
82 }
83 }
84
Snapshot()85 void KumquatInstance::Snapshot() { ASSERT_THAT(virtgpu_kumquat_snapshot_save(mVirtGpu), Eq(0)); }
86
Restore()87 void KumquatInstance::Restore() { ASSERT_THAT(virtgpu_kumquat_snapshot_restore(mVirtGpu), Eq(0)); }
88
89 } // namespace tests
90 } // namespace gfxstream
91