Skip to content

Commit

Permalink
CLI-side tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
csasarak committed Jul 1, 2024
1 parent c126aef commit 55457e7
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 57 deletions.
143 changes: 86 additions & 57 deletions test/App/Fossa/Container/AnalyzeNativeSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import App.Fossa.Container.Scan (
parseDockerEngineSource,
)
import App.Fossa.Container.Sources.DockerArchive (analyzeFromDockerArchive)
import Container.Types (
ContainerScan (imageData),
ContainerScanImage (imageLayers),
srcUnits,
)
import Container.Types (ContainerScan (ContainerScan, imageData), ContainerScanImage (ContainerScanImage, imageLayers), layerId, observations, srcUnits)
import Control.Carrier.Debug (IgnoreDebugC, ignoreDebug)
import Control.Carrier.Diagnostics (DiagnosticsC, Has)
import Control.Carrier.Stack (StackC, runStack)
Expand Down Expand Up @@ -40,6 +36,7 @@ import Test.Effect (
handleDiag,
shouldBe',
shouldBeSupersetOf',
shouldMatchList',
shouldNotContain',
)
import Test.Hspec (Spec, SpecWith, describe, it, runIO)
Expand All @@ -57,61 +54,68 @@ import Types (
DiscoveredProjectType (SetuptoolsProjectType),
TargetFilter (TypeDirTarget, TypeTarget),
)
import qualified Data.Map as Map

spec :: Spec
spec = do
describe "parseDockerEngineSource" $ do
it' "should fail if docker engine is not accessible" $ do
expectDockerSdkNotAccessible
expectFatal' $ parseDockerEngineSource exampleImgWithTag

it' "should fail if text lacks tag signifier " $ do
expectDockerSdkToBeAccessible
expectFatal' $ parseDockerEngineSource exampleImgWithoutTag

it' "should fail if image's size cannot be retrieved" $ do
expectDockerSdkToBeAccessible
expectGetImageSizeToFail
expectFatal' $ parseDockerEngineSource exampleImgWithTag

it' "should parse image source if image size can be inferred via docker api" $ do
expectDockerSdkToBeAccessible
expectGetImageSizeToSucceed
src <- parseDockerEngineSource exampleImgWithTag
src `shouldBe'` DockerEngine exampleImgWithTag

describe "analyze" $ do
currDir <- runIO getCurrentDir
let imageArchive = currDir </> appDepsImage

it' "should not analyze application dependencies when only-system-dependencies are requested" $ do
containerScan <- analyzeFromDockerArchive True mempty (toFlag' False) imageArchive
buildImportsOf containerScan `shouldNotContain'` [numpy, scipy, black]

it' "should analyze application dependencies" $ do
containerScan <- analyzeFromDockerArchive False mempty (toFlag' False) imageArchive
buildImportsOf containerScan `shouldBeSupersetOf'` [numpy, scipy, black]
buildImportsOf containerScan `shouldNotContain'` [networkX]

it' "should apply tool exclusion filter" $ do
containerScan <- analyzeFromDockerArchive False (excludeTool SetuptoolsProjectType) (toFlag' False) imageArchive
buildImportsOf containerScan `shouldNotContain'` [numpy, scipy, black]

it' "should apply project exclusion filter" $ do
let appAPath = $(mkRelDir "app/services/b/")
containerScan <- analyzeFromDockerArchive False (excludeProject SetuptoolsProjectType appAPath) (toFlag' False) imageArchive
buildImportsOf containerScan `shouldNotContain'` [scipy]
buildImportsOf containerScan `shouldBeSupersetOf'` [numpy, black]

it' "should analyze all targets, if default filter is disabled" $ do
containerScan <- analyzeFromDockerArchive False mempty (toFlag' True) imageArchive
buildImportsOf containerScan `shouldBeSupersetOf'` [numpy, scipy, black, networkX]

it' "should apply path exclusion filter" $ do
let appAPath = $(mkRelDir "app/services/b/internal/")
containerScan <- analyzeFromDockerArchive False (excludePath appAPath) (toFlag' False) imageArchive
buildImportsOf containerScan `shouldNotContain'` [black]
buildImportsOf containerScan `shouldBeSupersetOf'` [numpy, scipy]
dockerEngineSpec
analyzeSpec
jarsInContainerSpec

dockerEngineSpec :: Spec
dockerEngineSpec = describe "parseDockerEngineSource" $ do
it' "should fail if docker engine is not accessible" $ do
expectDockerSdkNotAccessible
expectFatal' $ parseDockerEngineSource exampleImgWithTag

it' "should fail if text lacks tag signifier " $ do
expectDockerSdkToBeAccessible
expectFatal' $ parseDockerEngineSource exampleImgWithoutTag

it' "should fail if image's size cannot be retrieved" $ do
expectDockerSdkToBeAccessible
expectGetImageSizeToFail
expectFatal' $ parseDockerEngineSource exampleImgWithTag

it' "should parse image source if image size can be inferred via docker api" $ do
expectDockerSdkToBeAccessible
expectGetImageSizeToSucceed
src <- parseDockerEngineSource exampleImgWithTag
src `shouldBe'` DockerEngine exampleImgWithTag

analyzeSpec :: Spec
analyzeSpec = describe "analyze" $ do
currDir <- runIO getCurrentDir
let imageArchive = currDir </> appDepsImage

it' "should not analyze application dependencies when only-system-dependencies are requested" $ do
containerScan <- analyzeFromDockerArchive True mempty (toFlag' False) imageArchive
buildImportsOf containerScan `shouldNotContain'` [numpy, scipy, black]

it' "should analyze application dependencies" $ do
containerScan <- analyzeFromDockerArchive False mempty (toFlag' False) imageArchive
buildImportsOf containerScan `shouldBeSupersetOf'` [numpy, scipy, black]
buildImportsOf containerScan `shouldNotContain'` [networkX]

it' "should apply tool exclusion filter" $ do
containerScan <- analyzeFromDockerArchive False (excludeTool SetuptoolsProjectType) (toFlag' False) imageArchive
buildImportsOf containerScan `shouldNotContain'` [numpy, scipy, black]

it' "should apply project exclusion filter" $ do
let appAPath = $(mkRelDir "app/services/b/")
containerScan <- analyzeFromDockerArchive False (excludeProject SetuptoolsProjectType appAPath) (toFlag' False) imageArchive
buildImportsOf containerScan `shouldNotContain'` [scipy]
buildImportsOf containerScan `shouldBeSupersetOf'` [numpy, black]

it' "should analyze all targets, if default filter is disabled" $ do
containerScan <- analyzeFromDockerArchive False mempty (toFlag' True) imageArchive
buildImportsOf containerScan `shouldBeSupersetOf'` [numpy, scipy, black, networkX]

it' "should apply path exclusion filter" $ do
let appAPath = $(mkRelDir "app/services/b/internal/")
containerScan <- analyzeFromDockerArchive False (excludePath appAPath) (toFlag' False) imageArchive
buildImportsOf containerScan `shouldNotContain'` [black]
buildImportsOf containerScan `shouldBeSupersetOf'` [numpy, scipy]

buildImportsOf :: ContainerScan -> [Locator]
buildImportsOf scan =
Expand Down Expand Up @@ -182,3 +186,28 @@ excludeTool tool = AllFilters mempty $ comboExclude [TypeTarget $ toText tool] m

excludeProject :: DiscoveredProjectType -> Path Rel Dir -> AllFilters
excludeProject ty path = AllFilters mempty $ comboExclude [TypeDirTarget (toText ty) path] mempty

jarsInContainerImage :: Path Rel File
jarsInContainerImage = $(mkRelFile "test/App/Fossa/Container/testdata/jar_test_container.tar")

jarsInContainerSpec :: Spec
jarsInContainerSpec = describe "Jars in Containers" $ do
currDir <- runIO getCurrentDir
let imageArchivePath = currDir </> jarsInContainerImage
baseLayerId = "sha256:cc2447e1835a40530975ab80bb1f872fbab0f2a0faecf2ab16fbbb89b3589438"
otherLayerId = "sha256:4d84019f77d1aa837a2cb4225bb79fc03a45ae5a247284dda07cfb9fb8077bd1"

it' "Reads and merges the layers correctly" $ do
ContainerScan{imageData = ContainerScanImage{imageLayers}} <- analyzeFromDockerArchive False mempty (toFlag' False) imageArchivePath
let layerIds = map layerId imageLayers
layerIds
`shouldMatchList'` [baseLayerId, otherLayerId]
it' "Each layer should have the expected number of JAR observations" $ do
ContainerScan{imageData = ContainerScanImage{imageLayers}} <- analyzeFromDockerArchive False mempty (toFlag' False) imageArchivePath
let observationsMap = Map.fromList $ map (\layer -> (layerId layer, observations layer)) imageLayers

-- The CLI only passes observations along without inspecting them.
-- So this test just checks that the number of them that we expect are there.
-- More specific tests for observation content are in Millhone.
(length <$> Map.lookup baseLayerId observationsMap) `shouldBe'` Just 0
(length <$> Map.lookup otherLayerId observationsMap) `shouldBe'` Just 2
6 changes: 6 additions & 0 deletions test/App/Fossa/Container/testdata/container_jars.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Use this DockerFile to build an image used in the jars in containers tests.
FROM alpine
# https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.17.1/
COPY jackson-annotations-2.17.1.jar .
# https://repo1.maven.org/maven2/org/apache/commons/commons-email2-jakarta/2.0.0-M1/
COPY commons-email2-jakarta-2.0.0-M1.jar ./inner_directory/
3 changes: 3 additions & 0 deletions test/App/Fossa/Container/testdata/jar_test_container.tar
Git LFS file not shown

0 comments on commit 55457e7

Please sign in to comment.