From ebebf46514c0d5abb3b5f82da7f42aa02ba7de63 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 29 Jul 2019 17:54:55 +0100 Subject: [PATCH 1/3] Add class-removed-method-overload-ko, w/ bad msg --- .../src/test/class-removed-method-overload-ko/problems.txt | 1 + .../src/test/class-removed-method-overload-ko/v1/A.scala | 4 ++++ .../src/test/class-removed-method-overload-ko/v2/A.scala | 3 +++ 3 files changed, 8 insertions(+) create mode 100644 functional-tests/src/test/class-removed-method-overload-ko/problems.txt create mode 100644 functional-tests/src/test/class-removed-method-overload-ko/v1/A.scala create mode 100644 functional-tests/src/test/class-removed-method-overload-ko/v2/A.scala diff --git a/functional-tests/src/test/class-removed-method-overload-ko/problems.txt b/functional-tests/src/test/class-removed-method-overload-ko/problems.txt new file mode 100644 index 00000000..96aa06c3 --- /dev/null +++ b/functional-tests/src/test/class-removed-method-overload-ko/problems.txt @@ -0,0 +1 @@ +method foo(java.lang.Object)java.lang.String in class A's type is different in new version, where it is (java.lang.String)java.lang.String instead of (java.lang.Object)java.lang.String diff --git a/functional-tests/src/test/class-removed-method-overload-ko/v1/A.scala b/functional-tests/src/test/class-removed-method-overload-ko/v1/A.scala new file mode 100644 index 00000000..b084d86f --- /dev/null +++ b/functional-tests/src/test/class-removed-method-overload-ko/v1/A.scala @@ -0,0 +1,4 @@ +final class A { + def foo(s: String): String = s + def foo(o: Object): String = o.toString +} diff --git a/functional-tests/src/test/class-removed-method-overload-ko/v2/A.scala b/functional-tests/src/test/class-removed-method-overload-ko/v2/A.scala new file mode 100644 index 00000000..e85081f8 --- /dev/null +++ b/functional-tests/src/test/class-removed-method-overload-ko/v2/A.scala @@ -0,0 +1,3 @@ +final class A { + def foo(s: String): String = s +} From b4ceddc821d8575c55c1dc00ee50bf9489259a0e Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 29 Jul 2019 17:55:22 +0100 Subject: [PATCH 2/3] Removed overloads are missing, not incompatible Previously the method checker didn't take overloading into account, which means that the loss of a method overloading (which includes the loss of a static forwarder methods, when upgrading from Scala 2.12.7 to 2.12.8+) was reported as an "incompatible method type" problem or a "incompatible result type" problem. With this change these are now correctly reported as "direct missing method" problems. --- .../lib/analyze/method/MethodChecker.scala | 30 ++++++++++++------- .../problems.txt | 2 +- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/core/src/main/scala/com/typesafe/tools/mima/lib/analyze/method/MethodChecker.scala b/core/src/main/scala/com/typesafe/tools/mima/lib/analyze/method/MethodChecker.scala index 4cc6e06a..348e485a 100644 --- a/core/src/main/scala/com/typesafe/tools/mima/lib/analyze/method/MethodChecker.scala +++ b/core/src/main/scala/com/typesafe/tools/mima/lib/analyze/method/MethodChecker.scala @@ -8,20 +8,28 @@ private[analyze] abstract class BaseMethodChecker extends Checker[MethodInfo, Cl protected val rules = Seq(AccessModifier, FinalModifier, AbstractModifier, JavaStatic) - protected def check(method: MethodInfo, in: Iterator[MethodInfo]): Option[Problem] = { - val meths = in.filter(method.paramsCount == _.paramsCount).toList + protected def check(method: MethodInfo, newclazz: ClassInfo, methsLookup: ClassInfo => Iterator[MethodInfo]): Option[Problem] = { + val meths = methsLookup(newclazz).filter(method.paramsCount == _.paramsCount).toList // newmeths if (meths.isEmpty) Some(DirectMissingMethodProblem(method)) else { meths.find(m => m.descriptor == method.descriptor && m.signature == method.signature) match { case Some(found) => checkRules(rules)(method, found) - case None => meths.filter(method.matchesType(_)) match { - case Nil => Some(IncompatibleMethTypeProblem(method, uniques(meths))) - case filtered @ first :: _ => filtered.find(_.tpe.resultType == method.tpe.resultType) match { - case None => Some(IncompatibleResultTypeProblem(method, first)) + case None => + val filtered = meths.filter(method.matchesType(_)) + filtered.find(_.tpe.resultType == method.tpe.resultType) match { case Some(found) => Some(IncompatibleSignatureProblem(method, found)) + case None => + val oldmethsDescriptors = methsLookup(method.owner).map(_.descriptor).toSet + if (meths.forall(newmeth => oldmethsDescriptors.contains(newmeth.descriptor))) + Some(DirectMissingMethodProblem(method)) + else { + filtered match { + case Nil => Some(IncompatibleMethTypeProblem(method, uniques(meths))) + case first :: _ => Some(IncompatibleResultTypeProblem(method, first)) + } + } } - } } } } @@ -35,9 +43,9 @@ private[analyze] class ClassMethodChecker extends BaseMethodChecker { if (method.nonAccessible) None else if (method.isDeferred) - super.check(method, inclazz.lookupMethods(method.bytecodeName)) + super.check(method, inclazz, _.lookupMethods(method.bytecodeName)) else - super.check(method, inclazz.lookupClassMethods(method.bytecodeName)) + super.check(method, inclazz, _.lookupClassMethods(method.bytecodeName)) } } @@ -48,7 +56,7 @@ private[analyze] class TraitMethodChecker extends BaseMethodChecker { else if (method.owner.hasStaticImpl(method)) checkStaticImplMethod(method, inclazz) else - super.check(method, inclazz.lookupMethods(method.bytecodeName)) + super.check(method, inclazz, _.lookupMethods(method.bytecodeName)) } private def checkStaticImplMethod(method: MethodInfo, inclazz: ClassInfo) = { @@ -66,7 +74,7 @@ private[analyze] class TraitMethodChecker extends BaseMethodChecker { // otherwise we check the all concrete trait methods and report // either that the method is missing or that no method with the // same signature exists. Either way, we expect that a problem is reported! - val prob = super.check(method, inclazz.lookupConcreteTraitMethods(method.bytecodeName)) + val prob = super.check(method, inclazz, _.lookupConcreteTraitMethods(method.bytecodeName)) assert(prob.isDefined) prob } diff --git a/functional-tests/src/test/class-removed-method-overload-ko/problems.txt b/functional-tests/src/test/class-removed-method-overload-ko/problems.txt index 96aa06c3..dd9d5856 100644 --- a/functional-tests/src/test/class-removed-method-overload-ko/problems.txt +++ b/functional-tests/src/test/class-removed-method-overload-ko/problems.txt @@ -1 +1 @@ -method foo(java.lang.Object)java.lang.String in class A's type is different in new version, where it is (java.lang.String)java.lang.String instead of (java.lang.Object)java.lang.String +method foo(java.lang.Object)java.lang.String in class A does not have a correspondent in new version From 76dc612194428d7fe3e743ca692edfe89a201c20 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 29 Jul 2019 09:50:26 +0100 Subject: [PATCH 3/3] Test latest scala-library 2.12.9, analysed --- .../src/it/scala-library-2-12/problems.txt | 0 .../src/it/scala-library-2-12/test.conf | 182 ++++++++++++++++++ project/TestsPlugin.scala | 10 +- 3 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 functional-tests/src/it/scala-library-2-12/problems.txt create mode 100644 functional-tests/src/it/scala-library-2-12/test.conf diff --git a/functional-tests/src/it/scala-library-2-12/problems.txt b/functional-tests/src/it/scala-library-2-12/problems.txt new file mode 100644 index 00000000..e69de29b diff --git a/functional-tests/src/it/scala-library-2-12/test.conf b/functional-tests/src/it/scala-library-2-12/test.conf new file mode 100644 index 00000000..9a216d06 --- /dev/null +++ b/functional-tests/src/it/scala-library-2-12/test.conf @@ -0,0 +1,182 @@ +groupId = "org.scala-lang" +artifactId = "scala-library" +v1 = "2.12.0" +v2 = "2.12.9-bin-d386f96-SNAPSHOT" + +filter.problems=[ + # all + { problemName=Problem, matchName="scala.concurrent.impl.*" } + { problemName=Problem, matchName="scala.sys.process.*Impl*" } + + # 2.12.2 + # dropped private[immutable] method on private[immutable] VectorPointer + # ... which is extended by VectorBuilder & Vector, which are final + # ... and also extended by VectorIterator, which isn't... :-/ + { problemName=DirectMissingMethodProblem, matchName="scala.collection.immutable.VectorPointer.debug" } + { problemName=DirectMissingMethodProblem, matchName="scala.collection.immutable.VectorBuilder.debug" } + { problemName=DirectMissingMethodProblem, matchName="scala.collection.immutable.Vector.debug" } + { problemName=DirectMissingMethodProblem, matchName="scala.collection.immutable.VectorIterator.debug" } + # dropped private[mutable] & private[collection] methods on object OpenHashMap & object HashTable + { problemName=DirectMissingMethodProblem, matchName="scala.collection.mutable.OpenHashMap.nextPositivePowerOfTwo" } + { problemName=DirectMissingMethodProblem, matchName="scala.collection.mutable.HashTable.powerOfTwo" } + # -def #::(hd: A): Stream[A] + # +def #::[B >: A](hd: B): Stream[B] + { matchName="scala.collection.immutable.Stream#ConsWrapper.#::" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Stream#ConsWrapper.#:::" , problemName=IncompatibleSignatureProblem } + + # 2.12.3 + # Part of scala/scala#5805: "Change type parameters to the [A1, B1] convention", such as: + # -def getOrElse[AA >: A](or: => AA): AA + # +def getOrElse[A1 >: A](or: => A1): A1 + # -def flatMap[BB >: B, X](f: A => Either[X, BB]): Either[X, BB] + # +def flatMap[A1, B1 >: B](f: A => Either[A1, B1]): Either[A1, B1] + { matchName="scala.util.Either#LeftProjection.getOrElse" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#LeftProjection.flatMap" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#LeftProjection.filter" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#LeftProjection.flatMap" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#LeftProjection.getOrElse" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#LeftProjection.map" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#RightProjection.filter" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#RightProjection.flatMap" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#RightProjection.getOrElse" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either#RightProjection.map" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either.cond" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either.contains" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either.filterOrElse" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either.flatMap" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either.getOrElse" , problemName=IncompatibleSignatureProblem } + { matchName="scala.util.Either.map" , problemName=IncompatibleSignatureProblem } + + # 2.12.5 + # Now returns Iterator[List[Nothing]] instead of a Iterator[Traversable[Nothing]] + { matchName="scala.collection.immutable.Nil.tails" , problemName=IncompatibleSignatureProblem } + + # 2.12.7 + # new signature is missing...?? + { matchName="scala.collection.immutable.Nil.andThen" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.seq" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.thisCollection" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.toSeq" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.view" , problemName=IncompatibleSignatureProblem } + + # 2.12.8 + # Before there were 2 Symbol.apply forwarder methods: + # one which is String -> Symbol, which is for Symbol#apply + # one which is Object -> Object, which is the Function1 bridge method + { matchName="scala.Symbol.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.List.empty" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.andThen" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.drop" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.dropRight" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.dropWhile" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.head" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.reverse" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.reversed" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.seq" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.slice" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.tail" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.take" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.takeRight" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.takeWhile" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.thisCollection" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.toCollection" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.toSeq" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.view" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Queue.empty" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Stream.empty" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Stream.fill" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Stream.iterate" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Stream.range" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Stream.tabulate" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Vector.empty" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.mutable.LinkedList.empty" , problemName=DirectMissingMethodProblem } + { matchName="scala.sys.process.Process.Future" , problemName=DirectMissingMethodProblem } + { matchName="scala.sys.process.Process.Spawn" , problemName=DirectMissingMethodProblem } + { matchName="scala.util.Properties.propFilename" , problemName=DirectMissingMethodProblem } + { matchName="scala.util.Properties.scalaProps" , problemName=DirectMissingMethodProblem } + # 2.12.7 -> 2.12.8 + { matchName="scala.None.get" , problemName=DirectMissingMethodProblem } + { matchName="scala.ScalaReflectionException.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.UninitializedFieldError.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.GenMap.empty" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.groupBy" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.isDefinedAt" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.toIterable" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.toMap" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.toSet" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.immutable.Nil.toTraversable" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.parallel.CompositeThrowable.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.collection.script.Index.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.text.DocCons.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.text.DocGroup.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.text.DocNest.apply" , problemName=DirectMissingMethodProblem } + { matchName="scala.text.DocText.apply" , problemName=DirectMissingMethodProblem } + # more forwarders overloading confusing, now in the signatures + { matchName="scala.collection.immutable.Nil.++:" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.:+" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.combinations" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.contains" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.copyToBuffer" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.fold" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.genericBuilder" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.groupBy" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.grouped" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.indexOf" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.indexOfSlice" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.inits" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.lastIndexOf" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.lastIndexOfSlice" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.orElse" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.padTo" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.partition" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.patch" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.permutations" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.product" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.reduce" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.reduceLeft" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.reduceLeftOption" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.reduceOption" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.reduceRight" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.reduceRightOption" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.reverseMap" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.sameElements" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.scan" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.scanLeft" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.scanRight" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.sliding" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.sum" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.toBuffer" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.toSet" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.union" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.unzip" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.unzip3" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.updated" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.withFilter" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.zip" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.zipAll" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.zipWithIndex" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.Nil.zipWithIndex" , problemName=IncompatibleSignatureProblem } + + # 2.12.9 + # type param renames: + # + # - method max(scala.math.Ordering)java.lang.Object in class scala.collection.immutable.TreeSet + # has a different signature in new version, where it is + # (Lscala/math/Ordering;)TA; rather than + # (Lscala/math/Ordering;)TA; + # + # - method min(scala.math.Ordering)java.lang.Object in class scala.collection.immutable.TreeSet + # has a different signature in new version, where it is + # (Lscala/math/Ordering;)TA; rather than + # (Lscala/math/Ordering;)TA; + { matchName="scala.collection.immutable.TreeSet.max" , problemName=IncompatibleSignatureProblem } + { matchName="scala.collection.immutable.TreeSet.min" , problemName=IncompatibleSignatureProblem } + # more specific exceptions: + # - method result(scala.concurrent.Awaitable,scala.concurrent.duration.Duration)java.lang.Object + # in class scala.concurrent.Await has a different signature in new version, where it is + # (Lscala/concurrent/Awaitable;Lscala/concurrent/duration/Duration;)TT;^Ljava/util/concurrent/TimeoutException;^Ljava/lang/InterruptedException; rather than + # (Lscala/concurrent/Awaitable;Lscala/concurrent/duration/Duration;)TT;^Ljava/lang/Exception; + { matchName="scala.concurrent.Await.result" , problemName=IncompatibleSignatureProblem } + { matchName="scala.concurrent.Awaitable.result" , problemName=IncompatibleSignatureProblem } +] diff --git a/project/TestsPlugin.scala b/project/TestsPlugin.scala index 8a7f54f0..39d2f239 100644 --- a/project/TestsPlugin.scala +++ b/project/TestsPlugin.scala @@ -43,6 +43,11 @@ object TestsPlugin extends AutoPlugin { private lazy val tests = bases.get.map(testProject) private lazy val integrationTests = integrationTestBases.get.map(integrationTestProject) + private def sharedTestProjectSettings = Def.settings( + resolvers += "scala-pr-validation-snapshots" at "https://scala-ci.typesafe.com/artifactory/scala-pr-validation-snapshots/", + scalaVersion := testScalaVersion.value, + ) + private def integrationTestProject(base: File) = Project(s"it-${base.name}", base).disablePlugins(BintrayPlugin).settings(integrationTestProjectSettings) @@ -67,7 +72,7 @@ object TestsPlugin extends AutoPlugin { } private val integrationTestProjectSettings = Def.settings( - scalaVersion := testScalaVersion.value, + sharedTestProjectSettings, IntegrationTest / test := runIntegrationTest.value, ) @@ -100,8 +105,7 @@ object TestsPlugin extends AutoPlugin { } private val testProjectSettings = Def.settings( - resolvers += "scala-pr-validation-snapshots" at "https://scala-ci.typesafe.com/artifactory/scala-pr-validation-snapshots/", - scalaVersion := testScalaVersion.value, + sharedTestProjectSettings, inConfig(V1)(testPerConfigSettings), inConfig(V2)(testPerConfigSettings), Test / test := runFunctionalTest.value,