packages feed

loc-0.1.4.1: test/Main.hs

module Main (main) where

import Data.Loc
import Data.Loc.Internal.Prelude

import qualified Data.Loc.Pos as Pos
import qualified Data.Loc.Loc as Loc
import qualified Data.Loc.Area as Area
import qualified Data.Loc.Span as Span
import qualified Data.Loc.List.OneToTwo as OneToTwo
import qualified Data.Loc.List.ZeroToTwo as ZeroToTwo

import Hedgehog
import Test.Hspec
import Test.Hspec.Hedgehog

import qualified Data.List as List
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import qualified Gen

import Prelude (fromInteger, ($!), Num (..))

import qualified Data.List.NonEmpty as NonEmpty

main :: IO ()
main = hspec do
    posSpec
    locSpec
    spanSpec
    areaSpec

posSpec :: SpecWith ()
posSpec = describe "Pos" do
    specify "fromInteger" $ (fromInteger 3 :: Pos) == 3
    specify "fromInteger underflow" $ (return $! (fromInteger 0 :: Pos)) `shouldThrow` (== Underflow)
    specify "2 + 3" $ (2 + 3 :: Pos) == 5
    specify "3 - 2" $ (3 - 2 :: Pos) == 1
    specify "(-) underflow" $ (return $! (3 - 3 :: Pos)) `shouldThrow` (== Underflow)
    specify "2 * 3" $ (2 * 3 :: Pos) == 6
    specify "negate underflow" $ (return $! (negate 3 :: Pos)) `shouldThrow` (== Underflow)
    specify "toEnum" $ (toEnum 3 :: Pos) == 3
    specify "toEnum underflow" $ (return $! (toEnum 0 :: Pos)) `shouldThrow` (== Underflow)
    specify "fromEnum" $ fromEnum (3 :: Pos) == 3
    specify "show 1" $ Pos.posShowsPrec minPrec 1 "" == "1"
    specify "show 42" $ Pos.posShowsPrec minPrec 42 "" == "42"
    specify "read 1" $ readPrec_to_S Pos.posReadPrec minPrec "1" == [(1,"")]
    specify "read 42" $ readPrec_to_S Pos.posReadPrec minPrec "42" == [(42,"")]
    specify "read 0" $ readPrec_to_S Pos.posReadPrec minPrec "0" == []
    specify "read -1" $ readPrec_to_S Pos.posReadPrec minPrec "-1" == []

locSpec :: SpecWith ()
locSpec = describe "Loc" do

    specify "read and show" $ hedgehog do
        x <- forAll Gen.loc'
        read (show x) === x

    specify "read and show examples" $ hedgehog do
        show Loc.origin === "1:1"
        Loc.locShowsPrec minPrec (loc 3 14) "" === "3:14"
        readPrec_to_S Loc.locReadPrec minPrec "3:14" === [(read "3:14","")]

spanSpec :: SpecWith ()
spanSpec = describe "Span" do

    specify "joinAsc" $ hedgehog do
        spans <- forAll (Gen.list (Range.linear 1 10) Gen.span')
        areaSpansAsc (foldMap spanArea spans) === Span.joinAsc (List.sort spans)

    specify "read and show" $ hedgehog do
        x <- forAll Gen.span'
        read (show x) === x

    describe "read and show examples" do
        specify "show 3:14-6:5" $ Span.spanShowsPrec minPrec (Span.fromTo (read "3:14") (read "6:5")) "" == "3:14-6:5"
        specify "read 3:14-6:5" $ show (readPrec_to_S Span.spanReadPrec minPrec "3:14-6:5") == "[(3:14-6:5,\"\")]"
        specify "read 6:5-3:14" $ show (readPrec_to_S Span.spanReadPrec minPrec "6:5-3:14") == "[(3:14-6:5,\"\")]"
        specify "read 6:5-6:5" $ readPrec_to_S Span.spanReadPrec minPrec "6:5-6:5" == []

    describe "lines" do
        specify "one" $ NonEmpty.toList (Span.lines (read "2:6-2:10")) == [2]
        specify "many" $ NonEmpty.toList (Span.lines (read "2:6-8:4")) == [2,3,4,5,6,7,8]

    describe "overlapping" do
        specify "if only touching, no" $ not $ Span.overlapping (read "1:5-1:8") (read "1:8-1:12")
        specify "on a single line" $ Span.overlapping (read "1:5-1:9") (read "1:8-1:12")
        specify "one contained within another" $ Span.overlapping (read "1:5-1:15") (read "1:6-1:10")
        specify "same span" $ hedgehog do
            x <- forAll Gen.span'
            assert (Span.overlapping x x)

    describe "linesOverlapping" do
        specify "same span" $ hedgehog do
            x <- forAll Gen.span'
            assert (Span.linesOverlapping x x)
        specify "multi line" $ Span.linesOverlapping (read "1:1-1:2") (read "1:1-2:1")
        specify "no" $ not $ Span.linesOverlapping (read "1:1-1:2") (read "2:1-2:2")

    describe "touching" do
        specify "same span" $ hedgehog do
            x <- forAll Gen.span'
            assert (Span.touching x x)
        specify "barely" $ Span.touching (read "1:1-1:2") (read "1:2-1:3")
        specify "overlapping" $ Span.touching (read "1:1-1:2") (read "1:1-1:3")
        specify "no" $ not $ Span.touching (read "1:1-1:2") (read "1:3-1:4")

    describe "join" do
        specify "touching" $ Span.join (read "1:1-1:2") (read "1:2-1:3") == read "1:1-1:3"
        specify "overlapping" $ Span.join (read "1:1-1:2") (read "1:1-1:3") == read "1:1-1:3"

    describe "addition" do
        specify "example 1" $ read "1:1-1:2" Span.+ read "1:2-1:3" == OneToTwo.One (read "1:1-1:3")
        specify "example 2" $ read "1:1-1:2" Span.+ read "1:1-3:1" == OneToTwo.One (read "1:1-3:1")
        specify "example 3" $ read "1:1-1:2" Span.+ read "1:1-11:1" == OneToTwo.One (read "1:1-11:1")
        specify "example 4" $ read "1:1-1:2" Span.+ read "2:1-2:5" == OneToTwo.Two (read "1:1-1:2") (read "2:1-2:5")
        specify "example 5" $ read "2:1-2:5" Span.+ read "1:1-1:2" == OneToTwo.Two (read "2:1-2:5") (read "1:1-1:2")

    describe "subtraction" do
        specify "x - x" $ hedgehog do
            x <- forAll Gen.span'
            x Span.- x === ZeroToTwo.Zero
        specify "example 1" $ read "2:5-4:1" Span.- read "2:9-3:5" == ZeroToTwo.Two (read "2:5-2:9") (read "3:5-4:1")
        specify "example 2" $ read "2:5-4:1" Span.- read "2:5-3:5" == ZeroToTwo.One (read "3:5-4:1")
        specify "example 3" $ read "2:5-4:1" Span.- read "2:2-3:5" == ZeroToTwo.One (read "3:5-4:1")
        specify "example 4" $ read "2:5-4:1" Span.- read "2:2-4:4" == ZeroToTwo.Zero
        specify "example 5" $ read "1:1-8:1" Span.- read "1:2-8:1" == ZeroToTwo.One (read "1:1-1:2")

areaSpec :: SpecWith ()
areaSpec = describe "Area" do

    specify "add mempty = id for a single span" $ hedgehog do
        a <- forAll Gen.span'
        spanArea a Area.+ mempty === spanArea a

    specify "subtract mempty = id for a single span" $ hedgehog do
        a <- forAll Gen.span'
        spanArea a Area.- mempty === spanArea a

    specify "addition is commutative" $ hedgehog do
        a <- forAll Gen.area'
        b <- forAll Gen.area'
        a Area.+ b === b Area.+ a

    specify "add mempty = id" $ hedgehog do
        a <- forAll Gen.area'
        a Area.+ mempty === a

    specify "subtract mempty = id" $ hedgehog do
        a <- forAll Gen.area'
        a Area.- mempty === a

    specify "addition and subtraction" $ hedgehog do
        a <- forAll Gen.area'
        b <- forAll Gen.area'
        c <- forAll Gen.area'
        a Area.- b Area.- c === a Area.- (b Area.+ c)

    specify "addSpan" $ hedgehog do
        a <- forAll Gen.area'
        s <- forAll Gen.span'
        Area.addSpan s a === areaUnion (spanArea s) a

    specify "fromTo mempty 1" $ hedgehog do
        x <- forAll Gen.loc'
        y <- forAll Gen.loc'
        (Area.fromTo x y == mempty) === (x == y)

    specify "fromTo mempty 2" $ hedgehog do
        x <- forAll Gen.loc'
        Area.fromTo x x === mempty

    specify "read and show" $ hedgehog do
        x <- forAll Gen.area'
        read (show x) === x

    specify "read and show example 1" $ hedgehog do
        let x = show (readPrec_to_S Area.areaReadPrec minPrec "[]")
        x === "[([],\"\")]"

    specify "read and show example 2" $ hedgehog do
        x <- forAll (Gen.element ["[3:2-5:5,8:3-11:4]", "[3:2-5:5,11:4-8:3]"])
        let y = show (readPrec_to_S Area.areaReadPrec minPrec x)
        y === "[([3:2-5:5,8:3-11:4],\"\")]"

    specify "read and show example 3" $ hedgehog do
        let x = show (readPrec_to_S Area.areaReadPrec minPrec "[3:2-5:5,8:3-8:3]")
        x === "[]"

    specify "constructed from a single span" $ hedgehog do
        let x = read "4:5-6:3"
        spanArea x === read "[4:5-6:3]"

    specify "converted to a span, maybe" $ hedgehog do
        Area.areaSpan mempty === Nothing
        Area.areaSpan (read "[3:4-7:2]") === Just (read "3:4-7:2")
        Area.areaSpan (read "[3:4-7:2,15:6-17:9]") === Just (read "3:4-17:9")

    specify "converted to a list of spans" $ hedgehog do
        Area.spansAsc mempty === []
        Area.spansAsc (read "[3:4-7:2,15:6-17:9]") === [read "3:4-7:2", read "15:6-17:9"]

    specify "spanCount" $ hedgehog do
        Area.spanCount mempty === 0
        Area.spanCount (read "[3:4-7:2]") === 1
        Area.spanCount (read "[3:4-7:2,15:6-17:9]") === 2

    specify "firstSpan" $ hedgehog do
        Area.firstSpan mempty === Nothing
        Area.firstSpan (read "[3:4-7:2]") === Just (read "3:4-7:2")
        Area.firstSpan (read "[3:4-7:2,15:6-17:9]") === Just (read "3:4-7:2")

    specify "lastSpan" $ hedgehog do
        Area.lastSpan mempty === Nothing
        Area.lastSpan (read "[3:4-7:2]") === Just (read "3:4-7:2")
        Area.lastSpan (read "[3:4-7:2,15:6-17:9]") === Just (read "15:6-17:9")

    specify "start" $ hedgehog do
        Area.start mempty === Nothing
        Area.start (read "[3:4-7:2]") === Just (read "3:4")
        Area.start (read "[3:4-7:2,15:6-17:9]") === Just (read "3:4")

    specify "end" $ hedgehog do
        Area.end mempty === Nothing
        Area.end (read "[3:4-7:2]") === Just (read "7:2")
        Area.end (read "[3:4-7:2,15:6-17:9]") === Just (read "17:9")

    specify "addition examples" $ hedgehog do
        read "[1:1-1:2]" Area.+ mempty === read "[1:1-1:2]"
        read "[1:1-1:2]" Area.+ read "[1:2-1:3]" === read "[1:1-1:3]"
        read "[1:1-1:2]" Area.+ read "[1:1-3:1]" === read "[1:1-3:1]"
        read "[1:1-1:2]" Area.+ read "[1:1-11:1]" === read "[1:1-11:1]"
        read "[1:1-3:1,6:1-6:2]" Area.+ read "[1:1-6:1]" === read "[1:1-6:2]"
        read "[1:1-3:1]" Area.+ read "[5:1-6:2]" === read "[1:1-3:1,5:1-6:2]"

    specify "addSpan examples" $ hedgehog do
        Area.addSpan (read "1:1-6:1") (read "[1:1-3:1,6:1-6:2]") === read "[1:1-6:2]"