Testing a program's interface

Nothing in the core needs a window, a GPU or a thread, so a program's interface is tested by building its screen in a context and reading what layout and drawing give: rectangles (muiNode_GetRect), states, the focus, the draw list's commands, and the accessibility tree. The context counts its work (muiContext_GetWorkCounts), so a test can hold a frame to what it should cost:

// A test a program can run with no window and no GPU: its screen laid
// out and drawn twice with nothing changed, the second frame doing no
// work at all.
static bool StillFrameIsFree(muiContext* context, muiNodeId root)
{
    const muiLayoutInput layout = {800.0f, 600.0f, NULL, NULL, 0, NULL, {0, 0, 0, 0}};
    const muiDrawInput draw = {1, 1.0f, NULL, NULL};
    if (muiNode_ComputeLayout(context, root, &layout) != mui_success ||
        muiNode_BuildDrawList(context, root, &draw) != mui_success)
    {
        return false;
    }
    muiWorkCounts before = muiContext_GetWorkCounts(context);
    if (muiNode_ComputeLayout(context, root, &layout) != mui_success ||
        muiNode_BuildDrawList(context, root, &draw) != mui_success)
    {
        return false;
    }
    muiWorkCounts after = muiContext_GetWorkCounts(context);
    return after.styleCount == before.styleCount && after.sizeCount == before.sizeCount &&
           after.measureCount == before.measureCount && after.paintCount == before.paintCount;
}

Some ways to test with it:

A test that compares draw lists or rectangles should compare what the program promises, not every value: a small change in the library's rounding or a new command kind should not break a program's tests unless it changes what the user sees.