Skip to content

ValidateGraph

Description

Validate whether a given Graph object is valid. Aborts if provided graph is uninitialized or corrupted.

Parameters

Name Direction Description
g in Pointer to Graph object to validate.

Success

Continue execution, meaning given graph is most probably valid.

Failure

abort

Usage example (Cross-references)

Usage examples (Cross-references)
    /// TAGS: Graph, Memory, Reserve
    ///
    #define GraphReserve(g, n) (ValidateGraph(g), reserve_graph(GENERIC_GRAPH(g), sizeof(GRAPH_NODE_TYPE(g)), (n)))
    
    ///
    #define GraphForeachNode(g, node)                                                                                      \
        for (TYPE_OF(g) UNPL(pg) = (g); UNPL(pg); UNPL(pg) = NULL)                                                         \
            if ((ValidateGraph(UNPL(pg)), 1) && GraphNodeCount(UNPL(pg)) > 0)                                              \
                for (GenericGraphNodeIter UNPL(iter) = graph_node_iter_begin(GENERIC_GRAPH(UNPL(pg))); UNPL(iter).graph;  \
                     UNPL(iter).graph = NULL)                                                                              \
    ///
    #define GraphAddNodeL(g, lval)                                                                                         \
        (ValidateGraph(g),                                                                                                 \
         CHECK_TYPE_EQUIVALENCE(TYPE_OF(lval), GRAPH_NODE_TYPE(g)),                                                        \
         graph_push_node_owned(GENERIC_GRAPH(g), &(lval), sizeof(GRAPH_NODE_TYPE(g))))
    ///
    #define GraphAddNodeR(g, rval)                                                                                         \
        (ValidateGraph(g),                                                                                                 \
         CHECK_TYPE_CONVERTIBLE(GRAPH_NODE_TYPE(g), rval),                                                                 \
         graph_push_node(GENERIC_GRAPH(g), &LVAL_AS(GRAPH_NODE_TYPE(g), rval), sizeof(GRAPH_NODE_TYPE(g))))
    /// TAGS: Graph, AddEdge, Directed
    ///
    #define GraphAddEdge(g, from, to) (ValidateGraph(g), graph_add_edge(GENERIC_GRAPH(g), (from), (to)))
    
    ///
        }
    
        ValidateGraph(graph);
        graph_validate_node_id(graph, node._id_);
        return node;
    
    void deinit_graph(GenericGraph *graph, size item_size) {
        ValidateGraph(graph);
    
        clear_graph(graph, item_size);
        u64 slot_index;
    
        ValidateGraph(graph);
    
        for (slot_index = 0; slot_index < VecLen(&graph->slots); slot_index++) {
        (void)item_size;
    
        ValidateGraph(graph);
        old_capacity = VecCapacity(&graph->slots);
        }
    
        ValidateGraph(graph);
    
        if (VecLen(&graph->free_indices)) {
        }
    
        ValidateGraph(graph);
    
        index      = GraphNodeIdIndex(node_id);
        GraphNode node;
    
        ValidateGraph(graph);
        graph_validate_node_id(graph, node_id);
        GraphNeighbors *neighbors;
    
        ValidateGraph(graph);
        graph_validate_node_id(graph, from);
        neighbors = graph_out_neighbors_ptr(graph, from);
        GraphNeighbors *neighbors;
    
        ValidateGraph(graph);
        graph_validate_node_id(graph, to);
        neighbors = graph_in_neighbors_ptr(graph, to);
        GraphNeighbors *neighbors;
    
        ValidateGraph(graph);
        graph_validate_node_id(graph, from);
        graph_validate_node_id(graph, to);
        GraphNeighbors *in_neighbors;
    
        ValidateGraph(graph);
        graph_validate_node_id(graph, from);
        graph_validate_node_id(graph, to);
        GraphPendingEdgeRemoval pending;
    
        ValidateGraph(graph);
        graph_validate_node_id(graph, from);
        graph_validate_node_id(graph, to);
    
    bool graph_edge_marked_for_removal(GenericGraph *graph, GraphNodeId from, GraphNodeId to) {
        ValidateGraph(graph);
        graph_validate_node_id(graph, from);
        graph_validate_node_id(graph, to);
        size idx;
    
        ValidateGraph(graph);
        graph_validate_node_id(graph, from);
        graph_validate_node_id(graph, to);
        u64 explicit_edge_removal_count;
    
        ValidateGraph(graph);
    
        if (!graph->pending_delete_count && !VecLen(&graph->pending_edge_removals)) {
        GenericGraphNodeIter iter;
    
        ValidateGraph(graph);
    
        iter.graph                   = graph;
        }
    
        ValidateGraph(iter->graph);
        if (iter->expected_mutation_epoch != iter->graph->mutation_epoch) {
            LOG_FATAL("graph structure changed during node iteration");
        }
    
        ValidateGraph(iter->graph);
        if (iter->expected_mutation_epoch != iter->graph->mutation_epoch) {
            LOG_FATAL("graph structure changed during neighbor iteration");
        }
    
        ValidateGraph(iter->graph);
        if (iter->expected_mutation_epoch != iter->graph->mutation_epoch) {
            LOG_FATAL("graph structure changed during predecessor iteration");
        // Clear the memoized validated bit on a consistent graph so commit's entry
        // ValidateGraph skips the deep accounting scan.
        ValidateGraph(&graph);
    
        // Hide the last slot (c, occupied + unmarked) at index == new length.
    
        // Clear the memoized validated bit on a consistent graph.
        ValidateGraph(&graph);
    
        // Hide c (occupied + marked) at index == new length.
    
        GraphReserve(&graph, 8);
        ValidateGraph(&graph);
    
        bool        result            = VecCapacity(&graph.slots) >= 8;
        bool result = GraphAddEdge(&graph, a, c);
    
        ValidateGraph(&graph);
    
        result = result && GraphContainsNode(&graph, a) && GraphContainsNode(&graph, c);
        IntGraph graph = GraphInit(&alloc);
    
        ValidateGraph(&graph);
    
        // intentional bypass: the inner `slots` / `free_indices` /
    // validating this valid graph does NOT abort. NORMAL test.
    static bool test_graph_validate_passes_with_marked_node(void) {
        WriteFmt("Testing deep ValidateGraph accepts a valid graph that has a marked node\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        (void)d;
    
        ValidateGraph(&graph);
    
        bool result = (graph.pending_delete_count == 1);
    // > 1), re-arm the deep validator, and assert ValidateGraph aborts. DEADEND.
    static bool test_graph_non_pow2_alignment_rejected_deadend(void) {
        WriteFmt("Testing ValidateGraph rejects a non-power-of-two allocator alignment (should abort)\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        GraphAllocator(&graph)->alignment  = 3;
    
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    // real code while removing the mask for the mutant). DEADEND.
    static bool test_graph_validate_catches_corrupt_slots_vec_deadend(void) {
        WriteFmt("Testing ValidateGraph catches a corrupted slots vector (should abort)\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        GENERIC_GRAPH(&graph)->slots.__magic  = 0;
    
        ValidateGraph(&graph);
    
        return false;
    // does not mask the removed in-validator check (see slots-vec test). DEADEND.
    static bool test_graph_validate_catches_corrupt_free_indices_vec_deadend(void) {
        WriteFmt("Testing ValidateGraph catches a corrupted free_indices vector (should abort)\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        GENERIC_GRAPH(&graph)->free_indices.__magic  = 0;
    
        ValidateGraph(&graph);
    
        return false;
    // check (see slots-vec test). DEADEND.
    static bool test_graph_validate_catches_corrupt_pending_edges_vec_deadend(void) {
        WriteFmt("Testing ValidateGraph catches a corrupted pending_edge_removals vector (should abort)\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        GENERIC_GRAPH(&graph)->pending_edge_removals.__magic  = 0;
    
        ValidateGraph(&graph);
    
        return false;
    
        MAGIC_MARK_DIRTY(GENERIC_GRAPH(&graph));
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    
        MAGIC_MARK_DIRTY(GENERIC_GRAPH(&graph));
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    
        MAGIC_MARK_DIRTY(GENERIC_GRAPH(&graph));
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    
        MAGIC_MARK_DIRTY(GENERIC_GRAPH(&graph));
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    
        MAGIC_MARK_DIRTY(g);
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    
        MAGIC_MARK_DIRTY(g);
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    
        MAGIC_MARK_DIRTY(g);
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    
        MAGIC_MARK_DIRTY(g);
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    
        MAGIC_MARK_DIRTY(g);
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
    // is not an out-neighbor and force re-validation; real code aborts.
    static bool test_graph_validate_rejects_missing_pending_edge_deadend(void) {
        WriteFmt("Testing ValidateGraph rejects pending removal of a missing edge (should abort)\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
        MAGIC_MARK_DIRTY(GENERIC_GRAPH(&graph));
    
        ValidateGraph(&graph);
    
        GraphDeinit(&graph);
        // memoized validated bit; subsequent ValidateGraph calls skip the deep
        // accounting scan that would otherwise reject the length tweak below.
        ValidateGraph(&graph);
    
        // intentional bypass: no public setter shrinks the slot array. Hiding the
        GraphAddEdge(&graph, c, a);
    
        ValidateGraph(&graph);
    
        node_b                            = GraphGetNode(&graph, b);
Last updated on