[libcamera-devel,v3] test: log/process: check CAP_SYS_ADMIN in test init

Message ID 20200815151036.509376-1-vicamo.yang@canonical.com
State New
Delegated to: Laurent Pinchart
Headers show
Series
  • [libcamera-devel,v3] test: log/process: check CAP_SYS_ADMIN in test init
Related show

Commit Message

You-Sheng Yang Aug. 15, 2020, 3:10 p.m. UTC
While these tests may be executed as normal user at build time,
unshare() call will fail and so are tests log_process and process_test.
This change checks if one is granted with necessary capabilities so that
we don't fail the build unexpectedly.

v2:
 - add a shared capability testing util func
 - drop merge process kill(-1) patch
 - drop patch for removed list-camera test
v3:
 - mark libcap dependency as optional

Signed-off-by: You-Sheng Yang <vicamo.yang@canonical.com>
---
 test/libtest/meson.build      |  3 ++-
 test/libtest/test.cpp         | 32 +++++++++++++++++++++++++++++++-
 test/libtest/test.h           |  6 ++++++
 test/log/log_process.cpp      | 13 ++++++++++++-
 test/log/meson.build          |  3 ++-
 test/meson.build              | 15 +++++++++++++--
 test/process/meson.build      |  3 ++-
 test/process/process_test.cpp | 15 +++++++++++++++
 8 files changed, 83 insertions(+), 7 deletions(-)

Patch

diff --git a/test/libtest/meson.build b/test/libtest/meson.build
index 542335e..9e7c603 100644
--- a/test/libtest/meson.build
+++ b/test/libtest/meson.build
@@ -18,7 +18,8 @@  test_includes_internal = [
 ]
 
 libtest = static_library('libtest', libtest_sources,
-                         dependencies : libcamera_dep,
+                         dependencies : [ libcamera_dep, libtest_dep ],
+                         cpp_args : libtest_cpp_args,
                          include_directories : test_includes_internal)
 
 test_libraries = [libtest]
diff --git a/test/libtest/test.cpp b/test/libtest/test.cpp
index fd9f3d7..564e0bc 100644
--- a/test/libtest/test.cpp
+++ b/test/libtest/test.cpp
@@ -5,10 +5,40 @@ 
  * test.cpp - libcamera test base class
  */
 
-#include <stdlib.h>
+#include <stdarg.h>
 
 #include "test.h"
 
+TestStatus
+Test::testCapabilities(int nCapabilities, ...)
+{
+#ifdef HAVE_LIBLOG
+	va_list args;
+
+	va_start(args, nCapabilities);
+
+	cap_t caps = cap_get_proc();
+	if (caps == NULL)
+		return TestFail;
+
+	cap_value_t v;
+	cap_flag_t f;
+	cap_flag_value_t fv;
+	while (nCapabilities-- > 0) {
+		v = (cap_value_t)va_arg(args, int);
+		f = (cap_flag_t)va_arg(args, int);
+		if ((cap_get_flag(caps, v, f, &fv) < 0) || (fv != CAP_SET))
+			break;
+	}
+
+	cap_free(caps);
+
+	return nCapabilities >= 0 ? TestFail : TestPass;
+#else
+	return TestSkip;
+#endif
+}
+
 Test::Test()
 {
 }
diff --git a/test/libtest/test.h b/test/libtest/test.h
index 26d4b94..da64179 100644
--- a/test/libtest/test.h
+++ b/test/libtest/test.h
@@ -7,6 +7,10 @@ 
 #ifndef __TEST_TEST_H__
 #define __TEST_TEST_H__
 
+#ifdef HAVE_LIBLOG
+#include <sys/capability.h>
+#endif
+
 #include <sstream>
 
 enum TestStatus {
@@ -23,6 +27,8 @@  public:
 
 	int execute();
 
+	static TestStatus testCapabilities(int nCapabilities, ...);
+
 protected:
 	virtual int init() { return 0; }
 	virtual int run() = 0;
diff --git a/test/log/log_process.cpp b/test/log/log_process.cpp
index d46d5e3..0db7e20 100644
--- a/test/log/log_process.cpp
+++ b/test/log/log_process.cpp
@@ -55,13 +55,24 @@  class LogProcessTest : public Test
 protected:
 	int init()
 	{
+#ifdef HAVE_LIBLOG
+		/* Check required permissions: CAP_SYS_ADMIN: unshare */
+		int ret = testCapabilities(1, CAP_SYS_ADMIN, CAP_EFFECTIVE);
+		if (ret != TestPass) {
+			char *cap = cap_to_name(CAP_SYS_ADMIN);
+			cerr << "Insufficient capability: " << cap << endl;
+			cap_free(cap);
+			return TestSkip;
+		}
+#endif
+
 		random_device random;
 		num_ = random();
 		logPath_ = "/tmp/libcamera.worker.test." +
 			   to_string(num_) + ".log";
 
 		proc_.finished.connect(this, &LogProcessTest::procFinished);
-		return 0;
+		return TestPass;
 	}
 
 	int run()
diff --git a/test/log/meson.build b/test/log/meson.build
index 8cd664e..d4745a1 100644
--- a/test/log/meson.build
+++ b/test/log/meson.build
@@ -7,7 +7,8 @@  log_test = [
 
 foreach t : log_test
     exe = executable(t[0], t[1],
-                     dependencies : libcamera_dep,
+                     dependencies : [ libcamera_dep, libtest_dep ],
+                     cpp_args : libtest_cpp_args,
                      link_with : test_libraries,
                      include_directories : test_includes_internal)
 
diff --git a/test/meson.build b/test/meson.build
index 0a1d434..ea48b32 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -1,5 +1,14 @@ 
 # SPDX-License-Identifier: CC0-1.0
 
+libtest_dep = []
+libtest_cpp_args = []
+
+libcap = dependency('libcap', required : false)
+if libcap.found()
+    libtest_dep += [ libcap ]
+    libtest_cpp_args += [ '-DHAVE_LIBLOG' ]
+endif
+
 subdir('libtest')
 
 subdir('camera')
@@ -46,7 +55,8 @@  internal_tests = [
 
 foreach t : public_tests
     exe = executable(t[0], t[1],
-                     dependencies : libcamera_dep,
+                     dependencies : [ libcamera_dep, libtest_dep ],
+                     cpp_args : libtest_cpp_args,
                      link_with : test_libraries,
                      include_directories : test_includes_public)
 
@@ -55,7 +65,8 @@  endforeach
 
 foreach t : internal_tests
     exe = executable(t[0], t[1],
-                     dependencies : libcamera_dep,
+                     dependencies : [ libcamera_dep, libtest_dep ],
+                     cpp_args : libtest_cpp_args,
                      link_with : test_libraries,
                      include_directories : test_includes_internal)
 
diff --git a/test/process/meson.build b/test/process/meson.build
index c215fa7..c141042 100644
--- a/test/process/meson.build
+++ b/test/process/meson.build
@@ -6,7 +6,8 @@  process_tests = [
 
 foreach t : process_tests
     exe = executable(t[0], t[1],
-                     dependencies : libcamera_dep,
+                     dependencies : [ libcamera_dep, libtest_dep ],
+                     cpp_args : libtest_cpp_args,
                      link_with : test_libraries,
                      include_directories : test_includes_internal)
 
diff --git a/test/process/process_test.cpp b/test/process/process_test.cpp
index 721a7c9..6386826 100644
--- a/test/process/process_test.cpp
+++ b/test/process/process_test.cpp
@@ -41,6 +41,21 @@  public:
 	}
 
 protected:
+	int init()
+	{
+#ifdef HAVE_LIBLOG
+		/* Check required permissions: CAP_SYS_ADMIN: unshare */
+		int ret = testCapabilities(1, CAP_SYS_ADMIN, CAP_EFFECTIVE);
+		if (ret != TestPass) {
+			char *cap = cap_to_name(CAP_SYS_ADMIN);
+			cerr << "Insufficient capability: " << cap << endl;
+			cap_free(cap);
+			return TestSkip;
+		}
+#endif
+		return TestPass;
+	}
+
 	int run()
 	{
 		EventDispatcher *dispatcher = Thread::current()->eventDispatcher();