Execute every documented example as a test
Some checks failed
akbasic CI Build / cmake_build (push) Successful in 3m2s
akbasic CI Build / sanitizers (push) Successful in 3m52s
akbasic CI Build / coverage (push) Failing after 3m24s
akbasic CI Build / akgl_build (push) Failing after 20s
akbasic CI Build / mutation_test (push) Has been cancelled
Some checks failed
akbasic CI Build / cmake_build (push) Successful in 3m2s
akbasic CI Build / sanitizers (push) Successful in 3m52s
akbasic CI Build / coverage (push) Failing after 3m24s
akbasic CI Build / akgl_build (push) Failing after 20s
akbasic CI Build / mutation_test (push) Has been cancelled
docs/ and README.md carry 85 fenced blocks. Every one was checked by hand exactly once, when it was written, which is not a standard that survives a changing interpreter -- and four were already wrong: two transcripts showing a leading space PRINT does not emit, akbasic_TextSink in README.md missing the two members it had grown hours earlier, and FILTER's refusal quoted with wording the code does not use. tests/docs_examples.sh reads a fence-tag vocabulary and runs what it finds. BASIC programs and transcripts run and are byte-compared against an `output` block; C snippets compile with -fsyntax-only against the real include path, which CMake writes out because it is transitive through akerror, akstdlib and akgl; shell blocks run in a sandbox. Anything that would reconfigure the build tree, hit the network or re-enter the suite is tagged norun with the reason in MAINTENANCE.md, and the two cmake blocks stay hand-maintained by decision. An untagged block is a failure rather than a default, and the pass line reports what it executed by kind. Both exist because the way a harness like this dies is by quietly matching nothing and passing -- which it duly did on the first CTest run, where a generator expression evaluating to nothing still contributed an empty argument that the script read as a filename. The count is what caught it. The excerpt check earns its own mention: a block tagged `c excerpt=include/akbasic/sink.h` must still appear in that header, comments and whitespace ignored. Compiling it would only redefine the type, so a compile check could not have found the stale struct, and did not. Registered as the CTest case docs_examples in both configurations. Fixing the four wrong examples turned up two interpreter defects, fixed in the previous commit and recorded in TODO.md section 8. MAINTENANCE.md is new: the fence-tag reference, what to do when the case fails, and the conventions that until now only existed inside source comments -- the three test lists and how two of them invert "passed", the sorted verb table, that a golden file is never edited to suit this interpreter, and that a fix gets mutation-checked with a file copy rather than git checkout. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2
tests/docs_preludes/akglbody.post
Normal file
2
tests/docs_preludes/akglbody.post
Normal file
@@ -0,0 +1,2 @@
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
21
tests/docs_preludes/akglbody.pre
Normal file
21
tests/docs_preludes/akglbody.pre
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Prelude for the akgl-backend fragment in docs/10-embedding.md. Same shape as
|
||||
* hostbody.pre, plus the renderer and the two backend states those calls take.
|
||||
* Only compiled in the AKBASIC_WITH_AKGL build, which is the only one where
|
||||
* <akbasic/akgl.h> exists to include.
|
||||
*/
|
||||
#include <akerror.h>
|
||||
#include <akbasic/runtime.h>
|
||||
#include <akbasic/akgl.h>
|
||||
|
||||
static akbasic_Runtime RUNTIME;
|
||||
static akbasic_GraphicsBackend graphics;
|
||||
static akbasic_SpriteBackend sprites;
|
||||
static akbasic_AkglGraphics gstate;
|
||||
static akbasic_AkglSprites sstate;
|
||||
static akgl_RenderBackend *my_renderer;
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_docs_fragment(void);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_docs_fragment(void)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
2
tests/docs_preludes/hostbody.post
Normal file
2
tests/docs_preludes/hostbody.post
Normal file
@@ -0,0 +1,2 @@
|
||||
SUCCEED_RETURN(e);
|
||||
}
|
||||
22
tests/docs_preludes/hostbody.pre
Normal file
22
tests/docs_preludes/hostbody.pre
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Prelude for the statement fragments in docs/10-embedding.md: the variable
|
||||
* exchange, the device lending, and the akgl backends.
|
||||
*
|
||||
* Each is shown as the two or three lines that matter, so they need a function
|
||||
* to sit in and the surrounding declarations to refer to. `e` is the error
|
||||
* context the chapter's examples name.
|
||||
*/
|
||||
#include <akerror.h>
|
||||
#include <akbasic/runtime.h>
|
||||
#include <akbasic/sink.h>
|
||||
|
||||
static akbasic_Runtime RUNTIME;
|
||||
static akbasic_GraphicsBackend graphics;
|
||||
static akbasic_AudioBackend audio;
|
||||
static akbasic_InputBackend input;
|
||||
static akbasic_SpriteBackend sprites;
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_docs_fragment(void);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_docs_fragment(void)
|
||||
{
|
||||
PREPARE_ERROR(e);
|
||||
6
tests/docs_preludes/hostcalls.post
Normal file
6
tests/docs_preludes/hostcalls.post
Normal file
@@ -0,0 +1,6 @@
|
||||
} CLEANUP {
|
||||
} PROCESS(errctx) {
|
||||
} FINISH(errctx, true);
|
||||
(void)score;
|
||||
SUCCEED_RETURN(errctx);
|
||||
}
|
||||
27
tests/docs_preludes/hostcalls.pre
Normal file
27
tests/docs_preludes/hostcalls.pre
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Prelude for the "used like this" fragment in README.md.
|
||||
*
|
||||
* The fragment is a run of CATCH calls, which only compile inside an ATTEMPT --
|
||||
* that is the whole point of the macro protocol and the reason the fragment is
|
||||
* shown without its scaffolding. `host_set_string` is the third accessor the
|
||||
* surrounding prose says exists but does not print.
|
||||
*/
|
||||
#include <akerror.h>
|
||||
#include <akbasic/error.h>
|
||||
#include <akbasic/runtime.h>
|
||||
#include <akbasic/variable.h>
|
||||
|
||||
static akbasic_Runtime SCRIPT;
|
||||
static const char *PROGRAM = "10 PRINT \"HI\"\n";
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *host_set_int(akbasic_Runtime *obj, const char *name, int64_t value);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *host_get_int(akbasic_Runtime *obj, const char *name, int64_t *dest);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *host_set_string(akbasic_Runtime *obj, const char *name, const char *value);
|
||||
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_docs_fragment(void);
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akbasic_docs_fragment(void)
|
||||
{
|
||||
PREPARE_ERROR(errctx);
|
||||
int64_t score = 0;
|
||||
|
||||
ATTEMPT {
|
||||
2
tests/docs_preludes/hostloop.post
Normal file
2
tests/docs_preludes/hostloop.post
Normal file
@@ -0,0 +1,2 @@
|
||||
static int64_t your_clock_ms(void) { return 0; }
|
||||
static void your_draw_a_frame(void) { }
|
||||
13
tests/docs_preludes/hostloop.pre
Normal file
13
tests/docs_preludes/hostloop.pre
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Prelude for the "shortest useful host" example in docs/10-embedding.md.
|
||||
*
|
||||
* The example calls two functions it does not define, on purpose: a host's clock
|
||||
* and a host's renderer are the host's business, and spelling them out would
|
||||
* bury the four calls the section is actually about. Declare them here so the
|
||||
* block compiles as written.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <akerror.h>
|
||||
|
||||
static int64_t your_clock_ms(void);
|
||||
static void your_draw_a_frame(void);
|
||||
10
tests/docs_preludes/hostvars.pre
Normal file
10
tests/docs_preludes/hostvars.pre
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Prelude for the two host<->script accessors in README.md.
|
||||
*
|
||||
* The block is shown as two functions and nothing else, because the includes
|
||||
* are already listed two sections above it.
|
||||
*/
|
||||
#include <akerror.h>
|
||||
#include <akbasic/error.h>
|
||||
#include <akbasic/runtime.h>
|
||||
#include <akbasic/variable.h>
|
||||
Reference in New Issue
Block a user