megaparsec-5.3.1: tests/Text/Megaparsec/PosSpec.hs
{-# LANGUAGE CPP #-}
{-# OPTIONS -fno-warn-orphans #-}
module Text.Megaparsec.PosSpec (spec) where
import Data.Function (on)
import Data.List (isInfixOf)
import Data.Semigroup ((<>))
import Test.Hspec
import Test.Hspec.Megaparsec.AdHoc
import Test.QuickCheck
import Text.Megaparsec.Pos
#if !MIN_VERSION_base(4,8,0)
import Data.Word (Word)
#endif
spec :: Spec
spec = do
describe "mkPos" $ do
context "when the argument is 0" $
it "throws InvalidPosException" $
mkPos (0 :: Word) `shouldThrow` (== InvalidPosException)
context "when the argument is not 0" $
it "returns Pos with the given value" $
property $ \n ->
(n > 0) ==> (mkPos n >>= shouldBe n . unPos)
describe "unsafePos" $
context "when the argument is a positive integer" $
it "returns Pos with the given value" $
property $ \n ->
(n > 0) ==> (unPos (unsafePos n) === n)
describe "Read and Show instances of Pos" $
it "printed representation of Pos is isomorphic to its value" $
property $ \x ->
read (show x) === (x :: Pos)
describe "Ord instance of Pos" $
it "works just like Ord instance of underlying Word" $
property $ \x y ->
compare x y === (compare `on` unPos) x y
describe "Semigroup instance of Pos" $
it "works like addition" $
property $ \x y ->
x <> y === unsafePos (unPos x + unPos y) .&&.
unPos (x <> y) === unPos x + unPos y
describe "initialPos" $
it "consturcts initial position correctly" $
property $ \path ->
let x = initialPos path
in sourceName x === path .&&.
sourceLine x === unsafePos 1 .&&.
sourceColumn x === unsafePos 1
describe "Read and Show instances of SourcePos" $
it "printed representation of SourcePos in isomorphic to its value" $
property $ \x ->
read (show x) === (x :: SourcePos)
describe "sourcePosPretty" $ do
it "displays file name" $
property $ \x ->
sourceName x `isInfixOf` sourcePosPretty x
it "displays line number" $
property $ \x ->
(show . unPos . sourceLine) x `isInfixOf` sourcePosPretty x
it "displays column number" $
property $ \x ->
(show . unPos . sourceColumn) x `isInfixOf` sourcePosPretty x
describe "defaultUpdatePos" $ do
it "returns actual position unchanged" $
property $ \w pos ch ->
fst (defaultUpdatePos w pos ch) === pos
it "does not change file name" $
property $ \w pos ch ->
(sourceName . snd) (defaultUpdatePos w pos ch) === sourceName pos
context "when given newline character" $
it "increments line number" $
property $ \w pos ->
(sourceLine . snd) (defaultUpdatePos w pos '\n')
=== (sourceLine pos <> pos1)
context "when given tab character" $
it "shits column number to next tab position" $
property $ \w pos ->
let c = sourceColumn pos
c' = (sourceColumn . snd) (defaultUpdatePos w pos '\t')
in c' > c .&&. (((unPos c' - 1) `rem` unPos w) == 0)
context "when given character other than newline or tab" $
it "increments column number by one" $
property $ \w pos ch ->
(ch /= '\n' && ch /= '\t') ==>
(sourceColumn . snd) (defaultUpdatePos w pos ch)
=== (sourceColumn pos <> pos1)