packages feed

language-docker-16.0.0: test/Language/Docker/PrettyPrintSpec.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}

module Language.Docker.PrettyPrintSpec where

import Data.Default
import qualified Data.Set as Set
import qualified Data.Text as Text
import Prettyprinter
import Prettyprinter.Render.Text
import Language.Docker.Syntax
import Language.Docker.PrettyPrint
import Test.HUnit hiding (Label)
import Test.Hspec


spec :: Spec
spec = do
  describe "pretty print ADD" $ do
    it "with just copy" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( def :: AddFlags )
       in assertPretty "ADD foo bar" add
    it "with just checksum" $ do
      let add = Add
                  ( AddArgs [SourcePath "http://www.example.com/foo"] (TargetPath "bar") )
                  ( AddFlags ( Checksum "sha256:24454f830cdd" ) NoChown NoChmod NoLink NoKeepGitDir NoUnpack [])
       in assertPretty "ADD --checksum=sha256:24454f830cdd http://www.example.com/foo bar" add
    it "with just chown" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum ( Chown "root:root" ) NoChmod NoLink NoKeepGitDir NoUnpack [] )
       in assertPretty "ADD --chown=root:root foo bar" add
    it "with just chmod" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum NoChown ( Chmod "751" ) NoLink NoKeepGitDir NoUnpack [] )
       in assertPretty "ADD --chmod=751 foo bar" add
    it "with just link (true)" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum NoChown NoChmod ( Link True ) NoKeepGitDir NoUnpack [] )
       in assertPretty "ADD --link foo bar" add

    it "with just link (false)" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum NoChown NoChmod ( Link False ) NoKeepGitDir NoUnpack [] )
       in assertPretty "ADD --link=false foo bar" add

    it "with just keep-git-dir" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum NoChown NoChmod NoLink ( KeepGitDir True ) NoUnpack [] )
       in assertPretty "ADD --keep-git-dir foo bar" add
    it "with chown, chmod and link" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum ( Chown "root:root" ) ( Chmod "751" ) ( Link True ) NoKeepGitDir NoUnpack [] )
       in assertPretty "ADD --chown=root:root --chmod=751 --link foo bar" add
    it "with all flags" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags
                      ( Checksum "sha256:24454f830cdd" )
                      ( Chown "root:root" )
                      ( Chmod "751" )
                      ( Link True )
                      ( KeepGitDir True )
                      ( Unpack True )
                      []
                  )
       in assertPretty "ADD --checksum=sha256:24454f830cdd --chown=root:root --chmod=751 --link --keep-git-dir --unpack foo bar" add
    it "with unpack true" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum NoChown NoChmod NoLink NoKeepGitDir (Unpack True) [] )
       in assertPretty "ADD --unpack foo bar" add
    it "with unpack false" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum NoChown NoChmod NoLink NoKeepGitDir (Unpack False) [] )
       in assertPretty "ADD --unpack=false foo bar" add
    it "with just exclude" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum NoChown NoChmod NoLink NoKeepGitDir NoUnpack [Exclude "*.tmp"] )
       in assertPretty "ADD --exclude=*.tmp foo bar" add
    it "with multiple exclude flags" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum NoChown NoChmod NoLink NoKeepGitDir NoUnpack [Exclude "*.tmp", Exclude "*.log"] )
       in assertPretty "ADD --exclude=*.tmp --exclude=*.log foo bar" add
    it "with exclude and other flags" $ do
      let add = Add
                  ( AddArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( AddFlags NoChecksum (Chown "root:root") NoChmod NoLink NoKeepGitDir NoUnpack [Exclude "*.tmp"] )
       in assertPretty "ADD --chown=root:root --exclude=*.tmp foo bar" add

  describe "pretty print COPY" $ do
    it "with just copy" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( def :: CopyFlags )
       in assertPretty "COPY foo bar" copy
    it "with just chown" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( CopyFlags ( Chown "root:root" ) NoChmod NoLink NoParents NoSource [] )
       in assertPretty "COPY --chown=root:root foo bar" copy
    it "with just chmod" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( CopyFlags NoChown ( Chmod "751" ) NoLink NoParents NoSource [] )
       in assertPretty "COPY --chmod=751 foo bar" copy
    it "with just link (true)" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( CopyFlags NoChown NoChmod ( Link True ) NoParents NoSource [] )
       in assertPretty "COPY --link foo bar" copy

    it "with just link (false)" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( CopyFlags NoChown NoChmod ( Link False ) NoParents NoSource [] )
       in assertPretty "COPY --link=false foo bar" copy

    it "with just parents" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( CopyFlags NoChown NoChmod NoLink ( Parents True ) NoSource [] )
       in assertPretty "COPY --parents foo bar" copy

    it "with source baseimage" $ do
      let copy =
            Copy
              ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
              ( CopyFlags NoChown NoChmod NoLink NoParents ( CopySource "baseimage" ) [])
       in assertPretty "COPY --from=baseimage foo bar" copy
    it "with both chown and chmod" $ do
      let copy =
            Copy
              ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
              ( CopyFlags
                  ( Chown "root:root" ) ( Chmod "751" ) NoLink NoParents NoSource []
              )
       in assertPretty "COPY --chown=root:root --chmod=751 foo bar" copy

    it "with all flags" $ do
      let copy =
            Copy
              ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
              ( CopyFlags
                  ( Chown "root:root")
                  ( Chmod "751")
                  ( Link True )
                  ( Parents True )
                  ( CopySource "baseimage" )
                  []
              )
       in assertPretty
            "COPY --chown=root:root --chmod=751 --link --parents --from=baseimage foo bar"
            copy

    it "with just exclude" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( CopyFlags NoChown NoChmod NoLink NoParents NoSource [Exclude "*.tmp"] )
       in assertPretty "COPY --exclude=*.tmp foo bar" copy
    it "with multiple exclude flags" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( CopyFlags NoChown NoChmod NoLink NoParents NoSource [Exclude "*.tmp", Exclude "*.log"] )
       in assertPretty "COPY --exclude=*.tmp --exclude=*.log foo bar" copy
    it "with exclude and other flags" $ do
      let copy = Copy
                  ( CopyArgs [SourcePath "foo"] (TargetPath "bar") )
                  ( CopyFlags (Chown "root:root") NoChmod NoLink NoParents NoSource [Exclude "*.tmp"] )
       in assertPretty "COPY --chown=root:root --exclude=*.tmp foo bar" copy

  describe "pretty print RUN" $ do
    it "just a simple RUN" $ do
      let run = Run ( RunArgs ( ArgumentsText "foobar" ) def )
       in assertPretty "RUN foobar" run

    it "RUN in JSON format" $ do
      let run = Run ( RunArgs ( ArgumentsList "foobar barfoo" ) def )
       in assertPretty "RUN [\"foobar\", \"barfoo\"]" run

    it "RUN with --mount=type=tmpfs" $ do
      let run =
            Run
              ( RunArgs
                  ( ArgumentsText "foobar" )
                  ( RunFlags
                      { mount = Set.singleton ( TmpfsMount ( TmpOpts "/tgt" (Just "4G") ) ),
                        security = Nothing,
                        network = Nothing
                      }
                  )
              )
       in assertPretty "RUN --mount=type=tmpfs,target=/tgt,size=4G foobar" run

  describe "pretty print # escape" $ do
    it "# escape = \\" $ do
      let esc = Pragma (Escape (EscapeChar '\\'))
       in assertPretty "# escape = \\" esc
    it "# escape = `" $ do
      let esc = Pragma (Escape (EscapeChar '`'))
       in assertPretty "# escape = `" esc

  describe "pretty print # syntax" $ do
    it "# syntax = docker/dockerfile:1.0" $ do
      let img = Pragma
                  ( Syntax
                    ( SyntaxImage
                        ( Image
                            { registryName = Nothing,
                              imageName = "docker/dockerfile:1.0"
                            }
                        )
                    )
                  )
       in assertPretty "# syntax = docker/dockerfile:1.0" img


assertPretty :: Text.Text -> Instruction Text.Text -> Assertion
assertPretty expected inst = assertEqual
    "prettyfied instruction not pretty enough"
    expected
    (prettyPrintStrict inst)

prettyPrintStrict :: Instruction Text.Text -> Text.Text
prettyPrintStrict =
  let ?esc = defaultEsc
   in renderStrict
      . layoutPretty (LayoutOptions Unbounded)
      . prettyPrintInstruction