summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/testcase/tstUSBProxyLinux.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/testcase/tstUSBProxyLinux.cpp')
-rw-r--r--src/VBox/Main/testcase/tstUSBProxyLinux.cpp195
1 files changed, 195 insertions, 0 deletions
diff --git a/src/VBox/Main/testcase/tstUSBProxyLinux.cpp b/src/VBox/Main/testcase/tstUSBProxyLinux.cpp
new file mode 100644
index 00000000..41f885d9
--- /dev/null
+++ b/src/VBox/Main/testcase/tstUSBProxyLinux.cpp
@@ -0,0 +1,195 @@
+/* $Id: tstUSBProxyLinux.cpp $ */
+/** @file
+ * USBProxyBackendLinux test case.
+ */
+
+/*
+ * Copyright (C) 2011-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+
+#include "USBGetDevices.h"
+
+#include <VBox/err.h>
+#include <iprt/assert.h>
+#include <iprt/env.h>
+#include <iprt/string.h>
+#include <iprt/test.h>
+
+/*** BEGIN STUBS ***/
+
+static struct
+{
+ const char *pcszEnvUsb;
+ const char *pcszEnvUsbRoot;
+ const char *pcszDevicesRoot;
+ bool fDevicesAccessible;
+ const char *pcszUsbfsRoot;
+ bool fUsbfsAccessible;
+ int rcMethodInit;
+ const char *pcszDevicesRootExpected;
+ bool fUsingUsbfsExpected;
+ int rcExpected;
+} s_testEnvironment[] =
+{
+ /* "sysfs" and valid root in the environment */
+ { "sysfs", "/dev/bus/usb", "/dev/bus/usb", true, NULL, false, VINF_SUCCESS, "/dev/bus/usb", false, VINF_SUCCESS },
+ /* "sysfs" and bad root in the environment */
+ { "sysfs", "/dev/bus/usb", "/dev/vboxusb", false, "/proc/usb/bus", false, VINF_SUCCESS, "", true, VERR_NOT_FOUND },
+ /* "sysfs" and no root in the environment */
+ { "sysfs", NULL, "/dev/vboxusb", true, NULL, false, VINF_SUCCESS, "/dev/vboxusb", false, VINF_SUCCESS },
+ /* "usbfs" and valid root in the environment */
+ { "usbfs", "/dev/bus/usb", NULL, false, "/dev/bus/usb", true, VINF_SUCCESS, "/dev/bus/usb", true, VINF_SUCCESS },
+ /* "usbfs" and bad root in the environment */
+ { "usbfs", "/dev/bus/usb", "/dev/vboxusb", false, "/proc/usb/bus", false, VINF_SUCCESS, "", true, VERR_NOT_FOUND },
+ /* "usbfs" and no root in the environment */
+ { "usbfs", NULL, NULL, false, "/proc/bus/usb", true, VINF_SUCCESS, "/proc/bus/usb", true, VINF_SUCCESS },
+ /* invalid method in the environment, sysfs available */
+ { "invalid", "/dev/bus/usb", "/dev/vboxusb", true, NULL, false, VINF_SUCCESS, "/dev/vboxusb", false, VINF_SUCCESS },
+ /* invalid method in the environment, usbfs available */
+ { "invalid", "/dev/bus/usb", NULL, true, "/proc/bus/usb", true, VINF_SUCCESS, "/proc/bus/usb", true, VINF_SUCCESS },
+ /* invalid method in the environment, sysfs inaccessible */
+ { "invalid", "/dev/bus/usb", "/dev/vboxusb", false, NULL, false, VINF_SUCCESS, "", true, VERR_VUSB_USB_DEVICE_PERMISSION },
+ /* invalid method in the environment, usbfs inaccessible */
+ { "invalid", "/dev/bus/usb", NULL, false, "/proc/bus/usb", false, VINF_SUCCESS, "", true, VERR_VUSB_USBFS_PERMISSION },
+ /* No environment, sysfs and usbfs available but without access permissions. */
+ { NULL, NULL, "/dev/vboxusb", false, "/proc/bus/usb", false, VERR_NO_MEMORY, "", true, VERR_VUSB_USB_DEVICE_PERMISSION },
+ /* No environment, sysfs and usbfs available, access permissions for sysfs. */
+ { NULL, NULL, "/dev/vboxusb", true, "/proc/bus/usb", false, VINF_SUCCESS, "/dev/vboxusb", false, VINF_SUCCESS },
+ /* No environment, sysfs and usbfs available, access permissions for usbfs. */
+ { NULL, NULL, "/dev/vboxusb", false, "/proc/bus/usb", true, VINF_SUCCESS, "/proc/bus/usb", true, VINF_SUCCESS },
+ /* No environment, sysfs available but without access permissions. */
+ { NULL, NULL, "/dev/vboxusb", false, NULL, false, VERR_NO_MEMORY, "", true, VERR_VUSB_USB_DEVICE_PERMISSION },
+ /* No environment, usbfs available but without access permissions. */
+ { NULL, NULL, NULL, false, "/proc/bus/usb", false, VERR_NO_MEMORY, "", true, VERR_VUSB_USBFS_PERMISSION },
+};
+
+static void testInit(RTTEST hTest)
+{
+ RTTestSub(hTest, "Testing USBProxyLinuxChooseMethod");
+ for (unsigned i = 0; i < RT_ELEMENTS(s_testEnvironment); ++i)
+ {
+ bool fUsingUsbfs = true;
+ const char *pcszDevicesRoot = "";
+
+ TestUSBSetEnv(s_testEnvironment[i].pcszEnvUsb,
+ s_testEnvironment[i].pcszEnvUsbRoot);
+ TestUSBSetupInit(s_testEnvironment[i].pcszUsbfsRoot,
+ s_testEnvironment[i].fUsbfsAccessible,
+ s_testEnvironment[i].pcszDevicesRoot,
+ s_testEnvironment[i].fDevicesAccessible,
+ s_testEnvironment[i].rcMethodInit);
+ int rc = USBProxyLinuxChooseMethod(&fUsingUsbfs, &pcszDevicesRoot);
+ RTTESTI_CHECK_MSG(rc == s_testEnvironment[i].rcExpected,
+ ("rc=%Rrc (test index %i) instead of %Rrc!\n",
+ rc, i, s_testEnvironment[i].rcExpected));
+ RTTESTI_CHECK_MSG(!RTStrCmp(pcszDevicesRoot,
+ s_testEnvironment[i].pcszDevicesRootExpected),
+ ("testGetDevicesRoot() returned %s (test index %i) instead of %s!\n",
+ pcszDevicesRoot, i,
+ s_testEnvironment[i].pcszDevicesRootExpected));
+ RTTESTI_CHECK_MSG( fUsingUsbfs
+ == s_testEnvironment[i].fUsingUsbfsExpected,
+ ("testGetUsingUsbfs() returned %RTbool (test index %i) instead of %RTbool!\n",
+ fUsingUsbfs, i,
+ s_testEnvironment[i].fUsingUsbfsExpected));
+ }
+}
+
+static struct
+{
+ const char *pacszDeviceAddresses[16];
+ const char *pacszAccessibleFiles[16];
+ const char *pcszRoot;
+ bool fIsDeviceNodes;
+ bool fAvailableExpected;
+} s_testCheckDeviceRoot[] =
+{
+ /* /dev/vboxusb accessible -> device nodes method available */
+ { { NULL }, { "/dev/vboxusb" }, "/dev/vboxusb", true, true },
+ /* /dev/vboxusb present but not accessible -> device nodes method not
+ * available */
+ { { NULL }, { NULL }, "/dev/vboxusb", true, false },
+ /* /proc/bus/usb available but empty -> usbfs method available (we can't
+ * really check in this case) */
+ { { NULL }, { "/proc/bus/usb" }, "/proc/bus/usb", false, true },
+ /* /proc/bus/usb not available or not accessible -> usbfs method not available */
+ { { NULL }, { NULL }, "/proc/bus/usb", false, false },
+ /* /proc/bus/usb available, one inaccessible device -> usbfs method not
+ * available */
+ { { "/proc/bus/usb/001/001" }, { "/proc/bus/usb" }, "/proc/bus/usb", false, false },
+ /* /proc/bus/usb available, one device of two inaccessible -> usbfs method
+ * not available */
+ { { "/proc/bus/usb/001/001", "/proc/bus/usb/002/002" },
+ { "/proc/bus/usb", "/proc/bus/usb/001/001" }, "/proc/bus/usb", false, false },
+ /* /proc/bus/usb available, two accessible devices -> usbfs method
+ * available */
+ { { "/proc/bus/usb/001/001", "/proc/bus/usb/002/002" },
+ { "/proc/bus/usb", "/proc/bus/usb/001/001", "/proc/bus/usb/002/002" },
+ "/proc/bus/usb", false, true }
+};
+
+static void testCheckDeviceRoot(RTTEST hTest)
+{
+ RTTestSub(hTest, "Testing the USBProxyLinuxCheckDeviceRoot API");
+ for (unsigned i = 0; i < RT_ELEMENTS(s_testCheckDeviceRoot); ++i)
+ {
+ TestUSBSetAvailableUsbfsDevices(s_testCheckDeviceRoot[i]
+ .pacszDeviceAddresses);
+ TestUSBSetAccessibleFiles(s_testCheckDeviceRoot[i]
+ .pacszAccessibleFiles);
+ bool fAvailable = USBProxyLinuxCheckDeviceRoot
+ (s_testCheckDeviceRoot[i].pcszRoot,
+ s_testCheckDeviceRoot[i].fIsDeviceNodes);
+ RTTESTI_CHECK_MSG( fAvailable
+ == s_testCheckDeviceRoot[i].fAvailableExpected,
+ ("USBProxyLinuxCheckDeviceRoot() returned %RTbool (test index %i) instead of %RTbool!\n",
+ fAvailable, i,
+ s_testCheckDeviceRoot[i].fAvailableExpected));
+ }
+}
+
+int main(void)
+{
+ /*
+ * Init the runtime, test and say hello.
+ */
+ RTTEST hTest;
+ RTEXITCODE rcExit = RTTestInitAndCreate("tstUSBProxyLinux", &hTest);
+ if (rcExit != RTEXITCODE_SUCCESS)
+ return rcExit;
+ RTTestBanner(hTest);
+
+ /*
+ * Run the tests.
+ */
+ testInit(hTest);
+ testCheckDeviceRoot(hTest);
+
+ /*
+ * Summary
+ */
+ return RTTestSummaryAndDestroy(hTest);
+}