packages feed

miss-0: tests/Tests/Git.hs

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Tests.Git (tests) where

import           Control.Monad
import           Control.Monad.Trans
import qualified Data.ByteString.Lazy as BL
import           Data.Git.Formats
import           Data.Git.Hash
import           Data.Git.Monad
import           Data.Git.Object
import           Data.Git.Ref
import           Data.Git.Types
import qualified Data.Map as Map
import           Data.Maybe (listToMaybe)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import           System.Process
import           System.Exit
import           Test.QuickCheck.Gen (unGen)
import           Test.QuickCheck.Random (mkQCGen)
import           TestUtil
import           Text.Printf

tests :: TestTree
tests = testGroup "Git"
  [ gitTests
  , packingTests
  ]

gitTests :: TestTree
gitTests = testGroup "GitT"
  [ testRepoProp "read-write Blob" $ \b -> do
      s <- writeBlob b
      flushObjects
      (Just b == ) <$> findBlob s
  , testRepoProp "read-write Tree" $ \t -> do
      s <- writeTree t
      (Just t == ) <$> findTree s
  , testRepoProp "read-write Commit" $ \c -> do
      s <- writeCommit c
      (Just c == ) <$> findCommit s
  , testRepoProp "read-write Tagt" $ \t -> do
      s <- writeTag t
      (Just t == ) <$> findTag s
  , testRepoProp "resolveSha" $ \b -> do
      bs <- writeBlob b
      let Just fn = pathComponent "file"
      ts <- writeTree . Tree . Map.fromList $ [(Entry fn BlobMode, bs)]
      (Just bs == ) <$> resolveSha ts [fn]
  , testRepoProp "resolveBlob" $ \b -> do
      bs <- writeBlob b
      let Just fn = pathComponent "file"
      ts <- writeTree . Tree . Map.fromList $ [(Entry fn BlobMode, bs)]
      (Just b == ) <$> resolveBlob ts [fn]
  , testWithRepo "resolveSha" $ do
      bs <- writeBlob (Blob "saf234fdf")
      let fn = "file"
      sts <- writeTree (Tree (Map.fromList [(Entry fn BlobMode, bs)]))
      let dn = "dir"
      ts <- writeTree (Tree (Map.fromList [(Entry dn TreeMode, sts)]))
      cs <- writeCommit $ testCommit { commitTree = ts }
      gs <- writeTag (Tag cs CommitType "Our Tag" (testContact, testDate) "No Message")
      resolveSha ts [] >>= liftIO . (@=?) (Just ts)
      resolveSha cs [] >>= liftIO . (@=?) (Just ts)
      resolveSha zeroSha [] >>= liftIO . (@=?) Nothing
      resolveSha cs [dn] >>= liftIO . (@=?) (Just sts)
      resolveSha cs [dn, fn] >>= liftIO . (@=?) (Just bs)
      resolveSha gs [] >>= liftIO . (@=?) (Just ts)
      resolveSha gs [dn] >>= liftIO . (@=?) (Just sts)
      resolveSha gs [dn, fn] >>= liftIO . (@=?) (Just bs)
  , testWithRepo "grepCommit" $ do
      (cs'::[Commit]) <- liftIO $ generate $ listOf1 arbitrary
      let cs = foldl (\pl c -> (c {commitParents=maybe [] (pure.sha1) $ listToMaybe pl}):pl) [] cs'
      tc <- head <$> mapM writeCommit cs
      forM_ cs $ \c ->
        grepCommit ((==) (commitTree c) . commitTree) tc >>= liftIO . (@=?) (Just $ sha1 c)
      grepCommit (const False) tc >>= liftIO . (@=?) Nothing
      grepCommit (const True) zeroSha >>=
                 liftIO . (@=?) Nothing
  , testWithRepo "Test packed ref reading" $ do
      c1 <- writeCommit $ testCommit
      c2 <- writeCommit $ testCommit { commitParents = [c1] }
      writeBranch "master" c1
      liftIO $ callProcess "git" ["pack-refs", "--all"]
      readBranch "master" >>= liftIO . (@=?) (Just c1)
      writeBranch "master" c2
      lookupRef (Branch "master") >>= liftIO . (@=?) (Just c2)
  ]

packingTests :: TestTree
packingTests = testGroup "PackingT"
  [ testRepoProp "packed read-write Blob" $ \b -> do
      s <- packing $ do
            s' <- writeBlob b
            flushObjects
            return s'
      (Just b == ) <$> findBlob s
  , testRepoProp "packed read-write Tree" $ \t -> do
      s <- packing $ writeTree t
      (Just t == ) <$> findTree s
  , testRepoProp "packed read-write Commit" $ \c -> do
      s <- packing $ writeCommit c
      (Just c == ) <$> findCommit s
  , testRepoProp "read-write Tagt" $ \t -> do
      s <- packing $ writeTag t
      (Just t == ) <$> findTag s
  , testRepoProp "packed resolveSha" $ \b -> do
      let Just fn = pathComponent "file"
      (bs, ts) <- packing $ do
        bs' <- writeBlob b
        ts' <- writeTree . Tree . Map.fromList $ [(Entry fn BlobMode, bs')]
        return (bs', ts')
      (Just bs == ) <$> resolveSha ts [fn]
  , testRepoProp "packed finds after sync" $ \b -> do
      let Just fn = pathComponent "file"
      packing $ do
        bs' <- writeBlob b
        ts' <- writeTree . Tree . Map.fromList $ [(Entry fn BlobMode, bs')]
        flushObjects
        (Just bs' == ) <$> resolveSha ts' [fn]
  , testInDir "Repacked" $ do
      os <- generate $ listOf1 arbitrary
      initRepo Nothing
      void . runGit ".git" $ mapM writeObject os
      rawSystem "git" ["repack", "-a", "-k", "-d", "-q"] >>= liftIO . (@=?) ExitSuccess
      runGit ".git" $
        forM_ os $ \o ->
          lookupSha (sha1 o) >>= liftIO . (@=?) (Just o)
  , testInDir "Delta" $ do
      let gen = mkQCGen 27
      let foo = unGen (BL.pack <$> vectorOf 2000 arbitrary) gen 569
      let bar = unGen (BL.pack <$> vectorOf  150 arbitrary) gen 457
      let baz = unGen (BL.pack <$> vectorOf  100 arbitrary) gen 727
      let f1 = Blob $ mconcat [BL.take 2000 foo, " base "]
      let f2 = Blob $ mconcat [BL.take 1800 foo, " delta1 ", bar]
      let f3 = Blob $ mconcat [BL.take 1800 foo, " delta delta2 ", baz]
      initRepo Nothing
      (s1, s2, s3) <- runGit ".git" $ (,,) <$> writeBlob f1 <*> writeBlob f2 <*> writeBlob f3
      let [h1, h2, h3] = map (T.unpack.TE.decodeUtf8.getSha1Hex.toHex) [s1, s2, s3]
      void $ readProcess "git"  ["pack-objects", ".git/objects/pack/pack"]
               (printf "%s\n%s\n%s\n" h1 h2 h3)
      -- Loose objects are prefered so they have to go.
      system "rm .git/objects/??/* && rmdir .git/objects/??" >>= liftIO . (@=?) ExitSuccess
      runGit ".git" $
        forM_ [f1, f2, f3] $ \o ->
          lookupSha (sha1 o) >>= liftIO . (@=?) (Just $ BlobObj o)
  ]