├── Changes ├── META.json ├── Makefile ├── README.md ├── compat ├── 10 │ └── pgtap--0.98.0--0.99.0.patch ├── 9.2 │ └── pgtap--0.95.0--0.96.0.patch ├── 9.4 │ ├── pgtap--0.96.0--0.97.0.patch │ └── pgtap--0.99.0--1.0.0.patch ├── 9.6 │ └── pgtap--0.97.0--0.98.0.patch ├── gencore ├── install-9.1.patch ├── install-9.2.patch ├── install-9.4.patch └── install-9.6.patch ├── contrib └── pgtap.spec ├── doc └── pgtap.mmd ├── pgtap.control ├── release.md ├── sql ├── pgtap--0.90.0--0.91.0.sql ├── pgtap--0.91.0--0.92.0.sql ├── pgtap--0.92.0--0.93.0.sql ├── pgtap--0.93.0--0.94.0.sql ├── pgtap--0.94.0--0.95.0.sql ├── pgtap--0.95.0--0.96.0.sql.in ├── pgtap--0.96.0--0.97.0.sql.in ├── pgtap--0.97.0--0.98.0.sql.in ├── pgtap--0.98.0--0.99.0.sql.in ├── pgtap--0.99.0--1.0.0.sql.in ├── pgtap--1.0.0--1.1.0.sql ├── pgtap--1.1.0--1.2.0.sql ├── pgtap--1.2.0--1.3.0.sql ├── pgtap--1.3.0--1.3.1.sql ├── pgtap--1.3.1--1.3.2.sql ├── pgtap--1.3.2--1.3.3.sql ├── pgtap--1.3.3--1.3.4.sql ├── pgtap--unpackaged--0.91.0.sql └── pgtap.sql.in ├── test ├── Dockerfile ├── docker-compose.yml ├── expected │ ├── aretap.out │ ├── build.out │ ├── check.out │ ├── cmpok.out │ ├── coltap.out │ ├── create.out │ ├── do_tap.out │ ├── enumtap.out │ ├── extension.out │ ├── fktap.out │ ├── functap.out │ ├── hastap.out │ ├── index.out │ ├── inheritance.out │ ├── inheritance_1.out │ ├── inheritance_2.out │ ├── inheritance_3.out │ ├── istap.out │ ├── matching.out │ ├── moretap.out │ ├── ownership.out │ ├── partitions.out │ ├── performs_ok.out │ ├── performs_within.out │ ├── pg73.out │ ├── pktap.out │ ├── policy.out │ ├── privs.out │ ├── proctap.out │ ├── resultset.out │ ├── roletap.out │ ├── ruletap.out │ ├── runjusttests.out │ ├── runjusttests_1.out │ ├── runjusttests_2.out │ ├── runjusttests_3.out │ ├── runjusttests_4.out │ ├── runjusttests_5.out │ ├── runjusttests_6.out │ ├── runnotests.out │ ├── runtests.out │ ├── runtests_1.out │ ├── runtests_2.out │ ├── runtests_3.out │ ├── runtests_4.out │ ├── runtests_5.out │ ├── throwtap.out │ ├── todotap.out │ ├── trigger.out │ ├── unique.out │ ├── update.out │ ├── usergroup.out │ ├── util.out │ └── valueset.out ├── psql.sql ├── run ├── schedule │ ├── build.sql │ ├── create.sql │ ├── main.sch │ ├── update.sch │ └── update.sql ├── setup.sql ├── sql │ ├── aretap.sql │ ├── check.sql │ ├── cmpok.sql │ ├── coltap.sql │ ├── do_tap.sql │ ├── enumtap.sql │ ├── extension.sql │ ├── fktap.sql │ ├── functap.sql │ ├── hastap.sql │ ├── index.sql │ ├── inheritance.sql │ ├── istap.sql │ ├── matching.sql │ ├── moretap.sql │ ├── ownership.sql │ ├── partitions.sql │ ├── performs_ok.sql │ ├── performs_within.sql │ ├── pg73.sql │ ├── pktap.sql │ ├── policy.sql │ ├── privs.sql │ ├── proctap.sql │ ├── resultset.sql │ ├── roletap.sql │ ├── ruletap.sql │ ├── runjusttests.sql │ ├── runnotests.sql │ ├── runtests.sql │ ├── throwtap.sql │ ├── todotap.sql │ ├── trigger.sql │ ├── unique.sql │ ├── usergroup.sql │ ├── util.sql │ └── valueset.sql └── test_MVU.sh └── tools ├── getos.sh ├── missing_extensions.sh ├── parallel_conn.sh ├── psql_args.sh └── util.sh /META.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pgTAP", 3 | "abstract": "Unit testing for PostgreSQL", 4 | "description": "pgTAP is a suite of database functions that make it easy to write TAP-emitting unit tests in psql scripts or xUnit-style test functions.", 5 | "version": "1.3.4", 6 | "maintainer": [ 7 | "David E. Wheeler ", 8 | "pgTAP List " 9 | ], 10 | "license": { 11 | "PostgreSQL": "https://www.postgresql.org/about/licence" 12 | }, 13 | "prereqs": { 14 | "runtime": { 15 | "requires": { 16 | "plpgsql": 0, 17 | "PostgreSQL": "9.1.0" 18 | }, 19 | "recommends": { 20 | "PostgreSQL": "9.4.0" 21 | } 22 | } 23 | }, 24 | "provides": { 25 | "pgtap": { 26 | "abstract": "Unit testing for PostgreSQL", 27 | "file": "sql/pgtap.sql", 28 | "version": "1.3.4" 29 | }, 30 | "pgtap-core": { 31 | "abstract": "Unit testing for PostgreSQL", 32 | "file": "sql/pgtap-core.sql", 33 | "version": "1.3.4" 34 | }, 35 | "pgtap-schema": { 36 | "abstract": "Schema unit testing for PostgreSQL", 37 | "file": "sql/pgtap-schema.sql", 38 | "version": "1.3.4" 39 | } 40 | }, 41 | "resources": { 42 | "homepage": "https://pgtap.org/", 43 | "bugtracker": { 44 | "web": "https://github.com/theory/pgtap/issues" 45 | }, 46 | "repository": { 47 | "url": "https://github.com/theory/pgtap.git", 48 | "web": "https://github.com/theory/pgtap", 49 | "type": "git" 50 | } 51 | }, 52 | "generated_by": "David E. Wheeler", 53 | "meta-spec": { 54 | "version": "1.0.0", 55 | "url": "https://pgxn.org/meta/spec.txt" 56 | }, 57 | "tags": [ 58 | "testing", 59 | "unit testing", 60 | "tap", 61 | "tddd", 62 | "test driven database development" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pgTAP 1.3.4 2 | ============ 3 | 4 | [pgTAP](https://pgtap.org) is a unit testing framework for PostgreSQL written 5 | in PL/pgSQL and PL/SQL. It includes a comprehensive collection of 6 | [TAP](https://testanything.org)-emitting assertion functions, as well as the 7 | ability to integrate with other TAP-emitting test frameworks. It can also be 8 | used in the xUnit testing style. For detailed documentation, see the 9 | documentation in `doc/pgtap.mmd` or 10 | [online](https://pgtap.org/documentation.html "Complete pgTAP Documentation"). 11 | 12 | [![PGXN version](https://badge.fury.io/pg/pgtap.svg)](https://badge.fury.io/pg/pgtap) 13 | [![🐘 Postgres](https://github.com/theory/pgtap/actions/workflows/test.yml/badge.svg)](https://github.com/theory/pgtap/actions/workflows/test.yml) 14 | 15 | pgTAP must be installed on a host with PostgreSQL server running; it cannot 16 | be installed remotely. 17 | 18 | To build it, just do this: 19 | 20 | ```sh 21 | make 22 | make install 23 | make installcheck 24 | ``` 25 | 26 | If you encounter an error such as: 27 | 28 | ``` 29 | "Makefile", line 8: Need an operator 30 | ``` 31 | 32 | You need to use GNU make, which may well be installed on your system as 33 | `gmake`: 34 | 35 | ```sh 36 | gmake 37 | gmake install 38 | gmake installcheck 39 | ``` 40 | 41 | If you encounter an error such as: 42 | 43 | ``` 44 | make: pg_config: Command not found 45 | ``` 46 | Or: 47 | 48 | ``` 49 | Makefile:52: *** pgTAP requires PostgreSQL 9.1 or later. This is . Stop. 50 | ``` 51 | 52 | Be sure that you have `pg_config` installed and in your path. If you used a 53 | package management system such as RPM to install PostgreSQL, be sure that the 54 | `-devel` package is also installed. If necessary tell the build process where 55 | to find it: 56 | 57 | ```sh 58 | env PG_CONFIG=/path/to/pg_config make && make install && make installcheck 59 | ``` 60 | 61 | And finally, if all that fails, copy the entire distribution directory to the 62 | `contrib/` subdirectory of the PostgreSQL source tree and try it there without 63 | `pg_config`: 64 | 65 | ```sh 66 | env NO_PGXS=1 make && make install && make installcheck 67 | ``` 68 | 69 | If you encounter an error such as: 70 | 71 | ``` 72 | ERROR: must be owner of database regression 73 | ``` 74 | 75 | You need to run the test suite using a super user, such as the default 76 | "postgres" super user: 77 | 78 | ``` 79 | make installcheck PGUSER=postgres 80 | ``` 81 | 82 | If you encounter an error such as: 83 | 84 | ``` 85 | ERROR: Missing extensions required for testing: citext isn ltree 86 | ``` 87 | 88 | Install the PostgreSQL 89 | [Additional Supplied Modules](https://www.postgresql.org/docs/current/contrib.html), 90 | which are required to run the tests. If you used a package management system 91 | such as RPM to install PostgreSQL, install the `-contrib` package. 92 | 93 | To install the extension in a custom prefix on PostgreSQL 18 or later, pass 94 | the `prefix` argument to `install` (but no other `make` targets): 95 | 96 | ```sh 97 | make install prefix=/usr/local/extras 98 | ``` 99 | 100 | Then ensure that the prefix is included in the following [`postgresql.conf` 101 | parameters]: 102 | 103 | ```ini 104 | extension_control_path = '/usr/local/extras/postgresql/share:$system' 105 | dynamic_library_path = '/usr/local/extras/postgresql/lib:$libdir' 106 | ``` 107 | 108 | Once pgTAP is installed, you can add it to a database by connecting as a super 109 | user and running: 110 | 111 | ```sql 112 | CREATE EXTENSION pgtap; 113 | ``` 114 | 115 | If you've upgraded your cluster to PostgreSQL 9.1 and already had pgTAP 116 | installed, you can upgrade it to a properly packaged extension with: 117 | 118 | ```sql 119 | CREATE EXTENSION pgtap FROM unpackaged; 120 | ``` 121 | 122 | If you want to install pgTAP and all of its supporting objects into a specific 123 | schema, use the `SCHEMA` clause to specify the schema, like so: 124 | 125 | ```sql 126 | CREATE EXTENSION pgtap SCHEMA tap; 127 | ``` 128 | 129 | Dependencies 130 | ------------ 131 | 132 | pgTAP requires PostgreSQL 9.1 or higher. 133 | 134 | Copyright and License 135 | --------------------- 136 | 137 | Copyright (c) 2008-2025 David E. Wheeler. Some rights reserved. 138 | 139 | Permission to use, copy, modify, and distribute this software and its 140 | documentation for any purpose, without fee, and without a written agreement is 141 | hereby granted, provided that the above copyright notice and this paragraph 142 | and the following two paragraphs appear in all copies. 143 | 144 | IN NO EVENT SHALL DAVID E. WHEELER BE LIABLE TO ANY PARTY FOR DIRECT, 145 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 146 | PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 147 | IF DAVID E. WHEELER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 148 | 149 | DAVID E. WHEELER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT 150 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 151 | PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, 152 | AND DAVID E. WHEELER HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, 153 | UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 154 | -------------------------------------------------------------------------------- /compat/10/pgtap--0.98.0--0.99.0.patch: -------------------------------------------------------------------------------- 1 | --- sql/pgtap--0.98.0--0.99.0.sql 2 | +++ sql/pgtap--0.98.0--0.99.0.sql 3 | @@ -134,6 +134,7 @@ 4 | ); 5 | $$ LANGUAGE sql; 6 | 7 | +DROP VIEW tap_funky; 8 | CREATE OR REPLACE VIEW tap_funky 9 | AS SELECT p.oid AS oid, 10 | n.nspname AS schema, 11 | @@ -144,7 +144,7 @@ CREATE OR REPLACE VIEW tap_funky 12 | || p.prorettype::regtype AS returns, 13 | p.prolang AS langoid, 14 | p.proisstrict AS is_strict, 15 | - p.prokind AS kind, 16 | + CASE proisagg WHEN true THEN 'a' WHEN false THEN 'f' END AS kind, 17 | p.prosecdef AS is_definer, 18 | p.proretset AS returns_set, 19 | p.provolatile::char AS volatility, 20 | -------------------------------------------------------------------------------- /compat/9.4/pgtap--0.96.0--0.97.0.patch: -------------------------------------------------------------------------------- 1 | --- sql/pgtap--0.96.0--0.97.0.sql 2 | +++ sql/pgtap--0.96.0--0.97.0.sql 3 | @@ -298,78 +298,3 @@ 4 | 'Extension ' || quote_ident($1) || ' should not exist' ); 5 | $$ LANGUAGE SQL; 6 | 7 | --- https://github.com/theory/pgtap/pull/119 8 | - 9 | --- throws_ok ( sql, errcode, errmsg, description ) 10 | -CREATE OR REPLACE FUNCTION throws_ok ( TEXT, CHAR(5), TEXT, TEXT ) 11 | -RETURNS TEXT AS $$ 12 | -DECLARE 13 | - query TEXT := _query($1); 14 | - errcode ALIAS FOR $2; 15 | - errmsg ALIAS FOR $3; 16 | - desctext ALIAS FOR $4; 17 | - descr TEXT; 18 | -BEGIN 19 | - descr := COALESCE( 20 | - desctext, 21 | - 'threw ' || errcode || ': ' || errmsg, 22 | - 'threw ' || errcode, 23 | - 'threw ' || errmsg, 24 | - 'threw an exception' 25 | - ); 26 | - EXECUTE query; 27 | - RETURN ok( FALSE, descr ) || E'\n' || diag( 28 | - ' caught: no exception' || 29 | - E'\n wanted: ' || COALESCE( errcode, 'an exception' ) 30 | - ); 31 | -EXCEPTION WHEN OTHERS OR ASSERT_FAILURE THEN 32 | - IF (errcode IS NULL OR SQLSTATE = errcode) 33 | - AND ( errmsg IS NULL OR SQLERRM = errmsg) 34 | - THEN 35 | - -- The expected errcode and/or message was thrown. 36 | - RETURN ok( TRUE, descr ); 37 | - ELSE 38 | - -- This was not the expected errcode or errmsg. 39 | - RETURN ok( FALSE, descr ) || E'\n' || diag( 40 | - ' caught: ' || SQLSTATE || ': ' || SQLERRM || 41 | - E'\n wanted: ' || COALESCE( errcode, 'an exception' ) || 42 | - COALESCE( ': ' || errmsg, '') 43 | - ); 44 | - END IF; 45 | -END; 46 | -$$ LANGUAGE plpgsql; 47 | - 48 | --- lives_ok( sql, description ) 49 | -CREATE OR REPLACE FUNCTION lives_ok ( TEXT, TEXT ) 50 | -RETURNS TEXT AS $$ 51 | -DECLARE 52 | - code TEXT := _query($1); 53 | - descr ALIAS FOR $2; 54 | - detail text; 55 | - hint text; 56 | - context text; 57 | - schname text; 58 | - tabname text; 59 | - colname text; 60 | - chkname text; 61 | - typname text; 62 | -BEGIN 63 | - EXECUTE code; 64 | - RETURN ok( TRUE, descr ); 65 | -EXCEPTION WHEN OTHERS OR ASSERT_FAILURE THEN 66 | - -- There should have been no exception. 67 | - GET STACKED DIAGNOSTICS 68 | - detail = PG_EXCEPTION_DETAIL, 69 | - hint = PG_EXCEPTION_HINT, 70 | - context = PG_EXCEPTION_CONTEXT, 71 | - schname = SCHEMA_NAME, 72 | - tabname = TABLE_NAME, 73 | - colname = COLUMN_NAME, 74 | - chkname = CONSTRAINT_NAME, 75 | - typname = PG_DATATYPE_NAME; 76 | - RETURN ok( FALSE, descr ) || E'\n' || diag( 77 | - ' died: ' || _error_diag(SQLSTATE, SQLERRM, detail, hint, context, schname, tabname, colname, chkname, typname) 78 | - ); 79 | -END; 80 | -$$ LANGUAGE plpgsql; 81 | - 82 | -------------------------------------------------------------------------------- /compat/9.6/pgtap--0.97.0--0.98.0.patch: -------------------------------------------------------------------------------- 1 | --- sql/pgtap--0.97.0--0.98.0.sql 2 | +++ sql/pgtap--0.97.0--0.98.0.sql 3 | @@ -309,133 +309,3 @@ 4 | 'Table ' || quote_ident($1) || ' should not be partitioned' 5 | ); 6 | $$ LANGUAGE sql; 7 | - 8 | --- _partof( child_schema, child_table, parent_schema, parent_table ) 9 | -CREATE OR REPLACE FUNCTION _partof ( NAME, NAME, NAME, NAME ) 10 | -RETURNS BOOLEAN AS $$ 11 | - SELECT EXISTS( 12 | - SELECT true 13 | - FROM pg_catalog.pg_namespace cn 14 | - JOIN pg_catalog.pg_class cc ON cn.oid = cc.relnamespace 15 | - JOIN pg_catalog.pg_inherits i ON cc.oid = i.inhrelid 16 | - JOIN pg_catalog.pg_class pc ON i.inhparent = pc.oid 17 | - JOIN pg_catalog.pg_namespace pn ON pc.relnamespace = pn.oid 18 | - WHERE cn.nspname = $1 19 | - AND cc.relname = $2 20 | - AND cc.relispartition 21 | - AND pn.nspname = $3 22 | - AND pc.relname = $4 23 | - AND pc.relkind = 'p' 24 | - ) 25 | -$$ LANGUAGE sql; 26 | - 27 | --- _partof( child_table, parent_table ) 28 | -CREATE OR REPLACE FUNCTION _partof ( NAME, NAME ) 29 | -RETURNS BOOLEAN AS $$ 30 | - SELECT EXISTS( 31 | - SELECT true 32 | - FROM pg_catalog.pg_class cc 33 | - JOIN pg_catalog.pg_inherits i ON cc.oid = i.inhrelid 34 | - JOIN pg_catalog.pg_class pc ON i.inhparent = pc.oid 35 | - WHERE cc.relname = $1 36 | - AND cc.relispartition 37 | - AND pc.relname = $2 38 | - AND pc.relkind = 'p' 39 | - AND pg_catalog.pg_table_is_visible(cc.oid) 40 | - AND pg_catalog.pg_table_is_visible(pc.oid) 41 | - ) 42 | -$$ LANGUAGE sql; 43 | - 44 | --- is_partition_of( child_schema, child_table, parent_schema, parent_table, description ) 45 | -CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, NAME, NAME, TEXT ) 46 | -RETURNS TEXT AS $$ 47 | - SELECT ok( _partof($1, $2, $3, $4), $5); 48 | -$$ LANGUAGE sql; 49 | - 50 | --- is_partition_of( child_schema, child_table, parent_schema, parent_table ) 51 | -CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, NAME, NAME ) 52 | -RETURNS TEXT AS $$ 53 | - SELECT ok( 54 | - _partof($1, $2, $3, $4), 55 | - 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should be a partition of ' 56 | - || quote_ident($3) || '.' || quote_ident($4) 57 | - ); 58 | -$$ LANGUAGE sql; 59 | - 60 | --- is_partition_of( child_table, parent_table, description ) 61 | -CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, TEXT ) 62 | -RETURNS TEXT AS $$ 63 | - SELECT ok( _partof($1, $2), $3); 64 | -$$ LANGUAGE sql; 65 | - 66 | --- is_partition_of( child_table, parent_table ) 67 | -CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME ) 68 | -RETURNS TEXT AS $$ 69 | - SELECT ok( 70 | - _partof($1, $2), 71 | - 'Table ' || quote_ident($1) || ' should be a partition of ' || quote_ident($2) 72 | - ); 73 | -$$ LANGUAGE sql; 74 | - 75 | --- _parts(schema, table) 76 | -CREATE OR REPLACE FUNCTION _parts( NAME, NAME ) 77 | -RETURNS SETOF NAME AS $$ 78 | - SELECT i.inhrelid::regclass::name 79 | - FROM pg_catalog.pg_namespace n 80 | - JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace 81 | - JOIN pg_catalog.pg_inherits i ON c.oid = i.inhparent 82 | - WHERE n.nspname = $1 83 | - AND c.relname = $2 84 | - AND c.relkind = 'p' 85 | -$$ LANGUAGE SQL; 86 | - 87 | --- _parts(table) 88 | -CREATE OR REPLACE FUNCTION _parts( NAME ) 89 | -RETURNS SETOF NAME AS $$ 90 | - SELECT i.inhrelid::regclass::name 91 | - FROM pg_catalog.pg_class c 92 | - JOIN pg_catalog.pg_inherits i ON c.oid = i.inhparent 93 | - WHERE c.relname = $1 94 | - AND c.relkind = 'p' 95 | - AND pg_catalog.pg_table_is_visible(c.oid) 96 | -$$ LANGUAGE SQL; 97 | - 98 | --- partitions_are( schema, table, partitions, description ) 99 | -CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME, NAME[], TEXT ) 100 | -RETURNS TEXT AS $$ 101 | - SELECT _are( 102 | - 'partitions', 103 | - ARRAY(SELECT _parts($1, $2) EXCEPT SELECT unnest($3)), 104 | - ARRAY(SELECT unnest($3) EXCEPT SELECT _parts($1, $2)), 105 | - $4 106 | - ); 107 | -$$ LANGUAGE SQL; 108 | - 109 | --- partitions_are( schema, table, partitions ) 110 | -CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME, NAME[] ) 111 | -RETURNS TEXT AS $$ 112 | - SELECT partitions_are( 113 | - $1, $2, $3, 114 | - 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct partitions' 115 | - ); 116 | -$$ LANGUAGE SQL; 117 | - 118 | --- partitions_are( table, partitions, description ) 119 | -CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME[], TEXT ) 120 | -RETURNS TEXT AS $$ 121 | - SELECT _are( 122 | - 'partitions', 123 | - ARRAY(SELECT _parts($1) EXCEPT SELECT unnest($2)), 124 | - ARRAY(SELECT unnest($2) EXCEPT SELECT _parts($1)), 125 | - $3 126 | - ); 127 | -$$ LANGUAGE SQL; 128 | - 129 | --- partitions_are( table, partitions ) 130 | -CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME[] ) 131 | -RETURNS TEXT AS $$ 132 | - SELECT partitions_are( 133 | - $1, $2, 134 | - 'Table ' || quote_ident($1) || ' should have the correct partitions' 135 | - ); 136 | -$$ LANGUAGE SQL; 137 | -------------------------------------------------------------------------------- /compat/gencore: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | use warnings; 5 | 6 | my $invert = shift; 7 | my %keep = map { chomp; $_ => 1 } ; 8 | my ($name, $type) = $invert ? ('Schema', 'schema-testing') : ('Core', 'assertion'); 9 | 10 | print qq{ 11 | -- This file defines pgTAP $name, a portable collection of $type 12 | -- functions for TAP-based unit testing on PostgreSQL 9.1 or higher. It is 13 | -- distributed under the revised FreeBSD license. The home page for the pgTAP 14 | -- project is: 15 | 16 | -- 17 | -- https://pgtap.org/ 18 | -- 19 | 20 | }; 21 | 22 | print "-- Requires pgtap-core.sql\n--\n" if $invert; 23 | 24 | my $print = 0; 25 | while (<>) { 26 | if (/^CREATE OR REPLACE \w+ (\w+)/) { 27 | if ($1 eq 'os_name' || $1 eq 'pg_typeof') { 28 | # Never keep this one. 29 | $print = 0; 30 | } elsif ($invert ? !$keep{$1} : $keep{$1}) { 31 | $print = 1; 32 | print; 33 | } else { 34 | $print = 0; 35 | } 36 | } else { 37 | print if $print; 38 | } 39 | } 40 | 41 | __DATA__ 42 | pg_version 43 | pg_version_num 44 | pgtap_version 45 | plan 46 | no_plan 47 | _get 48 | _get_latest 49 | _get_note 50 | _set 51 | _add 52 | add_result 53 | num_failed 54 | _finish 55 | finish 56 | diag 57 | diag_test_name 58 | ok 59 | is 60 | isnt 61 | _alike 62 | matches 63 | imatches 64 | alike 65 | ialike 66 | _unalike 67 | doesnt_match 68 | doesnt_imatch 69 | unalike 70 | unialike 71 | cmp_ok 72 | pass 73 | fail 74 | todo 75 | todo_start 76 | in_todo 77 | todo_end 78 | _todo 79 | skip 80 | _query 81 | throws_ok 82 | lives_ok 83 | performs_ok 84 | performs_within 85 | _time_trial_type 86 | _time_trials 87 | _ident_array_to_string 88 | _prokind 89 | tap_funky 90 | _funkargs 91 | _got_func 92 | has_function 93 | hasnt_function 94 | _pg_sv_type_array 95 | can 96 | _has_type 97 | has_type 98 | hasnt_type 99 | has_domain 100 | hasnt_domain 101 | has_enum 102 | hasnt_enum 103 | enum_has_labels 104 | display_type 105 | _cmp_types 106 | _cast_exists 107 | has_cast 108 | hasnt_cast 109 | _expand_context 110 | _get_context 111 | cast_context_is 112 | _op_exists 113 | has_operator 114 | has_leftop 115 | has_rightop 116 | _is_trusted 117 | has_language 118 | hasnt_language 119 | language_is_trusted 120 | _opc_exists 121 | has_opclass 122 | hasnt_opclass 123 | _nosuch 124 | _func_compare 125 | _lang 126 | function_lang_is 127 | _returns 128 | function_returns 129 | _definer 130 | is_definer 131 | isnt_definer 132 | _type_func 133 | is_aggregate 134 | isnt_aggregate 135 | is_normal_function 136 | isnt_normal_function 137 | is_window 138 | isnt_window 139 | is_procedure 140 | isnt_procedure 141 | _strict 142 | is_strict 143 | isnt_strict 144 | _expand_vol 145 | _refine_vol 146 | _vol 147 | volatility_is 148 | findfuncs 149 | _runem 150 | _is_verbose 151 | do_tap 152 | _currtest 153 | _cleanup 154 | _runner 155 | runtests 156 | _temptable 157 | _temptypes 158 | _docomp 159 | _relcomp 160 | set_eq 161 | bag_eq 162 | _do_ne 163 | _relne 164 | set_ne 165 | bag_ne 166 | set_has 167 | bag_has 168 | set_hasnt 169 | bag_hasnt 170 | results_eq 171 | results_ne 172 | isa_ok 173 | is_empty 174 | collect_tap 175 | _tlike 176 | throws_like 177 | throws_ilike 178 | throws_matching 179 | throws_imatching 180 | _dexists 181 | _get_dtype 182 | domain_type_is 183 | domain_type_isnt 184 | row_eq 185 | _error_diag 186 | 187 | -------------------------------------------------------------------------------- /compat/install-9.1.patch: -------------------------------------------------------------------------------- 1 | --- sql/pgtap.sql 2 | +++ sql/pgtap.sql 3 | @@ -781,10 +781,6 @@ 4 | RETURN ok( TRUE, descr ); 5 | EXCEPTION WHEN OTHERS THEN 6 | -- There should have been no exception. 7 | - GET STACKED DIAGNOSTICS 8 | - detail = PG_EXCEPTION_DETAIL, 9 | - hint = PG_EXCEPTION_HINT, 10 | - context = PG_EXCEPTION_CONTEXT; 11 | RETURN ok( FALSE, descr ) || E'\n' || diag( 12 | ' died: ' || _error_diag(SQLSTATE, SQLERRM, detail, hint, context, schname, tabname, colname, chkname, typname) 13 | ); 14 | @@ -6732,10 +6728,6 @@ 15 | -- Something went wrong. Record that fact. 16 | errstate := SQLSTATE; 17 | errmsg := SQLERRM; 18 | - GET STACKED DIAGNOSTICS 19 | - detail = PG_EXCEPTION_DETAIL, 20 | - hint = PG_EXCEPTION_HINT, 21 | - context = PG_EXCEPTION_CONTEXT; 22 | END; 23 | 24 | -- Always raise an exception to rollback any changes. 25 | @@ -7203,7 +7195,6 @@ 26 | RETURN ok( true, $3 ); 27 | EXCEPTION 28 | WHEN datatype_mismatch THEN 29 | - GET STACKED DIAGNOSTICS err_msg = MESSAGE_TEXT; 30 | RETURN ok( false, $3 ) || E'\n' || diag( 31 | E' Number of columns or their types differ between the queries' || 32 | CASE WHEN have_rec::TEXT = want_rec::text THEN '' ELSE E':\n' || 33 | @@ -7357,7 +7348,6 @@ 34 | RETURN ok( false, $3 ); 35 | EXCEPTION 36 | WHEN datatype_mismatch THEN 37 | - GET STACKED DIAGNOSTICS err_msg = MESSAGE_TEXT; 38 | RETURN ok( false, $3 ) || E'\n' || diag( 39 | E' Number of columns or their types differ between the queries' || 40 | CASE WHEN have_rec::TEXT = want_rec::text THEN '' ELSE E':\n' || 41 | -------------------------------------------------------------------------------- /compat/install-9.2.patch: -------------------------------------------------------------------------------- 1 | --- sql/pgtap.sql 2 | +++ sql/pgtap.sql 3 | @@ -784,12 +784,7 @@ 4 | GET STACKED DIAGNOSTICS 5 | detail = PG_EXCEPTION_DETAIL, 6 | hint = PG_EXCEPTION_HINT, 7 | - context = PG_EXCEPTION_CONTEXT, 8 | - schname = SCHEMA_NAME, 9 | - tabname = TABLE_NAME, 10 | - colname = COLUMN_NAME, 11 | - chkname = CONSTRAINT_NAME, 12 | - typname = PG_DATATYPE_NAME; 13 | + context = PG_EXCEPTION_CONTEXT; 14 | RETURN ok( FALSE, descr ) || E'\n' || diag( 15 | ' died: ' || _error_diag(SQLSTATE, SQLERRM, detail, hint, context, schname, tabname, colname, chkname, typname) 16 | ); 17 | @@ -6740,12 +6735,7 @@ 18 | GET STACKED DIAGNOSTICS 19 | detail = PG_EXCEPTION_DETAIL, 20 | hint = PG_EXCEPTION_HINT, 21 | - context = PG_EXCEPTION_CONTEXT, 22 | - schname = SCHEMA_NAME, 23 | - tabname = TABLE_NAME, 24 | - colname = COLUMN_NAME, 25 | - chkname = CONSTRAINT_NAME, 26 | - typname = PG_DATATYPE_NAME; 27 | + context = PG_EXCEPTION_CONTEXT; 28 | END; 29 | 30 | -- Always raise an exception to rollback any changes. 31 | -------------------------------------------------------------------------------- /compat/install-9.6.patch: -------------------------------------------------------------------------------- 1 | --- sql/pgtap.sql 2 | +++ sql/pgtap.sql 3 | @@ -10266,136 +10266,6 @@ 4 | ); 5 | $$ LANGUAGE sql; 6 | 7 | --- _partof( child_schema, child_table, parent_schema, parent_table ) 8 | -CREATE OR REPLACE FUNCTION _partof ( NAME, NAME, NAME, NAME ) 9 | -RETURNS BOOLEAN AS $$ 10 | - SELECT EXISTS( 11 | - SELECT true 12 | - FROM pg_catalog.pg_namespace cn 13 | - JOIN pg_catalog.pg_class cc ON cn.oid = cc.relnamespace 14 | - JOIN pg_catalog.pg_inherits i ON cc.oid = i.inhrelid 15 | - JOIN pg_catalog.pg_class pc ON i.inhparent = pc.oid 16 | - JOIN pg_catalog.pg_namespace pn ON pc.relnamespace = pn.oid 17 | - WHERE cn.nspname = $1 18 | - AND cc.relname = $2 19 | - AND cc.relispartition 20 | - AND pn.nspname = $3 21 | - AND pc.relname = $4 22 | - AND pc.relkind = 'p' 23 | - ) 24 | -$$ LANGUAGE sql; 25 | - 26 | --- _partof( child_table, parent_table ) 27 | -CREATE OR REPLACE FUNCTION _partof ( NAME, NAME ) 28 | -RETURNS BOOLEAN AS $$ 29 | - SELECT EXISTS( 30 | - SELECT true 31 | - FROM pg_catalog.pg_class cc 32 | - JOIN pg_catalog.pg_inherits i ON cc.oid = i.inhrelid 33 | - JOIN pg_catalog.pg_class pc ON i.inhparent = pc.oid 34 | - WHERE cc.relname = $1 35 | - AND cc.relispartition 36 | - AND pc.relname = $2 37 | - AND pc.relkind = 'p' 38 | - AND pg_catalog.pg_table_is_visible(cc.oid) 39 | - AND pg_catalog.pg_table_is_visible(pc.oid) 40 | - ) 41 | -$$ LANGUAGE sql; 42 | - 43 | --- is_partition_of( child_schema, child_table, parent_schema, parent_table, description ) 44 | -CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, NAME, NAME, TEXT ) 45 | -RETURNS TEXT AS $$ 46 | - SELECT ok( _partof($1, $2, $3, $4), $5); 47 | -$$ LANGUAGE sql; 48 | - 49 | --- is_partition_of( child_schema, child_table, parent_schema, parent_table ) 50 | -CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, NAME, NAME ) 51 | -RETURNS TEXT AS $$ 52 | - SELECT ok( 53 | - _partof($1, $2, $3, $4), 54 | - 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should be a partition of ' 55 | - || quote_ident($3) || '.' || quote_ident($4) 56 | - ); 57 | -$$ LANGUAGE sql; 58 | - 59 | --- is_partition_of( child_table, parent_table, description ) 60 | -CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME, TEXT ) 61 | -RETURNS TEXT AS $$ 62 | - SELECT ok( _partof($1, $2), $3); 63 | -$$ LANGUAGE sql; 64 | - 65 | --- is_partition_of( child_table, parent_table ) 66 | -CREATE OR REPLACE FUNCTION is_partition_of ( NAME, NAME ) 67 | -RETURNS TEXT AS $$ 68 | - SELECT ok( 69 | - _partof($1, $2), 70 | - 'Table ' || quote_ident($1) || ' should be a partition of ' || quote_ident($2) 71 | - ); 72 | -$$ LANGUAGE sql; 73 | - 74 | --- _parts(schema, table) 75 | -CREATE OR REPLACE FUNCTION _parts( NAME, NAME ) 76 | -RETURNS SETOF NAME AS $$ 77 | - SELECT i.inhrelid::regclass::name 78 | - FROM pg_catalog.pg_namespace n 79 | - JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace 80 | - JOIN pg_catalog.pg_inherits i ON c.oid = i.inhparent 81 | - WHERE n.nspname = $1 82 | - AND c.relname = $2 83 | - AND c.relkind = 'p' 84 | -$$ LANGUAGE SQL; 85 | - 86 | --- _parts(table) 87 | -CREATE OR REPLACE FUNCTION _parts( NAME ) 88 | -RETURNS SETOF NAME AS $$ 89 | - SELECT i.inhrelid::regclass::name 90 | - FROM pg_catalog.pg_class c 91 | - JOIN pg_catalog.pg_inherits i ON c.oid = i.inhparent 92 | - WHERE c.relname = $1 93 | - AND c.relkind = 'p' 94 | - AND pg_catalog.pg_table_is_visible(c.oid) 95 | -$$ LANGUAGE SQL; 96 | - 97 | --- partitions_are( schema, table, partitions, description ) 98 | -CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME, NAME[], TEXT ) 99 | -RETURNS TEXT AS $$ 100 | - SELECT _are( 101 | - 'partitions', 102 | - ARRAY(SELECT _parts($1, $2) EXCEPT SELECT unnest($3)), 103 | - ARRAY(SELECT unnest($3) EXCEPT SELECT _parts($1, $2)), 104 | - $4 105 | - ); 106 | -$$ LANGUAGE SQL; 107 | - 108 | --- partitions_are( schema, table, partitions ) 109 | -CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME, NAME[] ) 110 | -RETURNS TEXT AS $$ 111 | - SELECT partitions_are( 112 | - $1, $2, $3, 113 | - 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct partitions' 114 | - ); 115 | -$$ LANGUAGE SQL; 116 | - 117 | --- partitions_are( table, partitions, description ) 118 | -CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME[], TEXT ) 119 | -RETURNS TEXT AS $$ 120 | - SELECT _are( 121 | - 'partitions', 122 | - ARRAY(SELECT _parts($1) EXCEPT SELECT unnest($2)), 123 | - ARRAY(SELECT unnest($2) EXCEPT SELECT _parts($1)), 124 | - $3 125 | - ); 126 | -$$ LANGUAGE SQL; 127 | - 128 | --- partitions_are( table, partitions ) 129 | -CREATE OR REPLACE FUNCTION partitions_are( NAME, NAME[] ) 130 | -RETURNS TEXT AS $$ 131 | - SELECT partitions_are( 132 | - $1, $2, 133 | - 'Table ' || quote_ident($1) || ' should have the correct partitions' 134 | - ); 135 | -$$ LANGUAGE SQL; 136 | - 137 | CREATE OR REPLACE FUNCTION _ident_array_to_sorted_string( name[], text ) 138 | RETURNS text AS $$ 139 | SELECT array_to_string(ARRAY( 140 | -------------------------------------------------------------------------------- /contrib/pgtap.spec: -------------------------------------------------------------------------------- 1 | Summary: Unit testing suite for PostgreSQL 2 | Name: pgtap 3 | Version: 1.3.4 4 | Release: 1%{?dist} 5 | Group: Applications/Databases 6 | License: PostgreSQL 7 | URL: https://pgtap.org/ 8 | Source0: https://api.pgxn.org/dist/pgtap/%{version}/pgtap-%{version}.zip 9 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root 10 | Provides: %{name} 11 | Provides: %{name}-core 12 | Provides: %{name}-schema 13 | 14 | %description 15 | pgTAP is a unit testing framework for PostgreSQL written in PL/pgSQL and 16 | PL/SQL. It includes a comprehensive collection of TAP-emitting assertion 17 | functions, as well as the ability to integrate with other TAP-emitting test 18 | frameworks. It can also be used in the xUnit testing style. 19 | 20 | %define postgresver %(pg_config --version|awk '{print $2}'| cut -d. -f1,2) 21 | Requires: postgresql-server = %{postgresver}, perl-Test-Harness >= 3.0 22 | Requires: perl(TAP::Parser::SourceHandler::pgTAP) 23 | BuildRequires: postgresql-devel = %{postgresver} 24 | 25 | %prep 26 | %setup -q 27 | 28 | %build 29 | make 30 | 31 | %install 32 | %{__rm} -rf %{buildroot} 33 | make install USE_PGXS=1 DESTDIR=%{buildroot} 34 | 35 | %clean 36 | %{__rm} -rf %{buildroot} 37 | 38 | %files 39 | %defattr(-,root,root,-) 40 | %{_datadir}/pgsql/contrib/* 41 | %{_docdir}/pgsql/contrib/README.pgtap 42 | 43 | %changelog 44 | * Mon Apr 8 2024 David E. Wheeler 1.3.4-1 45 | - Update to 1.3.4 46 | 47 | * Sun Feb 4 2024 David E. Wheeler 1.3.2-1 48 | - Update to 1.3.2 49 | 50 | * Sun Sep 24 2023 David E. Wheeler 1.3.1-1 51 | - Update to 1.3.1 52 | 53 | * Mon Aug 14 2023 David E. Wheeler 1.3.0-1 54 | - Update to 1.3.0 55 | 56 | * Sun Dec 5 2021 David E. Wheeler 1.2.0-1 57 | - Update to 1.2.0 58 | 59 | * Sat Oct 24 2020 Jim Nasby 1.1.0-2 60 | - Remove last vestiges of pre-PostgreSQL 9.1 61 | - Use https for URLs 62 | 63 | * Mon Nov 25 2019 Jim Nasby 1.1.0-1 64 | - Update to 1.1.0 65 | - Remove support for PostgreSQL prior to 9.1 66 | 67 | * Thu Feb 21 2019 Jim Nasby 1.0.0-1 68 | - Update to 1.0.0 69 | 70 | * Sun Sep 16 2018 David E. Wheeler 0.99.0-1 71 | - Update to v0.99.0. 72 | 73 | * Mon Nov 6 2017 David E. Wheeler 0.98.0-1 74 | - Update to v0.98.0. 75 | - Added pgTAP harness Perl module requirement. 76 | - Added explicit list of provided features. 77 | 78 | * Mon Jan 28 2013 David Wheeler 0.93.0 79 | - Upgraded to pgTAP 0.93.0 80 | 81 | * Tue Jan 15 2013 David E. Wheeler 0.92.0-1 82 | - Upgraded to pgTAP 0.92.0 83 | 84 | * Tue Aug 23 2011 David Wheeler 0.91.0 85 | - Removed USE_PGXS from Makefile; it has not been supported in some time. 86 | - Removed TAPSCHEMA from Makefile; use PGOPTIONS=--search_path=tap with 87 | psql instead. 88 | 89 | * Tue Feb 01 2011 David Wheeler 0.25.0 90 | - Removed pg_prove and pg_tapgen, which are now distributed via CPAN. 91 | 92 | * Sun Mar 01 2010 Darrell Fuhriman 0.24-2 93 | - Make install work where the pgtap.so library is needed. 94 | 95 | * Sun Dec 27 2009 David Wheeler 0.24-1 96 | - Updated Source URL to a more predictable format. 97 | 98 | * Mon Aug 24 2009 David Fetter 0.23-1 99 | - Got corrected .spec from Devrim GUNDUZ 100 | - Bumped version to 0.23. 101 | 102 | * Wed Aug 19 2009 Darrell Fuhriman 0.22-1 103 | - initial RPM 104 | 105 | -------------------------------------------------------------------------------- /pgtap.control: -------------------------------------------------------------------------------- 1 | # pgTAP extension 2 | comment = 'Unit testing for PostgreSQL' 3 | default_version = '1.3.4' 4 | module_pathname = 'pgtap' 5 | requires = 'plpgsql' 6 | relocatable = true 7 | superuser = false 8 | -------------------------------------------------------------------------------- /release.md: -------------------------------------------------------------------------------- 1 | pgTAP Release Management 2 | ======================== 3 | 4 | Here are the steps to take to make a release of pgTAP: 5 | 6 | * Review and fix any open bugs in the 7 | [issue tracker](https://github.com/theory/pgtap/issues). 8 | 9 | * Review and merge any appropriate 10 | [pull requests](https://github.com/theory/pgtap/pulls). 11 | 12 | * Make sure that [all tests](https://github.com/theory/pgtap/actions) pass on 13 | all supported versions of Postgres. If you want to run the tests manually, 14 | you can use the [pgxn-utils Docker image](https://github.com/pgxn/docker-pgxn-tools) 15 | or [pgenv](https://github.com/theory/pgenv/) to install and 16 | switch between versions. For each version, ensure that: 17 | 18 | + Patches apply cleanly (try to eliminate Hunk warnings for patches to 19 | `pgtap.sql` itself, usually by fixing line numbers) 20 | 21 | + All files are installed. 22 | 23 | + `ALTER EXTENSION pgtap UPDATE;` works. 24 | 25 | + `CREATE EXTENSION pgtap;` works. 26 | 27 | + All tests pass in `make installcheck`. 28 | 29 | * If you've made any significant changes while testing versions backward, test 30 | them again in forward order (9.1, 9.2, 9.3, etc.) to make sure the changes 31 | didn't break any later versions. 32 | 33 | * Review the documentation in `doc/pgtap.mmd`, and make any necessary changes, 34 | including to the list of PostgreSQL version-compatibility notes at the end 35 | of the document. 36 | 37 | * Add an item to the top of the `%changelog` section of `contrib/pgtap.spec`. 38 | It should use the version you're about to release, as well as the date (use 39 | `date +'%a %b %d %Y'`) and your name and email address. Add at least one 40 | bullet mentioning the upgrade. 41 | 42 | * Run `make html` (you'll need 43 | [MultiMarkdown](https://fletcherpenney.net/multimarkdown/) (Homebrew: 44 | `brew install multimarkdown`) in your path and the 45 | [Pod::Simple::XHTML](https://metacpan.org/module/Pod::Simple::XHTML) 46 | (Homebrew: `brew install cpanm && cpanm Pod::Simple::XHTML`) Perl module 47 | installed), then checkout the `gh-pages` branch and make these changes: 48 | 49 | + `cp .documentation.html.template documentation.html`. Edit 50 | documentation.html, the main div should look like this: 51 | 52 |
53 | 54 | 55 |
56 | 57 | 58 |
59 | 60 | 61 |
62 | 63 | + Copy the first `

` and `

` from `doc/pgtap.html` into the 64 | `DOCS INTRO HERE` section. 65 | 66 | + Copy the rest of `doc/pgtap.html` into the 67 | `DOCS HERE, WITH INTRO MOVED ABOVE` section. 68 | 69 | + Copy the entire contents of `doc/toc.html` into the 70 | `DOC SANS pgTAP x.xx` section, and then remove the first `

  • ` element that 71 | says "pgTAP x.xx". 72 | 73 | + Review to ensure that everything looks right; use `git diff` to make sure 74 | nothing important was lost. It should mainly be additions. 75 | 76 | + Commit the changes, but don't push them yet. 77 | 78 | * Go back to the `main` branch and proofread the additions to the `Changes` 79 | file since the last release. Make sure all relevant changes are recorded 80 | there, and that any typos or formatting errors are corrected. 81 | 82 | * Timestamp the `Changes` file. I generate the timestamp like so: 83 | 84 | perl -MDateTime -e 'print DateTime->now->datetime . "Z\n"' 85 | 86 | Paste that into the line with the new version, maybe increment by a minute 87 | to account for the time you'll need to actually do the release. 88 | 89 | * Commit the timestamp and push it: 90 | 91 | git ci -m 'Timestamp v0.98.0.' 92 | git push 93 | 94 | * Once again make sure [all tests](https://github.com/theory/pgtap/actions) 95 | pass. Fix any that fail. 96 | 97 | * Once all tests pass, tag the release with its semantic version (including 98 | the leading `v`) and push the tag. 99 | 100 | git tag -sm 'Tag v0.98.0.' v0.98.0 101 | git push --tags 102 | 103 | * Monitor the [release workflow](https://github.com/theory/pgtap/actions/workflows/release.yml) 104 | to make sure the new version is released on both PGXN and GitHub. 105 | 106 | * Push the `gh-pages` branch: 107 | 108 | git push 109 | 110 | * Increment the minor version to kick off development for the next release. 111 | The version should be added to the `Changes` file, and incremented in the 112 | following files: 113 | 114 | + `META.json` (including for the three parts of the `provides` section) 115 | + `README.md` 116 | + `contrib/pgtap.spec` 117 | + `doc/pgtap.mmd` 118 | + `pgtap.control` 119 | 120 | * Commit that change and push it. 121 | 122 | git ci -m 'Increment to v1.0.1.' 123 | git push 124 | 125 | * Start hacking on the next version! 126 | -------------------------------------------------------------------------------- /sql/pgtap--0.90.0--0.91.0.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION pgtap_version() 2 | RETURNS NUMERIC AS 'SELECT 0.91;' 3 | LANGUAGE SQL IMMUTABLE; 4 | 5 | CREATE OR REPLACE FUNCTION has_tablespace( NAME, TEXT, TEXT ) 6 | RETURNS TEXT AS $$ 7 | BEGIN 8 | IF pg_version_num() >= 90200 THEN 9 | RETURN ok( 10 | EXISTS( 11 | SELECT true 12 | FROM pg_catalog.pg_tablespace 13 | WHERE spcname = $1 14 | AND pg_tablespace_location(oid) = $2 15 | ), $3 16 | ); 17 | ELSE 18 | RETURN ok( 19 | EXISTS( 20 | SELECT true 21 | FROM pg_catalog.pg_tablespace 22 | WHERE spcname = $1 23 | AND spclocation = $2 24 | ), $3 25 | ); 26 | END IF; 27 | END; 28 | $$ LANGUAGE plpgsql; 29 | 30 | -------------------------------------------------------------------------------- /sql/pgtap--0.93.0--0.94.0.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION pgtap_version() 2 | RETURNS NUMERIC AS 'SELECT 0.94;' 3 | LANGUAGE SQL IMMUTABLE; 4 | 5 | CREATE OR REPLACE FUNCTION _get_func_privs(TEXT, TEXT) 6 | RETURNS TEXT[] AS $$ 7 | BEGIN 8 | IF pg_catalog.has_function_privilege($1, $2, 'EXECUTE') THEN 9 | RETURN '{EXECUTE}'; 10 | ELSE 11 | RETURN '{}'; 12 | END IF; 13 | EXCEPTION 14 | -- Not a valid func name. 15 | WHEN undefined_function THEN RETURN '{undefined_function}'; 16 | -- Not a valid role. 17 | WHEN undefined_object THEN RETURN '{undefined_role}'; 18 | END; 19 | $$ LANGUAGE plpgsql; 20 | 21 | CREATE OR REPLACE FUNCTION _fprivs_are ( TEXT, NAME, NAME[], TEXT ) 22 | RETURNS TEXT AS $$ 23 | DECLARE 24 | grants TEXT[] := _get_func_privs($2, $1); 25 | BEGIN 26 | IF grants[1] = 'undefined_function' THEN 27 | RETURN ok(FALSE, $4) || E'\n' || diag( 28 | ' Function ' || $1 || ' does not exist' 29 | ); 30 | ELSIF grants[1] = 'undefined_role' THEN 31 | RETURN ok(FALSE, $4) || E'\n' || diag( 32 | ' Role ' || quote_ident($2) || ' does not exist' 33 | ); 34 | END IF; 35 | RETURN _assets_are('privileges', grants, $3, $4); 36 | END; 37 | $$ LANGUAGE plpgsql; 38 | 39 | -- has_table( schema, table ) 40 | CREATE OR REPLACE FUNCTION has_table ( NAME, NAME ) 41 | RETURNS TEXT AS $$ 42 | SELECT ok( 43 | _rexists( 'r', $1, $2 ), 44 | 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' 45 | ); 46 | $$ LANGUAGE SQL; 47 | 48 | -- hasnt_table( schema, table ) 49 | CREATE OR REPLACE FUNCTION hasnt_table ( NAME, NAME ) 50 | RETURNS TEXT AS $$ 51 | SELECT ok( 52 | NOT _rexists( 'r', $1, $2 ), 53 | 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' 54 | ); 55 | $$ LANGUAGE SQL; 56 | 57 | -- has_foreign_table( schema, table ) 58 | CREATE OR REPLACE FUNCTION has_foreign_table ( NAME, NAME ) 59 | RETURNS TEXT AS $$ 60 | SELECT ok( 61 | _rexists( 'f', $1, $2 ), 62 | 'Foreign table ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' 63 | ); 64 | $$ LANGUAGE SQL; 65 | 66 | -- hasnt_foreign_table( schema, table ) 67 | CREATE OR REPLACE FUNCTION hasnt_foreign_table ( NAME, NAME ) 68 | RETURNS TEXT AS $$ 69 | SELECT ok( 70 | NOT _rexists( 'f', $1, $2 ), 71 | 'Foreign table ' || quote_ident($1) || '.' || quote_ident($2) || ' not should exist' 72 | ); 73 | $$ LANGUAGE SQL; 74 | 75 | CREATE OR REPLACE FUNCTION skip ( why text, how_many int ) 76 | RETURNS TEXT AS $$ 77 | DECLARE 78 | output TEXT[]; 79 | BEGIN 80 | output := '{}'; 81 | FOR i IN 1..how_many LOOP 82 | output = array_append( 83 | output, 84 | ok( TRUE ) || ' ' || diag( 'SKIP' || COALESCE( ' ' || why, '') ) 85 | ); 86 | END LOOP; 87 | RETURN array_to_string(output, E'\n'); 88 | END; 89 | $$ LANGUAGE plpgsql; 90 | 91 | CREATE OR REPLACE FUNCTION skip ( text ) 92 | RETURNS TEXT AS $$ 93 | SELECT ok( TRUE ) || ' ' || diag( 'SKIP' || COALESCE(' ' || $1, '') ); 94 | $$ LANGUAGE sql; 95 | 96 | -- check_test( test_output, pass, name, description, diag, match_diag ) 97 | CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT, BOOLEAN ) 98 | RETURNS SETOF TEXT AS $$ 99 | DECLARE 100 | tnumb INTEGER; 101 | aok BOOLEAN; 102 | adescr TEXT; 103 | res BOOLEAN; 104 | descr TEXT; 105 | adiag TEXT; 106 | have ALIAS FOR $1; 107 | eok ALIAS FOR $2; 108 | name ALIAS FOR $3; 109 | edescr ALIAS FOR $4; 110 | ediag ALIAS FOR $5; 111 | matchit ALIAS FOR $6; 112 | BEGIN 113 | -- What test was it that just ran? 114 | tnumb := currval('__tresults___numb_seq'); 115 | 116 | -- Fetch the results. 117 | EXECUTE 'SELECT aok, descr FROM __tresults__ WHERE numb = ' || tnumb 118 | INTO aok, adescr; 119 | 120 | -- Now delete those results. 121 | EXECUTE 'DELETE FROM __tresults__ WHERE numb = ' || tnumb; 122 | EXECUTE 'ALTER SEQUENCE __tresults___numb_seq RESTART WITH ' || tnumb; 123 | 124 | -- Set up the description. 125 | descr := coalesce( name || ' ', 'Test ' ) || 'should '; 126 | 127 | -- So, did the test pass? 128 | RETURN NEXT is( 129 | aok, 130 | eok, 131 | descr || CASE eok WHEN true then 'pass' ELSE 'fail' END 132 | ); 133 | 134 | -- Was the description as expected? 135 | IF edescr IS NOT NULL THEN 136 | RETURN NEXT is( 137 | adescr, 138 | edescr, 139 | descr || 'have the proper description' 140 | ); 141 | END IF; 142 | 143 | -- Were the diagnostics as expected? 144 | IF ediag IS NOT NULL THEN 145 | -- Remove ok and the test number. 146 | adiag := substring( 147 | have 148 | FROM CASE WHEN aok THEN 4 ELSE 9 END + char_length(tnumb::text) 149 | ); 150 | 151 | -- Remove the description, if there is one. 152 | IF adescr <> '' THEN 153 | adiag := substring( 154 | adiag FROM 1 + char_length( ' - ' || substr(diag( adescr ), 3) ) 155 | ); 156 | END IF; 157 | 158 | IF NOT aok THEN 159 | -- Remove failure message from ok(). 160 | adiag := substring(adiag FROM 1 + char_length(diag( 161 | 'Failed test ' || tnumb || 162 | CASE adescr WHEN '' THEN '' ELSE COALESCE(': "' || adescr || '"', '') END 163 | ))); 164 | END IF; 165 | 166 | IF ediag <> '' THEN 167 | -- Remove the space before the diagnostics. 168 | adiag := substring(adiag FROM 2); 169 | END IF; 170 | 171 | -- Remove the #s. 172 | adiag := replace( substring(adiag from 3), E'\n# ', E'\n' ); 173 | 174 | -- Now compare the diagnostics. 175 | IF matchit THEN 176 | RETURN NEXT matches( 177 | adiag, 178 | ediag, 179 | descr || 'have the proper diagnostics' 180 | ); 181 | ELSE 182 | RETURN NEXT is( 183 | adiag, 184 | ediag, 185 | descr || 'have the proper diagnostics' 186 | ); 187 | END IF; 188 | END IF; 189 | 190 | -- And we're done 191 | RETURN; 192 | END; 193 | $$ LANGUAGE plpgsql; 194 | -------------------------------------------------------------------------------- /sql/pgtap--1.0.0--1.1.0.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION pgtap_version() 2 | RETURNS NUMERIC AS 'SELECT 1.1;' 3 | LANGUAGE SQL IMMUTABLE; 4 | 5 | 6 | -- These are now obsolete 7 | DROP FUNCTION col_not_null ( NAME, NAME ); 8 | DROP FUNCTION col_is_null ( NAME, NAME, NAME ); 9 | DROP FUNCTION col_is_null ( NAME, NAME ); 10 | 11 | -- _col_is_null( schema, table, column, desc, null ) 12 | CREATE OR REPLACE FUNCTION _col_is_null ( NAME, NAME, NAME, TEXT, bool ) 13 | RETURNS TEXT AS $$ 14 | DECLARE 15 | qcol CONSTANT text := quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3); 16 | c_desc CONSTANT text := coalesce( 17 | $4, 18 | 'Column ' || qcol || ' should ' 19 | || CASE WHEN $5 THEN 'be NOT' ELSE 'allow' END || ' NULL' 20 | ); 21 | BEGIN 22 | IF NOT _cexists( $1, $2, $3 ) THEN 23 | RETURN fail( c_desc ) || E'\n' 24 | || diag (' Column ' || qcol || ' does not exist' ); 25 | END IF; 26 | RETURN ok( 27 | EXISTS( 28 | SELECT true 29 | FROM pg_catalog.pg_namespace n 30 | JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace 31 | JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid 32 | WHERE n.nspname = $1 33 | AND c.relname = $2 34 | AND a.attnum > 0 35 | AND NOT a.attisdropped 36 | AND a.attname = $3 37 | AND a.attnotnull = $5 38 | ), c_desc 39 | ); 40 | END; 41 | $$ LANGUAGE plpgsql; 42 | 43 | -- _col_is_null( table, column, desc, null ) 44 | CREATE OR REPLACE FUNCTION _col_is_null ( NAME, NAME, TEXT, bool ) 45 | RETURNS TEXT AS $$ 46 | DECLARE 47 | qcol CONSTANT text := quote_ident($1) || '.' || quote_ident($2); 48 | c_desc CONSTANT text := coalesce( 49 | $3, 50 | 'Column ' || qcol || ' should ' 51 | || CASE WHEN $4 THEN 'be NOT' ELSE 'allow' END || ' NULL' 52 | ); 53 | BEGIN 54 | IF NOT _cexists( $1, $2 ) THEN 55 | RETURN fail( c_desc ) || E'\n' 56 | || diag (' Column ' || qcol || ' does not exist' ); 57 | END IF; 58 | RETURN ok( 59 | EXISTS( 60 | SELECT true 61 | FROM pg_catalog.pg_class c 62 | JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid 63 | WHERE pg_catalog.pg_table_is_visible(c.oid) 64 | AND c.relname = $1 65 | AND a.attnum > 0 66 | AND NOT a.attisdropped 67 | AND a.attname = $2 68 | AND a.attnotnull = $4 69 | ), c_desc 70 | ); 71 | END; 72 | $$ LANGUAGE plpgsql; 73 | 74 | -- col_not_null( schema, table, column, description ) 75 | -- col_not_null( schema, table, column ) 76 | CREATE OR REPLACE FUNCTION col_not_null ( 77 | schema_name NAME, table_name NAME, column_name NAME, description TEXT DEFAULT NULL 78 | ) RETURNS TEXT AS $$ 79 | SELECT _col_is_null( $1, $2, $3, $4, true ); 80 | $$ LANGUAGE SQL; 81 | 82 | -- col_not_null( table, column, description ) 83 | -- col_not_null( table, column ) 84 | CREATE OR REPLACE FUNCTION col_not_null ( 85 | table_name NAME, column_name NAME, description TEXT DEFAULT NULL 86 | ) RETURNS TEXT AS $$ 87 | SELECT _col_is_null( $1, $2, $3, true ); 88 | $$ LANGUAGE SQL; 89 | 90 | -- col_is_null( schema, table, column, description ) 91 | -- col_is_null( schema, table, column ) 92 | CREATE OR REPLACE FUNCTION col_is_null ( 93 | schema_name NAME, table_name NAME, column_name NAME, description TEXT DEFAULT NULL 94 | ) RETURNS TEXT AS $$ 95 | SELECT _col_is_null( $1, $2, $3, $4, false ); 96 | $$ LANGUAGE SQL; 97 | 98 | -- col_is_null( table, column, description ) 99 | -- col_is_null( table, column ) 100 | CREATE OR REPLACE FUNCTION col_is_null ( 101 | table_name NAME, column_name NAME, description TEXT DEFAULT NULL 102 | ) RETURNS TEXT AS $$ 103 | SELECT _col_is_null( $1, $2, $3, false ); 104 | $$ LANGUAGE SQL; 105 | 106 | -- _keys( schema, table, constraint_type ) 107 | CREATE OR REPLACE FUNCTION _keys ( NAME, NAME, CHAR ) 108 | RETURNS SETOF NAME[] AS $$ 109 | SELECT _pg_sv_column_array(x.conrelid,x.conkey) -- name[] doesn't support collation 110 | FROM pg_catalog.pg_namespace n 111 | JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace 112 | JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid 113 | WHERE n.nspname = $1 114 | AND c.relname = $2 115 | AND x.contype = $3 116 | ORDER BY 1 117 | $$ LANGUAGE sql; 118 | 119 | -- _keys( table, constraint_type ) 120 | CREATE OR REPLACE FUNCTION _keys ( NAME, CHAR ) 121 | RETURNS SETOF NAME[] AS $$ 122 | SELECT _pg_sv_column_array(x.conrelid,x.conkey) -- name[] doesn't support collation 123 | FROM pg_catalog.pg_class c 124 | JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid 125 | AND c.relname = $1 126 | AND x.contype = $2 127 | WHERE pg_catalog.pg_table_is_visible(c.oid) 128 | ORDER BY 1 129 | $$ LANGUAGE sql; 130 | 131 | 132 | -- finish 133 | DROP FUNCTION finish(); 134 | DROP FUNCTION _finish (INTEGER, INTEGER, INTEGER); 135 | 136 | CREATE OR REPLACE FUNCTION _finish (INTEGER, INTEGER, INTEGER, BOOLEAN DEFAULT NULL) 137 | RETURNS SETOF TEXT AS $$ 138 | DECLARE 139 | curr_test ALIAS FOR $1; 140 | exp_tests INTEGER := $2; 141 | num_faild ALIAS FOR $3; 142 | plural CHAR; 143 | raise_ex ALIAS FOR $4; 144 | BEGIN 145 | plural := CASE exp_tests WHEN 1 THEN '' ELSE 's' END; 146 | 147 | IF curr_test IS NULL THEN 148 | RAISE EXCEPTION '# No tests run!'; 149 | END IF; 150 | 151 | IF exp_tests = 0 OR exp_tests IS NULL THEN 152 | -- No plan. Output one now. 153 | exp_tests = curr_test; 154 | RETURN NEXT '1..' || exp_tests; 155 | END IF; 156 | 157 | IF curr_test <> exp_tests THEN 158 | RETURN NEXT diag( 159 | 'Looks like you planned ' || exp_tests || ' test' || 160 | plural || ' but ran ' || curr_test 161 | ); 162 | ELSIF num_faild > 0 THEN 163 | IF raise_ex THEN 164 | RAISE EXCEPTION '% test% failed of %', num_faild, CASE num_faild WHEN 1 THEN '' ELSE 's' END, exp_tests; 165 | END IF; 166 | RETURN NEXT diag( 167 | 'Looks like you failed ' || num_faild || ' test' || 168 | CASE num_faild WHEN 1 THEN '' ELSE 's' END 169 | || ' of ' || exp_tests 170 | ); 171 | ELSE 172 | 173 | END IF; 174 | RETURN; 175 | END; 176 | $$ LANGUAGE plpgsql; 177 | 178 | CREATE OR REPLACE FUNCTION finish (exception_on_failure BOOLEAN DEFAULT NULL) 179 | RETURNS SETOF TEXT AS $$ 180 | SELECT * FROM _finish( 181 | _get('curr_test'), 182 | _get('plan'), 183 | num_failed(), 184 | $1 185 | ); 186 | $$ LANGUAGE sql; 187 | -------------------------------------------------------------------------------- /sql/pgtap--1.3.1--1.3.2.sql: -------------------------------------------------------------------------------- 1 | DROP FUNCTION parse_type(type text, OUT typid oid, OUT typmod int4); 2 | 3 | CREATE OR REPLACE FUNCTION format_type_string ( TEXT ) 4 | RETURNS TEXT AS $$ 5 | DECLARE 6 | want_type TEXT := $1; 7 | typmodin_arg cstring[]; 8 | typmodin_func regproc; 9 | typmod int; 10 | BEGIN 11 | IF want_type::regtype = 'interval'::regtype THEN 12 | -- RAISE NOTICE 'cannot resolve: %', want_type; -- TODO 13 | RETURN want_type; 14 | END IF; 15 | 16 | -- Extract type modifier from type declaration and format as cstring[] literal. 17 | typmodin_arg := translate(substring(want_type FROM '[(][^")]+[)]'), '()', '{}'); 18 | 19 | -- Find typmodin function for want_type. 20 | SELECT typmodin INTO typmodin_func 21 | FROM pg_catalog.pg_type 22 | WHERE oid = want_type::regtype; 23 | 24 | IF typmodin_func = 0 THEN 25 | -- Easy: types without typemods. 26 | RETURN format_type(want_type::regtype, null); 27 | END IF; 28 | 29 | -- Get typemod via type-specific typmodin function. 30 | EXECUTE format('SELECT %I(%L)', typmodin_func, typmodin_arg) INTO typmod; 31 | RETURN format_type(want_type::regtype, typmod); 32 | EXCEPTION WHEN OTHERS THEN RETURN NULL; 33 | END; 34 | $$ LANGUAGE PLPGSQL STABLE; 35 | -------------------------------------------------------------------------------- /sql/pgtap--1.3.2--1.3.3.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION format_type_string ( TEXT ) 2 | RETURNS TEXT AS $$ 3 | DECLARE 4 | want_type TEXT := $1; 5 | BEGIN 6 | IF pg_version_num() >= 170000 THEN 7 | -- to_regtypemod() in 17 allows easy and corret normalization. 8 | RETURN format_type(to_regtype(want_type), to_regtypemod(want_type)); 9 | END IF; 10 | 11 | IF want_type::regtype = 'interval'::regtype THEN 12 | -- We cannot normlize interval types without to_regtypemod(), So 13 | -- just return it as is. 14 | RETURN want_type; 15 | END IF; 16 | 17 | -- Use the typmodin functions to correctly normalize types. 18 | DECLARE 19 | typmodin_arg cstring[]; 20 | typmodin_func regproc; 21 | typmod int; 22 | BEGIN 23 | -- Extract type modifier from type declaration and format as cstring[] literal. 24 | typmodin_arg := translate(substring(want_type FROM '[(][^")]+[)]'), '()', '{}'); 25 | 26 | -- Find typmodin function for want_type. 27 | SELECT typmodin INTO typmodin_func 28 | FROM pg_catalog.pg_type 29 | WHERE oid = want_type::regtype; 30 | 31 | IF typmodin_func = 0 THEN 32 | -- Easy: types without typemods. 33 | RETURN format_type(want_type::regtype, null); 34 | END IF; 35 | 36 | -- Get typemod via type-specific typmodin function. 37 | EXECUTE format('SELECT %s(%L)', typmodin_func, typmodin_arg) INTO typmod; 38 | RETURN format_type(want_type::regtype, typmod); 39 | END; 40 | EXCEPTION WHEN OTHERS THEN RETURN NULL; 41 | END; 42 | $$ LANGUAGE PLPGSQL STABLE; 43 | -------------------------------------------------------------------------------- /sql/pgtap--1.3.3--1.3.4.sql: -------------------------------------------------------------------------------- 1 | -- has_composite( schema, type ) 2 | CREATE OR REPLACE FUNCTION has_composite ( NAME, NAME ) 3 | RETURNS TEXT AS $$ 4 | SELECT has_composite( 5 | $1, $2, 6 | 'Composite type ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' 7 | ); 8 | $$ LANGUAGE SQL; 9 | 10 | -- hasnt_composite( schema, type ) 11 | CREATE OR REPLACE FUNCTION hasnt_composite ( NAME, NAME ) 12 | RETURNS TEXT AS $$ 13 | SELECT hasnt_composite( 14 | $1, $2, 15 | 'Composite type ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' 16 | ); 17 | $$ LANGUAGE SQL; 18 | 19 | -- index_is_partial( schema, table, index, description ) 20 | CREATE OR REPLACE FUNCTION index_is_partial ( NAME, NAME, NAME, text ) 21 | RETURNS TEXT AS $$ 22 | DECLARE 23 | res boolean; 24 | BEGIN 25 | SELECT x.indpred IS NOT NULL 26 | FROM pg_catalog.pg_index x 27 | JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid 28 | JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid 29 | JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace 30 | WHERE ct.relname = $2 31 | AND ci.relname = $3 32 | AND n.nspname = $1 33 | INTO res; 34 | 35 | RETURN ok( COALESCE(res, false), $4 ); 36 | END; 37 | $$ LANGUAGE plpgsql; 38 | 39 | -- index_is_partial( schema, table, index ) 40 | CREATE OR REPLACE FUNCTION index_is_partial ( NAME, NAME, NAME ) 41 | RETURNS TEXT AS $$ 42 | SELECT index_is_partial( 43 | $1, $2, $3, 44 | 'Index ' || quote_ident($3) || ' should be partial' 45 | ); 46 | $$ LANGUAGE sql; 47 | 48 | -- index_is_partial( table, index ) 49 | CREATE OR REPLACE FUNCTION index_is_partial ( NAME, NAME ) 50 | RETURNS TEXT AS $$ 51 | DECLARE 52 | res boolean; 53 | BEGIN 54 | SELECT x.indpred IS NOT NULL 55 | FROM pg_catalog.pg_index x 56 | JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid 57 | JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid 58 | WHERE ct.relname = $1 59 | AND ci.relname = $2 60 | AND pg_catalog.pg_table_is_visible(ct.oid) 61 | INTO res; 62 | 63 | RETURN ok( 64 | COALESCE(res, false), 65 | 'Index ' || quote_ident($2) || ' should be partial' 66 | ); 67 | END; 68 | $$ LANGUAGE plpgsql; 69 | 70 | -- index_is_partial( index ) 71 | CREATE OR REPLACE FUNCTION index_is_partial ( NAME ) 72 | RETURNS TEXT AS $$ 73 | DECLARE 74 | res boolean; 75 | BEGIN 76 | SELECT x.indpred IS NOT NULL 77 | FROM pg_catalog.pg_index x 78 | JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid 79 | JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid 80 | WHERE ci.relname = $1 81 | AND pg_catalog.pg_table_is_visible(ct.oid) 82 | INTO res; 83 | 84 | RETURN ok( 85 | COALESCE(res, false), 86 | 'Index ' || quote_ident($1) || ' should be partial' 87 | ); 88 | END; 89 | $$ LANGUAGE plpgsql; 90 | -------------------------------------------------------------------------------- /test/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG pgtag 2 | FROM postgres:${pgtag:-alpine} 3 | ENV POSTGRES_HOST_AUTH_METHOD trust 4 | 5 | RUN apk --no-cache add make perl-dev patch \ 6 | && cpan -T TAP::Parser::SourceHandler::pgTAP 7 | ENV PGUSER postgres 8 | 9 | WORKDIR /pgtap 10 | ENV PATH /pgtap/test:$PATH 11 | -------------------------------------------------------------------------------- /test/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | test: 5 | build: 6 | context: . 7 | args: [pgtag] 8 | volumes: 9 | - ../:/pgtap 10 | - postgres:/var/lib/postgresql/data 11 | 12 | volumes: 13 | postgres: 14 | driver_opts: 15 | type: tmpfs 16 | device: tmpfs 17 | 18 | -------------------------------------------------------------------------------- /test/expected/build.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | -------------------------------------------------------------------------------- /test/expected/check.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..48 3 | ok 1 - has_check( schema, table, desc ) should pass 4 | ok 2 - has_check( schema, table, desc ) should have the proper description 5 | ok 3 - has_check( schema, table, desc ) should have the proper diagnostics 6 | ok 4 - has_check( table, desc ) should pass 7 | ok 5 - has_check( table, desc ) should have the proper description 8 | ok 6 - has_check( table, desc ) should have the proper diagnostics 9 | ok 7 - has_check( table ) should pass 10 | ok 8 - has_check( table ) should have the proper description 11 | ok 9 - has_check( table ) should have the proper diagnostics 12 | ok 10 - has_check( schema, table, descr ) fail should fail 13 | ok 11 - has_check( schema, table, descr ) fail should have the proper description 14 | ok 12 - has_check( schema, table, descr ) fail should have the proper diagnostics 15 | ok 13 - has_check( table, desc ) fail should fail 16 | ok 14 - has_check( table, desc ) fail should have the proper description 17 | ok 15 - has_check( table, desc ) fail should have the proper diagnostics 18 | ok 16 - col_has_check( sch, tab, col, desc ) should pass 19 | ok 17 - col_has_check( sch, tab, col, desc ) should have the proper description 20 | ok 18 - col_has_check( sch, tab, col, desc ) should have the proper diagnostics 21 | ok 19 - col_has_check( sch, tab, cols, desc ) should pass 22 | ok 20 - col_has_check( sch, tab, cols, desc ) should have the proper description 23 | ok 21 - col_has_check( sch, tab, cols, desc ) should have the proper diagnostics 24 | ok 22 - col_has_check( tab, col, desc ) should pass 25 | ok 23 - col_has_check( tab, col, desc ) should have the proper description 26 | ok 24 - col_has_check( tab, col, desc ) should have the proper diagnostics 27 | ok 25 - col_has_check( tab, cols, desc ) should pass 28 | ok 26 - col_has_check( tab, cols, desc ) should have the proper description 29 | ok 27 - col_has_check( tab, cols, desc ) should have the proper diagnostics 30 | ok 28 - col_has_check( table, column ) should pass 31 | ok 29 - col_has_check( table, column ) should have the proper description 32 | ok 30 - col_has_check( table, column ) should have the proper diagnostics 33 | ok 31 - col_has_check( table, columns ) should pass 34 | ok 32 - col_has_check( table, columns ) should have the proper description 35 | ok 33 - col_has_check( table, columns ) should have the proper diagnostics 36 | ok 34 - col_has_check( sch, tab, col, desc ) fail should fail 37 | ok 35 - col_has_check( sch, tab, col, desc ) fail should have the proper description 38 | ok 36 - col_has_check( sch, tab, col, desc ) fail should have the proper diagnostics 39 | ok 37 - col_has_check( tab, col, desc ) fail should fail 40 | ok 38 - col_has_check( tab, col, desc ) fail should have the proper description 41 | ok 39 - col_has_check( tab, col, desc ) fail should have the proper diagnostics 42 | ok 40 - col_has_check( sch, tab, col[], desc ) should pass 43 | ok 41 - col_has_check( sch, tab, col[], desc ) should have the proper description 44 | ok 42 - col_has_check( sch, tab, col[], desc ) should have the proper diagnostics 45 | ok 43 - col_has_check( tab, col[], desc ) should pass 46 | ok 44 - col_has_check( tab, col[], desc ) should have the proper description 47 | ok 45 - col_has_check( tab, col[], desc ) should have the proper diagnostics 48 | ok 46 - col_has_check( tab, col[] ) should pass 49 | ok 47 - col_has_check( tab, col[] ) should have the proper description 50 | ok 48 - col_has_check( tab, col[] ) should have the proper diagnostics 51 | -------------------------------------------------------------------------------- /test/expected/cmpok.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..38 3 | ok 1 - cmp_ok( int, =, int ) should pass 4 | ok 2 - cmp_ok( int, =, int ) should have the proper description 5 | ok 3 - cmp_ok( int, =, int ) should have the proper diagnostics 6 | ok 4 - cmp_ok( int, <>, int ) should pass 7 | ok 5 - cmp_ok( int, <>, int ) should have the proper description 8 | ok 6 - cmp_ok( int, <>, int ) should have the proper diagnostics 9 | ok 7 - cmp_ok( polygon, ~=, polygon ) should pass 10 | ok 8 - cmp_ok( polygon, ~=, polygon ) should have the proper description 11 | ok 9 - cmp_ok( int[], =, int[] ) should pass 12 | ok 10 - cmp_ok( int[], =, int[] ) should have the proper description 13 | ok 11 - cmp_ok( int[], =, int[] ) should have the proper diagnostics 14 | ok 12 - cmp_ok( inet[], =, inet[] ) should pass 15 | ok 13 - cmp_ok( inet[], =, inet[] ) should have the proper description 16 | ok 14 - cmp_ok( inet[], =, inet[] ) should have the proper diagnostics 17 | ok 15 - cmp_ok() fail should fail 18 | ok 16 - cmp_ok() fail should have the proper description 19 | ok 17 - cmp_ok() fail should have the proper diagnostics 20 | ok 18 - cmp_ok() NULL fail should fail 21 | ok 19 - cmp_ok() NULL fail should have the proper description 22 | ok 20 - cmp_ok() NULL fail should have the proper diagnostics 23 | ok 21 - isa_ok("", text, desc) should pass 24 | ok 22 - isa_ok("", text, desc) should have the proper description 25 | ok 23 - isa_ok("", text, desc) should have the proper diagnostics 26 | ok 24 - isa_ok("", text, desc) should pass 27 | ok 25 - isa_ok("", text, desc) should have the proper description 28 | ok 26 - isa_ok("", text, desc) should have the proper diagnostics 29 | ok 27 - isa_ok(false, boolean) should pass 30 | ok 28 - isa_ok(false, boolean) should have the proper description 31 | ok 29 - isa_ok(false, boolean) should have the proper diagnostics 32 | ok 30 - isa_ok(NULL, boolean) should pass 33 | ok 31 - isa_ok(NULL, boolean) should have the proper description 34 | ok 32 - isa_ok(NULL, boolean) should have the proper diagnostics 35 | ok 33 - isa_ok(ARRAY, boolean[]) should pass 36 | ok 34 - isa_ok(ARRAY, boolean[]) should have the proper description 37 | ok 35 - isa_ok(ARRAY, boolean[]) should have the proper diagnostics 38 | ok 36 - isa_ok(bool, int[]) should fail 39 | ok 37 - isa_ok(bool, int[]) should have the proper description 40 | ok 38 - isa_ok(bool, int[]) should have the proper diagnostics 41 | -------------------------------------------------------------------------------- /test/expected/create.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | -------------------------------------------------------------------------------- /test/expected/do_tap.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..29 3 | ok 1 - findfuncs(public, ^test, this) should work 4 | ok 2 - findfuncs(public, ^test) should work 5 | ok 3 - findfuncs(^test, this) should work 6 | ok 4 - findfuncs(^test) should work 7 | ok 5 - findfuncs(unknown) should find no tests 8 | # public."test ident"() 9 | ok 6 - ident 10 | ok 7 - ident 2 11 | # public.testplpgsql() 12 | ok 8 - plpgsql simple 13 | ok 9 - plpgsql simple 2 14 | # public.testthis() 15 | ok 10 - simple pass 16 | ok 11 - another simple pass 17 | # public."test ident"() 18 | ok 12 - ident 19 | ok 13 - ident 2 20 | # public.testplpgsql() 21 | ok 14 - plpgsql simple 22 | ok 15 - plpgsql simple 2 23 | # public.testthis() 24 | ok 16 - simple pass 25 | ok 17 - another simple pass 26 | # public."test ident"() 27 | ok 18 - ident 28 | ok 19 - ident 2 29 | # public.testplpgsql() 30 | ok 20 - plpgsql simple 31 | ok 21 - plpgsql simple 2 32 | # public.testthis() 33 | ok 22 - simple pass 34 | ok 23 - another simple pass 35 | # public."test ident"() 36 | ok 24 - ident 37 | ok 25 - ident 2 38 | # public.testplpgsql() 39 | ok 26 - plpgsql simple 40 | ok 27 - plpgsql simple 2 41 | # public.testthis() 42 | ok 28 - simple pass 43 | ok 29 - another simple pass 44 | -------------------------------------------------------------------------------- /test/expected/extension.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..72 3 | ok 1 - extensions_are(sch, exts, desc) should pass 4 | ok 2 - extensions_are(sch, exts, desc) should have the proper description 5 | ok 3 - extensions_are(sch, exts, desc) should have the proper diagnostics 6 | ok 4 - extensions_are(sch, exts) should pass 7 | ok 5 - extensions_are(sch, exts) should have the proper description 8 | ok 6 - extensions_are(sch, exts) should have the proper diagnostics 9 | ok 7 - extensions_are(exts, desc) should pass 10 | ok 8 - extensions_are(exts, desc) should have the proper description 11 | ok 9 - extensions_are(exts, desc) should have the proper diagnostics 12 | ok 10 - extensions_are(exts) should pass 13 | ok 11 - extensions_are(exts) should have the proper description 14 | ok 12 - extensions_are(exts) should have the proper diagnostics 15 | ok 13 - extensions_are(ci_schema, exts, desc) should pass 16 | ok 14 - extensions_are(ci_schema, exts, desc) should have the proper description 17 | ok 15 - extensions_are(ci_schema, exts, desc) should have the proper diagnostics 18 | ok 16 - extensions_are(non-sch, exts) should pass 19 | ok 17 - extensions_are(non-sch, exts) should have the proper description 20 | ok 18 - extensions_are(non-sch, exts) should have the proper diagnostics 21 | ok 19 - extensions_are(sch, good/bad, desc) should fail 22 | ok 20 - extensions_are(sch, good/bad, desc) should have the proper description 23 | ok 21 - extensions_are(sch, good/bad, desc) should have the proper diagnostics 24 | ok 22 - extensions_are(someexts) should fail 25 | ok 23 - extensions_are(someexts) should have the proper description 26 | ok 24 - extensions_are(someexts) should have the proper diagnostics 27 | ok 25 - has_extension( schema, name, desc ) should pass 28 | ok 26 - has_extension( schema, name, desc ) should have the proper description 29 | ok 27 - has_extension( schema, name, desc ) should have the proper diagnostics 30 | ok 28 - has_extension( schema, name ) should pass 31 | ok 29 - has_extension( schema, name ) should have the proper description 32 | ok 30 - has_extension( schema, name ) should have the proper diagnostics 33 | ok 31 - has_extension( name, desc ) should pass 34 | ok 32 - has_extension( name, desc ) should have the proper description 35 | ok 33 - has_extension( name, desc ) should have the proper diagnostics 36 | ok 34 - has_extension( name ) should pass 37 | ok 35 - has_extension( name ) should have the proper description 38 | ok 36 - has_extension( name ) should have the proper diagnostics 39 | ok 37 - has_extension( schema, name, desc ) fail should fail 40 | ok 38 - has_extension( schema, name, desc ) fail should have the proper description 41 | ok 39 - has_extension( schema, name, desc ) fail should have the proper diagnostics 42 | ok 40 - has_extension( schema, name ) fail should fail 43 | ok 41 - has_extension( schema, name ) fail should have the proper description 44 | ok 42 - has_extension( schema, name ) fail should have the proper diagnostics 45 | ok 43 - has_extension( name, desc ) fail should fail 46 | ok 44 - has_extension( name, desc ) fail should have the proper description 47 | ok 45 - has_extension( name, desc ) fail should have the proper diagnostics 48 | ok 46 - has_extension( name ) fail should fail 49 | ok 47 - has_extension( name ) fail should have the proper description 50 | ok 48 - has_extension( name ) fail should have the proper diagnostics 51 | ok 49 - hasnt_extension( schema, name, desc ) should pass 52 | ok 50 - hasnt_extension( schema, name, desc ) should have the proper description 53 | ok 51 - hasnt_extension( schema, name, desc ) should have the proper diagnostics 54 | ok 52 - hasnt_extension( schema, name ) should pass 55 | ok 53 - hasnt_extension( schema, name ) should have the proper description 56 | ok 54 - hasnt_extension( schema, name ) should have the proper diagnostics 57 | ok 55 - hasnt_extension( name, desc ) should pass 58 | ok 56 - hasnt_extension( name, desc ) should have the proper description 59 | ok 57 - hasnt_extension( name, desc ) should have the proper diagnostics 60 | ok 58 - hasnt_extension( name ) should pass 61 | ok 59 - hasnt_extension( name ) should have the proper description 62 | ok 60 - hasnt_extension( name ) should have the proper diagnostics 63 | ok 61 - hasnt_extension( schema, name, desc ) should fail 64 | ok 62 - hasnt_extension( schema, name, desc ) should have the proper description 65 | ok 63 - hasnt_extension( schema, name, desc ) should have the proper diagnostics 66 | ok 64 - hasnt_extension( schema, name ) should fail 67 | ok 65 - hasnt_extension( schema, name ) should have the proper description 68 | ok 66 - hasnt_extension( schema, name ) should have the proper diagnostics 69 | ok 67 - hasnt_extension( name, desc ) should fail 70 | ok 68 - hasnt_extension( name, desc ) should have the proper description 71 | ok 69 - hasnt_extension( name, desc ) should have the proper diagnostics 72 | ok 70 - hasnt_extension( name ) should fail 73 | ok 71 - hasnt_extension( name ) should have the proper description 74 | ok 72 - hasnt_extension( name ) should have the proper diagnostics 75 | -------------------------------------------------------------------------------- /test/expected/inheritance_1.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..408 3 | ok 1 - has_inherited_tables(sch, tab, desc) should pass 4 | ok 2 - has_inherited_tables(sch, tab, desc) should have the proper description 5 | ok 3 - has_inherited_tables(sch, tab, desc) should have the proper diagnostics 6 | ok 4 - has_inherited_tables(sch, tab, desc) fail should fail 7 | ok 5 - has_inherited_tables(sch, tab, desc) fail should have the proper description 8 | ok 6 - has_inherited_tables(sch, tab, desc) fail should have the proper diagnostics 9 | ok 7 - has_inherited_tables(sch, nonesuch, desc) should fail 10 | ok 8 - has_inherited_tables(sch, nonesuch, desc) should have the proper description 11 | ok 9 - has_inherited_tables(sch, nonesuch, desc) should have the proper diagnostics 12 | ok 10 - has_inherited_tables(sch, tab) should pass 13 | ok 11 - has_inherited_tables(sch, tab) should have the proper description 14 | ok 12 - has_inherited_tables(sch, tab) should have the proper diagnostics 15 | ok 13 - has_inherited_tables(sch, tab) fail should fail 16 | ok 14 - has_inherited_tables(sch, tab) fail should have the proper description 17 | ok 15 - has_inherited_tables(sch, tab) fail should have the proper diagnostics 18 | ok 16 - has_inherited_tables(sch, nonesuch) should fail 19 | ok 17 - has_inherited_tables(sch, nonesuch) should have the proper description 20 | ok 18 - has_inherited_tables(sch, nonesuch) should have the proper diagnostics 21 | ok 19 - has_inherited_tables(tab, desc) should pass 22 | ok 20 - has_inherited_tables(tab, desc) should have the proper description 23 | ok 21 - has_inherited_tables(tab, desc) should have the proper diagnostics 24 | ok 22 - has_inherited_tables(tab, desc) fail should fail 25 | ok 23 - has_inherited_tables(tab, desc) fail should have the proper description 26 | ok 24 - has_inherited_tables(tab, desc) fail should have the proper diagnostics 27 | ok 25 - has_inherited_tables(nonesuch, desc) should fail 28 | ok 26 - has_inherited_tables(nonesuch, desc) should have the proper description 29 | ok 27 - has_inherited_tables(nonesuch, desc) should have the proper diagnostics 30 | ok 28 - has_inherited_tables(tab) should pass 31 | ok 29 - has_inherited_tables(tab) should have the proper description 32 | ok 30 - has_inherited_tables(tab) should have the proper diagnostics 33 | ok 31 - has_inherited_tables(tab) fail should fail 34 | ok 32 - has_inherited_tables(tab) fail should have the proper description 35 | ok 33 - has_inherited_tables(tab) fail should have the proper diagnostics 36 | ok 34 - has_inherited_tables(nonesuch) should fail 37 | ok 35 - has_inherited_tables(nonesuch) should have the proper description 38 | ok 36 - has_inherited_tables(nonesuch) should have the proper diagnostics 39 | ok 37 - hasnt_inherited_tables(sch, tab, desc) should pass 40 | ok 38 - hasnt_inherited_tables(sch, tab, desc) should have the proper description 41 | ok 39 - hasnt_inherited_tables(sch, tab, desc) should have the proper diagnostics 42 | ok 40 - hasnt_inherited_tables(sch, tab, desc) fail should fail 43 | ok 41 - hasnt_inherited_tables(sch, tab, desc) fail should have the proper description 44 | ok 42 - hasnt_inherited_tables(sch, tab, desc) fail should have the proper diagnostics 45 | ok 43 - hasnt_inherited_tables(sch, nonesuch, desc) should pass 46 | ok 44 - hasnt_inherited_tables(sch, nonesuch, desc) should have the proper description 47 | ok 45 - hasnt_inherited_tables(sch, nonesuch, desc) should have the proper diagnostics 48 | ok 46 - hasnt_inherited_tables(sch, tab) should pass 49 | ok 47 - hasnt_inherited_tables(sch, tab) should have the proper description 50 | ok 48 - hasnt_inherited_tables(sch, tab) should have the proper diagnostics 51 | ok 49 - hasnt_inherited_tables(sch, tab) fail should fail 52 | ok 50 - hasnt_inherited_tables(sch, tab) fail should have the proper description 53 | ok 51 - hasnt_inherited_tables(sch, tab) fail should have the proper diagnostics 54 | ok 52 - hasnt_inherited_tables(sch, nonesuch) should pass 55 | ok 53 - hasnt_inherited_tables(sch, nonesuch) should have the proper description 56 | ok 54 - hasnt_inherited_tables(sch, nonesuch) should have the proper diagnostics 57 | ok 55 - hasnt_inherited_tables(tab, desc) should pass 58 | ok 56 - hasnt_inherited_tables(tab, desc) should have the proper description 59 | ok 57 - hasnt_inherited_tables(tab, desc) should have the proper diagnostics 60 | ok 58 - hasnt_inherited_tables(tab, desc) fail should fail 61 | ok 59 - hasnt_inherited_tables(tab, desc) fail should have the proper description 62 | ok 60 - hasnt_inherited_tables(tab, desc) fail should have the proper diagnostics 63 | ok 61 - hasnt_inherited_tables(nonesuch, desc) should pass 64 | ok 62 - hasnt_inherited_tables(nonesuch, desc) should have the proper description 65 | ok 63 - hasnt_inherited_tables(nonesuch, desc) should have the proper diagnostics 66 | ok 64 - hasnt_inherited_tables(tab) should pass 67 | ok 65 - hasnt_inherited_tables(tab) should have the proper description 68 | ok 66 - hasnt_inherited_tables(tab) should have the proper diagnostics 69 | ok 67 - hasnt_inherited_tables(tab) fail should fail 70 | ok 68 - hasnt_inherited_tables(tab) fail should have the proper description 71 | ok 69 - hasnt_inherited_tables(tab) fail should have the proper diagnostics 72 | ok 70 - hasnt_inherited_tables(nonesuch) should pass 73 | ok 71 - hasnt_inherited_tables(nonesuch) should have the proper description 74 | ok 72 - hasnt_inherited_tables(nonesuch) should have the proper diagnostics 75 | ERROR: function is_ancestor_of(unknown, unknown, unknown, unknown, integer, unknown) does not exist 76 | LINE 2: is_ancestor_of( 'hide', 'h_parent', 'hide', 'h_child1', ... 77 | ^ 78 | HINT: No function matches the given name and argument types. You might need to add explicit type casts. 79 | -------------------------------------------------------------------------------- /test/expected/inheritance_2.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..408 3 | ok 1 - has_inherited_tables(sch, tab, desc) should pass 4 | ok 2 - has_inherited_tables(sch, tab, desc) should have the proper description 5 | ok 3 - has_inherited_tables(sch, tab, desc) should have the proper diagnostics 6 | ok 4 - has_inherited_tables(sch, tab, desc) fail should fail 7 | ok 5 - has_inherited_tables(sch, tab, desc) fail should have the proper description 8 | ok 6 - has_inherited_tables(sch, tab, desc) fail should have the proper diagnostics 9 | ok 7 - has_inherited_tables(sch, nonesuch, desc) should fail 10 | ok 8 - has_inherited_tables(sch, nonesuch, desc) should have the proper description 11 | ok 9 - has_inherited_tables(sch, nonesuch, desc) should have the proper diagnostics 12 | ok 10 - has_inherited_tables(sch, tab) should pass 13 | ok 11 - has_inherited_tables(sch, tab) should have the proper description 14 | ok 12 - has_inherited_tables(sch, tab) should have the proper diagnostics 15 | ok 13 - has_inherited_tables(sch, tab) fail should fail 16 | ok 14 - has_inherited_tables(sch, tab) fail should have the proper description 17 | ok 15 - has_inherited_tables(sch, tab) fail should have the proper diagnostics 18 | ok 16 - has_inherited_tables(sch, nonesuch) should fail 19 | ok 17 - has_inherited_tables(sch, nonesuch) should have the proper description 20 | ok 18 - has_inherited_tables(sch, nonesuch) should have the proper diagnostics 21 | ok 19 - has_inherited_tables(tab, desc) should pass 22 | ok 20 - has_inherited_tables(tab, desc) should have the proper description 23 | ok 21 - has_inherited_tables(tab, desc) should have the proper diagnostics 24 | ok 22 - has_inherited_tables(tab, desc) fail should fail 25 | ok 23 - has_inherited_tables(tab, desc) fail should have the proper description 26 | ok 24 - has_inherited_tables(tab, desc) fail should have the proper diagnostics 27 | ok 25 - has_inherited_tables(nonesuch, desc) should fail 28 | ok 26 - has_inherited_tables(nonesuch, desc) should have the proper description 29 | ok 27 - has_inherited_tables(nonesuch, desc) should have the proper diagnostics 30 | ok 28 - has_inherited_tables(tab) should pass 31 | ok 29 - has_inherited_tables(tab) should have the proper description 32 | ok 30 - has_inherited_tables(tab) should have the proper diagnostics 33 | ok 31 - has_inherited_tables(tab) fail should fail 34 | ok 32 - has_inherited_tables(tab) fail should have the proper description 35 | ok 33 - has_inherited_tables(tab) fail should have the proper diagnostics 36 | ok 34 - has_inherited_tables(nonesuch) should fail 37 | ok 35 - has_inherited_tables(nonesuch) should have the proper description 38 | ok 36 - has_inherited_tables(nonesuch) should have the proper diagnostics 39 | ok 37 - hasnt_inherited_tables(sch, tab, desc) should pass 40 | ok 38 - hasnt_inherited_tables(sch, tab, desc) should have the proper description 41 | ok 39 - hasnt_inherited_tables(sch, tab, desc) should have the proper diagnostics 42 | ok 40 - hasnt_inherited_tables(sch, tab, desc) fail should fail 43 | ok 41 - hasnt_inherited_tables(sch, tab, desc) fail should have the proper description 44 | ok 42 - hasnt_inherited_tables(sch, tab, desc) fail should have the proper diagnostics 45 | ok 43 - hasnt_inherited_tables(sch, nonesuch, desc) should pass 46 | ok 44 - hasnt_inherited_tables(sch, nonesuch, desc) should have the proper description 47 | ok 45 - hasnt_inherited_tables(sch, nonesuch, desc) should have the proper diagnostics 48 | ok 46 - hasnt_inherited_tables(sch, tab) should pass 49 | ok 47 - hasnt_inherited_tables(sch, tab) should have the proper description 50 | ok 48 - hasnt_inherited_tables(sch, tab) should have the proper diagnostics 51 | ok 49 - hasnt_inherited_tables(sch, tab) fail should fail 52 | ok 50 - hasnt_inherited_tables(sch, tab) fail should have the proper description 53 | ok 51 - hasnt_inherited_tables(sch, tab) fail should have the proper diagnostics 54 | ok 52 - hasnt_inherited_tables(sch, nonesuch) should pass 55 | ok 53 - hasnt_inherited_tables(sch, nonesuch) should have the proper description 56 | ok 54 - hasnt_inherited_tables(sch, nonesuch) should have the proper diagnostics 57 | ok 55 - hasnt_inherited_tables(tab, desc) should pass 58 | ok 56 - hasnt_inherited_tables(tab, desc) should have the proper description 59 | ok 57 - hasnt_inherited_tables(tab, desc) should have the proper diagnostics 60 | ok 58 - hasnt_inherited_tables(tab, desc) fail should fail 61 | ok 59 - hasnt_inherited_tables(tab, desc) fail should have the proper description 62 | ok 60 - hasnt_inherited_tables(tab, desc) fail should have the proper diagnostics 63 | ok 61 - hasnt_inherited_tables(nonesuch, desc) should pass 64 | ok 62 - hasnt_inherited_tables(nonesuch, desc) should have the proper description 65 | ok 63 - hasnt_inherited_tables(nonesuch, desc) should have the proper diagnostics 66 | ok 64 - hasnt_inherited_tables(tab) should pass 67 | ok 65 - hasnt_inherited_tables(tab) should have the proper description 68 | ok 66 - hasnt_inherited_tables(tab) should have the proper diagnostics 69 | ok 67 - hasnt_inherited_tables(tab) fail should fail 70 | ok 68 - hasnt_inherited_tables(tab) fail should have the proper description 71 | ok 69 - hasnt_inherited_tables(tab) fail should have the proper diagnostics 72 | ok 70 - hasnt_inherited_tables(nonesuch) should pass 73 | ok 71 - hasnt_inherited_tables(nonesuch) should have the proper description 74 | ok 72 - hasnt_inherited_tables(nonesuch) should have the proper diagnostics 75 | ERROR: function is_ancestor_of("unknown", "unknown", "unknown", "unknown", integer, "unknown") does not exist 76 | LINE 2: is_ancestor_of( 'hide', 'h_parent', 'hide', 'h_child1', ... 77 | ^ 78 | HINT: No function matches the given name and argument types. You may need to add explicit type casts. 79 | -------------------------------------------------------------------------------- /test/expected/inheritance_3.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..408 3 | ok 1 - has_inherited_tables(sch, tab, desc) should pass 4 | ok 2 - has_inherited_tables(sch, tab, desc) should have the proper description 5 | ok 3 - has_inherited_tables(sch, tab, desc) should have the proper diagnostics 6 | ok 4 - has_inherited_tables(sch, tab, desc) fail should fail 7 | ok 5 - has_inherited_tables(sch, tab, desc) fail should have the proper description 8 | ok 6 - has_inherited_tables(sch, tab, desc) fail should have the proper diagnostics 9 | ok 7 - has_inherited_tables(sch, nonesuch, desc) should fail 10 | ok 8 - has_inherited_tables(sch, nonesuch, desc) should have the proper description 11 | ok 9 - has_inherited_tables(sch, nonesuch, desc) should have the proper diagnostics 12 | ok 10 - has_inherited_tables(sch, tab) should pass 13 | ok 11 - has_inherited_tables(sch, tab) should have the proper description 14 | ok 12 - has_inherited_tables(sch, tab) should have the proper diagnostics 15 | ok 13 - has_inherited_tables(sch, tab) fail should fail 16 | ok 14 - has_inherited_tables(sch, tab) fail should have the proper description 17 | ok 15 - has_inherited_tables(sch, tab) fail should have the proper diagnostics 18 | ok 16 - has_inherited_tables(sch, nonesuch) should fail 19 | ok 17 - has_inherited_tables(sch, nonesuch) should have the proper description 20 | ok 18 - has_inherited_tables(sch, nonesuch) should have the proper diagnostics 21 | ok 19 - has_inherited_tables(tab, desc) should pass 22 | ok 20 - has_inherited_tables(tab, desc) should have the proper description 23 | ok 21 - has_inherited_tables(tab, desc) should have the proper diagnostics 24 | ok 22 - has_inherited_tables(tab, desc) fail should fail 25 | ok 23 - has_inherited_tables(tab, desc) fail should have the proper description 26 | ok 24 - has_inherited_tables(tab, desc) fail should have the proper diagnostics 27 | ok 25 - has_inherited_tables(nonesuch, desc) should fail 28 | ok 26 - has_inherited_tables(nonesuch, desc) should have the proper description 29 | ok 27 - has_inherited_tables(nonesuch, desc) should have the proper diagnostics 30 | ok 28 - has_inherited_tables(tab) should pass 31 | ok 29 - has_inherited_tables(tab) should have the proper description 32 | ok 30 - has_inherited_tables(tab) should have the proper diagnostics 33 | ok 31 - has_inherited_tables(tab) fail should fail 34 | ok 32 - has_inherited_tables(tab) fail should have the proper description 35 | ok 33 - has_inherited_tables(tab) fail should have the proper diagnostics 36 | ok 34 - has_inherited_tables(nonesuch) should fail 37 | ok 35 - has_inherited_tables(nonesuch) should have the proper description 38 | ok 36 - has_inherited_tables(nonesuch) should have the proper diagnostics 39 | ok 37 - hasnt_inherited_tables(sch, tab, desc) should pass 40 | ok 38 - hasnt_inherited_tables(sch, tab, desc) should have the proper description 41 | ok 39 - hasnt_inherited_tables(sch, tab, desc) should have the proper diagnostics 42 | ok 40 - hasnt_inherited_tables(sch, tab, desc) fail should fail 43 | ok 41 - hasnt_inherited_tables(sch, tab, desc) fail should have the proper description 44 | ok 42 - hasnt_inherited_tables(sch, tab, desc) fail should have the proper diagnostics 45 | ok 43 - hasnt_inherited_tables(sch, nonesuch, desc) should pass 46 | ok 44 - hasnt_inherited_tables(sch, nonesuch, desc) should have the proper description 47 | ok 45 - hasnt_inherited_tables(sch, nonesuch, desc) should have the proper diagnostics 48 | ok 46 - hasnt_inherited_tables(sch, tab) should pass 49 | ok 47 - hasnt_inherited_tables(sch, tab) should have the proper description 50 | ok 48 - hasnt_inherited_tables(sch, tab) should have the proper diagnostics 51 | ok 49 - hasnt_inherited_tables(sch, tab) fail should fail 52 | ok 50 - hasnt_inherited_tables(sch, tab) fail should have the proper description 53 | ok 51 - hasnt_inherited_tables(sch, tab) fail should have the proper diagnostics 54 | ok 52 - hasnt_inherited_tables(sch, nonesuch) should pass 55 | ok 53 - hasnt_inherited_tables(sch, nonesuch) should have the proper description 56 | ok 54 - hasnt_inherited_tables(sch, nonesuch) should have the proper diagnostics 57 | ok 55 - hasnt_inherited_tables(tab, desc) should pass 58 | ok 56 - hasnt_inherited_tables(tab, desc) should have the proper description 59 | ok 57 - hasnt_inherited_tables(tab, desc) should have the proper diagnostics 60 | ok 58 - hasnt_inherited_tables(tab, desc) fail should fail 61 | ok 59 - hasnt_inherited_tables(tab, desc) fail should have the proper description 62 | ok 60 - hasnt_inherited_tables(tab, desc) fail should have the proper diagnostics 63 | ok 61 - hasnt_inherited_tables(nonesuch, desc) should pass 64 | ok 62 - hasnt_inherited_tables(nonesuch, desc) should have the proper description 65 | ok 63 - hasnt_inherited_tables(nonesuch, desc) should have the proper diagnostics 66 | ok 64 - hasnt_inherited_tables(tab) should pass 67 | ok 65 - hasnt_inherited_tables(tab) should have the proper description 68 | ok 66 - hasnt_inherited_tables(tab) should have the proper diagnostics 69 | ok 67 - hasnt_inherited_tables(tab) fail should fail 70 | ok 68 - hasnt_inherited_tables(tab) fail should have the proper description 71 | ok 69 - hasnt_inherited_tables(tab) fail should have the proper diagnostics 72 | ok 70 - hasnt_inherited_tables(nonesuch) should pass 73 | ok 71 - hasnt_inherited_tables(nonesuch) should have the proper description 74 | ok 72 - hasnt_inherited_tables(nonesuch) should have the proper diagnostics 75 | ERROR: function is_ancestor_of("unknown", "unknown", "unknown", "unknown", integer, "unknown") does not exist 76 | HINT: No function matches the given name and argument types. You may need to add explicit type casts. 77 | -------------------------------------------------------------------------------- /test/expected/istap.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..47 3 | ok 1 - is(1, 1) should pass 4 | ok 2 - is(1, 1) should have the proper description 5 | ok 3 - is(1, 1) should have the proper diagnostics 6 | ok 4 - is('x', 'x') should pass 7 | ok 5 - is('x', 'x') should have the proper description 8 | ok 6 - is('x', 'x') should have the proper diagnostics 9 | ok 7 - is(1.1, 1.10) should pass 10 | ok 8 - is(1.1, 1.10) should have the proper description 11 | ok 9 - is(1.1, 1.10) should have the proper diagnostics 12 | ok 10 - is(true, true) should pass 13 | ok 11 - is(true, true) should have the proper description 14 | ok 12 - is(true, true) should have the proper diagnostics 15 | ok 13 - is(false, false) should pass 16 | ok 14 - is(false, false) should have the proper description 17 | ok 15 - is(false, false) should have the proper diagnostics 18 | ok 16 - is(1, 1, desc) should pass 19 | ok 17 - is(1, 1, desc) should have the proper description 20 | ok 18 - is(1, 1, desc) should have the proper diagnostics 21 | ok 19 - is(1, 2) should fail 22 | ok 20 - is(1, 2) should have the proper description 23 | ok 21 - is(1, 2) should have the proper diagnostics 24 | ok 22 - isnt(1, 2) should pass 25 | ok 23 - isnt(1, 2) should have the proper description 26 | ok 24 - isnt(1, 2) should have the proper diagnostics 27 | ok 25 - isnt(1, 1) should fail 28 | ok 26 - isnt(1, 1) should have the proper description 29 | ok 27 - isnt(1, 1) should have the proper diagnostics 30 | ok 28 - is() should work with psql variables 31 | ok 29 - is(NULL, NULL) should pass 32 | ok 30 - is(NULL, NULL) should have the proper description 33 | ok 31 - is(NULL, NULL) should have the proper diagnostics 34 | ok 32 - is(NULL, foo) should fail 35 | ok 33 - is(NULL, foo) should have the proper description 36 | ok 34 - is(NULL, foo) should have the proper diagnostics 37 | ok 35 - is(foo, NULL) should fail 38 | ok 36 - is(foo, NULL) should have the proper description 39 | ok 37 - is(foo, NULL) should have the proper diagnostics 40 | ok 38 - with records! 41 | ok 39 - is(mumble, row) fail should fail 42 | ok 40 - is(mumble, row) fail should have the proper description 43 | ok 41 - is(mumble, row) fail should have the proper diagnostics 44 | ok 42 - is(mumble, row) fail with NULL should fail 45 | ok 43 - is(mumble, row) fail with NULL should have the proper description 46 | ok 44 - is(mumble, row) fail with NULL should have the proper diagnostics 47 | ok 45 - is(mumble, NULL) should fail 48 | ok 46 - is(mumble, NULL) should have the proper description 49 | ok 47 - is(mumble, NULL) should have the proper diagnostics 50 | -------------------------------------------------------------------------------- /test/expected/matching.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..24 3 | ok 1 - matches() should work 4 | ok 2 - matches() should work with a regex 5 | ok 3 - imatches() should work with a regex 6 | ok 4 - matches() fail should fail 7 | ok 5 - matches() fail should have the proper description 8 | ok 6 - matches() fail should have the proper diagnostics 9 | ok 7 - doesnt_match() should work 10 | ok 8 - doesnt_match() should work with a regex 11 | ok 9 - doesnt_imatch() should work with a regex 12 | ok 10 - doesnt_match() fail should fail 13 | ok 11 - doesnt_match() fail should have the proper description 14 | ok 12 - doesnt_match() fail should have the proper diagnostics 15 | ok 13 - alike() should work 16 | ok 14 - alike() should work with a regex 17 | ok 15 - ialike() should work with a regex 18 | ok 16 - alike() fail should fail 19 | ok 17 - alike() fail should have the proper description 20 | ok 18 - alike() fail should have the proper diagnostics 21 | ok 19 - unalike() should work 22 | ok 20 - unalike() should work with a regex 23 | ok 21 - iunalike() should work with a regex 24 | ok 22 - unalike() fail should fail 25 | ok 23 - unalike() fail should have the proper description 26 | ok 24 - unalike() fail should have the proper diagnostics 27 | -------------------------------------------------------------------------------- /test/expected/moretap.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..54 3 | ok 1 - Modify internal plan value 4 | ok 2 - My pass() passed, w00t! 5 | ok 3 - Testing fail() 6 | ok 4 - We should get the proper output from fail() 7 | ok 5 - The output of finish() should reflect the test failure 8 | ok 6 - Increase internal plan value after testing finish 9 | ok 7 - The output of finish(false) should reflect the test failure 10 | ok 8 - Increase internal plan value after testing finish 11 | ok 9 - The output of finish(NULL) should reflect the test failure 12 | ok 10 - Increase internal plan value after testing finish 13 | ok 11 - finish(true) should throw an exception 14 | ok 12 - We should have one failure 15 | ok 13 - Reset internal failure count 16 | ok 14 - We should now have no failures 17 | ok 15 - diag() should work properly 18 | ok 16 - multiline diag() should work properly 19 | ok 17 - multiline diag() should work properly with existing comments 20 | ok 18 - diag(int) 21 | ok 19 - diag(numeric) 22 | ok 20 - diag(timestamptz) 23 | ok 21 - variadic text 24 | ok 22 - variadic int 25 | ok 23 - variadic unknown 26 | ok 24 - no_plan() should have stored a plan of 0 27 | ok 25 - Set the plan to 4000 28 | ok 26 - The output of finish() should reflect a high test plan 29 | ok 27 - Set the plan to 4 30 | ok 28 - The output of finish() should reflect a low test plan 31 | ok 29 - Reset the plan 32 | ok 30 - plan() should have stored the test count 33 | ok 31 - ok(true) should pass 34 | ok 32 - ok(true) should have the proper description 35 | ok 33 - ok(true) should have the proper diagnostics 36 | ok 34 - ok(true, '') should pass 37 | ok 35 - ok(true, '') should have the proper description 38 | ok 36 - ok(true, '') should have the proper diagnostics 39 | ok 37 - ok(true, 'foo') should pass 40 | ok 38 - ok(true, 'foo') should have the proper description 41 | ok 39 - ok(true, 'foo') should have the proper diagnostics 42 | ok 40 - ok(false) should fail 43 | ok 41 - ok(false) should have the proper description 44 | ok 42 - ok(false) should have the proper diagnostics 45 | ok 43 - ok(false, '') should fail 46 | ok 44 - ok(false, '') should have the proper description 47 | ok 45 - ok(false, '') should have the proper diagnostics 48 | ok 46 - ok(false, 'foo') should fail 49 | ok 47 - ok(false, 'foo') should have the proper description 50 | ok 48 - ok(false, 'foo') should have the proper diagnostics 51 | ok 49 - ok(NULL, 'null') should fail 52 | ok 50 - ok(NULL, 'null') should have the proper description 53 | ok 51 - ok(NULL, 'null') should have the proper diagnostics 54 | ok 52 - multiline desc should pass 55 | ok 53 - multiline desc should have the proper description 56 | ok 54 - multiline desc should have the proper diagnostics 57 | -------------------------------------------------------------------------------- /test/expected/performs_ok.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..24 3 | ok 1 - simple select should pass 4 | ok 2 - simple select should have the proper description 5 | ok 3 - simple select should have the proper diagnostics 6 | ok 4 - simple select no desc should pass 7 | ok 5 - simple select no desc should have the proper description 8 | ok 6 - simple select no desc should have the proper diagnostics 9 | ok 7 - simple select numeric should pass 10 | ok 8 - simple select numeric should have the proper description 11 | ok 9 - simple select numeric should have the proper diagnostics 12 | ok 10 - simple prepare should pass 13 | ok 11 - simple prepare should have the proper description 14 | ok 12 - simple prepare should have the proper diagnostics 15 | ok 13 - simple execute should pass 16 | ok 14 - simple execute should have the proper description 17 | ok 15 - simple execute should have the proper diagnostics 18 | ok 16 - simple select fail should fail 19 | ok 17 - simple select fail should have the proper description 20 | ok 18 - simple select fail should have the proper diagnostics 21 | ok 19 - simple select no desc fail should fail 22 | ok 20 - simple select no desc fail should have the proper description 23 | ok 21 - simple select no desc fail should have the proper diagnostics 24 | ok 22 - simple select no desc numeric fail should fail 25 | ok 23 - simple select no desc numeric fail should have the proper description 26 | ok 24 - simple select no desc numeric fail should have the proper diagnostics 27 | -------------------------------------------------------------------------------- /test/expected/performs_within.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..24 3 | ok 1 - simple select should pass 4 | ok 2 - simple select should have the proper description 5 | ok 3 - simple select should have the proper diagnostics 6 | ok 4 - simple select no desc should pass 7 | ok 5 - simple select no desc should have the proper description 8 | ok 6 - simple select no desc should have the proper diagnostics 9 | ok 7 - simple select numeric should pass 10 | ok 8 - simple select numeric should have the proper description 11 | ok 9 - simple select numeric should have the proper diagnostics 12 | ok 10 - simple prepare should pass 13 | ok 11 - simple prepare should have the proper description 14 | ok 12 - simple prepare should have the proper diagnostics 15 | ok 13 - simple execute should pass 16 | ok 14 - simple execute should have the proper description 17 | ok 15 - simple execute should have the proper diagnostics 18 | ok 16 - simple select fail should fail 19 | ok 17 - simple select fail should have the proper description 20 | ok 18 - simple select fail should have the proper diagnostics 21 | ok 19 - simple select no desc fail should fail 22 | ok 20 - simple select no desc fail should have the proper description 23 | ok 21 - simple select no desc fail should have the proper diagnostics 24 | ok 22 - simple select no desc numeric fail should fail 25 | ok 23 - simple select no desc numeric fail should have the proper description 26 | ok 24 - simple select no desc numeric fail should have the proper diagnostics 27 | -------------------------------------------------------------------------------- /test/expected/pg73.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..39 3 | ok 1 4 | ok 2 - true 5 | ok 3 6 | ok 4 - NOT false 7 | ok 5 8 | ok 6 - three 9 | ok 7 10 | ok 8 11 | ok 9 12 | ok 10 - 1=2 13 | ok 11 - now()=now() 14 | ok 12 - '1 hour'::interval, '1 hour'::interval 15 | ok 13 16 | ok 14 - now=now date 17 | ok 15 - now!=now+1 18 | ok 16 - now()=now() timestamp 19 | ok 17 - now()=now() date 20 | ok 18 - TRUE=TRUE 21 | ok 19 - TRUE!=FALSE 22 | ok 20 - a=a char 23 | ok 21 - a!=b char 24 | ok 22 - a=a text 25 | ok 23 - a!=b text 26 | ok 24 - 3=3 int 27 | ok 25 - 3!=4 int 28 | ok 26 - 3=3 integer 29 | ok 27 - 3!=4 integer 30 | ok 28 - 3=3 int2 31 | ok 29 - 3!=4 int2 32 | ok 30 - 3=3 int4 33 | ok 31 - 3!=4 int4 34 | ok 32 - 3=3 int8 35 | ok 33 - 3!=4 int8 36 | ok 34 - 3.2=3.2 float 37 | ok 35 - 3.2!=4.5 float 38 | ok 36 - 3.2=3.2 float4 39 | ok 37 - 3.2!=4.5 float4 40 | ok 38 - 3.2=3.2 float8 41 | ok 39 - 3.2!=4.5 float8 42 | -------------------------------------------------------------------------------- /test/expected/roletap.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..39 3 | ok 1 - has_role(current role) should pass 4 | ok 2 - has_role(current role) should have the proper description 5 | ok 3 - has_role(current role) should have the proper diagnostics 6 | ok 4 - has_role(current role, desc) should pass 7 | ok 5 - has_role(current role, desc) should have the proper description 8 | ok 6 - has_role(current role, desc) should have the proper diagnostics 9 | ok 7 - has_role(nonexistent role) should fail 10 | ok 8 - has_role(nonexistent role) should have the proper description 11 | ok 9 - has_role(nonexistent role) should have the proper diagnostics 12 | ok 10 - has_role(nonexistent role, desc) should fail 13 | ok 11 - has_role(nonexistent role, desc) should have the proper description 14 | ok 12 - has_role(nonexistent role, desc) should have the proper diagnostics 15 | ok 13 - hasnt_role(current role) should fail 16 | ok 14 - hasnt_role(current role) should have the proper description 17 | ok 15 - hasnt_role(current role) should have the proper diagnostics 18 | ok 16 - hasnt_role(current role, desc) should fail 19 | ok 17 - hasnt_role(current role, desc) should have the proper description 20 | ok 18 - hasnt_role(current role, desc) should have the proper diagnostics 21 | ok 19 - hasnt_role(nonexistent role) should pass 22 | ok 20 - hasnt_role(nonexistent role) should have the proper description 23 | ok 21 - hasnt_role(nonexistent role) should have the proper diagnostics 24 | ok 22 - hasnt_role(nonexistent role, desc) should pass 25 | ok 23 - hasnt_role(nonexistent role, desc) should have the proper description 26 | ok 24 - hasnt_role(nonexistent role, desc) should have the proper diagnostics 27 | ok 25 - roles_are(roles, desc) should pass 28 | ok 26 - roles_are(roles, desc) should have the proper description 29 | ok 27 - roles_are(roles, desc) should have the proper diagnostics 30 | ok 28 - roles_are(roles) should pass 31 | ok 29 - roles_are(roles) should have the proper description 32 | ok 30 - roles_are(roles) should have the proper diagnostics 33 | ok 31 - roles_are(roles, desc) missing should fail 34 | ok 32 - roles_are(roles, desc) missing should have the proper description 35 | ok 33 - roles_are(roles, desc) missing should have the proper diagnostics 36 | ok 34 - roles_are(roles, desc) extras should fail 37 | ok 35 - roles_are(roles, desc) extras should have the proper description 38 | ok 36 - roles_are(roles, desc) extras should have the proper diagnostics 39 | ok 37 - roles_are(roles, desc) missing and extras should fail 40 | ok 38 - roles_are(roles, desc) missing and extras should have the proper description 41 | ok 39 - roles_are(roles, desc) missing and extras should have the proper diagnostics 42 | -------------------------------------------------------------------------------- /test/expected/runjusttests.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | # Subtest: whatever."test ident"() 3 | ok 1 - ident 4 | ok 2 - ident 2 5 | 1..2 6 | ok 1 - whatever."test ident" 7 | # Subtest: whatever.testnada() 8 | 1..0 9 | # No tests run! 10 | not ok 2 - whatever.testnada 11 | # Failed test 2: "whatever.testnada" 12 | # Subtest: whatever.testplpgsql() 13 | ok 1 - plpgsql simple 14 | ok 2 - plpgsql simple 2 15 | ok 3 - Should be a 1 in the test table 16 | 1..3 17 | ok 3 - whatever.testplpgsql 18 | # Subtest: whatever.testplpgsqldie() 19 | # Test died: P0001: This test should die, but not halt execution. 20 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 21 | # DETAIL: DETAIL 22 | # SCHEMA: SCHEMA 23 | # TABLE: TABLE 24 | # COLUMN: COLUMN 25 | # CONSTRAINT: CONSTRAINT 26 | # TYPE: TYPE 27 | # CONTEXT: 28 | # PL/pgSQL function __die() line 3 at RAISE 29 | # SQL statement "SELECT __die();" 30 | # PL/pgSQL function whatever.testplpgsqldie() line 43 at EXECUTE 31 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 32 | # SQL function "runtests" statement 1 33 | # SQL function "runtests" statement 1 34 | not ok 4 - whatever.testplpgsqldie 35 | # Failed test 4: "whatever.testplpgsqldie" 36 | # Subtest: whatever.testthis() 37 | ok 1 - simple pass 38 | ok 2 - another simple pass 39 | 1..2 40 | ok 5 - whatever.testthis 41 | # Subtest: whatever.testy() 42 | ok 1 - pass 43 | not ok 2 - this test intentionally fails 44 | # Failed test 2: "this test intentionally fails" 45 | 1..2 46 | # Looks like you failed 1 test of 2 47 | not ok 6 - whatever.testy 48 | # Failed test 6: "whatever.testy" 49 | # Subtest: whatever.testz() 50 | ok 1 - Late test should find nothing in the test table 51 | 1..1 52 | ok 7 - whatever.testz 53 | 1..7 54 | # Looks like you failed 3 tests of 7 55 | -------------------------------------------------------------------------------- /test/expected/runjusttests_1.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | # Subtest: whatever."test ident"() 3 | ok 1 - ident 4 | ok 2 - ident 2 5 | 1..2 6 | ok 1 - whatever."test ident" 7 | # Subtest: whatever.testnada() 8 | 1..0 9 | # No tests run! 10 | not ok 2 - whatever.testnada 11 | # Failed test 2: "whatever.testnada" 12 | # Subtest: whatever.testplpgsql() 13 | ok 1 - plpgsql simple 14 | ok 2 - plpgsql simple 2 15 | ok 3 - Should be a 1 in the test table 16 | 1..3 17 | ok 3 - whatever.testplpgsql 18 | # Subtest: whatever.testplpgsqldie() 19 | # Test died: P0001: This test should die, but not halt execution. 20 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 21 | # DETAIL: DETAIL 22 | # SCHEMA: SCHEMA 23 | # TABLE: TABLE 24 | # COLUMN: COLUMN 25 | # CONSTRAINT: CONSTRAINT 26 | # TYPE: TYPE 27 | # CONTEXT: 28 | # SQL statement "SELECT __die();" 29 | # PL/pgSQL function whatever.testplpgsqldie() line 43 at EXECUTE statement 30 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 31 | # SQL function "runtests" statement 1 32 | # SQL function "runtests" statement 1 33 | not ok 4 - whatever.testplpgsqldie 34 | # Failed test 4: "whatever.testplpgsqldie" 35 | # Subtest: whatever.testthis() 36 | ok 1 - simple pass 37 | ok 2 - another simple pass 38 | 1..2 39 | ok 5 - whatever.testthis 40 | # Subtest: whatever.testy() 41 | ok 1 - pass 42 | not ok 2 - this test intentionally fails 43 | # Failed test 2: "this test intentionally fails" 44 | 1..2 45 | # Looks like you failed 1 test of 2 46 | not ok 6 - whatever.testy 47 | # Failed test 6: "whatever.testy" 48 | # Subtest: whatever.testz() 49 | ok 1 - Late test should find nothing in the test table 50 | 1..1 51 | ok 7 - whatever.testz 52 | 1..7 53 | # Looks like you failed 3 tests of 7 54 | -------------------------------------------------------------------------------- /test/expected/runjusttests_2.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | # Subtest: whatever."test ident"() 3 | ok 1 - ident 4 | ok 2 - ident 2 5 | 1..2 6 | ok 1 - whatever."test ident" 7 | # Subtest: whatever.testnada() 8 | 1..0 9 | # No tests run! 10 | not ok 2 - whatever.testnada 11 | # Failed test 2: "whatever.testnada" 12 | # Subtest: whatever.testplpgsql() 13 | ok 1 - plpgsql simple 14 | ok 2 - plpgsql simple 2 15 | ok 3 - Should be a 1 in the test table 16 | 1..3 17 | ok 3 - whatever.testplpgsql 18 | # Subtest: whatever.testplpgsqldie() 19 | # Test died: P0001: This test should die, but not halt execution. 20 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 21 | # DETAIL: DETAIL 22 | # CONTEXT: 23 | # SQL statement "SELECT __die();" 24 | # PL/pgSQL function whatever.testplpgsqldie() line 43 at EXECUTE statement 25 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 26 | # SQL function "runtests" statement 1 27 | # SQL function "runtests" statement 1 28 | not ok 4 - whatever.testplpgsqldie 29 | # Failed test 4: "whatever.testplpgsqldie" 30 | # Subtest: whatever.testthis() 31 | ok 1 - simple pass 32 | ok 2 - another simple pass 33 | 1..2 34 | ok 5 - whatever.testthis 35 | # Subtest: whatever.testy() 36 | ok 1 - pass 37 | not ok 2 - this test intentionally fails 38 | # Failed test 2: "this test intentionally fails" 39 | 1..2 40 | # Looks like you failed 1 test of 2 41 | not ok 6 - whatever.testy 42 | # Failed test 6: "whatever.testy" 43 | # Subtest: whatever.testz() 44 | ok 1 - Late test should find nothing in the test table 45 | 1..1 46 | ok 7 - whatever.testz 47 | 1..7 48 | # Looks like you failed 3 tests of 7 49 | -------------------------------------------------------------------------------- /test/expected/runjusttests_3.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | # Subtest: whatever."test ident"() 3 | ok 1 - ident 4 | ok 2 - ident 2 5 | 1..2 6 | ok 1 - whatever."test ident" 7 | # Subtest: whatever.testnada() 8 | 1..0 9 | # No tests run! 10 | not ok 2 - whatever.testnada 11 | # Failed test 2: "whatever.testnada" 12 | # Subtest: whatever.testplpgsql() 13 | ok 1 - plpgsql simple 14 | ok 2 - plpgsql simple 2 15 | ok 3 - Should be a 1 in the test table 16 | 1..3 17 | ok 3 - whatever.testplpgsql 18 | # Subtest: whatever.testplpgsqldie() 19 | # Test died: P0001: This test should die, but not halt execution. 20 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 21 | # DETAIL: DETAIL 22 | # CONTEXT: 23 | # SQL statement "SELECT __die();" 24 | # PL/pgSQL function whatever.testplpgsqldie() line 34 at EXECUTE statement 25 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 26 | # SQL function "runtests" statement 1 27 | # SQL function "runtests" statement 1 28 | not ok 4 - whatever.testplpgsqldie 29 | # Failed test 4: "whatever.testplpgsqldie" 30 | # Subtest: whatever.testthis() 31 | ok 1 - simple pass 32 | ok 2 - another simple pass 33 | 1..2 34 | ok 5 - whatever.testthis 35 | # Subtest: whatever.testy() 36 | ok 1 - pass 37 | not ok 2 - this test intentionally fails 38 | # Failed test 2: "this test intentionally fails" 39 | 1..2 40 | # Looks like you failed 1 test of 2 41 | not ok 6 - whatever.testy 42 | # Failed test 6: "whatever.testy" 43 | # Subtest: whatever.testz() 44 | ok 1 - Late test should find nothing in the test table 45 | 1..1 46 | ok 7 - whatever.testz 47 | 1..7 48 | # Looks like you failed 3 tests of 7 49 | -------------------------------------------------------------------------------- /test/expected/runjusttests_4.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | # Subtest: whatever."test ident"() 3 | ok 1 - ident 4 | ok 2 - ident 2 5 | 1..2 6 | ok 1 - whatever."test ident" 7 | # Subtest: whatever.testnada() 8 | 1..0 9 | # No tests run! 10 | not ok 2 - whatever.testnada 11 | # Failed test 2: "whatever.testnada" 12 | # Subtest: whatever.testplpgsql() 13 | ok 1 - plpgsql simple 14 | ok 2 - plpgsql simple 2 15 | ok 3 - Should be a 1 in the test table 16 | 1..3 17 | ok 3 - whatever.testplpgsql 18 | # Subtest: whatever.testplpgsqldie() 19 | # Test died: P0001: This test should die, but not halt execution. 20 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 21 | not ok 4 - whatever.testplpgsqldie 22 | # Failed test 4: "whatever.testplpgsqldie" 23 | # Subtest: whatever.testthis() 24 | ok 1 - simple pass 25 | ok 2 - another simple pass 26 | 1..2 27 | ok 5 - whatever.testthis 28 | # Subtest: whatever.testy() 29 | ok 1 - pass 30 | not ok 2 - this test intentionally fails 31 | # Failed test 2: "this test intentionally fails" 32 | 1..2 33 | # Looks like you failed 1 test of 2 34 | not ok 6 - whatever.testy 35 | # Failed test 6: "whatever.testy" 36 | # Subtest: whatever.testz() 37 | ok 1 - Late test should find nothing in the test table 38 | 1..1 39 | ok 7 - whatever.testz 40 | 1..7 41 | # Looks like you failed 3 tests of 7 42 | -------------------------------------------------------------------------------- /test/expected/runjusttests_5.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | # Subtest: whatever."test ident"() 3 | ok 1 - ident 4 | ok 2 - ident 2 5 | 1..2 6 | ok 1 - whatever."test ident" 7 | # Subtest: whatever.testnada() 8 | 1..0 9 | # No tests run! 10 | not ok 2 - whatever.testnada 11 | # Failed test 2: "whatever.testnada" 12 | # Subtest: whatever.testplpgsql() 13 | ok 1 - plpgsql simple 14 | ok 2 - plpgsql simple 2 15 | ok 3 - Should be a 1 in the test table 16 | 1..3 17 | ok 3 - whatever.testplpgsql 18 | # Subtest: whatever.testplpgsqldie() 19 | # Test died: P0001: This test should die, but not halt execution. 20 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 21 | # DETAIL: DETAIL 22 | # SCHEMA: SCHEMA 23 | # TABLE: TABLE 24 | # COLUMN: COLUMN 25 | # CONSTRAINT: CONSTRAINT 26 | # TYPE: TYPE 27 | # CONTEXT: 28 | # SQL statement "SELECT __die();" 29 | # PL/pgSQL function whatever.testplpgsqldie() line 43 at EXECUTE 30 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 31 | # SQL function "runtests" statement 1 32 | # SQL function "runtests" statement 1 33 | not ok 4 - whatever.testplpgsqldie 34 | # Failed test 4: "whatever.testplpgsqldie" 35 | # Subtest: whatever.testthis() 36 | ok 1 - simple pass 37 | ok 2 - another simple pass 38 | 1..2 39 | ok 5 - whatever.testthis 40 | # Subtest: whatever.testy() 41 | ok 1 - pass 42 | not ok 2 - this test intentionally fails 43 | # Failed test 2: "this test intentionally fails" 44 | 1..2 45 | # Looks like you failed 1 test of 2 46 | not ok 6 - whatever.testy 47 | # Failed test 6: "whatever.testy" 48 | # Subtest: whatever.testz() 49 | ok 1 - Late test should find nothing in the test table 50 | 1..1 51 | ok 7 - whatever.testz 52 | 1..7 53 | # Looks like you failed 3 tests of 7 54 | -------------------------------------------------------------------------------- /test/expected/runjusttests_6.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | # Subtest: whatever."test ident"() 3 | ok 1 - ident 4 | ok 2 - ident 2 5 | 1..2 6 | ok 1 - whatever."test ident" 7 | # Subtest: whatever.testnada() 8 | 1..0 9 | # No tests run! 10 | not ok 2 - whatever.testnada 11 | # Failed test 2: "whatever.testnada" 12 | # Subtest: whatever.testplpgsql() 13 | ok 1 - plpgsql simple 14 | ok 2 - plpgsql simple 2 15 | ok 3 - Should be a 1 in the test table 16 | 1..3 17 | ok 3 - whatever.testplpgsql 18 | # Subtest: whatever.testplpgsqldie() 19 | # Test died: This test should die, but not halt execution. 20 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 21 | not ok 4 - whatever.testplpgsqldie 22 | # Failed test 4: "whatever.testplpgsqldie" 23 | # Subtest: whatever.testthis() 24 | ok 1 - simple pass 25 | ok 2 - another simple pass 26 | 1..2 27 | ok 5 - whatever.testthis 28 | # Subtest: whatever.testy() 29 | ok 1 - pass 30 | not ok 2 - this test intentionally fails 31 | # Failed test 2: "this test intentionally fails" 32 | 1..2 33 | # Looks like you failed 1 test of 2 34 | not ok 6 - whatever.testy 35 | # Failed test 6: "whatever.testy" 36 | # Subtest: whatever.testz() 37 | ok 1 - Late test should find nothing in the test table 38 | 1..1 39 | ok 7 - whatever.testz 40 | 1..7 41 | # Looks like you failed 3 tests of 7 42 | -------------------------------------------------------------------------------- /test/expected/runnotests.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | # Subtest: whatever.testthis() 3 | 1..0 4 | # No tests run! 5 | not ok 1 - whatever.testthis 6 | # Failed test 1: "whatever.testthis" 7 | 1..1 8 | # Looks like you failed 1 test of 1 9 | -------------------------------------------------------------------------------- /test/expected/runtests_1.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | ok 1 - starting up 3 | ok 2 - starting up some more 4 | # Subtest: whatever."test ident"() 5 | ok 1 - setup 6 | ok 2 - Should be nothing in the test table 7 | ok 3 - setup more 8 | ok 4 - ident 9 | ok 5 - ident 2 10 | ok 6 - teardown 11 | ok 7 - teardown more 12 | 1..7 13 | ok 3 - whatever."test ident" 14 | # Subtest: whatever.testdividebyzero() 15 | ok 1 - setup 16 | ok 2 - Should be nothing in the test table 17 | ok 3 - setup more 18 | # Test died: 22012: division by zero 19 | # CONTEXT: 20 | # SQL function "testdividebyzero" during startup 21 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 22 | # SQL function "runtests" statement 1 23 | # SQL function "runtests" statement 1 24 | not ok 4 - whatever.testdividebyzero 25 | # Failed test 4: "whatever.testdividebyzero" 26 | # Subtest: whatever.testplpgsql() 27 | ok 1 - setup 28 | ok 2 - Should be nothing in the test table 29 | ok 3 - setup more 30 | ok 4 - plpgsql simple 31 | ok 5 - plpgsql simple 2 32 | ok 6 - Should be a 1 in the test table 33 | ok 7 - teardown 34 | ok 8 - teardown more 35 | 1..8 36 | ok 5 - whatever.testplpgsql 37 | # Subtest: whatever.testplpgsqldie() 38 | ok 1 - setup 39 | ok 2 - Should be nothing in the test table 40 | ok 3 - setup more 41 | # Test died: P0001: This test should die, but not halt execution. 42 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 43 | # DETAIL: DETAIL 44 | # SCHEMA: SCHEMA 45 | # TABLE: TABLE 46 | # COLUMN: COLUMN 47 | # CONSTRAINT: CONSTRAINT 48 | # TYPE: TYPE 49 | # CONTEXT: 50 | # SQL statement "SELECT __die();" 51 | # PL/pgSQL function whatever.testplpgsqldie() line 23 at EXECUTE 52 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 53 | # SQL function "runtests" statement 1 54 | # SQL function "runtests" statement 1 55 | not ok 6 - whatever.testplpgsqldie 56 | # Failed test 6: "whatever.testplpgsqldie" 57 | # Subtest: whatever.testthis() 58 | ok 1 - setup 59 | ok 2 - Should be nothing in the test table 60 | ok 3 - setup more 61 | ok 4 - simple pass 62 | ok 5 - another simple pass 63 | ok 6 - teardown 64 | ok 7 - teardown more 65 | 1..7 66 | ok 7 - whatever.testthis 67 | # Subtest: whatever.testy() 68 | ok 1 - setup 69 | ok 2 - Should be nothing in the test table 70 | ok 3 - setup more 71 | not ok 4 - this test intentionally fails 72 | # Failed test 4: "this test intentionally fails" 73 | ok 5 - teardown 74 | ok 6 - teardown more 75 | 1..6 76 | # Looks like you failed 1 test of 6 77 | not ok 8 - whatever.testy 78 | # Failed test 8: "whatever.testy" 79 | # Subtest: whatever.testz() 80 | ok 1 - setup 81 | ok 2 - Should be nothing in the test table 82 | ok 3 - setup more 83 | ok 4 - Late test should find nothing in the test table 84 | ok 5 - teardown 85 | ok 6 - teardown more 86 | 1..6 87 | ok 9 - whatever.testz 88 | ok 10 - shutting down 89 | ok 11 - shutting down more 90 | 1..11 91 | # Looks like you failed 3 tests of 11 92 | ok 1 - starting up 93 | ok 2 - starting up some more 94 | # Subtest: whatever."test ident"() 95 | ok 1 - setup 96 | ok 2 - Should be nothing in the test table 97 | ok 3 - setup more 98 | ok 4 - ident 99 | ok 5 - ident 2 100 | ok 6 - teardown 101 | ok 7 - teardown more 102 | 1..7 103 | ok 3 - whatever."test ident" 104 | # Subtest: whatever.testdividebyzero() 105 | ok 1 - setup 106 | ok 2 - Should be nothing in the test table 107 | ok 3 - setup more 108 | # Test died: 22012: division by zero 109 | # CONTEXT: 110 | # SQL function "testdividebyzero" during startup 111 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 112 | # SQL function "runtests" statement 1 113 | not ok 4 - whatever.testdividebyzero 114 | # Failed test 4: "whatever.testdividebyzero" 115 | # Subtest: whatever.testplpgsql() 116 | ok 1 - setup 117 | ok 2 - Should be nothing in the test table 118 | ok 3 - setup more 119 | ok 4 - plpgsql simple 120 | ok 5 - plpgsql simple 2 121 | ok 6 - Should be a 1 in the test table 122 | ok 7 - teardown 123 | ok 8 - teardown more 124 | 1..8 125 | ok 5 - whatever.testplpgsql 126 | # Subtest: whatever.testplpgsqldie() 127 | ok 1 - setup 128 | ok 2 - Should be nothing in the test table 129 | ok 3 - setup more 130 | # Test died: P0001: This test should die, but not halt execution. 131 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 132 | # DETAIL: DETAIL 133 | # SCHEMA: SCHEMA 134 | # TABLE: TABLE 135 | # COLUMN: COLUMN 136 | # CONSTRAINT: CONSTRAINT 137 | # TYPE: TYPE 138 | # CONTEXT: 139 | # SQL statement "SELECT __die();" 140 | # PL/pgSQL function whatever.testplpgsqldie() line 23 at EXECUTE 141 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 142 | # SQL function "runtests" statement 1 143 | not ok 6 - whatever.testplpgsqldie 144 | # Failed test 6: "whatever.testplpgsqldie" 145 | # Subtest: whatever.testthis() 146 | ok 1 - setup 147 | ok 2 - Should be nothing in the test table 148 | ok 3 - setup more 149 | ok 4 - simple pass 150 | ok 5 - another simple pass 151 | ok 6 - teardown 152 | ok 7 - teardown more 153 | 1..7 154 | ok 7 - whatever.testthis 155 | # Subtest: whatever.testy() 156 | ok 1 - setup 157 | ok 2 - Should be nothing in the test table 158 | ok 3 - setup more 159 | not ok 4 - this test intentionally fails 160 | # Failed test 4: "this test intentionally fails" 161 | ok 5 - teardown 162 | ok 6 - teardown more 163 | 1..6 164 | # Looks like you failed 1 test of 6 165 | not ok 8 - whatever.testy 166 | # Failed test 8: "whatever.testy" 167 | # Subtest: whatever.testz() 168 | ok 1 - setup 169 | ok 2 - Should be nothing in the test table 170 | ok 3 - setup more 171 | ok 4 - Late test should find nothing in the test table 172 | ok 5 - teardown 173 | ok 6 - teardown more 174 | 1..6 175 | ok 9 - whatever.testz 176 | ok 10 - shutting down 177 | ok 11 - shutting down more 178 | 1..11 179 | # Looks like you failed 3 tests of 11 180 | -------------------------------------------------------------------------------- /test/expected/runtests_3.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | ok 1 - starting up 3 | ok 2 - starting up some more 4 | # Subtest: whatever."test ident"() 5 | ok 1 - setup 6 | ok 2 - Should be nothing in the test table 7 | ok 3 - setup more 8 | ok 4 - ident 9 | ok 5 - ident 2 10 | ok 6 - teardown 11 | ok 7 - teardown more 12 | 1..7 13 | ok 3 - whatever."test ident" 14 | # Subtest: whatever.testdividebyzero() 15 | ok 1 - setup 16 | ok 2 - Should be nothing in the test table 17 | ok 3 - setup more 18 | # Test died: 22012: division by zero 19 | # CONTEXT: 20 | # SQL function "testdividebyzero" during startup 21 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 22 | # SQL function "runtests" statement 1 23 | # SQL function "runtests" statement 1 24 | not ok 4 - whatever.testdividebyzero 25 | # Failed test 4: "whatever.testdividebyzero" 26 | # Subtest: whatever.testplpgsql() 27 | ok 1 - setup 28 | ok 2 - Should be nothing in the test table 29 | ok 3 - setup more 30 | ok 4 - plpgsql simple 31 | ok 5 - plpgsql simple 2 32 | ok 6 - Should be a 1 in the test table 33 | ok 7 - teardown 34 | ok 8 - teardown more 35 | 1..8 36 | ok 5 - whatever.testplpgsql 37 | # Subtest: whatever.testplpgsqldie() 38 | ok 1 - setup 39 | ok 2 - Should be nothing in the test table 40 | ok 3 - setup more 41 | # Test died: P0001: This test should die, but not halt execution. 42 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 43 | # DETAIL: DETAIL 44 | # CONTEXT: 45 | # SQL statement "SELECT __die();" 46 | # PL/pgSQL function whatever.testplpgsqldie() line 34 at EXECUTE statement 47 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 48 | # SQL function "runtests" statement 1 49 | # SQL function "runtests" statement 1 50 | not ok 6 - whatever.testplpgsqldie 51 | # Failed test 6: "whatever.testplpgsqldie" 52 | # Subtest: whatever.testthis() 53 | ok 1 - setup 54 | ok 2 - Should be nothing in the test table 55 | ok 3 - setup more 56 | ok 4 - simple pass 57 | ok 5 - another simple pass 58 | ok 6 - teardown 59 | ok 7 - teardown more 60 | 1..7 61 | ok 7 - whatever.testthis 62 | # Subtest: whatever.testy() 63 | ok 1 - setup 64 | ok 2 - Should be nothing in the test table 65 | ok 3 - setup more 66 | not ok 4 - this test intentionally fails 67 | # Failed test 4: "this test intentionally fails" 68 | ok 5 - teardown 69 | ok 6 - teardown more 70 | 1..6 71 | # Looks like you failed 1 test of 6 72 | not ok 8 - whatever.testy 73 | # Failed test 8: "whatever.testy" 74 | # Subtest: whatever.testz() 75 | ok 1 - setup 76 | ok 2 - Should be nothing in the test table 77 | ok 3 - setup more 78 | ok 4 - Late test should find nothing in the test table 79 | ok 5 - teardown 80 | ok 6 - teardown more 81 | 1..6 82 | ok 9 - whatever.testz 83 | ok 10 - shutting down 84 | ok 11 - shutting down more 85 | 1..11 86 | # Looks like you failed 3 tests of 11 87 | ok 1 - starting up 88 | ok 2 - starting up some more 89 | # Subtest: whatever."test ident"() 90 | ok 1 - setup 91 | ok 2 - Should be nothing in the test table 92 | ok 3 - setup more 93 | ok 4 - ident 94 | ok 5 - ident 2 95 | ok 6 - teardown 96 | ok 7 - teardown more 97 | 1..7 98 | ok 3 - whatever."test ident" 99 | # Subtest: whatever.testdividebyzero() 100 | ok 1 - setup 101 | ok 2 - Should be nothing in the test table 102 | ok 3 - setup more 103 | # Test died: 22012: division by zero 104 | # CONTEXT: 105 | # SQL function "testdividebyzero" during startup 106 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 107 | # SQL function "runtests" statement 1 108 | not ok 4 - whatever.testdividebyzero 109 | # Failed test 4: "whatever.testdividebyzero" 110 | # Subtest: whatever.testplpgsql() 111 | ok 1 - setup 112 | ok 2 - Should be nothing in the test table 113 | ok 3 - setup more 114 | ok 4 - plpgsql simple 115 | ok 5 - plpgsql simple 2 116 | ok 6 - Should be a 1 in the test table 117 | ok 7 - teardown 118 | ok 8 - teardown more 119 | 1..8 120 | ok 5 - whatever.testplpgsql 121 | # Subtest: whatever.testplpgsqldie() 122 | ok 1 - setup 123 | ok 2 - Should be nothing in the test table 124 | ok 3 - setup more 125 | # Test died: P0001: This test should die, but not halt execution. 126 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 127 | # DETAIL: DETAIL 128 | # CONTEXT: 129 | # SQL statement "SELECT __die();" 130 | # PL/pgSQL function whatever.testplpgsqldie() line 34 at EXECUTE statement 131 | # PL/pgSQL function _runner(text[],text[],text[],text[],text[]) line 62 at FOR over EXECUTE statement 132 | # SQL function "runtests" statement 1 133 | not ok 6 - whatever.testplpgsqldie 134 | # Failed test 6: "whatever.testplpgsqldie" 135 | # Subtest: whatever.testthis() 136 | ok 1 - setup 137 | ok 2 - Should be nothing in the test table 138 | ok 3 - setup more 139 | ok 4 - simple pass 140 | ok 5 - another simple pass 141 | ok 6 - teardown 142 | ok 7 - teardown more 143 | 1..7 144 | ok 7 - whatever.testthis 145 | # Subtest: whatever.testy() 146 | ok 1 - setup 147 | ok 2 - Should be nothing in the test table 148 | ok 3 - setup more 149 | not ok 4 - this test intentionally fails 150 | # Failed test 4: "this test intentionally fails" 151 | ok 5 - teardown 152 | ok 6 - teardown more 153 | 1..6 154 | # Looks like you failed 1 test of 6 155 | not ok 8 - whatever.testy 156 | # Failed test 8: "whatever.testy" 157 | # Subtest: whatever.testz() 158 | ok 1 - setup 159 | ok 2 - Should be nothing in the test table 160 | ok 3 - setup more 161 | ok 4 - Late test should find nothing in the test table 162 | ok 5 - teardown 163 | ok 6 - teardown more 164 | 1..6 165 | ok 9 - whatever.testz 166 | ok 10 - shutting down 167 | ok 11 - shutting down more 168 | 1..11 169 | # Looks like you failed 3 tests of 11 170 | -------------------------------------------------------------------------------- /test/expected/runtests_4.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | ok 1 - starting up 3 | ok 2 - starting up some more 4 | # Subtest: whatever."test ident"() 5 | ok 1 - setup 6 | ok 2 - Should be nothing in the test table 7 | ok 3 - setup more 8 | ok 4 - ident 9 | ok 5 - ident 2 10 | ok 6 - teardown 11 | ok 7 - teardown more 12 | 1..7 13 | ok 3 - whatever."test ident" 14 | # Subtest: whatever.testdividebyzero() 15 | ok 1 - setup 16 | ok 2 - Should be nothing in the test table 17 | ok 3 - setup more 18 | # Test died: 22012: division by zero 19 | not ok 4 - whatever.testdividebyzero 20 | # Failed test 4: "whatever.testdividebyzero" 21 | # Subtest: whatever.testplpgsql() 22 | ok 1 - setup 23 | ok 2 - Should be nothing in the test table 24 | ok 3 - setup more 25 | ok 4 - plpgsql simple 26 | ok 5 - plpgsql simple 2 27 | ok 6 - Should be a 1 in the test table 28 | ok 7 - teardown 29 | ok 8 - teardown more 30 | 1..8 31 | ok 5 - whatever.testplpgsql 32 | # Subtest: whatever.testplpgsqldie() 33 | ok 1 - setup 34 | ok 2 - Should be nothing in the test table 35 | ok 3 - setup more 36 | # Test died: P0001: This test should die, but not halt execution. 37 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 38 | not ok 6 - whatever.testplpgsqldie 39 | # Failed test 6: "whatever.testplpgsqldie" 40 | # Subtest: whatever.testthis() 41 | ok 1 - setup 42 | ok 2 - Should be nothing in the test table 43 | ok 3 - setup more 44 | ok 4 - simple pass 45 | ok 5 - another simple pass 46 | ok 6 - teardown 47 | ok 7 - teardown more 48 | 1..7 49 | ok 7 - whatever.testthis 50 | # Subtest: whatever.testy() 51 | ok 1 - setup 52 | ok 2 - Should be nothing in the test table 53 | ok 3 - setup more 54 | not ok 4 - this test intentionally fails 55 | # Failed test 4: "this test intentionally fails" 56 | ok 5 - teardown 57 | ok 6 - teardown more 58 | 1..6 59 | # Looks like you failed 1 test of 6 60 | not ok 8 - whatever.testy 61 | # Failed test 8: "whatever.testy" 62 | # Subtest: whatever.testz() 63 | ok 1 - setup 64 | ok 2 - Should be nothing in the test table 65 | ok 3 - setup more 66 | ok 4 - Late test should find nothing in the test table 67 | ok 5 - teardown 68 | ok 6 - teardown more 69 | 1..6 70 | ok 9 - whatever.testz 71 | ok 10 - shutting down 72 | ok 11 - shutting down more 73 | 1..11 74 | # Looks like you failed 3 tests of 11 75 | ok 1 - starting up 76 | ok 2 - starting up some more 77 | # Subtest: whatever."test ident"() 78 | ok 1 - setup 79 | ok 2 - Should be nothing in the test table 80 | ok 3 - setup more 81 | ok 4 - ident 82 | ok 5 - ident 2 83 | ok 6 - teardown 84 | ok 7 - teardown more 85 | 1..7 86 | ok 3 - whatever."test ident" 87 | # Subtest: whatever.testdividebyzero() 88 | ok 1 - setup 89 | ok 2 - Should be nothing in the test table 90 | ok 3 - setup more 91 | # Test died: 22012: division by zero 92 | not ok 4 - whatever.testdividebyzero 93 | # Failed test 4: "whatever.testdividebyzero" 94 | # Subtest: whatever.testplpgsql() 95 | ok 1 - setup 96 | ok 2 - Should be nothing in the test table 97 | ok 3 - setup more 98 | ok 4 - plpgsql simple 99 | ok 5 - plpgsql simple 2 100 | ok 6 - Should be a 1 in the test table 101 | ok 7 - teardown 102 | ok 8 - teardown more 103 | 1..8 104 | ok 5 - whatever.testplpgsql 105 | # Subtest: whatever.testplpgsqldie() 106 | ok 1 - setup 107 | ok 2 - Should be nothing in the test table 108 | ok 3 - setup more 109 | # Test died: P0001: This test should die, but not halt execution. 110 | # Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself. 111 | not ok 6 - whatever.testplpgsqldie 112 | # Failed test 6: "whatever.testplpgsqldie" 113 | # Subtest: whatever.testthis() 114 | ok 1 - setup 115 | ok 2 - Should be nothing in the test table 116 | ok 3 - setup more 117 | ok 4 - simple pass 118 | ok 5 - another simple pass 119 | ok 6 - teardown 120 | ok 7 - teardown more 121 | 1..7 122 | ok 7 - whatever.testthis 123 | # Subtest: whatever.testy() 124 | ok 1 - setup 125 | ok 2 - Should be nothing in the test table 126 | ok 3 - setup more 127 | not ok 4 - this test intentionally fails 128 | # Failed test 4: "this test intentionally fails" 129 | ok 5 - teardown 130 | ok 6 - teardown more 131 | 1..6 132 | # Looks like you failed 1 test of 6 133 | not ok 8 - whatever.testy 134 | # Failed test 8: "whatever.testy" 135 | # Subtest: whatever.testz() 136 | ok 1 - setup 137 | ok 2 - Should be nothing in the test table 138 | ok 3 - setup more 139 | ok 4 - Late test should find nothing in the test table 140 | ok 5 - teardown 141 | ok 6 - teardown more 142 | 1..6 143 | ok 9 - whatever.testz 144 | ok 10 - shutting down 145 | ok 11 - shutting down more 146 | 1..11 147 | # Looks like you failed 3 tests of 11 148 | -------------------------------------------------------------------------------- /test/expected/throwtap.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..97 3 | ok 1 - four-argument form should pass 4 | ok 2 - four-argument form should have the proper description 5 | ok 3 - four-argument form should have the proper diagnostics 6 | ok 4 - three-argument errcode should pass 7 | ok 5 - three-argument errcode should have the proper description 8 | ok 6 - three-argument errcode should have the proper diagnostics 9 | ok 7 - two-argument errcode should pass 10 | ok 8 - two-argument errcode should have the proper description 11 | ok 9 - three argument errmsg should pass 12 | ok 10 - three argument errmsg should have the proper description 13 | ok 11 - three argument errmsg should have the proper diagnostics 14 | ok 12 - two-argument errmsg should pass 15 | ok 13 - two-argument errmsg should have the proper description 16 | ok 14 - two-argument errmsg should have the proper diagnostics 17 | ok 15 - single-argument form should pass 18 | ok 16 - single-argument form should have the proper description 19 | ok 17 - single-argument form should have the proper diagnostics 20 | ok 18 - prepared statement & errcode should pass 21 | ok 19 - prepared statement & errcode should have the proper description 22 | ok 20 - execute & errcode should pass 23 | ok 21 - execute & errcode should have the proper description 24 | ok 22 - invalid errcode should fail 25 | ok 23 - invalid errcode should have the proper description 26 | ok 24 - invalid errcode should have the proper diagnostics 27 | ok 25 - throws_ok(1/0, NULL) should work 28 | ok 26 - throws_ok diagnostics should fail 29 | ok 27 - throws_ok diagnostics should have the proper description 30 | ok 28 - throws_ok diagnostics should have the proper diagnostics 31 | ok 29 - lives_ok() should work 32 | ok 30 - lives_ok(prepared) should pass 33 | ok 31 - lives_ok(prepared) should have the proper description 34 | ok 32 - lives_ok(execute) should pass 35 | ok 33 - lives_ok(execute) should have the proper description 36 | ok 34 - lives_ok failure diagnostics should fail 37 | ok 35 - lives_ok failure diagnostics should have the proper description 38 | ok 36 - lives_ok failure diagnostics should have the proper diagnostics 39 | ok 37 - throws_like(sql, pattern, desc) should pass 40 | ok 38 - throws_like(sql, pattern, desc) should have the proper description 41 | ok 39 - throws_like(sql, pattern, desc) should have the proper diagnostics 42 | ok 40 - throws_like(sql, pattern) should pass 43 | ok 41 - throws_like(sql, pattern) should have the proper description 44 | ok 42 - throws_like(sql, pattern) should have the proper diagnostics 45 | ok 43 - throws_like(sql, pattern, desc) fail should fail 46 | ok 44 - throws_like(sql, pattern, desc) fail should have the proper description 47 | ok 45 - throws_like(sql, pattern, desc) fail should have the proper diagnostics 48 | ok 46 - throws_like(valid sql, pattern, desc) should fail 49 | ok 47 - throws_like(valid sql, pattern, desc) should have the proper description 50 | ok 48 - throws_like(valid sql, pattern, desc) should have the proper diagnostics 51 | ok 49 - throws_ilike(sql, pattern, desc) should pass 52 | ok 50 - throws_ilike(sql, pattern, desc) should have the proper description 53 | ok 51 - throws_ilike(sql, pattern, desc) should have the proper diagnostics 54 | ok 52 - throws_ilike(sql, pattern) should pass 55 | ok 53 - throws_ilike(sql, pattern) should have the proper description 56 | ok 54 - throws_ilike(sql, pattern) should have the proper diagnostics 57 | ok 55 - throws_ilike(sql, pattern, desc) fail should fail 58 | ok 56 - throws_ilike(sql, pattern, desc) fail should have the proper description 59 | ok 57 - throws_ilike(sql, pattern, desc) fail should have the proper diagnostics 60 | ok 58 - throws_ilike(valid sql, pattern, desc) should fail 61 | ok 59 - throws_ilike(valid sql, pattern, desc) should have the proper description 62 | ok 60 - throws_ilike(valid sql, pattern, desc) should have the proper diagnostics 63 | ok 61 - throws_matching(sql, regex, desc) should pass 64 | ok 62 - throws_matching(sql, regex, desc) should have the proper description 65 | ok 63 - throws_matching(sql, regex, desc) should have the proper diagnostics 66 | ok 64 - throws_matching(sql, regex, desc) should pass 67 | ok 65 - throws_matching(sql, regex, desc) should have the proper description 68 | ok 66 - throws_matching(sql, regex, desc) should have the proper diagnostics 69 | ok 67 - throws_matching(sql, regex, desc) should fail 70 | ok 68 - throws_matching(sql, regex, desc) should have the proper description 71 | ok 69 - throws_matching(sql, regex, desc) should have the proper diagnostics 72 | ok 70 - throws_matching(valid sql, regex, desc) should fail 73 | ok 71 - throws_matching(valid sql, regex, desc) should have the proper description 74 | ok 72 - throws_matching(valid sql, regex, desc) should have the proper diagnostics 75 | ok 73 - throws_imatching(sql, regex, desc) should pass 76 | ok 74 - throws_imatching(sql, regex, desc) should have the proper description 77 | ok 75 - throws_imatching(sql, regex, desc) should have the proper diagnostics 78 | ok 76 - throws_imatching(sql, regex, desc) should pass 79 | ok 77 - throws_imatching(sql, regex, desc) should have the proper description 80 | ok 78 - throws_imatching(sql, regex, desc) should have the proper diagnostics 81 | ok 79 - throws_imatching(sql, regex, desc) should fail 82 | ok 80 - throws_imatching(sql, regex, desc) should have the proper description 83 | ok 81 - throws_imatching(sql, regex, desc) should have the proper diagnostics 84 | ok 82 - throws_imatching(valid sql, regex, desc) should fail 85 | ok 83 - throws_imatching(valid sql, regex, desc) should have the proper description 86 | ok 84 - throws_imatching(valid sql, regex, desc) should have the proper diagnostics 87 | ok 85 - Create check_assert function 88 | ok 86 - throws_ok catches assert should pass 89 | ok 87 - throws_ok catches assert should have the proper description 90 | ok 88 - throws_ok catches assert should have the proper diagnostics 91 | ok 89 - throws_ok does not accept passing assert should fail 92 | ok 90 - throws_ok does not accept passing assert should have the proper description 93 | ok 91 - throws_ok does not accept passing assert should have the proper diagnostics 94 | ok 92 - lives_ok calling check_assert(true) should pass 95 | ok 93 - lives_ok calling check_assert(true) should have the proper description 96 | ok 94 - lives_ok calling check_assert(true) should have the proper diagnostics 97 | ok 95 - lives_ok with check_assert(false) should fail 98 | ok 96 - lives_ok with check_assert(false) should have the proper description 99 | ok 97 - lives_ok with check_assert(false) should have the proper diagnostics 100 | -------------------------------------------------------------------------------- /test/expected/todotap.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..36 3 | ok 1 - todo fail 4 | ok 2 - todo pass 5 | ok 3 - TODO tests should display properly 6 | ok 4 - todo fail 7 | ok 5 - Single default todo test should display properly 8 | ok 6 - todo fail 9 | ok 7 - todo pass 10 | ok 8 - TODO tests should display properly 11 | ok 9 - simple skip should pass 12 | ok 10 - simple skip should have the proper description 13 | ok 11 - simple skip should have the proper diagnostics 14 | ok 12 - skip with num should pass 15 | ok 13 - skip with num should have the proper description 16 | ok 14 - skip with num should have the proper diagnostics 17 | ok 15 - Skip multiple 18 | ok 16 - Skip multiple 19 | ok 17 - Skip multiple 20 | ok 18 - We should get the proper output for multiple skips 21 | ok 19 - inverted skip should pass 22 | ok 20 - inverted skip should have the proper description 23 | ok 21 - inverted skip should have the proper diagnostics 24 | ok 22 - num only should pass 25 | ok 23 - num only should have the proper description 26 | ok 24 - num only should have the proper diagnostics 27 | ok 25 - todo fail 28 | ok 26 - todo fail 29 | ok 27 - todo fail 30 | ok 28 - Nested todos should work properly 31 | ok 29 - todo fail 32 | ok 30 - todo fail 33 | ok 31 - todo fail 34 | ok 32 - todo_start() and todo_end() should work properly with in_todo() 35 | ok 33 - todo fail 36 | ok 34 - todo pass 37 | ok 35 - Should be able to revers the arguments to todo() 38 | ok 36 - Should get an exception when todo_end() is called without todo_start() 39 | -------------------------------------------------------------------------------- /test/expected/trigger.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..84 3 | ok 1 - has_trigger(schema, table, trigger, desc) should pass 4 | ok 2 - has_trigger(schema, table, trigger, desc) should have the proper description 5 | ok 3 - has_trigger(schema, table, trigger, desc) should have the proper diagnostics 6 | ok 4 - has_trigger(schema, table, trigger) should pass 7 | ok 5 - has_trigger(schema, table, trigger) should have the proper description 8 | ok 6 - has_trigger(schema, table, trigger) should have the proper diagnostics 9 | ok 7 - has_trigger(table, trigger, desc) should pass 10 | ok 8 - has_trigger(table, trigger, desc) should have the proper description 11 | ok 9 - has_trigger(table, trigger, desc) should have the proper diagnostics 12 | ok 10 - has_trigger(table, trigger) should pass 13 | ok 11 - has_trigger(table, trigger) should have the proper description 14 | ok 12 - has_trigger(table, trigger) should have the proper diagnostics 15 | ok 13 - has_trigger(schema, table, nonexistent, desc) should fail 16 | ok 14 - has_trigger(schema, table, nonexistent, desc) should have the proper description 17 | ok 15 - has_trigger(schema, table, nonexistent, desc) should have the proper diagnostics 18 | ok 16 - has_trigger(table, nonexistent) no schema fail should fail 19 | ok 17 - has_trigger(table, nonexistent) no schema fail should have the proper description 20 | ok 18 - has_trigger(table, nonexistent) no schema fail should have the proper diagnostics 21 | ok 19 - hasnt_trigger(schema, table, trigger, desc) should fail 22 | ok 20 - hasnt_trigger(schema, table, trigger, desc) should have the proper description 23 | ok 21 - hasnt_trigger(schema, table, trigger, desc) should have the proper diagnostics 24 | ok 22 - hasnt_trigger(schema, table, trigger) should fail 25 | ok 23 - hasnt_trigger(schema, table, trigger) should have the proper description 26 | ok 24 - hasnt_trigger(schema, table, trigger) should have the proper diagnostics 27 | ok 25 - hasnt_trigger(table, trigger, desc) should fail 28 | ok 26 - hasnt_trigger(table, trigger, desc) should have the proper description 29 | ok 27 - hasnt_trigger(table, trigger, desc) should have the proper diagnostics 30 | ok 28 - hasnt_trigger(table, trigger) should fail 31 | ok 29 - hasnt_trigger(table, trigger) should have the proper description 32 | ok 30 - hasnt_trigger(table, trigger) should have the proper diagnostics 33 | ok 31 - hasnt_trigger(schema, table, nonexistent, desc) should pass 34 | ok 32 - hasnt_trigger(schema, table, nonexistent, desc) should have the proper description 35 | ok 33 - hasnt_trigger(schema, table, nonexistent, desc) should have the proper diagnostics 36 | ok 34 - hasnt_trigger(table, nonexistent) no schema fail should pass 37 | ok 35 - hasnt_trigger(table, nonexistent) no schema fail should have the proper description 38 | ok 36 - hasnt_trigger(table, nonexistent) no schema fail should have the proper diagnostics 39 | ok 37 - trigger_is() should pass 40 | ok 38 - trigger_is() should have the proper description 41 | ok 39 - trigger_is() should have the proper diagnostics 42 | ok 40 - trigger_is() no desc should pass 43 | ok 41 - trigger_is() no desc should have the proper description 44 | ok 42 - trigger_is() no desc should have the proper diagnostics 45 | ok 43 - trigger_is() no schema should pass 46 | ok 44 - trigger_is() no schema should have the proper description 47 | ok 45 - trigger_is() no schema should have the proper diagnostics 48 | ok 46 - trigger_is() no schema or desc should pass 49 | ok 47 - trigger_is() no schema or desc should have the proper description 50 | ok 48 - trigger_is() no schema or desc should have the proper diagnostics 51 | ok 49 - trigger_is() fail should fail 52 | ok 50 - trigger_is() fail should have the proper description 53 | ok 51 - trigger_is() fail should have the proper diagnostics 54 | ok 52 - trigger_is() no schema fail should fail 55 | ok 53 - trigger_is() no schema fail should have the proper description 56 | ok 54 - trigger_is() no schema fail should have the proper diagnostics 57 | ok 55 - triggers_are(schema, table, triggers, desc) should pass 58 | ok 56 - triggers_are(schema, table, triggers, desc) should have the proper description 59 | ok 57 - triggers_are(schema, table, triggers, desc) should have the proper diagnostics 60 | ok 58 - triggers_are(schema, table, triggers) should pass 61 | ok 59 - triggers_are(schema, table, triggers) should have the proper description 62 | ok 60 - triggers_are(schema, table, triggers) should have the proper diagnostics 63 | ok 61 - triggers_are(schema, table, triggers) + extra should fail 64 | ok 62 - triggers_are(schema, table, triggers) + extra should have the proper description 65 | ok 63 - triggers_are(schema, table, triggers) + extra should have the proper diagnostics 66 | ok 64 - triggers_are(schema, table, triggers) + missing should fail 67 | ok 65 - triggers_are(schema, table, triggers) + missing should have the proper description 68 | ok 66 - triggers_are(schema, table, triggers) + missing should have the proper diagnostics 69 | ok 67 - triggers_are(schema, table, triggers) + extra & missing should fail 70 | ok 68 - triggers_are(schema, table, triggers) + extra & missing should have the proper description 71 | ok 69 - triggers_are(schema, table, triggers) + extra & missing should have the proper diagnostics 72 | ok 70 - triggers_are(table, triggers, desc) should pass 73 | ok 71 - triggers_are(table, triggers, desc) should have the proper description 74 | ok 72 - triggers_are(table, triggers, desc) should have the proper diagnostics 75 | ok 73 - triggers_are(table, triggers) should pass 76 | ok 74 - triggers_are(table, triggers) should have the proper description 77 | ok 75 - triggers_are(table, triggers) should have the proper diagnostics 78 | ok 76 - triggers_are(table, triggers) + extra should fail 79 | ok 77 - triggers_are(table, triggers) + extra should have the proper description 80 | ok 78 - triggers_are(table, triggers) + extra should have the proper diagnostics 81 | ok 79 - triggers_are(table, triggers) + missing should fail 82 | ok 80 - triggers_are(table, triggers) + missing should have the proper description 83 | ok 81 - triggers_are(table, triggers) + missing should have the proper diagnostics 84 | ok 82 - triggers_are(table, triggers) + extra & missing should fail 85 | ok 83 - triggers_are(table, triggers) + extra & missing should have the proper description 86 | ok 84 - triggers_are(table, triggers) + extra & missing should have the proper diagnostics 87 | -------------------------------------------------------------------------------- /test/expected/unique.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..54 3 | ok 1 - has_unique( schema, table, description ) should pass 4 | ok 2 - has_unique( schema, table, description ) should have the proper description 5 | ok 3 - has_unique( schema, table, description ) should have the proper diagnostics 6 | ok 4 - has_unique( table, description ) should pass 7 | ok 5 - has_unique( table, description ) should have the proper description 8 | ok 6 - has_unique( table, description ) should have the proper diagnostics 9 | ok 7 - has_unique( table ) should pass 10 | ok 8 - has_unique( table ) should have the proper description 11 | ok 9 - has_unique( table ) should have the proper diagnostics 12 | ok 10 - has_unique( schema, table, description ) fail should fail 13 | ok 11 - has_unique( schema, table, description ) fail should have the proper description 14 | ok 12 - has_unique( schema, table, description ) fail should have the proper diagnostics 15 | ok 13 - has_unique( table, description ) fail should fail 16 | ok 14 - has_unique( table, description ) fail should have the proper description 17 | ok 15 - has_unique( table, description ) fail should have the proper diagnostics 18 | ok 16 - col_is_unique( schema, table, column, description ) should pass 19 | ok 17 - col_is_unique( schema, table, column, description ) should have the proper description 20 | ok 18 - col_is_unique( schema, table, column, description ) should have the proper diagnostics 21 | ok 19 - col_is_unique( schema, table, columns, description ) should pass 22 | ok 20 - col_is_unique( schema, table, columns, description ) should have the proper description 23 | ok 21 - col_is_unique( schema, table, columns, description ) should have the proper diagnostics 24 | ok 22 - col_is_unique( table, column, description ) should pass 25 | ok 23 - col_is_unique( table, column, description ) should have the proper description 26 | ok 24 - col_is_unique( table, column, description ) should have the proper diagnostics 27 | ok 25 - col_is_unique( table, columns, description ) should pass 28 | ok 26 - col_is_unique( table, columns, description ) should have the proper description 29 | ok 27 - col_is_unique( table, columns, description ) should have the proper diagnostics 30 | ok 28 - col_is_unique( schema, table, column ) should pass 31 | ok 29 - col_is_unique( schema, table, column ) should have the proper description 32 | ok 30 - col_is_unique( schema, table, column ) should have the proper diagnostics 33 | ok 31 - col_is_unique( schema, table, columns ) should pass 34 | ok 32 - col_is_unique( schema, table, columns ) should have the proper description 35 | ok 33 - col_is_unique( schema, table, columns ) should have the proper diagnostics 36 | ok 34 - col_is_unique( table, column ) should pass 37 | ok 35 - col_is_unique( table, column ) should have the proper description 38 | ok 36 - col_is_unique( table, column ) should have the proper diagnostics 39 | ok 37 - col_is_unique( table, columns ) should pass 40 | ok 38 - col_is_unique( table, columns ) should have the proper description 41 | ok 39 - col_is_unique( table, columns ) should have the proper diagnostics 42 | ok 40 - col_is_unique( schema, table, column, description ) fail should fail 43 | ok 41 - col_is_unique( schema, table, column, description ) fail should have the proper description 44 | ok 42 - col_is_unique( schema, table, column, description ) fail should have the proper diagnostics 45 | ok 43 - col_is_unique( table, column, description ) fail should fail 46 | ok 44 - col_is_unique( table, column, description ) fail should have the proper description 47 | ok 45 - col_is_unique( table, column, description ) fail should have the proper diagnostics 48 | ok 46 - col_is_unique( schema, table, column[], description ) should pass 49 | ok 47 - col_is_unique( schema, table, column[], description ) should have the proper description 50 | ok 48 - col_is_unique( schema, table, column[], description ) should have the proper diagnostics 51 | ok 49 - col_is_unique( table, column[], description ) should pass 52 | ok 50 - col_is_unique( table, column[], description ) should have the proper description 53 | ok 51 - col_is_unique( table, column[], description ) should have the proper diagnostics 54 | ok 52 - col_is_unique( table, column[] ) should pass 55 | ok 53 - col_is_unique( table, column[] ) should have the proper description 56 | ok 54 - col_is_unique( table, column[] ) should have the proper diagnostics 57 | -------------------------------------------------------------------------------- /test/expected/update.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..2 3 | ok 1 - Old version of pgtap correctly installed 4 | ok 2 - pgtap correctly updated 5 | -------------------------------------------------------------------------------- /test/expected/usergroup.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..90 3 | ok 1 - has_user(current user) should pass 4 | ok 2 - has_user(current user) should have the proper description 5 | ok 3 - has_user(current user) should have the proper diagnostics 6 | ok 4 - has_user(current user, desc) should pass 7 | ok 5 - has_user(current user, desc) should have the proper description 8 | ok 6 - has_user(current user, desc) should have the proper diagnostics 9 | ok 7 - has_user(nonexistent user) should fail 10 | ok 8 - has_user(nonexistent user) should have the proper description 11 | ok 9 - has_user(nonexistent user) should have the proper diagnostics 12 | ok 10 - has_user(nonexistent user, desc) should fail 13 | ok 11 - has_user(nonexistent user, desc) should have the proper description 14 | ok 12 - has_user(nonexistent user, desc) should have the proper diagnostics 15 | ok 13 - hasnt_user(current user) should fail 16 | ok 14 - hasnt_user(current user) should have the proper description 17 | ok 15 - hasnt_user(current user) should have the proper diagnostics 18 | ok 16 - hasnt_user(current user, desc) should fail 19 | ok 17 - hasnt_user(current user, desc) should have the proper description 20 | ok 18 - hasnt_user(current user, desc) should have the proper diagnostics 21 | ok 19 - hasnt_user(nonexistent user) should pass 22 | ok 20 - hasnt_user(nonexistent user) should have the proper description 23 | ok 21 - hasnt_user(nonexistent user) should have the proper diagnostics 24 | ok 22 - hasnt_user(nonexistent user, desc) should pass 25 | ok 23 - hasnt_user(nonexistent user, desc) should have the proper description 26 | ok 24 - hasnt_user(nonexistent user, desc) should have the proper diagnostics 27 | ok 25 - is_superuser(nonexistent user, desc) should fail 28 | ok 26 - is_superuser(nonexistent user, desc) should have the proper description 29 | ok 27 - is_superuser(nonexistent user, desc) should have the proper diagnostics 30 | ok 28 - is_superuser(nonexistent user) should fail 31 | ok 29 - is_superuser(nonexistent user) should have the proper description 32 | ok 30 - is_superuser(nonexistent user) should have the proper diagnostics 33 | ok 31 - isnt_superuser(nonexistent user, desc) should fail 34 | ok 32 - isnt_superuser(nonexistent user, desc) should have the proper description 35 | ok 33 - isnt_superuser(nonexistent user, desc) should have the proper diagnostics 36 | ok 34 - isnt_superuser(nonexistent user) should fail 37 | ok 35 - isnt_superuser(nonexistent user) should have the proper description 38 | ok 36 - isnt_superuser(nonexistent user) should have the proper diagnostics 39 | ok 37 - is_superuser( current user ) should pass 40 | ok 38 - is_superuser( current user ) should have the proper description 41 | ok 39 - is_superuser( current user ) should have the proper diagnostics 42 | ok 40 - is_superuser( current user, desc ) should pass 43 | ok 41 - is_superuser( current user, desc ) should have the proper description 44 | ok 42 - is_superuser( current user, desc ) should have the proper diagnostics 45 | ok 43 - has_group(group) should pass 46 | ok 44 - has_group(group) should have the proper description 47 | ok 45 - has_group(group) should have the proper diagnostics 48 | ok 46 - has_group(group, desc) should pass 49 | ok 47 - has_group(group, desc) should have the proper description 50 | ok 48 - has_group(group, desc) should have the proper diagnostics 51 | ok 49 - has_group(nonexistent group) should fail 52 | ok 50 - has_group(nonexistent group) should have the proper description 53 | ok 51 - has_group(nonexistent group) should have the proper diagnostics 54 | ok 52 - has_group(nonexistent group, desc) should fail 55 | ok 53 - has_group(nonexistent group, desc) should have the proper description 56 | ok 54 - has_group(nonexistent group, desc) should have the proper diagnostics 57 | ok 55 - hasnt_group(group) should fail 58 | ok 56 - hasnt_group(group) should have the proper description 59 | ok 57 - hasnt_group(group) should have the proper diagnostics 60 | ok 58 - hasnt_group(group, desc) should fail 61 | ok 59 - hasnt_group(group, desc) should have the proper description 62 | ok 60 - hasnt_group(group, desc) should have the proper diagnostics 63 | ok 61 - hasnt_group(nonexistent group) should pass 64 | ok 62 - hasnt_group(nonexistent group) should have the proper description 65 | ok 63 - hasnt_group(nonexistent group) should have the proper diagnostics 66 | ok 64 - hasnt_group(nonexistent group, desc) should pass 67 | ok 65 - hasnt_group(nonexistent group, desc) should have the proper description 68 | ok 66 - hasnt_group(nonexistent group, desc) should have the proper diagnostics 69 | ok 67 - isnt_member_of(meanies, [current_user], desc) should pass 70 | ok 68 - isnt_member_of(meanies, [current_user], desc) should have the proper description 71 | ok 69 - isnt_member_of(meanies, [current_user], desc) should have the proper diagnostics 72 | ok 70 - isnt_member_of(meanies, [current_user]) should pass 73 | ok 71 - isnt_member_of(meanies, [current_user]) should have the proper description 74 | ok 72 - isnt_member_of(meanies, [current_user]) should have the proper diagnostics 75 | ok 73 - isnt_member_of(meanies, current_user, desc) should pass 76 | ok 74 - isnt_member_of(meanies, current_user, desc) should have the proper description 77 | ok 75 - isnt_member_of(meanies, current_user, desc) should have the proper diagnostics 78 | ok 76 - isnt_member_of(meanies, current_user) should pass 79 | ok 77 - isnt_member_of(meanies, current_user) should have the proper description 80 | ok 78 - isnt_member_of(meanies, current_user) should have the proper diagnostics 81 | ok 79 - is_member_of(meanies, [current_user], desc) should pass 82 | ok 80 - is_member_of(meanies, [current_user], desc) should have the proper description 83 | ok 81 - is_member_of(meanies, [current_user], desc) should have the proper diagnostics 84 | ok 82 - is_member_of(meanies, [current_user]) should pass 85 | ok 83 - is_member_of(meanies, [current_user]) should have the proper description 86 | ok 84 - is_member_of(meanies, [current_user]) should have the proper diagnostics 87 | ok 85 - is_member_of(meanies, current_user, desc) should pass 88 | ok 86 - is_member_of(meanies, current_user, desc) should have the proper description 89 | ok 87 - is_member_of(meanies, current_user, desc) should have the proper diagnostics 90 | ok 88 - is_member_of(meanies, current_user) should pass 91 | ok 89 - is_member_of(meanies, current_user) should have the proper description 92 | ok 90 - is_member_of(meanies, current_user) should have the proper diagnostics 93 | -------------------------------------------------------------------------------- /test/expected/util.out: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | 1..14 3 | ok 1 - pg_type(int) should work 4 | ok 2 - pg_type(numeric) should work 5 | ok 3 - pg_type(text) should work 6 | ok 4 - pg_version() should return text 7 | ok 5 - pg_version() should return same as "server_version" setting 8 | ok 6 - pg_version() should work 9 | ok 7 - pg_version_num() should return same as "server_version_num" setting 10 | ok 8 - pg_version_num() should return integer 11 | ok 9 - pg_version_num() should be correct 12 | ok 10 - os_name() should output something like an OS name 13 | ok 11 - findfincs() should return distinct values 14 | ok 12 - pgtap_version() should work 15 | ok 13 - collect_tap(text[]) should simply collect tap 16 | ok 14 - variadic collect_tap() should simply collect tap 17 | -------------------------------------------------------------------------------- /test/psql.sql: -------------------------------------------------------------------------------- 1 | \set QUIET 1 2 | 3 | -- 4 | -- Tests for pgTAP. 5 | -- 6 | -- 7 | -- Format the output for nice TAP. 8 | \pset format unaligned 9 | \pset tuples_only true 10 | \pset pager 11 | 12 | -- Revert all changes on failure. 13 | \set ON_ERROR_ROLLBACK 1 14 | \set ON_ERROR_STOP true 15 | -------------------------------------------------------------------------------- /test/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -e -u -o pipefail 4 | 5 | make install 6 | psql -Ec 'DROP EXTENSION IF EXISTS pgtap; CREATE EXTENSION pgtap;' 7 | make test 8 | -------------------------------------------------------------------------------- /test/schedule/build.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/psql.sql 3 | 4 | /* 5 | * Presumably no one is installing this way anymore, but this is a nice way to 6 | * pick up any syntax errors during install. 7 | */ 8 | BEGIN; 9 | \i sql/pgtap.sql 10 | ROLLBACK; 11 | -------------------------------------------------------------------------------- /test/schedule/create.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/psql.sql 3 | CREATE EXTENSION pgtap; 4 | -------------------------------------------------------------------------------- /test/schedule/main.sch: -------------------------------------------------------------------------------- 1 | test: build 2 | test: create 3 | -------------------------------------------------------------------------------- /test/schedule/update.sch: -------------------------------------------------------------------------------- 1 | test: update 2 | -------------------------------------------------------------------------------- /test/schedule/update.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/psql.sql 3 | 4 | CREATE EXTENSION pgtap VERSION :'old_ver'; 5 | SELECT plan(2); 6 | SELECT is( 7 | (SELECT extversion FROM pg_extension WHERE extname = 'pgtap') 8 | , :'old_ver' 9 | , 'Old version of pgtap correctly installed' 10 | ); 11 | 12 | ALTER EXTENSION pgtap UPDATE TO :'new_ver'; 13 | 14 | SELECT is( 15 | (SELECT extversion FROM pg_extension WHERE extname = 'pgtap') 16 | , :'new_ver' 17 | , 'pgtap correctly updated' 18 | ); 19 | 20 | SELECT finish(); 21 | -------------------------------------------------------------------------------- /test/setup.sql: -------------------------------------------------------------------------------- 1 | \i test/psql.sql 2 | 3 | BEGIN; 4 | -- \i sql/pgtap.sql 5 | -------------------------------------------------------------------------------- /test/sql/check.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(48); 5 | 6 | -- This will be rolled back. :-) 7 | SET client_min_messages = warning; 8 | CREATE TABLE public.sometab( 9 | id INT NOT NULL PRIMARY KEY, 10 | name TEXT DEFAULT '' CHECK ( name IN ('foo', 'bar', 'baz') ), 11 | numb NUMERIC(10, 2), 12 | myint NUMERIC(8), 13 | CHECK (numb > 1.0 AND myint < 10) 14 | ); 15 | RESET client_min_messages; 16 | 17 | /****************************************************************************/ 18 | -- Test has_check(). 19 | 20 | SELECT * FROM check_test( 21 | has_check( 'public', 'sometab', 'public.sometab should have a check constraint' ), 22 | true, 23 | 'has_check( schema, table, desc )', 24 | 'public.sometab should have a check constraint', 25 | '' 26 | ); 27 | 28 | SELECT * FROM check_test( 29 | has_check( 'sometab', 'sometab should have a check constraint' ), 30 | true, 31 | 'has_check( table, desc )', 32 | 'sometab should have a check constraint', 33 | '' 34 | ); 35 | 36 | SELECT * FROM check_test( 37 | has_check( 'sometab' ), 38 | true, 39 | 'has_check( table )', 40 | 'Table sometab should have a check constraint', 41 | '' 42 | ); 43 | 44 | SELECT * FROM check_test( 45 | has_check( 'pg_catalog', 'pg_class', 'pg_catalog.pg_class should have a check constraint' ), 46 | false, 47 | 'has_check( schema, table, descr ) fail', 48 | 'pg_catalog.pg_class should have a check constraint', 49 | '' 50 | ); 51 | 52 | SELECT * FROM check_test( 53 | has_check( 'pg_class', 'pg_class should have a check constraint' ), 54 | false, 55 | 'has_check( table, desc ) fail', 56 | 'pg_class should have a check constraint', 57 | '' 58 | ); 59 | 60 | /****************************************************************************/ 61 | -- Test col_has_check(). 62 | 63 | SELECT * FROM check_test( 64 | col_has_check( 'public', 'sometab', 'name', 'public.sometab.name should have a check' ), 65 | true, 66 | 'col_has_check( sch, tab, col, desc )', 67 | 'public.sometab.name should have a check', 68 | '' 69 | ); 70 | 71 | SELECT * FROM check_test( 72 | col_has_check( 'public', 'sometab', ARRAY['numb', 'myint'], 'public.sometab.numb+myint should have a check' ), 73 | true, 74 | 'col_has_check( sch, tab, cols, desc )', 75 | 'public.sometab.numb+myint should have a check', 76 | '' 77 | ); 78 | 79 | SELECT * FROM check_test( 80 | col_has_check( 'sometab', 'name', 'sometab.name should have a check' ), 81 | true, 82 | 'col_has_check( tab, col, desc )', 83 | 'sometab.name should have a check', 84 | '' 85 | ); 86 | 87 | SELECT * FROM check_test( 88 | col_has_check( 'sometab', ARRAY['numb', 'myint'], 'sometab.numb+myint should have a check' ), 89 | true, 90 | 'col_has_check( tab, cols, desc )', 91 | 'sometab.numb+myint should have a check', 92 | '' 93 | ); 94 | 95 | SELECT * FROM check_test( 96 | col_has_check( 'sometab', 'name' ), 97 | true, 98 | 'col_has_check( table, column )', 99 | 'Column sometab(name) should have a check constraint', 100 | '' 101 | ); 102 | 103 | SELECT * FROM check_test( 104 | col_has_check( 'sometab', ARRAY['numb', 'myint'] ), 105 | true, 106 | 'col_has_check( table, columns )', 107 | 'Columns sometab(numb, myint) should have a check constraint', 108 | '' 109 | ); 110 | 111 | SELECT * FROM check_test( 112 | col_has_check( 'public', 'sometab', 'id', 'public.sometab.id should have a check' ), 113 | false, 114 | 'col_has_check( sch, tab, col, desc ) fail', 115 | 'public.sometab.id should have a check', 116 | ' have: {name} 117 | {numb,myint} 118 | want: {id}' 119 | ); 120 | 121 | SELECT * FROM check_test( 122 | col_has_check( 'sometab', 'id', 'sometab.id should have a check' ), 123 | false, 124 | 'col_has_check( tab, col, desc ) fail', 125 | 'sometab.id should have a check', 126 | ' have: {name} 127 | {numb,myint} 128 | want: {id}' 129 | ); 130 | 131 | /****************************************************************************/ 132 | -- Test col_has_check() with an array of columns. 133 | 134 | SET LOCAL client_min_messages = warning; 135 | CREATE TABLE public.argh ( 136 | id INT NOT NULL, 137 | name TEXT NOT NULL, 138 | CHECK ( id IN (1, 2) AND name IN ('foo', 'bar')) 139 | ); 140 | RESET client_min_messages; 141 | 142 | SELECT * FROM check_test( 143 | col_has_check( 'public', 'argh', ARRAY['id', 'name'], 'id + name should have a check' ), 144 | true, 145 | 'col_has_check( sch, tab, col[], desc )', 146 | 'id + name should have a check', 147 | '' 148 | ); 149 | 150 | SELECT * FROM check_test( 151 | col_has_check( 'argh', ARRAY['id', 'name'], 'id + name should have a check' ), 152 | true, 153 | 'col_has_check( tab, col[], desc )', 154 | 'id + name should have a check', 155 | '' 156 | ); 157 | 158 | SELECT * FROM check_test( 159 | col_has_check( 'argh', ARRAY['id', 'name'] ), 160 | true, 161 | 'col_has_check( tab, col[] )', 162 | 'Columns argh(id, name) should have a check constraint', 163 | '' 164 | ); 165 | 166 | /****************************************************************************/ 167 | -- Finish the tests and clean up. 168 | SELECT * FROM finish(); 169 | ROLLBACK; 170 | -------------------------------------------------------------------------------- /test/sql/cmpok.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(38); 5 | 6 | /****************************************************************************/ 7 | -- Test cmp_ok(). 8 | SELECT * FROM check_test( 9 | cmp_ok( 1, '=', 1, '1 should = 1' ), 10 | true, 11 | 'cmp_ok( int, =, int )', 12 | '1 should = 1', 13 | '' 14 | ); 15 | 16 | SELECT * FROM check_test( 17 | cmp_ok( 1, '<>', 2, '1 should <> 2' ), 18 | true, 19 | 'cmp_ok( int, <>, int )', 20 | '1 should <> 2', 21 | '' 22 | ); 23 | 24 | SELECT * FROM check_test( 25 | cmp_ok( '((0,0),(1,1))'::polygon, '~=', '((1,1),(0,0))'::polygon ), 26 | true, 27 | 'cmp_ok( polygon, ~=, polygon )' 28 | '', 29 | '' 30 | ); 31 | 32 | SELECT * FROM check_test( 33 | cmp_ok( ARRAY[1, 2], '=', ARRAY[1, 2]), 34 | true, 35 | 'cmp_ok( int[], =, int[] )', 36 | '', 37 | '' 38 | ); 39 | 40 | SELECT * FROM check_test( 41 | cmp_ok( ARRAY['192.168.1.2'::inet], '=', ARRAY['192.168.1.2'::inet] ), 42 | true, 43 | 'cmp_ok( inet[], =, inet[] )', 44 | '', 45 | '' 46 | ); 47 | 48 | SELECT * FROM check_test( 49 | cmp_ok( 1, '=', 2, '1 should = 2' ), 50 | false, 51 | 'cmp_ok() fail', 52 | '1 should = 2', 53 | ' ''1'' 54 | = 55 | ''2''' 56 | ); 57 | 58 | SELECT * FROM check_test( 59 | cmp_ok( 1, '=', NULL, '1 should = NULL' ), 60 | false, 61 | 'cmp_ok() NULL fail', 62 | '1 should = NULL', 63 | ' ''1'' 64 | = 65 | NULL' 66 | ); 67 | 68 | 69 | /****************************************************************************/ 70 | -- Test isa_ok(). 71 | SELECT * FROM check_test( 72 | isa_ok( ''::text, 'text', 'an empty string' ), 73 | true, 74 | 'isa_ok("", text, desc)', 75 | 'an empty string isa text', 76 | '' 77 | ); 78 | 79 | SELECT * FROM check_test( 80 | isa_ok( ''::text, 'text', 'an empty string' ), 81 | true, 82 | 'isa_ok("", text, desc)', 83 | 'an empty string isa text', 84 | '' 85 | ); 86 | 87 | SELECT * FROM check_test( 88 | isa_ok( false, 'bool' ), 89 | true, 90 | 'isa_ok(false, boolean)', 91 | 'the value isa boolean', 92 | '' 93 | ); 94 | 95 | SELECT * FROM check_test( 96 | isa_ok( NULL::boolean, 'bool' ), 97 | true, 98 | 'isa_ok(NULL, boolean)', 99 | 'the value isa boolean', 100 | '' 101 | ); 102 | 103 | SELECT * FROM check_test( 104 | isa_ok( ARRAY[false], 'bool[]' ), 105 | true, 106 | 'isa_ok(ARRAY, boolean[])', 107 | 'the value isa boolean[]', 108 | '' 109 | ); 110 | 111 | SELECT * FROM check_test( 112 | isa_ok( true, 'int[]' ), 113 | false, 114 | 'isa_ok(bool, int[])', 115 | 'the value isa integer[]', 116 | ' the value isn''t a "integer[]" it''s a "boolean"' 117 | ); 118 | 119 | /****************************************************************************/ 120 | -- Finish the tests and clean up. 121 | SELECT * FROM finish(); 122 | ROLLBACK; 123 | -------------------------------------------------------------------------------- /test/sql/do_tap.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | SET client_min_messages = notice; 4 | 5 | SELECT plan(29); 6 | --SELECT * FROM no_plan(); 7 | 8 | CREATE OR REPLACE FUNCTION public.testthis() RETURNS SETOF TEXT AS $$ 9 | SELECT pass('simple pass') AS foo 10 | UNION SELECT pass('another simple pass') 11 | ORDER BY foo ASC; 12 | $$ LANGUAGE SQL; 13 | 14 | CREATE OR REPLACE FUNCTION public.testplpgsql() RETURNS SETOF TEXT AS $$ 15 | BEGIN 16 | RETURN NEXT pass( 'plpgsql simple' ); 17 | RETURN NEXT pass( 'plpgsql simple 2' ); 18 | RETURN; 19 | END; 20 | $$ LANGUAGE plpgsql; 21 | 22 | CREATE OR REPLACE FUNCTION public."test ident"() RETURNS SETOF TEXT AS $$ 23 | BEGIN 24 | RETURN NEXT pass( 'ident' ); 25 | RETURN NEXT pass( 'ident 2' ); 26 | RETURN; 27 | END; 28 | $$ LANGUAGE plpgsql; 29 | 30 | SELECT is( 31 | findfuncs('public'::name, '^test', 'this'), 32 | ARRAY[ 'public."test ident"', 'public.testplpgsql'], 33 | 'findfuncs(public, ^test, this) should work' 34 | ); 35 | 36 | SELECT is( 37 | findfuncs('public'::name, '^test'), 38 | ARRAY[ 'public."test ident"', 'public.testplpgsql', 'public.testthis' ], 39 | 'findfuncs(public, ^test) should work' 40 | ); 41 | 42 | SELECT is( 43 | findfuncs('^test', 'this'), 44 | ARRAY[ 'public."test ident"', 'public.testplpgsql'], 45 | 'findfuncs(^test, this) should work' 46 | ); 47 | 48 | SELECT is( 49 | findfuncs('^test'), 50 | ARRAY[ 'public."test ident"', 'public.testplpgsql', 'public.testthis' ], 51 | 'findfuncs(^test) should work' 52 | ); 53 | 54 | SELECT is( 55 | findfuncs('foo'), 56 | CASE WHEN pg_version_num() < 80300 THEN NULL ELSE '{}'::text[] END, 57 | 'findfuncs(unknown) should find no tests' 58 | ); 59 | 60 | SELECT * FROM do_tap('public', '^test'); 61 | SELECT * FROM do_tap('public'::name); 62 | SELECT * FROM do_tap('^test'); 63 | SELECT * FROM do_tap(); 64 | 65 | /****************************************************************************/ 66 | -- Finish the tests and clean up. 67 | SELECT * FROM finish(); 68 | ROLLBACK; 69 | -------------------------------------------------------------------------------- /test/sql/istap.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(47); 5 | --SELECT * from no_plan(); 6 | 7 | /****************************************************************************/ 8 | -- Test is(). 9 | SELECT * FROM check_test( is(1, 1), true, 'is(1, 1)', '', '' ); 10 | SELECT * FROM check_test( is('x'::text, 'x'::text), true, 'is(''x'', ''x'')', '', '' ); 11 | SELECT * FROM check_test( is(1.1, 1.10), true, 'is(1.1, 1.10)', '', '' ); 12 | SELECT * FROM check_test( is(true, true), true, 'is(true, true)', '', '' ); 13 | SELECT * FROM check_test( is(false, false), true, 'is(false, false)', '', '' ); 14 | SELECT * FROM check_test( is(1, 1, 'foo'), true, 'is(1, 1, desc)', 'foo', '' ); 15 | SELECT * FROM check_test( is( 1, 2 ), false, 'is(1, 2)', '', ' have: 1 16 | want: 2'); 17 | 18 | /****************************************************************************/ 19 | -- Test isnt(). 20 | SELECT * FROM check_test( isnt(1, 2), true, 'isnt(1, 2)', '', '' ); 21 | SELECT * FROM check_test( isnt( 1, 1 ), false, 'isnt(1, 1)', '', ' have: 1 22 | want: anything else' ); 23 | 24 | /****************************************************************************/ 25 | -- Try using variables. 26 | \set foo '\'' waffle '\'' 27 | \set bar '\'' waffle '\'' 28 | SELECT is( :foo::text, :bar::text, 'is() should work with psql variables' ); 29 | 30 | /****************************************************************************/ 31 | -- Try using NULLs. 32 | 33 | SELECT * FROM check_test( 34 | is( NULL::text, NULL::text, 'NULLs' ), 35 | true, 36 | 'is(NULL, NULL)', 37 | 'NULLs', 38 | '' 39 | ); 40 | 41 | SELECT * FROM check_test( 42 | is( NULL::text, 'foo' ), 43 | false, 44 | 'is(NULL, foo)', 45 | '', 46 | ' have: NULL 47 | want: foo' 48 | ); 49 | 50 | SELECT * FROM check_test( 51 | is( 'foo', NULL::text ), 52 | false, 53 | 'is(foo, NULL)', 54 | '', 55 | ' have: foo 56 | want: NULL' 57 | ); 58 | 59 | SET client_min_messages = warning; 60 | CREATE TABLE mumble ( id int, name text ); 61 | RESET client_min_messages; 62 | INSERT INTO mumble VALUES (1, 'hey'); 63 | 64 | SELECT is( mumble.*, ROW(1, 'hey')::mumble, 'with records!' ) 65 | FROM mumble; 66 | 67 | SELECT check_test( 68 | is( mumble.*, ROW(1, 'HEY')::mumble ), 69 | false, 70 | 'is(mumble, row) fail', 71 | '', 72 | ' have: (1,hey) 73 | want: (1,HEY)' 74 | ) FROM mumble; 75 | 76 | SELECT check_test( 77 | is( mumble.*, ROW(1, NULL)::mumble ), 78 | false, 79 | 'is(mumble, row) fail with NULL', 80 | '', 81 | ' have: (1,hey) 82 | want: (1,)' 83 | ) FROM mumble; 84 | 85 | SELECT check_test( 86 | is( mumble.*, NULL::mumble ), 87 | false, 88 | 'is(mumble, NULL)', 89 | '', 90 | ' have: (1,hey) 91 | want: NULL' 92 | ) FROM mumble; 93 | 94 | /****************************************************************************/ 95 | -- Finish the tests and clean up. 96 | SELECT * FROM finish(false); -- Arbitrarily decided to test `finish(false)` here... :) 97 | ROLLBACK; 98 | -------------------------------------------------------------------------------- /test/sql/matching.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(24); 5 | 6 | /****************************************************************************/ 7 | -- Test matches(). 8 | SELECT matches( 'foo'::text, 'o', 'matches() should work' ); 9 | SELECT matches( 'foo'::text, '^fo', 'matches() should work with a regex' ); 10 | SELECT imatches( 'FOO'::text, '^fo', 'imatches() should work with a regex' ); 11 | 12 | -- Check matches() diagnostics. 13 | SELECT * FROM check_test( 14 | matches( 'foo'::text, '^a' ), 15 | false, 16 | 'matches() fail', 17 | '', 18 | ' ''foo'' 19 | doesn''t match: ''^a''' 20 | ); 21 | 22 | -- Check doesnt_match. 23 | SELECT doesnt_match( 'foo'::text, 'a', 'doesnt_match() should work' ); 24 | SELECT doesnt_match( 'foo'::text, '^o', 'doesnt_match() should work with a regex' ); 25 | SELECT doesnt_imatch( 'foo'::text, '^o', 'doesnt_imatch() should work with a regex' ); 26 | 27 | -- Check doesnt_match diagnostics. 28 | SELECT * FROM check_test( 29 | doesnt_match( 'foo'::text, 'o' ), 30 | false, 31 | 'doesnt_match() fail', 32 | '', 33 | ' ''foo'' 34 | matches: ''o''' 35 | ); 36 | 37 | /****************************************************************************/ 38 | -- Test alike(). 39 | SELECT alike( 'foo'::text, 'foo', 'alike() should work' ); 40 | SELECT alike( 'foo'::text, 'fo%', 'alike() should work with a regex' ); 41 | SELECT ialike( 'FOO'::text, 'fo%', 'ialike() should work with a regex' ); 42 | 43 | -- Check alike() diagnostics. 44 | SELECT * FROM check_test( 45 | alike( 'foo'::text, 'a%'::text ), 46 | false, 47 | 'alike() fail', 48 | '', 49 | ' ''foo'' 50 | doesn''t match: ''a%''' 51 | ); 52 | 53 | -- Test unalike(). 54 | SELECT unalike( 'foo'::text, 'f', 'unalike() should work' ); 55 | SELECT unalike( 'foo'::text, 'f%i', 'unalike() should work with a regex' ); 56 | SELECT unialike( 'FOO'::text, 'f%i', 'iunalike() should work with a regex' ); 57 | 58 | -- Check unalike() diagnostics. 59 | SELECT * FROM check_test( 60 | unalike( 'foo'::text, 'f%'::text ), 61 | false, 62 | 'unalike() fail', 63 | '', 64 | ' ''foo'' 65 | matches: ''f%''' 66 | ); 67 | 68 | /****************************************************************************/ 69 | -- Finish the tests and clean up. 70 | SELECT * FROM finish(); 71 | ROLLBACK; 72 | -------------------------------------------------------------------------------- /test/sql/moretap.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | \set numb_tests 54 5 | SELECT plan(:numb_tests); 6 | 7 | -- Replace the internal record of the plan for a few tests. 8 | SELECT is( _set('plan', 4), 4, 'Modify internal plan value'); 9 | 10 | /****************************************************************************/ 11 | -- Test pass(). 12 | SELECT pass( 'My pass() passed, w00t!' ); 13 | 14 | -- Test fail(). 15 | \set fail_numb 3 16 | \echo ok :fail_numb - Testing fail() 17 | SELECT is( 18 | fail('oops'), 19 | format( E'not ok %1$s - oops\n# Failed test %1$s: "oops"', :fail_numb ), 20 | 'We should get the proper output from fail()' 21 | ); 22 | 23 | /* 24 | * NOTE: From this point until we call _set('failed') below we should always 25 | * have *one* test failure, *BUT* if the tests themselves start failing then 26 | * you'll have extra failures which will throw off all the successive counts! 27 | */ 28 | 29 | -- Check the finish() output with no value. 30 | SELECT is( 31 | (SELECT * FROM finish() LIMIT 1), 32 | '# Looks like you failed 1 test of 4', 33 | 'The output of finish() should reflect the test failure' 34 | ); 35 | 36 | -- Make sure that false and NULL work as well 37 | SELECT is( _set('plan', 6), 6, 'Increase internal plan value after testing finish' ); 38 | SELECT is( 39 | (SELECT * FROM finish(false) LIMIT 1), 40 | '# Looks like you failed 1 test of 6', 41 | 'The output of finish(false) should reflect the test failure' 42 | ); 43 | SELECT is( _set('plan', 8), 8, 'Increase internal plan value after testing finish' ); 44 | SELECT is( 45 | (SELECT * FROM finish(NULL) LIMIT 1), 46 | '# Looks like you failed 1 test of 8', 47 | 'The output of finish(NULL) should reflect the test failure' 48 | ); 49 | 50 | -- Verify that finish(true) works 51 | SELECT is( _set('plan', 10), 10, 'Increase internal plan value after testing finish' ); 52 | SELECT throws_ok( 53 | $$SELECT finish(true)$$, 54 | '1 test failed of 10', 55 | 'finish(true) should throw an exception' 56 | ); 57 | 58 | /****************************************************************************/ 59 | -- Check num_failed 60 | SELECT is( num_failed(), 1, 'We should have one failure' ); 61 | SELECT is( _set('failed', 0), 0, 'Reset internal failure count' ); 62 | SELECT is( num_failed(), 0, 'We should now have no failures' ); 63 | 64 | /****************************************************************************/ 65 | -- Check diag. 66 | SELECT is( diag('foo'), '# foo', 'diag() should work properly' ); 67 | SELECT is( diag( 'foo 68 | bar'), '# foo 69 | # bar', 'multiline diag() should work properly' ); 70 | SELECT is( diag( 'foo 71 | # bar'), '# foo 72 | # # bar', 'multiline diag() should work properly with existing comments' ); 73 | 74 | -- Try anyelement form. 75 | SELECT is(diag(6), '# 6', 'diag(int)'); 76 | SELECT is(diag(11.2), '# 11.2', 'diag(numeric)'); 77 | SELECT is(diag(NOW()), '# ' || NOW(), 'diag(timestamptz)'); 78 | 79 | -- Try variadic anyarray 80 | CREATE FUNCTION test_variadic() RETURNS SETOF TEXT AS $$ 81 | BEGIN 82 | IF pg_version_num() >= 80400 THEN 83 | RETURN NEXT is(diag('foo'::text, 'bar', 'baz'), '# foobarbaz', 'variadic text'); 84 | RETURN NEXT is(diag(1::int, 3, 4), '# 134', 'variadic int'); 85 | RETURN NEXT is(diag('foo', 'bar', 'baz'), '# foobarbaz', 'variadic unknown'); 86 | ELSE 87 | RETURN NEXT pass('variadic text'); 88 | RETURN NEXT pass('variadic int'); 89 | RETURN NEXT pass('variadic unknown'); 90 | RETURN; 91 | END IF; 92 | END; 93 | $$ LANGUAGE plpgsql; 94 | 95 | SELECT * FROM test_variadic(); 96 | 97 | /****************************************************************************/ 98 | -- Check no_plan. 99 | DELETE FROM __tcache__ WHERE label = 'plan'; 100 | SELECT * FROM no_plan(); 101 | SELECT is( _get('plan'), 0, 'no_plan() should have stored a plan of 0' ); 102 | 103 | -- Set the plan to a high number. 104 | DELETE FROM __tcache__ WHERE label = 'plan'; 105 | SELECT is( plan(4000), '1..4000', 'Set the plan to 4000' ); 106 | SELECT is( 107 | (SELECT * FROM finish() LIMIT 1), 108 | '# Looks like you planned 4000 tests but ran 25', 109 | 'The output of finish() should reflect a high test plan' 110 | ); 111 | 112 | -- Set the plan to a low number. 113 | DELETE FROM __tcache__ WHERE label = 'plan'; 114 | SELECT is( plan(4), '1..4', 'Set the plan to 4' ); 115 | SELECT is( 116 | (SELECT * FROM finish() LIMIT 1), 117 | '# Looks like you planned 4 tests but ran 27', 118 | 'The output of finish() should reflect a low test plan' 119 | ); 120 | 121 | -- Reset the original plan. 122 | DELETE FROM __tcache__ WHERE label = 'plan'; 123 | SELECT is( plan(:numb_tests), '1..' || :numb_tests, 'Reset the plan' ); 124 | SELECT is( _get('plan'), :numb_tests, 'plan() should have stored the test count' ); 125 | 126 | /****************************************************************************/ 127 | -- Test ok() 128 | SELECT * FROM check_test( ok(true), true, 'ok(true)', '', ''); 129 | SELECT * FROM check_test( ok(true, ''), true, 'ok(true, '''')', '', '' ); 130 | SELECT * FROM check_test( ok(true, 'foo'), true, 'ok(true, ''foo'')', 'foo', '' ); 131 | 132 | SELECT * FROM check_test( ok(false), false, 'ok(false)', '', '' ); 133 | SELECT * FROM check_test( ok(false, ''), false, 'ok(false, '''')', '', '' ); 134 | SELECT * FROM check_test( ok(false, 'foo'), false, 'ok(false, ''foo'')', 'foo', '' ); 135 | SELECT * FROM check_test( ok(NULL, 'null'), false, 'ok(NULL, ''null'')', 'null', ' (test result was NULL)' ); 136 | 137 | /****************************************************************************/ 138 | -- test multiline description. Second line is effectively diagnostic output. 139 | SELECT * FROM check_test( 140 | ok( true, 'foo 141 | bar' ), 142 | true, 143 | 'multiline desc', 'foo', 'bar' 144 | ); 145 | 146 | /****************************************************************************/ 147 | -- Finish the tests and clean up. 148 | SELECT * FROM finish(); 149 | ROLLBACK; 150 | -------------------------------------------------------------------------------- /test/sql/performs_ok.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(24); 5 | --SELECT * FROM no_plan(); 6 | 7 | /****************************************************************************/ 8 | -- Test performs_ok(). 9 | SELECT * FROM check_test( 10 | performs_ok( 'SELECT TRUE', 500, 'whatever' ), 11 | true, 12 | 'simple select', 13 | 'whatever', 14 | '' 15 | ); 16 | 17 | SELECT * FROM check_test( 18 | performs_ok( 'SELECT TRUE', 500 ), 19 | true, 20 | 'simple select no desc', 21 | 'Should run in less than 500 ms', 22 | '' 23 | ); 24 | 25 | SELECT * FROM check_test( 26 | performs_ok( 'SELECT TRUE', 199.99 ), 27 | true, 28 | 'simple select numeric', 29 | 'Should run in less than 199.99 ms', 30 | '' 31 | ); 32 | 33 | PREPARE mytest AS SELECT TRUE; 34 | SELECT * FROM check_test( 35 | performs_ok( 'mytest', 100 ), 36 | true, 37 | 'simple prepare', 38 | 'Should run in less than 100 ms', 39 | '' 40 | ); 41 | 42 | SELECT * FROM check_test( 43 | performs_ok( 'EXECUTE mytest', 100 ), 44 | true, 45 | 'simple execute', 46 | 'Should run in less than 100 ms', 47 | '' 48 | ); 49 | 50 | SELECT * FROM check_test( 51 | performs_ok( 'SELECT TRUE', 0, 'whatever' ), 52 | false, 53 | 'simple select fail', 54 | 'whatever', 55 | ' runtime: [[:digit:]]+([.][[:digit:]]+)? ms 56 | exceeds: 0 ms', 57 | true 58 | ); 59 | 60 | SELECT * FROM check_test( 61 | performs_ok( 'SELECT TRUE', 0 ), 62 | false, 63 | 'simple select no desc fail', 64 | 'Should run in less than 0 ms', 65 | ' runtime: [[:digit:]]+([.][[:digit:]]+)? ms 66 | exceeds: 0 ms', 67 | true 68 | ); 69 | 70 | SELECT * FROM check_test( 71 | performs_ok( 'SELECT TRUE', 0.00 ), 72 | false, 73 | 'simple select no desc numeric fail', 74 | 'Should run in less than 0.00 ms', 75 | ' runtime: [[:digit:]]+([.][[:digit:]]+)? ms 76 | exceeds: 0.00 ms', 77 | true 78 | ); 79 | 80 | /****************************************************************************/ 81 | -- Finish the tests and clean up. 82 | SELECT * FROM finish(); 83 | ROLLBACK; 84 | -------------------------------------------------------------------------------- /test/sql/performs_within.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(24); 5 | --SELECT * FROM no_plan(); 6 | 7 | /****************************************************************************/ 8 | -- Test performs_within(). 9 | SELECT * FROM check_test( 10 | performs_within( 'SELECT TRUE', 500, 500, 1, 'whatever' ), 11 | true, 12 | 'simple select', 13 | 'whatever', 14 | '' 15 | ); 16 | 17 | SELECT * FROM check_test( 18 | performs_within( 'SELECT TRUE', 500, 500, 1 ), 19 | true, 20 | 'simple select no desc', 21 | 'Should run within 500 +/- 500 ms', 22 | '' 23 | ); 24 | 25 | SELECT * FROM check_test( 26 | performs_within( 'SELECT TRUE', 99.99, 99.99 ), 27 | true, 28 | 'simple select numeric', 29 | 'Should run within 99.99 +/- 99.99 ms', 30 | '' 31 | ); 32 | 33 | PREPARE mytest AS SELECT TRUE; 34 | SELECT * FROM check_test( 35 | performs_within( 'mytest', 500, 500 ), 36 | true, 37 | 'simple prepare', 38 | 'Should run within 500 +/- 500 ms', 39 | '' 40 | ); 41 | 42 | SELECT * FROM check_test( 43 | performs_within( 'EXECUTE mytest', 500, 500 ), 44 | true, 45 | 'simple execute', 46 | 'Should run within 500 +/- 500 ms', 47 | '' 48 | ); 49 | 50 | SELECT * FROM check_test( 51 | performs_within( 'SELECT TRUE', 0, 0, 'whatever' ), 52 | false, 53 | 'simple select fail', 54 | 'whatever', 55 | ' average runtime: [[:digit:]]+([.][[:digit:]]+)? ms' || 56 | E'\n' || E' desired average: 0 \\+/- 0 ms', 57 | true 58 | ); 59 | 60 | SELECT * FROM check_test( 61 | performs_within( 'SELECT TRUE', 0, 0 ), 62 | false, 63 | 'simple select no desc fail', 64 | 'Should run within 0 +/- 0 ms', 65 | ' average runtime: [[:digit:]]+([.][[:digit:]]+)? ms' || 66 | E'\n' || E' desired average: 0 \\+/- 0 ms', 67 | true 68 | ); 69 | 70 | SELECT * FROM check_test( 71 | performs_within( 'SELECT TRUE', 0.0, 0.0 ), 72 | false, 73 | 'simple select no desc numeric fail', 74 | 'Should run within 0.0 +/- 0.0 ms', 75 | ' average runtime: [[:digit:]]+([.][[:digit:]]+)? ms' || 76 | E'\n' || E' desired average: 0.0 \\+/- 0.0 ms', 77 | true 78 | ); 79 | 80 | /****************************************************************************/ 81 | -- Finish the tests and clean up. 82 | SELECT * FROM finish(); 83 | ROLLBACK; 84 | -------------------------------------------------------------------------------- /test/sql/pg73.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | select plan(39); 5 | 6 | select ok(true); 7 | select ok(true, 'true'); 8 | select ok(NOT false); 9 | select ok(NOT false, 'NOT false'); 10 | select ok(3 = 3); 11 | select ok(3 = 3, 'three'); 12 | 13 | select ok(1 != 2); 14 | select ok(1 <> 2); 15 | select isnt(1,2); 16 | select isnt(1,2,'1=2'); 17 | 18 | select is( now(), now(), 'now()=now()'); 19 | select is( '1 hour'::interval, '1 hour'::interval, '''1 hour''::interval, ''1 hour''::interval'); 20 | select is( now()::date, now()::date); 21 | select is( now()::date, now()::date, 'now=now date' ); 22 | select isnt( now()::date, now()::date + 1, 'now!=now+1' ); 23 | 24 | select is( now()::timestamp, now()::timestamp, 'now()=now() timestamp'); 25 | select is( now()::date, now()::date, 'now()=now() date'); 26 | select is( TRUE, TRUE, 'TRUE=TRUE' ); 27 | select isnt( TRUE, FALSE, 'TRUE!=FALSE' ); 28 | select is('a'::char, 'a'::char, 'a=a char'); 29 | select isnt('a'::char, 'b'::char, 'a!=b char'); 30 | 31 | select is('a'::text, 'a'::text, 'a=a text'); 32 | select isnt('a'::text, 'b'::text, 'a!=b text'); 33 | select is(3::int, 3::int, '3=3 int'); 34 | select isnt(3::int, 4::int, '3!=4 int'); 35 | select is(3::integer, 3::integer, '3=3 integer'); 36 | select isnt(3::integer, 4::integer, '3!=4 integer'); 37 | select is(3::int2, 3::int2, '3=3 int2'); 38 | select isnt(3::int2, 4::int2, '3!=4 int2'); 39 | select is(3::int4, 3::int4, '3=3 int4'); 40 | select isnt(3::int4, 4::int4, '3!=4 int4'); 41 | select is(3::int8, 3::int8, '3=3 int8'); 42 | select isnt(3::int8, 4::int8, '3!=4 int8'); 43 | select is(3.2::float, 3.2::float, '3.2=3.2 float'); 44 | select isnt(3.2::float, 4.5::float, '3.2!=4.5 float'); 45 | select is(3.2::float4, 3.2::float4, '3.2=3.2 float4'); 46 | select isnt(3.2::float4, 4.5::float4, '3.2!=4.5 float4'); 47 | select is(3.2::float8, 3.2::float8, '3.2=3.2 float8'); 48 | select isnt(3.2::float8, 4.5::float8, '3.2!=4.5 float8'); 49 | 50 | select * from finish(); 51 | ROLLBACK; 52 | -------------------------------------------------------------------------------- /test/sql/roletap.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(39); 5 | --SELECT * FROM no_plan(); 6 | 7 | /****************************************************************************/ 8 | -- Test has_role() and hasnt_role(). 9 | 10 | SELECT * FROM check_test( 11 | has_role(current_role), 12 | true, 13 | 'has_role(current role)', 14 | 'Role ' || quote_ident(current_role) || ' should exist', 15 | '' 16 | ); 17 | SELECT * FROM check_test( 18 | has_role(current_role, 'whatever'), 19 | true, 20 | 'has_role(current role, desc)', 21 | 'whatever', 22 | '' 23 | ); 24 | SELECT * FROM check_test( 25 | has_role('aoijaoisjfaoidfjaisjdfosjf'), 26 | false, 27 | 'has_role(nonexistent role)', 28 | 'Role aoijaoisjfaoidfjaisjdfosjf should exist', 29 | '' 30 | ); 31 | SELECT * FROM check_test( 32 | has_role('aoijaoisjfaoidfjaisjdfosjf', 'desc'), 33 | false, 34 | 'has_role(nonexistent role, desc)', 35 | 'desc', 36 | '' 37 | ); 38 | 39 | SELECT * FROM check_test( 40 | hasnt_role(current_role), 41 | false, 42 | 'hasnt_role(current role)', 43 | 'Role ' || quote_ident(current_role) || ' should not exist', 44 | '' 45 | ); 46 | SELECT * FROM check_test( 47 | hasnt_role(current_role, 'whatever'), 48 | false, 49 | 'hasnt_role(current role, desc)', 50 | 'whatever', 51 | '' 52 | ); 53 | SELECT * FROM check_test( 54 | hasnt_role('aoijaoisjfaoidfjaisjdfosjf'), 55 | true, 56 | 'hasnt_role(nonexistent role)', 57 | 'Role aoijaoisjfaoidfjaisjdfosjf should not exist', 58 | '' 59 | ); 60 | SELECT * FROM check_test( 61 | hasnt_role('aoijaoisjfaoidfjaisjdfosjf', 'desc'), 62 | true, 63 | 'hasnt_role(nonexistent role, desc)', 64 | 'desc', 65 | '' 66 | ); 67 | 68 | /****************************************************************************/ 69 | -- Test roles_are(). 70 | 71 | CREATE FUNCTION ___myroles(ex text) RETURNS NAME[] AS $$ 72 | SELECT COALESCE(ARRAY( SELECT rolname FROM pg_catalog.pg_roles WHERE rolname <> $1 ), '{}'::name[]);; 73 | $$ LANGUAGE SQL; 74 | 75 | SELECT * FROM check_test( 76 | roles_are( ___myroles(''), 'whatever' ), 77 | true, 78 | 'roles_are(roles, desc)', 79 | 'whatever', 80 | '' 81 | ); 82 | 83 | SELECT * FROM check_test( 84 | roles_are( ___myroles('') ), 85 | true, 86 | 'roles_are(roles)', 87 | 'There should be the correct roles', 88 | '' 89 | ); 90 | 91 | SELECT * FROM check_test( 92 | roles_are( array_append(___myroles(''), '__howdy__'), 'whatever' ), 93 | false, 94 | 'roles_are(roles, desc) missing', 95 | 'whatever', 96 | ' Missing roles: 97 | __howdy__' 98 | ); 99 | 100 | SELECT * FROM check_test( 101 | roles_are( ___myroles(current_role), 'whatever' ), 102 | false, 103 | 'roles_are(roles, desc) extras', 104 | 'whatever', 105 | ' Extra roles: 106 | ' || quote_ident(current_role) 107 | ); 108 | 109 | SELECT * FROM check_test( 110 | roles_are( array_append(___myroles(current_role), '__howdy__'), 'whatever' ), 111 | false, 112 | 'roles_are(roles, desc) missing and extras', 113 | 'whatever', 114 | ' Extra roles: 115 | ' || quote_ident(current_role) || ' 116 | Missing roles: 117 | __howdy__' 118 | ); 119 | 120 | /****************************************************************************/ 121 | -- Finish the tests and clean up. 122 | SELECT * FROM finish(); 123 | ROLLBACK; 124 | -------------------------------------------------------------------------------- /test/sql/runjusttests.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | SET client_min_messages = warning; 4 | 5 | CREATE SCHEMA whatever; 6 | CREATE TABLE whatever.foo ( id serial primary key ); 7 | 8 | -- Make sure we get test function names. 9 | SET client_min_messages = notice; 10 | 11 | CREATE OR REPLACE FUNCTION whatever.testthis() RETURNS SETOF TEXT AS $$ 12 | SELECT collect_tap(ARRAY[ 13 | pass('simple pass'), 14 | pass('another simple pass') 15 | ]); 16 | $$ LANGUAGE SQL; 17 | 18 | CREATE OR REPLACE FUNCTION whatever.testplpgsql() RETURNS SETOF TEXT AS $$ 19 | BEGIN 20 | RETURN NEXT pass( 'plpgsql simple' ); 21 | RETURN NEXT pass( 'plpgsql simple 2' ); 22 | INSERT INTO whatever.foo VALUES(1); 23 | RETURN NEXT is( MAX(id), 1, 'Should be a 1 in the test table') FROM whatever.foo; 24 | END; 25 | $$ LANGUAGE plpgsql; 26 | 27 | CREATE OR REPLACE FUNCTION whatever.testplpgsqldie() RETURNS SETOF TEXT AS $$ 28 | BEGIN 29 | RETURN NEXT pass( 'plpgsql simple' ); -- Won't appear in results. 30 | RETURN NEXT pass( 'plpgsql simple 2' ); -- Won't appear in results. 31 | INSERT INTO whatever.foo VALUES(1); 32 | RETURN NEXT is( MAX(id), 1, 'Should be a 1 in the test table') FROM whatever.foo; 33 | IF pg_version_num() >= 90300 THEN 34 | EXECUTE $E$ 35 | CREATE OR REPLACE FUNCTION __die() RETURNS VOID LANGUAGE plpgsql AS $F$ 36 | BEGIN 37 | RAISE EXCEPTION 'This test should die, but not halt execution. 38 | Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself.' 39 | USING 40 | DETAIL = 'DETAIL', 41 | COLUMN = 'COLUMN', 42 | CONSTRAINT = 'CONSTRAINT', 43 | DATATYPE = 'TYPE', 44 | TABLE = 'TABLE', 45 | SCHEMA = 'SCHEMA'; 46 | END; 47 | $F$; 48 | $E$; 49 | ELSIF pg_version_num() >= 80400 THEN 50 | EXECUTE $E$ 51 | CREATE OR REPLACE FUNCTION __die() RETURNS VOID LANGUAGE plpgsql AS $F$ 52 | BEGIN 53 | RAISE EXCEPTION 'This test should die, but not halt execution. 54 | Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself.' 55 | USING DETAIL = 'DETAIL'; 56 | END; 57 | $F$; 58 | $E$; 59 | ELSE 60 | EXECUTE $E$ 61 | CREATE OR REPLACE FUNCTION __die() RETURNS VOID LANGUAGE plpgsql AS $F$ 62 | BEGIN 63 | RAISE EXCEPTION 'This test should die, but not halt execution. 64 | Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself.'; 65 | END; 66 | $F$; 67 | $E$; 68 | END IF; 69 | EXECUTE 'SELECT __die();'; 70 | END; 71 | $$ LANGUAGE plpgsql; 72 | 73 | CREATE OR REPLACE FUNCTION whatever.testy() RETURNS SETOF TEXT AS $$ 74 | SELECT collect_tap(ARRAY[ 75 | pass('pass'), 76 | fail('this test intentionally fails') 77 | ]); 78 | $$ LANGUAGE SQL; 79 | 80 | CREATE OR REPLACE FUNCTION whatever.testnada() RETURNS SETOF TEXT AS $$ 81 | BEGIN 82 | -- Do nothing. 83 | END; 84 | $$ LANGUAGE plpgsql; 85 | 86 | CREATE OR REPLACE FUNCTION whatever.testz() RETURNS SETOF TEXT AS $$ 87 | SELECT is( MAX(id), NULL, 'Late test should find nothing in the test table') FROM whatever.foo; 88 | $$ LANGUAGE SQL; 89 | 90 | CREATE OR REPLACE FUNCTION whatever."test ident"() RETURNS SETOF TEXT AS $$ 91 | BEGIN 92 | RETURN NEXT pass( 'ident' ); 93 | RETURN NEXT pass( 'ident 2' ); 94 | END; 95 | $$ LANGUAGE plpgsql; 96 | 97 | -- Run the actual tests. Yes, it's a one-liner! 98 | SELECT * FROM runtests('whatever'::name); 99 | 100 | ROLLBACK; 101 | -------------------------------------------------------------------------------- /test/sql/runnotests.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | SET client_min_messages = warning; 4 | 5 | CREATE SCHEMA whatever; 6 | 7 | CREATE OR REPLACE FUNCTION whatever.testthis() RETURNS SETOF TEXT AS $$ 8 | BEGIN 9 | -- Do nothing. 10 | END; 11 | $$ LANGUAGE plpgsql; 12 | 13 | SELECT * FROM runtests('whatever'::name); 14 | ROLLBACK; 15 | -------------------------------------------------------------------------------- /test/sql/runtests.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | SET client_min_messages = warning; 4 | 5 | CREATE SCHEMA whatever; 6 | CREATE TABLE whatever.foo ( id serial primary key ); 7 | 8 | /* 9 | 10 | Expected output: 11 | 12 | runtests.out: 9.6 and up 13 | runtests_1.out: 9.5 14 | runtests_2.out: 9.3 - 9.4 15 | runtests_3.out: 9.2 16 | runtests_4.out: 9.1 17 | 18 | */ 19 | 20 | -- Make sure we get test function names. 21 | SET client_min_messages = notice; 22 | 23 | CREATE OR REPLACE FUNCTION whatever.startup() RETURNS SETOF TEXT AS $$ 24 | SELECT pass('starting up'); 25 | $$ LANGUAGE SQL; 26 | 27 | CREATE OR REPLACE FUNCTION whatever.startupmore() RETURNS SETOF TEXT AS $$ 28 | SELECT pass('starting up some more'); 29 | $$ LANGUAGE SQL; 30 | 31 | CREATE OR REPLACE FUNCTION whatever.setup() RETURNS SETOF TEXT AS $$ 32 | SELECT collect_tap(ARRAY[ 33 | pass('setup'), 34 | (SELECT is( MAX(id), NULL, 'Should be nothing in the test table') FROM whatever.foo) 35 | ]); 36 | $$ LANGUAGE SQL; 37 | 38 | CREATE OR REPLACE FUNCTION whatever.setupmore() RETURNS SETOF TEXT AS $$ 39 | SELECT pass('setup more'); 40 | $$ LANGUAGE SQL; 41 | 42 | CREATE OR REPLACE FUNCTION whatever.teardown() RETURNS SETOF TEXT AS $$ 43 | SELECT pass('teardown'); 44 | $$ LANGUAGE SQL; 45 | 46 | CREATE OR REPLACE FUNCTION whatever.teardownmore() RETURNS SETOF TEXT AS $$ 47 | SELECT pass('teardown more'); 48 | $$ LANGUAGE SQL; 49 | 50 | CREATE OR REPLACE FUNCTION whatever.shutdown() RETURNS SETOF TEXT AS $$ 51 | SELECT pass('shutting down'); 52 | $$ LANGUAGE SQL; 53 | 54 | CREATE OR REPLACE FUNCTION whatever.shutdownmore() RETURNS SETOF TEXT AS $$ 55 | SELECT pass('shutting down more'); 56 | $$ LANGUAGE SQL; 57 | 58 | CREATE OR REPLACE FUNCTION whatever.testthis() RETURNS SETOF TEXT AS $$ 59 | SELECT collect_tap(ARRAY[ 60 | pass('simple pass'), 61 | pass('another simple pass') 62 | ]); 63 | $$ LANGUAGE SQL; 64 | 65 | CREATE OR REPLACE FUNCTION whatever.testplpgsql() RETURNS SETOF TEXT AS $$ 66 | BEGIN 67 | RETURN NEXT pass( 'plpgsql simple' ); 68 | RETURN NEXT pass( 'plpgsql simple 2' ); 69 | INSERT INTO whatever.foo VALUES(1); 70 | RETURN NEXT is( MAX(id), 1, 'Should be a 1 in the test table') FROM whatever.foo; 71 | END; 72 | $$ LANGUAGE plpgsql; 73 | 74 | CREATE OR REPLACE FUNCTION whatever.testplpgsqldie() RETURNS SETOF TEXT AS $$ 75 | BEGIN 76 | RETURN NEXT pass( 'plpgsql simple' ); -- Won't appear in results. 77 | RETURN NEXT pass( 'plpgsql simple 2' ); -- Won't appear in results. 78 | INSERT INTO whatever.foo VALUES(1); 79 | RETURN NEXT is( MAX(id), 1, 'Should be a 1 in the test table') FROM whatever.foo; 80 | IF pg_version_num() >= 90300 THEN 81 | EXECUTE $E$ 82 | CREATE OR REPLACE FUNCTION __die() RETURNS VOID LANGUAGE plpgsql AS $F$ 83 | BEGIN 84 | RAISE EXCEPTION 'This test should die, but not halt execution. 85 | Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself.' 86 | USING 87 | DETAIL = 'DETAIL', 88 | COLUMN = 'COLUMN', 89 | CONSTRAINT = 'CONSTRAINT', 90 | DATATYPE = 'TYPE', 91 | TABLE = 'TABLE', 92 | SCHEMA = 'SCHEMA'; 93 | END; 94 | $F$; 95 | $E$; 96 | EXECUTE 'SELECT __die();'; 97 | ELSIF pg_version_num() >= 80400 THEN 98 | EXECUTE $E$ 99 | CREATE OR REPLACE FUNCTION __die() RETURNS VOID LANGUAGE plpgsql AS $F$ 100 | BEGIN 101 | RAISE EXCEPTION 'This test should die, but not halt execution. 102 | Note that in some cases we get what appears to be a duplicate context message, but that is due to Postgres itself.' 103 | USING DETAIL = 'DETAIL'; 104 | END; 105 | $F$; 106 | $E$; 107 | EXECUTE 'SELECT __die();'; 108 | ELSE 109 | RAISE EXCEPTION 'This test should die, but not halt execution'; 110 | END IF; 111 | END; 112 | $$ LANGUAGE plpgsql; 113 | 114 | CREATE OR REPLACE FUNCTION whatever.testdividebyzero() RETURNS SETOF TEXT AS $$ 115 | select cast(1/0 as text) 116 | $$ LANGUAGE sql; 117 | 118 | CREATE OR REPLACE FUNCTION whatever.testy() RETURNS SETOF TEXT AS $$ 119 | SELECT fail('this test intentionally fails'); 120 | $$ LANGUAGE SQL; 121 | 122 | CREATE OR REPLACE FUNCTION whatever.testz() RETURNS SETOF TEXT AS $$ 123 | SELECT is( MAX(id), NULL, 'Late test should find nothing in the test table') FROM whatever.foo; 124 | $$ LANGUAGE SQL; 125 | 126 | CREATE OR REPLACE FUNCTION whatever."test ident"() RETURNS SETOF TEXT AS $$ 127 | BEGIN 128 | RETURN NEXT pass( 'ident' ); 129 | RETURN NEXT pass( 'ident 2' ); 130 | END; 131 | $$ LANGUAGE plpgsql; 132 | 133 | -- Run the actual tests. Yes, it's a one-liner! 134 | SELECT * FROM runtests('whatever'::name); 135 | 136 | -- Verify that startup, shutdown, etc aren't run as normal tests 137 | SELECT * FROM runtests('whatever'::name, '.*') WHERE pg_version_num() >= 80300; 138 | 139 | ROLLBACK; 140 | -------------------------------------------------------------------------------- /test/sql/todotap.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(36); 5 | --SELECT * FROM no_plan(); 6 | 7 | /****************************************************************************/ 8 | -- Test todo tests. 9 | \echo ok 1 - todo fail 10 | \echo ok 2 - todo pass 11 | SELECT * FROM todo('just because', 2 ); 12 | SELECT is( 13 | fail('This is a todo test' ) || ' 14 | ' 15 | || pass('This is a todo test that unexpectedly passes' ), 16 | 'not ok 1 - This is a todo test # TODO just because 17 | # Failed (TODO) test 1: "This is a todo test" 18 | ok 2 - This is a todo test that unexpectedly passes # TODO just because', 19 | 'TODO tests should display properly' 20 | ); 21 | 22 | -- Try just a reason. 23 | \echo ok 4 - todo fail 24 | SELECT * FROM todo( 'for whatever reason' ); 25 | SELECT is( 26 | fail('Another todo test'), 27 | 'not ok 4 - Another todo test # TODO for whatever reason 28 | # Failed (TODO) test 4: "Another todo test"', 29 | 'Single default todo test should display properly' 30 | ); 31 | 32 | -- Try just a number. 33 | \echo ok 6 - todo fail 34 | \echo ok 7 - todo pass 35 | SELECT * FROM todo( 2 ); 36 | SELECT is( 37 | fail('This is a todo test' ) || ' 38 | ' 39 | || pass('This is a todo test that unexpectedly passes' ), 40 | 'not ok 6 - This is a todo test # TODO 41 | # Failed (TODO) test 6: "This is a todo test" 42 | ok 7 - This is a todo test that unexpectedly passes # TODO ', 43 | 'TODO tests should display properly' 44 | ); 45 | 46 | /****************************************************************************/ 47 | -- Test skipping tests. 48 | SELECT * FROM check_test( 49 | skip('Just because'), 50 | true, 51 | 'simple skip', 52 | '', 53 | 'SKIP Just because' 54 | ); 55 | 56 | SELECT * FROM check_test( 57 | skip('Just because', 1), 58 | true, 59 | 'skip with num', 60 | '', 61 | 'SKIP Just because' 62 | ); 63 | 64 | \echo ok 15 - Skip multiple 65 | \echo ok 16 - Skip multiple 66 | \echo ok 17 - Skip multiple 67 | SELECT is( 68 | skip( 'Whatever', 3 ), 69 | 'ok 15 # SKIP Whatever 70 | ok 16 # SKIP Whatever 71 | ok 17 # SKIP Whatever', 72 | 'We should get the proper output for multiple skips' 73 | ); 74 | 75 | -- Test inversion. 76 | SELECT * FROM check_test( 77 | skip(1, 'Just because'), 78 | true, 79 | 'inverted skip', 80 | '', 81 | 'SKIP Just because' 82 | ); 83 | 84 | -- Test num only. 85 | SELECT * FROM check_test( 86 | skip(1), 87 | true, 88 | 'num only', 89 | '', 90 | 'SKIP' 91 | ); 92 | 93 | /****************************************************************************/ 94 | -- Try nesting todo tests. 95 | \echo ok 25 - todo fail 96 | \echo ok 26 - todo fail 97 | \echo ok 27 - todo fail 98 | SELECT * FROM todo('just because', 2 ); 99 | SELECT is( 100 | ARRAY( 101 | SELECT fail('This is a todo test 1') AS stuff 102 | UNION 103 | SELECT todo::text FROM todo('inside') 104 | UNION 105 | SELECT fail('This is a todo test 2') 106 | UNION 107 | SELECT fail('This is a todo test 3') 108 | ORDER BY stuff 109 | ), 110 | ARRAY[ 111 | 'not ok 25 - This is a todo test 1 # TODO just because 112 | # Failed (TODO) test 25: "This is a todo test 1"', 113 | 'not ok 26 - This is a todo test 2 # TODO inside 114 | # Failed (TODO) test 26: "This is a todo test 2"', 115 | 'not ok 27 - This is a todo test 3 # TODO just because 116 | # Failed (TODO) test 27: "This is a todo test 3"' 117 | ], 118 | 'Nested todos should work properly' 119 | ); 120 | 121 | /****************************************************************************/ 122 | -- Test todo_start() and todo_end(). 123 | \echo ok 29 - todo fail 124 | \echo ok 30 - todo fail 125 | \echo ok 31 - todo fail 126 | SELECT * FROM todo_start('some todos'); 127 | SELECT is( 128 | ARRAY( 129 | SELECT fail('This is a todo test 1') AS stuff 130 | UNION 131 | SELECT in_todo()::text 132 | UNION 133 | SELECT todo::text FROM todo('inside') 134 | UNION 135 | SELECT fail('This is a todo test 2') 136 | UNION 137 | SELECT fail('This is a todo test 3') 138 | UNION 139 | SELECT todo_end::text FROM todo_end() 140 | UNION 141 | SELECT in_todo()::text 142 | ORDER BY stuff 143 | ), 144 | ARRAY[ 145 | 'false', 146 | 'not ok 29 - This is a todo test 1 # TODO some todos 147 | # Failed (TODO) test 29: "This is a todo test 1"', 148 | 'not ok 30 - This is a todo test 2 # TODO inside 149 | # Failed (TODO) test 30: "This is a todo test 2"', 150 | 'not ok 31 - This is a todo test 3 # TODO some todos 151 | # Failed (TODO) test 31: "This is a todo test 3"', 152 | 'true' 153 | ], 154 | 'todo_start() and todo_end() should work properly with in_todo()' 155 | ); 156 | 157 | /****************************************************************************/ 158 | -- Make sure we can reverse the arguments. 159 | \echo ok 33 - todo fail 160 | \echo ok 34 - todo pass 161 | SELECT * FROM todo(2, 'just because' ); 162 | SELECT is( 163 | fail('This is a todo test' ) || ' 164 | ' 165 | || fail('Another todo test'), 166 | 'not ok 33 - This is a todo test # TODO just because 167 | # Failed (TODO) test 33: "This is a todo test" 168 | not ok 34 - Another todo test # TODO just because 169 | # Failed (TODO) test 34: "Another todo test"', 170 | 'Should be able to revers the arguments to todo()' 171 | ); 172 | 173 | -- Test the exception. 174 | SELECT throws_ok( 175 | 'SELECT todo_end()', 176 | 'P0001', 177 | 'todo_end() called without todo_start()', 178 | 'Should get an exception when todo_end() is called without todo_start()' 179 | ); 180 | 181 | /****************************************************************************/ 182 | -- Finish the tests and clean up. 183 | SELECT * FROM finish(); 184 | ROLLBACK; 185 | -------------------------------------------------------------------------------- /test/sql/unique.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(18*3); 5 | 6 | -- This will be rolled back. :-) 7 | SET client_min_messages = warning; 8 | CREATE TABLE public.sometab( 9 | id INT NOT NULL PRIMARY KEY, 10 | name TEXT DEFAULT '' UNIQUE, 11 | numb NUMERIC(10, 2), 12 | myint NUMERIC(8), 13 | UNIQUE (numb, myint) 14 | ); 15 | -- This table has no unique index 16 | CREATE TABLE public.uniqueless( 17 | id INT PRIMARY KEY 18 | ); 19 | RESET client_min_messages; 20 | 21 | /****************************************************************************/ 22 | -- Test has_unique(). 23 | 24 | SELECT * FROM check_test( 25 | has_unique( 'public', 'sometab', 'public.sometab should have a unique constraint' ), 26 | true, 27 | 'has_unique( schema, table, description )', 28 | 'public.sometab should have a unique constraint', 29 | '' 30 | ); 31 | 32 | SELECT * FROM check_test( 33 | has_unique( 'sometab', 'sometab should have a unique constraint' ), 34 | true, 35 | 'has_unique( table, description )', 36 | 'sometab should have a unique constraint', 37 | '' 38 | ); 39 | 40 | SELECT * FROM check_test( 41 | has_unique( 'sometab' ), 42 | true, 43 | 'has_unique( table )', 44 | 'Table sometab should have a unique constraint', 45 | '' 46 | ); 47 | 48 | SELECT * FROM check_test( 49 | has_unique( 'public', 'uniqueless', 'public.uniqueless should have a unique constraint' ), 50 | false, 51 | 'has_unique( schema, table, description ) fail', 52 | 'public.uniqueless should have a unique constraint', 53 | '' 54 | ); 55 | 56 | SELECT * FROM check_test( 57 | has_unique( 'uniqueless', 'uniqueless should have a unique constraint' ), 58 | false, 59 | 'has_unique( table, description ) fail', 60 | 'uniqueless should have a unique constraint', 61 | '' 62 | ); 63 | 64 | /****************************************************************************/ 65 | -- Test col_is_unique(). 66 | 67 | SELECT * FROM check_test( 68 | col_is_unique( 'public', 'sometab', 'name', 'public.sometab.name should be unique' ), 69 | true, 70 | 'col_is_unique( schema, table, column, description )', 71 | 'public.sometab.name should be unique', 72 | '' 73 | ); 74 | 75 | SELECT * FROM check_test( 76 | col_is_unique( 'public', 'sometab', ARRAY['numb', 'myint'], 'public.sometab.numb+myint should be unique' ), 77 | true, 78 | 'col_is_unique( schema, table, columns, description )', 79 | 'public.sometab.numb+myint should be unique', 80 | '' 81 | ); 82 | 83 | SELECT * FROM check_test( 84 | col_is_unique( 'sometab', 'name', 'sometab.name should be unique' ), 85 | true, 86 | 'col_is_unique( table, column, description )', 87 | 'sometab.name should be unique', 88 | '' 89 | ); 90 | 91 | SELECT * FROM check_test( 92 | col_is_unique( 'sometab', ARRAY['numb', 'myint'], 'sometab.numb+myint should be unique' ), 93 | true, 94 | 'col_is_unique( table, columns, description )', 95 | 'sometab.numb+myint should be unique', 96 | '' 97 | ); 98 | 99 | SELECT * FROM check_test( 100 | col_is_unique( 'public', 'sometab', 'name'::name ), 101 | true, 102 | 'col_is_unique( schema, table, column )', 103 | 'Column sometab(name) should have a unique constraint', 104 | '' 105 | ); 106 | 107 | SELECT * FROM check_test( 108 | col_is_unique( 'public', 'sometab', ARRAY['numb'::name, 'myint'] ), 109 | true, 110 | 'col_is_unique( schema, table, columns )', 111 | 'Columns sometab(numb, myint) should have a unique constraint', 112 | '' 113 | ); 114 | 115 | SELECT * FROM check_test( 116 | col_is_unique( 'sometab', 'name' ), 117 | true, 118 | 'col_is_unique( table, column )', 119 | 'Column sometab(name) should have a unique constraint', 120 | '' 121 | ); 122 | 123 | SELECT * FROM check_test( 124 | col_is_unique( 'sometab', ARRAY['numb', 'myint'] ), 125 | true, 126 | 'col_is_unique( table, columns )', 127 | 'Columns sometab(numb, myint) should have a unique constraint', 128 | '' 129 | ); 130 | 131 | SELECT * FROM check_test( 132 | col_is_unique( 'public', 'sometab', 'id', 'public.sometab.id should be unique' ), 133 | false, 134 | 'col_is_unique( schema, table, column, description ) fail', 135 | 'public.sometab.id should be unique', 136 | ' have: {name} 137 | {numb,myint} 138 | want: {id}' 139 | ); 140 | 141 | SELECT * FROM check_test( 142 | col_is_unique( 'sometab', 'id', 'sometab.id should be unique' ), 143 | false, 144 | 'col_is_unique( table, column, description ) fail', 145 | 'sometab.id should be unique', 146 | ' have: {name} 147 | {numb,myint} 148 | want: {id}' 149 | ); 150 | 151 | /****************************************************************************/ 152 | -- Test col_is_unique() with an array of columns. 153 | 154 | SET client_min_messages = warning; 155 | CREATE TABLE public.argh ( 156 | id INT NOT NULL, 157 | name TEXT NOT NULL, 158 | UNIQUE (id, name) 159 | ); 160 | RESET client_min_messages; 161 | 162 | SELECT * FROM check_test( 163 | col_is_unique( 'public', 'argh', ARRAY['id', 'name'], 'id + name should be unique' ), 164 | true, 165 | 'col_is_unique( schema, table, column[], description )', 166 | 'id + name should be unique', 167 | '' 168 | ); 169 | 170 | SELECT * FROM check_test( 171 | col_is_unique( 'argh', ARRAY['id', 'name'], 'id + name should be unique' ), 172 | true, 173 | 'col_is_unique( table, column[], description )', 174 | 'id + name should be unique', 175 | '' 176 | ); 177 | 178 | SELECT * FROM check_test( 179 | col_is_unique( 'argh', ARRAY['id', 'name'] ), 180 | true, 181 | 'col_is_unique( table, column[] )', 182 | 'Columns argh(id, name) should have a unique constraint', 183 | '' 184 | ); 185 | 186 | /****************************************************************************/ 187 | -- Finish the tests and clean up. 188 | SELECT * FROM finish(); 189 | ROLLBACK; 190 | -------------------------------------------------------------------------------- /test/sql/util.sql: -------------------------------------------------------------------------------- 1 | \unset ECHO 2 | \i test/setup.sql 3 | 4 | SELECT plan(14); 5 | --SELECT * FROM no_plan(); 6 | 7 | SELECT is( pg_typeof(42), 'integer', 'pg_type(int) should work' ); 8 | SELECT is( pg_typeof(42.1), 'numeric', 'pg_type(numeric) should work' ); 9 | SELECT is( pg_typeof(''::text), 'text', 'pg_type(text) should work' ); 10 | 11 | SELECT is( pg_typeof( pg_version() ), 'text', 'pg_version() should return text' ); 12 | SELECT is( 13 | pg_version(), 14 | current_setting( 'server_version'), 15 | 'pg_version() should return same as "server_version" setting' 16 | ); 17 | SELECT matches( 18 | pg_version(), 19 | '(?x)' 20 | '(?: ^[89][.][[:digit:]]{1,2}([.][[:digit:]]{1,2}|devel|(alpha|beta|rc)[[:digit:]]+) )' 21 | '|' 22 | '(?: ^1[[:digit:]] (?: [.] [[:digit:]]{1,2} | devel | (?:alpha|beta|rc)[[:digit:]]+))', 23 | 'pg_version() should work' 24 | ); 25 | 26 | SELECT CASE WHEN pg_version_num() < 81000 27 | THEN pass( 'pg_version_num() should return same as "server_version_num" setting' ) 28 | ELSE is( 29 | pg_version_num(), 30 | current_setting('server_version_num')::integer, 31 | 'pg_version_num() should return same as "server_version_num" setting' 32 | ) 33 | END; 34 | 35 | SELECT is( 36 | pg_typeof( pg_version_num() ), 37 | 'integer', 38 | 'pg_version_num() should return integer' 39 | ); 40 | SELECT matches( 41 | pg_version_num()::text, 42 | '^[89][[:digit:]]{4}$|^1[[:digit:]]{5}$', 43 | 'pg_version_num() should be correct' 44 | ); 45 | 46 | SELECT matches( 47 | os_name(), 48 | '^[[:alnum:]]+$', 49 | 'os_name() should output something like an OS name' 50 | ); 51 | 52 | SELECT is( 53 | findfuncs('pg_catalog'::name, '^abs$'), 54 | ARRAY['pg_catalog.abs'], 55 | 'findfincs() should return distinct values' 56 | ); 57 | 58 | SELECT cmp_ok( 59 | pgtap_version(), 60 | '>=', 61 | 1.0, 62 | 'pgtap_version() should work' 63 | ); 64 | 65 | /****************************************************************************/ 66 | -- Test collect_tap(). 67 | SELECT is( 68 | collect_tap(ARRAY['foo', 'bar', 'baz']), 69 | 'foo 70 | bar 71 | baz', 72 | 'collect_tap(text[]) should simply collect tap' 73 | ); 74 | 75 | CREATE FUNCTION test_variadic() RETURNS TEXT AS $$ 76 | BEGIN 77 | IF pg_version_num() >= 80400 THEN 78 | RETURN collect_tap('foo', 'bar', 'baz'); 79 | ELSE 80 | RETURN collect_tap(ARRAY['foo', 'bar', 'baz']); 81 | END IF; 82 | END; 83 | $$ LANGUAGE plpgsql; 84 | 85 | SELECT is( 86 | test_variadic(), 87 | 'foo 88 | bar 89 | baz', 90 | 'variadic collect_tap() should simply collect tap' 91 | ); 92 | 93 | /****************************************************************************/ 94 | -- Finish the tests and clean up. 95 | SELECT * FROM finish(); 96 | ROLLBACK; 97 | -------------------------------------------------------------------------------- /tools/missing_extensions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | MISSING_EXTENSIONS=$1 4 | EXTENSION_TEST_FILES=$2 5 | 6 | # Doesn't seem worth pulling all of util.sh in for just this, but if you need 7 | # anything else please just pull it in! 8 | stderr() { 9 | echo "$@" >&2 10 | } 11 | 12 | if [ -n "$MISSING_EXTENSIONS" ]; then 13 | if [ -n "$ALLOW_MISSING_EXTENSIONS" ]; then 14 | stderr 15 | stderr '***************************' 16 | stderr "WARNING: Some mandatory extensions ($MISSING_EXTENSIONS) are not installed, ignoring tests: $EXTENSION_TEST_FILES" 17 | stderr '***************************' 18 | stderr 19 | else 20 | stderr 21 | stderr '***************************' 22 | stderr "ERROR: Missing extensions required for testing: $MISSING_EXTENSIONS" 23 | stderr 24 | stderr "You may over-ride by setting \$ALLOW_MISSING_EXTENSIONS to a value." 25 | stderr '***************************' 26 | stderr 27 | exit 1 28 | fi 29 | fi 30 | -------------------------------------------------------------------------------- /tools/parallel_conn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Find the maximum safe connections for parallel execution 4 | 5 | error () { 6 | echo $@ 1>&2 7 | } 8 | die () { 9 | error $@ 10 | exit 1 11 | } 12 | 13 | [ $# -le 1 ] || die "$0: Invalid number of arguments" 14 | 15 | PARALLEL_CONN=$1 16 | 17 | if [ -n "$PARALLEL_CONN" ]; then 18 | [ $PARALLEL_CONN -ge 1 ] 2>/dev/null || die "Invalid value for PARALLEL_CONN ($PARALLEL_CONN)" 19 | echo $PARALLEL_CONN 20 | exit 21 | fi 22 | 23 | COMMAND="SELECT greatest(1, current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int - (SELECT count(*) FROM pg_stat_activity) - 2)" 24 | 25 | if PARALLEL_CONN=`psql -d ${PGDATABASE:-postgres} -P pager=off -P tuples_only=true -qAXtc "$COMMAND" 2> /dev/null`; then 26 | if [ $PARALLEL_CONN -ge 1 ] 2>/dev/null; then 27 | # We know it's a number at this point 28 | [ $PARALLEL_CONN -eq 1 ] && error "NOTICE: unable to run tests in parallel; not enough connections" 29 | echo $PARALLEL_CONN 30 | exit 31 | fi 32 | fi 33 | 34 | error "Problems encountered determining maximum parallel test connections; forcing serial mode" 35 | echo 1 36 | -------------------------------------------------------------------------------- /tools/psql_args.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script allows for passing args to psql using pg_regress's --launcher option 4 | 5 | while [ $# -gt 0 ]; do 6 | case $1 in 7 | */psql) 8 | found=1 9 | break 10 | ;; 11 | *) 12 | args="$args $1" 13 | shift 14 | ;; 15 | esac 16 | done 17 | 18 | if [ -z "$found" ]; then 19 | echo "Error: psql not found in arguments" 20 | exit 1 21 | fi 22 | 23 | #$* $args <&0 || exit $? 24 | $* $args || exit $? 25 | -------------------------------------------------------------------------------- /tools/util.sh: -------------------------------------------------------------------------------- 1 | # Adapted from https://github.com/decibel/db_tools/blob/0.1.10/lib/util.sh 2 | 3 | ME=`basename $0` 4 | 5 | DEBUG=${DEBUG:-0} 6 | 7 | stderr() { 8 | echo "$@" 1>&2 9 | } 10 | 11 | debug() { 12 | local level=$1 13 | shift 14 | if [ $level -le $DEBUG ] ; then 15 | local oldIFS 16 | oldIFS=$IFS 17 | unset IFS 18 | # Output debug level if it's over threashold 19 | if [ $DEBUG -ge ${DEBUGEXTRA:-10} ]; then 20 | stderr "${level}: $@" 21 | else 22 | stderr "$@" 23 | fi 24 | IFS=$oldIFS 25 | fi 26 | } 27 | 28 | debug_vars () { 29 | level=$1 30 | shift 31 | local out='' 32 | local value='' 33 | for variable in $*; do 34 | eval value=\$$variable 35 | out="$out $variable='$value'" 36 | done 37 | debug $level $out 38 | } 39 | 40 | debug_do() { 41 | local level 42 | level=$1 43 | shift 44 | [ $level -gt $DEBUG ] || ( "$@" ) 45 | } 46 | 47 | debug_ls() { 48 | # Reverse test since we *exit* if we shouldn't debug! Also, note that unlike 49 | # `exit`, `return` does not default to 0. 50 | [ $1 -le $DEBUG ] || return 0 51 | ( 52 | level=$1 53 | shift 54 | 55 | # Look through each argument and see if more than one exist. If so, we don't 56 | # need to print what it is we're listing. 57 | location='' 58 | for a in "$@"; do 59 | if [ -e "$a" ]; then 60 | if [ -n "$location" ]; then 61 | location='' 62 | break 63 | else 64 | location=$a 65 | fi 66 | fi 67 | done 68 | 69 | stderr # blank line 70 | [ -z "$location" ] || stderr "$location" 71 | ls "$@" >&2 72 | ) 73 | } 74 | 75 | error() { 76 | local stack lineno 77 | stack='' 78 | lineno='' 79 | while [ "$1" = "-s" -o "$1" = "-n" ]; do 80 | if [ "$1" = "-n" ]; then 81 | lineno=$2 82 | shift 2 83 | fi 84 | if [ "$1" = "-s" ]; then 85 | stack=1 86 | shift 87 | fi 88 | done 89 | 90 | stderr "$@" 91 | 92 | if [ -n "$stack" ]; then 93 | stacktrace 1 # Skip our own frame 94 | else 95 | [ -z "$lineno" ] || echo "File \"$0\", line $lineno" 1>&2 96 | fi 97 | } 98 | 99 | die() { 100 | local return=$1 101 | debug_vars 99 return 102 | shift 103 | error "$@" 104 | [ $DEBUG -le 0 ] || stacktrace 1 105 | if [ -n "${DIE_EXTRA:-}" ]; then 106 | local lineno='' 107 | error 108 | error $DIE_EXTRA 109 | fi 110 | exit $return 111 | } 112 | 113 | db_exists() { 114 | local exists 115 | exists=`psql -qtc "SELECT EXISTS( SELECT 1 FROM pg_database WHERE datname = '$dbname' )" postgres $@ | tr -d ' '` 116 | if [ "$exists" == "t" ]; then 117 | return 0 118 | else 119 | return 1 120 | fi 121 | } 122 | 123 | stacktrace () { 124 | debug 200 "stacktrace( $@ )" 125 | local frame=${1:-0} 126 | local line='' 127 | local file='' 128 | debug_vars 200 frame line file 129 | 130 | # NOTE the stderr redirect below! 131 | ( 132 | echo 133 | echo Stacktrace: 134 | while caller $frame; do 135 | frame=$(( $frame + 1 )) 136 | done | while read line function file; do 137 | if [ -z "$function" -o "$function" = main ]; then 138 | echo "$file: line $line" 139 | else 140 | echo "$file: line $line: function $function" 141 | fi 142 | done 143 | ) 1>&2 144 | } 145 | 146 | # This is intended to be used by a trap, ie: 147 | # trap err_report ERR 148 | err_report() { 149 | stderr "errexit on line $(caller)" >&2 150 | } 151 | 152 | find_at_path() ( 153 | export PATH="$1:$PATH" # Unfortunately need to maintain old PATH to be able to find `which` :( 154 | out=$(command -v $2) 155 | [ -n "$out" ] || die 2 "unable to find $2" 156 | echo $out 157 | ) 158 | 159 | # vi: noexpandtab ts=2 sw=2 160 | --------------------------------------------------------------------------------