-- packages/acs-events/sql/postgres/test/time_interval-test.sql -- -- Regression tests for time_interval API -- -- @author jowell@jsabino.com -- @creation-date 2001-06-26 -- -- $Id: time_intervals-test.sql,v 1.4 2018/03/27 12:22:17 hectorr Exp $ -- Note: These tests use the semi-ported utPLSQL regression package \i utest-create.sql -- Set-up the regression test CREATE OR REPLACE FUNCTION ut__setup() RETURNS integer AS $$ BEGIN raise notice 'Setting up time_intervals test...'; -- create copies of the tables (shadow tables) to verify API operations -- No need for execute here? create table ut_time_intervals as select * from time_intervals; -- For testing purposes, both tables should still be empty PERFORM ut_assert__eqtable ('Comparing copied data for time interval', 'time_intervals', 'ut_time_intervals' ); -- Store keys that are in the table prior to the regression test create table ut_interval_ids as select interval_id from time_intervals; return 0; END; $$ LANGUAGE plpgsql; -- Clean up the mess that regression testing did CREATE OR REPLACE FUNCTION ut__teardown() RETURNS integer AS $$ BEGIN raise notice 'Tearing down time_intervals test...'; -- Delete intervals added by tests -- cascade delete in timespans should delete corresponding entries in that table -- Note that we exclude deleting rows that existed prior to regression test delete from ut_time_intervals where interval_id not in (select interval_id from ut_interval_ids); -- Drop test tables -- cascade option does not work? drop table ut_time_intervals; drop table ut_interval_ids; return 0; END; $$ LANGUAGE plpgsql; -- Postgres has this weird behavior that you cannot change a row twice -- within a transaction. -- We test the creation of a time interval entry -- added select define_function_args('ut__new','date1,date2'); -- -- procedure ut__new/2 -- CREATE OR REPLACE FUNCTION ut__new( new__date1 timestamptz, new__date2 timestamptz ) RETURNS integer AS $$ DECLARE new__interval_id time_intervals.interval_id%TYPE; v_result integer; BEGIN raise notice 'Testing time_interval__new...'; -- create a time interval, and check if entry is made v_result := ut_assert__isnotnull ('Creating a new test time interval:', time_interval__new(new__date1, new__date2) ); -- Verify that the API does the correct insert by manually entering -- an entry in the shadow table -- Note that we did not port the currval in the timepsan_seq view select currval('timespan_sequence') into new__interval_id; insert into ut_time_intervals(interval_id, start_date, end_date) values(new__interval_id, new__date1, new__date2); PERFORM ut_assert__eqtable ('Comparing created data for time interval :', 'time_intervals', 'ut_time_intervals' ); -- If successful, interval id is correct return new__interval_id; END; $$ LANGUAGE plpgsql; -- Check the deletion of a time interval -- added select define_function_args('ut__delete','interval_id'); -- -- procedure ut__delete/1 -- CREATE OR REPLACE FUNCTION ut__delete( delete__interval_id integer ) RETURNS integer AS $$ DECLARE BEGIN raise notice 'Testing time interval delete...'; -- Delete entry from shadow table delete from ut_time_intervals where interval_id = delete__interval_id; -- Delete the row from actual table PERFORM time_interval__delete(delete__interval_id); -- Verify time interval not there. PERFORM ut_assert__eqtable ('Delete verification', 'ut_time_intervals', 'time_intervals' ); -- If successful, interval id is correct return 0; END; $$ LANGUAGE plpgsql; -- added select define_function_args('ut__edit','interval_id,start_date,end_date'); -- -- procedure ut__edit/3 -- CREATE OR REPLACE FUNCTION ut__edit( edit__interval_id integer, edit__start_date timestamptz, edit__end_date timestamptz ) RETURNS integer AS $$ DECLARE BEGIN raise notice 'Testing time_interval__edit...'; -- Edit the time interval PERFORM time_interval__edit(edit__interval_id,edit__start_date,edit__end_date); -- Verify if edit__start_date is not null and edit__end_date is not null then update ut_time_intervals set start_date = edit__start_date, end_date = edit__end_date where interval_id = edit__interval_id; end if; if edit__start_date is null and edit__end_date is not null then update ut_time_intervals set end_date = edit__end_date where interval_id = edit__interval_id; end if; if edit__start_date is not null and edit__end_date is null then update ut_time_intervals set start_date = edit__start_date where interval_id = edit__interval_id; end if; PERFORM ut_assert__eqtable ('Comparing edited data for time interval', 'time_intervals', 'ut_time_intervals' ); return 0; END; $$ LANGUAGE plpgsql; -- added select define_function_args('ut__eq','msg,interval_id_1,interval_id_2,result'); -- -- procedure ut__eq/4 -- CREATE OR REPLACE FUNCTION ut__eq( eq__msg varchar, eq__interval_id_1 integer, eq__interval_id_2 integer, eq__result boolean ) RETURNS integer AS $$ DECLARE BEGIN PERFORM ut_assert__eq (eq__msg, time_interval__eq(eq__interval_id_1, eq__interval_id_2), eq__result ); return 0; END; $$ LANGUAGE plpgsql; -- added select define_function_args('ut__shift','interval_id,offset_1,offset_2,date1,date2'); -- -- procedure ut__shift/5 -- CREATE OR REPLACE FUNCTION ut__shift( shift__interval_id integer, shift__offset_1 integer, shift__offset_2 integer, shift__date1 timestamptz, shift__date2 timestamptz ) RETURNS integer AS $$ DECLARE BEGIN raise notice 'Testing shift...'; -- Shift the time interval PERFORM time_interval__shift(shift__interval_id, shift__offset_1, shift__offset_2); -- Verify update ut_time_intervals set start_date = shift__date1, end_date = shift__date2 where interval_id = shift__interval_id; PERFORM ut_assert__eqtable ('Comparing shifted data for time intervals', 'time_intervals', 'ut_time_intervals' ); return 0; END; $$ LANGUAGE plpgsql; -- added -- -- procedure ut__overlaps_p/4 -- CREATE OR REPLACE FUNCTION ut__overlaps_p( overlaps_p__msg varchar, overlaps_p__interval_id_1 integer, overlaps_p__interval_id_2 integer, overlaps_p__result boolean ) RETURNS integer AS $$ DECLARE BEGIN -- Test the time interval PERFORM ut_assert__eq (overlaps_p__msg, time_interval__overlaps_p(overlaps_p__interval_id_1, overlaps_p__interval_id_2), overlaps_p__result ); return 0; END; $$ LANGUAGE plpgsql; -- added -- -- procedure ut__overlaps_p/5 -- CREATE OR REPLACE FUNCTION ut__overlaps_p( overlaps_p__msg varchar, overlaps_p__interval_id integer, overlaps_p__start_date timestamptz, overlaps_p__end_date timestamptz, overlaps_p__result boolean ) RETURNS integer AS $$ DECLARE BEGIN -- Test the time interval PERFORM ut_assert__eq (overlaps_p__msg, time_interval__overlaps_p(overlaps_p__interval_id, overlaps_p__start_date, overlaps_p__end_date), overlaps_p__result ); return 0; END; $$ LANGUAGE plpgsql; -- added select define_function_args('ut__overlaps_p','msg,start_date_1,end_date_1,start_date_2,end_date_2,result'); -- -- procedure ut__overlaps_p/6 -- CREATE OR REPLACE FUNCTION ut__overlaps_p( overlaps_p__msg varchar, overlaps_p__start_date_1 timestamptz, overlaps_p__end_date_1 timestamptz, overlaps_p__start_date_2 timestamptz, overlaps_p__end_date_2 timestamptz, overlaps_p__result boolean ) RETURNS integer AS $$ DECLARE BEGIN -- Test the time interval PERFORM ut_assert__eq (overlaps_p__msg, time_interval__overlaps_p(overlaps_p__start_date_1, overlaps_p__end_date_1, overlaps_p__start_date_2, overlaps_p__end_date_2), overlaps_p__result ); return 0; END; $$ LANGUAGE plpgsql; -- added select define_function_args('ut__copy','interval_id,offset'); -- -- procedure ut__copy/2 -- CREATE OR REPLACE FUNCTION ut__copy( copy__interval_id integer, copy__offset integer ) RETURNS integer AS $$ DECLARE v_interval_id time_intervals.interval_id%TYPE; interval_row record; BEGIN raise notice 'Testing time_interval__copy...'; -- Copy the time interval v_interval_id := time_interval__copy(copy__interval_id,copy__offset); -- Get the copied start and end dates, before the offset select * into interval_row from time_intervals where interval_id = copy__interval_id; -- Insert for testing insert into ut_time_intervals (interval_id, start_date, end_date) values (v_interval_id, interval_row.start_date + copy__offset, interval_row.end_date + copy__offset); -- Verify copies PERFORM ut_assert__eqtable ('Comparing copied data for time intervals', 'time_intervals', 'ut_time_intervals' ); return v_interval_id; END; $$ LANGUAGE plpgsql; -- -- procedure ut__regression1/0 -- CREATE OR REPLACE FUNCTION ut__regression1( ) RETURNS integer AS $$ DECLARE v_result integer := 0; v_interval_id time_intervals.interval_id%TYPE; v_interval_id_ck time_intervals.interval_id%TYPE; BEGIN raise notice 'Regression test, part 1 (creates and edits).'; -- We first check if the creation of time intervals work v_interval_id := ut__new(timestamptz '2001-01-01',timestamptz '2001-01-02'); -- Try to edit, putting new values for start date and end dates PERFORM ut__edit(v_interval_id,timestamptz '2001-01-02',timestamptz '2001-01-30'); -- Edit, but this time, change only the start date PERFORM ut__edit(v_interval_id,timestamptz '2001-01-07',null); -- Edit, but this time, change only the end date PERFORM ut__edit(v_interval_id,null,timestamptz '2001-01-08'); -- We now test equality of (identical) intervals PERFORM ut__eq('Equal (same) intervals',v_interval_id,v_interval_id,true); -- Create another interval for comparison v_interval_id_ck := ut__new(timestamptz '2001-01-07',timestamptz '2001-01-08'); -- We now test equality of (nonidentical) intervals PERFORM ut__eq('Equal (distinct) intervals',v_interval_id,v_interval_id_ck,true); -- Shift the second interval start date by one day, the end date by two days PERFORM ut__shift(v_interval_id_ck,1,2,timestamptz '2001-01-08', timestamptz '2001-01-10'); -- Now test inequality of time intervals PERFORM ut__eq('Unequal (distinct) intervals',v_interval_id,v_interval_id_ck,false); -- Shift the second interval start date BACK by one day, the end date same PERFORM ut__shift(v_interval_id_ck,-1,0,timestamptz '2001-01-07', timestamptz '2001-01-10'); -- Now test inequality of time intervals PERFORM ut__eq('Unequal (distinct) intervals: start date equal',v_interval_id,v_interval_id_ck,false); -- Shift the second interval, start date same, but the end date BACK by two days PERFORM ut__shift(v_interval_id_ck,0,-2,timestamptz '2001-01-07', timestamptz '2001-01-08'); -- Should be equal again PERFORM ut__eq('Equal again, (distinct) intervals',v_interval_id,v_interval_id_ck,true); -- For fun, shift start date BACK by two days, the end date BACK by 1 day PERFORM ut__shift(v_interval_id_ck,-2,-1,timestamptz '2001-01-05', timestamptz '2001-01-07'); -- Should be unequal again PERFORM ut__eq('For fun, unequal (distinct) intervals',v_interval_id,v_interval_id_ck,false); -- Note that at this point, interval pointed to by v_interval_id is from 2001-01-07 through 2001-01-08 -- while interval pointed to by v_interval_id_ck is from 2001-01-05 through 2001-01-07. -- They overlap. PERFORM ut__overlaps_p('Overlapping intervals',v_interval_id,v_interval_id_ck,true); -- Ok, shift the dtart and end dates by one so that intervals do not overlap PERFORM ut__shift(v_interval_id_ck,-1,-1,timestamptz '2001-01-04', timestamptz '2001-01-06'); -- They should not overlap now. PERFORM ut__overlaps_p('Non-overlapping intervals',v_interval_id,v_interval_id_ck,false); -- We test the overloaded function definitions of time_interval__overlaps_p -- Note that we are comparing with 2001-01-07 through 2001-01-08 PERFORM ut__overlaps_p('Overlapping intervals', v_interval_id, timestamptz '2001-01-06', timestamptz '2001-01-09', true); -- How about an interval next month? PERFORM ut__overlaps_p('Non-overlapping intervals', v_interval_id, timestamptz '2001-02-06', timestamptz '2001-02-09', false); -- Try a null starting interval PERFORM ut__overlaps_p('Overlapping intervals (null start)', v_interval_id, null, timestamptz '2001-01-09', true); -- Try a null starting interval PERFORM ut__overlaps_p('Overlapping intervals (null end)', v_interval_id, timestamptz '2001-01-06', null, true); -- What if the interval is not an allowable interval? -- By definition, any interval should be non-overlapping with a non-existent interval PERFORM ut__overlaps_p('Non-overlapping intervals (non-allowed interval, outside month)', v_interval_id, timestamptz '2001-02-09', timestamptz '2001-02-06', false); -- What if the interval is not an allowable interval? -- By definition, any interval should be non-overlapping with a non-existent interval PERFORM ut__overlaps_p('Non-overlapping intervals (non-allowed interval, in month)', v_interval_id, timestamptz '2001-01-09', timestamptz '2001-01-06', false); -- Yet another overloaded definition PERFORM ut__overlaps_p('Overlapping intervals (not in time_intervals)', timestamptz '2001-01-06', timestamptz '2001-01-09', timestamptz '2001-01-07', timestamptz '2001-01-08', true); -- Yet another overloaded definition PERFORM ut__overlaps_p('Overlapping intervals (not in time_intervals)', timestamptz '2001-01-06', timestamptz '2001-01-09', timestamptz '2001-01-09', timestamptz '2001-01-10', true); -- Yet another overloaded definition PERFORM ut__overlaps_p('Overlapping intervals (not in time_intervals)', timestamptz '2001-01-06', timestamptz '2001-01-09', null, timestamptz '2001-01-10', true); PERFORM ut__overlaps_p('Overlapping intervals (not in time_intervals)', timestamptz '2001-01-06', timestamptz '2001-01-09', timestamptz '2001-01-10', null, false); -- Yet another overloaded definition PERFORM ut__overlaps_p('Non-overlapping intervals (not in time_intervals)', timestamptz '2001-02-06', timestamptz '2001-02-09', timestamptz '2001-01-07', timestamptz '2001-01-08', false); -- Overwrite the check interval a copy, with zero offset v_interval_id_ck := ut__copy(v_interval_id,0); -- Should be equal -- Now test equality of time intervals PERFORM ut__eq('Copied intervals (zero offset)',v_interval_id,v_interval_id_ck,true); -- Overwrite the check interval a copy, with non-zero offset v_interval_id_ck := ut__copy(v_interval_id,1); -- Should be unequal -- Now test inequality of time intervals PERFORM ut__eq('Copied intervals (non-zero offset)',v_interval_id,v_interval_id_ck,false); -- We will improve the regression test so there is reporting -- of individual test results. For now, reaching this far is -- enough to declare success. return v_result; END; $$ LANGUAGE plpgsql; -- -- procedure ut__regression2/0 -- CREATE OR REPLACE FUNCTION ut__regression2( ) RETURNS integer AS $$ DECLARE v_result integer := 0; rec_interval record; BEGIN raise notice 'Regression test, part 2 (deletes).'; -- Remove all entries made by regression test -- This also tests the deletion mechanism FOR rec_interval IN select * from time_intervals where interval_id not in (select interval_id from ut_interval_ids) LOOP PERFORM ut__delete(rec_interval.interval_id); END LOOP; -- We will improve the regression test so there is reporting -- of individual test results. For now, reaching this far is -- enough to declare success. return v_result; END; $$ LANGUAGE plpgsql; -------------------------------------------------------------------------------- -- Main regression test. PostgreSQL does not allow multiple changes made to a -- primary key inside a transaction if the primary key is referenced by another -- table (e.g., insert and delete). As a fix, we break down the regression test -- so that row creations and edits are separate from row deletions -------------------------------------------------------------------------------- select (case when ut__setup() = 0 then 'Regression test properly set up.' end) as setup_result; select (case when ut__regression1() = 0 then 'Regression test, part 1 successful.' end) as test_result; select (case when ut__regression2() = 0 then 'Regression test, part 2 successful.' end) as test_result; select (case when ut__teardown() = 0 then 'Regression test properly torn down.' end) as teardown_result; -- Clean up created functions. -- This depends on openacs4 installed. select drop_package('ut'); -------------------------------------------------------------------------------- -- End of regression test -------------------------------------------------------------------------------- \i utest-drop.sql