diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | ChangeLog.md | 3 | ||||
-rw-r--r-- | LICENSE | 30 | ||||
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | Setup.hs | 2 | ||||
-rw-r--r-- | package.yaml | 44 | ||||
-rw-r--r-- | src/Squeal/PostgreSQL/Hspec.hs | 114 | ||||
-rw-r--r-- | stack.yaml | 69 | ||||
-rw-r--r-- | test/Spec.hs | 2 |
9 files changed, 268 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2449568 --- /dev/null +++ b/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | .stack-work/ | ||
2 | squeal-hspec.cabal | ||
3 | *~ \ No newline at end of file | ||
diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 0000000..f9a2fd7 --- /dev/null +++ b/ChangeLog.md | |||
@@ -0,0 +1,3 @@ | |||
1 | # Changelog for squeal-hspec | ||
2 | |||
3 | ## Unreleased changes | ||
@@ -0,0 +1,30 @@ | |||
1 | Copyright Author name here (c) 2019 | ||
2 | |||
3 | All rights reserved. | ||
4 | |||
5 | Redistribution and use in source and binary forms, with or without | ||
6 | modification, are permitted provided that the following conditions are met: | ||
7 | |||
8 | * Redistributions of source code must retain the above copyright | ||
9 | notice, this list of conditions and the following disclaimer. | ||
10 | |||
11 | * Redistributions in binary form must reproduce the above | ||
12 | copyright notice, this list of conditions and the following | ||
13 | disclaimer in the documentation and/or other materials provided | ||
14 | with the distribution. | ||
15 | |||
16 | * Neither the name of Author name here nor the names of other | ||
17 | contributors may be used to endorse or promote products derived | ||
18 | from this software without specific prior written permission. | ||
19 | |||
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
diff --git a/README.md b/README.md new file mode 100644 index 0000000..56f44b9 --- /dev/null +++ b/README.md | |||
@@ -0,0 +1 @@ | |||
# squeal-hspec | |||
diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/Setup.hs | |||
@@ -0,0 +1,2 @@ | |||
1 | import Distribution.Simple | ||
2 | main = defaultMain | ||
diff --git a/package.yaml b/package.yaml new file mode 100644 index 0000000..fb93c52 --- /dev/null +++ b/package.yaml | |||
@@ -0,0 +1,44 @@ | |||
1 | name: squeal-hspec | ||
2 | version: 0.1.0.0 | ||
3 | github: "githubuser/squeal-hspec" | ||
4 | license: BSD3 | ||
5 | author: "Author name here" | ||
6 | maintainer: "example@example.com" | ||
7 | copyright: "2019 Author name here" | ||
8 | |||
9 | extra-source-files: | ||
10 | - README.md | ||
11 | - ChangeLog.md | ||
12 | |||
13 | # Metadata used when publishing your package | ||
14 | # synopsis: Short description of your package | ||
15 | # category: Web | ||
16 | |||
17 | # To avoid duplicated efforts in documentation and dealing with the | ||
18 | # complications of embedding Haddock markup inside cabal files, it is | ||
19 | # common to point users to the README.md file. | ||
20 | description: Please see the README on GitHub at <https://github.com/githubuser/squeal-hspec#readme> | ||
21 | |||
22 | dependencies: | ||
23 | - base >= 4.7 && < 5 | ||
24 | - bytestring | ||
25 | - squeal-postgresql | ||
26 | - hspec | ||
27 | - tmp-postgres | ||
28 | - monad-control | ||
29 | - transformers-base | ||
30 | - generics-sop | ||
31 | |||
32 | library: | ||
33 | source-dirs: src | ||
34 | |||
35 | tests: | ||
36 | squeal-hspec-test: | ||
37 | main: Spec.hs | ||
38 | source-dirs: test | ||
39 | ghc-options: | ||
40 | - -threaded | ||
41 | - -rtsopts | ||
42 | - -with-rtsopts=-N | ||
43 | dependencies: | ||
44 | - squeal-hspec | ||
diff --git a/src/Squeal/PostgreSQL/Hspec.hs b/src/Squeal/PostgreSQL/Hspec.hs new file mode 100644 index 0000000..44011b7 --- /dev/null +++ b/src/Squeal/PostgreSQL/Hspec.hs | |||
@@ -0,0 +1,114 @@ | |||
1 | {-| | ||
2 | Helpers for creating database tests with hspec and squeal, inspired by Jonathan Fischoff's | ||
3 | [hspec-pg-transact](http://hackage.haskell.org/package/hspec-pg-transact). | ||
4 | |||
5 | This uses @tmp-postgres@ to automatically and connect to a temporary instance of postgres on a random port. | ||
6 | |||
7 | Tests can be written with 'itDB' which is wrapper around 'it' that uses the passed in 'TestDB' to run a db transaction automatically for the test. | ||
8 | |||
9 | The libary also provides a few other functions for more fine grained control over running transactions in tests. | ||
10 | -} | ||
11 | {-# LANGUAGE DataKinds #-} | ||
12 | {-# LANGUAGE FlexibleContexts #-} | ||
13 | {-# LANGUAGE KindSignatures #-} | ||
14 | {-# LANGUAGE MonoLocalBinds #-} | ||
15 | {-# LANGUAGE RankNTypes #-} | ||
16 | {-# LANGUAGE RecordWildCards #-} | ||
17 | {-# LANGUAGE TypeInType #-} | ||
18 | {-# LANGUAGE TypeOperators #-} | ||
19 | module Squeal.PostgreSQL.Hspec | ||
20 | where | ||
21 | |||
22 | import Control.Exception | ||
23 | import Control.Monad | ||
24 | import Control.Monad.Base (liftBase) | ||
25 | import Control.Monad.Trans.Control (MonadBaseControl) | ||
26 | import qualified Data.ByteString.Char8 as BSC | ||
27 | import qualified Database.Postgres.Temp as Temp | ||
28 | import Generics.SOP (K) | ||
29 | import Squeal.PostgreSQL | ||
30 | import Squeal.PostgreSQL.Migration | ||
31 | import Squeal.PostgreSQL.Pool | ||
32 | import Test.Hspec | ||
33 | |||
34 | data TestDB a = TestDB | ||
35 | { tempDB :: Temp.DB | ||
36 | -- ^ Handle for temporary @postgres@ process | ||
37 | , pool :: Pool a | ||
38 | -- ^ Pool of 50 connections to the temporary @postgres@ | ||
39 | } | ||
40 | |||
41 | type Migrations schema m a = (MonadBaseControl IO m) => | ||
42 | PQ (("schema_migrations" ::: Table MigrationsTable) ': '[]) | ||
43 | (("schema_migrations" ::: Table MigrationsTable) ': schema) m a | ||
44 | |||
45 | type Fixtures schema = (Pool (K Connection schema) -> IO ()) | ||
46 | type Actions schema a = PoolPQ schema IO a | ||
47 | type SquealContext (schema :: SchemaType) = TestDB (K Connection schema) | ||
48 | |||
49 | -- | Start a temporary @postgres@ process and create a pool of connections to it | ||
50 | setupDB | ||
51 | :: Migrations schema IO a | ||
52 | -> Fixtures schema | ||
53 | -> IO (SquealContext schema) | ||
54 | setupDB migration fixtures = do | ||
55 | tempDB <- either throwIO return =<< Temp.startAndLogToTmp [] | ||
56 | let connectionString = BSC.pack (Temp.connectionString tempDB) | ||
57 | putStrLn $ Temp.connectionString tempDB | ||
58 | let singleStripe = 1 | ||
59 | keepConnectionForOneHour = 3600 | ||
60 | poolSizeOfFifty = 50 | ||
61 | pool <- createConnectionPool | ||
62 | connectionString | ||
63 | singleStripe | ||
64 | keepConnectionForOneHour | ||
65 | poolSizeOfFifty | ||
66 | withConnection connectionString migration | ||
67 | fixtures pool | ||
68 | pure TestDB {..} | ||
69 | |||
70 | -- | Drop all the connections and shutdown the @postgres@ process | ||
71 | teardownDB :: TestDB a -> IO () | ||
72 | teardownDB TestDB {..} = do | ||
73 | destroyAllResources pool | ||
74 | void $ Temp.stop tempDB | ||
75 | |||
76 | -- | Run an 'IO' action with a connection from the pool | ||
77 | withPool :: TestDB (K Connection schema) -> Actions schema a -> IO a | ||
78 | withPool testDB = liftBase . flip runPoolPQ (pool testDB) | ||
79 | |||
80 | -- | Run an 'DB' transaction, using 'transactionally_' | ||
81 | withDB :: Actions schema a -> TestDB (K Connection schema) -> IO a | ||
82 | withDB action testDB = | ||
83 | runPoolPQ (transactionally_ action) (pool testDB) | ||
84 | |||
85 | -- | Flipped version of 'withDB' | ||
86 | runDB :: TestDB (K Connection schema) -> Actions schema a -> IO a | ||
87 | runDB = flip withDB | ||
88 | |||
89 | -- | Helper for writing tests. Wrapper around 'it' that uses the passed | ||
90 | -- in 'TestDB' to run a db transaction automatically for the test. | ||
91 | itDB :: String -> Actions schema a -> SpecWith (TestDB (K Connection schema)) | ||
92 | itDB msg action = it msg $ void . withDB action | ||
93 | |||
94 | -- | Wraps 'describe' with a | ||
95 | -- | ||
96 | -- @ | ||
97 | -- 'beforeAll' ('setupDB' migrate) | ||
98 | -- @ | ||
99 | -- | ||
100 | -- hook for creating a db and a | ||
101 | -- | ||
102 | -- @ | ||
103 | -- 'afterAll' 'teardownDB' | ||
104 | -- @ | ||
105 | -- | ||
106 | -- hook for stopping a db. | ||
107 | describeDB | ||
108 | :: Migrations schema IO a | ||
109 | -> Fixtures schema | ||
110 | -> String | ||
111 | -> SpecWith (SquealContext schema) | ||
112 | -> Spec | ||
113 | describeDB migrate fixture str = | ||
114 | beforeAll (setupDB migrate fixture) . afterAll teardownDB . describe str | ||
diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..913ef7a --- /dev/null +++ b/stack.yaml | |||
@@ -0,0 +1,69 @@ | |||
1 | # This file was automatically generated by 'stack init' | ||
2 | # | ||
3 | # Some commonly used options have been documented as comments in this file. | ||
4 | # For advanced use and comprehensive documentation of the format, please see: | ||
5 | # https://docs.haskellstack.org/en/stable/yaml_configuration/ | ||
6 | |||
7 | # Resolver to choose a 'specific' stackage snapshot or a compiler version. | ||
8 | # A snapshot resolver dictates the compiler version and the set of packages | ||
9 | # to be used for project dependencies. For example: | ||
10 | # | ||
11 | # resolver: lts-3.5 | ||
12 | # resolver: nightly-2015-09-21 | ||
13 | # resolver: ghc-7.10.2 | ||
14 | # resolver: ghcjs-0.1.0_ghc-7.10.2 | ||
15 | # | ||
16 | # The location of a snapshot can be provided as a file or url. Stack assumes | ||
17 | # a snapshot provided as a file might change, whereas a url resource does not. | ||
18 | # | ||
19 | # resolver: ./custom-snapshot.yaml | ||
20 | # resolver: https://example.com/snapshots/2018-01-01.yaml | ||
21 | resolver: lts-12.20 | ||
22 | |||
23 | # User packages to be built. | ||
24 | # Various formats can be used as shown in the example below. | ||
25 | # | ||
26 | # packages: | ||
27 | # - some-directory | ||
28 | # - https://example.com/foo/bar/baz-0.0.2.tar.gz | ||
29 | # - location: | ||
30 | # git: https://github.com/commercialhaskell/stack.git | ||
31 | # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a | ||
32 | # - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a | ||
33 | # subdirs: | ||
34 | # - auto-update | ||
35 | # - wai | ||
36 | packages: | ||
37 | - '.' | ||
38 | |||
39 | # Dependency packages to be pulled from upstream that are not in the resolver | ||
40 | # using the same syntax as the packages field. | ||
41 | # (e.g., acme-missiles-0.3) | ||
42 | extra-deps: | ||
43 | - squeal-postgresql-0.4.0.0 | ||
44 | - records-sop-0.1.0.2 | ||
45 | - tmp-postgres-0.1.1.0 | ||
46 | |||
47 | # Override default flag values for local packages and extra-deps | ||
48 | # flags: {} | ||
49 | |||
50 | # Extra package databases containing global packages | ||
51 | # extra-package-dbs: [] | ||
52 | |||
53 | # Control whether we use the GHC we find on the path | ||
54 | # system-ghc: true | ||
55 | # | ||
56 | # Require a specific version of stack, using version ranges | ||
57 | # require-stack-version: -any # Default | ||
58 | # require-stack-version: ">=1.7" | ||
59 | # | ||
60 | # Override the architecture used by stack, especially useful on Windows | ||
61 | # arch: i386 | ||
62 | # arch: x86_64 | ||
63 | # | ||
64 | # Extra directories used by stack for building | ||
65 | # extra-include-dirs: [/path/to/dir] | ||
66 | # extra-lib-dirs: [/path/to/dir] | ||
67 | # | ||
68 | # Allow a newer minor version of GHC than the snapshot specifies | ||
69 | # compiler-check: newer-minor | ||
diff --git a/test/Spec.hs b/test/Spec.hs new file mode 100644 index 0000000..cd4753f --- /dev/null +++ b/test/Spec.hs | |||
@@ -0,0 +1,2 @@ | |||
1 | main :: IO () | ||
2 | main = putStrLn "Test suite not yet implemented" | ||