da43859b97
Layout, Build und Konventionen analog zu mydb und cxx_scaffold_cli: Header und Quellen nebeneinander in playground/, Unit-Tests als .test.c/.test.cpp daneben, Integrationstests in tests/. Geruest-Module counter (C, Unity) und notebook (C++, doctest) zeigen jede Regel einmal an lauffaehigem Code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
90 lines
2.8 KiB
C++
90 lines
2.8 KiB
C++
/* tests/basics/driver.cpp
|
|
* Integrationstest (P1204R0 Regel 7.2).
|
|
*
|
|
* Unterschied zu den .test-Dateien neben den Modulen: dieser Test kennt NUR
|
|
* die oeffentliche API. Kein unity.h, kein doctest.h, kein Zugriff auf
|
|
* details/, keine Kenntnis vom Layout. Er wuerde genauso gegen eine
|
|
* installierte Bibliothek laufen -- und testet damit das, was ein Benutzer
|
|
* tatsaechlich bekommt.
|
|
*
|
|
* Deshalb auch kein Test-Framework: ein Integrationstest soll ein
|
|
* eigenstaendiges Programm sein, das ohne Argumente laeuft und ueber seinen
|
|
* Exit-Code Auskunft gibt.
|
|
*/
|
|
#include <cstdio>
|
|
#include <string>
|
|
|
|
#include <playground/counter.h>
|
|
#include <playground/notebook.hpp>
|
|
|
|
#define CHECK(cond) \
|
|
do \
|
|
{ \
|
|
if (!(cond)) \
|
|
{ \
|
|
std::fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); \
|
|
return 1; \
|
|
} \
|
|
} while (0)
|
|
|
|
namespace
|
|
{
|
|
|
|
/* Beide Module zusammen: der C-Zaehler treibt, das C++-Notizbuch protokolliert.
|
|
* Genau diese Kombination ist das, was main.cpp einem Benutzer vormacht. */
|
|
int
|
|
counter_drives_notebook_until_saturation()
|
|
{
|
|
Counter* counter = counter_create(3U);
|
|
CHECK(counter != nullptr);
|
|
|
|
playground::Notebook notebook;
|
|
|
|
for (int step = 0; step < 5; ++step)
|
|
{
|
|
notebook.append("tick", std::to_string(counter_tick(counter)));
|
|
}
|
|
|
|
/* Fuenf Ticks, aber Limit 3: der Zaehler steht, das Protokoll nicht. */
|
|
CHECK(notebook.size() == 5U);
|
|
CHECK(counter_value(counter) == 3U);
|
|
CHECK(counter_saturated(counter));
|
|
|
|
const auto last = notebook.latest("tick");
|
|
CHECK(last.has_value());
|
|
CHECK(*last == "3");
|
|
|
|
counter_free(counter);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
reset_makes_the_counter_usable_again()
|
|
{
|
|
Counter* counter = counter_create(2U);
|
|
CHECK(counter != nullptr);
|
|
|
|
counter_tick(counter);
|
|
counter_tick(counter);
|
|
CHECK(counter_saturated(counter));
|
|
|
|
counter_reset(counter);
|
|
CHECK(!counter_saturated(counter));
|
|
CHECK(counter_tick(counter) == 1U);
|
|
|
|
counter_free(counter);
|
|
return 0;
|
|
}
|
|
|
|
} /* namespace */
|
|
|
|
int
|
|
main()
|
|
{
|
|
if (counter_drives_notebook_until_saturation() != 0) return 1;
|
|
if (reset_makes_the_counter_usable_again() != 0) return 1;
|
|
|
|
std::puts("integration/basics: ok");
|
|
return 0;
|
|
}
|