From cb4420256597084c4bdee57affa3d34bf5dabc6c Mon Sep 17 00:00:00 2001 From: Ruud Senden <8635138+rsenden@users.noreply.github.com> Date: Fri, 17 May 2024 16:48:19 +0200 Subject: [PATCH] ftest: Add basic FoD action tests --- .../fod/FoDBuiltinActionDefinitionSpec.groovy | 2 +- .../ftest/fod/FoDBuiltinActionRunSpec.groovy | 82 ++++++++++ .../fod/_common/FoDReleaseSupplier.groovy | 144 ++++++++++++++++++ .../ssc/SSCBuiltinActionDefinitionSpec.groovy | 2 +- .../ftest/ssc/SSCBuiltinActionRunSpec.groovy | 2 +- 5 files changed, 229 insertions(+), 3 deletions(-) create mode 100644 fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDBuiltinActionRunSpec.groovy create mode 100644 fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/_common/FoDReleaseSupplier.groovy diff --git a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDBuiltinActionDefinitionSpec.groovy b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDBuiltinActionDefinitionSpec.groovy index 745bff4182..cbd9c7491f 100644 --- a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDBuiltinActionDefinitionSpec.groovy +++ b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDBuiltinActionDefinitionSpec.groovy @@ -23,7 +23,7 @@ import spock.lang.AutoCleanup import spock.lang.Requires import spock.lang.Shared -@Prefix("fod.action") +@Prefix("fod.action.def") class FoDBuiltinActionDefinitionSpec extends FcliBaseSpec { def "list"() { diff --git a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDBuiltinActionRunSpec.groovy b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDBuiltinActionRunSpec.groovy new file mode 100644 index 0000000000..55a9267161 --- /dev/null +++ b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDBuiltinActionRunSpec.groovy @@ -0,0 +1,82 @@ +/** + * Copyright 2023 Open Text. + * + * The only warranties for products and services of Open Text + * and its affiliates and licensors ("Open Text") are as may + * be set forth in the express warranty statements accompanying + * such products and services. Nothing herein should be construed + * as constituting an additional warranty. Open Text shall not be + * liable for technical or editorial errors or omissions contained + * herein. The information contained herein is subject to change + * without notice. + */ +package com.fortify.cli.ftest.fod + +import static com.fortify.cli.ftest._common.spec.FcliSession.FcliSessionType.FOD + +import java.nio.file.Files +import java.nio.file.Path + +import com.fortify.cli.ftest._common.Fcli +import com.fortify.cli.ftest._common.spec.FcliBaseSpec +import com.fortify.cli.ftest._common.spec.FcliSession +import com.fortify.cli.ftest._common.spec.Global +import com.fortify.cli.ftest._common.spec.Prefix +import com.fortify.cli.ftest._common.spec.TempDir +import com.fortify.cli.ftest.fod._common.FoDReleaseSupplier + +import spock.lang.Shared + +@Prefix("fod.action.run") @FcliSession(FOD) +class FoDBuiltinActionRunSpec extends FcliBaseSpec { + @Shared @TempDir("action-output") String actionOutputDir; + @Global(FoDReleaseSupplier.EightBall.class) FoDReleaseSupplier eightBallReleaseSupplier; + + def "runWithOutputFile"() { + def random = System.currentTimeMillis() + def outputFile = "${actionOutputDir}/output-${random}" + def args = "fod action run ${action} -f ${outputFile} --rel ${eightBallReleaseSupplier.release.get("releaseId")}" + when: + def result = Fcli.run(args) + then: + verifyAll(result.stdout) { + size()==1 + Files.exists(Path.of(outputFile)) + } + where: + action << ['release-summary', + 'github-sast-report', + 'gitlab-dast-report', + 'gitlab-sast-report', + 'sarif-sast-report', + 'sonarqube-sast-report'] + } + + + def "runBitBucketSastReport"() { + def random = System.currentTimeMillis() + def reportFile = "${actionOutputDir}/bb-report-${random}" + def annotationsFile = "${actionOutputDir}/bb-annotations-${random}" + def args = "fod action run bitbucket-sast-report -r ${reportFile} -a ${annotationsFile} --rel ${eightBallReleaseSupplier.release.get("releaseId")}" + when: + def result = Fcli.run(args) + then: + verifyAll(result.stdout) { + size()==2 + Files.exists(Path.of(reportFile)) + Files.exists(Path.of(annotationsFile)) + } + } + + def "runCheckPolicy"() { + def args = "fod action run check-policy --rel ${eightBallReleaseSupplier.release.get("releaseId")}" + when: + def result = Fcli.run(args, {}) + then: + verifyAll(result.stdout) { + size()>1 + it.any { it.contains('PASS') || it.contains('FAIL') } + it.any { it.contains("Status: ") } + } + } +} diff --git a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/_common/FoDReleaseSupplier.groovy b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/_common/FoDReleaseSupplier.groovy new file mode 100644 index 0000000000..17c33d0d4e --- /dev/null +++ b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/_common/FoDReleaseSupplier.groovy @@ -0,0 +1,144 @@ +/** + * Copyright 2023 Open Text. + * + * The only warranties for products and services of Open Text + * and its affiliates and licensors ("Open Text") are as may + * be set forth in the express warranty statements accompanying + * such products and services. Nothing herein should be construed + * as constituting an additional warranty. Open Text shall not be + * liable for technical or editorial errors or omissions contained + * herein. The information contained herein is subject to change + * without notice. + */ +package com.fortify.cli.ftest.fod._common + +import java.nio.file.Path + +import com.fortify.cli.ftest._common.Fcli +import com.fortify.cli.ftest._common.spec.Global.IGlobalValueSupplier +import com.fortify.cli.ftest._common.util.WorkDirHelper +import com.fortify.cli.ftest.fod._common.AbstractFoDAppSupplier.FoDApp +import com.fortify.cli.ftest.ssc._common.SSCAppVersionSupplier.SSCAppVersion + +public class FoDReleaseSupplier implements Closeable, AutoCloseable { + private final Closure init; + private FoDRelease release; + + public FoDReleaseSupplier() { + this({}); + } + + public FoDReleaseSupplier(Closure init) { + this.init = init; + } + + public FoDRelease getRelease() { + if ( !release ) { + release = new FoDRelease().create() + init(release); + } + return release + } + + @Override + public void close() { + if ( release ) { + release.close(); + release = null; + } + } + + public static class FoDRelease { + private final String random = System.currentTimeMillis() + private final String fcliVariableName = "fod_release_"+random + private final String releaseName = "v"+random + private final FoDApp app = new FoDWebAppSupplier().createInstance() + + public FoDRelease create() { + Fcli.run("fod release create ${app.appName}:${releaseName} "+ + "--status Development --store ${fcliVariableName}", + {it.expectSuccess(true, "Unable to create application release")}) + return this + } + + public String get(String propertyPath) { + Fcli.run("util var contents $fcliVariableName -o expr={$propertyPath}", + {it.expectSuccess(true, "Error getting application version property "+propertyPath)}) + .stdout[0] + } + + public String getVariableName() { + return fcliVariableName + } + + public String getVariableRef() { + return "::"+fcliVariableName+"::" + } + + public void close() { + app.close() // Should automatically delete release? + } + } + + private static abstract class ReleaseGlobalValueSupplier implements IGlobalValueSupplier { + private FoDReleaseSupplier releaseSupplier; + public final FoDReleaseSupplier getValue(WorkDirHelper workDirHelper) { + if ( !releaseSupplier ) { + releaseSupplier = new FoDReleaseSupplier({ FoDRelease r -> initRelease(workDirHelper, r) }); + } + return releaseSupplier + } + @Override + public final void close() { + if ( releaseSupplier ) { + releaseSupplier.close(); + releaseSupplier = null; + } + } + protected String upload(FoDRelease release, Path fprPath) { + def varName = "global${this.class.simpleName}Fpr" + Fcli.run("fod sast-scan import -f $fprPath --release ${release.variableRef} --store ${varName}") + waitForScan(release) + return varName; + } + protected abstract void initRelease(WorkDirHelper workDirHelper, FoDRelease version); + + private void waitForScan(FoDRelease release) { + def relScanurl = Fcli.run("fod release get ${release.variableRef} -o expr=/api/v3/releases/{releaseId}/scans --store relId").stdout[0] + def timeoutMs = 60000 + def start = System.currentTimeMillis() + def success = false; + while(true){ + def result = Fcli.run("fod rest call ${relScanurl}") + if(result.stdout.findAll{element -> element.contains("analysisStatusType: Completed")}.size()>0) { + success=true; + break; + } else if(System.currentTimeMillis()-start > timeoutMs) { + break; + } + sleep(3000) + } + } + } + + public static class Empty extends ReleaseGlobalValueSupplier { + @Override + protected void initRelease(WorkDirHelper workDirHelper, FoDRelease version) {} + } + + public static class EightBall extends ReleaseGlobalValueSupplier { + @Override + protected void initRelease(WorkDirHelper workDirHelper, FoDRelease version) { + upload(version, workDirHelper.getResource("runtime/shared/EightBall-22.1.0.fpr")); + } + } + + public static class LoginProject extends ReleaseGlobalValueSupplier { + @Override + protected void initRelease(WorkDirHelper workDirHelper, FoDRelease version) { + upload(version, workDirHelper.getResource("runtime/shared/LoginProject.fpr")); + } + } +} + + diff --git a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCBuiltinActionDefinitionSpec.groovy b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCBuiltinActionDefinitionSpec.groovy index ac9ad6cbc8..8095a6fb5f 100644 --- a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCBuiltinActionDefinitionSpec.groovy +++ b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCBuiltinActionDefinitionSpec.groovy @@ -23,7 +23,7 @@ import spock.lang.AutoCleanup import spock.lang.Requires import spock.lang.Shared -@Prefix("ssc.action") +@Prefix("ssc.action.def") class SSCBuiltinActionDefinitionSpec extends FcliBaseSpec { def "list"() { diff --git a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCBuiltinActionRunSpec.groovy b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCBuiltinActionRunSpec.groovy index 3a4b482c82..b89a7b838c 100644 --- a/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCBuiltinActionRunSpec.groovy +++ b/fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCBuiltinActionRunSpec.groovy @@ -27,7 +27,7 @@ import com.fortify.cli.ftest.ssc._common.SSCAppVersionSupplier import spock.lang.Shared -@Prefix("ssc.action") @FcliSession(SSC) +@Prefix("ssc.action.run") @FcliSession(SSC) class SSCBuiltinActionRunSpec extends FcliBaseSpec { @Shared @TempDir("action-output") String actionOutputDir; @Global(SSCAppVersionSupplier.EightBall.class) SSCAppVersionSupplier eightBallVersionSupplier;