tests: Add tests for the pg-safeupdate library

This commit is contained in:
Laurence Isla
2022-08-10 11:50:57 -05:00
committed by GitHub
parent 57bc3d805c
commit 4ac47df528
8 changed files with 151 additions and 24 deletions
+6 -6
View File
@@ -46,12 +46,12 @@ let
postgresqlVersions =
[
{ name = "postgresql-14"; postgresql = pkgs.postgresql_14.withPackages (p: [ p.postgis ]); }
{ name = "postgresql-13"; postgresql = pkgs.postgresql_13.withPackages (p: [ p.postgis ]); }
{ name = "postgresql-12"; postgresql = pkgs.postgresql_12.withPackages (p: [ p.postgis ]); }
{ name = "postgresql-11"; postgresql = pkgs.postgresql_11.withPackages (p: [ p.postgis ]); }
{ name = "postgresql-10"; postgresql = pkgs.postgresql_10.withPackages (p: [ p.postgis ]); }
{ name = "postgresql-9.6"; postgresql = pkgs.postgresql_9_6.withPackages (p: [ p.postgis ]); }
{ name = "postgresql-14"; postgresql = pkgs.postgresql_14.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-13"; postgresql = pkgs.postgresql_13.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-12"; postgresql = pkgs.postgresql_12.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-11"; postgresql = pkgs.postgresql_11.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-10"; postgresql = pkgs.postgresql_10.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
{ name = "postgresql-9.6"; postgresql = pkgs.postgresql_9_6.withPackages (p: [ p.postgis p.pg_safeupdate ]); }
];
patches =
+1
View File
@@ -201,6 +201,7 @@ test-suite spec
Feature.Query.JsonOperatorSpec
Feature.Query.MultipleSchemaSpec
Feature.Query.ErrorSpec
Feature.Query.PgSafeUpdateSpec
Feature.Query.PostGISSpec
Feature.Query.QueryLimitedSpec
Feature.Query.QuerySpec
@@ -0,0 +1,76 @@
module Feature.Query.PgSafeUpdateSpec where
import Network.Wai (Application)
import Network.HTTP.Types
import Test.Hspec hiding (pendingWith)
import Test.Hspec.Wai
import Test.Hspec.Wai.JSON
import Protolude hiding (get, put)
import SpecHelper
spec :: SpecWith ((), Application)
spec =
describe "Enabling pg-safeupdate" $ do
context "Full table update" $
it "does not update and throws no error if no condition is present" $
request methodPatch "/safe_update"
[("Prefer", "count=exact")]
[json| {"name": "New name"} |]
`shouldRespondWith`
""
{ matchStatus = 404
, matchHeaders = [ matchHeaderAbsent hContentType
, "Content-Range" <:> "*/0" ]
}
context "Full table delete" $ do
it "does not delete and throws error if no condition is present" $
request methodDelete "/safe_delete" [] mempty
`shouldRespondWith`
[json|{
"code": "21000",
"details": null,
"hint": null,
"message": "DELETE requires a WHERE clause"
}|]
{ matchStatus = 400 }
it "allows full table delete if a filter is present" $
request methodDelete "/safe_delete?id=gt.0"
[("Prefer", "count=exact")]
mempty
`shouldRespondWith`
""
{ matchStatus = 204
, matchHeaders = [ matchHeaderAbsent hContentType
, "Content-Range" <:> "*/3" ]
}
disabledSpec :: SpecWith ((), Application)
disabledSpec =
describe "Disabling pg-safeupdate" $ do
context "Full table update" $
it "does not update and does not throw error if no condition is present" $
request methodPatch "/unsafe_update"
[("Prefer", "count=exact")]
[json| {"name": "New name"} |]
`shouldRespondWith`
""
{ matchStatus = 404
, matchHeaders = [ matchHeaderAbsent hContentType
, "Content-Range" <:> "*/0" ]
}
context "Full table delete" $
it "deletes and does not throw error if no condition is present" $ do
request methodDelete "/unsafe_delete"
[("Prefer", "count=exact")]
mempty
`shouldRespondWith`
""
{ matchStatus = 204
, matchHeaders = [ matchHeaderAbsent hContentType
, "Content-Range" <:> "*/3" ]
}
+25 -18
View File
@@ -45,6 +45,7 @@ import qualified Feature.Query.HtmlRawOutputSpec
import qualified Feature.Query.InsertSpec
import qualified Feature.Query.JsonOperatorSpec
import qualified Feature.Query.MultipleSchemaSpec
import qualified Feature.Query.PgSafeUpdateSpec
import qualified Feature.Query.PlanSpec
import qualified Feature.Query.PostGISSpec
import qualified Feature.Query.QueryLimitedSpec
@@ -112,6 +113,7 @@ main = do
forceRollbackApp = app testCfgForceRollback
testCfgLegacyGucsApp = app testCfgLegacyGucs
planEnabledApp = app testPlanEnabledCfg
pgSafeUpdateApp = app testPgSafeUpdateEnabledCfg
extraSearchPathApp = appDbs testCfgExtraSearchPath
unicodeApp = appDbs testUnicodeCfg
@@ -126,24 +128,25 @@ main = do
analyzeTable "child_entities"
specs = uncurry describe <$> [
("Feature.Query.AndOrParamsSpec" , Feature.Query.AndOrParamsSpec.spec actualPgVersion)
, ("Feature.Auth.AuthSpec" , Feature.Auth.AuthSpec.spec actualPgVersion)
, ("Feature.ConcurrentSpec" , Feature.ConcurrentSpec.spec)
, ("Feature.CorsSpec" , Feature.CorsSpec.spec)
, ("Feature.Query.DeleteSpec" , Feature.Query.DeleteSpec.spec)
, ("Feature.Query.EmbedDisambiguationSpec" , Feature.Query.EmbedDisambiguationSpec.spec)
, ("Feature.Query.EmbedInnerJoinSpec" , Feature.Query.EmbedInnerJoinSpec.spec)
, ("Feature.Query.InsertSpec" , Feature.Query.InsertSpec.spec actualPgVersion)
, ("Feature.Query.JsonOperatorSpec" , Feature.Query.JsonOperatorSpec.spec actualPgVersion)
, ("Feature.OpenApi.OpenApiSpec" , Feature.OpenApi.OpenApiSpec.spec actualPgVersion)
, ("Feature.OptionsSpec" , Feature.OptionsSpec.spec actualPgVersion)
, ("Feature.Query.PlanSpec.disabledSpec" , Feature.Query.PlanSpec.disabledSpec)
, ("Feature.Query.QuerySpec" , Feature.Query.QuerySpec.spec actualPgVersion)
, ("Feature.Query.RawOutputTypesSpec" , Feature.Query.RawOutputTypesSpec.spec)
, ("Feature.Query.RpcSpec" , Feature.Query.RpcSpec.spec actualPgVersion)
, ("Feature.Query.SingularSpec" , Feature.Query.SingularSpec.spec)
, ("Feature.Query.UpdateSpec" , Feature.Query.UpdateSpec.spec)
, ("Feature.Query.UpsertSpec" , Feature.Query.UpsertSpec.spec actualPgVersion)
("Feature.Query.AndOrParamsSpec" , Feature.Query.AndOrParamsSpec.spec actualPgVersion)
, ("Feature.Auth.AuthSpec" , Feature.Auth.AuthSpec.spec actualPgVersion)
, ("Feature.ConcurrentSpec" , Feature.ConcurrentSpec.spec)
, ("Feature.CorsSpec" , Feature.CorsSpec.spec)
, ("Feature.Query.DeleteSpec" , Feature.Query.DeleteSpec.spec)
, ("Feature.Query.EmbedDisambiguationSpec" , Feature.Query.EmbedDisambiguationSpec.spec)
, ("Feature.Query.EmbedInnerJoinSpec" , Feature.Query.EmbedInnerJoinSpec.spec)
, ("Feature.Query.InsertSpec" , Feature.Query.InsertSpec.spec actualPgVersion)
, ("Feature.Query.JsonOperatorSpec" , Feature.Query.JsonOperatorSpec.spec actualPgVersion)
, ("Feature.OpenApi.OpenApiSpec" , Feature.OpenApi.OpenApiSpec.spec actualPgVersion)
, ("Feature.OptionsSpec" , Feature.OptionsSpec.spec actualPgVersion)
, ("Feature.Query.PgSafeUpdateSpec.disabledSpec" , Feature.Query.PgSafeUpdateSpec.disabledSpec)
, ("Feature.Query.PlanSpec.disabledSpec" , Feature.Query.PlanSpec.disabledSpec)
, ("Feature.Query.QuerySpec" , Feature.Query.QuerySpec.spec actualPgVersion)
, ("Feature.Query.RawOutputTypesSpec" , Feature.Query.RawOutputTypesSpec.spec)
, ("Feature.Query.RpcSpec" , Feature.Query.RpcSpec.spec actualPgVersion)
, ("Feature.Query.SingularSpec" , Feature.Query.SingularSpec.spec)
, ("Feature.Query.UpdateSpec" , Feature.Query.UpdateSpec.spec)
, ("Feature.Query.UpsertSpec" , Feature.Query.UpsertSpec.spec actualPgVersion)
]
hspec $ do
@@ -234,6 +237,10 @@ main = do
parallel $ before planEnabledApp $
describe "Feature.Query.PlanSpec.spec" $ Feature.Query.PlanSpec.spec actualPgVersion
-- this test runs with a pre request to enable the pg-safeupdate library per-session
parallel $ before pgSafeUpdateApp $
describe "Feature.Query.PgSafeUpdateSpec.spec" Feature.Query.PgSafeUpdateSpec.spec
-- Note: the rollback tests can not run in parallel, because they test persistance and
-- this results in race conditions
+3
View File
@@ -196,6 +196,9 @@ testMultipleSchemaCfg = baseCfg { configDbSchemas = fromList ["v1", "v2", "SPECI
testCfgLegacyGucs :: AppConfig
testCfgLegacyGucs = baseCfg { configDbUseLegacyGucs = False }
testPgSafeUpdateEnabledCfg :: AppConfig
testPgSafeUpdateEnabledCfg = baseCfg { configDbPreRequest = Just $ QualifiedIdentifier "test" "load_safeupdate" }
analyzeTable :: Text -> IO ()
analyzeTable tableName =
void $ readProcess "psql" ["--set", "ON_ERROR_STOP=1", "-a", "-c", toS $ "ANALYZE test.\"" <> tableName <> "\""] []
+9
View File
@@ -803,3 +803,12 @@ INSERT INTO "SPECIAL ""@/\#~_-".names (id, name) VALUES (1, 'John'), (2, 'Mary')
TRUNCATE TABLE do$llar$s CASCADE;
INSERT INTO do$llar$s (a$num$) VALUES (100), (200), (300);
TRUNCATE TABLE safe_update CASCADE;
INSERT INTO safe_update(id, name) VALUES (1, 'First'), (2, 'Second'), (3, 'Third');
TRUNCATE TABLE safe_delete CASCADE;
INSERT INTO safe_delete(id, name) VALUES (1, 'First'), (2, 'Second'), (3, 'Third');
TRUNCATE TABLE unsafe_update CASCADE;
INSERT INTO unsafe_update(id, name) VALUES (1, 'First'), (2, 'Second'), (3, 'Third');
TRUNCATE TABLE unsafe_delete CASCADE;
INSERT INTO unsafe_delete(id, name) VALUES (1, 'First'), (2, 'Second'), (3, 'Third');
+4
View File
@@ -195,6 +195,10 @@ GRANT ALL ON TABLE
, shop_bles
, "SPECIAL ""@/\#~_-".names
, do$llar$s
, safe_update
, safe_delete
, unsafe_update
, unsafe_delete
TO postgrest_test_anonymous;
GRANT INSERT ON TABLE insertonly TO postgrest_test_anonymous;
+27
View File
@@ -2689,3 +2689,30 @@ $$ LANGUAGE sql;
CREATE TABLE do$llar$s (
a$num$ numeric
);
-- Tables and functions to test the pg-safeupdate library
CREATE TABLE test.safe_update(
id INT PRIMARY KEY,
name TEXT
);
CREATE TABLE test.safe_delete(
id INT PRIMARY KEY,
name TEXT
);
CREATE TABLE test.unsafe_update(
id INT PRIMARY KEY,
name TEXT
);
CREATE TABLE test.unsafe_delete(
id INT PRIMARY KEY,
name TEXT
);
CREATE OR REPLACE FUNCTION test.load_safeupdate() RETURNS VOID AS $$
BEGIN
LOAD 'safeupdate';
END; $$ LANGUAGE plpgsql SECURITY DEFINER;