run spec tests in parallel
reduces time to run postgrest-test-spec-all by 20-25%
This commit is contained in:
committed by
Wolfgang Walther
parent
a52c114ff4
commit
dbe3c163bd
+12
-11
@@ -293,29 +293,30 @@ spec actualPgVersion = do
|
|||||||
-- reset pk sequence first to make test repeatable
|
-- reset pk sequence first to make test repeatable
|
||||||
request methodPost "/rpc/reset_sequence"
|
request methodPost "/rpc/reset_sequence"
|
||||||
[("Prefer", "tx=commit")]
|
[("Prefer", "tx=commit")]
|
||||||
[json|{"name": "items_id_seq", "value": 20}|]
|
[json|{"name": "items2_id_seq", "value": 20}|]
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|""|]
|
[json|""|]
|
||||||
|
|
||||||
request methodPost "/items" [("Prefer", "return=representation")] "{}"
|
request methodPost "/items2"
|
||||||
`shouldRespondWith` [json|[{ id: 20 }]|]
|
[("Prefer", "return=representation")]
|
||||||
{ matchStatus = 201,
|
[json|{}|]
|
||||||
matchHeaders = []
|
`shouldRespondWith`
|
||||||
}
|
[json|[{ id: 20 }]|]
|
||||||
|
{ matchStatus = 201 }
|
||||||
|
|
||||||
it "successfully inserts a row with all-default columns with prefer=rep and &select=" $ do
|
it "successfully inserts a row with all-default columns with prefer=rep and &select=" $ do
|
||||||
-- reset pk sequence first to make test repeatable
|
-- reset pk sequence first to make test repeatable
|
||||||
request methodPost "/rpc/reset_sequence"
|
request methodPost "/rpc/reset_sequence"
|
||||||
[("Prefer", "tx=commit")]
|
[("Prefer", "tx=commit")]
|
||||||
[json|{"name": "items_id_seq", "value": 20}|]
|
[json|{"name": "items3_id_seq", "value": 20}|]
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|""|]
|
[json|""|]
|
||||||
|
|
||||||
request methodPost "/items?select=id" [("Prefer", "return=representation")] "{}"
|
request methodPost "/items3?select=id"
|
||||||
|
[("Prefer", "return=representation")]
|
||||||
|
[json|{}|]
|
||||||
`shouldRespondWith` [json|[{ id: 20 }]|]
|
`shouldRespondWith` [json|[{ id: 20 }]|]
|
||||||
{ matchStatus = 201,
|
{ matchStatus = 201 }
|
||||||
matchHeaders = []
|
|
||||||
}
|
|
||||||
|
|
||||||
context "POST with ?columns parameter" $ do
|
context "POST with ?columns parameter" $ do
|
||||||
it "ignores json keys not included in ?columns" $ do
|
it "ignores json keys not included in ?columns" $ do
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ shouldPersistMutations reqHeaders respHeaders = do
|
|||||||
[json|[{"id":0}]|]
|
[json|[{"id":0}]|]
|
||||||
{ matchStatus = 201
|
{ matchStatus = 201
|
||||||
, matchHeaders = respHeaders }
|
, matchHeaders = respHeaders }
|
||||||
get "items?id=eq.0"
|
get "/items?id=eq.0"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":0}]|]
|
[json|[{"id":0}]|]
|
||||||
deleteItems
|
deleteItems
|
||||||
@@ -92,7 +92,7 @@ shouldPersistMutations reqHeaders respHeaders = do
|
|||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":0}]|]
|
[json|[{"id":0}]|]
|
||||||
{ matchHeaders = respHeaders }
|
{ matchHeaders = respHeaders }
|
||||||
get "items?id=eq.0"
|
get "/items?id=eq.0"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":0}]|]
|
[json|[{"id":0}]|]
|
||||||
deleteItems
|
deleteItems
|
||||||
@@ -105,10 +105,10 @@ shouldPersistMutations reqHeaders respHeaders = do
|
|||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":-1}]|]
|
[json|[{"id":-1}]|]
|
||||||
{ matchHeaders = respHeaders }
|
{ matchHeaders = respHeaders }
|
||||||
get "items?id=eq.0"
|
get "/items?id=eq.0"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[]|]
|
[json|[]|]
|
||||||
get "items?id=eq.-1"
|
get "/items?id=eq.-1"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":-1}]|]
|
[json|[{"id":-1}]|]
|
||||||
deleteItems
|
deleteItems
|
||||||
@@ -121,7 +121,7 @@ shouldPersistMutations reqHeaders respHeaders = do
|
|||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":0}]|]
|
[json|[{"id":0}]|]
|
||||||
{ matchHeaders = respHeaders }
|
{ matchHeaders = respHeaders }
|
||||||
get "items?id=eq.0"
|
get "/items?id=eq.0"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[]|]
|
[json|[]|]
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ shouldNotPersistMutations reqHeaders respHeaders = do
|
|||||||
[json|[{"id":0}]|]
|
[json|[{"id":0}]|]
|
||||||
{ matchStatus = 201
|
{ matchStatus = 201
|
||||||
, matchHeaders = respHeaders }
|
, matchHeaders = respHeaders }
|
||||||
get "items?id=eq.0"
|
get "/items?id=eq.0"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[]|]
|
[json|[]|]
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ shouldNotPersistMutations reqHeaders respHeaders = do
|
|||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":0}]|]
|
[json|[{"id":0}]|]
|
||||||
{ matchHeaders = respHeaders }
|
{ matchHeaders = respHeaders }
|
||||||
get "items?id=eq.0"
|
get "/items?id=eq.0"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[]|]
|
[json|[]|]
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ shouldNotPersistMutations reqHeaders respHeaders = do
|
|||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":0}]|]
|
[json|[{"id":0}]|]
|
||||||
{ matchHeaders = respHeaders }
|
{ matchHeaders = respHeaders }
|
||||||
get "items?id=eq.0"
|
get "/items?id=eq.0"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[]|]
|
[json|[]|]
|
||||||
get "items?id=eq.1"
|
get "items?id=eq.1"
|
||||||
@@ -170,7 +170,7 @@ shouldNotPersistMutations reqHeaders respHeaders = do
|
|||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":1}]|]
|
[json|[{"id":1}]|]
|
||||||
{ matchHeaders = respHeaders }
|
{ matchHeaders = respHeaders }
|
||||||
get "items?id=eq.1"
|
get "/items?id=eq.1"
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|[{"id":1}]|]
|
[json|[{"id":1}]|]
|
||||||
|
|
||||||
|
|||||||
@@ -51,32 +51,14 @@ spec = do
|
|||||||
|
|
||||||
context "in a nonempty table" $ do
|
context "in a nonempty table" $ do
|
||||||
it "can update a single item" $ do
|
it "can update a single item" $ do
|
||||||
get "/items?id=eq.42"
|
patch "/items?id=eq.2"
|
||||||
`shouldRespondWith`
|
|
||||||
[json|[]|]
|
|
||||||
|
|
||||||
request methodPatch "/items?id=eq.2"
|
|
||||||
[("Prefer", "tx=commit")]
|
|
||||||
[json| { "id":42 } |]
|
[json| { "id":42 } |]
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
""
|
""
|
||||||
{ matchStatus = 204
|
{ matchStatus = 204
|
||||||
, matchHeaders = ["Content-Range" <:> "0-0/*"
|
, matchHeaders = ["Content-Range" <:> "0-0/*"]
|
||||||
, "Preference-Applied" <:> "tx=commit" ]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- check it really got updated
|
|
||||||
get "/items?id=eq.42"
|
|
||||||
`shouldRespondWith`
|
|
||||||
[json|[ { "id": 42 } ]|]
|
|
||||||
|
|
||||||
-- put value back for other tests
|
|
||||||
request methodPatch "/items?id=eq.42"
|
|
||||||
[("Prefer", "tx=commit")]
|
|
||||||
[json| { "id":2 } |]
|
|
||||||
`shouldRespondWith`
|
|
||||||
204
|
|
||||||
|
|
||||||
it "returns empty array when no rows updated and return=rep" $
|
it "returns empty array when no rows updated and return=rep" $
|
||||||
request methodPatch "/items?id=eq.999999"
|
request methodPatch "/items?id=eq.999999"
|
||||||
[("Prefer", "return=representation")] [json| { "id":999999 } |]
|
[("Prefer", "return=representation")] [json| { "id":999999 } |]
|
||||||
|
|||||||
+31
-25
@@ -114,7 +114,6 @@ main = do
|
|||||||
, ("Feature.OptionsSpec" , Feature.OptionsSpec.spec)
|
, ("Feature.OptionsSpec" , Feature.OptionsSpec.spec)
|
||||||
, ("Feature.QuerySpec" , Feature.QuerySpec.spec actualPgVersion)
|
, ("Feature.QuerySpec" , Feature.QuerySpec.spec actualPgVersion)
|
||||||
, ("Feature.RawOutputTypesSpec" , Feature.RawOutputTypesSpec.spec)
|
, ("Feature.RawOutputTypesSpec" , Feature.RawOutputTypesSpec.spec)
|
||||||
, ("Feature.RollbackAllowedSpec" , Feature.RollbackSpec.allowed)
|
|
||||||
, ("Feature.RpcSpec" , Feature.RpcSpec.spec actualPgVersion)
|
, ("Feature.RpcSpec" , Feature.RpcSpec.spec actualPgVersion)
|
||||||
, ("Feature.SingularSpec" , Feature.SingularSpec.spec)
|
, ("Feature.SingularSpec" , Feature.SingularSpec.spec)
|
||||||
, ("Feature.UpdateSpec" , Feature.UpdateSpec.spec)
|
, ("Feature.UpdateSpec" , Feature.UpdateSpec.spec)
|
||||||
@@ -122,56 +121,74 @@ main = do
|
|||||||
]
|
]
|
||||||
|
|
||||||
hspec $ do
|
hspec $ do
|
||||||
mapM_ (before withApp) specs
|
mapM_ (parallel . before withApp) specs
|
||||||
|
|
||||||
-- we analyze to get accurate results from EXPLAIN
|
-- we analyze to get accurate results from EXPLAIN
|
||||||
beforeAll_ analyze . before withApp $
|
parallel $ beforeAll_ analyze . before withApp $
|
||||||
describe "Feature.RangeSpec" Feature.RangeSpec.spec
|
describe "Feature.RangeSpec" Feature.RangeSpec.spec
|
||||||
|
|
||||||
-- this test runs with a raw-output-media-types set to text/html
|
-- this test runs with a raw-output-media-types set to text/html
|
||||||
before htmlRawOutputApp $
|
parallel $ before htmlRawOutputApp $
|
||||||
describe "Feature.HtmlRawOutputSpec" Feature.HtmlRawOutputSpec.spec
|
describe "Feature.HtmlRawOutputSpec" Feature.HtmlRawOutputSpec.spec
|
||||||
|
|
||||||
-- this test runs with a different server flag
|
-- this test runs with a different server flag
|
||||||
before maxRowsApp $
|
parallel $ before maxRowsApp $
|
||||||
describe "Feature.QueryLimitedSpec" Feature.QueryLimitedSpec.spec
|
describe "Feature.QueryLimitedSpec" Feature.QueryLimitedSpec.spec
|
||||||
|
|
||||||
-- this test runs with a different schema
|
-- this test runs with a different schema
|
||||||
before unicodeApp $
|
parallel $ before unicodeApp $
|
||||||
describe "Feature.UnicodeSpec" Feature.UnicodeSpec.spec
|
describe "Feature.UnicodeSpec" Feature.UnicodeSpec.spec
|
||||||
|
|
||||||
-- this test runs with a proxy
|
-- this test runs with a proxy
|
||||||
before proxyApp $
|
parallel $ before proxyApp $
|
||||||
describe "Feature.ProxySpec" Feature.ProxySpec.spec
|
describe "Feature.ProxySpec" Feature.ProxySpec.spec
|
||||||
|
|
||||||
-- this test runs without a JWT secret
|
-- this test runs without a JWT secret
|
||||||
before noJwtApp $
|
parallel $ before noJwtApp $
|
||||||
describe "Feature.NoJwtSpec" Feature.NoJwtSpec.spec
|
describe "Feature.NoJwtSpec" Feature.NoJwtSpec.spec
|
||||||
|
|
||||||
-- this test runs with a binary JWT secret
|
-- this test runs with a binary JWT secret
|
||||||
before binaryJwtApp $
|
parallel $ before binaryJwtApp $
|
||||||
describe "Feature.BinaryJwtSecretSpec" Feature.BinaryJwtSecretSpec.spec
|
describe "Feature.BinaryJwtSecretSpec" Feature.BinaryJwtSecretSpec.spec
|
||||||
|
|
||||||
-- this test runs with a binary JWT secret and an audience claim
|
-- this test runs with a binary JWT secret and an audience claim
|
||||||
before audJwtApp $
|
parallel $ before audJwtApp $
|
||||||
describe "Feature.AudienceJwtSecretSpec" Feature.AudienceJwtSecretSpec.spec
|
describe "Feature.AudienceJwtSecretSpec" Feature.AudienceJwtSecretSpec.spec
|
||||||
|
|
||||||
-- this test runs with asymmetric JWK
|
-- this test runs with asymmetric JWK
|
||||||
before asymJwkApp $
|
parallel $ before asymJwkApp $
|
||||||
describe "Feature.AsymmetricJwtSpec" Feature.AsymmetricJwtSpec.spec
|
describe "Feature.AsymmetricJwtSpec" Feature.AsymmetricJwtSpec.spec
|
||||||
|
|
||||||
-- this test runs with asymmetric JWKSet
|
-- this test runs with asymmetric JWKSet
|
||||||
before asymJwkSetApp $
|
parallel $ before asymJwkSetApp $
|
||||||
describe "Feature.AsymmetricJwtSpec" Feature.AsymmetricJwtSpec.spec
|
describe "Feature.AsymmetricJwtSpec" Feature.AsymmetricJwtSpec.spec
|
||||||
|
|
||||||
-- this test runs with a nonexistent db-schema
|
-- this test runs with a nonexistent db-schema
|
||||||
before nonexistentSchemaApp $
|
parallel $ before nonexistentSchemaApp $
|
||||||
describe "Feature.NonexistentSchemaSpec" Feature.NonexistentSchemaSpec.spec
|
describe "Feature.NonexistentSchemaSpec" Feature.NonexistentSchemaSpec.spec
|
||||||
|
|
||||||
-- this test runs with an extra search path
|
-- this test runs with an extra search path
|
||||||
before extraSearchPathApp $
|
parallel $ before extraSearchPathApp $
|
||||||
describe "Feature.ExtraSearchPathSpec" Feature.ExtraSearchPathSpec.spec
|
describe "Feature.ExtraSearchPathSpec" Feature.ExtraSearchPathSpec.spec
|
||||||
|
|
||||||
|
when (actualPgVersion >= pgVersion96) $ do
|
||||||
|
-- this test runs with a root spec function override
|
||||||
|
parallel $ before rootSpecApp $
|
||||||
|
describe "Feature.RootSpec" Feature.RootSpec.spec
|
||||||
|
parallel $ before responseHeadersApp $
|
||||||
|
describe "Feature.RpcPreRequestGucsSpec" Feature.RpcPreRequestGucsSpec.spec
|
||||||
|
|
||||||
|
-- this test runs with multiple schemas
|
||||||
|
parallel $ before multipleSchemaApp $
|
||||||
|
describe "Feature.MultipleSchemaSpec" $ Feature.MultipleSchemaSpec.spec actualPgVersion
|
||||||
|
|
||||||
|
-- Note: the rollback tests can not run in parallel, because they test persistance and
|
||||||
|
-- this results in race conditions
|
||||||
|
|
||||||
|
-- this test runs with tx-rollback-all = true and tx-allow-override = true
|
||||||
|
before withApp $
|
||||||
|
describe"Feature.RollbackAllowedSpec" Feature.RollbackSpec.allowed
|
||||||
|
|
||||||
-- this test runs with tx-rollback-all = false and tx-allow-override = false
|
-- this test runs with tx-rollback-all = false and tx-allow-override = false
|
||||||
before disallowRollbackApp $
|
before disallowRollbackApp $
|
||||||
describe "Feature.RollbackDisallowedSpec" Feature.RollbackSpec.disallowed
|
describe "Feature.RollbackDisallowedSpec" Feature.RollbackSpec.disallowed
|
||||||
@@ -180,17 +197,6 @@ main = do
|
|||||||
before forceRollbackApp $
|
before forceRollbackApp $
|
||||||
describe "Feature.RollbackForcedSpec" Feature.RollbackSpec.forced
|
describe "Feature.RollbackForcedSpec" Feature.RollbackSpec.forced
|
||||||
|
|
||||||
when (actualPgVersion >= pgVersion96) $ do
|
|
||||||
-- this test runs with a root spec function override
|
|
||||||
before rootSpecApp $
|
|
||||||
describe "Feature.RootSpec" Feature.RootSpec.spec
|
|
||||||
before responseHeadersApp $
|
|
||||||
describe "Feature.RpcPreRequestGucsSpec" Feature.RpcPreRequestGucsSpec.spec
|
|
||||||
|
|
||||||
-- this test runs with multiple schemas
|
|
||||||
before multipleSchemaApp $
|
|
||||||
describe "Feature.MultipleSchemaSpec" $ Feature.MultipleSchemaSpec.spec actualPgVersion
|
|
||||||
|
|
||||||
where
|
where
|
||||||
setupDbStructure pool schemas extraSearchPath ver =
|
setupDbStructure pool schemas extraSearchPath ver =
|
||||||
either (panic.show) id <$> P.use pool (HT.transaction HT.ReadCommitted HT.Read $ getDbStructure (toList schemas) extraSearchPath ver True)
|
either (panic.show) id <$> P.use pool (HT.transaction HT.ReadCommitted HT.Read $ getDbStructure (toList schemas) extraSearchPath ver True)
|
||||||
|
|||||||
Vendored
+3
@@ -16,6 +16,7 @@ SET search_path = test, "تست", pg_catalog;
|
|||||||
GRANT ALL ON TABLE
|
GRANT ALL ON TABLE
|
||||||
items
|
items
|
||||||
, items2
|
, items2
|
||||||
|
, items3
|
||||||
, "articleStars"
|
, "articleStars"
|
||||||
, articles
|
, articles
|
||||||
, auto_incrementing_pk
|
, auto_incrementing_pk
|
||||||
@@ -143,6 +144,8 @@ GRANT INSERT ON TABLE insertonly TO postgrest_test_anonymous;
|
|||||||
GRANT USAGE ON SEQUENCE
|
GRANT USAGE ON SEQUENCE
|
||||||
auto_incrementing_pk_id_seq
|
auto_incrementing_pk_id_seq
|
||||||
, items_id_seq
|
, items_id_seq
|
||||||
|
, items2_id_seq
|
||||||
|
, items3_id_seq
|
||||||
, callcounter_count
|
, callcounter_count
|
||||||
, leak_id_seq
|
, leak_id_seq
|
||||||
TO postgrest_test_anonymous;
|
TO postgrest_test_anonymous;
|
||||||
|
|||||||
Vendored
+4
@@ -113,6 +113,10 @@ CREATE TABLE items2 (
|
|||||||
id bigserial primary key
|
id bigserial primary key
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE items3 (
|
||||||
|
id bigserial primary key
|
||||||
|
);
|
||||||
|
|
||||||
CREATE FUNCTION search(id BIGINT) RETURNS SETOF items
|
CREATE FUNCTION search(id BIGINT) RETURNS SETOF items
|
||||||
LANGUAGE plpgsql
|
LANGUAGE plpgsql
|
||||||
AS $$BEGIN
|
AS $$BEGIN
|
||||||
|
|||||||
Reference in New Issue
Block a user