summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp389
1 files changed, 389 insertions, 0 deletions
diff --git a/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp b/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp
new file mode 100644
index 00000000..dfe363ee
--- /dev/null
+++ b/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp
@@ -0,0 +1,389 @@
+/* $Id: tstClipboardTransfers.cpp $ */
+/** @file
+ * Shared Clipboard transfers test case.
+ */
+
+/*
+ * Copyright (C) 2019-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
+ */
+
+#include "../VBoxSharedClipboardSvc-internal.h"
+
+#include <VBox/HostServices/VBoxClipboardSvc.h>
+
+#include <iprt/assert.h>
+#include <iprt/dir.h>
+#include <iprt/file.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include <iprt/test.h>
+
+
+static int testCreateTempDir(RTTEST hTest, const char *pszTestcase, char *pszTempDir, size_t cbTempDir)
+{
+ char szTempDir[RTPATH_MAX];
+ int rc = RTPathTemp(szTempDir, sizeof(szTempDir));
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ rc = RTPathAppend(szTempDir, sizeof(szTempDir), "tstClipboardTransfers");
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ rc = RTDirCreate(szTempDir, 0700, 0);
+ if (rc == VERR_ALREADY_EXISTS)
+ rc = VINF_SUCCESS;
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ rc = RTPathAppend(szTempDir, sizeof(szTempDir), "XXXXX");
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ rc = RTDirCreateTemp(szTempDir, 0700);
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ rc = RTPathJoin(pszTempDir, cbTempDir, szTempDir, pszTestcase);
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Created temporary directory: %s\n", pszTempDir);
+
+ return rc;
+}
+
+static int testRemoveTempDir(RTTEST hTest)
+{
+ char szTempDir[RTPATH_MAX];
+ int rc = RTPathTemp(szTempDir, sizeof(szTempDir));
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ rc = RTPathAppend(szTempDir, sizeof(szTempDir), "tstClipboardTransfers");
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ rc = RTDirRemoveRecursive(szTempDir, RTDIRRMREC_F_CONTENT_AND_DIR);
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Removed temporary directory: %s\n", szTempDir);
+
+ return rc;
+}
+
+static int testCreateDir(RTTEST hTest, const char *pszPathToCreate)
+{
+ RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Creating directory: %s\n", pszPathToCreate);
+
+ int rc = RTDirCreateFullPath(pszPathToCreate, 0700);
+ if (rc == VERR_ALREADY_EXISTS)
+ rc = VINF_SUCCESS;
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+
+ return rc;
+}
+
+static int testCreateFile(RTTEST hTest, const char *pszTempDir, const char *pszFileName, uint32_t fOpen, size_t cbSize,
+ char **ppszFilePathAbs)
+{
+ char szFilePath[RTPATH_MAX];
+
+ int rc = RTStrCopy(szFilePath, sizeof(szFilePath), pszTempDir);
+ RTTESTI_CHECK_RC_OK_RET(rc, rc);
+
+ rc = RTPathAppend(szFilePath, sizeof(szFilePath), pszFileName);
+ RTTESTI_CHECK_RC_OK_RET(rc, rc);
+
+ char *pszDirToCreate = RTStrDup(szFilePath);
+ RTTESTI_CHECK_RET(pszDirToCreate, VERR_NO_MEMORY);
+
+ RTPathStripFilename(pszDirToCreate);
+
+ rc = testCreateDir(hTest, pszDirToCreate);
+ RTTESTI_CHECK_RC_OK_RET(rc, rc);
+
+ RTStrFree(pszDirToCreate);
+ pszDirToCreate = NULL;
+
+ if (!fOpen)
+ fOpen = RTFILE_O_OPEN_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE;
+
+ RTTestPrintf(hTest, RTTESTLVL_DEBUG, "Creating file: %s\n", szFilePath);
+
+ RTFILE hFile;
+ rc = RTFileOpen(&hFile, szFilePath, fOpen);
+ if (RT_SUCCESS(rc))
+ {
+ if (cbSize)
+ {
+ /** @todo Fill in some random stuff. */
+ }
+
+ rc = RTFileClose(hFile);
+ RTTESTI_CHECK_RC_RET(rc, VINF_SUCCESS, rc);
+ }
+
+ if (ppszFilePathAbs)
+ *ppszFilePathAbs = RTStrDup(szFilePath);
+
+ return rc;
+}
+
+typedef struct TESTTRANSFERROOTENTRY
+{
+ TESTTRANSFERROOTENTRY(const RTCString &a_strPath)
+ : strPath(a_strPath) { }
+
+ RTCString strPath;
+} TESTTRANSFERROOTENTRY;
+
+static int testAddRootEntry(RTTEST hTest, const char *pszTempDir,
+ const TESTTRANSFERROOTENTRY &rootEntry, char **ppszRoots)
+{
+ char *pszRoots = NULL;
+
+ const char *pszPath = rootEntry.strPath.c_str();
+
+ char *pszPathAbs;
+ int rc = testCreateFile(hTest, pszTempDir, pszPath, 0, 0, &pszPathAbs);
+ RTTESTI_CHECK_RC_OK_RET(rc, rc);
+
+ rc = RTStrAAppend(&pszRoots, pszPathAbs);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ rc = RTStrAAppend(&pszRoots, "\r\n");
+ RTTESTI_CHECK_RC_OK(rc);
+
+ RTStrFree(pszPathAbs);
+
+ *ppszRoots = pszRoots;
+
+ return rc;
+}
+
+static int testAddRootEntries(RTTEST hTest, const char *pszTempDir,
+ RTCList<TESTTRANSFERROOTENTRY> &lstBase, RTCList<TESTTRANSFERROOTENTRY> lstToExtend,
+ char **ppszRoots)
+{
+ int rc = VINF_SUCCESS;
+
+ char *pszRoots = NULL;
+
+ for (size_t i = 0; i < lstBase.size(); ++i)
+ {
+ char *pszEntry = NULL;
+ rc = testAddRootEntry(hTest, pszTempDir, lstBase.at(i), &pszEntry);
+ RTTESTI_CHECK_RC_OK_BREAK(rc);
+ rc = RTStrAAppend(&pszRoots, pszEntry);
+ RTTESTI_CHECK_RC_OK_BREAK(rc);
+ RTStrFree(pszEntry);
+ }
+
+ for (size_t i = 0; i < lstToExtend.size(); ++i)
+ {
+ char *pszEntry = NULL;
+ rc = testAddRootEntry(hTest, pszTempDir, lstToExtend.at(i), &pszEntry);
+ RTTESTI_CHECK_RC_OK_BREAK(rc);
+ rc = RTStrAAppend(&pszRoots, pszEntry);
+ RTTESTI_CHECK_RC_OK_BREAK(rc);
+ RTStrFree(pszEntry);
+ }
+
+ if (RT_SUCCESS(rc))
+ *ppszRoots = pszRoots;
+
+ return rc;
+}
+
+static void testTransferRootsSetSingle(RTTEST hTest,
+ RTCList<TESTTRANSFERROOTENTRY> &lstBase, RTCList<TESTTRANSFERROOTENTRY> lstToExtend,
+ int rcExpected)
+{
+ PSHCLTRANSFER pTransfer;
+ int rc = ShClTransferCreate(&pTransfer);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ char szTestTransferRootsSetDir[RTPATH_MAX];
+ rc = testCreateTempDir(hTest, "testTransferRootsSet", szTestTransferRootsSetDir, sizeof(szTestTransferRootsSetDir));
+ RTTESTI_CHECK_RC_OK_RETV(rc);
+
+ /* This is the file we're trying to access (but not supposed to). */
+ rc = testCreateFile(hTest, szTestTransferRootsSetDir, "must-not-access-this", 0, 0, NULL);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ char *pszRoots;
+ rc = testAddRootEntries(hTest, szTestTransferRootsSetDir, lstBase, lstToExtend, &pszRoots);
+ RTTESTI_CHECK_RC_OK_RETV(rc);
+
+ rc = ShClTransferRootsSet(pTransfer, pszRoots, strlen(pszRoots) + 1);
+ RTTESTI_CHECK_RC(rc, rcExpected);
+
+ RTStrFree(pszRoots);
+
+ rc = ShClTransferDestroy(pTransfer);
+ RTTESTI_CHECK_RC_OK(rc);
+}
+
+static void testTransferObjOpenSingle(RTTEST hTest,
+ RTCList<TESTTRANSFERROOTENTRY> &lstRoots, const char *pszObjPath, int rcExpected)
+{
+ RT_NOREF(hTest);
+
+ PSHCLTRANSFER pTransfer;
+ int rc = ShClTransferCreate(&pTransfer);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ rc = ShClTransferInit(pTransfer, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_LOCAL);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ char szTestTransferObjOpenDir[RTPATH_MAX];
+ rc = testCreateTempDir(hTest, "testTransferObjOpen", szTestTransferObjOpenDir, sizeof(szTestTransferObjOpenDir));
+ RTTESTI_CHECK_RC_OK_RETV(rc);
+
+ /* This is the file we're trying to access (but not supposed to). */
+ rc = testCreateFile(hTest, szTestTransferObjOpenDir, "file1.txt", 0, 0, NULL);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ RTCList<TESTTRANSFERROOTENTRY> lstToExtendEmpty;
+
+ char *pszRoots;
+ rc = testAddRootEntries(hTest, szTestTransferObjOpenDir, lstRoots, lstToExtendEmpty, &pszRoots);
+ RTTESTI_CHECK_RC_OK_RETV(rc);
+
+ rc = ShClTransferRootsSet(pTransfer, pszRoots, strlen(pszRoots) + 1);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ RTStrFree(pszRoots);
+
+ SHCLOBJOPENCREATEPARMS openCreateParms;
+ rc = ShClTransferObjOpenParmsInit(&openCreateParms);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ rc = RTStrCopy(openCreateParms.pszPath, openCreateParms.cbPath, pszObjPath);
+ RTTESTI_CHECK_RC_OK(rc);
+
+ SHCLOBJHANDLE hObj;
+ rc = ShClTransferObjOpen(pTransfer, &openCreateParms, &hObj);
+ RTTESTI_CHECK_RC(rc, rcExpected);
+ if (RT_SUCCESS(rc))
+ {
+ rc = ShClTransferObjClose(pTransfer, hObj);
+ RTTESTI_CHECK_RC_OK(rc);
+ }
+
+ rc = ShClTransferDestroy(pTransfer);
+ RTTESTI_CHECK_RC_OK(rc);
+}
+
+static void testTransferBasics(RTTEST hTest)
+{
+ RT_NOREF(hTest);
+
+ RTTestISub("Testing transfer basics");
+
+ SHCLEVENTSOURCE Source;
+ int rc = ShClEventSourceCreate(&Source, 0);
+ RTTESTI_CHECK_RC_OK(rc);
+ rc = ShClEventSourceDestroy(&Source);
+ RTTESTI_CHECK_RC_OK(rc);
+ PSHCLTRANSFER pTransfer;
+ rc = ShClTransferCreate(&pTransfer);
+ RTTESTI_CHECK_RC_OK(rc);
+ rc = ShClTransferDestroy(pTransfer);
+ RTTESTI_CHECK_RC_OK(rc);
+}
+
+static void testTransferRootsSet(RTTEST hTest)
+{
+ RTTestISub("Testing setting transfer roots");
+
+ /* Define the (valid) transfer root set. */
+ RTCList<TESTTRANSFERROOTENTRY> lstBase;
+ lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/file1.txt"));
+ lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir1/file1.txt"));
+ lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir1/sub1/file1.txt"));
+ lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir2/file1.txt"));
+ lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir2/sub1/file1.txt"));
+
+ RTCList<TESTTRANSFERROOTENTRY> lstBreakout;
+ testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VINF_SUCCESS);
+
+ lstBreakout.clear();
+ lstBase.append(TESTTRANSFERROOTENTRY("../must-not-access-this"));
+ testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
+
+ lstBreakout.clear();
+ lstBase.append(TESTTRANSFERROOTENTRY("does-not-exist/file1.txt"));
+ testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
+
+ lstBreakout.clear();
+ lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/../must-not-access-this"));
+ testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
+
+ lstBreakout.clear();
+ lstBase.append(TESTTRANSFERROOTENTRY("my-transfer-1/./../must-not-access-this"));
+ testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
+
+ lstBreakout.clear();
+ lstBase.append(TESTTRANSFERROOTENTRY("../does-not-exist"));
+ testTransferRootsSetSingle(hTest, lstBase, lstBreakout, VERR_INVALID_PARAMETER);
+}
+
+static void testTransferObjOpen(RTTEST hTest)
+{
+ RTTestISub("Testing setting transfer object open");
+
+ /* Define the (valid) transfer root set. */
+ RTCList<TESTTRANSFERROOTENTRY> lstRoots;
+ lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/file1.txt"));
+ lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir1/file1.txt"));
+ lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir1/sub1/file1.txt"));
+ lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir2/file1.txt"));
+ lstRoots.append(TESTTRANSFERROOTENTRY("my-transfer-1/dir2/sub1/file1.txt"));
+
+ testTransferObjOpenSingle(hTest, lstRoots, "file1.txt", VINF_SUCCESS);
+ testTransferObjOpenSingle(hTest, lstRoots, "does-not-exist.txt", VERR_PATH_NOT_FOUND);
+ testTransferObjOpenSingle(hTest, lstRoots, "dir1/does-not-exist.txt", VERR_PATH_NOT_FOUND);
+ testTransferObjOpenSingle(hTest, lstRoots, "../must-not-access-this.txt", VERR_INVALID_PARAMETER);
+ testTransferObjOpenSingle(hTest, lstRoots, "dir1/../../must-not-access-this.txt", VERR_INVALID_PARAMETER);
+}
+
+int main(int argc, char *argv[])
+{
+ /*
+ * Init the runtime, test and say hello.
+ */
+ const char *pcszExecName;
+ NOREF(argc);
+ pcszExecName = strrchr(argv[0], '/');
+ pcszExecName = pcszExecName ? pcszExecName + 1 : argv[0];
+ RTTEST hTest;
+ RTEXITCODE rcExit = RTTestInitAndCreate(pcszExecName, &hTest);
+ if (rcExit != RTEXITCODE_SUCCESS)
+ return rcExit;
+ RTTestBanner(hTest);
+
+ testTransferBasics(hTest);
+ testTransferRootsSet(hTest);
+ testTransferObjOpen(hTest);
+
+ int rc = testRemoveTempDir(hTest);
+ RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
+
+ /*
+ * Summary
+ */
+ return RTTestSummaryAndDestroy(hTest);
+}
+