Commit graph

181 commits

Author SHA1 Message Date
7ed8486774 Library: rework detection of ''same object''
We use the memory address to detect reference to ''the same language object.''
While primarily a testing tool, this predicate is also used in the
core application at places, especially to prevent self-assignment
and to handle custom allocations.

It turns out that actually we need two flavours for convenient usage
 - `isSameObject` uses strict comparison of address and accepts only references
 - `isSameAdr` can also accept pointers and even void*, but will dereference pointers
This leads to some further improvements of helper utilities related to memory addresses...
2024-11-15 00:11:14 +01:00
0b9e184fa3 Library: replace usages of rand() in the whole code base
* most usages are drop-in replacements
 * occasionally the other convenience functions can be used
 * verify call-paths from core code to identify usages
 * ensure reseeding for all tests involving some kind of randomness...

__Note__: some tests were not yet converted,
since their usage of randomness is actually not thread-safe.
This problem existed previously, since also `rand()` is not thread safe,
albeit in most cases it is possible to ignore this problem, as
''garbled internal state'' is also somehow „random“
2024-11-13 04:23:46 +01:00
064484450e Library: adapt some existing usages to the convenience API 2024-11-12 22:35:54 +01:00
ce2116fccd Library: option to provide an explicit random seed for tests
* add new option to the commandline option parser
 * pass this as std::optional to the test-suite constructor
 * use this value optionally to inject a fixed value on re-seeding
 * provide diagnostic output to show the actual seed value used
2024-11-12 15:49:15 +01:00
cffa2cd6c2 Library: implement test access to hidden global RandomSequencer
this seems to be the ''classical problem situation''
where a »clean« Dependency-Injection would require to waste storage
for a pointer to the same global resource in each and every distinct test class.

Since the Test-Suite is effectively global — even more so now due to
the reliance on "the" global `RandomSequencer` (PNRG) — we'll have to
bite the bullet and access a global static variable hidden behind teh scenes.
2024-11-10 16:22:46 +01:00
c13d6d45f4 Library: add new API for random seeding
...to the base-class of all tests
 * `seedRand()` shall be invoked by every test using randomisation
   * it will draw a new seed for the implicit default-PRNG
   * it will document this seed value
   * but when a seed was given via cmdline, it will inject that instead
 * `makeRandGen()` will create a new dedicated generator instance,
   attached (by seeding) to the current default-PRNG

It is not clear yet how to pass the actual `SeedNucleus`, which
for obvious reasons must be maintained by the `test::Suite`
2024-11-10 04:40:39 +01:00
31c24e0017 Library: investigate discrepancy in allocator
part of the observed deviation stems form bugs in logging and checksum calculation;
but there seems to be a real problem hidden in the allocator usage of the
new component, since the use-cnt of the handle does not drop to zero
2024-06-18 17:20:23 +02:00
055df59dde Library: tracking diagnostic allocator now complete and tested 2024-06-17 01:55:49 +02:00
10edc31eac Library: build adaptor for automated unique-ownership
This adaptor works in concert with the generic allocator
building blocks (prospective ''Concepts'') and automatically
registers a either static or dynamic back-link to the factory
for clean-up.

Use this wrapper fore more in-depth test of the new `TrackingAllocator`
and verify proper behaviour through the `EventLog`
2024-06-16 19:31:16 +02:00
be3cf61111 Library: verify fundamental properties of TrackingAllocator
* implement some further statistic and diagnostic helpers
 * explicitly create and discard a base allocation for test
2024-06-16 15:44:43 +02:00
32bea9521b Library: get the simple testcase to work
- create two vectors, attached to the `TrackingAllocator`
- emplace Tracker-Objects
- move an object to the other vector
- destroy the containers

🠲 Event-Log looks plausible!
2024-06-16 04:23:06 +02:00
a3fb6f46ed Library: implement the MemoryPool for TrackingAllocator
- use a meta-registry of pools
- retrieve and manage the `MemoryPool` instances by shared_ptr, with a weak registry entry
- use a hastable for the allocations, keyed by the allocated memory address
2024-06-16 04:22:29 +02:00
ad90b7d687 Library: define requirements for tracking test-allocator
- ability to verify a hash-checksum
- ability to watch number of allocations and allotted bytes
- using either a common global pool or a separate dedicated pool
- log all operations into a common `EventLog` instance
- front-end adaptors for use as C++ custom allocator
2024-06-16 04:22:29 +02:00
e82dd86b39 Library: reorganise test helpers and cover logging tracker object
...these features are now used quite regularly,
and so a dedicated documentation test seems indicated.

Actually my intention is to add a tracking allocator to these test helpers
(and then to use that to verify the custom allocator usage of `lib::Several`)
2024-06-16 04:22:29 +02:00
d327094603 Library: draft a scheme to configure lib::Several with a custom allocator
Phew... this was a tough one — and not sure yet if this even remotely works...

Anyway, the `lib::SeveralBuilder` is already prepared for collaboration with a
custom allocator, since it delegates all memory handling through a base policy,
which in turn relies on std::allocator_traits.

The challenge however is to find a way...
 * to make this clear and easy to use
 * to expose an extension point for specific tweaks
 * and to make all this work without excessive header cross dependencies
2024-06-16 04:22:28 +02:00
d9f86ad891 Library: investigate case with known element type
- the test-dummy objects need a `noexcept` move ctor
- **bug** here: need an explicit check to prevent other types
  than the known element type from ''sneaking in''
2024-06-16 04:22:28 +02:00
1a76fb46f3 Library: elaborate SeveralBuilder operations
Consider what (not) to support.
Notably I decided ''not to support'' moving out of an iterator,
since doing so would contradict the fundamental assumptions of
the »Lumiera Forward Iterator« Concept.

Start verifying some variations of element placement,
still focussing on the simple cases
2024-06-16 04:22:28 +02:00
597d8191c7 Library: code the DataSource template
...turns out challenging, since our intention here
is borderline to the intended design of the Lumiera ETD.
It ''should work'' though, when combined with a Variant-visitor...
2024-03-27 04:07:55 +01:00
59390cd2f8 Library: reorder some pervasively used includes
reduce footprint of lib/util.hpp
 (Note: it is not possible to forward-declare std::string here)

define the shorthand "cStr()" in lib/symbol.hpp

reorder relevant includes to ensure std::hash is "hijacked" first
2024-03-21 19:57:34 +01:00
1f5518e2c8 Library: introduce functions for floating-point comparisons
- rough numeric comparisons (optionally given precision)
- epsilon comparison based on numeric_limits
2024-03-16 03:03:29 +01:00
a6aad5261c Library: complete and verify temp-dir helper
verify also that clean-up happens in case of exceptions thrown;
as an aside, add Macro to check for ''any'' exception and match
on something in the message (as opposed to just a Lumiera Exception)
2024-03-13 02:50:13 +01:00
18b1d37a3d Library: also create unique temporary files
...using the same method for sake of uniformity

Also move the permissions helpers to the file.hpp support functions
and setup a separate unit test for these
2024-03-12 22:54:05 +01:00
a1832b1cb9 Library: base implementation of temp-dir creation
Inspired by https://stackoverflow.com/a/58454949

Verified behaviour of fs::create_directory
 --> it returns true only if it ''indeed could create'' a new directory
 --> it returns false if the directory exists already
 --> it throws when some other obstacle shows up

As an aside: the Header include/limits.h could be cleaned up,
and it is used solely from C++ code, thus could be typed, namespaced etc.
2024-03-12 20:14:29 +01:00
6e8c07ccd6 Library: draft tests to document the new features
Yesterday I decided to include some facilities I have written in 2022
for the Yoshimi-Testsuite. The intention is to use these as-is, and just
to adapt them stylistically to the Lumiera code base.

However — at least some basic documentation in the form of
very basic unit-tests can be considered »acceptance criteria«
2024-03-11 17:44:19 +01:00
580c1f1f68 Scheduler-test: complete instrumentation helper
Verify proper operation under pressure
using a multithreaded stress test
2024-02-15 00:52:59 +01:00
67036f45b0 Scheduler-test: Integration-test now running smoothly
The last round of refactorings yielded significant improvements
 - parallelisation now works as expected
 - processing progresses closer to the schedule
 - run time was reduced

The processing load for this test is tuned in a way to overload the
scheduler massively at the end -- the result must be correct non the less.

There was one notable glitch with an assertion failure from the memory manager.
Hopefully I can reproduce this by pressing and overloading the Scheduler more...
2023-12-18 23:34:10 +01:00
df4ee5e9c1 Scheduler-test: implement pure computation load
..initial gauging is a tricky subject,
since existing computer's performance spans a wide scale

Allowing
 - pre calibration -98% .. +190%
 - single run ±20%
 - benchmark ±5%
2023-12-11 03:10:42 +01:00
beebf51ac7 Scheduler-test: draft a configurable CPU load component
...which can be deliberately attached (or not attached) to the
individual node invocation functor, allowing to study the effect
of actual load vs. zero-load and worker contention
2023-12-10 19:58:18 +01:00
7eca3ffe42 Scheduler-test: a helper for one-time operations
Invent a special JobFunctor...
 - can be created / bound from a λ
 - self-manages its storage on the heap
 - can be invoked once, then discards itself

Intention is to pass such one-time actions to the Scheduler
to cause some ad-hoc transitions tied to curren circumstances;
a notable example will be the callback after load-test completion.
2023-12-08 03:16:57 +01:00
aafd277ebe Chain-Load: rework the pattern for dynamic rules
...as it turns out, the solution embraced first was the cleanest way
to handle dynamic configuration of parameters; just it did not work
at that time, due to the reference binding problem in the Lambdas.
Meanwhile, the latter has been resolved by relying on the LazyInit
mechanism. Thus it is now possible to abandon the manipulation by
side effect and rather require the dynamic rule to return a
''pristine instance''.

With these adjustments, it is now possible to install a rule
which expands only for some kinds of nodes; this is used here
to crate a starting point for a **reduction rule** to kick in.
2023-11-30 02:13:39 +01:00
3d5fdce1c7 Chain-Load: demonstrate use of the expansion rule
...played a lot with the parameters
...behaviour and DOT graphs look plausible
...document three typical examples with statistics
2023-11-29 02:58:55 +01:00
7a22e7f987 Test: helper for transitory manipulations
Use a simple destructor-trick to set up a concise notation
for temporarily manipulating a value for testing.
The manipulation will automatically be undone
when leaving scope
2023-11-08 19:27:08 +01:00
6a7a2832bf Scheduler: simplify usage of microbenchmark helper
as an aside, the header lib/test/microbenchmark.hpp
turns out to be prolific for this kind of investigation.

However, it is somewhat obnoxious that the »test subject«
must expose the signature <size_t(size_t)>.

Thus, with some metaprogramming magic, an generic adaptor
can be built to accept a range of typical alternatives,
and even the quite obvious signature void(void).
Since all these will be wrapped directly into a lambda,
the optimiser will remove these adaptations altogether.
2023-10-30 20:17:16 +01:00
b5e9d67a79 Scheduler: wrap-up and comment test cases thus far
...up to now, Behaviour is as expected
- with some minor discrepancies still to be fixed
- and an effect due to the test-scaffolding
2023-10-27 03:37:24 +02:00
097001d16f Scheduler: investigate timings of dispatch()
...there seemed to be an anomaly of 50...100µs

==> conclusion: this is due to the instrumentation code
    - it largely caused by the EventLog, which was never meant
      to be used in performance-critical code, and does hefty
      heap allocations and string processing.
    - moreover, there clearly is a cache-effect, adding a Factor 2
      whenever some time passed since the last EventLog call

==> can be considered just an artifact of the test setup and
    will have no impact on the scheduler


remark: this commit adds a lot of instrumentation code
2023-10-27 02:53:34 +02:00
a71bcaae43 Scheduler: shorthand notation for work-Function test
To cover the visible behaviour of the work-Function,
we have to check an amalgam of timing delays and time differences.

This kind of test tends to be problematic, since timings are always
random and also machine dependent, and thus we need to produce pronounced effects
2023-10-26 01:14:13 +02:00
c37871ca78 Library/Application: switch Locking from POSIX to C++14
While not directly related to the thread handling framework,
it seems indicated to clean-up this part of the application alongside.

For »everyday« locking concerns, an Object Monitor abstraction was built
several years ago and together with the thread-wrapper, both at that time
based on direct usage of POSIX. This changeset does a mere literal
replacement of the POSIX calls with the corresponding C++ wrappers
on the lowest level. The resulting code is needlessly indirect, yet
at API-level this change is totally a drop-in replacment.
2023-10-13 23:46:38 +02:00
7b25609896 Library: test coverage for self-managed thread
...extract and improve the tuple-rewriting function
...improve instance tracking test dummy objects
...complete test coverage and verify proper memory handling
2023-10-11 21:06:56 +02:00
08c3e76f14 Library: identified design challenges
On a close look, the wrapper design as pursued here
turns out to be prone to insidious data race problems.
This was true also for the existing solution, but becomes
more clear due to the precise definitions from the C++ standard.

This is a confusing situation, because these races typically do not
materialise in practice; due to the latency of the OS scheduler the
new thread starts invoking user code at least 100µs after the Wrapper
object is fully constructed (typically more like 500µs, which is a lot)

The standard case (lib::Thread) in its current form is correct, but borderline
to undefined behaviour, and any initialisation of members in a derived class
would be off limits (the thread-wrapper should not be used as baseclass,
rather as member)
2023-10-07 03:25:39 +02:00
ff052ec5a2 Library/Application: switch Microbenchmark + SyncBarrier tests
...these were already written envisionaging he new API,
so it's more or less a drop-in replacement.

- cant use vector anymore, since thread objects are move-only
- use ScopedCollection instead, which also has the benefit of
  allocating the requires space up-front. Allow to deduce the
  type parameter of the placed elements
2023-10-03 22:56:09 +02:00
201672a0ad Library: reconsider join / stringify API
- it is not directly possible to provide a variadic join(args...),
  due to overload resolution ambiguities

- as a remedy, simplify the invocation of stringify() for the typical cases,
  and provide some frequently used shortcuts
2023-09-29 17:00:13 +02:00
59bb99f653 Library: fix shortcoming with exception-expectations
VERIFY_ERROR allows to check that an expected except is actually thrown.

The implementation was lazy however;
it just investigated the C-style error flag instead of *really* verifying
that an *lumiera::Exception* with the expected flag was caught.

This discrepancy can be a problem when there is a stray error flag set,
or for some reason the error flag gets cleared before the exception
reaches the top-level catch-block in the test.
2023-09-27 01:09:40 +02:00
c183045dfa Library: switch Microbenchmark setup to C++17 threads
Over time, a collection of microbenchmark helper functions was
extracted from occasional use -- including a variant to perform
parallelised microbenchmarks. While not used beyond sporadic experiments yet,
this framework seems a perfect fit for measuring the SyncBarrier performance.

There is only one catch:
 - it uses the old Threadpool + POSIX thread support
 - these require the Threadpool service to be started...
 - which in turn prohibits using them for libary tests

And last but not least: this setup already requires a barrier.

==> switch the existing microbenchmark setup to c++17 threads preliminarily
    (until the thread-wrapper has been reworked).
==> also introduce the new SyncBarrier here immediately
==> use this as a validation test of the setup + SyncBarrier
2023-09-24 18:07:28 +02:00
1c6ee62c1a Activity-Lang: allow to verify invocation param in test
requires to supplement EventLog matching primitives
to pick and verify a specific positional argument.

Moreover, it is more or less arbitrary which job invocation parameters
are unpacked and exposed for verification; we'll have to see what is
actually required for writing tests...
2023-08-15 20:03:01 +02:00
161f604cbd Activity-Lang: setup a mocked JobFunctor for diagnostics
...now step by step building up the scaffolding
to build and verify Activity terms...
2023-08-15 18:52:51 +02:00
e3f1aa4f7c Activity-Lang: support negative assertions for tests
Testcase (detect function invocation) passes now as expected


Some Library / Framework changes

- rename event-log-test.cpp
- allow the ExpectString also to work with concatenated expectation strings


Remark: there was a warning in the comment in event-log.hpp,
pointing out that negative assertions are shallow.

However, after the rework in 9/2018 (commit: d923138d1)
...this should no longer be true, since we perform proper backtracking,
leading to an exhaustive search.
2023-08-14 19:25:56 +02:00
25ad461a28 Activity-Lang: switch invocation detection to delegated matcher
ActivityMatch inherits privately from the EventMatch object,
and is thus able to delegate relevant matching queries, but
also to provide high-level special matchers.

This new design resolves the ambiguity regarding function arguments.
Moreover, we can now record the current sequence-Number as *attribute*
in the respective log record (this is the benefit of using structured
log entries instead of just a textual log), thereby avoiding the various
pitfalls with explicit bracketing sequence-number log entries

bottom line: this reworked design seems to be a better fit,
even while technically the implementation with the wrapped matcher
is somewhat ugly...
2023-08-14 02:05:13 +02:00
ff4acb04d7 Activity-Lang: investigate ways to verify invocation sequences
The EventLog seems to provide all the building blocks, but we need
some higher level special matchers (and maybe we also want to hide
some of the basic EventLog matchers). A soulution might be to wrap
the EventMatcher and delegate all follow-up builder calls.

This seems adequate, since the EventLog-Matcher is basically used as black box,
building up more elaborate matchers from the provided basic matchers...


Spent some time again to understand how EventLog matching works.

My feelings towards this piece of code are always the same: it is
somewhat too "tricky", but I am not aware of any other technique
to get this degree of elaborate chained matching on structured records,
short of building a dedicated matching engine from scratch.

The other alternative would be to use a flat textual log (instead of
the structured log records from EventLog), but then we'd have to
generate quite intricate regular expressions from the builder,
and I'm really doubtful it would be easier and clearer....
2023-08-13 20:49:30 +02:00
db1adb63a7 Activity-Lang: draft a diagnostic helper
...for coverage of the Activity-Language,
various invocations of unspecific functions must be verified,
with the additional twist that the implementation avoids indirections
and is thus hard to rig for tests.

Solution-Idea: provide a λ-mock to log any invocation into the
Event-Log helper, which was created some years ago to trace GUI communication...
2023-07-31 21:53:16 +02:00
28b3900284 Block-Flow: final adjustments from performance test (closes: #1311)
Further extensive testing with parameter variations,
using the test setup in `BlockFlow_test::storageFlow()`

- Tweaks to improve convergence under extreme overload;
  sudden load peaks are now accomodated typically < 5 sec

- Make the test definition parametric, to simplify variations

- Extract the generic microbenchmark helper function

- Documentation
2023-07-22 06:07:35 +02:00