mirror of https://gitee.com/openkylin/openmpi.git
1113 lines
37 KiB
C
1113 lines
37 KiB
C
/*
|
|
* Copyright (c) 2014 Cisco Systems, Inc. All rights reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
|
|
#include "opal_config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
|
|
#include "opal/constants.h"
|
|
#include "opal/class/opal_list.h"
|
|
#include "opal/class/opal_pointer_array.h"
|
|
#include "opal/util/bipartite_graph.h"
|
|
#include "opal/util/bipartite_graph_internal.h"
|
|
|
|
# define test_out(...) fprintf(stderr, __VA_ARGS__)
|
|
# define check(a) \
|
|
do { \
|
|
if (!(a)) { \
|
|
test_out("%s:%d: check failed, '%s'\n", __func__, __LINE__, #a); \
|
|
return 1; \
|
|
} \
|
|
} while (0)
|
|
# define check_str_eq(a,b) \
|
|
do { \
|
|
const char *a_ = (a); \
|
|
const char *b_ = (b); \
|
|
if (0 != strcmp(a_,b_)) { \
|
|
test_out("%s:%d: check failed, \"%s\" != \"%s\"\n", \
|
|
__func__, __LINE__, a_, b_); \
|
|
return 1; \
|
|
} \
|
|
} while (0)
|
|
# define check_int_eq(got, expected) \
|
|
do { \
|
|
if ((got) != (expected)) { \
|
|
test_out("%s:%d: check failed, \"%s\" != \"%s\", got %d\n", \
|
|
__func__, __LINE__, #got, #expected, (got)); \
|
|
return 1; \
|
|
} \
|
|
} while (0)
|
|
/* just use check_int_eq for now, no public error code to string routine
|
|
* exists (opal_err2str is static) */
|
|
# define check_err_code(got, expected) \
|
|
check_int_eq(got, expected)
|
|
# define check_msg(a, msg) \
|
|
do { \
|
|
if (!(a)) { \
|
|
test_out("%s:%d: check failed, \"%s\" (%s)\n", \
|
|
__func__, __LINE__, #a, (msg)); \
|
|
return 1; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define check_graph_is_consistent(g) \
|
|
do { \
|
|
check(opal_bp_graph_order(g) <= opal_pointer_array_get_size(&g->vertices)); \
|
|
check(g->source_idx >= -1 || g->source_idx < opal_bp_graph_order(g)); \
|
|
check(g->sink_idx >= -1 || g->sink_idx < opal_bp_graph_order(g)); \
|
|
} while (0)
|
|
|
|
#define check_has_in_out_degree(g, u, expected_indegree, expected_outdegree) \
|
|
do { \
|
|
check_int_eq(opal_bp_graph_indegree(g, (u)), expected_indegree); \
|
|
check_int_eq(opal_bp_graph_outdegree(g, (u)), expected_outdegree); \
|
|
} while (0)
|
|
|
|
/* Check the given path for sanity and that it does not have a cycle. Uses
|
|
* the "racing pointers" approach for cycle checking. */
|
|
#define check_path_cycle(n, source, sink, pred) \
|
|
do { \
|
|
int i_, j_; \
|
|
check_int_eq(pred[source], -1); \
|
|
for (i_ = 0; i_ < n; ++i_) { \
|
|
check(pred[i_] >= -1); \
|
|
check(pred[i_] < n); \
|
|
} \
|
|
i_ = (sink); \
|
|
j_ = pred[(sink)]; \
|
|
while (i_ != -1 && j_ != -1) { \
|
|
check_msg(i_ != j_, "CYCLE DETECTED"); \
|
|
i_ = pred[i_]; \
|
|
j_ = pred[j_]; \
|
|
if (j_ != -1) { \
|
|
j_ = pred[j_]; \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
static int v_cleanup_count = 0;
|
|
static int e_cleanup_count = 0;
|
|
|
|
static void v_cleanup(void *v_data)
|
|
{
|
|
++v_cleanup_count;
|
|
}
|
|
|
|
static void e_cleanup(void *e_data)
|
|
{
|
|
++e_cleanup_count;
|
|
}
|
|
|
|
/* a utility function for comparing integer pairs, useful for sorting the edge
|
|
* list returned by opal_bp_graph_solve_bipartite_assignment */
|
|
static int cmp_int_pair(const void *a, const void *b)
|
|
{
|
|
int *ia = (int *)a;
|
|
int *ib = (int *)b;
|
|
|
|
if (ia[0] < ib[0]) {
|
|
return -1;
|
|
}
|
|
else if (ia[0] > ib[0]) {
|
|
return 1;
|
|
}
|
|
else { /* ia[0] == ib[0] */
|
|
if (ia[1] < ib[1]) {
|
|
return -1;
|
|
}
|
|
else if (ia[1] > ib[1]) {
|
|
return 1;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Simple time function so that we don't have to deal with the
|
|
complexity of finding mpi.h to use MPI_Wtime */
|
|
static double gettime(void)
|
|
{
|
|
double wtime;
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
wtime = tv.tv_sec;
|
|
wtime += (double)tv.tv_usec / 1000000.0;
|
|
|
|
return wtime;
|
|
}
|
|
|
|
static int test_graph_create(void *ctx)
|
|
{
|
|
opal_bp_graph_t *g;
|
|
int i;
|
|
int err;
|
|
int user_data;
|
|
int index;
|
|
|
|
/* TEST CASE: check zero-vertex case */
|
|
g = NULL;
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
check(opal_bp_graph_order(g) == 0);
|
|
check_graph_is_consistent(g);
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
/* TEST CASE: check nonzero-vertex case with no cleanup routines */
|
|
g = NULL;
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
check_graph_is_consistent(g);
|
|
for (i = 0; i < 4; ++i) {
|
|
index = -1;
|
|
err = opal_bp_graph_add_vertex(g, &user_data, &index);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(index == i);
|
|
}
|
|
check(opal_bp_graph_order(g) == 4);
|
|
check_graph_is_consistent(g);
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
/* TEST CASE: make sure cleanup routines are invoked properly */
|
|
g = NULL;
|
|
v_cleanup_count = 0;
|
|
e_cleanup_count = 0;
|
|
err = opal_bp_graph_create(&v_cleanup, &e_cleanup, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
check_graph_is_consistent(g);
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, &user_data, &index);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(index == i);
|
|
}
|
|
check(opal_bp_graph_order(g) == 5);
|
|
check_graph_is_consistent(g);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/1,
|
|
/*capacity=*/2, &user_data);
|
|
check_graph_is_consistent(g);
|
|
check(v_cleanup_count == 0);
|
|
check(e_cleanup_count == 0);
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(v_cleanup_count == 5);
|
|
check(e_cleanup_count == 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_graph_clone(void *ctx)
|
|
{
|
|
opal_bp_graph_t *g, *gx;
|
|
int i;
|
|
int err;
|
|
int user_data;
|
|
int index;
|
|
|
|
/* TEST CASE: make sure that simple cloning works fine */
|
|
g = NULL;
|
|
v_cleanup_count = 0;
|
|
e_cleanup_count = 0;
|
|
err = opal_bp_graph_create(&v_cleanup, &e_cleanup, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
check_graph_is_consistent(g);
|
|
|
|
/* add 5 edges */
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, &user_data, &index);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
check(opal_bp_graph_order(g) == 5);
|
|
check_graph_is_consistent(g);
|
|
|
|
/* and two edges */
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/1,
|
|
/*capacity=*/2, &user_data);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_graph_is_consistent(g);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/3, /*v=*/1, /*cost=*/2,
|
|
/*capacity=*/100, &user_data);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_graph_is_consistent(g);
|
|
|
|
/* now clone it and ensure that we get the same kind of graph */
|
|
gx = NULL;
|
|
err = opal_bp_graph_clone(g, /*copy_user_data=*/false, &gx);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(gx != NULL);
|
|
|
|
/* double check that cleanups still happen as expected after cloning */
|
|
err = opal_bp_graph_free(gx);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(v_cleanup_count == 0);
|
|
check(e_cleanup_count == 0);
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(v_cleanup_count == 5);
|
|
check(e_cleanup_count == 2);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_graph_accessors(void *ctx)
|
|
{
|
|
opal_bp_graph_t *g;
|
|
int i;
|
|
int err;
|
|
|
|
/* TEST CASE: check _indegree/_outdegree/_order work correctly */
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
check(opal_bp_graph_indegree(g, i) == 0);
|
|
check(opal_bp_graph_outdegree(g, i) == 0);
|
|
}
|
|
|
|
check(opal_bp_graph_order(g) == 4);
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/2,
|
|
/*capacity=*/1, NULL);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/1, /*cost=*/2,
|
|
/*capacity=*/1, NULL);
|
|
|
|
check(opal_bp_graph_indegree(g, 0) == 0);
|
|
check(opal_bp_graph_outdegree(g, 0) == 2);
|
|
check(opal_bp_graph_indegree(g, 1) == 1);
|
|
check(opal_bp_graph_outdegree(g, 1) == 0);
|
|
check(opal_bp_graph_indegree(g, 2) == 1);
|
|
check(opal_bp_graph_outdegree(g, 2) == 0);
|
|
check(opal_bp_graph_indegree(g, 3) == 0);
|
|
check(opal_bp_graph_outdegree(g, 3) == 0);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_graph_assignment_solver(void *ctx)
|
|
{
|
|
opal_bp_graph_t *g;
|
|
int i;
|
|
int err;
|
|
int nme;
|
|
int *me;
|
|
int iter;
|
|
double start, end;
|
|
|
|
/* TEST CASE: check that simple cases are solved correctly
|
|
*
|
|
* 0 --> 2
|
|
* 1 --> 3
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/10,
|
|
/*capacity=*/1, NULL);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/3, /*cost=*/2,
|
|
/*capacity=*/1, NULL);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 2);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
check(me[0] == 0 && me[1] == 2);
|
|
check(me[2] == 1 && me[3] == 3);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
|
|
/* TEST CASE: left side has more vertices than the right side
|
|
*
|
|
* 0 --> 3
|
|
* 1 --> 4
|
|
* 2 --> 4
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/4, /*cost=*/2,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/4, /*cost=*/1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 2);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
check(me[0] == 0 && me[1] == 3);
|
|
check(me[2] == 2 && me[3] == 4);
|
|
free(me);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
|
|
/* test Christian's case:
|
|
* 0 --> 2
|
|
* 0 --> 3
|
|
* 1 --> 3
|
|
*
|
|
* make sure that 0-->2 & 1-->3 get chosen.
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/3, /*cost=*/5,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 2);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
check(me[0] == 0 && me[1] == 2);
|
|
check(me[2] == 1 && me[3] == 3);
|
|
free(me);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
/* Also need to do this version of it to be safe:
|
|
* 0 --> 2
|
|
* 1 --> 2
|
|
* 1 --> 3
|
|
*
|
|
* Should choose 0-->2 & 1-->3 here too.
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/2, /*cost=*/1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/3, /*cost=*/5,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 2);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
check(me[0] == 0 && me[1] == 2);
|
|
check(me[2] == 1 && me[3] == 3);
|
|
free(me);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
/* TEST CASE: test Christian's case with negative weights:
|
|
* 0 --> 2
|
|
* 0 --> 3
|
|
* 1 --> 3
|
|
*
|
|
* make sure that 0-->2 & 1-->3 get chosen.
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/-1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/-10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/3, /*cost=*/-5,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 2);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
check(me[0] == 0 && me[1] == 2);
|
|
check(me[2] == 1 && me[3] == 3);
|
|
free(me);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
|
|
/* TEST CASE: add some disconnected vertices
|
|
* 0 --> 2
|
|
* 0 --> 3
|
|
* 1 --> 3
|
|
* x --> 4
|
|
*
|
|
* make sure that 0-->2 & 1-->3 get chosen.
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/-1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/-10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/3, /*cost=*/-5,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 2);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
check(me[0] == 0 && me[1] == 2);
|
|
check(me[2] == 1 && me[3] == 3);
|
|
free(me);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
/* TEST CASE: sample UDP graph from bldsb005 + bldsb007
|
|
* 0 --> 2 (cost -4294967296)
|
|
* 1 --> 2 (cost -4294967296)
|
|
* 0 --> 3 (cost -4294967296)
|
|
* 1 --> 3 (cost -4294967296)
|
|
*
|
|
* Make sure that either (0-->2 && 1-->3) or (0-->3 && 1-->2) get chosen.
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 4; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/-4294967296,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/2, /*cost=*/-4294967296,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/-4294967296,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/3, /*cost=*/-4294967296,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 2);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
if (me[1] == 2) {
|
|
check(me[0] == 0 && me[1] == 2);
|
|
check(me[2] == 1 && me[3] == 3);
|
|
} else {
|
|
check(me[0] == 0 && me[1] == 3);
|
|
check(me[2] == 1 && me[3] == 2);
|
|
}
|
|
free(me);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
|
|
/* TEST CASE: check that simple cases are solved correctly
|
|
*
|
|
* 0 --> 2
|
|
* 1 --> 2
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 3; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/-100,
|
|
/*capacity=*/1, NULL);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/2, /*cost=*/-100,
|
|
/*capacity=*/1, NULL);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 1);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
check((me[0] == 0 || me[0] == 1) && me[1] == 2);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
|
|
/* TEST CASE: performance sanity check
|
|
*
|
|
* Construct this graph and ensure that it doesn't take too long on a large
|
|
* cluster (1000 nodes).
|
|
* 0 --> 3
|
|
* 1 --> 4
|
|
* 2 --> 4
|
|
*/
|
|
#define NUM_ITER (10000)
|
|
start = gettime();
|
|
for (iter = 0; iter < NUM_ITER; ++iter) {
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/4, /*cost=*/2,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/4, /*cost=*/1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
me = NULL;
|
|
err = opal_bp_graph_solve_bipartite_assignment(g,
|
|
&nme,
|
|
&me);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check_int_eq(nme, 2);
|
|
check(me != NULL);
|
|
qsort(me, nme, 2*sizeof(int), &cmp_int_pair);
|
|
check(me[0] == 0 && me[1] == 3);
|
|
check(me[2] == 2 && me[3] == 4);
|
|
free(me);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
end = gettime();
|
|
/* ensure that this operation on a 1000 node cluster will take less than one second */
|
|
check(((end - start) / NUM_ITER) < 0.001);
|
|
#if 0
|
|
fprintf(stderr, "timing for %d iterations is %f seconds (%f s/iter)\n",
|
|
NUM_ITER, end - start, (end - start) / NUM_ITER);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_graph_bellman_ford(void *ctx)
|
|
{
|
|
opal_bp_graph_t *g;
|
|
int i;
|
|
int err;
|
|
bool path_found;
|
|
int *pred;
|
|
|
|
/* TEST CASE: check that simple cases are solved correctly
|
|
* -> 0 --> 2
|
|
* / \
|
|
* 4 --> 5
|
|
* \ /
|
|
* -> 1 --> 3 /
|
|
*
|
|
* should yield the path 5,1,3,6 (see costs in code below)
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 6; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/2, /*cost=*/10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/3, /*cost=*/2,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/4, /*v=*/0, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/4, /*v=*/1, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/5, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/3, /*v=*/5, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
pred = malloc(6*sizeof(*pred));
|
|
check(pred != NULL);
|
|
path_found = opal_bp_graph_bellman_ford(g, /*source=*/4, /*target=*/5, pred);
|
|
check(path_found);
|
|
check_path_cycle(6, /*source=*/4, /*target=*/5, pred);
|
|
check_int_eq(pred[5], 3);
|
|
check_int_eq(pred[3], 1);
|
|
check_int_eq(pred[1], 4);
|
|
free(pred);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
|
|
/* TEST CASE: left side has more vertices than the right side, then
|
|
* convert to a flow network
|
|
*
|
|
* 0 --> 3
|
|
* 1 --> 4
|
|
* 2 --> 4
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/4, /*cost=*/2,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/4, /*cost=*/1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
err = opal_bp_graph_bipartite_to_flow(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
pred = malloc(7*sizeof(*pred));
|
|
check(pred != NULL);
|
|
path_found = opal_bp_graph_bellman_ford(g, /*source=*/5, /*target=*/6, pred);
|
|
check(path_found);
|
|
check_int_eq(g->source_idx, 5);
|
|
check_int_eq(g->sink_idx, 6);
|
|
check_path_cycle(7, /*source=*/5, /*target=*/6, pred);
|
|
check_int_eq(pred[6], 4);
|
|
check_int_eq(pred[4], 2);
|
|
check_int_eq(pred[2], 5);
|
|
free(pred);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
/* TEST CASE: same as previous, but with very large cost values (try to
|
|
* catch incorrect integer conversions)
|
|
*
|
|
* 0 --> 3
|
|
* 1 --> 4
|
|
* 2 --> 4
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/INT32_MAX+10LL,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/4, /*cost=*/INT32_MAX+2LL,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/4, /*cost=*/INT32_MAX+1LL,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
err = opal_bp_graph_bipartite_to_flow(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
pred = malloc(7*sizeof(*pred));
|
|
check(pred != NULL);
|
|
path_found = opal_bp_graph_bellman_ford(g, /*source=*/5, /*target=*/6, pred);
|
|
check(path_found);
|
|
check_int_eq(g->source_idx, 5);
|
|
check_int_eq(g->sink_idx, 6);
|
|
check_path_cycle(7, /*source=*/5, /*target=*/6, pred);
|
|
check_int_eq(pred[6], 4);
|
|
check_int_eq(pred[4], 2);
|
|
check_int_eq(pred[2], 5);
|
|
free(pred);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
/* TEST CASE: left side has more vertices than the right side, then
|
|
* convert to a flow network. Negative costs are used, but should not
|
|
* result in a negative cycle.
|
|
*
|
|
* 0 --> 3
|
|
* 1 --> 4
|
|
* 2 --> 4
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/-1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/4, /*cost=*/-2,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/4, /*cost=*/-10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
err = opal_bp_graph_bipartite_to_flow(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
pred = malloc(7*sizeof(*pred));
|
|
check(pred != NULL);
|
|
path_found = opal_bp_graph_bellman_ford(g, /*source=*/5, /*target=*/6, pred);
|
|
check(path_found);
|
|
check_int_eq(g->source_idx, 5);
|
|
check_int_eq(g->sink_idx, 6);
|
|
check_path_cycle(7, /*source=*/5, /*target=*/6, pred);
|
|
check_int_eq(pred[6], 4);
|
|
check_int_eq(pred[4], 2);
|
|
check_int_eq(pred[2], 5);
|
|
free(pred);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_graph_flow_conversion(void *ctx)
|
|
{
|
|
opal_bp_graph_t *g;
|
|
int i;
|
|
int err;
|
|
|
|
/* TEST CASE: left side has more vertices than the right side, then
|
|
* convert to a flow network
|
|
*
|
|
* 0 --> 3
|
|
* 1 --> 4
|
|
* 2 --> 4
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
for (i = 0; i < 5; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
err = opal_bp_graph_add_edge(g, /*u=*/0, /*v=*/3, /*cost=*/10,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/1, /*v=*/4, /*cost=*/2,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/4, /*cost=*/1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
check_int_eq(opal_bp_graph_order(g), 5);
|
|
check_has_in_out_degree(g, 0, /*exp_indeg=*/0, /*exp_outdeg=*/1);
|
|
check_has_in_out_degree(g, 1, /*exp_indeg=*/0, /*exp_outdeg=*/1);
|
|
check_has_in_out_degree(g, 2, /*exp_indeg=*/0, /*exp_outdeg=*/1);
|
|
check_has_in_out_degree(g, 3, /*exp_indeg=*/1, /*exp_outdeg=*/0);
|
|
check_has_in_out_degree(g, 4, /*exp_indeg=*/2, /*exp_outdeg=*/0);
|
|
|
|
/* this should add two nodes and a bunch of edges */
|
|
err = opal_bp_graph_bipartite_to_flow(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
check_int_eq(opal_bp_graph_order(g), 7);
|
|
check_has_in_out_degree(g, 0, /*exp_indeg=*/2, /*exp_outdeg=*/2);
|
|
check_has_in_out_degree(g, 1, /*exp_indeg=*/2, /*exp_outdeg=*/2);
|
|
check_has_in_out_degree(g, 2, /*exp_indeg=*/2, /*exp_outdeg=*/2);
|
|
check_has_in_out_degree(g, 3, /*exp_indeg=*/2, /*exp_outdeg=*/2);
|
|
check_has_in_out_degree(g, 4, /*exp_indeg=*/3, /*exp_outdeg=*/3);
|
|
check_has_in_out_degree(g, 5, /*exp_indeg=*/3, /*exp_outdeg=*/3);
|
|
check_has_in_out_degree(g, 6, /*exp_indeg=*/2, /*exp_outdeg=*/2);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
|
|
/* TEST CASE: empty graph
|
|
*
|
|
* there's no reason that the code should bother to support this, it's not
|
|
* useful
|
|
*/
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
check_int_eq(opal_bp_graph_order(g), 0);
|
|
err = opal_bp_graph_bipartite_to_flow(g);
|
|
check_err_code(err, OPAL_ERR_BAD_PARAM);
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_graph_param_checking(void *ctx)
|
|
{
|
|
opal_bp_graph_t *g;
|
|
int i;
|
|
int err;
|
|
|
|
err = opal_bp_graph_create(NULL, NULL, &g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
check(g != NULL);
|
|
|
|
/* try with no vertices */
|
|
err = opal_bp_graph_add_edge(g, /*u=*/3, /*v=*/5, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_ERR_BAD_PARAM);
|
|
|
|
for (i = 0; i < 6; ++i) {
|
|
err = opal_bp_graph_add_vertex(g, NULL, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
}
|
|
|
|
/* try u out of range */
|
|
err = opal_bp_graph_add_edge(g, /*u=*/9, /*v=*/5, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_ERR_BAD_PARAM);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/6, /*v=*/5, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_ERR_BAD_PARAM);
|
|
|
|
/* try v out of range */
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/8, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_ERR_BAD_PARAM);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/6, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_ERR_BAD_PARAM);
|
|
|
|
/* try adding an edge that already exists */
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/4, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/4, /*cost=*/0,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_EXISTS);
|
|
|
|
/* try an edge with an out of range cost */
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/3, /*cost=*/INT64_MAX,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_ERR_BAD_PARAM);
|
|
err = opal_bp_graph_add_edge(g, /*u=*/2, /*v=*/3, /*cost=*/INT64_MAX-1,
|
|
/*capacity=*/1, NULL);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
err = opal_bp_graph_free(g);
|
|
check_err_code(err, OPAL_SUCCESS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int test_graph_helper_macros(void *ctx)
|
|
{
|
|
int u, v;
|
|
int pred[6];
|
|
bool visited[6][6];
|
|
int pair1[2];
|
|
int pair2[2];
|
|
|
|
#define RESET_ARRAYS(n, pred, visited) \
|
|
do { \
|
|
for (u = 0; u < 6; ++u) { \
|
|
pred[u] = -1; \
|
|
for (v = 0; v < 6; ++v) { \
|
|
visited[u][v] = false; \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
/* TEST CASE: make sure that an empty path does not cause any edges to be
|
|
* visited */
|
|
RESET_ARRAYS(6, pred, visited);
|
|
FOREACH_UV_ON_PATH(pred, 3, 5, u, v) {
|
|
visited[u][v] = true;
|
|
}
|
|
for (u = 0; u < 6; ++u) {
|
|
for (v = 0; v < 6; ++v) {
|
|
check(visited[u][v] == false);
|
|
}
|
|
}
|
|
|
|
/* TEST CASE: make sure that every edge in the given path gets visited */
|
|
RESET_ARRAYS(6, pred, visited);
|
|
pred[5] = 2;
|
|
pred[2] = 1;
|
|
pred[1] = 3;
|
|
FOREACH_UV_ON_PATH(pred, 3, 5, u, v) {
|
|
visited[u][v] = true;
|
|
}
|
|
for (u = 0; u < 6; ++u) {
|
|
for (v = 0; v < 6; ++v) {
|
|
if ((u == 2 && v == 5) ||
|
|
(u == 1 && v == 2) ||
|
|
(u == 3 && v == 1)) {
|
|
check(visited[u][v] == true);
|
|
}
|
|
else {
|
|
check(visited[u][v] == false);
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef RESET_ARRAYS
|
|
|
|
/* not technically a macro, but make sure that the pair comparison function
|
|
* isn't broken (because it was in an earlier revision...) */
|
|
pair1[0] = 0; pair1[1] = 1;
|
|
pair2[0] = 0; pair2[1] = 1;
|
|
check(cmp_int_pair(&pair1[0], &pair2[0]) == 0);
|
|
|
|
pair1[0] = 1; pair1[1] = 1;
|
|
pair2[0] = 0; pair2[1] = 1;
|
|
check(cmp_int_pair(pair1, pair2) > 0);
|
|
|
|
pair1[0] = 0; pair1[1] = 1;
|
|
pair2[0] = 1; pair2[1] = 1;
|
|
check(cmp_int_pair(pair1, pair2) < 0);
|
|
|
|
pair1[0] = 1; pair1[1] = 0;
|
|
pair2[0] = 1; pair2[1] = 1;
|
|
check(cmp_int_pair(pair1, pair2) < 0);
|
|
|
|
pair1[0] = 1; pair1[1] = 1;
|
|
pair2[0] = 1; pair2[1] = 0;
|
|
check(cmp_int_pair(pair1, pair2) > 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
check(test_graph_create(NULL) == 0);
|
|
check(test_graph_clone(NULL) == 0);
|
|
check(test_graph_accessors(NULL) == 0);
|
|
check(test_graph_assignment_solver(NULL) == 0);
|
|
check(test_graph_bellman_ford(NULL) == 0);
|
|
check(test_graph_flow_conversion(NULL) == 0);
|
|
check(test_graph_param_checking(NULL) == 0);
|
|
check(test_graph_helper_macros(NULL) == 0);
|
|
|
|
return 0;
|
|
}
|