diff --git a/build.sbt b/build.sbt index a2374b181..8d569bac2 100644 --- a/build.sbt +++ b/build.sbt @@ -37,7 +37,8 @@ def compilerOptions(scalaVersion: String) = Seq( "-Ywarn-unused:params", // Warn if a value parameter is unused. "-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused. "-Ywarn-unused:privates", // Warn if a private member is unused. - "-Ywarn-value-discard" // Warn when non-Unit expression results are unused. + "-Ywarn-value-discard", // Warn when non-Unit expression results are unused. + "-Wnonunit-statement" // Warn when non-unit statements are discarded. ) ++ (if (priorTo2_13(scalaVersion)) Seq( "-Yno-adapted-args", @@ -61,6 +62,7 @@ lazy val standardSettings = Seq( licenses += ("Apache-2.0", url("https://www.apache.org/licenses/LICENSE-2.0.html")), Test / fork := true, scalacOptions ++= compilerOptions(scalaVersion.value), + Test / scalacOptions -= "-Wnonunit-statement", // too noisy with Scalacheck javacOptions ++= Seq("-source", "8", "-target", "8"), // Additional meta-info required by maven central startYear := Some(2015), diff --git a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/BaseFeature.scala b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/BaseFeature.scala index 4744367bf..feacb02c1 100644 --- a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/BaseFeature.scala +++ b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/BaseFeature.scala @@ -61,7 +61,7 @@ object BaseFeature { def addShutdownHook(h: () => Future[_]): Unit = hooks.push(h) - def shutDownGlobalResources(): Future[Done] = { + def shutDownGlobalResources(): Future[Unit] = { import scala.concurrent.ExecutionContext.Implicits.global @tailrec def clearHooks(previous: Future[Any] = Future.successful[Any](())): Future[Any] = @@ -69,10 +69,10 @@ object BaseFeature { case None => previous case Some(f) => clearHooks { - previous.flatMap { _ => f().recover { case _ => Done } } + previous.flatMap { _ => f().recover { case _ => () } } } } - clearHooks().map(_ => Done) + clearHooks().map(_ => ()) } } diff --git a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/BodyElementCollectorMacro.scala b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/BodyElementCollectorMacro.scala index 05197f5e2..af9c81105 100644 --- a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/BodyElementCollectorMacro.scala +++ b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/BodyElementCollectorMacro.scala @@ -80,7 +80,7 @@ class BodyElementCollectorMacro(context: blackbox.Context) { val validExpressions = Array.newBuilder[Tree] val errors = Array.newBuilder[(c.universe.Position, String)] - def evalTree(s: Tree) = + def evalTree(s: Tree): Unit = typeCheck(elementType, seq)(s) match { case Right(tree) => validExpressions += tree case Left(e) => errors += e diff --git a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/CoreDsl.scala b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/CoreDsl.scala index c358a4beb..139486e2e 100644 --- a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/CoreDsl.scala +++ b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/dsl/CoreDsl.scala @@ -16,7 +16,7 @@ import scala.concurrent.duration.FiniteDuration trait CoreDsl { - def Feature(name: String) = FeatureBuilder(name) + def Feature(name: String): FeatureBuilder = FeatureBuilder(name) private[dsl] case class FeatureBuilder(name: String, ignored: Option[String] = None) { def ignoredBecause(reason: String): FeatureBuilder = copy(ignored = Some(reason)) @@ -26,14 +26,14 @@ trait CoreDsl { implicit final def featureBuilder(f: FeatureBuilder): BodyElementCollector[ScenarioDef, FeatureDef] = BodyElementCollector[ScenarioDef, FeatureDef](scenarios => FeatureDef(f.name, scenarios, f.ignored)) - def Scenario(name: String) = ScenarioBuilder(name) + def Scenario(name: String): ScenarioBuilder = ScenarioBuilder(name) private[dsl] case class ScenarioBuilder(name: String, ignored: Option[String] = None, focus: Boolean = false) { def ignoredBecause(reason: String): ScenarioBuilder = copy(ignored = Some(reason)) def ignoredIfDefined(reason: Option[String]): ScenarioBuilder = copy(ignored = reason) /** Focus on this scenario ignoring all other scenarios withing a `Feature` */ def focused: ScenarioBuilder = copy(focus = true) - def pending = ScenarioDef(name, Nil, pending = true) + def pending: ScenarioDef = ScenarioDef(name, Nil, pending = true) } implicit final def scenarioBuilder(s: ScenarioBuilder): BodyElementCollector[Step, ScenarioDef] = diff --git a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/http/HttpService.scala b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/http/HttpService.scala index 86d2253f0..86a8e96d6 100644 --- a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/http/HttpService.scala +++ b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/http/HttpService.scala @@ -183,7 +183,7 @@ object HttpService { def decodeSessionHeaders(headers: String): Either[CornichonError, List[(String, String)]] = traverseIL(headers.split(interHeadersValueDelim).iterator) { header => - val index = header.indexOf(headersKeyValueDelim) + val index = header.indexOf(headersKeyValueDelim.toInt) if (index == -1) Left(BadSessionHeadersEncoding(header)) else diff --git a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/matchers/MatcherParser.scala b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/matchers/MatcherParser.scala index b726798bc..e0e54fbeb 100644 --- a/cornichon-core/src/main/scala/com/github/agourlay/cornichon/matchers/MatcherParser.scala +++ b/cornichon-core/src/main/scala/com/github/agourlay/cornichon/matchers/MatcherParser.scala @@ -12,7 +12,7 @@ class MatcherParser(val input: ParserInput) extends Parser { Ignore ~ zeroOrMore(MatcherRule).separatedBy(Ignore) ~ Ignore ~ EOI } - private def MatcherRule = rule("*" ~ MatcherTXT ~ "*" ~> MatcherKey) + private def MatcherRule = rule('*' ~ MatcherTXT ~ '*' ~> MatcherKey) private def MatcherTXT = rule(capture(oneOrMore(allowedCharsInMatcher))) diff --git a/cornichon-core/src/test/scala/com/github/agourlay/cornichon/core/SessionProperties.scala b/cornichon-core/src/test/scala/com/github/agourlay/cornichon/core/SessionProperties.scala index 2c78dcdbe..88d3433e6 100644 --- a/cornichon-core/src/test/scala/com/github/agourlay/cornichon/core/SessionProperties.scala +++ b/cornichon-core/src/test/scala/com/github/agourlay/cornichon/core/SessionProperties.scala @@ -92,8 +92,8 @@ object SessionProperties extends Properties("Session") { forAll(keyGen, valueGen, valueGen) { (key, firstValue, secondValue) => val s = Session.newEmpty.addValueUnsafe(key, firstValue).addValueUnsafe(key, secondValue) val error = IndexNotFoundForKey(key, 3, Vector(firstValue, secondValue)) - s.get(key, Some(3)) == Left(error) - error.renderedMessage == s"index '3' not found for key '$key' with values \n0 -> $firstValue\n1 -> $secondValue" + s.get(key, Some(3)) == Left(error) && + error.renderedMessage == s"index '3' not found for key '$key' with values \n0 -> $firstValue\n1 -> $secondValue" } property("get proposes similar keys in Session in case of a missing key") = diff --git a/cornichon-kafka/src/main/scala/com/github/agourlay/cornichon/kafka/KafkaDsl.scala b/cornichon-kafka/src/main/scala/com/github/agourlay/cornichon/kafka/KafkaDsl.scala index 0142f3f8c..f3f9a2597 100644 --- a/cornichon-kafka/src/main/scala/com/github/agourlay/cornichon/kafka/KafkaDsl.scala +++ b/cornichon-kafka/src/main/scala/com/github/agourlay/cornichon/kafka/KafkaDsl.scala @@ -67,7 +67,6 @@ trait KafkaDsl { if (messages.size < atLeastAmount) NotEnoughMessagesPolled(atLeastAmount, messages.toList).asLeft else { - messages.drop(messages.size - atLeastAmount) val newSession = messages.foldLeft(sc.session) { (session, value) => commonSessionExtraction(session, topic, value).valueUnsafe } @@ -76,7 +75,7 @@ trait KafkaDsl { } ) - def kafka(topic: String) = KafkaStepBuilder(sessionKey = topic) + def kafka(topic: String): KafkaStepBuilder = KafkaStepBuilder(sessionKey = topic) private def commonSessionExtraction(session: Session, topic: String, response: ConsumerRecord[String, String]) = session.addValues( diff --git a/cornichon-scalatest/src/main/scala/com/github/agourlay/cornichon/scalatest/ScalatestFeature.scala b/cornichon-scalatest/src/main/scala/com/github/agourlay/cornichon/scalatest/ScalatestFeature.scala index 7c398e841..2d550b7a2 100644 --- a/cornichon-scalatest/src/main/scala/com/github/agourlay/cornichon/scalatest/ScalatestFeature.scala +++ b/cornichon-scalatest/src/main/scala/com/github/agourlay/cornichon/scalatest/ScalatestFeature.scala @@ -6,31 +6,29 @@ import com.github.agourlay.cornichon.core._ import com.github.agourlay.cornichon.dsl.BaseFeature import com.github.agourlay.cornichon.dsl.BaseFeature.shutDownGlobalResources import com.github.agourlay.cornichon.scalatest.ScalatestFeature._ - import org.scalatest._ import org.scalatest.wordspec.AsyncWordSpecLike import java.util import java.util.concurrent.atomic.AtomicInteger - -import scala.concurrent.Future +import scala.concurrent.{ Await, Future } import scala.concurrent.duration._ import scala.util.{ Failure, Success, Try } trait ScalatestFeature extends AsyncWordSpecLike with BeforeAndAfterAll with ParallelTestExecution { this: BaseFeature => - override def beforeAll() = { + override def beforeAll(): Unit = { reserveGlobalRuntime() beforeFeature.foreach(f => f()) } - override def afterAll() = { + override def afterAll(): Unit = { afterFeature.foreach(f => f()) releaseGlobalRuntime() } - override def run(testName: Option[String], args: Args) = + override def run(testName: Option[String], args: Args): Status = if (executeScenariosInParallel) super.run(testName, args) else super.run(testName, args.copy(distributor = None)) @@ -96,14 +94,16 @@ object ScalatestFeature { private val registeredUsage = new AtomicInteger private val safePassInRow = new AtomicInteger - // Custom Reaper process for the time being as we want to cleanup after all Feature + // Custom Reaper process for the time being as we want to clean up after all Feature // Will tear down stuff if no Feature registers during 10 secs private val timer = new util.Timer() private val timerTask = new util.TimerTask { def run(): Unit = { if (registeredUsage.get() == 0) { safePassInRow.incrementAndGet() - if (safePassInRow.get() == 2) { shutDownGlobalResources(); () } else () + if (safePassInRow.get() == 2) { + Await.result(shutDownGlobalResources(), Duration.Inf) + } } else if (safePassInRow.get() > 0) { safePassInRow.decrementAndGet() () diff --git a/cornichon-test-framework/src/main/scala/com/github/agourlay/cornichon/framework/CornichonFeatureSbtTask.scala b/cornichon-test-framework/src/main/scala/com/github/agourlay/cornichon/framework/CornichonFeatureSbtTask.scala index efdf02401..0b8b70146 100644 --- a/cornichon-test-framework/src/main/scala/com/github/agourlay/cornichon/framework/CornichonFeatureSbtTask.scala +++ b/cornichon-test-framework/src/main/scala/com/github/agourlay/cornichon/framework/CornichonFeatureSbtTask.scala @@ -15,7 +15,7 @@ class CornichonFeatureSbtTask(task: TaskDef, scenarioNameFilter: Set[String], ex override def execute(eventHandler: EventHandler, loggers: Array[Logger]): Array[Task] = { val fqn = task.fullyQualifiedName() val featureInfo = FeatureInfo(fqn, Class.forName(fqn), task.fingerprint(), task.selectors().head) - val featureTask = loadAndExecute(featureInfo, eventHandler, explicitSeed, scenarioNameFilter) + val featureTask = loadAndExecute(featureInfo, eventHandler, explicitSeed, scenarioNameFilter).map(_ => ()) Await.result(featureTask.unsafeToFuture(), Duration.Inf) Array.empty } diff --git a/cornichon-test-framework/src/main/scala/com/github/agourlay/cornichon/framework/JUnitXmlReporter.scala b/cornichon-test-framework/src/main/scala/com/github/agourlay/cornichon/framework/JUnitXmlReporter.scala index 64714512a..66e4dca17 100644 --- a/cornichon-test-framework/src/main/scala/com/github/agourlay/cornichon/framework/JUnitXmlReporter.scala +++ b/cornichon-test-framework/src/main/scala/com/github/agourlay/cornichon/framework/JUnitXmlReporter.scala @@ -6,13 +6,14 @@ import java.io.{ File, PrintWriter } import java.net.{ InetAddress, UnknownHostException } import java.text.SimpleDateFormat import java.util.Properties - import sbt.testing.{ Event, Status } +import scala.annotation.nowarn import scala.collection.mutable.ListBuffer import scala.concurrent.duration.FiniteDuration // Freely adapted from Scalatest's "org.scalatest.tools.JUnitXmlReporter" +@nowarn("msg=unused value of type scala.xml.NodeBuffer") object JUnitXmlReporter { private lazy val propertiesXml = genPropertiesXml