%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % HELPERS % plunit is a Prolog unit-test framework initially developed for SWI-Prolog :- use_module(library(plunit)). :- discontiguous test/2. % Run the tests. test :- run_tests(sql). % 'clean' drop: call drop/1 and swallow any thrown exceptions cdrop(Table) :- catch(drop(Table), _, true). % Checks that two lists have the same content. same_content(L1, L2) :- msort(L1, S), msort(L2, S). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TESTS :- begin_tests(sql). % Test if create/1 works. test(create_table, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), tables(Tables), member(foo, Tables), !. % Test if create/1 throws an error on dup table name. test(create_redundant, [throws(_), cleanup(cdrop(foo))]) :- create_table(foo, [bar, baz]), create_table(foo, [bab, bac]). % Test if the columns are properly recorded. test(cols, cleanup(cdrop(foo))) :- create_table(foo, [baru, bazu]), cols(foo, Cols), assertion(Cols == [baru, bazu]). % Test if drop/1 works. test(drop) :- create_table(foo, [bar, baz]), drop(foo), !, tables(Tables), \+ member(foo, Tables). % Test if drop/1 throws an error on unknown table name. test(drop_inexistant, throws(_)) :- drop(foobar). % Test if row/2 returns the different rows of a given table. test(rows, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), rows(foo, Rows), assertion(length(Rows,2)). % Test if row/2 fails on an unknown table name. test(row_inexistant, throws(_)) :- rows(foo, _Row). % Test if rows/1 works when called for a given table name. test(rows, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), rows(foo). % Test if rows/1 throws an error on unknown table name. test(rows_inexistant, throws(_)) :- rows(foo). % Simple insert/2 & selec/4 test. test(insert2, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), %selec(foo, *, [], X/Y), !, selec(foo, *, X/Y), !, assertion(X == [+bar, +baz]), assertion(Y == [1, 2]), insert(foo, [3, 4]), findall(Z, selec(foo, *, [], _/Z), Zs), !, assertion(Zs == [[1,2],[3,4]]). % Test if insert/2 throws an error on unknown table name. test(insert_inexistant, throws(_)) :- insert(foo, [1, 2]). % Simple delete/1 test. test(delete1, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), delete(foo), findall(Z, selec(foo, *, [], _/Z), Zs), assertion(Zs == []), tables(Tables), member(foo, Tables). % Simple delete/2 test. test(delete2, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), delete(foo, [+bar = 1]), findall(Z, selec(foo, *, [], _/Z), Zs), assertion(Zs == [[3, 4]]). % Another simple delete/2 test. test(delete2bis, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), delete(foo, [+bar >= 1]), findall(Z, selec(foo, *, [], _/Z), Zs), assertion(Zs == []). % Test delete/2 using multiple conditions. test(delete2_mult, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), delete(foo, [+bar = 1, +baz = 2]), findall(Z, selec(foo, *, [], _/Z), Zs), assertion(Zs == [[3, 4]]). % Another test of delete/2 using multiple conditions. test(delete2_mult_bis, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), delete(foo, [+bar > 1, +baz < 2]), findall(Z, selec(foo, *, [], _/Z), Zs), assertion(Zs == [[1, 2],[3,4]]). % Test selec/4 with a single condition +col condition. test(selec_cond1) :- selec(persons, *, [+id = 0], _/Row1), !, assertion(Row1 == [0, "Jeffrey", "Bowman", 30, "Daytona Beach"]), selec(persons, *, [+first = "Lorena"], _/Row2), !, assertion(Row2 == [1, "Lorena", "Michaels", 50, "Boardman"]). % Test selec/4 with two +col conditions. test(selec_cond_mult1) :- selec(persons, *, [+age = 47, +city = "Atlanta"], _/Row), !, assertion(Row == [11, "Betty", "Strickland", 47, "Atlanta"]). % Test selec/4 with a single projection and no conditions. test(selec_proj) :- findall(Row, selec(persons, [+first], [], _/Row), Rows0), flatten(Rows0, Rows), assertion(Rows == ["Jeffrey", "Lorena", "Joseph", "Stewart", "Thomas", "Tameka", "Annette", "David", "Anthony", "Lindsay", "Claudette", "Betty", "Richard", "Robert", "Candace", "Sandra"]). % Test selec/4 with projections and a condition. test(selec_mult_proj) :- findall(Row, selec(persons, [+first, +last], [+age >= 70], _/Row), Rows), same_content(Rows, [ ["Stewart", "Sullivan"], ["Thomas", "Marshall"], ["Lindsay", "Faught"]]). % Test that drop/1 correctly removes rows. test(drop_implem, cleanup(cdrop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), drop(foo), create_table(foo, [bar, baz]), findall(Z, selec(foo, *, [], _/Z), Zs), !, assertion(Zs == []). % Test that tables/1 works. test(tables, cleanup((cdrop(foo), cdrop(bar), cdrop(baz)))) :- create_table(foo, []), create_table(bar, []), create_table(baz, []), drop(bar), tables(Tables), member(foo, Tables), !, member(baz, Tables), !, \+ member(bar, Tables), !. % Test that insert/2 throws an error on unknown table name. test(insert_inexistant, throws(_)) :- insert(foobar, [1, 2]). % Test that insert/2 throws an error if it is supplied too few values. test(insert_count1, [throws(_), cleanup(drop(foo))]) :- create_table(foo, [bar, baz]), insert(foo, [1]). % Test that insert/2 throws an error if it is supplied too many values. test(insert_count2, [throws(_), cleanup(drop(foo))]) :- create_table(foo, [bar, baz]), insert(foo, [1, 2, 3]). % Tests that delete/1 throws an error on unknown table name. test(delete_inexistant1, throws(_)) :- delete(foobar). % Tests that delete/2 throws an error on unknown table name. test(delete_inexistant2, throws(_)) :- delete(foobar, []). % Simple delete/2 test using the +. test(delete2_1, cleanup(drop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), delete(foo, [+baz = 4]), findall(Z, selec(foo, *, [], _/Z), Zs), assertion(Zs == [[1, 2]]). % delete/2 test using mixed notations. test(delete2_2, cleanup(drop(foo))) :- create_table(foo, [bar, baz]), insert(foo, [1, 2]), insert(foo, [3, 4]), insert(foo, [3, 5]), delete(foo, [+bar = 3, +baz = 4]), findall(Z, selec(foo, *, [], _/Z), Zs), assertion(Zs == [[1, 2], [3, 5]]). % Test selec/4 with a projection and multiple conditions. test(selec_mult_cond) :- findall(Row, selec(persons, [+first, +last], [+age >= 60, +city = "Atlanta"], _/Row), Rows), same_content(Rows, [["Robert", "Evans"]]). % ==============================================================================