2016-04-28 20:41:00 -05:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
|
|
|
* 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/.
|
|
|
|
*/
|
|
|
|
|
2020-04-18 03:39:50 -05:00
|
|
|
#pragma once
|
2017-02-07 10:16:59 -06:00
|
|
|
|
2020-12-20 17:35:31 -06:00
|
|
|
#include <test/testlog.hpp>
|
|
|
|
#include <test/lokassert.hpp>
|
2016-04-28 20:41:00 -05:00
|
|
|
|
2016-09-28 15:04:51 -05:00
|
|
|
#include <Poco/BinaryReader.h>
|
2017-05-01 23:01:28 -05:00
|
|
|
#include <Poco/Dynamic/Var.h>
|
|
|
|
#include <Poco/JSON/JSON.h>
|
|
|
|
#include <Poco/JSON/Parser.h>
|
2016-04-28 20:41:00 -05:00
|
|
|
#include <Poco/Net/HTTPClientSession.h>
|
|
|
|
#include <Poco/Net/HTTPRequest.h>
|
|
|
|
#include <Poco/Net/HTTPResponse.h>
|
|
|
|
#include <Poco/Net/HTTPSClientSession.h>
|
|
|
|
#include <Poco/Net/NetException.h>
|
2019-05-22 04:54:36 -05:00
|
|
|
#include <Poco/Net/StreamSocket.h>
|
|
|
|
#include <Poco/Net/SecureStreamSocket.h>
|
2016-04-28 20:41:00 -05:00
|
|
|
#include <Poco/Net/Socket.h>
|
|
|
|
#include <Poco/Path.h>
|
|
|
|
#include <Poco/URI.h>
|
2017-04-16 22:31:03 -05:00
|
|
|
|
2016-04-28 20:41:00 -05:00
|
|
|
#include <Common.hpp>
|
2021-04-13 00:46:02 -05:00
|
|
|
#include "Socket.hpp"
|
2016-11-12 15:38:13 -06:00
|
|
|
#include "common/FileUtil.hpp"
|
2021-11-18 06:08:14 -06:00
|
|
|
#include <tools/COOLWebSocket.hpp>
|
2021-03-27 16:41:26 -05:00
|
|
|
#include <common/ConfigUtil.hpp>
|
|
|
|
#include <common/Util.hpp>
|
2021-03-31 12:38:17 -05:00
|
|
|
#include <net/WebSocketSession.hpp>
|
2016-04-28 20:41:00 -05:00
|
|
|
|
2020-12-20 17:35:31 -06:00
|
|
|
#include <iterator>
|
|
|
|
#include <fstream>
|
2021-03-10 10:20:42 -06:00
|
|
|
#include <string>
|
2021-03-19 11:18:16 -05:00
|
|
|
#include <chrono>
|
|
|
|
#include <thread>
|
2020-12-20 17:35:31 -06:00
|
|
|
|
2016-07-31 10:17:06 -05:00
|
|
|
#ifndef TDOC
|
2016-09-15 13:02:32 -05:00
|
|
|
#error TDOC must be defined (see Makefile.am)
|
2016-07-31 10:17:06 -05:00
|
|
|
#endif
|
|
|
|
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
// Sometimes we need to retry some commands as they can (due to timing or load) soft-fail.
|
|
|
|
constexpr int COMMAND_RETRY_COUNT = 5;
|
|
|
|
|
2016-04-28 20:41:00 -05:00
|
|
|
/// Common helper testing functions.
|
2021-11-15 10:07:24 -06:00
|
|
|
/// Avoid the temptation to reuse from COOL code!
|
2016-04-28 20:41:00 -05:00
|
|
|
/// These are supposed to be testing the latter.
|
|
|
|
namespace helpers
|
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
|
2016-11-05 16:25:39 -05:00
|
|
|
inline
|
|
|
|
std::vector<char> genRandomData(const size_t size)
|
|
|
|
{
|
|
|
|
std::vector<char> v(size);
|
|
|
|
v.resize(size);
|
2018-02-07 03:17:42 -06:00
|
|
|
char* data = v.data();
|
2016-11-05 16:25:39 -05:00
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
data[i] = static_cast<char>(Util::rng::getNext());
|
|
|
|
}
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2016-11-05 16:26:39 -05:00
|
|
|
inline
|
|
|
|
std::string genRandomString(const size_t size)
|
|
|
|
{
|
|
|
|
std::string text;
|
|
|
|
text.reserve(size);
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
|
|
{
|
2021-06-22 03:02:25 -05:00
|
|
|
// Sensible characters only, avoiding 0x7f DEL
|
|
|
|
text += static_cast<char>('!' + Util::rng::getNext() % 94);
|
2016-11-05 16:26:39 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
2016-06-13 19:31:14 -05:00
|
|
|
inline
|
|
|
|
std::vector<char> readDataFromFile(const std::string& filename)
|
|
|
|
{
|
2016-07-06 22:23:43 -05:00
|
|
|
std::ifstream ifs(Poco::Path(TDOC, filename).toString(), std::ios::binary);
|
|
|
|
|
|
|
|
// Apparently std::ios::binary is not good
|
|
|
|
// enough to stop eating new-line chars!
|
|
|
|
ifs.unsetf(std::ios::skipws);
|
2016-06-13 19:31:14 -05:00
|
|
|
|
|
|
|
std::istream_iterator<char> start(ifs);
|
|
|
|
std::istream_iterator<char> end;
|
|
|
|
return std::vector<char>(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
|
|
|
std::vector<char> readDataFromFile(std::unique_ptr<std::fstream>& file)
|
|
|
|
{
|
|
|
|
file->seekg(0, std::ios_base::end);
|
|
|
|
const std::streamsize size = file->tellg();
|
|
|
|
|
|
|
|
std::vector<char> v;
|
|
|
|
v.resize(size);
|
|
|
|
|
|
|
|
file->seekg(0, std::ios_base::beg);
|
|
|
|
file->read(v.data(), size);
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
test: thread-safe common shared test data
This protects against memory corruptions,
and a cascade of issues, such as the following:
Attaching to process 56245
[New LWP 56246]
[New LWP 56252]
[New LWP 56253]
[New LWP 56254]
[New LWP 56362]
[New LWP 56364]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fda228f7d2d in __GI___pthread_timedjoin_ex (threadid=140574279595776, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89
89 pthread_join_common.c: No such file or directory.
Thread 7 (Thread 0x7fda197fa700 (LWP 56364)):
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x00007fda228f9023 in __GI___pthread_mutex_lock (mutex=0x55e9937567e0 <SigHandlerTrap>) at ../nptl/pthread_mutex_lock.c:78
#2 0x000055e9934cd4fe in __gthread_mutex_lock (__mutex=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748
#3 std::mutex::lock (this=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/c++/7/bits/std_mutex.h:103
#4 std::unique_lock<std::mutex>::lock (this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:267
#5 std::unique_lock<std::mutex>::unique_lock (__m=..., this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:197
#6 SigUtil::handleFatalSignal (signal=11) at common/SigUtil.cpp:214
#7 <signal handler called>
#8 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_capacity (this=<optimized out>, __capacity=0) at /usr/include/c++/7/bits/basic_string.h:200
#9 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (__str=..., this=<optimized out>) at /usr/include/c++/7/bits/basic_string.h:542
#10 std::_Construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (
__p=<optimized out>) at /usr/include/c++/7/bits/stl_construct.h:75
#11 std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=0x7fd9f40017b0, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:83
#12 std::uninitialized_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=<optimized out>, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:134
#13 std::__uninitialized_copy_a<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (__result=<optimized out>, __last=..., __first=...)
at /usr/include/c++/7/bits/stl_uninitialized.h:289
#14 std::__uninitialized_move_if_noexcept_a<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > (__alloc=..., __result=<optimized out>, __last=0x55e995662850,
__first=<optimized out>) at /usr/include/c++/7/bits/stl_uninitialized.h:312
#15 std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_realloc_insert<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (
this=this@entry=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>,
__position=<error: Cannot access memory at address 0x3735003238323a>, __args#0="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp") at /usr/include/c++/7/bits/vector.tcc:424
#16 0x000055e9934aa829 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (__x="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at /usr/include/c++/7/bits/stl_vector.h:948
#17 (anonymous namespace)::FileDeleter::registerForDeletion (file="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at common/FileUtil.cpp:69
#18 FileUtil::getTempFilePath (srcDir=..., srcFilename=..., dstFilenamePrefix=...) at common/FileUtil.cpp:97
#19 0x00007fda216b51c9 in helpers::getDocumentPathAndURL (docFilename="viewcursor.odp", documentPath="", documentURL="", prefix="loadTorture_viewcursor.odp_") at ./helpers.hpp:151
#20 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_viewcursor.odp ", docName="viewcursor.odp", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#21 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994dbc758) at UnitLoadTorture.cpp:186
#22 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#23 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#24 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994dbc758) at /usr/include/c++/7/thread:234
#25 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994dbc758) at /usr/include/c++/7/thread:243
#26 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994dbc750) at /usr/include/c++/7/thread:186
#27 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#28 0x00007fda228f66db in start_thread (arg=0x7fda197fa700) at pthread_create.c:463
#29 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 6 (Thread 0x7fd9fffff700 (LWP 56362)):
#0 __lll_lock_wait_private () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95
#1 0x00007fda225952db in __GI___libc_malloc (bytes=bytes@entry=3635) at malloc.c:3063
#2 0x00007fda2262f364 in __backtrace_symbols (array=array@entry=0x7fd9ffffc540, size=size@entry=26) at backtracesyms.c:69
#3 0x000055e9934cc439 in SigUtil::dumpBacktrace () at common/SigUtil.cpp:253
#4 0x000055e9934cd5ae in SigUtil::handleFatalSignal (signal=6) at common/SigUtil.cpp:236
#5 <signal handler called>
#6 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#7 0x00007fda2253e801 in __GI_abort () at abort.c:79
#8 0x00007fda22587897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fda226b4b9a "%s
") at ../sysdeps/posix/libc_fatal.c:181
#9 0x00007fda2258e90a in malloc_printerr (str=str@entry=0x7fda226b2e0e "malloc(): memory corruption") at malloc.c:5350
#10 0x00007fda22592994 in _int_malloc (av=av@entry=0x7fda00000020, bytes=bytes@entry=32) at malloc.c:3738
#11 0x00007fda225952ed in __GI___libc_malloc (bytes=32) at malloc.c:3065
#12 0x00007fda22db9258 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#13 0x00007fda244adaae in __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate (this=0x7fd9ffffe740, __n=1)
at /usr/include/c++/5/ext/new_allocator.h:104
#14 0x00007fda244ad300 in __gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::allocate (__a=..., __n=1)
at /usr/include/c++/5/ext/alloc_traits.h:182
#15 0x00007fda244ac858 in std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_allocate (this=0x7fd9ffffe740, __n=1) at /usr/include/c++/5/bits/stl_vector.h:170
#16 0x00007fda244ab7c7 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_insert_aux (this=0x7fd9ffffe740, __position=non-dereferenceable iterator for std::vector, __x="home") at /usr/include/c++/5/bits/vector.tcc:353
#17 0x00007fda244aada2 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (this=0x7fd9ffffe740, __x="home") at /usr/include/c++/5/bits/stl_vector.h:925
#18 0x00007fda2350ddcb in Poco::Path::pushDirectory (this=0x7fd9ffffe6c0, dir="home") at src/Path.cpp:471
#19 0x00007fda2350ea27 in Poco::Path::parseUnix (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:671
#20 0x00007fda2350cd6b in Poco::Path::assign (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:182
#21 0x00007fda2350c1be in Poco::Path::Path (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:54
#22 0x00007fda2350d33a in Poco::Path::makeAbsolute (this=0x7fd9ffffe8f0) at src/Path.cpp:318
#23 0x00007fda216b52ca in helpers::getDocumentPathAndURL (docFilename="setclientpart.ods", documentPath="/tmp/loadTorture_setclientpart.ods_ae70d2e_setclientpart.ods", documentURL="",
prefix="loadTorture_setclientpart.ods_") at ./helpers.hpp:153
#24 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_setclientpart.ods ", docName="setclientpart.ods", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#25 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994cffe18) at UnitLoadTorture.cpp:186
#26 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#27 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#28 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994cffe18) at /usr/include/c++/7/thread:234
#29 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994cffe18) at /usr/include/c++/7/thread:243
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994cffe10) at /usr/include/c++/7/thread:186
#31 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#32 0x00007fda228f66db in start_thread (arg=0x7fd9fffff700) at pthread_create.c:463
#33 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Change-Id: Ib60954e49e692082e686cb3fdc5fc9d5cfbc83c9
Reviewed-on: https://gerrit.libreoffice.org/83047
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
2019-11-17 19:32:54 -06:00
|
|
|
inline void getDocumentPathAndURL(const std::string& docFilename, std::string& documentPath,
|
|
|
|
std::string& documentURL, std::string prefix)
|
2016-04-28 20:41:00 -05:00
|
|
|
{
|
test: thread-safe common shared test data
This protects against memory corruptions,
and a cascade of issues, such as the following:
Attaching to process 56245
[New LWP 56246]
[New LWP 56252]
[New LWP 56253]
[New LWP 56254]
[New LWP 56362]
[New LWP 56364]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fda228f7d2d in __GI___pthread_timedjoin_ex (threadid=140574279595776, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89
89 pthread_join_common.c: No such file or directory.
Thread 7 (Thread 0x7fda197fa700 (LWP 56364)):
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x00007fda228f9023 in __GI___pthread_mutex_lock (mutex=0x55e9937567e0 <SigHandlerTrap>) at ../nptl/pthread_mutex_lock.c:78
#2 0x000055e9934cd4fe in __gthread_mutex_lock (__mutex=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748
#3 std::mutex::lock (this=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/c++/7/bits/std_mutex.h:103
#4 std::unique_lock<std::mutex>::lock (this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:267
#5 std::unique_lock<std::mutex>::unique_lock (__m=..., this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:197
#6 SigUtil::handleFatalSignal (signal=11) at common/SigUtil.cpp:214
#7 <signal handler called>
#8 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_capacity (this=<optimized out>, __capacity=0) at /usr/include/c++/7/bits/basic_string.h:200
#9 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (__str=..., this=<optimized out>) at /usr/include/c++/7/bits/basic_string.h:542
#10 std::_Construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (
__p=<optimized out>) at /usr/include/c++/7/bits/stl_construct.h:75
#11 std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=0x7fd9f40017b0, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:83
#12 std::uninitialized_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=<optimized out>, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:134
#13 std::__uninitialized_copy_a<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (__result=<optimized out>, __last=..., __first=...)
at /usr/include/c++/7/bits/stl_uninitialized.h:289
#14 std::__uninitialized_move_if_noexcept_a<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > (__alloc=..., __result=<optimized out>, __last=0x55e995662850,
__first=<optimized out>) at /usr/include/c++/7/bits/stl_uninitialized.h:312
#15 std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_realloc_insert<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (
this=this@entry=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>,
__position=<error: Cannot access memory at address 0x3735003238323a>, __args#0="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp") at /usr/include/c++/7/bits/vector.tcc:424
#16 0x000055e9934aa829 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (__x="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at /usr/include/c++/7/bits/stl_vector.h:948
#17 (anonymous namespace)::FileDeleter::registerForDeletion (file="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at common/FileUtil.cpp:69
#18 FileUtil::getTempFilePath (srcDir=..., srcFilename=..., dstFilenamePrefix=...) at common/FileUtil.cpp:97
#19 0x00007fda216b51c9 in helpers::getDocumentPathAndURL (docFilename="viewcursor.odp", documentPath="", documentURL="", prefix="loadTorture_viewcursor.odp_") at ./helpers.hpp:151
#20 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_viewcursor.odp ", docName="viewcursor.odp", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#21 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994dbc758) at UnitLoadTorture.cpp:186
#22 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#23 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#24 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994dbc758) at /usr/include/c++/7/thread:234
#25 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994dbc758) at /usr/include/c++/7/thread:243
#26 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994dbc750) at /usr/include/c++/7/thread:186
#27 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#28 0x00007fda228f66db in start_thread (arg=0x7fda197fa700) at pthread_create.c:463
#29 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 6 (Thread 0x7fd9fffff700 (LWP 56362)):
#0 __lll_lock_wait_private () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95
#1 0x00007fda225952db in __GI___libc_malloc (bytes=bytes@entry=3635) at malloc.c:3063
#2 0x00007fda2262f364 in __backtrace_symbols (array=array@entry=0x7fd9ffffc540, size=size@entry=26) at backtracesyms.c:69
#3 0x000055e9934cc439 in SigUtil::dumpBacktrace () at common/SigUtil.cpp:253
#4 0x000055e9934cd5ae in SigUtil::handleFatalSignal (signal=6) at common/SigUtil.cpp:236
#5 <signal handler called>
#6 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#7 0x00007fda2253e801 in __GI_abort () at abort.c:79
#8 0x00007fda22587897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fda226b4b9a "%s
") at ../sysdeps/posix/libc_fatal.c:181
#9 0x00007fda2258e90a in malloc_printerr (str=str@entry=0x7fda226b2e0e "malloc(): memory corruption") at malloc.c:5350
#10 0x00007fda22592994 in _int_malloc (av=av@entry=0x7fda00000020, bytes=bytes@entry=32) at malloc.c:3738
#11 0x00007fda225952ed in __GI___libc_malloc (bytes=32) at malloc.c:3065
#12 0x00007fda22db9258 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#13 0x00007fda244adaae in __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate (this=0x7fd9ffffe740, __n=1)
at /usr/include/c++/5/ext/new_allocator.h:104
#14 0x00007fda244ad300 in __gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::allocate (__a=..., __n=1)
at /usr/include/c++/5/ext/alloc_traits.h:182
#15 0x00007fda244ac858 in std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_allocate (this=0x7fd9ffffe740, __n=1) at /usr/include/c++/5/bits/stl_vector.h:170
#16 0x00007fda244ab7c7 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_insert_aux (this=0x7fd9ffffe740, __position=non-dereferenceable iterator for std::vector, __x="home") at /usr/include/c++/5/bits/vector.tcc:353
#17 0x00007fda244aada2 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (this=0x7fd9ffffe740, __x="home") at /usr/include/c++/5/bits/stl_vector.h:925
#18 0x00007fda2350ddcb in Poco::Path::pushDirectory (this=0x7fd9ffffe6c0, dir="home") at src/Path.cpp:471
#19 0x00007fda2350ea27 in Poco::Path::parseUnix (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:671
#20 0x00007fda2350cd6b in Poco::Path::assign (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:182
#21 0x00007fda2350c1be in Poco::Path::Path (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:54
#22 0x00007fda2350d33a in Poco::Path::makeAbsolute (this=0x7fd9ffffe8f0) at src/Path.cpp:318
#23 0x00007fda216b52ca in helpers::getDocumentPathAndURL (docFilename="setclientpart.ods", documentPath="/tmp/loadTorture_setclientpart.ods_ae70d2e_setclientpart.ods", documentURL="",
prefix="loadTorture_setclientpart.ods_") at ./helpers.hpp:153
#24 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_setclientpart.ods ", docName="setclientpart.ods", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#25 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994cffe18) at UnitLoadTorture.cpp:186
#26 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#27 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#28 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994cffe18) at /usr/include/c++/7/thread:234
#29 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994cffe18) at /usr/include/c++/7/thread:243
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994cffe10) at /usr/include/c++/7/thread:186
#31 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#32 0x00007fda228f66db in start_thread (arg=0x7fd9fffff700) at pthread_create.c:463
#33 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Change-Id: Ib60954e49e692082e686cb3fdc5fc9d5cfbc83c9
Reviewed-on: https://gerrit.libreoffice.org/83047
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
2019-11-17 19:32:54 -06:00
|
|
|
const std::string testname = prefix;
|
|
|
|
|
|
|
|
static std::mutex lock;
|
|
|
|
std::unique_lock<std::mutex> guard(lock);
|
|
|
|
|
2017-01-05 21:46:00 -06:00
|
|
|
std::replace(prefix.begin(), prefix.end(), ' ', '_');
|
2020-11-22 08:46:22 -06:00
|
|
|
documentPath = FileUtil::getTempFileCopyPath(TDOC, docFilename, prefix);
|
2016-09-29 12:20:52 -05:00
|
|
|
std::string encodedUri;
|
test: thread-safe common shared test data
This protects against memory corruptions,
and a cascade of issues, such as the following:
Attaching to process 56245
[New LWP 56246]
[New LWP 56252]
[New LWP 56253]
[New LWP 56254]
[New LWP 56362]
[New LWP 56364]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fda228f7d2d in __GI___pthread_timedjoin_ex (threadid=140574279595776, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89
89 pthread_join_common.c: No such file or directory.
Thread 7 (Thread 0x7fda197fa700 (LWP 56364)):
#0 __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1 0x00007fda228f9023 in __GI___pthread_mutex_lock (mutex=0x55e9937567e0 <SigHandlerTrap>) at ../nptl/pthread_mutex_lock.c:78
#2 0x000055e9934cd4fe in __gthread_mutex_lock (__mutex=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748
#3 std::mutex::lock (this=0x55e9937567e0 <SigHandlerTrap>) at /usr/include/c++/7/bits/std_mutex.h:103
#4 std::unique_lock<std::mutex>::lock (this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:267
#5 std::unique_lock<std::mutex>::unique_lock (__m=..., this=<synthetic pointer>) at /usr/include/c++/7/bits/std_mutex.h:197
#6 SigUtil::handleFatalSignal (signal=11) at common/SigUtil.cpp:214
#7 <signal handler called>
#8 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_capacity (this=<optimized out>, __capacity=0) at /usr/include/c++/7/bits/basic_string.h:200
#9 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (__str=..., this=<optimized out>) at /usr/include/c++/7/bits/basic_string.h:542
#10 std::_Construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (
__p=<optimized out>) at /usr/include/c++/7/bits/stl_construct.h:75
#11 std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=0x7fd9f40017b0, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:83
#12 std::uninitialized_copy<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*> (__result=<optimized out>, __last=..., __first=...) at /usr/include/c++/7/bits/stl_uninitialized.h:134
#13 std::__uninitialized_copy_a<std::move_iterator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (__result=<optimized out>, __last=..., __first=...)
at /usr/include/c++/7/bits/stl_uninitialized.h:289
#14 std::__uninitialized_move_if_noexcept_a<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > (__alloc=..., __result=<optimized out>, __last=0x55e995662850,
__first=<optimized out>) at /usr/include/c++/7/bits/stl_uninitialized.h:312
#15 std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_realloc_insert<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&> (
this=this@entry=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>,
__position=<error: Cannot access memory at address 0x3735003238323a>, __args#0="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp") at /usr/include/c++/7/bits/vector.tcc:424
#16 0x000055e9934aa829 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (__x="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at /usr/include/c++/7/bits/stl_vector.h:948
#17 (anonymous namespace)::FileDeleter::registerForDeletion (file="/tmp/loadTorture_viewcursor.odp_725a6013_viewcursor.odp",
this=0x55e9937566f0 <FileUtil::getTempFilePath(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::fileDeleter>) at common/FileUtil.cpp:69
#18 FileUtil::getTempFilePath (srcDir=..., srcFilename=..., dstFilenamePrefix=...) at common/FileUtil.cpp:97
#19 0x00007fda216b51c9 in helpers::getDocumentPathAndURL (docFilename="viewcursor.odp", documentPath="", documentURL="", prefix="loadTorture_viewcursor.odp_") at ./helpers.hpp:151
#20 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_viewcursor.odp ", docName="viewcursor.odp", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#21 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994dbc758) at UnitLoadTorture.cpp:186
#22 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#23 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#24 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994dbc758) at /usr/include/c++/7/thread:234
#25 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994dbc758) at /usr/include/c++/7/thread:243
#26 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994dbc750) at /usr/include/c++/7/thread:186
#27 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#28 0x00007fda228f66db in start_thread (arg=0x7fda197fa700) at pthread_create.c:463
#29 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Thread 6 (Thread 0x7fd9fffff700 (LWP 56362)):
#0 __lll_lock_wait_private () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:95
#1 0x00007fda225952db in __GI___libc_malloc (bytes=bytes@entry=3635) at malloc.c:3063
#2 0x00007fda2262f364 in __backtrace_symbols (array=array@entry=0x7fd9ffffc540, size=size@entry=26) at backtracesyms.c:69
#3 0x000055e9934cc439 in SigUtil::dumpBacktrace () at common/SigUtil.cpp:253
#4 0x000055e9934cd5ae in SigUtil::handleFatalSignal (signal=6) at common/SigUtil.cpp:236
#5 <signal handler called>
#6 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#7 0x00007fda2253e801 in __GI_abort () at abort.c:79
#8 0x00007fda22587897 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fda226b4b9a "%s
") at ../sysdeps/posix/libc_fatal.c:181
#9 0x00007fda2258e90a in malloc_printerr (str=str@entry=0x7fda226b2e0e "malloc(): memory corruption") at malloc.c:5350
#10 0x00007fda22592994 in _int_malloc (av=av@entry=0x7fda00000020, bytes=bytes@entry=32) at malloc.c:3738
#11 0x00007fda225952ed in __GI___libc_malloc (bytes=32) at malloc.c:3065
#12 0x00007fda22db9258 in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#13 0x00007fda244adaae in __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate (this=0x7fd9ffffe740, __n=1)
at /usr/include/c++/5/ext/new_allocator.h:104
#14 0x00007fda244ad300 in __gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::allocate (__a=..., __n=1)
at /usr/include/c++/5/ext/alloc_traits.h:182
#15 0x00007fda244ac858 in std::_Vector_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_allocate (this=0x7fd9ffffe740, __n=1) at /usr/include/c++/5/bits/stl_vector.h:170
#16 0x00007fda244ab7c7 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::_M_insert_aux (this=0x7fd9ffffe740, __position=non-dereferenceable iterator for std::vector, __x="home") at /usr/include/c++/5/bits/vector.tcc:353
#17 0x00007fda244aada2 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back (this=0x7fd9ffffe740, __x="home") at /usr/include/c++/5/bits/stl_vector.h:925
#18 0x00007fda2350ddcb in Poco::Path::pushDirectory (this=0x7fd9ffffe6c0, dir="home") at src/Path.cpp:471
#19 0x00007fda2350ea27 in Poco::Path::parseUnix (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:671
#20 0x00007fda2350cd6b in Poco::Path::assign (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:182
#21 0x00007fda2350c1be in Poco::Path::Path (this=0x7fd9ffffe6c0, path="/home/ash/prj/lo/online/test/") at src/Path.cpp:54
#22 0x00007fda2350d33a in Poco::Path::makeAbsolute (this=0x7fd9ffffe8f0) at src/Path.cpp:318
#23 0x00007fda216b52ca in helpers::getDocumentPathAndURL (docFilename="setclientpart.ods", documentPath="/tmp/loadTorture_setclientpart.ods_ae70d2e_setclientpart.ods", documentURL="",
prefix="loadTorture_setclientpart.ods_") at ./helpers.hpp:153
#24 0x00007fda216ad007 in UnitLoadTorture::loadTorture (this=<optimized out>, testname="loadTorture_setclientpart.ods ", docName="setclientpart.ods", thread_count=thread_count@entry=3,
max_jitter_ms=<optimized out>, max_jitter_ms@entry=75) at UnitLoadTorture.cpp:41
#25 0x00007fda216ad7dd in UnitLoadTorture::<lambda()>::operator() (__closure=0x55e994cffe18) at UnitLoadTorture.cpp:186
#26 std::__invoke_impl<void, UnitLoadTorture::testLoadTorture()::<lambda()> > (__f=...) at /usr/include/c++/7/bits/invoke.h:60
#27 std::__invoke<UnitLoadTorture::testLoadTorture()::<lambda()> > (__fn=...) at /usr/include/c++/7/bits/invoke.h:95
#28 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::_M_invoke<0> (this=0x55e994cffe18) at /usr/include/c++/7/thread:234
#29 std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > >::operator() (this=0x55e994cffe18) at /usr/include/c++/7/thread:243
#30 std::thread::_State_impl<std::thread::_Invoker<std::tuple<UnitLoadTorture::testLoadTorture()::<lambda()> > > >::_M_run(void) (this=0x55e994cffe10) at /usr/include/c++/7/thread:186
#31 0x00007fda22de366f in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#32 0x00007fda228f66db in start_thread (arg=0x7fd9fffff700) at pthread_create.c:463
#33 0x00007fda2261f88f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
Change-Id: Ib60954e49e692082e686cb3fdc5fc9d5cfbc83c9
Reviewed-on: https://gerrit.libreoffice.org/83047
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
2019-11-17 19:32:54 -06:00
|
|
|
Poco::URI::encode("file://" + Poco::Path(documentPath).makeAbsolute().toString(), ":/?",
|
|
|
|
encodedUri);
|
2021-11-15 09:41:58 -06:00
|
|
|
documentURL = "cool/" + encodedUri + "/ws";
|
2018-01-22 08:11:43 -06:00
|
|
|
TST_LOG("Test file: " << documentPath);
|
2016-04-28 20:41:00 -05:00
|
|
|
}
|
|
|
|
|
2016-04-28 21:44:40 -05:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
void sendTextFrame(COOLWebSocket& socket, const std::string& string, const std::string& testname)
|
2016-04-28 20:41:00 -05:00
|
|
|
{
|
2017-02-08 04:46:11 -06:00
|
|
|
#ifndef FUZZER
|
2021-11-18 06:08:14 -06:00
|
|
|
TST_LOG("Sending " << string.size() << " bytes: " << COOLProtocol::getAbbreviatedMessage(string));
|
2017-02-08 04:46:11 -06:00
|
|
|
#else
|
2018-01-22 08:11:43 -06:00
|
|
|
(void) testname;
|
2017-02-08 04:46:11 -06:00
|
|
|
#endif
|
2016-04-28 20:41:00 -05:00
|
|
|
socket.sendFrame(string.data(), string.size());
|
|
|
|
}
|
|
|
|
|
2016-05-08 23:39:01 -05:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
void sendTextFrame(const std::shared_ptr<COOLWebSocket>& socket, const std::string& string, const std::string& name = "")
|
2016-05-08 23:39:01 -05:00
|
|
|
{
|
2016-05-13 07:46:39 -05:00
|
|
|
sendTextFrame(*socket, string, name);
|
2016-05-08 23:39:01 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 12:38:17 -05:00
|
|
|
inline void sendTextFrame(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& string, const std::string& testname = std::string())
|
|
|
|
{
|
|
|
|
#ifndef FUZZER
|
|
|
|
TST_LOG("Sending " << string.size()
|
2021-11-18 06:08:14 -06:00
|
|
|
<< " bytes: " << COOLProtocol::getAbbreviatedMessage(string));
|
2021-03-31 12:38:17 -05:00
|
|
|
#else
|
|
|
|
(void)testname;
|
|
|
|
#endif
|
|
|
|
ws->sendMessage(string);
|
|
|
|
}
|
|
|
|
|
2021-03-10 09:44:43 -06:00
|
|
|
inline std::unique_ptr<Poco::Net::HTTPClientSession> createSession(const Poco::URI& uri)
|
2016-05-02 05:26:48 -05:00
|
|
|
{
|
|
|
|
#if ENABLE_SSL
|
2020-05-06 16:12:17 -05:00
|
|
|
if (uri.getScheme() == "https" || uri.getScheme() == "wss")
|
2021-03-10 09:44:43 -06:00
|
|
|
return Util::make_unique<Poco::Net::HTTPSClientSession>(uri.getHost(), uri.getPort());
|
2016-05-02 05:26:48 -05:00
|
|
|
#endif
|
2021-03-10 09:44:43 -06:00
|
|
|
|
|
|
|
return Util::make_unique<Poco::Net::HTTPClientSession>(uri.getHost(), uri.getPort());
|
2016-05-02 05:26:48 -05:00
|
|
|
}
|
2016-04-28 20:41:00 -05:00
|
|
|
|
2021-03-10 10:20:42 -06:00
|
|
|
/// Uses Poco to make an HTTP GET from the given URI.
|
|
|
|
inline std::pair<std::shared_ptr<Poco::Net::HTTPResponse>, std::string>
|
|
|
|
pocoGet(const Poco::URI& uri)
|
|
|
|
{
|
2021-03-19 11:18:16 -05:00
|
|
|
LOG_INF("pocoGet: " << uri.toString());
|
|
|
|
std::unique_ptr<Poco::Net::HTTPClientSession> session(helpers::createSession(uri));
|
|
|
|
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, uri.getPathAndQuery(),
|
|
|
|
Poco::Net::HTTPMessage::HTTP_1_1);
|
|
|
|
session->sendRequest(request);
|
|
|
|
auto response = std::make_shared<Poco::Net::HTTPResponse>();
|
|
|
|
std::istream& rs = session->receiveResponse(*response);
|
|
|
|
|
|
|
|
LOG_DBG("pocoGet response for [" << uri.toString() << "]: " << response->getStatus() << ' '
|
|
|
|
<< response->getReason()
|
|
|
|
<< ", hasContentLength: " << response->hasContentLength()
|
|
|
|
<< ", ContentLength: " << response->getContentLength64());
|
|
|
|
|
|
|
|
for (const auto& pair : *response)
|
2021-03-10 10:20:42 -06:00
|
|
|
{
|
2021-03-19 11:18:16 -05:00
|
|
|
LOG_TRC(pair.first << '=' << pair.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string responseString;
|
2021-09-10 08:04:56 -05:00
|
|
|
try
|
2021-03-19 11:18:16 -05:00
|
|
|
{
|
|
|
|
std::ostringstream outputStringStream;
|
|
|
|
Poco::StreamCopier::copyStream(rs, outputStringStream);
|
|
|
|
responseString = outputStringStream.str();
|
|
|
|
LOG_DBG("pocoGet [" << uri.toString() << "]: " << responseString);
|
|
|
|
}
|
2021-09-10 08:04:56 -05:00
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
|
|
|
LOG_ERR("Exception while reading Poco stream: " << ex.what());
|
|
|
|
}
|
2021-03-19 11:18:16 -05:00
|
|
|
|
|
|
|
return std::make_pair(response, responseString);
|
|
|
|
}
|
2021-03-10 10:20:42 -06:00
|
|
|
|
2021-03-19 11:18:16 -05:00
|
|
|
/// Uses Poco to make an HTTP GET from the given URI.
|
|
|
|
/// And optionally retries up to @retry times with
|
|
|
|
/// @delayMs between attempts.
|
|
|
|
inline std::pair<std::shared_ptr<Poco::Net::HTTPResponse>, std::string>
|
|
|
|
pocoGetRetry(const Poco::URI& uri, int retry = 3,
|
|
|
|
std::chrono::milliseconds delayMs = std::chrono::seconds(1))
|
|
|
|
{
|
|
|
|
for (int attempt = 1; attempt <= retry; ++attempt)
|
|
|
|
{
|
|
|
|
try
|
2021-03-10 10:20:42 -06:00
|
|
|
{
|
2021-03-19 11:18:16 -05:00
|
|
|
LOG_INF("pocoGet #" << attempt << ": " << uri.toString());
|
|
|
|
return pocoGet(uri);
|
2021-03-10 10:20:42 -06:00
|
|
|
}
|
2021-03-19 11:18:16 -05:00
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
|
|
|
LOG_ERR("pocoGet #" << attempt << " failed for [" << uri.toString()
|
|
|
|
<< "]: " << ex.what());
|
|
|
|
if (attempt == retry)
|
|
|
|
throw;
|
2021-03-10 10:20:42 -06:00
|
|
|
|
2021-03-19 11:18:16 -05:00
|
|
|
std::this_thread::sleep_for(delayMs);
|
|
|
|
}
|
2021-03-10 10:20:42 -06:00
|
|
|
}
|
2021-04-07 02:48:12 -05:00
|
|
|
|
|
|
|
auto response = std::make_shared<Poco::Net::HTTPResponse>();
|
|
|
|
std::string responseString;
|
|
|
|
return std::make_pair(response, responseString);
|
2021-03-10 10:20:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Uses Poco to make an HTTP GET from the given URI components.
|
|
|
|
inline std::pair<std::shared_ptr<Poco::Net::HTTPResponse>, std::string>
|
|
|
|
pocoGet(bool secure, const std::string& host, const int port, const std::string& url)
|
|
|
|
{
|
|
|
|
const char* scheme = (secure ? "https://" : "http://");
|
|
|
|
Poco::URI uri(scheme + host + ':' + std::to_string(port) + url);
|
|
|
|
return pocoGet(uri);
|
|
|
|
}
|
|
|
|
|
2019-05-22 04:54:36 -05:00
|
|
|
inline std::shared_ptr<Poco::Net::StreamSocket> createRawSocket()
|
|
|
|
{
|
|
|
|
return
|
|
|
|
#if ENABLE_SSL
|
|
|
|
std::make_shared<Poco::Net::SecureStreamSocket>
|
|
|
|
#else
|
|
|
|
std::make_shared<Poco::Net::StreamSocket>
|
|
|
|
#endif
|
2020-01-21 03:00:52 -06:00
|
|
|
(Poco::Net::SocketAddress("127.0.0.1", ClientPortNumber));
|
2019-05-22 04:54:36 -05:00
|
|
|
}
|
2016-05-03 02:40:25 -05:00
|
|
|
|
2020-07-02 11:54:56 -05:00
|
|
|
// Sets read / write timeout for the given file descriptor.
|
|
|
|
inline void setSocketTimeOut(int socketFD, int timeMS)
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
tv.tv_sec = (float)timeMS / (float)1000;
|
|
|
|
tv.tv_usec = timeMS;
|
|
|
|
setsockopt(socketFD, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sets socket's blocking mode. true for blocking, false for non blocking.
|
|
|
|
inline void setSocketBlockingMode(int socketFD, bool blocking)
|
|
|
|
{
|
|
|
|
ioctl(socketFD, FIONBIO, blocking == true ? 0: 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates a socket and connects it to a local server. Returns the file descriptor.
|
|
|
|
inline int connectToLocalServer(int portNumber, int socketTimeOutMS, bool blocking)
|
|
|
|
{
|
|
|
|
int socketFD = 0;
|
|
|
|
struct sockaddr_in serv_addr;
|
|
|
|
|
|
|
|
if ((socketFD = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
|
|
|
{
|
|
|
|
LOG_ERR("helpers::connectToLocalServer: Server client could not be created.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
serv_addr.sin_family = AF_INET;
|
|
|
|
serv_addr.sin_port = htons(portNumber);
|
|
|
|
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0)
|
|
|
|
{
|
|
|
|
LOG_ERR("helpers::connectToLocalServer: Invalid address.");
|
|
|
|
close(socketFD);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (connect(socketFD, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
|
|
|
|
{
|
|
|
|
LOG_ERR("helpers::connectToLocalServer: Connection failed.");
|
|
|
|
close(socketFD);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setSocketTimeOut(socketFD, socketTimeOutMS);
|
|
|
|
setSocketBlockingMode(socketFD, blocking);
|
|
|
|
return socketFD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-12 20:52:03 -05:00
|
|
|
/// Returns true iff built with SSL and it is successfully initialized.
|
|
|
|
inline bool haveSsl()
|
|
|
|
{
|
|
|
|
#if ENABLE_SSL
|
2021-06-23 20:30:28 -05:00
|
|
|
return ssl::Manager::isClientContextInitialized();
|
2021-04-12 20:52:03 -05:00
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return a fully-qualified URI, with schema, to the test loopback server.
|
|
|
|
inline std::string const& getTestServerURI()
|
2019-05-22 04:54:36 -05:00
|
|
|
{
|
2016-05-03 02:40:25 -05:00
|
|
|
static std::string serverURI(
|
2021-04-12 20:52:03 -05:00
|
|
|
(haveSsl() && config::isSslEnabled() ? "https://127.0.0.1:" : "http://127.0.0.1:")
|
2021-03-27 16:41:26 -05:00
|
|
|
+ std::to_string(ClientPortNumber));
|
2016-05-03 02:40:25 -05:00
|
|
|
|
|
|
|
return serverURI;
|
|
|
|
}
|
|
|
|
|
2016-09-28 15:04:51 -05:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
int getErrorCode(COOLWebSocket& ws, std::string& message, const std::string& testname)
|
2016-09-28 15:04:51 -05:00
|
|
|
{
|
|
|
|
int flags = 0;
|
|
|
|
int bytes = 0;
|
|
|
|
Poco::UInt16 statusCode = -1;
|
|
|
|
Poco::Buffer<char> buffer(READ_BUFFER_SIZE);
|
|
|
|
|
|
|
|
message.clear();
|
2017-01-15 11:15:11 -06:00
|
|
|
ws.setReceiveTimeout(Poco::Timespan(5000000));
|
2016-09-28 15:04:51 -05:00
|
|
|
do
|
|
|
|
{
|
2020-12-24 20:08:59 -06:00
|
|
|
// Read next WS frame and log it.
|
2021-03-08 20:59:33 -06:00
|
|
|
bytes = ws.receiveFrame(buffer.begin(), READ_BUFFER_SIZE, flags, testname);
|
2020-12-24 20:08:59 -06:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
2016-09-28 15:04:51 -05:00
|
|
|
}
|
2017-02-28 21:31:36 -06:00
|
|
|
while (bytes > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE);
|
2016-09-28 15:04:51 -05:00
|
|
|
|
|
|
|
if (bytes > 0)
|
|
|
|
{
|
2021-11-18 06:08:14 -06:00
|
|
|
TST_LOG("Got Close Frame: " << COOLWebSocket::getAbbreviatedFrameDump(buffer.begin(), bytes,
|
2020-12-24 20:08:59 -06:00
|
|
|
flags));
|
2016-09-28 15:04:51 -05:00
|
|
|
Poco::MemoryBinaryReader reader(buffer, Poco::BinaryReader::NETWORK_BYTE_ORDER);
|
|
|
|
reader >> statusCode;
|
2021-01-04 07:47:32 -06:00
|
|
|
if (static_cast<unsigned>(bytes) > sizeof(statusCode))
|
2020-12-24 20:08:59 -06:00
|
|
|
{
|
|
|
|
// An optional message after the status code.
|
2021-01-04 07:47:32 -06:00
|
|
|
message.append(buffer.begin() + sizeof(statusCode), bytes - sizeof(statusCode));
|
2020-12-24 20:08:59 -06:00
|
|
|
}
|
2016-09-28 15:04:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return statusCode;
|
|
|
|
}
|
|
|
|
|
2017-01-03 16:02:53 -06:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
int getErrorCode(const std::shared_ptr<COOLWebSocket>& ws, std::string& message, const std::string& testname)
|
2017-01-03 16:02:53 -06:00
|
|
|
{
|
2017-01-15 11:15:11 -06:00
|
|
|
return getErrorCode(*ws, message, testname);
|
2017-01-03 16:02:53 -06:00
|
|
|
}
|
|
|
|
|
2021-03-31 16:45:02 -05:00
|
|
|
inline std::vector<char>
|
2021-11-18 06:08:14 -06:00
|
|
|
getResponseMessage(COOLWebSocket& ws, const std::string& prefix, const std::string& testname,
|
2021-03-31 16:45:02 -05:00
|
|
|
const std::chrono::milliseconds timeoutMs = std::chrono::seconds(10))
|
2016-05-08 23:39:01 -05:00
|
|
|
{
|
2016-05-03 22:35:34 -05:00
|
|
|
try
|
|
|
|
{
|
2016-05-10 20:38:03 -05:00
|
|
|
int flags = 0;
|
2016-05-03 22:35:34 -05:00
|
|
|
std::vector<char> response;
|
|
|
|
|
2021-03-31 16:45:02 -05:00
|
|
|
auto endTime = std::chrono::steady_clock::now() + timeoutMs;
|
2020-01-20 09:16:36 -06:00
|
|
|
|
2016-05-03 22:35:34 -05:00
|
|
|
ws.setReceiveTimeout(0);
|
|
|
|
do
|
|
|
|
{
|
2020-01-20 09:16:36 -06:00
|
|
|
auto now = std::chrono::steady_clock::now();
|
|
|
|
if (now > endTime) // timedout
|
|
|
|
{
|
2021-04-14 16:42:04 -05:00
|
|
|
TST_LOG("Timeout waiting for [" << prefix << "] after " << timeoutMs);
|
2020-01-20 09:16:36 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
long waitTimeUs = std::chrono::duration_cast<std::chrono::microseconds>(endTime - now).count();
|
|
|
|
if (ws.poll(Poco::Timespan(waitTimeUs), Poco::Net::Socket::SELECT_READ))
|
2016-05-03 22:35:34 -05:00
|
|
|
{
|
2017-04-02 23:45:40 -05:00
|
|
|
response.resize(READ_BUFFER_SIZE * 8);
|
2021-03-08 20:59:33 -06:00
|
|
|
const int bytes = ws.receiveFrame(response.data(), response.size(), flags, testname);
|
2016-11-26 21:28:48 -06:00
|
|
|
response.resize(std::max(bytes, 0));
|
2021-11-18 06:08:14 -06:00
|
|
|
const auto message = COOLProtocol::getFirstLine(response);
|
2016-05-03 22:35:34 -05:00
|
|
|
if (bytes > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE)
|
|
|
|
{
|
2021-11-18 06:08:14 -06:00
|
|
|
if (COOLProtocol::matchPrefix(prefix, message))
|
2016-05-03 22:35:34 -05:00
|
|
|
{
|
2020-05-24 08:10:18 -05:00
|
|
|
TST_LOG('[' << prefix << "] Matched " <<
|
2021-11-18 06:08:14 -06:00
|
|
|
COOLWebSocket::getAbbreviatedFrameDump(response.data(), bytes, flags));
|
2016-05-03 22:35:34 -05:00
|
|
|
return response;
|
|
|
|
}
|
2016-11-25 03:48:59 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
response.resize(0);
|
2016-05-03 22:35:34 -05:00
|
|
|
}
|
|
|
|
|
2016-05-12 09:54:21 -05:00
|
|
|
if (bytes <= 0)
|
|
|
|
{
|
2020-02-17 02:08:34 -06:00
|
|
|
// Try again, timeout will be handled above.
|
|
|
|
continue;
|
2016-05-12 09:54:21 -05:00
|
|
|
}
|
2016-09-11 13:29:09 -05:00
|
|
|
|
2016-09-19 05:53:14 -05:00
|
|
|
if ((flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE)
|
2016-09-20 19:41:30 -05:00
|
|
|
{
|
2016-10-21 21:02:15 -05:00
|
|
|
// Don't ignore errors.
|
2021-11-18 06:08:14 -06:00
|
|
|
if (COOLProtocol::matchPrefix("error:", message))
|
2016-10-21 21:02:15 -05:00
|
|
|
{
|
|
|
|
throw std::runtime_error(message);
|
|
|
|
}
|
|
|
|
|
2020-05-24 08:10:18 -05:00
|
|
|
TST_LOG('[' << prefix << "] Ignored " <<
|
2021-11-18 06:08:14 -06:00
|
|
|
COOLWebSocket::getAbbreviatedFrameDump(response.data(), bytes, flags));
|
2016-09-20 19:41:30 -05:00
|
|
|
}
|
2016-05-03 22:35:34 -05:00
|
|
|
}
|
2016-10-21 11:59:03 -05:00
|
|
|
}
|
2020-01-20 09:16:36 -06:00
|
|
|
while ((flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE);
|
2016-05-03 22:35:34 -05:00
|
|
|
}
|
|
|
|
catch (const Poco::Net::WebSocketException& exc)
|
|
|
|
{
|
2021-03-08 17:18:33 -06:00
|
|
|
TST_LOG('[' << prefix << "] ERROR in helpers::getResponseMessage: " << exc.message());
|
2016-05-03 22:35:34 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return std::vector<char>();
|
|
|
|
}
|
|
|
|
|
2021-04-04 20:25:40 -05:00
|
|
|
inline std::vector<char> getResponseMessage(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& prefix, const std::string& testname,
|
|
|
|
const std::chrono::milliseconds timeoutMs
|
|
|
|
= std::chrono::seconds(10))
|
|
|
|
{
|
|
|
|
return ws->waitForMessage(prefix, timeoutMs, testname);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline std::string getResponseString(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& prefix, const std::string& testname,
|
|
|
|
const std::chrono::milliseconds timeoutMs
|
|
|
|
= std::chrono::seconds(10))
|
|
|
|
{
|
|
|
|
const std::vector<char> response = ws->waitForMessage(prefix, timeoutMs, testname);
|
|
|
|
|
|
|
|
return std::string(response.data(), response.size());
|
|
|
|
}
|
|
|
|
|
2021-04-04 22:17:39 -05:00
|
|
|
inline std::string assertResponseString(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& prefix, const std::string& testname,
|
|
|
|
const std::chrono::milliseconds timeoutMs
|
|
|
|
= std::chrono::seconds(10))
|
|
|
|
{
|
|
|
|
auto res = getResponseString(ws, prefix, testname, timeoutMs);
|
|
|
|
LOK_ASSERT_EQUAL(prefix, res.substr(0, prefix.length()));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2021-04-13 00:46:02 -05:00
|
|
|
inline int countMessages(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& prefix, const std::string& testname,
|
|
|
|
const std::chrono::milliseconds timeoutMs = std::chrono::seconds(10))
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
while (!getResponseMessage(ws, prefix, testname, timeoutMs).empty())
|
|
|
|
++count;
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline std::vector<char> getResponseMessage(const std::shared_ptr<COOLWebSocket>& ws,
|
2021-03-31 16:45:02 -05:00
|
|
|
const std::string& prefix, const std::string& testname,
|
|
|
|
const std::chrono::milliseconds timeoutMs
|
|
|
|
= std::chrono::seconds(10))
|
2016-05-10 20:38:03 -05:00
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
return getResponseMessage(*ws, prefix, testname, timeoutMs);
|
2016-05-10 20:38:03 -05:00
|
|
|
}
|
|
|
|
|
2016-10-08 20:24:45 -05:00
|
|
|
template <typename T>
|
2021-03-31 16:45:02 -05:00
|
|
|
std::string getResponseString(T& ws, const std::string& prefix, const std::string& testname,
|
|
|
|
const std::chrono::milliseconds timeoutMs = std::chrono::seconds(10))
|
2016-10-08 18:40:49 -05:00
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
const auto response = getResponseMessage(ws, prefix, testname, timeoutMs);
|
2016-10-08 18:40:49 -05:00
|
|
|
return std::string(response.data(), response.size());
|
2021-03-31 12:38:17 -05:00
|
|
|
}
|
|
|
|
|
2016-05-10 20:38:03 -05:00
|
|
|
template <typename T>
|
2021-03-31 16:45:02 -05:00
|
|
|
std::string assertResponseString(T& ws, const std::string& prefix, const std::string& testname,
|
|
|
|
const std::chrono::milliseconds timeoutMs
|
|
|
|
= std::chrono::seconds(10))
|
2016-05-10 20:38:03 -05:00
|
|
|
{
|
2021-04-04 22:17:39 -05:00
|
|
|
auto res = getResponseString(ws, prefix, testname, timeoutMs);
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_EQUAL(prefix, res.substr(0, prefix.length()));
|
2016-05-13 12:46:13 -05:00
|
|
|
return res;
|
2016-05-10 20:38:03 -05:00
|
|
|
}
|
|
|
|
|
2016-08-30 22:15:44 -05:00
|
|
|
/// Assert that we don't get a response with the given prefix.
|
|
|
|
template <typename T>
|
2018-08-27 02:10:01 -05:00
|
|
|
std::string assertNotInResponse(T& ws, const std::string& prefix, const std::string& testname)
|
2016-08-30 22:15:44 -05:00
|
|
|
{
|
2021-03-31 16:45:02 -05:00
|
|
|
const auto res = getResponseString(ws, prefix, testname, std::chrono::milliseconds(1000));
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_MESSAGE(testname + "Did not expect getting message [" + res + "].", res.empty());
|
2016-08-30 22:15:44 -05:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline int countMessages(COOLWebSocket& ws, const std::string& prefix, const std::string& testname,
|
2021-03-31 16:45:02 -05:00
|
|
|
const std::chrono::milliseconds timeoutMs = std::chrono::seconds(10))
|
2019-10-19 11:33:22 -05:00
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
while (!getResponseMessage(ws, prefix, testname, timeoutMs).empty())
|
|
|
|
++count;
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline int countMessages(const std::shared_ptr<COOLWebSocket>& ws, const std::string& prefix,
|
2021-03-31 16:45:02 -05:00
|
|
|
const std::string& testname,
|
|
|
|
const std::chrono::milliseconds timeoutMs = std::chrono::seconds(10))
|
2019-10-19 11:33:22 -05:00
|
|
|
{
|
|
|
|
return countMessages(*ws, prefix, testname, timeoutMs);
|
|
|
|
}
|
|
|
|
|
2016-10-08 20:48:41 -05:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
bool isDocumentLoaded(COOLWebSocket& ws, const std::string& testname, bool isView = true)
|
2016-10-08 20:48:41 -05:00
|
|
|
{
|
|
|
|
const std::string prefix = isView ? "status:" : "statusindicatorfinish:";
|
2021-11-02 02:29:24 -05:00
|
|
|
std::chrono::seconds timeout(60);
|
2021-11-08 06:46:38 -06:00
|
|
|
#if defined(__has_feature)
|
|
|
|
#if __has_feature(address_sanitizer)
|
2021-11-03 02:25:35 -05:00
|
|
|
timeout = std::chrono::seconds(120);
|
2021-11-08 06:46:38 -06:00
|
|
|
#endif
|
2021-11-03 02:25:35 -05:00
|
|
|
#endif
|
2021-11-02 02:29:24 -05:00
|
|
|
const auto message = getResponseString(ws, prefix, testname, timeout);
|
2021-11-18 06:08:14 -06:00
|
|
|
bool success = COOLProtocol::matchPrefix(prefix, message);
|
2020-01-17 14:49:38 -06:00
|
|
|
if (!success)
|
2021-11-02 02:29:24 -05:00
|
|
|
TST_LOG("ERR: Timed out loading document after " << timeout);
|
2020-01-17 14:49:38 -06:00
|
|
|
return success;
|
2016-10-08 20:48:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
bool isDocumentLoaded(std::shared_ptr<COOLWebSocket>& ws, const std::string& testname, bool isView = true)
|
2016-10-08 20:48:41 -05:00
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
return isDocumentLoaded(*ws, testname, isView);
|
2016-10-08 20:48:41 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 12:38:17 -05:00
|
|
|
inline bool isDocumentLoaded(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& testname, bool isView = true)
|
|
|
|
{
|
|
|
|
const std::string prefix = isView ? "status:" : "statusindicatorfinish:";
|
|
|
|
constexpr auto timeout = std::chrono::seconds(20); // Allow 20 secs to load
|
|
|
|
const std::string message = getResponseString(ws, prefix, testname, timeout);
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
const bool success = COOLProtocol::matchPrefix(prefix, message);
|
2021-03-31 12:38:17 -05:00
|
|
|
if (!success)
|
|
|
|
TST_LOG("ERROR: Timed out loading document. Did not get [" << prefix << "] in time.");
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2016-05-10 20:38:03 -05:00
|
|
|
// Connecting to a Kit process is managed by document broker, that it does several
|
|
|
|
// jobs to establish the bridge connection between the Client and Kit process,
|
|
|
|
// The result, it is mostly time outs to get messages in the unit test and it could fail.
|
|
|
|
// connectLOKit ensures the websocket is connected to a kit process.
|
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
std::shared_ptr<COOLWebSocket>
|
2016-09-15 03:33:18 -05:00
|
|
|
connectLOKit(const Poco::URI& uri,
|
2016-05-10 20:38:03 -05:00
|
|
|
Poco::Net::HTTPRequest& request,
|
2016-05-13 07:46:39 -05:00
|
|
|
Poco::Net::HTTPResponse& response,
|
2018-02-11 12:16:42 -06:00
|
|
|
const std::string& testname)
|
2016-05-10 20:38:03 -05:00
|
|
|
{
|
2021-03-08 17:18:33 -06:00
|
|
|
TST_LOG("Connecting to " << uri.toString());
|
|
|
|
constexpr int max_retries = 11;
|
|
|
|
int retries = max_retries - 1;
|
2016-05-10 20:38:03 -05:00
|
|
|
do
|
|
|
|
{
|
2016-11-15 15:22:02 -06:00
|
|
|
try
|
2016-11-12 12:25:35 -06:00
|
|
|
{
|
2016-11-15 15:22:02 -06:00
|
|
|
std::unique_ptr<Poco::Net::HTTPClientSession> session(createSession(uri));
|
2021-03-25 13:20:54 -05:00
|
|
|
TST_LOG("Connection to " << uri.toString() << " is "
|
|
|
|
<< (session->secure() ? "secure" : "plain"));
|
2021-11-18 06:08:14 -06:00
|
|
|
auto ws = std::make_shared<COOLWebSocket>(*session, request, response);
|
2021-03-08 17:18:33 -06:00
|
|
|
|
2018-02-07 03:17:42 -06:00
|
|
|
const char* expected_response = "statusindicator: ready";
|
2021-03-08 17:18:33 -06:00
|
|
|
|
|
|
|
TST_LOG("Connected to " << uri.toString() << ", waiting for response ["
|
|
|
|
<< expected_response << "]");
|
2018-01-22 08:11:43 -06:00
|
|
|
if (getResponseString(ws, expected_response, testname) == expected_response)
|
2016-11-15 15:22:02 -06:00
|
|
|
{
|
|
|
|
return ws;
|
|
|
|
}
|
|
|
|
|
2021-03-08 17:18:33 -06:00
|
|
|
TST_LOG("ERROR: Reconnecting (retry #" << (max_retries - retries) << ") to " << uri.toString());
|
2016-11-15 15:22:02 -06:00
|
|
|
}
|
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
2021-03-08 17:18:33 -06:00
|
|
|
TST_LOG("ERROR: Failed to connect to " << uri.toString() << ": " << ex.what());
|
2016-11-12 12:25:35 -06:00
|
|
|
}
|
2016-05-10 20:38:03 -05:00
|
|
|
|
2020-04-09 08:43:51 -05:00
|
|
|
std::this_thread::sleep_for(std::chrono::microseconds(POLL_TIMEOUT_MICRO_S));
|
2016-05-10 20:38:03 -05:00
|
|
|
}
|
|
|
|
while (retries--);
|
|
|
|
|
2021-03-08 17:18:33 -06:00
|
|
|
TST_LOG("ERROR: Giving up connecting to " << uri.toString());
|
2016-11-12 12:25:35 -06:00
|
|
|
throw std::runtime_error("Cannot connect to [" + uri.toString() + "].");
|
2016-05-08 23:39:01 -05:00
|
|
|
}
|
2016-05-03 22:35:34 -05:00
|
|
|
|
2021-03-31 16:11:51 -05:00
|
|
|
// Connecting to a Kit process is managed by document broker, that it does several
|
|
|
|
// jobs to establish the bridge connection between the Client and Kit process,
|
|
|
|
// The result, it is mostly time outs to get messages in the unit test and it could fail.
|
|
|
|
// connectLOKit ensures the websocket is connected to a kit process.
|
2021-04-12 23:48:47 -05:00
|
|
|
inline std::shared_ptr<http::WebSocketSession> connectLOKit(std::shared_ptr<SocketPoll> socketPoll,
|
2021-03-31 16:11:51 -05:00
|
|
|
const Poco::URI& uri,
|
|
|
|
const std::string& url,
|
|
|
|
const std::string& testname)
|
|
|
|
{
|
|
|
|
TST_LOG("Connecting to " << uri.toString());
|
|
|
|
constexpr int max_retries = 11;
|
|
|
|
int retries = max_retries - 1;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Load a document and get its status.
|
|
|
|
auto ws = http::WebSocketSession::create(uri.toString());
|
|
|
|
|
|
|
|
TST_LOG("Connection to " << uri.toString() << " is "
|
|
|
|
<< (ws->secure() ? "secure" : "plain"));
|
|
|
|
|
|
|
|
http::Request req(url);
|
2021-04-12 23:48:47 -05:00
|
|
|
ws->asyncRequest(req, std::move(socketPoll));
|
2021-03-31 16:11:51 -05:00
|
|
|
|
|
|
|
const char* expected_response = "statusindicator: ready";
|
|
|
|
|
|
|
|
TST_LOG("Connected to " << uri.toString() << ", waiting for response ["
|
|
|
|
<< expected_response << "]");
|
|
|
|
if (getResponseString(ws, expected_response, testname) == expected_response)
|
|
|
|
{
|
|
|
|
return ws;
|
|
|
|
}
|
|
|
|
|
|
|
|
TST_LOG("ERROR: Reconnecting (retry #" << (max_retries - retries) << ") to "
|
|
|
|
<< uri.toString());
|
|
|
|
}
|
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
|
|
|
TST_LOG("ERROR: Failed to connect to " << uri.toString() << ": " << ex.what());
|
|
|
|
}
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::microseconds(POLL_TIMEOUT_MICRO_S));
|
|
|
|
} while (retries--);
|
|
|
|
|
|
|
|
TST_LOG("ERROR: Giving up connecting to " << uri.toString());
|
|
|
|
throw std::runtime_error("Cannot connect to [" + uri.toString() + "].");
|
|
|
|
}
|
|
|
|
|
2016-04-28 21:44:40 -05:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
std::shared_ptr<COOLWebSocket> loadDocAndGetSocket(const Poco::URI& uri, const std::string& documentURL, const std::string& testname, bool isView = true, bool isAssert = true)
|
2016-04-28 20:41:00 -05:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Load a document and get its status.
|
|
|
|
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, documentURL);
|
|
|
|
Poco::Net::HTTPResponse response;
|
2021-11-18 06:08:14 -06:00
|
|
|
std::shared_ptr<COOLWebSocket> socket = connectLOKit(uri, request, response, testname);
|
2016-04-28 20:41:00 -05:00
|
|
|
|
2018-01-22 08:11:43 -06:00
|
|
|
sendTextFrame(socket, "load url=" + documentURL, testname);
|
2019-08-30 05:22:04 -05:00
|
|
|
bool isLoaded = isDocumentLoaded(*socket, testname, isView);
|
|
|
|
if (!isLoaded && !isAssert)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
2021-01-19 20:40:54 -06:00
|
|
|
|
|
|
|
LOK_ASSERT_MESSAGE("Failed to load the document " + documentURL, isLoaded);
|
2016-04-28 20:41:00 -05:00
|
|
|
|
2018-01-22 08:11:43 -06:00
|
|
|
TST_LOG("Loaded document [" << documentURL << "].");
|
2016-04-28 20:41:00 -05:00
|
|
|
return socket;
|
|
|
|
}
|
|
|
|
catch (const Poco::Exception& exc)
|
|
|
|
{
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_FAIL(exc.displayText());
|
2016-04-28 20:41:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Really couldn't reach here, but the compiler doesn't know any better.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-08-28 11:25:40 -05:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
std::shared_ptr<COOLWebSocket> loadDocAndGetSocket(const std::string& docFilename, const Poco::URI& uri, const std::string& testname, bool isView = true, bool isAssert = true)
|
2016-08-28 11:25:40 -05:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
std::string documentPath, documentURL;
|
2018-01-22 08:11:43 -06:00
|
|
|
getDocumentPathAndURL(docFilename, documentPath, documentURL, testname);
|
2019-08-30 05:22:04 -05:00
|
|
|
return loadDocAndGetSocket(uri, documentURL, testname, isView, isAssert);
|
2016-08-28 11:25:40 -05:00
|
|
|
}
|
|
|
|
catch (const Poco::Exception& exc)
|
|
|
|
{
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_FAIL(exc.displayText());
|
2016-08-28 11:25:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Really couldn't reach here, but the compiler doesn't know any better.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-03-31 12:38:17 -05:00
|
|
|
inline std::shared_ptr<http::WebSocketSession>
|
2021-04-12 23:48:47 -05:00
|
|
|
loadDocAndGetSession(std::shared_ptr<SocketPoll> socketPoll, const Poco::URI& uri,
|
|
|
|
const std::string& documentURL, const std::string& testname,
|
|
|
|
bool isView = true, bool isAssert = true)
|
2021-03-31 12:38:17 -05:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Load a document and get its status.
|
|
|
|
auto ws = http::WebSocketSession::create(uri.toString());
|
|
|
|
http::Request req(documentURL);
|
2021-04-12 23:48:47 -05:00
|
|
|
ws->asyncRequest(req, std::move(socketPoll));
|
2021-03-31 12:38:17 -05:00
|
|
|
|
|
|
|
sendTextFrame(ws, "load url=" + documentURL, testname);
|
|
|
|
const bool isLoaded = isDocumentLoaded(ws, testname, isView);
|
|
|
|
if (!isLoaded && !isAssert)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOK_ASSERT_MESSAGE("Failed to load the document " + documentURL, isLoaded);
|
|
|
|
|
|
|
|
TST_LOG("Loaded document [" << documentURL << "].");
|
|
|
|
return ws;
|
|
|
|
}
|
|
|
|
catch (const Poco::Exception& ex)
|
|
|
|
{
|
|
|
|
LOK_ASSERT_FAIL(ex.displayText());
|
|
|
|
}
|
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
|
|
|
LOK_ASSERT_FAIL(ex.what());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Really can't reach here, but the compiler doesn't know better.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-03-31 15:50:21 -05:00
|
|
|
inline std::shared_ptr<http::WebSocketSession>
|
2021-04-12 23:48:47 -05:00
|
|
|
loadDocAndGetSession(std::shared_ptr<SocketPoll> socketPoll, const std::string& docFilename,
|
|
|
|
const Poco::URI& uri, const std::string& testname, bool isView = true,
|
|
|
|
bool isAssert = true)
|
2021-03-31 15:50:21 -05:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
std::string documentPath, documentURL;
|
|
|
|
getDocumentPathAndURL(docFilename, documentPath, documentURL, testname);
|
2021-04-12 23:48:47 -05:00
|
|
|
return loadDocAndGetSession(std::move(socketPoll), uri, documentURL, testname, isView, isAssert);
|
2021-03-31 15:50:21 -05:00
|
|
|
}
|
|
|
|
catch (const std::exception& ex)
|
|
|
|
{
|
|
|
|
LOK_ASSERT_FAIL(ex.what());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Really couldn't reach here, but the compiler doesn't know any better.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-03-31 16:45:02 -05:00
|
|
|
inline void SocketProcessor(const std::string& testname,
|
2021-11-18 06:08:14 -06:00
|
|
|
const std::shared_ptr<COOLWebSocket>& socket,
|
2021-03-31 16:45:02 -05:00
|
|
|
const std::function<bool(const std::string& msg)>& handler,
|
|
|
|
const std::chrono::milliseconds timeoutMs = std::chrono::seconds(10))
|
2016-04-28 20:41:00 -05:00
|
|
|
{
|
2016-04-28 21:43:59 -05:00
|
|
|
socket->setReceiveTimeout(0);
|
|
|
|
|
2021-03-31 16:45:02 -05:00
|
|
|
const Poco::Timespan waitTime(std::chrono::microseconds(timeoutMs).count());
|
2016-05-13 07:46:39 -05:00
|
|
|
int flags = 0;
|
|
|
|
int n = 0;
|
2016-11-25 03:46:01 -06:00
|
|
|
char buffer[READ_BUFFER_SIZE];
|
2016-04-28 20:41:00 -05:00
|
|
|
do
|
|
|
|
{
|
2016-04-28 21:43:59 -05:00
|
|
|
if (!socket->poll(waitTime, Poco::Net::Socket::SELECT_READ))
|
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
TST_LOG("Timeout polling.");
|
2016-04-28 21:43:59 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-03-08 20:59:33 -06:00
|
|
|
n = socket->receiveFrame(buffer, sizeof(buffer), flags, testname);
|
2021-11-18 06:08:14 -06:00
|
|
|
TST_LOG("Got " << COOLWebSocket::getAbbreviatedFrameDump(buffer, n, flags));
|
2016-04-28 20:41:00 -05:00
|
|
|
if (n > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE)
|
|
|
|
{
|
2016-11-25 03:46:01 -06:00
|
|
|
if (!handler(std::string(buffer, n)))
|
2016-04-28 20:41:00 -05:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (n > 0 && (flags & Poco::Net::WebSocket::FRAME_OP_BITMASK) != Poco::Net::WebSocket::FRAME_OP_CLOSE);
|
|
|
|
}
|
|
|
|
|
2021-03-31 12:38:17 -05:00
|
|
|
inline void
|
|
|
|
SocketProcessor(const std::string& testname, const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::function<bool(const std::string& msg)>& handler,
|
|
|
|
const std::chrono::milliseconds timeout = std::chrono::milliseconds(10000))
|
|
|
|
{
|
|
|
|
ws->poll(
|
|
|
|
[&](const std::vector<char>& message) {
|
|
|
|
return !handler(std::string(message.data(), message.size()));
|
|
|
|
},
|
|
|
|
timeout, testname);
|
|
|
|
}
|
|
|
|
|
2016-05-22 17:52:36 -05:00
|
|
|
inline
|
2016-08-30 17:19:05 -05:00
|
|
|
void parseDocSize(const std::string& message, const std::string& type,
|
2022-02-16 16:22:18 -06:00
|
|
|
int& part, int& parts, int& width, int& height, int& viewid,
|
|
|
|
const std::string& testname)
|
2016-05-22 17:52:36 -05:00
|
|
|
{
|
2020-05-21 09:22:49 -05:00
|
|
|
StringVector tokens(Util::tokenize(message, ' '));
|
2016-05-22 17:52:36 -05:00
|
|
|
|
|
|
|
// Expected format is something like 'type= parts= current= width= height='.
|
|
|
|
const std::string text = tokens[0].substr(std::string("type=").size());
|
|
|
|
parts = std::stoi(tokens[1].substr(std::string("parts=").size()));
|
|
|
|
part = std::stoi(tokens[2].substr(std::string("current=").size()));
|
|
|
|
width = std::stoi(tokens[3].substr(std::string("width=").size()));
|
|
|
|
height = std::stoi(tokens[4].substr(std::string("height=").size()));
|
2016-07-26 07:03:46 -05:00
|
|
|
viewid = std::stoi(tokens[5].substr(std::string("viewid=").size()));
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_EQUAL(type, text);
|
2022-02-16 16:24:54 -06:00
|
|
|
LOK_ASSERT(parts > 0);
|
|
|
|
LOK_ASSERT(part >= 0);
|
|
|
|
LOK_ASSERT(width > 0);
|
|
|
|
LOK_ASSERT(height > 0);
|
|
|
|
LOK_ASSERT(viewid >= 0);
|
2016-05-22 17:52:36 -05:00
|
|
|
}
|
|
|
|
|
2021-04-04 22:17:39 -05:00
|
|
|
inline std::vector<char> getTileMessage(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& testname)
|
|
|
|
{
|
|
|
|
return getResponseMessage(ws, "tile", testname);
|
|
|
|
}
|
|
|
|
|
2016-05-22 18:53:24 -05:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
std::vector<char> getTileMessage(COOLWebSocket& ws, const std::string& testname)
|
2016-05-22 18:53:24 -05:00
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
return getResponseMessage(ws, "tile", testname);
|
2016-05-22 18:53:24 -05:00
|
|
|
}
|
|
|
|
|
2016-08-21 19:16:56 -05:00
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
std::vector<char> assertTileMessage(COOLWebSocket& ws, const std::string& testname)
|
2016-08-21 19:16:56 -05:00
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
const std::vector<char> response = getTileMessage(ws, testname);
|
2016-08-21 19:16:56 -05:00
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
const std::string firstLine = COOLProtocol::getFirstLine(response);
|
2020-05-21 09:22:49 -05:00
|
|
|
StringVector tileTokens(Util::tokenize(firstLine, ' '));
|
2020-01-20 10:45:53 -06:00
|
|
|
LOK_ASSERT_EQUAL(std::string("tile:"), tileTokens[0]);
|
|
|
|
LOK_ASSERT_EQUAL(std::string("part="), tileTokens[1].substr(0, std::string("part=").size()));
|
|
|
|
LOK_ASSERT_EQUAL(std::string("width="), tileTokens[2].substr(0, std::string("width=").size()));
|
|
|
|
LOK_ASSERT_EQUAL(std::string("height="), tileTokens[3].substr(0, std::string("height=").size()));
|
|
|
|
LOK_ASSERT_EQUAL(std::string("tileposx="), tileTokens[4].substr(0, std::string("tileposx=").size()));
|
|
|
|
LOK_ASSERT_EQUAL(std::string("tileposy="), tileTokens[5].substr(0, std::string("tileposy=").size()));
|
|
|
|
LOK_ASSERT_EQUAL(std::string("tilewidth="), tileTokens[6].substr(0, std::string("tilewidth=").size()));
|
|
|
|
LOK_ASSERT_EQUAL(std::string("tileheight="), tileTokens[7].substr(0, std::string("tileheight=").size()));
|
2016-08-21 19:16:56 -05:00
|
|
|
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline
|
2021-11-18 06:08:14 -06:00
|
|
|
std::vector<char> assertTileMessage(const std::shared_ptr<COOLWebSocket>& ws, const std::string& testname)
|
2016-08-21 19:16:56 -05:00
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
return assertTileMessage(*ws, testname);
|
2016-08-21 19:16:56 -05:00
|
|
|
}
|
|
|
|
|
2016-05-12 04:23:37 -05:00
|
|
|
enum SpecialKey { skNone=0, skShift=0x1000, skCtrl=0x2000, skAlt=0x4000 };
|
|
|
|
|
|
|
|
inline int getCharChar(char ch, SpecialKey specialKeys)
|
|
|
|
{
|
|
|
|
// Some primitive code just suitable to basic needs of specific test.
|
|
|
|
// TODO: improve as appropriate.
|
|
|
|
if (specialKeys & (skCtrl | skAlt))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (ch)
|
|
|
|
{
|
|
|
|
case '\x0a': // Enter
|
|
|
|
return 13;
|
|
|
|
default:
|
|
|
|
return ch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int getCharKey(char ch, SpecialKey specialKeys)
|
|
|
|
{
|
|
|
|
// Some primitive code just suitable to basic needs of specific test.
|
|
|
|
// TODO: improve as appropriate.
|
|
|
|
int result;
|
|
|
|
switch (ch)
|
|
|
|
{
|
|
|
|
case '\x0a': // Enter
|
|
|
|
result = 1280;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result = ch;
|
|
|
|
}
|
|
|
|
return result | specialKeys;
|
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline void sendKeyEvent(std::shared_ptr<COOLWebSocket>& socket, const char* type, int chr, int key, const std::string& testname)
|
2016-05-12 04:23:37 -05:00
|
|
|
{
|
|
|
|
std::ostringstream ssIn;
|
|
|
|
ssIn << "key type=" << type << " char=" << chr << " key=" << key;
|
2016-10-07 22:38:11 -05:00
|
|
|
sendTextFrame(socket, ssIn.str(), testname);
|
2016-05-12 04:23:37 -05:00
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline void sendKeyPress(std::shared_ptr<COOLWebSocket>& socket, int chr, int key, const std::string& testname)
|
2016-05-12 04:23:37 -05:00
|
|
|
{
|
2016-10-07 22:38:11 -05:00
|
|
|
sendKeyEvent(socket, "input", chr, key, testname);
|
|
|
|
sendKeyEvent(socket, "up", chr, key, testname);
|
2016-05-12 04:23:37 -05:00
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline void sendChar(std::shared_ptr<COOLWebSocket>& socket, char ch, SpecialKey specialKeys, const std::string& testname)
|
2016-05-12 04:23:37 -05:00
|
|
|
{
|
2016-10-07 22:38:11 -05:00
|
|
|
sendKeyPress(socket, getCharChar(ch, specialKeys), getCharKey(ch, specialKeys), testname);
|
2016-05-12 04:23:37 -05:00
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline void sendText(std::shared_ptr<COOLWebSocket>& socket, const std::string& text, const std::string& testname)
|
2021-04-04 22:17:39 -05:00
|
|
|
{
|
|
|
|
for (char ch : text)
|
|
|
|
{
|
|
|
|
sendChar(socket, ch, skNone, testname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void sendKeyEvent(std::shared_ptr<http::WebSocketSession>& socket, const char* type, int chr,
|
|
|
|
int key, const std::string& testname)
|
|
|
|
{
|
|
|
|
std::ostringstream ssIn;
|
|
|
|
ssIn << "key type=" << type << " char=" << chr << " key=" << key;
|
|
|
|
sendTextFrame(socket, ssIn.str(), testname);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void sendKeyPress(std::shared_ptr<http::WebSocketSession>& socket, int chr, int key,
|
|
|
|
const std::string& testname)
|
|
|
|
{
|
|
|
|
sendKeyEvent(socket, "input", chr, key, testname);
|
|
|
|
sendKeyEvent(socket, "up", chr, key, testname);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void sendChar(std::shared_ptr<http::WebSocketSession>& socket, char ch,
|
|
|
|
SpecialKey specialKeys, const std::string& testname)
|
|
|
|
{
|
|
|
|
sendKeyPress(socket, getCharChar(ch, specialKeys), getCharKey(ch, specialKeys), testname);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void sendText(std::shared_ptr<http::WebSocketSession>& socket, const std::string& text,
|
|
|
|
const std::string& testname)
|
2016-05-12 04:23:37 -05:00
|
|
|
{
|
|
|
|
for (char ch : text)
|
|
|
|
{
|
2016-10-07 22:38:11 -05:00
|
|
|
sendChar(socket, ch, skNone, testname);
|
2016-05-12 04:23:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-06 14:02:52 -05:00
|
|
|
inline void saveTileAs(const std::vector<char> &tileResponse,
|
|
|
|
const std::string &filename,
|
|
|
|
const std::string &testname)
|
|
|
|
{
|
2021-11-18 06:08:14 -06:00
|
|
|
const std::string firstLine = COOLProtocol::getFirstLine(tileResponse);
|
2019-05-06 14:02:52 -05:00
|
|
|
std::vector<char> res(tileResponse.begin() + firstLine.size() + 1, tileResponse.end());
|
|
|
|
std::stringstream streamRes;
|
|
|
|
std::copy(res.begin(), res.end(), std::ostream_iterator<char>(streamRes));
|
|
|
|
std::fstream outStream(filename, std::ios::out);
|
|
|
|
outStream.write(res.data(), res.size());
|
|
|
|
outStream.close();
|
2020-05-24 08:10:18 -05:00
|
|
|
TST_LOG("Saved [" << firstLine << "] to [" << filename << ']');
|
2019-05-06 14:02:52 -05:00
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline std::vector<char> getTileAndSave(std::shared_ptr<COOLWebSocket>& socket,
|
2017-04-30 20:54:38 -05:00
|
|
|
const std::string& req,
|
|
|
|
const std::string& filename,
|
|
|
|
const std::string& testname)
|
|
|
|
{
|
2018-01-22 08:11:43 -06:00
|
|
|
TST_LOG("Requesting: " << req);
|
2017-04-30 20:54:38 -05:00
|
|
|
sendTextFrame(socket, req, testname);
|
|
|
|
|
2018-02-07 03:17:42 -06:00
|
|
|
const std::vector<char> tile = getResponseMessage(socket, "tile:", testname);
|
2018-01-22 08:11:43 -06:00
|
|
|
TST_LOG(" Tile PNG size: " << tile.size());
|
2017-04-30 20:54:38 -05:00
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
const std::string firstLine = COOLProtocol::getFirstLine(tile);
|
2017-04-30 20:54:38 -05:00
|
|
|
std::vector<char> res(tile.begin() + firstLine.size() + 1, tile.end());
|
|
|
|
std::stringstream streamRes;
|
|
|
|
std::copy(res.begin(), res.end(), std::ostream_iterator<char>(streamRes));
|
|
|
|
|
|
|
|
if (!filename.empty())
|
2019-05-06 14:02:52 -05:00
|
|
|
saveTileAs(tile, filename, testname);
|
2017-04-30 20:54:38 -05:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline void getServerVersion(COOLWebSocket& socket,
|
2017-05-01 23:01:28 -05:00
|
|
|
int& major, int& minor,
|
|
|
|
const std::string& testname)
|
|
|
|
{
|
2021-11-17 04:16:38 -06:00
|
|
|
const std::string clientVersion = "coolclient 0.1";
|
2018-02-11 12:16:42 -06:00
|
|
|
sendTextFrame(socket, clientVersion, testname);
|
2017-05-01 23:01:28 -05:00
|
|
|
std::vector<char> loVersion = getResponseMessage(socket, "lokitversion", testname);
|
2021-11-18 06:08:14 -06:00
|
|
|
std::string line = COOLProtocol::getFirstLine(loVersion.data(), loVersion.size());
|
2017-05-01 23:01:28 -05:00
|
|
|
line = line.substr(strlen("lokitversion "));
|
|
|
|
Poco::JSON::Parser parser;
|
|
|
|
Poco::Dynamic::Var loVersionVar = parser.parse(line);
|
|
|
|
const Poco::SharedPtr<Poco::JSON::Object>& loVersionObject = loVersionVar.extract<Poco::JSON::Object::Ptr>();
|
|
|
|
std::string loProductVersion = loVersionObject->get("ProductVersion").toString();
|
|
|
|
std::istringstream stream(loProductVersion);
|
|
|
|
stream >> major;
|
2021-04-16 07:10:46 -05:00
|
|
|
if (stream.get() == '.')
|
|
|
|
{
|
|
|
|
stream >> minor;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
minor = 0;
|
|
|
|
}
|
2017-05-01 23:01:28 -05:00
|
|
|
|
2018-01-22 08:11:43 -06:00
|
|
|
TST_LOG("Client [" << major << '.' << minor << "].");
|
2017-05-01 23:01:28 -05:00
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline void getServerVersion(std::shared_ptr<COOLWebSocket>& socket,
|
2017-05-01 23:01:28 -05:00
|
|
|
int& major, int& minor,
|
|
|
|
const std::string& testname)
|
|
|
|
{
|
|
|
|
getServerVersion(*socket, major, minor, testname);
|
|
|
|
}
|
|
|
|
|
2022-02-16 16:22:18 -06:00
|
|
|
inline bool svgMatch(const std::string& testname, const std::vector<char>& response,
|
|
|
|
const char* templateFile)
|
2019-05-02 10:14:12 -05:00
|
|
|
{
|
|
|
|
const std::vector<char> expectedSVG = helpers::readDataFromFile(templateFile);
|
|
|
|
if (expectedSVG != response)
|
|
|
|
{
|
|
|
|
TST_LOG_BEGIN("Svg mismatch: response is\n");
|
|
|
|
if(response.empty())
|
|
|
|
TST_LOG_APPEND("<empty>");
|
|
|
|
else
|
|
|
|
TST_LOG_APPEND(std::string(response.data(), response.size()));
|
|
|
|
TST_LOG_APPEND("\nvs. expected (from '" << templateFile << "' :\n");
|
|
|
|
TST_LOG_APPEND(std::string(expectedSVG.data(), expectedSVG.size()));
|
|
|
|
std::string newName = templateFile;
|
|
|
|
newName += ".new";
|
2020-05-24 08:10:18 -05:00
|
|
|
TST_LOG_APPEND("Updated template writing to: " << newName << '\n');
|
2019-05-02 10:14:12 -05:00
|
|
|
TST_LOG_END;
|
2019-10-13 20:27:53 -05:00
|
|
|
|
2019-05-02 10:14:12 -05:00
|
|
|
FILE *of = fopen(Poco::Path(TDOC, newName).toString().c_str(), "w");
|
2022-02-16 16:24:54 -06:00
|
|
|
LOK_ASSERT(fwrite(response.data(), response.size(), 1, of) == response.size());
|
2019-05-02 10:14:12 -05:00
|
|
|
fclose(of);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
/// Select all and wait for the text selection update.
|
2021-11-18 06:08:14 -06:00
|
|
|
inline void selectAll(const std::shared_ptr<COOLWebSocket>& socket, const std::string& testname, int repeat = COMMAND_RETRY_COUNT)
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
{
|
|
|
|
for (int i = 0; i < repeat; ++i)
|
|
|
|
{
|
|
|
|
sendTextFrame(socket, "uno .uno:SelectAll", testname);
|
|
|
|
if (!getResponseString(socket, "textselection:", testname).empty())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-14 16:42:04 -05:00
|
|
|
/// Sends a command and waits for an event in response, with retrying.
|
|
|
|
inline void sendAndWait(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& testname, const std::string& command,
|
|
|
|
const std::string& response,
|
|
|
|
std::chrono::milliseconds timeoutPerAttempt = std::chrono::seconds(10),
|
|
|
|
int repeat = COMMAND_RETRY_COUNT)
|
2021-03-31 12:38:17 -05:00
|
|
|
{
|
2021-04-14 16:42:04 -05:00
|
|
|
for (int i = 1; i <= repeat; ++i)
|
2021-03-31 12:38:17 -05:00
|
|
|
{
|
2021-04-14 16:42:04 -05:00
|
|
|
TST_LOG("Sending [" << command << "], waiting for [" << response << "], attempt #" << i);
|
|
|
|
sendTextFrame(ws, command, testname);
|
|
|
|
if (!getResponseString(ws, response, testname, timeoutPerAttempt).empty())
|
2021-03-31 12:38:17 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
|
2021-04-15 07:59:24 -05:00
|
|
|
/// Sends a command and drain an event in response.
|
|
|
|
/// We expect @response within the given @timeoutResponse and
|
|
|
|
/// we drain all messages to get a steady-state.
|
|
|
|
/// Draining happens for @timeoutDrain.
|
|
|
|
inline bool sendAndDrain(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& testname, const std::string& command,
|
|
|
|
const std::string& response,
|
|
|
|
std::chrono::milliseconds timeoutResponse = std::chrono::seconds(10),
|
|
|
|
std::chrono::milliseconds timeoutDrain = std::chrono::milliseconds(300))
|
|
|
|
{
|
|
|
|
TST_LOG("Sending [" << command << "], waiting for [" << response
|
|
|
|
<< "], and draining the events.");
|
|
|
|
sendTextFrame(ws, command, testname);
|
|
|
|
const std::string res = getResponseString(ws, response, testname, timeoutResponse);
|
|
|
|
if (res.empty())
|
|
|
|
{
|
|
|
|
TST_LOG("Timed-out waiting for [" << response << "] after sending [" << command << "].");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!getResponseString(ws, response, testname, timeoutDrain).empty())
|
|
|
|
; // Skip.
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-04-14 16:42:04 -05:00
|
|
|
/// Select all and wait for the text selection update.
|
|
|
|
inline void selectAll(const std::shared_ptr<http::WebSocketSession>& ws,
|
|
|
|
const std::string& testname,
|
|
|
|
std::chrono::milliseconds timeoutPerAttempt = std::chrono::seconds(10),
|
|
|
|
int repeat = COMMAND_RETRY_COUNT)
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
{
|
2021-04-14 16:42:04 -05:00
|
|
|
sendAndWait(ws, testname, "uno .uno:SelectAll", "textselection:", timeoutPerAttempt, repeat);
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
}
|
|
|
|
|
2021-03-31 12:38:17 -05:00
|
|
|
/// Delete all and wait for the text selection update.
|
|
|
|
inline void deleteAll(const std::shared_ptr<http::WebSocketSession>& ws,
|
2021-04-14 16:42:04 -05:00
|
|
|
const std::string& testname,
|
|
|
|
std::chrono::milliseconds timeoutPerAttempt = std::chrono::seconds(10),
|
|
|
|
int repeat = COMMAND_RETRY_COUNT)
|
2021-03-31 12:38:17 -05:00
|
|
|
{
|
2021-12-01 19:13:02 -06:00
|
|
|
selectAll(ws, testname, timeoutPerAttempt, repeat);
|
2021-03-31 12:38:17 -05:00
|
|
|
|
2021-04-14 16:42:04 -05:00
|
|
|
sendAndWait(ws, testname, "uno .uno:Delete", "textselection:", timeoutPerAttempt, repeat);
|
2021-03-31 12:38:17 -05:00
|
|
|
}
|
|
|
|
|
2021-03-25 13:12:05 -05:00
|
|
|
inline std::string getAllText(const std::shared_ptr<http::WebSocketSession>& socket,
|
|
|
|
const std::string& testname,
|
|
|
|
const std::string& expected = std::string(),
|
|
|
|
int retry = COMMAND_RETRY_COUNT)
|
|
|
|
{
|
|
|
|
static const std::string prefix = "textselectioncontent: ";
|
|
|
|
|
2021-04-14 16:42:04 -05:00
|
|
|
for (int i = 1; i <= retry; ++i)
|
2021-03-25 13:12:05 -05:00
|
|
|
{
|
2021-04-14 16:42:04 -05:00
|
|
|
TST_LOG("getAllText attempt #" << i);
|
|
|
|
|
2021-03-25 13:12:05 -05:00
|
|
|
selectAll(socket, testname);
|
|
|
|
|
|
|
|
sendTextFrame(socket, "gettextselection mimetype=text/plain;charset=utf-8", testname);
|
|
|
|
std::string text = getResponseString(socket, prefix, testname);
|
|
|
|
if (!text.empty())
|
|
|
|
{
|
|
|
|
if (expected.empty() || (prefix + expected) == text)
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
|
2021-04-14 16:42:04 -05:00
|
|
|
/// Delete all and wait for the text selection update.
|
2021-11-18 06:08:14 -06:00
|
|
|
inline void deleteAll(const std::shared_ptr<COOLWebSocket>& socket, const std::string& testname, int repeat = COMMAND_RETRY_COUNT)
|
2021-04-14 16:42:04 -05:00
|
|
|
{
|
|
|
|
selectAll(socket, testname);
|
|
|
|
|
|
|
|
for (int i = 0; i < repeat; ++i)
|
|
|
|
{
|
|
|
|
sendTextFrame(socket, "uno .uno:Delete", testname);
|
|
|
|
if (!getResponseString(socket, "textselection:", testname).empty())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-18 06:08:14 -06:00
|
|
|
inline std::string getAllText(const std::shared_ptr<COOLWebSocket>& socket,
|
2019-10-19 11:32:43 -05:00
|
|
|
const std::string& testname,
|
2020-06-01 22:21:22 -05:00
|
|
|
const std::string& expected = std::string(),
|
2019-10-19 11:32:43 -05:00
|
|
|
int retry = COMMAND_RETRY_COUNT)
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
{
|
2019-10-19 11:32:43 -05:00
|
|
|
static const std::string prefix = "textselectioncontent: ";
|
|
|
|
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
for (int i = 0; i < retry; ++i)
|
|
|
|
{
|
|
|
|
selectAll(socket, testname);
|
|
|
|
|
|
|
|
sendTextFrame(socket, "gettextselection mimetype=text/plain;charset=utf-8", testname);
|
2021-03-25 13:12:05 -05:00
|
|
|
std::string text = getResponseString(socket, prefix, testname);
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
if (!text.empty())
|
2019-10-19 11:32:43 -05:00
|
|
|
{
|
|
|
|
if (expected.empty() || (prefix + expected) == text)
|
|
|
|
return text;
|
|
|
|
}
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
}
|
|
|
|
|
2019-10-19 11:32:43 -05:00
|
|
|
return std::string();
|
test: improve stability of a number of tests
There are numerous race conditions between issuing
action and getting the events. This causes a
mismatch, such that the events from SelectAll
is received when waiting for the events for a
subsequent action (say, Delete).
To make matters worse, sometimes Core issues
an invalidation whilst sending the events for
an action, and this completely messes our
accounting of what events we expect.
This latter could also be an issue with real
clients, however it's less likely to be
disruptive. Still, it is possible that
the client doesn't get key events
because Core had a hiccup, which breaks
the tests.
For the tests at least, the solution is to
re-issue the last action, such that we make
sure that we move forward only when the correct
event is received, or we timeout waiting.
The end results is that tests now don't fail
nearly as often as they used to.
Reviewed-on: https://gerrit.libreoffice.org/80894
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Andras Timar <andras.timar@collabora.com>
(cherry picked from commit 050403daf04d6b36ef850006ba4a15eab6be9afc)
Change-Id: Ib1a658846061990649987ca083915a49c1fb092a
Reviewed-on: https://gerrit.libreoffice.org/81565
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Tested-by: Ashod Nakashian <ashnakash@gmail.com>
2019-10-12 12:47:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-02-07 10:16:59 -06:00
|
|
|
|
2016-04-28 20:41:00 -05:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|