[libcamera-devel] [PATCH v3 02/33] test: file_descriptor: Add test

Niklas Söderlund niklas.soderlund at ragnatech.se
Fri Jan 10 20:37:37 CET 2020


Add a test which exercises the whole FileDescriptor interface.

Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 test/file-descriptor.cpp | 208 +++++++++++++++++++++++++++++++++++++++
 test/meson.build         |   1 +
 2 files changed, 209 insertions(+)
 create mode 100644 test/file-descriptor.cpp

diff --git a/test/file-descriptor.cpp b/test/file-descriptor.cpp
new file mode 100644
index 0000000000000000..3e5e880093e748b0
--- /dev/null
+++ b/test/file-descriptor.cpp
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * file_descriptor.cpp - FileDescriptor test
+ */
+
+#include <fcntl.h>
+#include <iostream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libcamera/file_descriptor.h>
+
+#include "test.h"
+
+using namespace libcamera;
+using namespace std;
+
+class FileDescriptorTest : public Test
+{
+protected:
+	int init()
+	{
+		desc1_ = nullptr;
+		desc2_ = nullptr;
+
+		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;
+	}
+
+	int run()
+	{
+		/* Test creating empty FileDescriptor. */
+		desc1_ = new FileDescriptor();
+
+		if (desc1_->fd() != -1) {
+			std::cout << "Failed fd numerical check (default constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		delete desc1_;
+		desc1_ = nullptr;
+
+		/* Test creating FileDescriptor from numerical file descriptor. */
+		desc1_ = new FileDescriptor(fd_);
+		if (desc1_->fd() == fd_) {
+			std::cout << "Failed fd numerical check (int constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		if (!isValidFd(fd_) || !isValidFd(desc1_->fd())) {
+			std::cout << "Failed fd validity after construction (int constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		int fd = desc1_->fd();
+
+		delete desc1_;
+		desc1_ = nullptr;
+
+		if (!isValidFd(fd_) || isValidFd(fd)) {
+			std::cout << "Failed fd validity after destruction (int constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		/* Test creating FileDescriptor from other FileDescriptor. */
+		desc1_ = new FileDescriptor(fd_);
+		desc2_ = new FileDescriptor(*desc1_);
+
+		if (desc1_->fd() == fd_ || desc2_->fd() == fd_ || desc1_->fd() != desc2_->fd()) {
+			std::cout << "Failed fd numerical check (copy constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		if (!isValidFd(desc1_->fd()) || !isValidFd(desc2_->fd())) {
+			std::cout << "Failed fd validity after construction (copy constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		delete desc1_;
+		desc1_ = nullptr;
+
+		if (!isValidFd(desc2_->fd())) {
+			std::cout << "Failed fd validity after destruction (copy constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		delete desc2_;
+		desc2_ = nullptr;
+
+		/* Test creating FileDescriptor by taking over other FileDescriptor. */
+		desc1_ = new FileDescriptor(fd_);
+		fd = desc1_->fd();
+		desc2_ = new FileDescriptor(std::move(*desc1_));
+
+		if (desc1_->fd() != -1 || desc2_->fd() != fd) {
+			std::cout << "Failed fd numerical check (move constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		if (!isValidFd(desc2_->fd())) {
+			std::cout << "Failed fd validity after construction (move constructor)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		delete desc1_;
+		desc1_ = nullptr;
+		delete desc2_;
+		desc2_ = nullptr;
+
+		/* Test creating FileDescriptor by copy assignment. */
+		desc1_ = new FileDescriptor();
+		desc2_ = new FileDescriptor(fd_);
+
+		fd = desc2_->fd();
+		*desc1_ = *desc2_;
+
+		if (desc1_->fd() != fd || desc2_->fd() != fd) {
+			std::cout << "Failed fd numerical check (copy assignment)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		if (!isValidFd(desc1_->fd()) || !isValidFd(desc2_->fd())) {
+			std::cout << "Failed fd validity after construction (copy assignment)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		delete desc1_;
+		desc1_ = nullptr;
+		delete desc2_;
+		desc2_ = nullptr;
+
+		/* Test creating FileDescriptor by move assignment. */
+		desc1_ = new FileDescriptor();
+		desc2_ = new FileDescriptor(fd_);
+
+		fd = desc2_->fd();
+		*desc1_ = std::move(*desc2_);
+
+		if (desc1_->fd() != fd || desc2_->fd() != -1) {
+			std::cout << "Failed fd numerical check (move assignment)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		if (!isValidFd(desc1_->fd())) {
+			std::cout << "Failed fd validity after construction (move assignment)"
+				  << std::endl;
+			return TestFail;
+		}
+
+		delete desc1_;
+		desc1_ = nullptr;
+		delete desc2_;
+		desc2_ = nullptr;
+
+		return TestPass;
+	}
+
+	void cleanup()
+	{
+		delete desc2_;
+		delete desc1_;
+
+		if (fd_ > 0)
+			close(fd_);
+	}
+
+private:
+	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_;
+	FileDescriptor *desc1_, *desc2_;
+};
+
+TEST_REGISTER(FileDescriptorTest)
diff --git a/test/meson.build b/test/meson.build
index 1bb2161dc05a7b1d..daaa1aac926dd0ea 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -25,6 +25,7 @@ internal_tests = [
     ['event',                           'event.cpp'],
     ['event-dispatcher',                'event-dispatcher.cpp'],
     ['event-thread',                    'event-thread.cpp'],
+    ['file-descriptor',                 'file-descriptor.cpp'],
     ['message',                         'message.cpp'],
     ['object',                          'object.cpp'],
     ['object-invoke',                   'object-invoke.cpp'],
-- 
2.24.1



More information about the libcamera-devel mailing list