Tests, examples and sandbox#
Organization#
tests/
main.cc GoogleTest entry point
elements/ everything a program using the library would provide: socket types, validators,
callbacks, node types, data bank and operators. Only for the tests and examples.
contexts/ functions building ready-to-use situations (no GoogleTest dependency)
fundamentals/ identifiers, qualifiers, SmallMap, Registry, DataBank
structures/ sockets (enumerations, validators), nodes, node definitions, links and callbacks
graph/ Graph: nodes, sockets, links, interface, topology, CmpGraph
serialization/ primitives, components, graph round trips, corrupted buffers
graph_manager/ graphs in memory, heads, save/load, proxy nodes
graph_runtime/ build, run, proxies at runtime
examples/ one program per .cc, built on elements and contexts
sandbox/ quick trials, one program per .cc, not versioned
All the unit tests are compiled into build/tests/tests-nodes-graph. The examples are also registered in
CTest, so ctest checks that they still run without error. The commands are in the README.
Test elements (tests/elements)#
Node type |
Purpose |
|---|---|
|
Constant source. Its input is not linkable. |
|
|
|
|
|
Text output, to test incompatible types (Text vs Number). |
|
Accepts any type and has every callback attached: they write into |
|
Registered without operator: the runtime must throw. |
|
Its operator always fails: |
Socket types: TYPE_NUMBER, TYPE_BOOLEAN, TYPE_TEXT (validators registered; Text refuses the
empty string) and TYPE_UNCHECKED (no validator). Data bank: ng_test::DataBank =
ng::DataBank<Number, Boolean, Text>. Every operator appends its name to
ng_test::operators::get_execution_log() to check the execution order.
These elements are compiled as a CMake OBJECT library, otherwise their static registrations would be
dropped by the linker (see Registries and self-registration).
Contexts (tests/contexts)#
make_arithmetic_graph(x, y):product = (x + y) * y, results “sum” and “product”.make_diamond_graph(): depths 0, 1, 1, 2.make_chain_graph(n): n Add nodes in a row, node i at depth i.make_feature_rich_graph(): every feature that must survive serialization.ScopedLibrary: resets theGraphManagerand gives it a head in a new temporary folder, both cleaned on destruction. Use it in every test touching the disk or proxies.save_doubler_graph(gm)/save_quadrupler_graph(gm): saved graphs for the proxy tests (x * 2andx * 4through two nested doublers).
The context functions throw if a step fails, so a broken context is visible immediately instead of producing confusing test failures.
Writing a test#
Pick the folder of the right level of abstraction and create (or extend) a
test_*.ccfile: it is picked up at the next build.Prefer building the situation with a context function or test elements rather than registering new things in the global registries from the test (they are shared by all the tests).
Tests touching the
GraphManagermust use aScopedLibrary; tests reading the callbacks or execution logs must clear them first.Tests must not depend on their order:
--gtest_shuffle --gtest_repeat=20must pass.
To check that tests really detect a bug, re-introduce the bug temporarily and check that they fail.
Sanitizers#
The deserialization deals with untrusted bytes: after changing it, run the tests with AddressSanitizer and
UndefinedBehaviorSanitizer (command in the README). The CorruptedBuffers tests are designed to be run
this way.