From 53e11977648a6dcc0da6100d44436bac0c9bf3c3 Mon Sep 17 00:00:00 2001 From: "David E. Wheeler" Date: Sat, 7 Oct 2023 13:52:08 -0400 Subject: [PATCH] Fix tests on Postgres 16 --- sql/19-tag-stats-json.sql | 50 +++++++++++++++++++++++++++++++++++++++ t/dist_management.pg | 14 +++++------ t/json_data.pg | 8 +++---- t/tokens.pg | 21 ++++++---------- t/users.pg | 20 +++++++--------- 5 files changed, 76 insertions(+), 37 deletions(-) create mode 100644 sql/19-tag-stats-json.sql diff --git a/sql/19-tag-stats-json.sql b/sql/19-tag-stats-json.sql new file mode 100644 index 0000000..8ac5237 --- /dev/null +++ b/sql/19-tag-stats-json.sql @@ -0,0 +1,50 @@ +-- sql/19-tag-stats-json.sql SQL Migration + +SET client_min_messages TO warning; + +BEGIN; + +CREATE OR REPLACE FUNCTION tag_stats_json( + num_popular INT DEFAULT 56 +) RETURNS TEXT LANGUAGE sql STABLE STRICT AS $$ +/* + + % select tag_stats_json(4); + tag_stats_json + ────────────────────────────────────────────── + { ↵ + "count": 212, ↵ + "popular": [ ↵ + {"tag": "data types", "dists": 4}, ↵ + {"tag": "key value", "dists": 2}, ↵ + {"tag": "france", "dists": 1}, ↵ + {"tag": "key value pair", "dists": 1} ↵ + ] ↵ + } ↵ + +Returns a JSON representation of tag statistics. These include: + +* `count`: A count of all tags in the database. +* `popular`: A list of the most used tags in the system, listed in descending + order by the number of uses. + +Since tags are case-insensitive, `tag_stats_json()` returns lowercases tag +names. + +Pass in the optional `num_popular` parameter to limit the number of tags that +appear in the popular list. The default limit is 56. + +*/ + SELECT E'{\n "count": ' || COUNT(DISTINCT tag) || E',\n "popular": [\n' + || array_to_string(ARRAY( + SELECT ' {"tag": ' || json_value(LOWER(tag)) + || ', "dists": ' || COUNT(DISTINCT distribution) || E'}' + FROM distribution_tags + GROUP BY tag + ORDER BY COUNT(DISTINCT distribution) DESC, tag + LIMIT $1 + ), E',\n') || E'\n ]\n}\n' + FROM distribution_tags +$$; + +COMMIT; diff --git a/t/dist_management.pg b/t/dist_management.pg index 332966c..fcb2d49 100644 --- a/t/dist_management.pg +++ b/t/dist_management.pg @@ -10,7 +10,7 @@ SELECT has_function(f) ]) AS f; SELECT has_function('setup_meta', ARRAY['label', 'text', 'text']); -SELECT has_function('record_ownership', ARRAY['label', 'text[]']); +SELECT has_function('record_ownership', ARRAY['label', 'text[]']); -- ' SELECT has_function('add_distribution', ARRAY['label', 'text', 'text']); SELECT has_function('get_distribution', ARRAY['term', 'semver']); SELECT has_function('update_distribution', ARRAY['label', 'text', 'text']); @@ -189,7 +189,7 @@ SELECT results_eq( -- Test record_ownership(). SELECT function_returns('record_ownership', ARRAY['label', 'text[]'], 'boolean' ); SELECT function_lang_is('record_ownership', ARRAY['label', 'text[]'], 'plpgsql' ); -SELECT volatility_is( 'record_ownership', ARRAY['label', 'text[]'], 'volatile' ); +SELECT volatility_is( 'record_ownership', ARRAY['label', 'text[]'], 'volatile' ); -- ' SELECT throws_ok( $$ SELECT record_ownership('nobody', ARRAY['foo']) $$, @@ -826,7 +826,7 @@ SELECT bag_eq( {"tag": "foo", "dists": 2}, {"tag": "bar", "dists": 1}, {"tag": "baz", "dists": 1}, - {"tag": "PAIR", "dists": 1} + {"tag": "pair", "dists": 1} ] } '), ('stats','user','{ @@ -1116,11 +1116,11 @@ SELECT bag_eq( '), ('stats','tag','{ "count": 6, "popular": [ - {"tag": "Foo", "dists": 2}, + {"tag": "foo", "dists": 2}, {"tag": "bar", "dists": 1}, {"tag": "baz", "dists": 1}, {"tag": "heavy", "dists": 1}, - {"tag": "PAIR", "dists": 1}, + {"tag": "pair", "dists": 1}, {"tag": "words", "dists": 1} ] } @@ -1534,7 +1534,7 @@ SELECT bag_eq( {"tag": "foo", "dists": 2}, {"tag": "bar", "dists": 1}, {"tag": "baz", "dists": 1}, - {"tag": "PAIR", "dists": 1}, + {"tag": "pair", "dists": 1}, {"tag": "wang", "dists": 1}, {"tag": "words", "dists": 1}, {"tag": "yo", "dists": 1} @@ -1877,7 +1877,7 @@ SELECT bag_eq( {"tag": "foo", "dists": 2}, {"tag": "bar", "dists": 1}, {"tag": "baz", "dists": 1}, - {"tag": "PAIR", "dists": 1}, + {"tag": "pair", "dists": 1}, {"tag": "wang", "dists": 1}, {"tag": "words", "dists": 1}, {"tag": "yo", "dists": 1} diff --git a/t/json_data.pg b/t/json_data.pg index c988bbb..ef3205b 100644 --- a/t/json_data.pg +++ b/t/json_data.pg @@ -644,12 +644,12 @@ VALUES ('pair', '0.0.1', 'foo'), ('pair', '0.0.2-a1', 'foo'), ('pair', '0.0.2', 'foo'), - ('trip', '0.2.5', 'foo'), + ('trip', '0.2.5', 'Foo'), ('pair', '0.0.10', 'foo'), -- bar for two latest pairs. - ('pair', '0.0.2', 'bar'), - ('pair', '0.0.10', 'bar') + ('pair', '0.0.2', 'Bar'), + ('pair', '0.0.10', 'Bar') ; SELECT is_empty( @@ -760,7 +760,7 @@ SELECT results_eq( SELECT results_eq( $$ SELECT * FROM tag_json('pair', '0.0.10') ORDER BY tag $$, $$ VALUES ('bar'::tag, '{ - "tag": "bar", + "tag": "Bar", "releases": { "pair": { "stable": [ diff --git a/t/tokens.pg b/t/tokens.pg index f7eb157..9262b7b 100644 --- a/t/tokens.pg +++ b/t/tokens.pg @@ -70,18 +70,12 @@ SELECT is( /****************************************************************************/ -- Now mock rand_str_of_len() CREATE SCHEMA mock; - -CREATE FUNCTION mock.set_rand_str( - string TEXT -) RETURNS SETOF BOOLEAN LANGUAGE plperl AS $$ - $_SHARED{random_string} = shift; - return; -$$; +SET SESSION mock.random_string = 'foobar'; CREATE FUNCTION mock.rand_str_of_len( INTEGER -) RETURNS TEXT LANGUAGE plperl AS $$ - return $_SHARED{random_string}; +) RETURNS TEXT LANGUAGE sql AS $$ + SELECT current_setting('mock.random_string') $$; DO LANGUAGE plpgsql $$ @@ -90,7 +84,6 @@ BEGIN END; $$; -SELECT * FROM set_rand_str('foobar'); SELECT is(rand_str_of_len(NULL), 'foobar', 'Should get mocked random string'); /****************************************************************************/ @@ -174,7 +167,7 @@ SELECT ok( ); UPDATE users SET status = 'active' WHERE nickname = 'strongrrl'; -SELECT * FROM set_rand_str('howdy'); +SET SESSION mock.random_string = 'howdy'; SELECT is( forgot_password('strongrrl'), ARRAY['howdy', 'strongrrl@pgxn.org'], @@ -190,7 +183,7 @@ SELECT is( ) FROM tokens WHERE token = 'howdy'; -- Create another token for the same user. -SELECT * FROM set_rand_str('booyah'); +SET SESSION mock.random_string = 'booyah'; SELECT is( forgot_password('theory'), ARRAY['booyah','theory@pgxn.org'], @@ -276,7 +269,7 @@ SELECT is(set_by, 'kamala', 'New user should have been set by self') FROM users WHERE nickname = 'kamala'; -- Update the mocked random string. -SELECT * FROM set_rand_str('clanker'); +SET SESSION mock.random_string = 'clanker'; SELECT is(rand_str_of_len(NULL), 'clanker', 'Should get new mocked random string'); -- Now clear the password. @@ -311,7 +304,7 @@ SELECT throws_like( ); -- Create another token for the same user. -SELECT * FROM set_rand_str('mobius'); +SET SESSION mock.random_string = 'mobius'; SELECT is( clear_password('theory', 'kamala', '10 days'), ARRAY['mobius','kamala@pgxn.org'], diff --git a/t/users.pg b/t/users.pg index 4dd9add..cb0e7d2 100644 --- a/t/users.pg +++ b/t/users.pg @@ -232,17 +232,13 @@ SELECT throws_ok( /*****************************************************************************/ -- Mock NOW(). CREATE SCHEMA mock; - -CREATE FUNCTION set_now(timestamptz) RETURNS SETOF boolean LANGUAGE plperl AS $$ - $_SHARED{now} = shift; - return; -$$; +SET SESSION mock.time = '2010-08-19 11:01:03.306399+00'; -- Won't be used by table defaults, which seem to be linked to -- pg_catalog.now() at creation time. -CREATE FUNCTION mock.now() RETURNS timestamptz LANGUAGE plperl AS '$_SHARED{now}'; - -SELECT * FROM set_now('2010-08-19 11:01:03.306399+00'); +CREATE FUNCTION mock.now() RETURNS timestamptz IMMUTABLE PARALLEL SAFE LANGUAGE sql AS $$ + SELECT current_setting('mock.time')::timestamptz +$$; DO LANGUAGE plpgsql $$ BEGIN @@ -375,7 +371,7 @@ SELECT is( 'Password should be unchanged' ) FROM users WHERE nickname = 'theory'; -SELECT * FROM set_now('2010-08-19 14:01:03.306399+00'); +SET SESSION mock.time = '2010-08-19 14:01:03.306399+00'; SELECT isnt(updated_at, '2010-08-19 14:01:03.306399+00', 'updated_at should be default') FROM users WHERE nickname = 'theory'; @@ -464,7 +460,7 @@ SELECT ok( ); -- Update now(). -SELECT * FROM set_now('2010-08-20 14:01:03.306399+00'); +SET SESSION mock.time = '2010-08-20 14:01:03.306399+00'; SELECT ok( update_user( @@ -636,7 +632,7 @@ SELECT ok( UPDATE users SET updated_at = pg_catalog.now() WHERE nickname IN ('theory', 'strongrrl'); -SELECT * FROM set_now('2010-08-21 22:01:03.306399+00'); +SET SESSION mock.time = '2010-08-21 22:01:03.306399+00'; SELECT ok(is_admin, nickname || ' should be an admin') FROM users WHERE nickname IN ('theory', 'strongrrl'); @@ -706,7 +702,7 @@ SELECT is( 'User visted_at should be updated' ) FROM users WHERE nickname = 'theory'; -SELECT * FROM set_now('2010-08-23 11:01:03.306399+00'); +SET SESSION mock.time = '2010-08-23 11:01:03.306399+00'; -- Invalid password. SELECT ok(