When client-test starts, it determines all tests that would get
run, then runs all of them one-by-one in new instances. A single
test gets run directly.
The output changes slightly: the CppUnit summary with number of
failures or errors is no longer available and there are additional
blank lines between tests.
The advantage is that each single test is properly isolated from the
other, which is closer to how real syncs run. It also helps when
running under valgrind, because a leak can be attributed exactly to
one test and because it avoids permanently growing memory consumption
in long-running client-test runs (seen in the nightly testing even
when there were no leaks, perhaps because of memory fragmentation).
A potential downside of this change is that unexpected and undesirable
side effects of modules might no longer show up in testing, only when
combining them in real syncs. This should still be covered by
Client::Sync tests involving multiple modules.
cppcheck warned about this. This wasn't actually a problem (one member
was not used at all, the other was set later), but for the sake of
clean cppcheck scans let's fix it.
Logging must be thread-safe, because the glib log callback may be
called from arbitrary threads. This becomes more important with EDS
3.8, because it shifts the execution of synchronous calls into
threads.
Thread-safe logging will also be required for running the Synthesis
engine multithreaded, to overlap SyncML client communication with
preparing the sources.
To achieve this, the core Logging module protects its global data with
a recursive mutex. A recursive mutes is used because logging calls
themselves may be recursive, so ensuring single-lock semantic would be
hard.
Ref-counted boost pointers are used to track usage of Logger
instances. This allows removal of an instance from the logging stack
while it may still be in use. Destruction then will be delayed until
the last user of the instance drops it. The instance itself must be
prepared to handle this.
The Logging mutex is available to users of the Logging module. Code
which holds the logging mutex should not lock any other mutex, to
avoid deadlocks. The new code is a bit fuzzy on that, because it calls
other modules (glib, Synthesis engine) while holding the mutex. If
that becomes a problem, then the mutex can be unlocked, at the risk of
leading to reordered log messages in different channels (see
ServerLogger).
Making all loggers follow the new rules uses different
approaches.
Loggers like the one in the local transport child which use a parent
logger and an additional ref-counted class like the D-Bus helper keep
a weak reference to the helper and lock it before use. If it is gone
already, the second logging part is skipped. This is the recommended
approach.
In cases where introducing ref-counting for the second class would
have been too intrusive (Server and SessionHelper), a fake
boost::shared_ptr without a destructor is used as an intermediate step
towards the recommended approach. To avoid race conditions while the
instance these fake pointers refer to destructs, an explicit
"remove()" method is necessary which must hold the Logging
mutex. Using the potentially removed pointer must do the same. Such
fake ref-counted Loggers cannot be used as parent logger of other
loggers, because then remove() would not be able to drop the last
reference to the fake boost::shared_ptr.
Loggers with fake boost::shared_ptr must keep a strong reference,
because no-one else does. The goal is to turn this into weak
references eventually.
LogDir must protect concurrent access to m_report and the Synthesis
engine.
The LogRedirectLogger assumes that it is still the active logger while
disabling itself. The remove() callback method will always be invoked
before removing a logger from the stack.
The code which marked a failure as "ignored" unintentionally
cleared the overall error flag, causing client-test runs
with ignored and real failures to return 0 = success.
The SyncContext::initMain() must be called in main(), to give
all global instances a chance to influence the operation (like
registering platform init code). This failed for KDE when
the order of global instance instantiation happened to be wrong.
Setting signal handlers there also makes more sense.
The reason for doing process initialization in src/client-test-app.cpp
was that the rest of the code was meant to be SyncEvolution and Unix
independent. That's less of a concern today.
Running additional commands from client-test becomes more
expensive when client-test runs under valgrind with tracing
of children (as needed for local sync testing). It also create
additional output (at least a valgrind header+footer per command).
Avoid calling additional commands as much as possible. Specifically:
- fork/exec synccompare in the simple case (avoids one /bin/sh call)
- avoid setting PATH via env before searching for synccompare (expected
to be in the PATH when client-test is called)
- use that simple case for all servers (appending the synccompare
output again at the end of a test log via CLIENT_TEST_COMPARE_LOG
isn't that useful and was missing from some servers anyway)
- copy files with some C code instead of invoking cp or cat
- do the translation of logs to html in runtests.py
Both comma separated lists may now contain regular expressions, which
is very useful to ignore or skip one test for all data categories, for
example.
Because tests names did not have special characters in them, previous
values still work as before for a literal match against just one test.
The HTML version of the .log files links to ClientTest.cpp.html,
colorizes important parts and links to the sync session
directories.
Because it is much more useful than the plain text version, the
nightly.html now links to these .html files.
ClientTest.cpp.html is built with Python pygments if installed,
otherwise some builtin fallback code is used.
The stdout of synccompare was no longer redirected into
the .log file of the test it belonged to. Enabled that
again by redirecting both stderr and stdout.
The test failed only because the test's own introduction text on
stdout ended up being redirected. Flushing it before running the
test avoids that.
The flushing was added to both the client runner (because some other
tests also accidentally redirected the output, and it should be
made visible right away) and to the "glib" test (because it shouldn't
depend on flushing in the runner).
The LogRedirect instance created in main() was not flushed often
enough because the LoggerStdout instance pushed into the stack after
it intercepted all output, so the LogRedirect instance was never
invoked during a test.
This patch solves that by replacing the LoggerStdout with a
LogRedirect instance. This instance is then called by the LogDir
logger.
client-test ran without redirection stderr, which produces a lot of
output in the console in particular with the mKCal backend. This patch enables
stderr redirection (as usual, only if SYNCEVOLUTION_DEBUG is not set).
All normal output now goes to stdout/std::cout.
Running client-test with SYNCEVOLUTION_DEBUG set now prints all debug
messages to the console directly instead of writing them into per-test
.log files. This is useful when running tests like Client::Local which
do not involve the Synthesis engine. Whe using the Synthesis engine,
the normal HTML .log files are easier to read.
Destroying ORBit based Evolution backends at the very end of the
process life time caused assertions in ORBit. Added explicit cleanup
code which is called before triggering the normal library shutdown by
leaving main().
Cmdline and SyncContext standard output should always go
through a variable that can be pointed towards the actual
output channel.
Cmdline already had m_out for that, but it wasn't used
everywhere. Fixed.
SyncContext now has setOutput()/getOutput() and that is
used in SyncContext.cpp. It is not set anywhere yet.
To catch incorrect use of cout or cerr inside SyncEvolution,
the SyncEvo namespace defines its own cout and cerr which cannot
be used like std::cout/cerr, thus triggering compiler
errors. Use "std::cout/cerr" when necessary.
The intention is to get rid of the historic and inconsistent
naming of some classes and their corresponding files:
* EvolutionSyncClient = class derived from Funambol's SyncClient,
* SyncEvolutionConfig = SyncEvolution's config
With the strict 'namespace SyncEvo' and the syncevo/ path prefix for
most header files it is no longer necessary to have "SyncEvolution" or
"Evolution" in the names. This patch thus renames as follows:
EvolutionSyncClient => SyncContext
EvolutionSmartPtr => SmartPtr
SyncEvolutionCmdline => Cmdline
SyncEvolutionConfig => SyncConfig
SyncEvolutionUtil => util
The former EvolutionSyncClient always had a role that went beyond just
running a sync, for example it also provided config access. With the
upcoming server support it also won't be just a client. Thus the new
name "SyncContext".
The 'syncevo/' prefix is used throughout the code now.
removed whenever the prefix made it clear that the file belongs
to SyncEvolution. This helps finding incorrect include paths.
Quotes should be used exclusively for SyncEvolution files which don't
have a specific prefix yet (test.h, config.h) to help identifying
them.
Added syncevo/declarations.h, which has
This is now used for all SyncEvolution source files, except
for the GTK UI, which is written in plain C. In the library
it helps to avoid name clashes.
The reason for using defines instead of spelling out "namespace SyncEvo"
is twofold:
1. if that should ever become necessary, it is easier to
rename the namespace via configure options by changing
the define
2. editors don't indent the whole file content
Instead of calling rm, simply keep the file. This might be useful
when running a single test. When running multiple tests, tee will
overwrite the old one.
As with the previous change from AGPLv3 to LGPL v2.1, this is covered
by copyright ownership and/or the Funambol contributor agreement.
The motivation for adding v3 is greater flexibility regarding
reusing the code in other places and relicensing it.
update-copyright.sh can be used to add copyright remarks for the current
year. It finds the authors who made a change in each file and adds/updates
their copyright remark. Intel employees are grouped under "Intel Corporation".
This is permitted by the Funambol contributor agreement (copy
is in doc/Sync4jContribution.pdf). It reduces the license mix
and allows distributing synccompare without special precautions.
The logdir is now overridden so that all files (client.log, message
dumps, Synthesis logs) are written in a subdirectory names after
the current test. A <test>.log file captures all output written
outside of the sync itself.
The file is named after the current test, with : replaced by underscores.
This gets all log message outside of sync sessions. Those are still written into
separate files whose name needs to be adapted.
File names now only contain a single underscore instead of
multiple ones. The compare functions can be called so that they
return the result instead of throwing an assertion (useful for
doing multiple comparisons and then checking the result).
The synccompare Perl script is told to print the file names
that it is comparing.