diff --git a/changelog.txt b/changelog.txt
--- a/changelog.txt
+++ b/changelog.txt
@@ -2,5 +2,8 @@
 
 Version 0.1.0.2, published October 2020:
   ★ Adds tighter version bounds
-  ★ Supports base16-bytestring version 1.0,
-    drops support for earlier versions
+  ★ Supports base16-bytestring version 1.0, drops support for earlier versions
+
+Version 0.1.0.4, published March 2021:
+  ★ Adds support for GHC 9.0
+  ★ Removes the test suite's dependency on doctest
diff --git a/hex-text.cabal b/hex-text.cabal
--- a/hex-text.cabal
+++ b/hex-text.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.2
 
 name: hex-text
-version: 0.1.0.2
+version: 0.1.0.4
 category: Text
 
 synopsis: ByteString-Text hexidecimal conversions
@@ -15,7 +15,7 @@
 author:     Chris Martin
 maintainer: Chris Martin, Julie Moronuki
 
-copyright: 2018 Typeclass Consulting, LLC
+copyright: 2021 Mission Valley Software LLC
 license: MIT
 license-file: license.txt
 
@@ -27,7 +27,8 @@
   , GHC == 8.4.3
   , GHC == 8.6.5
   , GHC == 8.8.4
-  , GHC == 8.10.1
+  , GHC == 8.10.3
+  , GHC == 9.0.1
 
 extra-source-files:
     README.md
@@ -42,20 +43,20 @@
   ghc-options: -Wall
   hs-source-dirs: src
   build-depends:
-      base >=4.9 && <4.15
+      base >=4.9 && <4.16
     , base16-bytestring ^>= 1.0
     , bytestring ^>=0.10 || ^>=0.11
     , text ^>= 1.2
   exposed-modules:
       Text.Hex
 
-test-suite doctest
+test-suite test
   default-language: Haskell2010
-  ghc-options: -Wall
   hs-source-dirs: test
   type: exitcode-stdio-1.0
-  main-is: doctest.hs
-  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  main-is: test.hs
   build-depends:
-      base >=4.9 && <4.15
-    , doctest ^>= 0.16 || ^>= 0.17
+      base >=4.9 && <4.16
+    , bytestring ^>=0.10 || ^>=0.11
+    , hex-text
+    , text ^>= 1.2
diff --git a/license.txt b/license.txt
--- a/license.txt
+++ b/license.txt
@@ -1,4 +1,4 @@
-Copyright 2018 Typeclass Consulting, LLC
+Copyright 2021 Mission Valley Software LLC
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
diff --git a/test/doctest.hs b/test/doctest.hs
deleted file mode 100644
--- a/test/doctest.hs
+++ /dev/null
@@ -1,5 +0,0 @@
-import Test.DocTest
-
-main :: IO ()
-main =
-  doctest [ "-isrc", "src/Text/Hex.hs" ]
diff --git a/test/test.hs b/test/test.hs
new file mode 100644
--- /dev/null
+++ b/test/test.hs
@@ -0,0 +1,47 @@
+import Data.Foldable
+import Data.Semigroup
+import Data.String
+import Numeric.Natural
+import System.Exit
+import Text.Hex
+
+import qualified Data.ByteString as ByteString
+import qualified Data.ByteString.Lazy as LazyByteString
+import qualified Data.Text as Text
+import qualified Data.Text.Lazy as LazyText
+
+main = run tests
+
+tests = encodeHexTests <> decodeHexTests <> lazilyEncodeHexTests
+
+run [] = putStrLn "Okay"
+run xs = die $ "Test failures: " <> show (xs :: [Natural])
+
+infix 0 #
+x # True = []
+x # False = [x]
+
+encodeHexTests = fold
+  [ 1 # (encodeHex . ByteString.singleton) 192
+      == fromString "c0"
+  , 2 # (encodeHex . ByteString.singleton) 168
+      == fromString "a8"
+  , 3 # (encodeHex . ByteString.pack) [192, 168, 1, 2]
+      == fromString "c0a80102"
+  ]
+
+decodeHexTests = fold
+  [ 4 # (fmap ByteString.unpack . decodeHex . Text.pack) "c0a80102"
+      == Just [192,168,1,2]
+  , 5 # (fmap ByteString.unpack . decodeHex . Text.pack) "c0a8010"
+      == Nothing
+  , 6 # (fmap ByteString.unpack . decodeHex . Text.pack) "x0a80102"
+      == Nothing
+  , 7 # (fmap ByteString.unpack . decodeHex . Text.pack) "C0A80102"
+      == Just [192,168,1,2]
+  ]
+
+lazilyEncodeHexTests = fold
+  [ 8 # (LazyText.take 8 . lazilyEncodeHex . LazyByteString.pack . cycle) [1, 2, 3]
+      == fromString "01020301"
+  ]
