diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8f017e0279e35f893c9fdc9c98ac92cc17179b74..d6f9b81448787abb7b8de740833ac631229c0e86 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,3 +4,4 @@ build:
     - "x86_64-linux"
   script:
     - "cabal update && cabal build -w $GHC"
+    - "HPC=hpc cabal test -w $GHC"
diff --git a/hpc-bin.cabal b/hpc-bin.cabal
index da9deaa399743420ee0646f132678246928f751d..75ed0bfb3b94800a3ab956ccd013f6f1f48ff216 100644
--- a/hpc-bin.cabal
+++ b/hpc-bin.cabal
@@ -42,7 +42,7 @@ library
     autogen-modules: Paths_hpc_bin
 
     build-depends: base       >= 4   && < 5,
-                   deepseq    >= 1.4.7 && < 1.5,
+                   deepseq    >= 1.4.4 && < 1.5,
                    directory  >= 1   && < 1.4,
                    filepath   >= 1   && < 1.5,
                    containers >= 0.1 && < 0.7,
@@ -59,3 +59,25 @@ executable hpc
 
     build-depends: base >= 4 && < 5,
                    hpc-bin
+
+test-suite hpc-test
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  other-modules:
+      Paths_hpc_bin
+  autogen-modules:
+      Paths_hpc_bin
+  hs-source-dirs:
+      test
+  build-tool-depends: hpc-bin:hpc
+  build-depends:
+      base         >= 4   && < 5
+    , directory    >= 1   && < 1.4
+    , filepath      >= 1   && < 1.5
+    , process
+    , tasty
+    , tasty-golden
+    , tasty-hunit
+    , text
+    , utf8-string
+  default-language: Haskell2010
\ No newline at end of file
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
index 0000000000000000000000000000000000000000..4b383725db350b8d97a7fdc8b74c13fe60a0333e
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,99 @@
+import System.Process
+import System.Environment (getEnv)
+import System.Directory (doesFileExist)
+import Data.List
+import Control.Monad (void)
+import qualified Data.ByteString.Lazy.UTF8 as BS
+import qualified System.FilePath as FP
+import Test.Tasty
+import Test.Tasty.HUnit
+import Test.Tasty.Golden as G
+
+main :: IO ()
+main = defaultMain . testGroup "hpc tests" $
+    [ t10138
+    , t2991
+    , t17073
+    , t20568
+    , t11798
+    ]
+
+inputDir :: FilePath
+inputDir = "test" FP.</> "inputs"
+
+goldDir :: FilePath
+goldDir = FP.joinPath ["test", "gold"]
+
+goldFile :: FilePath -> FilePath
+goldFile file = goldDir FP.</> file
+
+rm :: [FilePath] -> IO ()
+rm files = void $ readCreateProcess ((shell (intercalate " && " . map ("rm -r " <>) $ files)) { cwd = Just inputDir }) ""
+
+runCommands :: [IO String] -> IO String
+runCommands commands = do
+    cmds <- traverse id commands
+    readCreateProcess ((shell $ intercalate " && " cmds) { cwd = Just inputDir }) "" 
+
+hpc :: String -> IO String
+hpc args = (<> args) . (<> " ") <$> getEnv "HPC"
+
+ghc :: String -> IO String
+ghc args = (<> args) . (<> " ") <$> getEnv "GHC"
+
+exec :: String -> String
+exec = ("./" <>)
+
+{- Tests -}
+
+t10138 :: TestTree
+t10138 = testCaseInfo "T10138" $ runCommands . pure $ hpc . intercalate " " $ 
+    ["report", "T10138.keepme.tix", "--hpcdir=.keepme.hpc.T10138"]
+
+t2991 :: TestTree
+t2991 = testCaseInfo "T2991" $ do
+    runCommands commands
+    clean
+    pure ""
+  where
+    -- The .mix file for the literate module should have non-zero entries
+    -- The 'grep' should exit with exit code 0
+    commands = [ghc "-fhpc T2991.hs", pure $ exec "T2991", pure "grep -q cover_me .hpc/T2991LiterateModule.mix"]
+    clean = rm ["*.hi", "*.o", "T2991", "T2991.tix", ".hpc"]  
+
+t17073 :: TestTree
+t17073 = goldenVsString "T17073" (goldFile "T17073.stdout") $ do 
+        out1 <- runCommands commands
+        clean
+        pure $ BS.fromString out1
+  where
+    commands = [ ("LANG=ASCII " <>) <$> ghc "-fhpc -v0 T17073.hs"
+                , pure $ exec "T17073"
+                , hpc "report T17073"
+                , hpc "version"
+                , ("LANG=ASCII " <>) <$> hpc "markup T17073"
+                ]
+    clean = rm ["T17073.hi", "T17073.o", "T17073", "*.html", "T17073.tix", ".hpc"]
+
+t20568 :: TestTree
+t20568 = goldenVsString "T20568" (goldFile "T20568.stdout") $ do
+        out <- runCommands commands
+        clean
+        pure $ BS.fromString $ last . lines $ out
+  where
+    commands = [ghc "T20568", pure $ exec "T20568"]
+    clean = rm ["T20568.hi", "T20568.o", "T20568"]    
+
+-- test that adding -fhpc triggers recompilation
+t11798 :: TestTree
+t11798 = goldenVsString "T11798" (goldFile "T11798.stdout") $ do
+        c1 <- ghc "T11798.hs"
+        out1 <- readCreateProcess ((shell c1) { cwd = Just inputDir }) ""
+        c2 <- ghc "-fhpc T11798.hs"
+        out2 <- readCreateProcess ((shell c2) { cwd = Just inputDir }) ""
+        fmap (assertBool ".hpc/T11798.mix does not exist") $ doesFileExist $ 
+            ".hpc" FP.</> "T11798.mix"
+        clean
+        pure $ BS.fromString $ unlines [last . lines $ out1,  last . lines $ out2]
+  where
+    clean = rm ["T11798.hi", "T11798.o", ".hpc"]
diff --git a/test/gold/T11798.stdout b/test/gold/T11798.stdout
new file mode 100644
index 0000000000000000000000000000000000000000..90142ddd41a4abc3c173c92367c77fd6a70fd92d
--- /dev/null
+++ b/test/gold/T11798.stdout
@@ -0,0 +1,2 @@
+[1 of 1] Compiling T11798           ( T11798.hs, T11798.o )
+[1 of 1] Compiling T11798           ( T11798.hs, T11798.o ) [HPC flags changed]
diff --git a/test/gold/T17073.stdout b/test/gold/T17073.stdout
new file mode 100644
index 0000000000000000000000000000000000000000..8abd540776a4e0874580a673a9e0a0fd4497c45d
--- /dev/null
+++ b/test/gold/T17073.stdout
@@ -0,0 +1,15 @@
+Добрый день
+100% expressions used (2/2)
+100% boolean coverage (0/0)
+     100% guards (0/0)
+     100% 'if' conditions (0/0)
+     100% qualifiers (0/0)
+100% alternatives used (0/0)
+100% local declarations used (0/0)
+100% top-level declarations used (1/1)
+hpc tools, version 0.68
+Writing: Main.hs.html
+Writing: hpc_index.html
+Writing: hpc_index_fun.html
+Writing: hpc_index_alt.html
+Writing: hpc_index_exp.html
diff --git a/test/gold/T20568.stdout b/test/gold/T20568.stdout
new file mode 100644
index 0000000000000000000000000000000000000000..6a2c427f8195ee8248d96e53060e747ab01de5d1
--- /dev/null
+++ b/test/gold/T20568.stdout
@@ -0,0 +1 @@
+IfThenElse (AstBool True) (AstInt 1) (AstInt 2)
\ No newline at end of file
diff --git a/test/inputs/.keepme.hpc.T10138/Main.mix b/test/inputs/.keepme.hpc.T10138/Main.mix
new file mode 100644
index 0000000000000000000000000000000000000000..26611fef243b96905ec125581274f01b3d53c0ce
--- /dev/null
+++ b/test/inputs/.keepme.hpc.T10138/Main.mix
@@ -0,0 +1 @@
+Mix "T10138.hs" 2015-03-09 18:22:16.403500034 UTC 2143033233 8 [(1:15-1:16,ExpBox False),(1:8-1:16,ExpBox False),(1:1-1:16,TopLevelBox ["main"])]
diff --git a/test/inputs/T10138.keepme.tix b/test/inputs/T10138.keepme.tix
new file mode 100644
index 0000000000000000000000000000000000000000..f348f7089ea1fce249ed3d7f7f3f54e473088549
--- /dev/null
+++ b/test/inputs/T10138.keepme.tix
@@ -0,0 +1 @@
+Tix [ TixModule "Main" 2143033233 3 [0,1,1]]
diff --git a/test/inputs/T11798.hs b/test/inputs/T11798.hs
new file mode 100644
index 0000000000000000000000000000000000000000..08d3558b714e365b8a92a7adb7c0ceddf5d36f04
--- /dev/null
+++ b/test/inputs/T11798.hs
@@ -0,0 +1,3 @@
+module T11798 where
+
+f x = [x,x,x]
\ No newline at end of file
diff --git a/test/inputs/T17073.hs b/test/inputs/T17073.hs
new file mode 100644
index 0000000000000000000000000000000000000000..d1e0a45b9aa26d37942ffbcb0fc9ce123cb3d902
--- /dev/null
+++ b/test/inputs/T17073.hs
@@ -0,0 +1,5 @@
+module Main where
+
+main :: IO ()
+main = putStrLn "Добрый день"
+
diff --git a/test/inputs/T20568.hs b/test/inputs/T20568.hs
new file mode 100644
index 0000000000000000000000000000000000000000..929f3eeb1ce9083a7945991d9ee9b87c5693de0b
--- /dev/null
+++ b/test/inputs/T20568.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE RebindableSyntax #-}
+
+-- | Test for #20586 regression: rebindable if shouldn't crash
+module Main where
+
+import Prelude
+
+main :: IO ()
+main = print $ program
+  where
+    program :: AST
+    program =
+      if AstBool True
+      then AstInt 1
+      else AstInt 2
+
+data AST =
+    AstGT AST AST
+  | AstInt Integer
+  | AstBool Bool
+  | IfThenElse AST AST AST
+  deriving Show
+
+ifThenElse :: AST -> AST -> AST -> AST
+ifThenElse = IfThenElse
diff --git a/test/inputs/T2991.hs b/test/inputs/T2991.hs
new file mode 100644
index 0000000000000000000000000000000000000000..62f26627ef8a39faac7e5c2dc633c7c6014bee7d
--- /dev/null
+++ b/test/inputs/T2991.hs
@@ -0,0 +1,5 @@
+module Main where
+-- Test that there are actually entries in the .mix file for an imported
+-- literate module
+import T2991LiterateModule
+main = return ()
diff --git a/test/inputs/T2991LiterateModule.lhs b/test/inputs/T2991LiterateModule.lhs
new file mode 100644
index 0000000000000000000000000000000000000000..55fc31c70fe2b9055a01e4012630ed34ee9dc4f8
--- /dev/null
+++ b/test/inputs/T2991LiterateModule.lhs
@@ -0,0 +1,4 @@
+\begin{code}
+module T2991LiterateModule where
+cover_me = 1
+\end{code}