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

Run unit tests with truffle-compiler #8467

Merged
merged 50 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
af6d619
logging-service-logback is JPMS module
Akirathan Dec 5, 2023
8f6157e
runtime uses truffle-compiler in tests
Akirathan Dec 5, 2023
2f7521e
Revert "logging-service-logback is JPMS module"
Akirathan Dec 5, 2023
308f8e8
Refactor Test/options to a separate task
Akirathan Dec 5, 2023
5dc8572
Provide a default logback-test logging config for tests
Akirathan Dec 5, 2023
b99c4a9
Do not add runtime-with-instruments to --patch-module
Akirathan Dec 5, 2023
9357291
Refactor mutable ListBuffer to List
Akirathan Dec 5, 2023
d3c5048
Introduce runtime-fat-jar project.
Akirathan Dec 6, 2023
3e0c531
compileModuleInfo task does not copy anything unless necessary
Akirathan Dec 7, 2023
ec95060
Merge branch 'develop' into wip/akirathan/8374-compiler-to-tests
Akirathan Dec 7, 2023
1c516be
JPMSUtils.filterModules filters only distinct modules
Akirathan Dec 7, 2023
0dd0056
Make sure that all GraalVM modules (including truffle langs) are in -…
Akirathan Dec 7, 2023
4a9c962
Create new module org.enso.interpreter.test
Akirathan Dec 8, 2023
81ec91e
module-info.java is not compiled every time
Akirathan Dec 8, 2023
ea70d95
Revert "Create new module org.enso.interpreter.test"
Akirathan Dec 11, 2023
1d42a25
Add skeleton of JPMSPlugin auto plugin.
Akirathan Dec 12, 2023
2af02fb
Add runtime-test-instruments project.
Akirathan Dec 12, 2023
95381be
Fix VectorTests in runtime
Akirathan Dec 12, 2023
6997cff
Fix the rest of runtime tests
Akirathan Dec 12, 2023
ffd95c4
runtime-with-instruments/test run with truffle-compiler
Akirathan Dec 12, 2023
acb27fc
fmt
Akirathan Dec 12, 2023
78c40a1
Fix some sbt issues with lazy val settings
Akirathan Dec 12, 2023
b98526e
Use service provider instead of reflection in runtime-test-instruments
Akirathan Dec 13, 2023
07f5fa4
Port NodeCountingTestInstrument into runtime-test-instruments
Akirathan Dec 14, 2023
05b221a
Merge runtime-with-instruments project into runtime/Test
Akirathan Dec 14, 2023
b66b3d7
Merge runtime-with-polyglot project into runtime/Test
Akirathan Dec 14, 2023
c9bf46f
Run runtime/test without -ea
Akirathan Dec 14, 2023
b68412e
fmt
Akirathan Dec 14, 2023
a4a82ab
Merge branch 'develop' into wip/akirathan/8374-compiler-to-tests
Akirathan Dec 14, 2023
111cda6
Include insight tool in runtime/Test
Akirathan Dec 15, 2023
256fb9c
withDebug command has better error message
Akirathan Dec 15, 2023
efa56f8
Remove BigNumberTest.averageOfMixedArrayOverDouble.
Akirathan Dec 15, 2023
b64d2b4
Fix context dispose in MetaObjectTest
Akirathan Dec 15, 2023
c3264d7
project-manager/test runs with truffle-compiler
Akirathan Dec 15, 2023
303d272
language-server/test runs with truffle-compiler
Akirathan Dec 15, 2023
0ac7249
JPMSUtils.compileModuleInfo takes an extraModulePath optional argument
Akirathan Dec 15, 2023
283fecb
Merge branch 'develop' into wip/akirathan/8374-compiler-to-tests
Akirathan Dec 15, 2023
b9e1c3d
Small fixes after merge
Akirathan Dec 15, 2023
9d5071f
langauge-server/test uses enso TestLogProvider
Akirathan Dec 15, 2023
8c90c5e
Add necessary modules on modulePath to language-server/test
Akirathan Dec 15, 2023
1ce3069
Add --patch-module option to language-server/test
Akirathan Dec 18, 2023
a342562
runtime/test uses Enso TestLogProvider
Akirathan Dec 18, 2023
3d097ee
Fix DebuggingEnsoTest.
Akirathan Dec 18, 2023
9ecbd68
Make sure runtime/test is run with -ea
Akirathan Dec 18, 2023
e8846cc
Make sure runtime/test is run with -ea
Akirathan Dec 18, 2023
e580ed9
Remove dependency on com.sandinh.sbt-java-module-info plugin
Akirathan Dec 18, 2023
e7171e9
CLeanup some unused methods
Akirathan Dec 18, 2023
e8ca9a9
fmt
Akirathan Dec 18, 2023
ef71ecf
project-manager/test uses TestLogProvider
Akirathan Dec 18, 2023
9820863
Remove unused logback-test.xml resource
Akirathan Dec 18, 2023
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
139 changes: 127 additions & 12 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ import src.main.scala.licenses.{
SBTDistributionComponent
}
import com.sandinh.javamodule.moduleinfo.JpmsModule
import com.sandinh.javamodule.moduleinfo.AutomaticModule
import sbt.librarymanagement.DependencyFilter

import java.io.File
import scala.collection.mutable.ListBuffer

// ============================================================================
// === Global Configuration ===================================================
Expand Down Expand Up @@ -519,6 +522,105 @@ lazy val componentModulesPaths =
)
}

lazy val graalModulesPaths =
taskKey[Def.Classpath](
"Gathers all GraalVM modules (Jar archives that should be put on module-path" +
" as files"
)
(ThisBuild / graalModulesPaths) := {
val runnerCp = (`engine-runner` / Runtime / fullClasspath).value
val runtimeCp = (LocalProject("runtime") / Runtime / fullClasspath).value
val fullCp = (runnerCp ++ runtimeCp).distinct
val log = streams.value.log
JPMSUtils.filterModulesFromClasspath(
fullCp,
GraalVM.modules,
log,
shouldContainAll = true
)
}

/** The javaOptions are created such that the `runtime/test` will run with truffle-compiler
* So we need to properly create --module-path option.
* Module `org.enso.runtime` is added to --module-path as a path to a directory with
* expanded classes, i.e., not a Jar archive. This means we also have to properly create
* --patch-module option. This is an optimization so that we don't have to assembly the
* `runtime.jar` fat jar for the tests.
*/
lazy val modulePathTestOptions =
taskKey[Seq[String]](
"Provides javaOptions for running tests with --module-path set such that " +
"enso (`org.enso.runtime`) module and truffle-compiler and the rest of " +
"the GraalVM modules are on module-path. Also makes sure that the `runtime.jar` " +
"fat jar is not rebuilt unnecessarily"
)
(ThisBuild / modulePathTestOptions) := {
val updateReport = (LocalProject("runtime") / Test / update).value
val runtimeModName = (LocalProject(
"runtime-with-instruments"
) / moduleInfos).value.head.moduleName
val runtimeMod = (LocalProject(
"runtime-with-instruments"
) / Compile / productDirectories).value
val graalMods = graalModulesPaths.value
val loggingMods = JPMSUtils.filterModulesFromUpdate(
updateReport,
logbackPkg ++ Seq(
"org.slf4j" % "slf4j-api" % slf4jVersion
),
streams.value.log,
shouldContainAll = true
)

/** All these modules will be in --patch-module cmdline option to java, which means that
* for the JVM, it will appear that all the classes contained in these sbt projects are contained
* in the `org.enso.runtime` module. In this way, we do not have to assembly the `runtime.jar`
* fat jar.
*/
val modulesToPatchIntoRuntime: Seq[File] =
(LocalProject(
"runtime-instrument-common"
) / Compile / productDirectories).value ++
(LocalProject(
"runtime-instrument-id-execution"
) / Compile / productDirectories).value ++
(LocalProject(
"runtime-instrument-repl-debugger"
) / Compile / productDirectories).value ++
(LocalProject(
"runtime-instrument-runtime-server"
) / Compile / productDirectories).value ++
(LocalProject(
"runtime-language-epb"
) / Compile / productDirectories).value ++
(LocalProject("runtime-compiler") / Compile / productDirectories).value
val patchStr = modulesToPatchIntoRuntime
.map(_.getAbsolutePath)
.mkString(File.pathSeparator)
val allModulesPaths: Seq[String] =
runtimeMod.map(_.getAbsolutePath) ++
graalMods.map(_.data.getAbsolutePath) ++
loggingMods.map(_.getAbsolutePath)
// We can't use org.enso.logger.TestLogProvider (or anything from our own logging framework here) because it is not
Akirathan marked this conversation as resolved.
Show resolved Hide resolved
// in a module, and it cannot be simple wrapped inside a module.
// So we use plain ch.qos.logback with its configuration.
val testLogbackConf = (LocalProject(
"logging-service-logback"
) / Test / sourceDirectory).value / "resources" / "logback-test.xml"
Seq(
"-Dslf4j.provider=ch.qos.logback.classic.spi.LogbackServiceProvider",
s"-Dlogback.configurationFile=${testLogbackConf.getAbsolutePath}",
"--module-path",
allModulesPaths.mkString(File.pathSeparator),
"--add-modules",
runtimeModName,
"--patch-module",
s"$runtimeModName=$patchStr",
"--add-reads",
s"$runtimeModName=ALL-UNNAMED"
)
}

// ============================================================================
// === Internal Libraries =====================================================
// ============================================================================
Expand Down Expand Up @@ -1263,15 +1365,26 @@ lazy val `language-server` = (project in file("engine/language-server"))
.settings(
// These settings are needed by language-server tests that create a runtime context.
Test / fork := true,
Test / javaOptions ++= testLogProviderOptions ++ Seq(
"-Dpolyglot.engine.WarnInterpreterOnly=false",
"-Dpolyglotimpl.DisableClassPathIsolation=true"
),
// Append enso language on the class-path
Test / unmanagedClasspath :=
(LocalProject(
Test / javaOptions ++= testLogProviderOptions ++ {
val runtimeJar = (LocalProject(
"runtime-with-instruments"
) / Compile / fullClasspath).value,
) / assembly / assemblyOutputPath).value
val log = streams.value.log
val requiredModules =
(Test / internalDependencyClasspath).value ++ (Test / unmanagedClasspath).value
val allModules = requiredModules.map(_.data.getAbsolutePath) ++ Seq(
runtimeJar.getAbsolutePath
)
Seq(
"--module-path",
allModules.mkString(File.pathSeparator),
"--add-modules",
// TODO: Use JPMSModule name
"org.enso.runtime"
)
},
// Append enso language on the class-path
Test / unmanagedClasspath := componentModulesPaths.value,
Test / compile := (Test / compile)
.dependsOn(LocalProject("enso") / updateLibraryManifests)
.value,
Expand Down Expand Up @@ -1419,7 +1532,8 @@ lazy val runtime = (project in file("engine/runtime"))
"junit" % "junit" % junitVersion % Test,
"com.github.sbt" % "junit-interface" % junitIfVersion % Test,
"org.hamcrest" % "hamcrest-all" % hamcrestVersion % Test,
"org.slf4j" % "slf4j-nop" % slf4jVersion % Benchmark
"org.slf4j" % "slf4j-nop" % slf4jVersion % Benchmark,
"org.slf4j" % "slf4j-api" % slf4jVersion % Test
),
// Add all GraalVM packages with Runtime scope - we don't need them for compilation,
// just provide them at runtime (in module-path).
Expand All @@ -1432,9 +1546,10 @@ lazy val runtime = (project in file("engine/runtime"))
GraalVM.toolsPkgs.map(_.withConfigurations(Some(Runtime.name)))
necessaryModules ++ langs ++ tools
},
Test / javaOptions ++= testLogProviderOptions ++ Seq(
"-Dpolyglotimpl.DisableClassPathIsolation=true"
),
Test / javaOptions := modulePathTestOptions.value,
Test / unmanagedClasspath := (LocalProject(
"runtime-with-instruments"
) / Compile / exportedProducts).value,
Test / fork := true,
Test / envVars ++= distributionEnvironmentOverrides ++ Map(
"ENSO_TEST_DISABLE_IR_CACHE" -> "false"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%logger{36}] -%kvp- %msg%n</pattern>
</encoder>
<!-- deny all events with a level below WARN, that is INFO, DEBUG and TRACE -->
<!-- Accepts only WARN and ERROR -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
</appender>

<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
54 changes: 40 additions & 14 deletions project/JPMSUtils.scala
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
import sbt.*
import sbt.Keys.*
import sbtassembly.Assembly.{Dependency, JarEntry, Library, Project}
import sbtassembly.MergeStrategy

import java.io.{File, FilenameFilter}
import sbtassembly.CustomMergeStrategy
import xsbti.compile.IncToolOptionsUtil
import sbt.internal.inc.{CompileOutput, PlainVirtualFile}
import sbtassembly.Assembly.{Dependency, JarEntry, Project}
import sbtassembly.{CustomMergeStrategy, MergeStrategy}
import xsbti.compile.IncToolOptionsUtil

import java.nio.file.attribute.BasicFileAttributes
import java.nio.file.{
FileVisitResult,
FileVisitor,
Files,
Path,
SimpleFileVisitor
}
import java.io.File
import java.nio.file.{Files, Path}

/** Collection of utility methods dealing with JPMS modules.
* The motivation comes from the update of GraalVM to
Expand Down Expand Up @@ -73,6 +64,41 @@ object JPMSUtils {
ret
}

/** Filters all the requested modules from the given [[UpdateReport]].
*
* @param updateReport The update report to filter. This is the result of `update.value`.
* @param modules The modules to filter from the update report.
* @param log The logger to use for logging.
* @param shouldContainAll If true, the method will log an error if not all modules were found.
* @return The list of files (Jar archives, directories, etc.) that were found in the update report.
*/
def filterModulesFromUpdate(
updateReport: UpdateReport,
modules: Seq[ModuleID],
log: sbt.util.Logger,
shouldContainAll: Boolean = false
): Seq[File] = {
def shouldFilterModule(module: ModuleID): Boolean = {
modules.exists(m =>
m.organization == module.organization &&
m.name == module.name &&
m.revision == module.revision
)
}

val foundFiles = updateReport.select(
module = shouldFilterModule
)
if (shouldContainAll) {
if (foundFiles.size < modules.size) {
log.error("Not all modules from update were found")
log.error(s"Returned (${foundFiles.size}): $foundFiles")
log.error(s"Expected: (${modules.size}): $modules")
}
}
foundFiles
}

def filterTruffleAndGraalArtifacts(
classPath: Def.Classpath
): Def.Classpath = {
Expand Down
Loading