Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify Common Test Fixture Properties (Note Possible API Changes) #4038

Merged
merged 6 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dataflowengineoss/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name := "dataflowengineoss"

dependsOn(Projects.semanticcpg, Projects.x2cpg)
dependsOn(Projects.semanticcpg, Projects.x2cpg % "compile->compile;test->test")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dependsOn(Projects.semanticcpg, Projects.x2cpg % "compile->compile;test->test")
dependsOn(Projects.semanticcpg, Projects.x2cpg, Projects.x2cpg % "test->test")

The ; separator led to problems with intellij in the past - splitting them up was the fix back then. Not sure if the problem still exists, but better play it safe.

Just noticed that this occurs in other places again - I'll send a PR for that after this is merged.


libraryDependencies ++= Seq(
"org.antlr" % "antlr4-runtime" % Versions.antlr,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.joern.dataflowengineoss.testfixtures

import io.joern.dataflowengineoss.DefaultSemantics
import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions}
import io.joern.dataflowengineoss.queryengine.EngineContext
import io.joern.dataflowengineoss.semanticsloader.{FlowSemantic, Semantics}
import io.joern.x2cpg.testfixtures.TestCpg
import io.shiftleft.semanticcpg.layers.LayerCreatorContext

/** Extends the capabilities of the test CPG to handle the configuration of data-flow enhancements.
*/
trait SemanticTestCpg { this: TestCpg =>

protected var _withOssDataflow = false
protected var _extraFlows = List.empty[FlowSemantic]
protected implicit var context: EngineContext = EngineContext()

/** Allows one to enable data-flow analysis capabilities to the TestCpg.
*/
def withOssDataflow(value: Boolean = true): this.type = {
_withOssDataflow = value
this
}

/** Allows one to add additional semantics to the engine context during PDG creation.
*/
def withExtraFlows(value: List[FlowSemantic] = List.empty): this.type = {
_extraFlows = value
this
}

/** Some frontends require OSS data-flow to execute after post-processing, so we choose to expose this method without
* defining where it's executed.
*/
def applyOssDataFlow(): Unit = {
if (_withOssDataflow) {
val context = new LayerCreatorContext(this)
val options = new OssDataFlowOptions(extraFlows = _extraFlows)
new OssDataFlow(options).run(context)
this.context = EngineContext(Semantics.fromList(DefaultSemantics().elements ++ _extraFlows))
}
}

}

/** Allows the tests to make use of the data-flow engine and any additional semantics.
*/
trait SemanticCpgTestFixture(extraFlows: List[FlowSemantic] = List.empty) {

implicit val context: EngineContext = EngineContext(Semantics.fromList(DefaultSemantics().elements ++ extraFlows))

}
2 changes: 1 addition & 1 deletion joern-cli/frontends/c2cpg/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name := "c2cpg"

dependsOn(Projects.semanticcpg, Projects.dataflowengineoss % Test, Projects.x2cpg % "compile->compile;test->test")
dependsOn(Projects.semanticcpg, Projects.dataflowengineoss % "compile->compile;test->test", Projects.x2cpg % "compile->compile;test->test")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, but feel free to keep as is, I'll clean this up after this PR is in


libraryDependencies ++= Seq(
"org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package io.joern.c2cpg.testfixtures

import better.files.File
import io.joern.c2cpg.{C2Cpg, Config}
import io.joern.c2cpg.parser.FileDefaults
import io.joern.c2cpg.{C2Cpg, Config}
import io.joern.dataflowengineoss.semanticsloader.FlowSemantic
import io.joern.dataflowengineoss.testfixtures.{SemanticCpgTestFixture, SemanticTestCpg}
import io.joern.x2cpg.testfixtures.{Code2CpgFixture, DefaultTestCpg, LanguageFrontend}
import io.shiftleft.codepropertygraph.Cpg
import org.scalatest.Inside

trait C2CpgFrontend extends LanguageFrontend {
def execute(sourceCodePath: java.io.File): Cpg = {
Expand All @@ -23,8 +24,18 @@ trait C2CpgFrontend extends LanguageFrontend {
}
}

class DefaultTestCpgWithC(val fileSuffix: String) extends DefaultTestCpg with C2CpgFrontend
class DefaultTestCpgWithC(val fileSuffix: String) extends DefaultTestCpg with C2CpgFrontend with SemanticTestCpg {
override protected def applyPasses(): Unit = {
super.applyPasses()
applyOssDataFlow()
}
}

class CCodeToCpgSuite(fileSuffix: String = FileDefaults.C_EXT)
extends Code2CpgFixture(() => new DefaultTestCpgWithC(fileSuffix))
with Inside
class CCodeToCpgSuite(
fileSuffix: String = FileDefaults.C_EXT,
withOssDataflow: Boolean = false,
extraFlows: List[FlowSemantic] = List.empty
) extends Code2CpgFixture(() =>
new DefaultTestCpgWithC(fileSuffix).withOssDataflow(withOssDataflow).withExtraFlows(extraFlows)
)
with SemanticCpgTestFixture(extraFlows)
2 changes: 1 addition & 1 deletion joern-cli/frontends/csharpsrc2cpg/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import scala.util.Try

name := "csharpsrc2cpg"

dependsOn(Projects.dataflowengineoss, Projects.x2cpg % "compile->compile;test->test")
dependsOn(Projects.dataflowengineoss % "compile->compile;test->test", Projects.x2cpg % "compile->compile;test->test")

lazy val appProperties = settingKey[Config]("App Properties")
appProperties := {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class DotNetAstGenRunner(config: Config) extends AstGenRunnerBase(config) {

private val logger = LoggerFactory.getLogger(getClass)

// The x86 variant seems to run well enough on MacOS M-family chips, whereas the ARM build crashes
override val MacArm: String = MacX86

override def fileFilter(file: String, out: File): Boolean = {
file.stripSuffix(".json").replace(out.pathAsString, config.inputPath) match {
case filePath if isIgnoredByUserConfig(filePath) => false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,28 @@ package io.joern.csharpsrc2cpg.testfixtures

import io.joern.csharpsrc2cpg.{CSharpSrc2Cpg, Config}
import io.joern.dataflowengineoss.language.Path
import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions}
import io.joern.dataflowengineoss.queryengine.EngineContext
import io.joern.x2cpg.{ValidationMode, X2Cpg}
import io.joern.dataflowengineoss.semanticsloader.FlowSemantic
import io.joern.dataflowengineoss.testfixtures.{SemanticCpgTestFixture, SemanticTestCpg}
import io.joern.x2cpg.testfixtures.{Code2CpgFixture, DefaultTestCpg, LanguageFrontend}
import io.joern.x2cpg.{ValidationMode, X2Cpg}
import io.shiftleft.codepropertygraph.generated.Cpg
import io.shiftleft.semanticcpg.language.{ICallResolver, NoResolve}
import io.shiftleft.semanticcpg.layers.LayerCreatorContext

import java.io.File

class CSharpCode2CpgFixture(withPostProcessing: Boolean = false, withDataFlow: Boolean = false)
extends Code2CpgFixture(() => new DefaultTestCpgWithCSharp(withPostProcessing, withDataFlow)) {
class CSharpCode2CpgFixture(
withPostProcessing: Boolean = false,
withDataFlow: Boolean = false,
extraFlows: List[FlowSemantic] = List.empty
) extends Code2CpgFixture(() =>
new DefaultTestCpgWithCSharp()
.withOssDataflow(withDataFlow)
.withExtraFlows(extraFlows)
.withPostProcessingPasses(withPostProcessing)
)
with SemanticCpgTestFixture(extraFlows) {

implicit val resolver: ICallResolver = NoResolve
implicit lazy val engineContext: EngineContext = EngineContext()
implicit val resolver: ICallResolver = NoResolve

protected def flowToResultPairs(path: Path): List[(String, Integer)] =
path.resultPairs().collect { case (firstElement: String, secondElement: Option[Integer]) =>
Expand Down Expand Up @@ -45,22 +52,11 @@ class CSharpCode2CpgFixture(withPostProcessing: Boolean = false, withDataFlow: B
|""".stripMargin
}

class DefaultTestCpgWithCSharp(withPostProcessing: Boolean, withDataFlow: Boolean)
extends DefaultTestCpg
with CSharpFrontend {

override def applyPasses(): Unit = {
X2Cpg.applyDefaultOverlays(this)
class DefaultTestCpgWithCSharp extends DefaultTestCpg with CSharpFrontend with SemanticTestCpg {

if (withPostProcessing) {
CSharpSrc2Cpg.postProcessingPasses(this, config).foreach(_.createAndApply())
}

if (withDataFlow) {
val context = new LayerCreatorContext(this)
val options = new OssDataFlowOptions()
new OssDataFlow(options).run(context)
}
override def applyPostProcessingPasses(): Unit = {
CSharpSrc2Cpg.postProcessingPasses(this, config).foreach(_.createAndApply())
super.applyPostProcessingPasses()
}

}
Expand Down
2 changes: 1 addition & 1 deletion joern-cli/frontends/gosrc2cpg/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.typesafe.config.{Config, ConfigFactory}

name := "gosrc2cpg"

dependsOn(Projects.dataflowengineoss, Projects.x2cpg % "compile->compile;test->test")
dependsOn(Projects.dataflowengineoss % "compile->compile;test->test", Projects.x2cpg % "compile->compile;test->test")

libraryDependencies ++= Seq(
"io.shiftleft" %% "codepropertygraph" % Versions.cpg,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package io.joern.go2cpg.testfixtures

import better.files.File
import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions}
import io.joern.dataflowengineoss.queryengine.EngineContext
import io.joern.gosrc2cpg.datastructures.GoGlobal
import io.joern.dataflowengineoss.semanticsloader.FlowSemantic
import io.joern.dataflowengineoss.testfixtures.{SemanticCpgTestFixture, SemanticTestCpg}
import io.joern.gosrc2cpg.{Config, GoSrc2Cpg}
import io.joern.x2cpg.X2Cpg
import io.joern.x2cpg.testfixtures.{Code2CpgFixture, DefaultTestCpg, LanguageFrontend}
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.semanticcpg.language.{ICallResolver, NoResolve}
import io.shiftleft.semanticcpg.layers.LayerCreatorContext
import org.scalatest.Inside
trait Go2CpgFrontend extends LanguageFrontend {
def execute(sourceCodePath: java.io.File): Cpg = {
Expand All @@ -25,29 +23,22 @@ trait Go2CpgFrontend extends LanguageFrontend {
}
}

class DefaultTestCpgWithGo(val fileSuffix: String) extends DefaultTestCpg with Go2CpgFrontend {

private var _withOssDataflow = false

def withOssDataflow(value: Boolean = true): this.type = {
_withOssDataflow = value
this
}

override def applyPasses(): Unit = {
X2Cpg.applyDefaultOverlays(this)
if (_withOssDataflow) {
val context = new LayerCreatorContext(this)
val options = new OssDataFlowOptions()
new OssDataFlow(options).run(context)
}
class DefaultTestCpgWithGo(val fileSuffix: String) extends DefaultTestCpg with Go2CpgFrontend with SemanticTestCpg {
override protected def applyPasses(): Unit = {
super.applyPasses()
applyOssDataFlow()
}
}

class GoCodeToCpgSuite(fileSuffix: String = ".go", withOssDataflow: Boolean = false)
extends Code2CpgFixture(() => new DefaultTestCpgWithGo(fileSuffix).withOssDataflow(withOssDataflow))
class GoCodeToCpgSuite(
fileSuffix: String = ".go",
withOssDataflow: Boolean = false,
extraFlows: List[FlowSemantic] = List.empty
) extends Code2CpgFixture(() =>
new DefaultTestCpgWithGo(fileSuffix).withOssDataflow(withOssDataflow).withExtraFlows(extraFlows)
)
with SemanticCpgTestFixture(extraFlows)
with Inside {
implicit val resolver: ICallResolver = NoResolve
implicit lazy val engineContext: EngineContext = EngineContext()
implicit val resolver: ICallResolver = NoResolve

}
2 changes: 1 addition & 1 deletion joern-cli/frontends/javasrc2cpg/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name := "javasrc2cpg"

dependsOn(Projects.dataflowengineoss, Projects.x2cpg % "compile->compile;test->test")
dependsOn(Projects.dataflowengineoss % "compile->compile;test->test", Projects.x2cpg % "compile->compile;test->test")

libraryDependencies ++= Seq(
"io.shiftleft" %% "codepropertygraph" % Versions.cpg,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package io.joern.javasrc2cpg.testfixtures

import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions}
import io.joern.dataflowengineoss.queryengine.EngineContext
import io.joern.dataflowengineoss.semanticsloader.FlowSemantic
import io.joern.dataflowengineoss.testfixtures.{SemanticCpgTestFixture, SemanticTestCpg}
import io.joern.javasrc2cpg.{Config, JavaSrc2Cpg}
import io.joern.x2cpg.X2Cpg
import io.joern.x2cpg.testfixtures.{Code2CpgFixture, LanguageFrontend, TestCpg}
import io.joern.x2cpg.testfixtures.{Code2CpgFixture, DefaultTestCpg, LanguageFrontend, TestCpg}
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.codepropertygraph.generated.PropertyNames
import io.shiftleft.codepropertygraph.generated.nodes.{Expression, Literal, StoredNode}
import io.shiftleft.codepropertygraph.generated.nodes.{Expression, Literal}
import io.shiftleft.semanticcpg.language.*
import io.shiftleft.semanticcpg.layers.LayerCreatorContext

import java.io.File

Expand All @@ -23,31 +22,29 @@ trait JavaSrcFrontend extends LanguageFrontend {
}
}

class JavaSrcTestCpg(enableTypeRecovery: Boolean = false) extends TestCpg with JavaSrcFrontend {
private var _withOssDataflow = false
class JavaSrcTestCpg(enableTypeRecovery: Boolean = false)
extends DefaultTestCpg
with JavaSrcFrontend
with SemanticTestCpg {

def withOssDataflow(value: Boolean = true): this.type = {
_withOssDataflow = value
this
}

override def applyPasses(): Unit = {
X2Cpg.applyDefaultOverlays(this)
override protected def applyPasses(): Unit = {
super.applyPasses()
if (enableTypeRecovery) JavaSrc2Cpg.typeRecoveryPasses(this).foreach(_.createAndApply())
if (_withOssDataflow) {
val context = new LayerCreatorContext(this)
val options = new OssDataFlowOptions()
new OssDataFlow(options).run(context)
}
applyOssDataFlow()
}

}

class JavaSrcCode2CpgFixture(withOssDataflow: Boolean = false, enableTypeRecovery: Boolean = false)
extends Code2CpgFixture(() => new JavaSrcTestCpg(enableTypeRecovery).withOssDataflow(withOssDataflow)) {
class JavaSrcCode2CpgFixture(
withOssDataflow: Boolean = false,
extraFlows: List[FlowSemantic] = List.empty,
enableTypeRecovery: Boolean = false
) extends Code2CpgFixture(() =>
new JavaSrcTestCpg(enableTypeRecovery).withOssDataflow(withOssDataflow).withExtraFlows(extraFlows)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting formatting... did scalafmt come up with that? in that case we need to update our config i guess... :)

)
with SemanticCpgTestFixture(extraFlows) {

implicit val resolver: ICallResolver = NoResolve
implicit lazy val engineContext: EngineContext = EngineContext()
implicit val resolver: ICallResolver = NoResolve

def getConstSourceSink(
cpg: Cpg,
Expand Down
2 changes: 1 addition & 1 deletion joern-cli/frontends/jimple2cpg/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name := "jimple2cpg"

dependsOn(Projects.dataflowengineoss, Projects.x2cpg % "compile->compile;test->test")
dependsOn(Projects.dataflowengineoss % "compile->compile;test->test", Projects.x2cpg % "compile->compile;test->test")

libraryDependencies ++= Seq(
"io.shiftleft" %% "codepropertygraph" % Versions.cpg,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package io.joern.jimple2cpg.testfixtures

import better.files.File as BFile
import io.joern.dataflowengineoss.semanticsloader.FlowSemantic
import io.joern.dataflowengineoss.testfixtures.{SemanticCpgTestFixture, SemanticTestCpg}
import io.joern.jimple2cpg.{Config, Jimple2Cpg}
import io.joern.x2cpg.X2Cpg
import io.joern.x2cpg.testfixtures.{Code2CpgFixture, LanguageFrontend, TestCpg}
import io.joern.x2cpg.testfixtures.{Code2CpgFixture, DefaultTestCpg, LanguageFrontend, TestCpg}
import io.shiftleft.codepropertygraph.Cpg

import java.io.File
Expand All @@ -22,16 +23,20 @@ trait Jimple2CpgFrontend extends LanguageFrontend {
}
}

class JimpleCode2CpgFixture() extends Code2CpgFixture(() => new JimpleTestCpg()) {}
class JimpleCode2CpgFixture(withOssDataflow: Boolean = false, extraFlows: List[FlowSemantic] = List.empty)
extends Code2CpgFixture(() => new JimpleTestCpg().withOssDataflow(withOssDataflow).withExtraFlows(extraFlows))
with SemanticCpgTestFixture(extraFlows) {}

class JimpleTestCpg() extends TestCpg with Jimple2CpgFrontend {
class JimpleTestCpg extends DefaultTestCpg with Jimple2CpgFrontend with SemanticTestCpg {

override protected def applyPasses(): Unit = {
super.applyPasses()
applyOssDataFlow()
}

override protected def codeDirPreProcessing(rootFile: Path, codeFiles: List[Path]): Unit =
JimpleCodeToCpgFixture.compileJava(rootFile, codeFiles.map(_.toFile))

override protected def applyPasses(): Unit = {
X2Cpg.applyDefaultOverlays(this)
}
}

object JimpleCodeToCpgFixture {
Expand Down
2 changes: 1 addition & 1 deletion joern-cli/frontends/jssrc2cpg/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.typesafe.config.{Config, ConfigFactory}

name := "jssrc2cpg"

dependsOn(Projects.dataflowengineoss, Projects.x2cpg % "compile->compile;test->test")
dependsOn(Projects.dataflowengineoss % "compile->compile;test->test", Projects.x2cpg % "compile->compile;test->test")

lazy val appProperties = settingKey[Config]("App Properties")
appProperties := {
Expand Down
Loading
Loading