/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2021, Google Inc. * * unique-fd.cpp - UniqueFD test */ #include #include #include #include #include #include #include #include "test.h" using namespace libcamera; using namespace std; class UniqueFDTest : public Test { protected: int init() override { return createFd(); } int run() override { /* Test creating empty UniqueFD. */ UniqueFD fd; if (fd.isValid() || fd.get() != -1) { std::cout << "Failed fd check (default constructor)" << std::endl; return TestFail; } /* Test creating UniqueFD from numerical file descriptor. */ UniqueFD fd2(fd_); if (!fd2.isValid() || fd2.get() != fd_) { std::cout << "Failed fd check (fd constructor)" << std::endl; return TestFail; } if (!isValidFd(fd_)) { std::cout << "Failed fd validity (fd constructor)" << std::endl; return TestFail; } /* Test move constructor. */ UniqueFD fd3(std::move(fd2)); if (!fd3.isValid() || fd3.get() != fd_) { std::cout << "Failed fd check (move constructor)" << std::endl; return TestFail; } if (fd2.isValid() || fd2.get() != -1) { std::cout << "Failed moved fd check (move constructor)" << std::endl; return TestFail; } if (!isValidFd(fd_)) { std::cout << "Failed fd validity (move constructor)" << std::endl; return TestFail; } /* Test move assignment operator. */ fd = std::move(fd3); if (!fd.isValid() || fd.get() != fd_) { std::cout << "Failed fd check (move assignment)" << std::endl; return TestFail; } if (fd3.isValid() || fd3.get() != -1) { std::cout << "Failed moved fd check (move assignment)" << std::endl; return TestFail; } if (!isValidFd(fd_)) { std::cout << "Failed fd validity (move assignment)" << std::endl; return TestFail; } /* Test swapping. */ fd2.swap(fd); if (!fd2.isValid() || fd2.get() != fd_) { std::cout << "Failed fd check (swap)" << std::endl; return TestFail; } if (fd.isValid() || fd.get() != -1) { std::cout << "Failed swapped fd check (swap)" << std::endl; return TestFail; } if (!isValidFd(fd_)) { std::cout << "Failed fd validity (swap)" << std::endl; return TestFail; } /* Test release. */ int numFd = fd2.release(); if (fd2.isValid() || fd2.get() != -1) { std::cout << "Failed fd check (release)" << std::endl; return TestFail; } if (numFd != fd_) { std::cout << "Failed released fd check (release)" << std::endl; return TestFail; } if (!isValidFd(fd_)) { std::cout << "Failed fd validity (release)" << std::endl; return TestFail; } /* Test reset assignment. */ fd.reset(numFd); if (!fd.isValid() || fd.get() != fd_) { std::cout << "Failed fd check (reset assignment)" << std::endl; return TestFail; } if (!isValidFd(fd_)) { std::cout << "Failed fd validity (reset assignment)" << std::endl; return TestFail; } /* Test reset destruction. */ fd.reset(); if (fd.isValid() || fd.get() != -1) { std::cout << "Failed fd check (reset destruction)" << std::endl; return TestFail; } if (isValidFd(fd_)) { std::cout << "Failed fd validity (reset destruction)" << std::endl; return TestFail; } /* Test destruction. */ if (createFd() == TestFail) { std::cout << "Failed to recreate test fd" << std::endl; return TestFail; } { UniqueFD fd4(fd_); } if (isValidFd(fd_)) { std::cout << "Failed fd validity (destruction)" << std::endl; return TestFail; } return TestPass; } void cleanup() override { if (fd_ > 0) close(fd_); } private: int createFd() { fd_ = open("/tmp", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR); if (fd_ < 0) return TestFail; /* Cache inode number of temp file. */ struct stat s; if (fstat(fd_, &s)) return TestFail; inodeNr_ = s.st_ino; return 0; } bool isValidFd(int fd) { struct stat s; if (fstat(fd, &s)) return false; /* Check that inode number matches cached temp file. */ return s.st_ino == inodeNr_; } int fd_; ino_t inodeNr_; }; TEST_REGISTER(UniqueFDTest) /a> 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133