diff --git a/MODULE.bazel b/MODULE.bazel index 39339e7a9..7ba661224 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -2,6 +2,7 @@ module(name = "codepropertygraph") bazel_dep(name = "protobuf", version = "34.1") bazel_dep(name = "bazel_tooling") +bazel_dep(name = "rules_java", version = "9.6.1") bazel_dep(name = "rules_jvm_external", version = "7.0") bazel_dep(name = "aspect_rules_lint", version = "2.5.2") bazel_dep(name = "buildifier_prebuilt", version = "8.5.1.2") @@ -46,6 +47,7 @@ maven.install( "com.google.protobuf:protobuf-java:4.34.1", "com.lihaoyi:ujson_3:4.4.3", "com.lihaoyi:os-lib_3:0.11.4", + "com.github.pathikrit:better-files_3:3.9.2", ], excluded_artifacts = [ # Exclude any scala libraries which might come in transitively. diff --git a/codepropertygraph/BUILD b/codepropertygraph/BUILD index 88a5064cc..d4a93cff9 100644 --- a/codepropertygraph/BUILD +++ b/codepropertygraph/BUILD @@ -1,3 +1,4 @@ +load("@rules_java//java:java_library.bzl", "java_library") load("//bazel:scala.bzl", "scala_library", "scala_test") scala_library( @@ -19,10 +20,32 @@ scala_library( ], ) +# We need to use the java_library rule because the dependency +# @rules_java//java/runfiles brings in an annotation processor and +# those only get picked up and executed by java_library and not +# scala_library. +java_library( + name = "tests_java", + testonly = True, + srcs = glob(["src/test/javaBazel/**/*.java"]), + deps = [ + "@rules_java//java/runfiles", + ], +) + scala_test( name = "tests", - srcs = glob(["src/main/scala/**/*.scala"]), + srcs = glob(["src/test/scala/**/*.scala"]), + data = glob(["src/test/resources/**"]), + # The compile time domain classes are neverlink, so the tests need the linked variant at runtime. + runtime_deps = ["//schema:domainClassesLinked"], deps = [ ":codepropertygraph", + ":tests_java", + "//schema:domainClassesNeverLinked", + "//schema:java_proto", + "@maven//:com_github_pathikrit_better_files_3", + "@maven//:io_joern_flatgraph_core_3", + "@maven//:io_joern_flatgraph_help_3", ], ) diff --git a/codepropertygraph/src/test/java/io/shiftleft/utils/CpgRunfilesLocatorJava.java b/codepropertygraph/src/test/java/io/shiftleft/utils/CpgRunfilesLocatorJava.java new file mode 100644 index 000000000..d3f734263 --- /dev/null +++ b/codepropertygraph/src/test/java/io/shiftleft/utils/CpgRunfilesLocatorJava.java @@ -0,0 +1,14 @@ +package io.shiftleft.utils; + +import java.io.IOException; +import java.util.Optional; + +// This class is only used in the sbt build where the runfiles location is not a +// build concept and thus handled on a case by case basis. +// The sbt implementation just returns empty to indicate that the runfiles +// cannot be retrieved. +class CpgRunfilesLocatorJava { + static Optional resolve(String path) throws IOException { + return Optional.empty(); + } +} diff --git a/codepropertygraph/src/test/javaBazel/io/shiftleft/utils/CpgRunfilesLocatorJava.java b/codepropertygraph/src/test/javaBazel/io/shiftleft/utils/CpgRunfilesLocatorJava.java new file mode 100644 index 000000000..914891284 --- /dev/null +++ b/codepropertygraph/src/test/javaBazel/io/shiftleft/utils/CpgRunfilesLocatorJava.java @@ -0,0 +1,25 @@ +package io.shiftleft.utils; + +import com.google.devtools.build.runfiles.AutoBazelRepository; +import com.google.devtools.build.runfiles.Runfiles; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Optional; + +// This class is only part of the Bazel build. +@AutoBazelRepository +class CpgRunfilesLocatorJava { + static Optional resolve(String path) throws IOException { + // The AutoBazelRepository_CpgRunfilesLocatorJava class is auto generated based on the @AutoBazelRepository + // annotation. + Runfiles runfiles = Runfiles.preload().withSourceRepository(AutoBazelRepository_CpgRunfilesLocatorJava.NAME); + String resolvedPath = runfiles.rlocation(path); + if (resolvedPath != null && Files.exists(Path.of(resolvedPath))) { + return Optional.of(resolvedPath); + } else { + return Optional.empty(); + } + } +} diff --git a/codepropertygraph/src/test/scala/io/shiftleft/codepropertygraph/cpgloading/CpgLoaderTests.scala b/codepropertygraph/src/test/scala/io/shiftleft/codepropertygraph/cpgloading/CpgLoaderTests.scala index 35a242461..01156cc1d 100644 --- a/codepropertygraph/src/test/scala/io/shiftleft/codepropertygraph/cpgloading/CpgLoaderTests.scala +++ b/codepropertygraph/src/test/scala/io/shiftleft/codepropertygraph/cpgloading/CpgLoaderTests.scala @@ -3,7 +3,7 @@ package io.shiftleft.codepropertygraph.cpgloading import flatgraph.{Accessors, DiffGraphApplier} import io.shiftleft.codepropertygraph.generated.Cpg import io.shiftleft.codepropertygraph.generated.nodes.NewMethod -import io.shiftleft.utils.{ProjectRoot, TempFileCopy} +import io.shiftleft.utils.{CpgRunfilesLocator, ProjectRoot, TempFileCopy} import io.shiftleft.codepropertygraph.generated.nodes.Type import org.scalatest.BeforeAndAfterAll import org.scalatest.matchers.should.Matchers @@ -37,7 +37,7 @@ class CpgLoaderTests extends AnyWordSpec with Matchers with BeforeAndAfterAll { } "allow loading of CPG in overflowdb format" in { - val odbCpg = ProjectRoot.relativise("codepropertygraph/src/test/resources/cpg.odb") + val odbCpg = testResource("cpg.odb") Using.resource(CpgLoader.load(odbCpg)) { cpg => cpg.graph.nodes("METHOD").size shouldBe 7 } @@ -75,7 +75,13 @@ class CpgLoaderTests extends AnyWordSpec with Matchers with BeforeAndAfterAll { } /** this test graph was created by c2cpg for https://github.com/joernio/joern/blob/master/tests/code/c/test.c */ - val flatgraphCpg = Paths.get(ProjectRoot.relativise("codepropertygraph/src/test/resources/cpg.fg")) + val flatgraphCpg = Paths.get(testResource("cpg.fg")) + + /** Bazel runfiles lookup with fallback to the project root relative path (sbt, IDE) */ + private def testResource(name: String): String = + CpgRunfilesLocator + .resolve(s"codepropertygraph/codepropertygraph/src/test/resources/$name") + .getOrElse(ProjectRoot.relativise(s"codepropertygraph/src/test/resources/$name")) /** flatgraph writes to this file on 'close', so we'll create a temporary copy */ private def temporaryFlatgraphCpg(): TempFileCopy = diff --git a/codepropertygraph/src/test/scala/io/shiftleft/utils/CpgRunfilesLocator.scala b/codepropertygraph/src/test/scala/io/shiftleft/utils/CpgRunfilesLocator.scala new file mode 100644 index 000000000..f04b98f98 --- /dev/null +++ b/codepropertygraph/src/test/scala/io/shiftleft/utils/CpgRunfilesLocator.scala @@ -0,0 +1,11 @@ +package io.shiftleft.utils + +import scala.jdk.OptionConverters.RichOptional + +/** Resolves files via the Bazel runfiles lookup. Only meant for tests inside of this repository. The sbt build always + * returns None, so callers need to fall back to [[ProjectRoot.relativise]]. + */ +private[shiftleft] object CpgRunfilesLocator { + def resolve(path: String): Option[String] = + CpgRunfilesLocatorJava.resolve(path).toScala +} diff --git a/maven_install.json b/maven_install.json index 75343a6d3..18d4808e0 100644 --- a/maven_install.json +++ b/maven_install.json @@ -1,6 +1,7 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", "__INPUT_ARTIFACTS_HASH": { + "com.github.pathikrit:better-files_3": 2078137804, "com.google.code.findbugs:jsr305": 495355163, "com.google.code.gson:gson": 597770368, "com.google.errorprone:error_prone_annotations": -1035138750, @@ -22,6 +23,8 @@ "__RESOLVED_ARTIFACTS_HASH": { "com.github.luben:zstd-jni": 1886873774, "com.github.luben:zstd-jni:jar:sources": -1190847340, + "com.github.pathikrit:better-files_3": -730147472, + "com.github.pathikrit:better-files_3:jar:sources": -1753499885, "com.github.scopt:scopt_3": 148843063, "com.github.scopt:scopt_3:jar:sources": 776003799, "com.google.code.findbugs:jsr305": 870839855, @@ -97,6 +100,13 @@ }, "version": "1.5.7-11" }, + "com.github.pathikrit:better-files_3": { + "shasums": { + "jar": "136c1770a63aa33b2710745bf7f8441cbbe0eeef0cab6b832bd0a46804158989", + "sources": "5a3d4cc0c63605353b1c528abfdc180ae4d74b6c50d6693eee4389dcec923e61" + }, + "version": "3.9.2" + }, "com.github.scopt:scopt_3": { "shasums": { "jar": "7cfb80743b761b3df8630a818265eb91fd93cd77b32ed5ebd6fba1bb7cff6a3f", @@ -385,6 +395,9 @@ "com.github.luben.zstd", "com.github.luben.zstd.util" ], + "com.github.pathikrit:better-files_3": [ + "better.files" + ], "com.github.scopt:scopt_3": [ "scopt" ], @@ -760,6 +773,8 @@ "https://repo1.maven.org/maven2/": [ "com.github.luben:zstd-jni", "com.github.luben:zstd-jni:jar:sources", + "com.github.pathikrit:better-files_3", + "com.github.pathikrit:better-files_3:jar:sources", "com.github.scopt:scopt_3", "com.github.scopt:scopt_3:jar:sources", "com.google.code.findbugs:jsr305",