/**
- * This is a collection of tests of the relation functions.
+ * This is a collection of tests of the Relation functions.
*/
+#include <stdlib.h>
#include <stringitem.h>
-#include <relation.h>
+#include <Relation.h>
-extern itemkeyfun tupleschema_callbacks;
+#define SIZE(x) (sizeof(x)/sizeof(void*))
+
+static char *tuple2string(Relation *r,Tuple *t) {
+ #define LIMIT 10000
+ static char tmp[10][ LIMIT ];
+ static int i = 0;
+ if ( t == 0 ) {
+ return "(null)";
+ }
+ if ( i >= 10 ) {
+ i = 0;
+ }
+ int n = r->content.type->tostring( r->content.type, t, tmp[i], LIMIT );
+ if ( n == 0 ) {
+ *(tmp[i]) = 0;
+ }
+ return tmp[i++];
+}
+
+static void query_report(Relation *r,Tuple *query) {
+ VectorIndex i;
+ for ( i = 0; i < r->content.table.size; i++ ) {
+ Tuple *t = Relation_next( r, &i, query );
+ fprintf( stderr, "check %s\n", tuple2string( r, t ) );
+ }
+}
+
+static void query_report_all(Relation *r,Tuple *query[]) {
+ int j;
+ for ( j = 0; query[j]; j++ ) {
+ fprintf( stderr, "query %s\n", tuple2string( r, query[j] ) );
+ query_report( r, query[j] );
+ }
+}
+
+// Report any knocked out tuples from Relation_add or Relation_delete
+// This will also clear and free the result Vector.
+static void knockout_report(Relation *r,Vector *v) {
+ VectorIndex i;
+ if ( v ) {
+ for ( i = 0; i < v->size; i++ ) {
+ Tuple **t = (Tuple **) Vector_next_used( v, &i );
+ fprintf( stderr, "knock %s\n", tuple2string( r, t? *t : 0 ) );
+ }
+ Vector_resize( v, 0, Vector_clear_any, 0 );
+ free( v );
+ }
+}
+
+// Test addition with several tuples, terminated by 0
+static void test_Relation_add(Relation *r,Tuple *query[]) {
+ int j;
+ for ( j = 0; query[j]; j++ ) {
+ fprintf( stderr, "add %s\n", tuple2string( r, query[j] ) );
+ knockout_report( r, Relation_add( r, query[j] ) );
+ }
+}
+
+// Test deletion with several queries, terminated by 0
+static void test_Relation_delete(Relation *r,Tuple *query[]) {
+ int j;
+ for ( j = 0; query[j]; j++ ) {
+ fprintf( stderr, "delete %s\n", tuple2string( r, query[j] ) );
+ knockout_report( r, Relation_delete( r, query[j] ) );
+ }
+}
int main(int argc,char **argv) {
- tuple *data[] = {
+
+ // AxB
+ Tuple *data2[] = {
TUPLE( "a", "b" ),
TUPLE( "a", "c" ),
TUPLE( "a", "d" ),
+ TUPLE( "b", "d" ),
+ 0
};
- // AxB
- relation rel2 = RELATION( &stringitem, &stringitem );
-
- relation_add( &rel2, data[0] );
+ Tuple *query2[] = {
+ TUPLE( "a", 0 ),
+ TUPLE( 0, "d" ),
+ 0
+ };
+ Relation rel2 = RELATION( &stringitem, &stringitem );
+ test_Relation_add( &rel2, data2 );
+ query_report( &rel2, 0 );
+ query_report_all( &rel2, query2 );
+ test_Relation_delete( &rel2, query2 );
+
// AxBxC
- relation rel3 = RELATION( &stringitem, &stringitem, &stringitem );
- // AxB -> C
- relation_add_constraint( &rel3, 1, 1, 0 );
- // AxC -> B
- relation_add_constraint( &rel3, 1, 0, 1 );
+ Tuple *data3[] = {
+ TUPLE( "a", "b", "c" ), // <a,b,?> <a,?,c> ***
+ TUPLE( "a", "c", "d" ), // <a,c,?> <a,?,d> ***
+ TUPLE( "a", "b", "e" ), // <a,b,?> <a,?,e> => -<a,b,c>
+ TUPLE( "b", "d", "d" ), // <b,d,?> <b,?,d>
+ TUPLE( "a", "d", "d" ), // <a,d,?> <a,?,d> => -<a,c,d>
+ TUPLE( "e", "c", "a" ), // <e,c,?> <e,?,a>
+ TUPLE( "f", "b", "d" ), // <f,b,?> <f,?,c>
+ 0
+ };
+ Tuple *query3[] = {
+ TUPLE( "a", 0, "d" ),
+ TUPLE( 0, 0, "d" ),
+ TUPLE( 0, "c", 0 ),
+ TUPLE( "f", "b", "d" ),
+ 0
+ };
+ Relation rel3 = RELATION( &stringitem, &stringitem, &stringitem );
+ Relation_add_constraint( &rel3, 1, 1, 0 ); // AxB -> C
+ Relation_add_constraint( &rel3, 1, 0, 1 ); // AxC -> B
+
+ test_Relation_add( &rel3, data3 );
+ query_report( &rel3, 0 );
+ query_report_all( &rel3, query3 );
+ test_Relation_delete( &rel3, query3 );
return 0;
}