adapt to use Relation_next
[rrq/rrqmisc.git] / tests / relationtests.c
1 /**
2  * This is a collection of tests of the Relation functions.
3  */
4 #include <stdlib.h>
5 #include <stringitem.h>
6 #include <Relation.h>
7
8 #define SIZE(x) (sizeof(x)/sizeof(void*))
9
10 static char *tuple2string(Relation *r,Tuple *t) {
11     #define LIMIT 10000
12     static char tmp[10][ LIMIT ];
13     static int i = 0;
14     if ( t == 0 ) {
15         return "(null)";
16     }
17     if ( i >= 10 ) {
18         i = 0;
19     }
20     int n = r->content.type->tostring(  r->content.type, t, tmp[i], LIMIT );
21     if ( n == 0 ) {
22         *(tmp[i]) = 0;
23     }
24     return tmp[i++];
25 }
26
27 static void query_report(Relation *r,Tuple *query) {
28     VectorIndex i;
29     for ( i = 0; i < r->content.table.size; i++ ) {
30         Tuple *t = Relation_next( r, &i, query );
31         fprintf( stderr, "check %s\n", tuple2string( r, t ) );
32     }
33 }
34
35 static void query_report_all(Relation *r,Tuple *query[]) {
36     int j;
37     for ( j = 0; query[j]; j++ ) {
38         fprintf( stderr, "query %s\n", tuple2string( r, query[j] ) );
39         query_report( r, query[j] );
40     }
41 }
42
43 // Report any knocked out tuples from Relation_add or Relation_delete
44 // This will also clear and free the result Vector.
45 static void knockout_report(Relation *r,Vector *v) {
46     VectorIndex i;
47     if ( v ) {
48         for ( i = 0; i < v->size; i++ ) {
49             Tuple **t = (Tuple **) Vector_next_used( v, &i );
50             fprintf( stderr, "knock %s\n", tuple2string( r, t? *t : 0 ) );
51         }
52         Vector_resize( v, 0, Vector_clear_any, 0 );
53         free( v );
54     }
55 }
56
57 // Test addition with several tuples, terminated by 0                          
58 static void test_Relation_add(Relation *r,Tuple *query[]) {
59     int j;
60     for ( j = 0; query[j]; j++ ) {
61         fprintf( stderr, "add %s\n", tuple2string( r, query[j] ) );
62         knockout_report( r, Relation_add( r, query[j] ) );
63     }
64 }
65
66 // Test deletion with several queries, terminated by 0
67 static void test_Relation_delete(Relation *r,Tuple *query[]) {
68     int j;
69     for ( j = 0; query[j]; j++ ) {
70         fprintf( stderr, "delete %s\n", tuple2string( r, query[j] ) );
71         knockout_report( r, Relation_delete( r, query[j] ) );
72     }
73 }
74
75 int main(int argc,char **argv) {
76
77     // AxB
78     Tuple *data2[] = {
79         TUPLE( "a", "b" ),
80         TUPLE( "a", "c" ),
81         TUPLE( "a", "d" ),
82         TUPLE( "b", "d" ),
83         0
84     };
85     Tuple *query2[] = {
86         TUPLE( "a", 0 ),
87         TUPLE( 0, "d" ),
88         0
89     };
90     Relation rel2 = RELATION( &stringitem, &stringitem );
91
92     test_Relation_add( &rel2, data2 );
93     query_report( &rel2, 0 );
94     query_report_all( &rel2, query2 );
95     test_Relation_delete( &rel2, query2 );
96     
97     // AxBxC
98     Tuple *data3[] = {
99         TUPLE( "a", "b", "c" ), // <a,b,?> <a,?,c> ***
100         TUPLE( "a", "c", "d" ), // <a,c,?> <a,?,d> ***
101         TUPLE( "a", "b", "e" ), // <a,b,?> <a,?,e> => -<a,b,c>
102         TUPLE( "b", "d", "d" ), // <b,d,?> <b,?,d>
103         TUPLE( "a", "d", "d" ), // <a,d,?> <a,?,d> => -<a,c,d>
104         TUPLE( "e", "c", "a" ), // <e,c,?> <e,?,a>
105         TUPLE( "f", "b", "d" ), // <f,b,?> <f,?,c>
106         0
107     };
108     Tuple *query3[] = {
109         TUPLE( "a", 0, "d" ),
110         TUPLE( 0, 0, "d" ),
111         TUPLE( 0, "c", 0 ),
112         TUPLE( "f", "b", "d" ),
113         0
114     };
115     Relation rel3 = RELATION( &stringitem, &stringitem, &stringitem );
116     Relation_add_constraint( &rel3, 1, 1, 0 ); // AxB -> C
117     Relation_add_constraint( &rel3, 1, 0, 1 ); // AxC -> B
118
119     test_Relation_add( &rel3, data3 );
120     query_report( &rel3, 0 );
121     query_report_all( &rel3, query3 );
122     test_Relation_delete( &rel3, query3 );
123
124     return 0;
125 }