content: module Ormolu.Utils.GlobSpec (spec) where
  
  import Ormolu.Utils.Glob (matchesGlob, mkGlob)
  import Test.Hspec (Spec, describe, it, shouldBe)
  import Test.Hspec.QuickCheck (prop)
  import Test.QuickCheck (Arbitrary (..), listOf, suchThat)
  
  newtype Wildcardless = Wildcardless String
    deriving (Show)
  
  instance Arbitrary Wildcardless where
    arbitrary = fmap Wildcardless $ listOf (arbitrary `suchThat` (/= '*'))
  
  newtype ModuleName = ModuleName String
    deriving (Show)
  
  instance Arbitrary ModuleName where
    arbitrary = fmap ModuleName $ listOf (arbitrary `suchThat` (/= '.')) `suchThat` (not . null)
  
  spec :: Spec
  spec =
    describe "glob" $ do
      it "should match modules exactly" $
        "Hello.world" `matchesGlob` mkGlob "Hello.world" `shouldBe` True
      it "should fail if case doesn't match" $
        "Some.thing" `matchesGlob` mkGlob "Some.Thing" `shouldBe` False
      it "should allow * to match anything on the same level" $
        "Level1.Level2.Level3" `matchesGlob` mkGlob "Level1.Le*2.Level3" `shouldBe` True
      it "should fail if input doesn't match glob even with wildcards" $
        "Control.Monad.Writer.Lazy" `matchesGlob` mkGlob "Data.Functor.*.Lazy" `shouldBe` False
      it "should disallow * to match anything on different level" $
        "Level1.Level2.Level3.Level4" `matchesGlob` mkGlob "Level1.*.Level4" `shouldBe` False
      it "should allow multiple *" $
        "Some.Fake.Path.With.Internals" `matchesGlob` mkGlob "Some.*.Path.*.Internals" `shouldBe` True
      it "should allow * at the beginning" $
        "MyApp42.Control.Monad" `matchesGlob` mkGlob "*42.Control.Monad" `shouldBe` True
      it "should allow * at the end" $
        "System.IO.Stuff" `matchesGlob` mkGlob "System.IO.*" `shouldBe` True
      it "should allow ** to match anything on the same level" $
        "Level1.Level2.Level3" `matchesGlob` mkGlob "Level1.L**2.Level3" `shouldBe` True
      it "should allow ** to match anything on multiple levels" $
        "Level1.Level2.Level3.Level4.Level5" `matchesGlob` mkGlob "Level1.L**4.Level5" `shouldBe` True
  
      describe "Properties" $ do
        prop "should obey: s `matches` glob s with s being any string without '*'" $
          \(Wildcardless s) -> s `matchesGlob` mkGlob s
        prop "should obey: (a <> b <> c) `matches` glob (a <> * <> c) with b being a module name" $
          \a (ModuleName b) c -> (a <> b <> c) `matchesGlob` mkGlob (a <> "*" <> c)
        prop "should obey:  (a <> b <> c) `matches` glob (a <> ** <> c)" $
          \a b c -> (a <> b <> c) `matchesGlob` mkGlob (a <> "**" <> c)
  