Changeset 34 for trunk/epic
- Timestamp:
- 06/08/09 21:47:59 (3 years ago)
- Location:
- trunk/epic
- Files:
-
- 3 modified
-
epic.sql (modified) (35 diffs)
-
test/test_asserts.sql (modified) (2 diffs)
-
test/test_timing.sql (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/epic/epic.sql
r33 r34 177 177 */ 178 178 179 CREATE OR REPLACE FUNCTION assert_test_schema() RETURNS boolean AS $$ 179 CREATE OR REPLACE FUNCTION _epic_init() RETURNS boolean AS $$ 180 DECLARE 181 t text; 180 182 BEGIN 181 183 SET client_min_messages = warning; 184 185 BEGIN 186 RAISE EXCEPTION 'ignore me'; 187 EXCEPTION WHEN OTHERS THEN 188 BEGIN 189 t := SQLSTATE; 190 t := SQLERRM; 191 EXCEPTION WHEN undefined_column THEN 192 -- PG 8.0 did not have SQLSTATE, SQLERRM available. Epic relies 193 -- on the ability to distinguish one error from another. 194 RAISE EXCEPTION 'Epic requires at least PostgreSQL version 8.1'; 195 END; 196 END; 182 197 183 198 BEGIN … … 189 204 BEGIN 190 205 CREATE TABLE test.results (name text PRIMARY KEY, module text, 191 result text, errcode text, errmsg text); 206 result text, errcode text, errmsg text, 207 runtime timestamp with time zone default now()); 192 208 EXCEPTION WHEN duplicate_table THEN 193 209 NULL; … … 198 214 $$ LANGUAGE plpgsql; 199 215 200 SELECT * FROM assert_test_schema();201 DROP FUNCTION assert_test_schema();216 SELECT * FROM _epic_init(); 217 DROP FUNCTION _epic_init(); 202 218 203 219 … … 208 224 ON pg_proc.pronamespace::oid = pg_namespace.oid::oid 209 225 WHERE pg_namespace.nspname = 'test' 210 AND pg_proc.proname LIKE E'test\_%';226 AND pg_proc.proname LIKE 'test_%'; 211 227 212 228 … … 219 235 IF result ~* '^[[:space:]]*(SELECT|EXECUTE)[[:space:]]' THEN 220 236 return result; 221 ELSIF result ~* E'^[[:space:]]*(VALUES)[[:space:]]*\\(' THEN237 ELSIF result ~* '^[[:space:]]*(VALUES)[[:space:]]*\\(' THEN 222 238 return result; 223 239 ELSE … … 348 364 rec record; 349 365 seen int := 0; 366 msg text; 350 367 BEGIN 351 368 FOR rec IN … … 360 377 361 378 IF seen = 0 THEN 362 RAISE EXCEPTION '% has no attributes.', quote_literal(tablename); 379 msg := quote_literal(tablename); 380 RAISE EXCEPTION '% has no attributes.', msg; 363 381 END IF; 364 382 END; … … 391 409 output_record test.results%ROWTYPE; 392 410 splitpoint int; 393 old_search_path text;394 411 BEGIN 395 412 SELECT module INTO modulename FROM test.testnames WHERE name = testname; … … 399 416 -- Allow test.* functions to be referenced without a schema name during this transaction. 400 417 PERFORM set_config('search_path', 'test, ' || current_setting('search_path'), true); 401 EXECUTE 'SELECT * FROM test.' || testname || '();'; 418 EXECUTE 'SELECT * FROM test.' || testname || '();' INTO output_record; 419 RETURN output_record; 402 420 EXCEPTION WHEN OTHERS THEN 403 421 IF SQLSTATE = 'P0001' AND SQLERRM LIKE '[%]%' THEN … … 406 424 VALUES (testname, modulename, substr(SQLERRM, 1, splitpoint), 407 425 CASE WHEN SQLERRM LIKE '[FAIL]%' THEN SQLSTATE ELSE '' END, 408 btrim(substr(SQLERRM, splitpoint + 1))) 409 RETURNING * INTO output_record;426 btrim(substr(SQLERRM, splitpoint + 1))); 427 SELECT INTO output_record * FROM test.results WHERE name = testname; 410 428 RETURN output_record; 411 429 ELSE 412 430 INSERT INTO test.results (name, module, result, errcode, errmsg) 413 VALUES (testname, modulename, '[FAIL]', SQLSTATE, SQLERRM) 414 RETURNING * INTO output_record;431 VALUES (testname, modulename, '[FAIL]', SQLSTATE, SQLERRM); 432 SELECT INTO output_record * FROM test.results WHERE name = testname; 415 433 RETURN output_record; 416 434 END IF; … … 425 443 -- Runs all tests in the given module, stores in test.results, and returns results. 426 444 DECLARE 427 testname pg_proc.proname%TYPE;445 testname record; 428 446 output_record test.results%ROWTYPE; 429 447 BEGIN … … 440 458 -- Runs all known test functions, stores in test.results, and returns results. 441 459 DECLARE 442 testname pg_proc.proname%TYPE;443 modulename text;460 testname record; 461 modulename record; 444 462 output_record test.results%ROWTYPE; 445 463 BEGIN 446 464 FOR modulename in SELECT DISTINCT module FROM test.testnames ORDER BY module ASC 447 465 LOOP 448 FOR testname IN SELECT name FROM test.testnames WHERE module = modulename ORDER BY name ASC466 FOR testname IN SELECT name FROM test.testnames WHERE module = modulename.module ORDER BY name ASC 449 467 LOOP 450 SELECT INTO output_record * FROM test.run_test(testname );468 SELECT INTO output_record * FROM test.run_test(testname.name); 451 469 RETURN NEXT output_record; 452 470 END LOOP; 453 471 END LOOP; 472 RETURN; 454 473 END; 455 474 $$ LANGUAGE plpgsql; … … 541 560 RAISE EXCEPTION 'Call: ''%'' did not return void. Got ''%'' instead.', call, retval; 542 561 END IF; 562 RETURN; 543 563 END; 544 564 $$ LANGUAGE plpgsql; … … 557 577 RAISE EXCEPTION '%', msg; 558 578 END IF; 579 RETURN; 559 580 END; 560 581 $$ LANGUAGE plpgsql IMMUTABLE; … … 572 593 RAISE EXCEPTION '% != %', elem_1, elem_2; 573 594 END IF; 595 RETURN; 574 596 END; 575 597 $$ LANGUAGE plpgsql IMMUTABLE; … … 585 607 RAISE EXCEPTION '% = %', elem_1, elem_2; 586 608 END IF; 609 RETURN; 587 610 END; 588 611 $$ LANGUAGE plpgsql IMMUTABLE; … … 601 624 RAISE EXCEPTION '% not < %', elem_1, elem_2; 602 625 END IF; 626 RETURN; 603 627 END; 604 628 $$ LANGUAGE plpgsql IMMUTABLE; … … 617 641 RAISE EXCEPTION '% not <= %', elem_1, elem_2; 618 642 END IF; 643 RETURN; 619 644 END; 620 645 $$ LANGUAGE plpgsql IMMUTABLE; … … 633 658 RAISE EXCEPTION '% not > %', elem_1, elem_2; 634 659 END IF; 660 RETURN; 635 661 END; 636 662 $$ LANGUAGE plpgsql IMMUTABLE; … … 649 675 RAISE EXCEPTION '% not >= %', elem_1, elem_2; 650 676 END IF; 677 RETURN; 651 678 END; 652 679 $$ LANGUAGE plpgsql IMMUTABLE; … … 667 694 -- errm = '' and state = ''. The resultant error will tell you the 668 695 -- SQLSTATE and SQLERRM that were raised. 696 DECLARE 697 msg text; 669 698 BEGIN 670 699 BEGIN … … 674 703 IF ((state IS NOT NULL AND SQLSTATE != state) OR 675 704 (errm IS NOT NULL AND SQLERRM != errm)) THEN 676 RAISE EXCEPTION 'Call: ''%'' raised ''(%) %'' instead of ''(%) %''.', call, SQLSTATE, SQLERRM, state, errm; 705 msg = 'Call: ''' || call || ''' raised ''(' || SQLSTATE || ') ' || SQLERRM || ''' instead of ''(' || state || ') ' || errm || '''.'; 706 RAISE EXCEPTION '%', msg; 677 707 END IF; 678 708 RETURN; 679 709 END; 680 RAISE EXCEPTION 'Call: % did not raise an error.', quote_literal(call); 710 msg := 'Call: ' || quote_literal(call) || ' did not raise an error.'; 711 RAISE EXCEPTION '%', msg; 681 712 END; 682 713 $$ LANGUAGE plpgsql; … … 713 744 s text; 714 745 e text; 746 msg text; 715 747 BEGIN 716 748 s := test.statement(call_1); … … 726 758 RAISE EXCEPTION 'Record: % from: % not found in: %', rec, call_2, call_1; 727 759 END LOOP; 760 RETURN; 728 761 END; 729 762 $$ LANGUAGE plpgsql; … … 753 786 found_1 boolean; 754 787 lower_bound int; 755 base_type text; 788 base_type text; 789 msg text; 756 790 BEGIN 757 791 -- Dump the call output into a temp table … … 826 860 DROP TABLE _test_assert_column_base; 827 861 EXECUTE 'DROP TABLE _test_assert_column_expected'; 828 RAISE EXCEPTION '%', SQLERRM; 829 END TRY; 862 msg := SQLERRM; 863 RAISE EXCEPTION '%', msg; 864 END; 830 865 831 866 CLOSE curs_base; … … 833 868 DROP TABLE _test_assert_column_base; 834 869 EXECUTE 'DROP TABLE _test_assert_column_expected'; 870 RETURN; 835 871 END; 836 872 $$ LANGUAGE plpgsql; … … 856 892 'SELECT ' || columns || ' FROM ' || call_2 857 893 ); 894 RETURN; 858 895 END; 859 896 $$ LANGUAGE plpgsql; … … 864 901 DECLARE 865 902 result bool; 866 failed text[] ;903 failed text[] DEFAULT '{}'::text[]; 867 904 failed_len int; 868 905 BEGIN … … 885 922 END IF; 886 923 END IF; 924 RETURN; 887 925 END; 888 926 $$ LANGUAGE plpgsql; … … 897 935 PERFORM test.fail('The call "' || call || '" is not empty.'); 898 936 END IF; 937 RETURN; 899 938 END; 900 939 $$ LANGUAGE plpgsql; … … 929 968 END IF; 930 969 END IF; 970 RETURN; 931 971 END; 932 972 $$ LANGUAGE plpgsql; … … 941 981 PERFORM test.fail('The call "' || call || '" is empty.'); 942 982 END IF; 983 RETURN; 943 984 END; 944 985 $$ LANGUAGE plpgsql; … … 957 998 IF number IS NULL THEN v_number := 1000000; END IF; 958 999 -- Mustn't use now() here since that value is fixed for the entire transaction. 959 start := clock_timestamp(); 1000 -- Also, clock_timestamp isn't available until 8.2 so we use timeofday instead. 1001 start := timeofday()::timestamp; 960 1002 FOR i IN 1..v_number 961 1003 LOOP … … 965 1007 -- overhead outweighs assignment overhead if we accumulated the time inside the loop; 966 1008 -- therefore I chose "outside" since it makes the whole run faster. ;) 967 RETURN ( clock_timestamp()- start);1009 RETURN (timeofday()::timestamp - start); 968 1010 END; 969 1011 $$ LANGUAGE plpgsql; -
trunk/epic/test/test_asserts.sql
r32 r34 90 90 91 91 92 CREATE OR REPLACE FUNCTION test._return_void() RETURNS VOID AS $$ 93 BEGIN 94 RETURN; 95 END; 96 $$ LANGUAGE plpgsql; 97 92 98 CREATE OR REPLACE FUNCTION test.test_assert_void() RETURNS VOID AS $$ 93 99 -- Assert the correct operation of test.assert_void … … 97 103 BEGIN 98 104 -- assert_void() MUST return VOID if the given call returns VOID. 99 SELECT INTO retval * FROM test.assert_void(' pg_sleep(0.1)');105 SELECT INTO retval * FROM test.assert_void('test._return_void()'); 100 106 IF retval != '' THEN 101 107 RAISE EXCEPTION 'assert_void did not itself return void. Got ''%'' instead.', retval; -
trunk/epic/test/test_timing.sql
r25 r34 1 1 -- Tests for the timing functions which Epic provides. 2 2 -- To run, execute epic.sql, then this script, then test.run_module('test_timing'). 3 4 CREATE OR REPLACE FUNCTION test._sleep(s double precision) RETURNS VOID AS $$ 5 -- sleep function for Postgres 8.1 6 DECLARE 7 start timestamp with time zone; 8 BEGIN 9 start := timeofday()::timestamp; 10 LOOP 11 EXIT WHEN (timeofday()::timestamp - start) > (s || ' second')::interval; 12 END LOOP; 13 END; 14 $$ LANGUAGE plpgsql; 3 15 4 16 CREATE OR REPLACE FUNCTION test.test_timing() RETURNS VOID AS $$ … … 8 20 BEGIN 9 21 -- Shame we have to use 0.01 but some platforms don't have finer resolution. 10 t := test.timing('SELECT pg_sleep(0.01)', 100);22 t := test.timing('SELECT test._sleep(0.01)', 100); 11 23 12 24 -- Let's assume that sleep(0.01) * 100 should never run *under* 1s
