Files
Abdelrahman Said a11edf0c53 Add graph references
2026-06-28 13:49:01 +01:00

169 lines
5.2 KiB
C

/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
/*
* This test tries to ensure that property caching works correctly in the most
* "dangerous" scenarios (going from disconnected to connected graphs and
* back). Feel free to extend the file later on with regression tests for any
* issues that we might find related to caching.
*
* There are no direct APIs to reach into the cache internals (because the
* presence of the cache is an implementation detail). Therefore, we simply do
* the following:
*
* - perform some operation
* - query the value of certain properties that we know that are typically
* cached (e.g., connectedness, presence of multi- and loop edges) etc
* - invalidate the cache
* - perform the query again, check whether the results match
*
* The assumption is that functions like igraph_is_simple(), igraph_has_loops()
* etc work correctly if the cache is empty; correctness of these functions
* without a cache should be tested in other unit tests, not here.
*/
igraph_error_t has_mutual_nonloop_edge(const igraph_t* graph, igraph_bool_t* result) {
return igraph_has_mutual(graph, result, /* loops = */ false);
}
igraph_error_t has_mutual_edge(const igraph_t* graph, igraph_bool_t* result) {
return igraph_has_mutual(graph, result, /* loops = */ true);
}
igraph_error_t is_weakly_connected(const igraph_t* graph, igraph_bool_t* result) {
return igraph_is_connected(graph, result, IGRAPH_WEAK);
}
igraph_error_t is_strongly_connected(const igraph_t* graph, igraph_bool_t* result) {
return igraph_is_connected(graph, result, IGRAPH_STRONG);
}
igraph_error_t is_forest(const igraph_t* graph, igraph_bool_t* result) {
return igraph_is_forest(graph, result, /* roots = */ NULL, IGRAPH_ALL);
}
igraph_error_t is_simple(const igraph_t* graph, igraph_bool_t* result) {
return igraph_is_simple(graph, result, IGRAPH_DIRECTED);
}
igraph_error_t is_simple_ignoring_directions(const igraph_t* graph, igraph_bool_t* result) {
return igraph_is_simple(graph, result, IGRAPH_UNDIRECTED);
}
void validate_properties(const igraph_t* graph) {
igraph_bool_t result, cached_result, recalculated_result;
#define CHECK(func) { \
igraph_invalidate_cache(graph); \
func(graph, &result); \
func(graph, &cached_result); \
igraph_invalidate_cache(graph); \
func(graph, &recalculated_result); \
IGRAPH_ASSERT(result == cached_result); \
IGRAPH_ASSERT(recalculated_result == cached_result); \
}
CHECK(igraph_has_loop);
CHECK(igraph_has_multiple);
CHECK(igraph_is_dag);
CHECK(is_forest);
CHECK(is_simple);
CHECK(is_simple_ignoring_directions);
CHECK(is_weakly_connected);
CHECK(is_strongly_connected);
CHECK(has_mutual_edge);
CHECK(has_mutual_nonloop_edge);
}
void test_basic_operations(igraph_t* graph) {
validate_properties(graph);
igraph_add_vertices(graph, 1, /* attr = */ NULL);
validate_properties(graph);
igraph_add_vertices(graph, 2, /* attr = */ NULL);
validate_properties(graph);
igraph_add_edge(graph, 0, 1);
validate_properties(graph);
igraph_add_edge(graph, 0, 2);
validate_properties(graph);
igraph_add_edge(graph, 1, 2);
validate_properties(graph);
igraph_add_edge(graph, 2, 0);
validate_properties(graph);
igraph_delete_edges(graph, igraph_ess_all(IGRAPH_EDGEORDER_ID));
validate_properties(graph);
igraph_add_edge(graph, 0, 2);
validate_properties(graph);
igraph_delete_vertices(graph, igraph_vss_1(1));
validate_properties(graph);
igraph_delete_vertices(graph, igraph_vss_all());
validate_properties(graph);
}
int test_basic_operations_directed(void) {
igraph_t g;
igraph_empty(&g, 0, IGRAPH_DIRECTED);
test_basic_operations(&g);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
int test_basic_operations_undirected(void) {
igraph_t g;
igraph_empty(&g, 0, IGRAPH_UNDIRECTED);
test_basic_operations(&g);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
int test_multi_loops_adjlist_init(void) {
igraph_t g;
igraph_adjlist_t al;
igraph_bool_t multi;
igraph_small(&g, 1, IGRAPH_UNDIRECTED,
0,0, 0,0, -1);
igraph_adjlist_init(&g, &al, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
igraph_has_multiple(&g, &multi);
IGRAPH_ASSERT(multi);
igraph_adjlist_destroy(&al);
igraph_destroy(&g);
return 0;
}
int main(void) {
RUN_TEST(test_basic_operations_directed);
RUN_TEST(test_basic_operations_undirected);
RUN_TEST(test_multi_loops_adjlist_init);
return 0;
}