stan-0.0.0.0: test/Test/Stan/Analysis/AntiPattern.hs
module Test.Stan.Analysis.AntiPattern
( analysisAntiPatternSpec
) where
import Test.Hspec (Spec, describe, it, xit)
import Stan.Analysis (Analysis)
import Test.Stan.Analysis.Common (noObservationAssert, observationAssert, observationAssertMulti)
import qualified Stan.Inspection.AntiPattern as AntiPattern
analysisAntiPatternSpec :: Analysis -> Spec
analysisAntiPatternSpec analysis = describe "Anti-patterns" $ do
let checkObservation = observationAssert ["AntiPattern"] analysis
let noObservation = noObservationAssert ["AntiPattern"] analysis
it "STAN-0201: finds usage of '[0 .. length xs]'" $
checkObservation AntiPattern.stan0201 16 19 35
it "STAN-0201: doesn't trigger on '[0 .. length xs - 1]'" $
noObservation AntiPattern.stan0201 19
it "STAN-0202: finds usage of 'foldl'" $
checkObservation AntiPattern.stan0202 22 13 18
it "STAN-0203: finds usage of 'Data.ByteString.Char8.pack'" $
checkObservation AntiPattern.stan0203 25 13 21
it "STAN-0204: finds usage of 'Data.HashMap.size'" $
checkObservation AntiPattern.stan0204 28 19 26
it "STAN-0204: finds usage of 'length' for 'HashMap'" $
checkObservation AntiPattern.stan0204 31 21 27
it "STAN-0205: finds usage of 'Data.HashSet.size'" $
checkObservation AntiPattern.stan0205 34 19 26
it "STAN-0205: finds usage of 'length' for 'HashSet'" $
checkObservation AntiPattern.stan0205 37 21 27
strictFieldsSpec analysis
it "STAN-0207: 'length' for (,)" $
checkObservation AntiPattern.stan0207 40 19 25
it "STAN-0207: 'null' for Maybe" $
checkObservation AntiPattern.stan0207 43 17 21
it "STAN-0207: 'foldr' for Either" $
checkObservation AntiPattern.stan0207 46 19 24
it "STAN-0208: finds usage of 'length' for 'Text'" $
checkObservation AntiPattern.stan0208 49 18 29
it "STAN-0209: finds usage of 'nub' for lists" $
checkObservation AntiPattern.stan0209 52 11 19
it "STAN-0210: finds usage of 'for_' for ranges" $
checkObservation AntiPattern.stan0210 55 12 35
it "STAN-0210: finds usage of 'forM_' for ranges" $
checkObservation AntiPattern.stan0210 58 15 29
it "STAN-0211: finds usage of 'http://' '</>'" $
checkObservation AntiPattern.stan0211 61 12 41
it "STAN-0211: finds usage of 'fooUrl' '</>'" $
checkObservation AntiPattern.stan0211 64 12 28
it "STAN-0211: finds usage of '</>' 'fooUrl'" $
checkObservation AntiPattern.stan0211 70 12 28
it "STAN-0211: doesn't trigger on 'fooUral' '</>'" $
noObservation AntiPattern.stan0211 76
unsafeFunctionsSpec analysis
patternMatchSpec analysis
compareSpec analysis
it "STAN-0215: finds usage of '/' in '</>' path left" $
checkObservation AntiPattern.stan0215 82 19 38
it "STAN-0215: finds usage of '/' in '</>' path right" $
checkObservation AntiPattern.stan0215 88 20 39
it "STAN-0215: finds usage of '\\' in '</>' path left" $
checkObservation AntiPattern.stan0215 85 22 42
it "STAN-0215: finds usage of '\\' in '</>' path right" $
checkObservation AntiPattern.stan0215 91 23 43
it "STAN-0215: don't triggered when no slashes" $
noObservation AntiPattern.stan0215 94
strictFieldsSpec :: Analysis -> Spec
strictFieldsSpec analysis = describe "STAN-0206: Strict data type fields" $ do
describe "Without extensions" $ do
let checkObservation = observationAssert ["AntiPattern", "Stan0206"] analysis
let noObservation = noObservationAssert ["AntiPattern", "Stan0206"] analysis
it "Doesn't trigger on strict field" $
noObservation AntiPattern.stan0206 7
it "Finds simple lazy field" $
checkObservation AntiPattern.stan0206 8 7 25
it "Finds polymorphic lazy field" $
checkObservation AntiPattern.stan0206 9 7 23
it "Doesn't trigger on plain newtype" $
noObservation AntiPattern.stan0206 12
it "Doesn't trigger on a record newtype" $
noObservation AntiPattern.stan0206 14
it "Doesn't trigger on strict sum type field among many fields" $
noObservation AntiPattern.stan0206 19
it "Finds lazy field in a sum type constructor with multiple fields" $
checkObservation AntiPattern.stan0206 20 9 12
it "Doesn't trigger on a single strict sum type field" $
noObservation AntiPattern.stan0206 21
it "Finds single lazy field in a sum type with multiple constructors" $
checkObservation AntiPattern.stan0206 22 11 15
describe "With the 'StrictData' extension" $ do
let noObservation = noObservationAssert ["AntiPattern", "Stan0206Extensions"] analysis
it "Doesn't trigger on a simple record field" $
noObservation AntiPattern.stan0206 9
it "Doesn't trigger on explicitly lazy field" $
noObservation AntiPattern.stan0206 10
it "Doesn't trigger on plain data type" $
noObservation AntiPattern.stan0206 13
unsafeFunctionsSpec :: Analysis -> Spec
unsafeFunctionsSpec analysis = describe "STAN-0212: Unsafe functions" $ do
let checkObservation = observationAssert ["AntiPattern", "Stan0212"] analysis
it "Find: undefined" $
checkObservation AntiPattern.stan0212 10 17 26
it "Find: unsafeCoerce" $
checkObservation AntiPattern.stan0212 13 20 32
it "Find: unsafePerformIO" $
checkObservation AntiPattern.stan0212 16 23 38
it "Find: unsafeInterleaveIO" $
checkObservation AntiPattern.stan0212 19 26 44
it "Find: unsafeDupablePerformIO" $
checkObservation AntiPattern.stan0212 22 30 52
it "Find: unsafeFixIO" $
checkObservation AntiPattern.stan0212 25 19 30
patternMatchSpec :: Analysis -> Spec
patternMatchSpec analysis = describe "STAN-0212: Pattern Matching on _" $ do
let checkObservation = observationAssert ["AntiPattern", "Stan0213"] analysis
let noObservation = noObservationAssert ["AntiPattern", "Stan0213"] analysis
it "for lambda case" $
checkObservation AntiPattern.stan0213 12 5 17
it "not triggered for lambda case on integers" $
noObservation AntiPattern.stan0213 17
it "for case" $
checkObservation AntiPattern.stan0213 23 5 18
it "not triggered for case on strings" $
noObservation AntiPattern.stan0213 29
it "not triggered for case on all constructors" $ do
noObservation AntiPattern.stan0213 33
noObservation AntiPattern.stan0213 34
noObservation AntiPattern.stan0213 35
it "not triggered for lambda case on all constructors" $ do
noObservation AntiPattern.stan0213 39
noObservation AntiPattern.stan0213 40
noObservation AntiPattern.stan0213 41
it "for case on maybe" $
checkObservation AntiPattern.stan0213 46 5 20
it "for lambda case on maybe" $
checkObservation AntiPattern.stan0213 51 5 20
it "not triggered for lambda case on maybe with full pm" $
noObservation AntiPattern.stan0213 56
it "not triggered for lambda case on one branch _" $
noObservation AntiPattern.stan0213 60
it "not triggered for lambda case on Chars" $
noObservation AntiPattern.stan0213 65
compareSpec :: Analysis -> Spec
compareSpec analysis = describe "STAN-0214: Replace multiple comparison operators" $ do
let checkObservation = observationAssertMulti
["AntiPattern", "Stan0214"]
analysis
AntiPattern.stan0214
let noObservation = noObservationAssert
["AntiPattern", "Stan0214"]
analysis
AntiPattern.stan0214
it "Finds: < and >" $
checkObservation 7 1 10 23
it "Finds: == and <" $
checkObservation 13 1 16 23
it "No warning on: == on different expressions" $ do
noObservation 19
noObservation 20
noObservation 21
noObservation 22
it "No warning on: Single >=" $ do
noObservation 25
noObservation 26
noObservation 27
it "No warning on: >= with different constants" $ do
noObservation 30
noObservation 31
noObservation 32
noObservation 33
noObservation 34
noObservation 35
xit "Handles functions with pattern-matching" $
checkObservation 41 1 44 20