diff options
Diffstat (limited to 'src/plugins/remotelinux/filesystemaccess_test.cpp')
-rw-r--r-- | src/plugins/remotelinux/filesystemaccess_test.cpp | 360 |
1 files changed, 355 insertions, 5 deletions
diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp index fcc8477974a..2edb78fa7b3 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.cpp +++ b/src/plugins/remotelinux/filesystemaccess_test.cpp @@ -9,7 +9,11 @@ #include <projectexplorer/devicesupport/filetransfer.h> #include <projectexplorer/devicesupport/sshparameters.h> #include <utils/filepath.h> +#include <utils/filestreamer.h> +#include <utils/filestreamermanager.h> +#include <utils/process.h> #include <utils/processinterface.h> +#include <utils/scopedtimer.h> #include <QDebug> #include <QFile> @@ -86,6 +90,45 @@ void FileSystemAccessTest::initTestCase() QVERIFY(!filePath.exists()); QVERIFY(filePath.createDir()); QVERIFY(filePath.exists()); + + const QString streamerLocalDir("streamerLocalDir"); + const QString streamerRemoteDir("streamerRemoteDir"); + const QString sourceDir("source"); + const QString destDir("dest"); + const QString localDir("local"); + const QString remoteDir("remote"); + const FilePath localRoot; + const FilePath remoteRoot = m_device->rootPath(); + const FilePath localTempDir = *localRoot.tmpDir(); + const FilePath remoteTempDir = *remoteRoot.tmpDir(); + m_localStreamerDir = localTempDir / streamerLocalDir; + m_remoteStreamerDir = remoteTempDir / streamerRemoteDir; + m_localSourceDir = m_localStreamerDir / sourceDir; + m_remoteSourceDir = m_remoteStreamerDir / sourceDir; + m_localDestDir = m_localStreamerDir / destDir; + m_remoteDestDir = m_remoteStreamerDir / destDir; + m_localLocalDestDir = m_localDestDir / localDir; + m_localRemoteDestDir = m_localDestDir / remoteDir; + m_remoteLocalDestDir = m_remoteDestDir / localDir; + m_remoteRemoteDestDir = m_remoteDestDir / remoteDir; + + QVERIFY(m_localSourceDir.createDir()); + QVERIFY(m_remoteSourceDir.createDir()); + QVERIFY(m_localDestDir.createDir()); + QVERIFY(m_remoteDestDir.createDir()); + QVERIFY(m_localLocalDestDir.createDir()); + QVERIFY(m_localRemoteDestDir.createDir()); + QVERIFY(m_remoteLocalDestDir.createDir()); + QVERIFY(m_remoteRemoteDestDir.createDir()); + + QVERIFY(m_localSourceDir.exists()); + QVERIFY(m_remoteSourceDir.exists()); + QVERIFY(m_localDestDir.exists()); + QVERIFY(m_remoteDestDir.exists()); + QVERIFY(m_localLocalDestDir.exists()); + QVERIFY(m_localRemoteDestDir.exists()); + QVERIFY(m_remoteLocalDestDir.exists()); + QVERIFY(m_remoteRemoteDestDir.exists()); } void FileSystemAccessTest::cleanupTestCase() @@ -94,6 +137,14 @@ void FileSystemAccessTest::cleanupTestCase() return; QVERIFY(baseFilePath().exists()); QVERIFY(baseFilePath().removeRecursively()); + + QVERIFY(m_localStreamerDir.removeRecursively()); + QVERIFY(m_remoteStreamerDir.removeRecursively()); + + QVERIFY(!m_localStreamerDir.exists()); + QVERIFY(!m_remoteStreamerDir.exists()); + + FileStreamerManager::stopAll(); } void FileSystemAccessTest::testCreateRemoteFile_data() @@ -102,13 +153,13 @@ void FileSystemAccessTest::testCreateRemoteFile_data() QTest::newRow("Spaces") << QByteArray("Line with spaces"); QTest::newRow("Newlines") << QByteArray("Some \n\n newlines \n"); - QTest::newRow("Carriage return") << QByteArray("Line with carriage \r return"); + QTest::newRow("CarriageReturn") << QByteArray("Line with carriage \r return"); QTest::newRow("Tab") << QByteArray("Line with \t tab"); QTest::newRow("Apostrophe") << QByteArray("Line with apostrophe's character"); - QTest::newRow("Quotation marks") << QByteArray("Line with \"quotation marks\""); - QTest::newRow("Backslash 1") << QByteArray("Line with \\ backslash"); - QTest::newRow("Backslash 2") << QByteArray("Line with \\\" backslash"); - QTest::newRow("Command output") << QByteArray("The date is: $(date +%D)"); + QTest::newRow("QuotationMarks") << QByteArray("Line with \"quotation marks\""); + QTest::newRow("Backslash1") << QByteArray("Line with \\ backslash"); + QTest::newRow("Backslash2") << QByteArray("Line with \\\" backslash"); + QTest::newRow("CommandOutput") << QByteArray("The date is: $(date +%D)"); const int charSize = sizeof(char) * 0x100; QByteArray charString(charSize, Qt::Uninitialized); @@ -132,6 +183,21 @@ void FileSystemAccessTest::testCreateRemoteFile() QVERIFY(!testFilePath.exists()); } +void FileSystemAccessTest::testWorkingDirectory() +{ + const FilePath dir = baseFilePath() / "testdir with space and 'various' \"quotes\" here"; + QVERIFY(dir.ensureWritableDir()); + Process proc; + proc.setCommand({"pwd", {}}); + proc.setWorkingDirectory(dir); + proc.start(); + QVERIFY(proc.waitForFinished()); + const QString out = proc.readAllStandardOutput().trimmed(); + QCOMPARE(out, dir.path()); + const QString err = proc.readAllStandardOutput(); + QVERIFY(err.isEmpty()); +} + void FileSystemAccessTest::testDirStatus() { FilePath filePath = baseFilePath(); @@ -201,6 +267,8 @@ void FileSystemAccessTest::testFileTransfer_data() QTest::addColumn<FileTransferMethod>("fileTransferMethod"); QTest::addRow("Sftp") << FileTransferMethod::Sftp; + // TODO: By default rsync doesn't support creating target directories, + // needs to be done manually - see RsyncDeployService. // QTest::addRow("Rsync") << FileTransferMethod::Rsync; } @@ -282,5 +350,287 @@ void FileSystemAccessTest::testFileTransfer() QVERIFY2(remoteDir.removeRecursively(&errorString), qPrintable(errorString)); } +void FileSystemAccessTest::testFileStreamer_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QByteArray>("data"); + + const QByteArray spaces("Line with spaces"); + const QByteArray newlines("Some \n\n newlines \n"); + const QByteArray carriageReturn("Line with carriage \r return"); + const QByteArray tab("Line with \t tab"); + const QByteArray apostrophe("Line with apostrophe's character"); + const QByteArray quotationMarks("Line with \"quotation marks\""); + const QByteArray backslash1("Line with \\ backslash"); + const QByteArray backslash2("Line with \\\" backslash"); + const QByteArray commandOutput("The date is: $(date +%D)"); + + const int charSize = sizeof(char) * 0x100; + QByteArray charString(charSize, Qt::Uninitialized); + char *data = charString.data(); + for (int c = 0; c < charSize; ++c) + data[c] = c; + + const int bigSize = 1024 * 1024; // = 256 * 1024 * 1024 = 268.435.456 bytes + QByteArray bigString; + for (int i = 0; i < bigSize; ++i) + bigString += charString; + + QTest::newRow("Spaces") << QString("spaces") << spaces; + QTest::newRow("Newlines") << QString("newlines") << newlines; + QTest::newRow("CarriageReturn") << QString("carriageReturn") << carriageReturn; + QTest::newRow("Tab") << QString("tab") << tab; + QTest::newRow("Apostrophe") << QString("apostrophe") << apostrophe; + QTest::newRow("QuotationMarks") << QString("quotationMarks") << quotationMarks; + QTest::newRow("Backslash1") << QString("backslash1") << backslash1; + QTest::newRow("Backslash2") << QString("backslash2") << backslash2; + QTest::newRow("CommandOutput") << QString("commandOutput") << commandOutput; + QTest::newRow("AllCharacters") << QString("charString") << charString; + QTest::newRow("BigString") << QString("bigString") << bigString; +} + +void FileSystemAccessTest::testFileStreamer() +{ + QTC_SCOPED_TIMER("testFileStreamer"); + + QFETCH(QString, fileName); + QFETCH(QByteArray, data); + + const FilePath localSourcePath = m_localSourceDir / fileName; + const FilePath remoteSourcePath = m_remoteSourceDir / fileName; + const FilePath localLocalDestPath = m_localDestDir / "local" / fileName; + const FilePath localRemoteDestPath = m_localDestDir / "remote" / fileName; + const FilePath remoteLocalDestPath = m_remoteDestDir / "local" / fileName; + const FilePath remoteRemoteDestPath = m_remoteDestDir / "remote" / fileName; + + localSourcePath.removeFile(); + remoteSourcePath.removeFile(); + localLocalDestPath.removeFile(); + localRemoteDestPath.removeFile(); + remoteLocalDestPath.removeFile(); + remoteRemoteDestPath.removeFile(); + + QVERIFY(!localSourcePath.exists()); + QVERIFY(!remoteSourcePath.exists()); + QVERIFY(!localLocalDestPath.exists()); + QVERIFY(!localRemoteDestPath.exists()); + QVERIFY(!remoteLocalDestPath.exists()); + QVERIFY(!remoteRemoteDestPath.exists()); + + std::optional<QByteArray> localData; + std::optional<QByteArray> remoteData; + std::optional<QByteArray> localLocalData; + std::optional<QByteArray> localRemoteData; + std::optional<QByteArray> remoteLocalData; + std::optional<QByteArray> remoteRemoteData; + + using namespace Tasking; + + const auto localWriter = [&] { + const auto setup = [&](FileStreamer &streamer) { + streamer.setStreamMode(StreamMode::Writer); + streamer.setDestination(localSourcePath); + streamer.setWriteData(data); + }; + return FileStreamerTask(setup); + }; + const auto remoteWriter = [&] { + const auto setup = [&](FileStreamer &streamer) { + streamer.setStreamMode(StreamMode::Writer); + streamer.setDestination(remoteSourcePath); + streamer.setWriteData(data); + }; + return FileStreamerTask(setup); + }; + const auto localReader = [&] { + const auto setup = [&](FileStreamer &streamer) { + streamer.setStreamMode(StreamMode::Reader); + streamer.setSource(localSourcePath); + }; + const auto onDone = [&](const FileStreamer &streamer) { + localData = streamer.readData(); + }; + return FileStreamerTask(setup, onDone); + }; + const auto remoteReader = [&] { + const auto setup = [&](FileStreamer &streamer) { + streamer.setStreamMode(StreamMode::Reader); + streamer.setSource(remoteSourcePath); + }; + const auto onDone = [&](const FileStreamer &streamer) { + remoteData = streamer.readData(); + }; + return FileStreamerTask(setup, onDone); + }; + const auto transfer = [](const FilePath &source, const FilePath &dest, + std::optional<QByteArray> *result) { + const auto setupTransfer = [=](FileStreamer &streamer) { + streamer.setSource(source); + streamer.setDestination(dest); + }; + const auto setupReader = [=](FileStreamer &streamer) { + streamer.setStreamMode(StreamMode::Reader); + streamer.setSource(dest); + }; + const auto onReaderDone = [result](const FileStreamer &streamer) { + *result = streamer.readData(); + }; + const Group root { + FileStreamerTask(setupTransfer), + FileStreamerTask(setupReader, onReaderDone) + }; + return root; + }; + + // In total: 5 local reads, 3 local writes, 5 remote reads, 3 remote writes + const Group root { + Group { + parallel, + localWriter(), + remoteWriter() + }, + Group { + parallel, + localReader(), + remoteReader() + }, + Group { + parallel, + transfer(localSourcePath, localLocalDestPath, &localLocalData), + transfer(remoteSourcePath, localRemoteDestPath, &localRemoteData), + transfer(localSourcePath, remoteLocalDestPath, &remoteLocalData), + transfer(remoteSourcePath, remoteRemoteDestPath, &remoteRemoteData), + } + }; + + using namespace std::chrono_literals; + QVERIFY(TaskTree::runBlocking(root, 10000ms)); + + QVERIFY(localData); + QCOMPARE(*localData, data); + QVERIFY(remoteData); + QCOMPARE(*remoteData, data); + + QVERIFY(localLocalData); + QCOMPARE(*localLocalData, data); + QVERIFY(localRemoteData); + QCOMPARE(*localRemoteData, data); + QVERIFY(remoteLocalData); + QCOMPARE(*remoteLocalData, data); + QVERIFY(remoteRemoteData); + QCOMPARE(*remoteRemoteData, data); +} + +void FileSystemAccessTest::testFileStreamerManager_data() +{ + testFileStreamer_data(); +} + +void FileSystemAccessTest::testFileStreamerManager() +{ + QTC_SCOPED_TIMER("testFileStreamerManager"); + + QFETCH(QString, fileName); + QFETCH(QByteArray, data); + + const FilePath localSourcePath = m_localSourceDir / fileName; + const FilePath remoteSourcePath = m_remoteSourceDir / fileName; + const FilePath localLocalDestPath = m_localDestDir / "local" / fileName; + const FilePath localRemoteDestPath = m_localDestDir / "remote" / fileName; + const FilePath remoteLocalDestPath = m_remoteDestDir / "local" / fileName; + const FilePath remoteRemoteDestPath = m_remoteDestDir / "remote" / fileName; + + localSourcePath.removeFile(); + remoteSourcePath.removeFile(); + localLocalDestPath.removeFile(); + localRemoteDestPath.removeFile(); + remoteLocalDestPath.removeFile(); + remoteRemoteDestPath.removeFile(); + + QVERIFY(!localSourcePath.exists()); + QVERIFY(!remoteSourcePath.exists()); + QVERIFY(!localLocalDestPath.exists()); + QVERIFY(!localRemoteDestPath.exists()); + QVERIFY(!remoteLocalDestPath.exists()); + QVERIFY(!remoteRemoteDestPath.exists()); + + std::optional<QByteArray> localData; + std::optional<QByteArray> remoteData; + std::optional<QByteArray> localLocalData; + std::optional<QByteArray> localRemoteData; + std::optional<QByteArray> remoteLocalData; + std::optional<QByteArray> remoteRemoteData; + + QEventLoop eventLoop1; + QEventLoop *loop = &eventLoop1; + int counter = 0; + int *hitCount = &counter; + + const auto writeAndRead = [hitCount, loop, data](const FilePath &destination, + std::optional<QByteArray> *result) { + const auto onWrite = [hitCount, loop, destination, result] + (const expected_str<qint64> &writeResult) { + QVERIFY(writeResult); + const auto onRead = [hitCount, loop, result] + (const expected_str<QByteArray> &readResult) { + QVERIFY(readResult); + *result = *readResult; + ++(*hitCount); + if (*hitCount == 2) + loop->quit(); + }; + FileStreamerManager::read(destination, onRead); + }; + FileStreamerManager::write(destination, data, onWrite); + }; + + writeAndRead(localSourcePath, &localData); + writeAndRead(remoteSourcePath, &remoteData); + loop->exec(); + + QVERIFY(localData); + QCOMPARE(*localData, data); + QVERIFY(remoteData); + QCOMPARE(*remoteData, data); + + QEventLoop eventLoop2; + loop = &eventLoop2; + counter = 0; + + const auto transferAndRead = [hitCount, loop, data](const FilePath &source, + const FilePath &destination, + std::optional<QByteArray> *result) { + const auto onTransfer = [hitCount, loop, destination, result] + (const expected_str<void> &transferResult) { + QVERIFY(transferResult); + const auto onRead = [hitCount, loop, result] + (const expected_str<QByteArray> &readResult) { + QVERIFY(readResult); + *result = *readResult; + ++(*hitCount); + if (*hitCount == 4) + loop->quit(); + }; + FileStreamerManager::read(destination, onRead); + }; + FileStreamerManager::copy(source, destination, onTransfer); + }; + + transferAndRead(localSourcePath, localLocalDestPath, &localLocalData); + transferAndRead(remoteSourcePath, localRemoteDestPath, &localRemoteData); + transferAndRead(localSourcePath, remoteLocalDestPath, &remoteLocalData); + transferAndRead(remoteSourcePath, remoteRemoteDestPath, &remoteRemoteData); + loop->exec(); + + QVERIFY(localLocalData); + QCOMPARE(*localLocalData, data); + QVERIFY(localRemoteData); + QCOMPARE(*localRemoteData, data); + QVERIFY(remoteLocalData); + QCOMPARE(*remoteLocalData, data); + QVERIFY(remoteRemoteData); + QCOMPARE(*remoteRemoteData, data); +} + } // Internal } // RemoteLinux |