lumiera_documentation/tests/vault/out/output-alloc-state-test.cpp
Ichthyostega 216ab525fd OutputSlot: integration with buffer management (+documentation)
Within the reworked design of the `OutputSlot` a proxy implementation
of the `BufferProvider` API is used (class `OutputBufferProxy`).

After analysis of the invocation patterns, I concluded that it seems adequate
to attach the special-purpose metadata generated by this integration
to the generic system of thread-local replicated `BufferMetadata` storage.

However, since thread-local instances are effectively static(global),
I was concerned that unit-testing might be impeded by accumulation of
stale metadata in the store linked to the main thread. Thus I created
a special configuration variant to retain the previously used setup
for the sake of unit testing (which applies especially to use of the
`DiagnosticOutputSlot`). Using a `SimpleBufferStateRegistry` for in
that case has the benefit that simply a local instance can be used
in the test and all metadata will be discarded afterwards.

Furthermore the factory syntax for obtaining an `OutputSlot` was improved,
drawing on the recent changes to `lib::ScopedCollection`.

Also I looked through some of the documentation and updated
the UML sequence diagram to reflect `OutputSlot`'s improved internal structure
2026-05-31 01:44:54 +02:00

200 lines
6.1 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
OutputAllocState(Test) - verify generation details
Copyright (C)
2026, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
* *****************************************************************/
/** @file output-alloc-state-test.cpp
** unit test \ref OutputAllocState_test
*/
#include "test/run.hpp"
#include "test/event-log.hpp"
#include "test/test-helper.hpp"
#include "vault/mem/buffhandle.hpp"
#include "vault/out/output-slot.hpp"
#include "vault/out/output-slot-connection.hpp"
#include "lib/format-obj.hpp"
#include "lib/util.hpp"
#include <memory>
#include <string>
using std::string;
using test::EventLog;
using vault::mem::Buff;
using vault::out::FrameID;
using util::isSameAdr;
namespace vault::out::test {
namespace { // test fixture...
uint64_t DUMMY_BUFF{0xAaAaAa};
EventLog log("static OutputAllocState_test");
inline std::string
mark (void const* dummyBuff) noexcept
{
return "Mem:" + util::showHashLSB ((size_t)dummyBuff);
}
/**
* Dummy implementation of the OutputSlot::Connection interface.
* Instead of engaging into actual output operations, this mock
* implementation protocols all received calls into an EventLog.
* A dummy memory address and buffer size is returned.
*/
class MockConnection
: public OutputSlot::Connection
{
/* === Connection API === */
size_t
getBufferSize() const override
{
log.call ("MockConnection", "getBufferSize");
return sizeof(DUMMY_BUFF);
}
Buff*
claimBufferFor (FrameID frame) override
{
log.call ("MockConnection", "claimBufferFor", frame);
void* dummy = &DUMMY_BUFF;
return static_cast<Buff*> (dummy);
}
void
publish (Buff* buff) override
{
log.call ("MockConnection", "publish", mark(buff));
}
void
release (Buff* buff) override
{
log.call ("MockConnection", "release", mark(buff));
}
void
shutDown() override
{
log.call ("MockConnection", "shutDown");
}
public:
MockConnection() { log.call ("MockConnection", "create"); }
~MockConnection() { log.call ("MockConnection", "destroy"); }
};
struct FakeSlot
: OutputSlot
{
static constexpr uint NUM_CONNECTIONS = 1;
static constexpr bool SINGLE_THREADED_TEST = true;
using Connections = lib::ScopedCollection<MockConnection>;
using MockConnectState = OutputSlot::AllocState<MockConnection, SINGLE_THREADED_TEST>;
FakeSlot()
: OutputSlot{std::make_unique<MockConnectState> (NUM_CONNECTIONS, Connections::fill())}
{ }
};
}//(End) test fixture
/***********************************************************************//**
* @test demonstrate how the internal implementation hub within OutputSlot
* is connected to some OutputSlot::Connection implementation and
* exposes a BuffHandle as front-end.
* - use an embedded EventLog to verify sequence of events
* - use a rigged mock connection that logs invocations
* - perform all operations for a typical output usage
* @see OutputSlotProtocol_test
* @see EventLog_test
*/
class OutputAllocState_test : public Test
{
virtual void
run (Arg)
{
log.clear ("Start OutputAllocState_test");
const FrameCnt FRA_NO = 55;
{
log.event("create FakeSlot");
FakeSlot slot;
log.event("retrieve DataSink");
auto sinks = slot.getOpenedSinks();
auto sink = *sinks;
++sinks;
CHECK (not sinks);
log.event("lock buffer");
BuffHandle han = sink(FRA_NO);
CHECK (han);
CHECK (han.size() == sizeof(DUMMY_BUFF));
CHECK (isSameAdr (han.rawStorage(), &DUMMY_BUFF));
log.event("emit buffer");
han.emit();
CHECK (not han);
log.event("release buffer");
han.release();
log.event("abandon FakeSlot");
}// last instance of this slot goes out of scope...
cout << "____Event-Log_________________\n"
<< util::join(log, "\n")
<< "\n───╼━━━━━━━━━━━╾──────────────"<<endl;
CHECK (log.verify ("Start OutputAllocState_test")
.beforeEvent("create FakeSlot")
.beforeCall ("create") .on("MockConnection")
.beforeEvent("retrieve DataSink")
.beforeCall ("getBufferSize") .on("MockConnection")
.beforeEvent("lock buffer")
.beforeCall ("claimBufferFor").on("MockConnection").arg(FRA_NO)
.beforeEvent("emit buffer")
.beforeCall ("publish") .on("MockConnection").arg(mark(&DUMMY_BUFF))
.beforeEvent("release buffer")
.beforeCall ("release") .on("MockConnection").arg(mark(&DUMMY_BUFF))
.beforeEvent("abandon FakeSlot")
.beforeCall ("shutDown") .on("MockConnection")
.beforeCall ("destroy") .on("MockConnection")
);
}
};
/** Register this test class... */
LAUNCHER (OutputAllocState_test, "unit common");
}// namespace vault::out::test