Debugging, improved logging, etc.

This commit is contained in:
Ulf Wiger
2026-05-30 13:15:17 +02:00
parent 2ea1966973
commit d7b052a076
14 changed files with 521 additions and 65 deletions
+58 -1
View File
@@ -16,13 +16,16 @@ for the duration of such a sequence, and this tends to lead to hacking
a plain process with a custom protocol.
This application attempts to make that a bit more structured.
In its initial version, there are two APIs:
In its initial version, there are a few different APIs:
* `gm_ctflow_fun`, where one can instantiate a stateful handler fun,
which can be called by test cases as needed.
* `gm_ctflow_worker`, a gen_server where the server logic is given
by a user-provided fun. The server is spawned under a
`simple_one_for_one` supervisor.
* `gm_ctflow_reg`, used to register and find `gm_ctflow_worker` processes.
Complies with the `via` addressing scheme for OTP behaviors.
* `gm_ctflow`, providing a shared dictionary, logging and status support.
The application `gm_ctflow` is intended to be started in
`init_per_suite/1` and stopped in `end_per_suite/1`, or in
@@ -70,6 +73,60 @@ end_per_group(_Grp, _Config) ->
This resets the state and removes all helper processes for each group.
A simple way to keep track of the flow state:
```erlang
init_per_testcase(_Case, Config) ->
gm_ctflow:status(),
Config.
end_per_testcase(_Case, _Config) ->
gm_ctflow:status(),
ok.
```
This gives output like this, from the `gm_ctflow_SUITE:incr/1` testcase:
```
*** User 2026-05-30 13:06:02.679 ***🔗
== Summary for flow my_counter
= Worker State: - none -
= Fun State: 0
= State: - none -
= Log History:
2026-05-30 13:06:02.654:
New flow: my_counter
*** User 2026-05-30 13:06:02.679 ***🔗
my_counter[<0.332.0>]: F(incr, 0) -> {ok,1,1}
*** User 2026-05-30 13:06:02.679 ***🔗
== Summary for flow my_counter
= Worker State: - none -
= Fun State: 1
= State: - none -
= Log History:
2026-05-30 13:06:02.654:
New flow: my_counter
2026-05-30 13:06:02.679:
F(incr, 0) -> {ok,1,1}
```
Normally, of course, there would be more going on in the test, making the
bookends a bit less dominant, but here we see the initial state of the flow
`my_counter`: The "Fun state" is `0`, while there's no worker, and no shared state.
The log history shows one previous message, from instantiating the fun.
The next log output shows the effect of calling the fun. Log messages produced
with `gm_ctflow:ct_log/[2,3]` go both to `ct:log/2` and the log history. The
flow is derived automatically, if possible, if not provided.
In the ending `status` output, we see the accumulated history, with timestamps
to make it easier to find the context in CT or SUT logs.
Build
-----