mirror of
https://github.com/enso-org/enso.git
synced 2024-08-16 16:30:33 +03:00
All unit tests use the same testing logging provider (#8593)
Make sure that the correct test logging provider is loaded in `project-manager/Test`, so that only WARN and ERROR log messages are displayed. Also, make sure that the test log provider parses the correct configuration file - Rename all the `application.conf` files in the test resources to `application-test.conf`. The problem was introduced in #8467
This commit is contained in:
parent
ac9d8c710f
commit
edc98593b9
25
build.sbt
25
build.sbt
@ -272,7 +272,6 @@ lazy val enso = (project in file("."))
|
||||
`syntax-definition`,
|
||||
`syntax-rust-definition`,
|
||||
`text-buffer`,
|
||||
logger,
|
||||
pkg,
|
||||
cli,
|
||||
`task-progress-notifications`,
|
||||
@ -528,13 +527,6 @@ lazy val compileModuleInfo = taskKey[Unit]("Compiles `module-info.java`")
|
||||
// === Internal Libraries =====================================================
|
||||
// ============================================================================
|
||||
|
||||
lazy val logger = (project in file("lib/scala/logger"))
|
||||
.settings(
|
||||
frgaalJavaCompilerSetting,
|
||||
version := "0.1",
|
||||
libraryDependencies ++= scalaCompiler
|
||||
)
|
||||
|
||||
lazy val `syntax-definition` =
|
||||
project in file("lib/scala/syntax/definition")
|
||||
|
||||
@ -907,7 +899,10 @@ lazy val `project-manager` = (project in file("lib/scala/project-manager"))
|
||||
"org.apache.commons" % "commons-lang3" % commonsLangVersion,
|
||||
"com.beachape" %% "enumeratum-circe" % enumeratumCirceVersion,
|
||||
"com.miguno.akka" %% "akka-mock-scheduler" % akkaMockSchedulerVersion % Test,
|
||||
"org.mockito" %% "mockito-scala" % mockitoScalaVersion % Test
|
||||
"org.mockito" %% "mockito-scala" % mockitoScalaVersion % Test,
|
||||
"junit" % "junit" % junitVersion % Test,
|
||||
"com.github.sbt" % "junit-interface" % junitIfVersion % Test,
|
||||
"org.hamcrest" % "hamcrest-all" % hamcrestVersion % Test
|
||||
),
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
||||
@ -1016,7 +1011,7 @@ lazy val `project-manager` = (project in file("lib/scala/project-manager"))
|
||||
.dependsOn(`json-rpc-server-test` % Test)
|
||||
.dependsOn(testkit % Test)
|
||||
.dependsOn(`runtime-version-manager-test` % Test)
|
||||
.dependsOn(`logging-service-logback` % Test)
|
||||
.dependsOn(`logging-service-logback` % "test->test")
|
||||
|
||||
/* Note [Classpath Separation]
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -1207,8 +1202,13 @@ val truffleRunOptionsSettings = Seq(
|
||||
javaOptions ++= "-ea" +: benchOnlyOptions
|
||||
)
|
||||
|
||||
/** Explicitly provide `application-test.conf` as the resource that should be used for
|
||||
* parsing the logging configuration. Explicitly setting `config.resource` prevents
|
||||
* the potential conflicts with other *.conf files.
|
||||
*/
|
||||
val testLogProviderOptions = Seq(
|
||||
"-Dslf4j.provider=org.enso.logger.TestLogProvider"
|
||||
"-Dslf4j.provider=org.enso.logger.TestLogProvider",
|
||||
"-Dconfig.resource=application-test.conf"
|
||||
)
|
||||
|
||||
lazy val `polyglot-api` = project
|
||||
@ -2126,8 +2126,7 @@ lazy val launcher = project
|
||||
.dependsOn(buildNativeImage)
|
||||
.dependsOn(LauncherShimsForTest.prepare())
|
||||
.evaluated,
|
||||
Test / fork := true,
|
||||
Test / javaOptions += s"-Dconfig.file=${sourceDirectory.value}/test/resources/application.conf"
|
||||
Test / fork := true
|
||||
)
|
||||
.dependsOn(cli)
|
||||
.dependsOn(`runtime-version-manager`)
|
||||
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.Collectors;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.spi.SLF4JServiceProvider;
|
||||
|
||||
/**
|
||||
* In the `runtime/Test` testing suite, {@link org.enso.logger.TestLogProvider} should be among the
|
||||
* logging providers, because it is explicitly chosen as the logging provider for the tests.
|
||||
*/
|
||||
public class TestLogProviderOnClasspath {
|
||||
@Test
|
||||
public void testLogProviderOnClasspath() {
|
||||
var sl = ServiceLoader.load(SLF4JServiceProvider.class);
|
||||
var serviceIterator = sl.iterator();
|
||||
List<SLF4JServiceProvider> providers = new ArrayList<>();
|
||||
while (serviceIterator.hasNext()) {
|
||||
providers.add(serviceIterator.next());
|
||||
}
|
||||
List<String> providerNames =
|
||||
providers.stream().map(elem -> elem.getClass().getName()).collect(Collectors.toList());
|
||||
assertThat(providerNames, hasItem("org.enso.logger.TestLogProvider"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogProviderIsInUnnamedModule() throws Exception {
|
||||
var testLogProviderClass = Class.forName("org.enso.logger.TestLogProvider");
|
||||
var mod = testLogProviderClass.getModule();
|
||||
assertThat(mod, notNullValue());
|
||||
assertThat("Should be an unnamed module - with null name", mod.getName(), nullValue());
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
# Empty
|
@ -0,0 +1 @@
|
||||
# Empty
|
@ -1,3 +0,0 @@
|
||||
# Logger
|
||||
|
||||
A configurable logging library.
|
@ -1 +0,0 @@
|
||||
package org.enso;
|
@ -1,165 +0,0 @@
|
||||
package org.enso
|
||||
|
||||
import scala.annotation.unused
|
||||
import scala.reflect.macros.blackbox.Context
|
||||
|
||||
class Logger {
|
||||
import Logger._
|
||||
|
||||
var nesting = 0
|
||||
|
||||
def log(s: String): Unit =
|
||||
macro funcRedirect
|
||||
|
||||
def warn(s: String): Unit =
|
||||
macro funcRedirect
|
||||
|
||||
def err(s: String): Unit =
|
||||
macro funcRedirect
|
||||
|
||||
def group[T](msg: String)(body: => T): T =
|
||||
macro groupRedirect[T]
|
||||
|
||||
def trace[T](body: => T): T =
|
||||
macro targetRedirect[T]
|
||||
|
||||
def trace_[T](body: => T): T =
|
||||
macro targetRedirect_[T]
|
||||
|
||||
def _log(msg: String): Unit =
|
||||
println("| " * nesting + msg)
|
||||
|
||||
def _warn(msg: String): Unit =
|
||||
println("| " * nesting + Console.YELLOW + msg + Console.RESET)
|
||||
|
||||
def _err(msg: String): Unit =
|
||||
println("| " * nesting + Console.RED + msg + Console.RESET)
|
||||
|
||||
def _group[T](msg: String)(body: => T): T = {
|
||||
_log(msg)
|
||||
beginGroup()
|
||||
val out = body
|
||||
endGroup()
|
||||
out
|
||||
}
|
||||
|
||||
def _trace[T](msg: String)(body: => T): T = {
|
||||
_log(msg)
|
||||
beginGroup()
|
||||
val out = body
|
||||
endGroup()
|
||||
out
|
||||
}
|
||||
|
||||
def _trace_[T](msg: String)(body: => T): T = {
|
||||
_log(msg)
|
||||
beginGroup()
|
||||
val out = body
|
||||
endGroup()
|
||||
out
|
||||
}
|
||||
|
||||
def beginGroup(): Unit =
|
||||
nesting += 1
|
||||
|
||||
def endGroup(): Unit =
|
||||
nesting -= 1
|
||||
|
||||
}
|
||||
|
||||
object Logger {
|
||||
def groupRedirect[R: c.WeakTypeTag](
|
||||
c: Context
|
||||
)(@unused msg: c.Tree)(body: c.Tree): c.Expr[R] = {
|
||||
import c.universe._
|
||||
val target = c.macroApplication match {
|
||||
case Apply(Apply(TypeApply(Select(base, name), typ), msg2), body2) =>
|
||||
val newName = TermName("_" + name.toString)
|
||||
Apply(Apply(TypeApply(Select(base, newName), typ), msg2), body2)
|
||||
case _ => throw new Error("Unsupported shape")
|
||||
}
|
||||
if (checkEnabled(c)) c.Expr(q"$target") else c.Expr(q"$body")
|
||||
}
|
||||
|
||||
def targetRedirect[R: c.WeakTypeTag](c: Context)(body: c.Tree): c.Expr[R] = {
|
||||
import c.universe._
|
||||
val target = c.macroApplication match {
|
||||
case Apply(TypeApply(Select(base, name), typ), body2) =>
|
||||
val newName = TermName("_" + name.toString)
|
||||
val owner = c.internal.enclosingOwner.asMethod
|
||||
val owner2 = owner.owner
|
||||
val parentObject = !owner2.isStatic
|
||||
val oname =
|
||||
if (parentObject) owner2.name.toString + "." + owner.name.toString
|
||||
else owner.name.toString
|
||||
val ownerName = Literal(Constant(oname))
|
||||
owner.paramLists match {
|
||||
case lst :: _ =>
|
||||
val lst2 = lst.map(x => q"$x")
|
||||
val msg =
|
||||
if (lst2.isEmpty) List(q"$ownerName")
|
||||
else List(q"$ownerName + $lst2.toString().drop(4)")
|
||||
Apply(Apply(TypeApply(Select(base, newName), typ), msg), body2)
|
||||
case _ => throw new Error("Unsupported shape")
|
||||
}
|
||||
case _ => throw new Error("Unsupported shape")
|
||||
}
|
||||
if (checkEnabled(c)) c.Expr(q"$target") else c.Expr(q"$body")
|
||||
}
|
||||
|
||||
def targetRedirect_[R: c.WeakTypeTag](c: Context)(body: c.Tree): c.Expr[R] = {
|
||||
import c.universe._
|
||||
val target = c.macroApplication match {
|
||||
case Apply(TypeApply(Select(base, name), typ), body2) =>
|
||||
val newName = TermName("_" + name.toString)
|
||||
val owner = c.internal.enclosingOwner.asMethod
|
||||
val owner2 = owner.owner
|
||||
val parentObject = !owner2.isStatic
|
||||
val oname =
|
||||
if (parentObject) owner2.name.toString + "." + owner.name.toString
|
||||
else owner.name.toString
|
||||
val ownerName = Literal(Constant(oname))
|
||||
owner.paramLists match {
|
||||
case _ :: _ =>
|
||||
val msg = List(q"$ownerName")
|
||||
Apply(Apply(TypeApply(Select(base, newName), typ), msg), body2)
|
||||
case _ => throw new Error("Unsupported shape")
|
||||
}
|
||||
case _ => throw new Error("Unsupported shape")
|
||||
}
|
||||
if (checkEnabled(c)) c.Expr(q"$target") else c.Expr(q"$body")
|
||||
}
|
||||
|
||||
def funcRedirect(c: Context)(@unused s: c.Tree): c.Expr[Unit] = {
|
||||
import c.universe._
|
||||
val target = c.macroApplication match {
|
||||
case Apply(Select(base, name), args) =>
|
||||
val newName = TermName("_" + name.toString)
|
||||
Apply(Select(base, newName), args)
|
||||
case _ => throw new Error("Unsupported shape")
|
||||
}
|
||||
if (checkEnabled(c)) c.Expr(q"$target") else c.Expr(q"{}")
|
||||
}
|
||||
|
||||
def checkEnabled(c: Context): Boolean = {
|
||||
val optPfx = "logging"
|
||||
val opts = c.settings.filter(_.matches(s"(\\+|\\-)$optPfx.*"))
|
||||
val owner = c.internal.enclosingOwner.fullName
|
||||
var enabled = true
|
||||
opts.foreach { opt =>
|
||||
val sign = opt.head
|
||||
val body = opt.tail.drop(optPfx.length)
|
||||
val status = sign == '+'
|
||||
val applies =
|
||||
if (body == "") true
|
||||
else {
|
||||
val pathPfx = body.head
|
||||
val path = body.tail
|
||||
pathPfx == '@' && owner.startsWith(path)
|
||||
}
|
||||
if (applies) enabled = status
|
||||
}
|
||||
enabled
|
||||
}
|
||||
|
||||
}
|
@ -18,6 +18,7 @@ public class TestLogProvider implements SLF4JServiceProvider {
|
||||
@Override
|
||||
public ILoggerFactory getLoggerFactory() {
|
||||
ILoggerFactory factory = underlying.getLoggerFactory();
|
||||
assert factory instanceof LoggerContext;
|
||||
if (!initialized) {
|
||||
try {
|
||||
new LogbackSetup((LoggerContext) factory).setup();
|
||||
|
@ -0,0 +1,46 @@
|
||||
package org.enso.projectmanager;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.Collectors;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.spi.SLF4JServiceProvider;
|
||||
|
||||
/**
|
||||
* In the `runtime/Test` testing suite, {@link }org.enso.logger.TestLogProvider} should be among the
|
||||
* logging providers, because it is explicitly chosen as the logging provider for the tests.
|
||||
*
|
||||
* <p>Note that the same test is in the `runtime/Test` project.
|
||||
*/
|
||||
public class TestLogProviderOnClasspath {
|
||||
@Test
|
||||
public void testLogProviderIsOnClasspath() {
|
||||
var sl = ServiceLoader.load(SLF4JServiceProvider.class);
|
||||
var serviceIterator = sl.iterator();
|
||||
List<SLF4JServiceProvider> providers = new ArrayList<>();
|
||||
while (serviceIterator.hasNext()) {
|
||||
providers.add(serviceIterator.next());
|
||||
}
|
||||
List<String> providerNames =
|
||||
providers.stream().map(elem -> elem.getClass().getName()).collect(Collectors.toList());
|
||||
assertThat(providerNames, hasItem("org.enso.logger.TestLogProvider"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogProviderIsInUnnamedModule() {
|
||||
Class<?> testLogProviderClass = null;
|
||||
try {
|
||||
testLogProviderClass = Class.forName("org.enso.logger.TestLogProvider");
|
||||
} catch (ClassNotFoundException e) {
|
||||
fail("TestLogProvider class not found");
|
||||
}
|
||||
var mod = testLogProviderClass.getModule();
|
||||
assertThat(mod, notNullValue());
|
||||
assertThat("Should be an unnamed module - with null name", mod.getName(), nullValue());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user