ormolu-0.5.3.0: tests/Ormolu/HackageInfoSpec.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}
module Ormolu.HackageInfoSpec (spec) where
import qualified Data.Map.Strict as Map
import Data.Maybe (mapMaybe)
import qualified Data.Set as Set
import Distribution.Types.PackageName (PackageName)
import Ormolu.Fixity
import Test.Hspec
-- | Build a fixity map using the Hackage/Hoogle database, and the boot
-- package list, and then check the fixity of the specified subset of
-- operators.
checkFixityMap ::
-- | List of dependencies
[PackageName] ->
-- | Threshold to choose the conflict resolution strategy
Float ->
-- | Associative list representing a subset of the resulting fixity map
-- that should be checked.
[(OpName, FixityInfo)] ->
Expectation
checkFixityMap
dependencies
threshold
expectedResult =
actualResult `shouldBe` expectedResult
where
actualResult =
mapMaybe
(\(k, _) -> (k,) <$> lookupFixity k resultMap)
expectedResult
resultMap =
buildFixityMap'
packageToOps
packageToPopularity
bootPackages
threshold
(Set.fromList dependencies)
-- | Build a fixity map from a custom package database, and then check the
-- fixity of the specified subset of operators.
checkFixityMap' ::
-- | Associative list for packageToOps:
-- package name -map-> (operator -map-> fixity)
[(PackageName, [(OpName, FixityInfo)])] ->
-- | Associative list for packageToPopularity:
-- package name -map-> download count
[(PackageName, Int)] ->
-- | List of packages that should have a higher priority than
-- unspecified packages (boot packages)
[PackageName] ->
-- | List of dependencies
[PackageName] ->
-- | Threshold to choose the conflict resolution strategy
Float ->
-- | Associative list representing a subset of the resulting fixity map
-- that should be checked.
[(OpName, FixityInfo)] ->
Expectation
checkFixityMap'
lPackageToOps
lPackageToPopularity
highPrioPackages
dependencies
threshold
expectedResult =
actualResult `shouldBe` expectedResult
where
actualResult =
mapMaybe
(\(k, _) -> (k,) <$> lookupFixity k resultMap)
expectedResult
resultMap =
buildFixityMap'
lPackageToOps'
lPackageToPopularity'
(Set.fromList highPrioPackages)
threshold
(Set.fromList dependencies)
lPackageToOps' =
Map.map Map.fromList $
Map.fromList lPackageToOps
lPackageToPopularity' = Map.fromList lPackageToPopularity
spec :: Spec
spec = do
it
"correctly merges fixities when a conflict appears in unspecified \
\packages, with max(pop) < threshold"
$ do
let operators =
[ ("A", [("+", FixityInfo (Just InfixL) 4 4)]),
("B", [("+", FixityInfo (Just InfixR) 6 6)])
]
popularity =
[ ("A", 3),
("B", 5)
]
dependencies = []
higherPriorityPackages = []
threshold = 0.9
result =
[ ("+", FixityInfo Nothing 4 6)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"keeps only the most popular declaration when a conflict appears in \
\unspecified packages, with max(pop) >= threshold"
$ do
let operators =
[ ("A", [("+", FixityInfo (Just InfixL) 4 4)]),
("B", [("+", FixityInfo (Just InfixR) 6 6)])
]
popularity =
[ ("A", 5),
("B", 103)
]
dependencies = []
higherPriorityPackages = []
threshold = 0.9
result =
[ ("+", FixityInfo (Just InfixR) 6 6)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"merges the ex-aequo most popular declaration when a conflict appears \
\in unspecified packages, with max(pop) >= threshold"
$ do
let operators =
[ ("A", [("+", FixityInfo (Just InfixL) 4 4)]),
("B", [("+", FixityInfo (Just InfixR) 6 6)]),
("C", [("+", FixityInfo (Just InfixR) 8 8)])
]
popularity =
[ ("A", 5),
("B", 103),
("C", 103)
]
dependencies = []
higherPriorityPackages = []
threshold = 0.4
result =
[ ("+", FixityInfo (Just InfixR) 6 8)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"keeps only the most popular declaration when a conflict appears in \
\unspecified packages, threshold == 0"
$ do
let operators =
[ ("A", [("+", FixityInfo (Just InfixL) 4 4)]),
("B", [("+", FixityInfo (Just InfixR) 6 6)])
]
popularity =
[ ("A", 5),
("B", 103)
]
dependencies = []
higherPriorityPackages = []
threshold = 0.0
result =
[ ("+", FixityInfo (Just InfixR) 6 6)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"merges all declarations when a conflict appears in unspecified \
\packages, threshold > 1"
$ do
let operators =
[ ("A", [("+", FixityInfo (Just InfixN) 4 4)]),
("B", [("+", FixityInfo (Just InfixN) 6 6)]),
("C", [("+", FixityInfo (Just InfixN) 8 8)])
]
popularity =
[ ("A", 0),
("B", 0),
("C", 11103)
]
dependencies = []
higherPriorityPackages = []
threshold = 10.0
result =
[ ("+", FixityInfo (Just InfixN) 4 8)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"merges all declarations when a conflict appears in cabal \
\dependencies"
$ do
let operators =
[ ( "A",
[ ("+", FixityInfo (Just InfixR) 4 4),
("-", FixityInfo (Just InfixR) 2 2)
]
),
( "B",
[ ("+", FixityInfo (Just InfixN) 6 6),
("-", FixityInfo (Just InfixL) 4 4)
]
),
("C", [("+", FixityInfo (Just InfixN) 8 8)])
]
popularity =
[ ("A", 0),
("B", 0),
("C", 11103)
]
dependencies = ["B", "C"]
higherPriorityPackages = []
threshold = 0.4
result =
[ ("+", FixityInfo (Just InfixN) 6 8),
("-", FixityInfo (Just InfixL) 4 4)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"merges all declarations when a conflict appears in higher-priority \
\packages"
$ do
let operators =
[ ( "A",
[ ("+", FixityInfo (Just InfixR) 4 4),
("-", FixityInfo (Just InfixR) 2 2)
]
),
( "B",
[ ("+", FixityInfo (Just InfixN) 6 6),
("-", FixityInfo (Just InfixL) 4 4)
]
),
("C", [("+", FixityInfo (Just InfixN) 8 8)])
]
popularity =
[ ("A", 0),
("B", 0),
("C", 11103)
]
dependencies = []
higherPriorityPackages = ["B", "C"]
threshold = 0.4
result =
[ ("+", FixityInfo (Just InfixN) 6 8),
("-", FixityInfo (Just InfixL) 4 4)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"whitelists declarations from base even when it is not listed in \
\cabal dependencies"
$ do
let operators =
[ ( "base",
[ ("+", FixityInfo (Just InfixR) 4 4),
("-", FixityInfo (Just InfixR) 2 2)
]
),
( "B",
[ ("+", FixityInfo (Just InfixN) 6 6),
("-", FixityInfo (Just InfixL) 4 4)
]
),
( "C",
[ ("+", FixityInfo (Just InfixN) 8 8),
("|>", FixityInfo (Just InfixN) 1 1)
]
)
]
popularity =
[ ("base", 0),
("B", 2),
("C", 11103)
]
dependencies = ["B", "C"]
higherPriorityPackages = []
threshold = 0.4
result =
[ ("+", FixityInfo (Just InfixR) 4 4),
("-", FixityInfo (Just InfixR) 2 2),
("|>", FixityInfo (Just InfixN) 1 1)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"whitelists declarations from base when base is also listed in cabal \
\dependencies"
$ do
let operators =
[ ( "base",
[ ("+", FixityInfo (Just InfixR) 4 4),
("-", FixityInfo (Just InfixR) 2 2)
]
),
( "B",
[ ("+", FixityInfo (Just InfixN) 6 6),
("?=", FixityInfo (Just InfixL) 4 4)
]
),
( "C",
[ ("<|>", FixityInfo (Just InfixN) 8 8),
("?=", FixityInfo (Just InfixN) 1 1)
]
)
]
popularity =
[ ("base", 0),
("B", 2),
("C", 11103)
]
dependencies = ["base", "B"]
higherPriorityPackages = []
threshold = 0.6
result =
[ ("+", FixityInfo (Just InfixR) 4 4),
("-", FixityInfo (Just InfixR) 2 2),
("?=", FixityInfo (Just InfixL) 4 4)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"gives higher priority to declarations from cabal dependencies than \
\declarations from both higher-priority & unspecified packages"
$ do
let operators =
[ ( "base",
[ ("+", FixityInfo (Just InfixR) 4 4),
("-", FixityInfo (Just InfixR) 2 2)
]
),
( "B",
[ ("+", FixityInfo (Just InfixN) 6 6),
("?=", FixityInfo (Just InfixL) 4 4)
]
),
( "C",
[ ("<|>", FixityInfo (Just InfixN) 8 8),
("?=", FixityInfo (Just InfixN) 1 1)
]
),
("D", [("+", FixityInfo (Just InfixR) 2 2)])
]
popularity =
[ ("base", 0),
("B", 2),
("C", 11103)
]
dependencies = ["base", "B"]
higherPriorityPackages = ["D"]
threshold = 0.6
result =
[ ("?=", FixityInfo (Just InfixL) 4 4),
("<|>", FixityInfo (Just InfixN) 8 8)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it
"gives higher priority to declarations from higher-priority packages \
\than declarations from unspecified packages"
$ do
let operators =
[ ( "base",
[ ("+", FixityInfo (Just InfixR) 4 4),
("-", FixityInfo (Just InfixR) 2 2)
]
),
( "B",
[ ("+", FixityInfo (Just InfixN) 6 6),
("?=", FixityInfo (Just InfixL) 4 4)
]
),
( "C",
[ ("<|>", FixityInfo (Just InfixN) 8 8),
("?=", FixityInfo (Just InfixN) 1 1)
]
),
("D", [("+", FixityInfo (Just InfixR) 2 2)])
]
popularity =
[ ("base", 0),
("B", 2),
("C", 11103)
]
dependencies = []
higherPriorityPackages = ["B"]
threshold = 0.6
result =
[ ("+", FixityInfo (Just InfixR) 4 4),
("?=", FixityInfo (Just InfixL) 4 4),
("<|>", FixityInfo (Just InfixN) 8 8)
]
checkFixityMap'
operators
popularity
higherPriorityPackages
dependencies
threshold
result
it "gives the correct fixity info for ':' (from base)" $ do
let dependencies = []
threshold = 0.6
result =
[ (":", FixityInfo (Just InfixR) 5 5)
]
checkFixityMap dependencies threshold result
it
"gives the base's fixity info for '<|>', even when a dependency has a \
\conflicting declaration for it"
$ do
let dependencies = ["pandoc"]
threshold = 0.9
result =
[ ("<|>", FixityInfo (Just InfixL) 3 3)
]
checkFixityMap dependencies threshold result
it
"gives the containers's fixity info for ':>' (because 'containers' is \
\a higher-priority package), even though max(pop) < threshold for \
\this operator)"
$ do
let dependencies = []
threshold = 0.9
result =
[ (":>", FixityInfo (Just InfixL) 5 5)
]
checkFixityMap dependencies threshold result
it
"gives the servant's fixity info for ':>' once servant is added as a \
\dependency (although ':>' is also defined in 'containers', a \
\higher-priority package)"
$ do
let dependencies = ["servant"]
threshold = 0.9
result =
[ (":>", FixityInfo (Just InfixR) 4 4)
]
checkFixityMap dependencies threshold result