2019-10-21 02:04:12 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
2023-11-09 12:23:00 -06:00
|
|
|
* Copyright the Collabora Online contributors.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
|
|
*
|
2019-10-21 02:04:12 -05:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
2021-03-25 08:47:10 -05:00
|
|
|
#include <config.h>
|
|
|
|
|
2019-10-21 02:04:12 -05:00
|
|
|
#include <Unit.hpp>
|
|
|
|
#include <Util.hpp>
|
|
|
|
#include <helpers.hpp>
|
2024-03-20 07:42:03 -05:00
|
|
|
#include <WebSocketSession.hpp>
|
|
|
|
#include <test/lokassert.hpp>
|
|
|
|
|
|
|
|
#include <string>
|
2019-10-21 02:04:12 -05:00
|
|
|
|
|
|
|
/// Load torture testcase.
|
|
|
|
class UnitLoadTorture : public UnitWSD
|
|
|
|
{
|
2024-02-20 11:26:44 -06:00
|
|
|
void loadTorture(const std::string& name, const std::string& docName,
|
|
|
|
const size_t thread_count, const size_t max_jitter_ms = 100);
|
2019-10-21 02:04:12 -05:00
|
|
|
TestResult testLoadTortureODT();
|
|
|
|
TestResult testLoadTortureODS();
|
|
|
|
TestResult testLoadTortureODP();
|
2024-02-20 11:26:44 -06:00
|
|
|
TestResult testLoadTortureODG();
|
2019-10-21 02:04:12 -05:00
|
|
|
TestResult testLoadTorture();
|
|
|
|
|
|
|
|
public:
|
2020-01-30 02:17:28 -06:00
|
|
|
UnitLoadTorture();
|
2020-12-24 11:15:37 -06:00
|
|
|
void invokeWSDTest() override;
|
2019-10-21 02:04:12 -05:00
|
|
|
};
|
|
|
|
|
2024-02-20 11:26:44 -06:00
|
|
|
void UnitLoadTorture::loadTorture(const std::string& name, const std::string& docName,
|
2019-10-21 02:04:12 -05:00
|
|
|
const size_t thread_count, const size_t max_jitter_ms)
|
|
|
|
{
|
|
|
|
// Load same document from many threads together.
|
|
|
|
std::string documentPath, documentURL;
|
2022-02-16 16:22:18 -06:00
|
|
|
helpers::getDocumentPathAndURL(docName, documentPath, documentURL, name);
|
2019-10-21 02:04:12 -05:00
|
|
|
|
2021-03-25 13:12:34 -05:00
|
|
|
TST_LOG("Starting test on " << documentURL << ' ' << documentPath);
|
|
|
|
|
2024-02-20 11:26:44 -06:00
|
|
|
std::mutex stateLock;
|
|
|
|
std::vector<int> view_ids;
|
|
|
|
|
2019-10-21 02:04:12 -05:00
|
|
|
std::atomic<int> sum_view_ids;
|
|
|
|
sum_view_ids = 0;
|
|
|
|
std::atomic<int> num_of_views(0);
|
|
|
|
std::atomic<int> num_to_load(thread_count);
|
2024-02-20 11:26:44 -06:00
|
|
|
|
2021-04-12 23:48:47 -05:00
|
|
|
std::shared_ptr<SocketPoll> poll = std::make_shared<SocketPoll>("WebSocketPoll");
|
|
|
|
poll->startThread();
|
2019-10-21 02:04:12 -05:00
|
|
|
|
|
|
|
std::vector<std::thread> threads;
|
|
|
|
for (size_t i = 0; i < thread_count; ++i)
|
|
|
|
{
|
|
|
|
threads.emplace_back([&] {
|
|
|
|
std::ostringstream oss;
|
|
|
|
oss << std::hex << std::this_thread::get_id();
|
|
|
|
const std::string id = oss.str();
|
|
|
|
|
|
|
|
TST_LOG(": #" << id << ", views: " << num_of_views << ", to load: " << num_to_load);
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Load a document and wait for the status.
|
2021-03-25 13:12:34 -05:00
|
|
|
auto wsSession = http::WebSocketSession::create(helpers::getTestServerURI());
|
|
|
|
http::Request req(documentURL);
|
|
|
|
wsSession->asyncRequest(req, poll);
|
|
|
|
|
|
|
|
wsSession->sendMessage("load url=" + documentURL);
|
2019-10-21 02:04:12 -05:00
|
|
|
|
2020-03-20 03:16:22 -05:00
|
|
|
// 20s is double of the default.
|
2021-03-25 13:12:34 -05:00
|
|
|
std::vector<char> message
|
2022-02-16 16:22:18 -06:00
|
|
|
= wsSession->waitForMessage("status:", std::chrono::seconds(20), name + id + ' ');
|
2021-11-18 06:08:14 -06:00
|
|
|
const std::string status = COOLProtocol::getFirstLine(message);
|
2021-03-25 13:12:34 -05:00
|
|
|
|
2019-10-21 02:04:12 -05:00
|
|
|
int viewid = -1;
|
2023-08-14 06:48:02 -05:00
|
|
|
LOK_ASSERT(COOLProtocol::getTokenIntegerFromMessage(status, "viewid", viewid));
|
2019-10-21 02:04:12 -05:00
|
|
|
|
2024-02-20 11:26:44 -06:00
|
|
|
LOK_ASSERT("Failed to create view in time " && viewid >= 0);
|
2019-10-21 02:04:12 -05:00
|
|
|
|
|
|
|
{
|
2024-02-20 11:26:44 -06:00
|
|
|
std::lock_guard<std::mutex> guard(stateLock);
|
|
|
|
LOK_ASSERT("Duplicate view-id generated " && std::find(view_ids.begin(), view_ids.end(), viewid) == view_ids.end());
|
|
|
|
view_ids.push_back(viewid);
|
2019-10-21 02:04:12 -05:00
|
|
|
}
|
2024-02-20 11:26:44 -06:00
|
|
|
|
|
|
|
++num_of_views;
|
|
|
|
--num_to_load;
|
|
|
|
|
|
|
|
TST_LOG(": #" << id << ", new viewId: " << viewid <<
|
|
|
|
", loaded views: " << num_of_views <<
|
|
|
|
", to load: " << num_to_load);
|
|
|
|
|
|
|
|
// Get all the views loaded - lean on test timeout to interrupt.
|
|
|
|
while (num_to_load > 0)
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
|
|
|
|
|
|
// delay randomly to close in random order:
|
|
|
|
const auto ms
|
|
|
|
= (max_jitter_ms > 0
|
|
|
|
? std::chrono::milliseconds(Util::rng::getNext() % max_jitter_ms)
|
|
|
|
: std::chrono::milliseconds(0));
|
|
|
|
std::this_thread::sleep_for(ms);
|
|
|
|
|
|
|
|
--num_of_views;
|
|
|
|
|
|
|
|
TST_LOG(": #" << id << ", view: " << num_of_views << " unloading");
|
2019-10-21 02:04:12 -05:00
|
|
|
}
|
|
|
|
catch (const std::exception& exc)
|
|
|
|
{
|
|
|
|
TST_LOG(": #" << id << ", Exception: " << exc.what());
|
|
|
|
--num_to_load;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& thread : threads)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
thread.join();
|
|
|
|
}
|
|
|
|
catch (const std::exception& exc)
|
|
|
|
{
|
|
|
|
TST_LOG(": Exception: " << exc.what());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UnitBase::TestResult UnitLoadTorture::testLoadTortureODT()
|
|
|
|
{
|
|
|
|
const int thread_count = 6;
|
|
|
|
|
2024-02-20 11:26:44 -06:00
|
|
|
loadTorture(testname, "empty.odt", thread_count);
|
2019-10-21 02:04:12 -05:00
|
|
|
|
|
|
|
return TestResult::Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnitBase::TestResult UnitLoadTorture::testLoadTortureODS()
|
|
|
|
{
|
|
|
|
const int thread_count = 6;
|
|
|
|
|
2024-02-20 11:26:44 -06:00
|
|
|
loadTorture(testname, "empty.ods", thread_count);
|
2019-10-21 02:04:12 -05:00
|
|
|
|
|
|
|
return TestResult::Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnitBase::TestResult UnitLoadTorture::testLoadTortureODP()
|
|
|
|
{
|
|
|
|
const int thread_count = 6;
|
|
|
|
|
2024-02-20 11:26:44 -06:00
|
|
|
loadTorture(testname, "empty.odp", thread_count);
|
|
|
|
|
|
|
|
return TestResult::Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnitBase::TestResult UnitLoadTorture::testLoadTortureODG()
|
|
|
|
{
|
|
|
|
const int thread_count = 6;
|
|
|
|
|
|
|
|
loadTorture(testname, "empty.odg", thread_count);
|
2019-10-21 02:04:12 -05:00
|
|
|
|
|
|
|
return TestResult::Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnitBase::TestResult UnitLoadTorture::testLoadTorture()
|
|
|
|
{
|
|
|
|
const int thread_count = 3;
|
|
|
|
const int max_jitter_ms = 75;
|
|
|
|
|
|
|
|
std::vector<std::string> docNames = { "setclientpart.ods", "hello.odt", "viewcursor.odp" };
|
|
|
|
|
|
|
|
std::vector<std::thread> threads;
|
|
|
|
threads.reserve(docNames.size());
|
|
|
|
for (const auto& docName : docNames)
|
|
|
|
{
|
|
|
|
threads.emplace_back([&] {
|
2022-02-16 16:22:18 -06:00
|
|
|
const auto name = "loadTorture_" + docName + ' ';
|
|
|
|
loadTorture(name, docName, thread_count, max_jitter_ms);
|
2019-10-21 02:04:12 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& thread : threads)
|
|
|
|
{
|
|
|
|
thread.join();
|
|
|
|
}
|
|
|
|
return TestResult::Ok;
|
|
|
|
}
|
|
|
|
|
2020-01-30 02:17:28 -06:00
|
|
|
UnitLoadTorture::UnitLoadTorture()
|
2022-02-16 16:22:18 -06:00
|
|
|
: UnitWSD("UnitLoadTorture")
|
2020-01-30 02:17:28 -06:00
|
|
|
{
|
|
|
|
// Double of the default.
|
2020-12-14 13:00:55 -06:00
|
|
|
constexpr std::chrono::minutes timeout_minutes(1);
|
|
|
|
setTimeout(timeout_minutes);
|
2020-01-30 02:17:28 -06:00
|
|
|
}
|
|
|
|
|
2020-12-24 11:15:37 -06:00
|
|
|
void UnitLoadTorture::invokeWSDTest()
|
2019-10-21 02:04:12 -05:00
|
|
|
{
|
|
|
|
UnitBase::TestResult result = testLoadTortureODT();
|
|
|
|
if (result != TestResult::Ok)
|
|
|
|
exitTest(result);
|
|
|
|
|
|
|
|
result = testLoadTortureODS();
|
|
|
|
if (result != TestResult::Ok)
|
|
|
|
exitTest(result);
|
|
|
|
|
|
|
|
result = testLoadTortureODP();
|
|
|
|
if (result != TestResult::Ok)
|
|
|
|
exitTest(result);
|
|
|
|
|
2024-02-20 11:26:44 -06:00
|
|
|
result = testLoadTortureODG();
|
|
|
|
if (result != TestResult::Ok)
|
|
|
|
exitTest(result);
|
|
|
|
|
2019-10-21 02:04:12 -05:00
|
|
|
result = testLoadTorture();
|
|
|
|
exitTest(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
UnitBase* unit_create_wsd(void) { return new UnitLoadTorture(); }
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|