etorreborre/specs2

Blocker regression in 4.12.7

Closed this issue ยท 13 comments

Here is the minimal failing spec and the accompanying error:

class ErrorPathSpec extends org.specs2.mutable.Specification {
  "Minimal Test" >> {
    "Nested" >> {
      1 ==== 1
    }
  }
}

Test log:

[info] ErrorPathSpec
[error] ! Minimal Test
[error]  java.lang.ClassCastException: class org.specs2.specification.core.Fragment cannot be cast to class 
org.specs2.specification.core.Execution (org.specs2.specification.core.Fragment and org.specs2.specification.core.Execution are 
in unnamed module of loader 'app') (file:1)

Made a new issue for visibility, I originally posted this on a closed issue here: #981 (comment)

This looks like a scala compiler bug, but I implemented a workaround. Fix coming up soon!

For the record, this works fine with specs2-5.x

fixed in 4.12.8

Seems there are new types of regressions, a few more hundred test are failing with cross-thread issues.

requirement failed: Domain context cannot be used across different threads:
Thread that created DomainContext: Thread[specs2-4,5,main]
Thread that is reading aggr. data: Thread[specs2-7,5,main]

... and similars. All these tests were greening on previous 4.2.x

Do you want me to raise a new issue with a reproducible?

I'm really sorry about that. Yes please a small reproducible test case would be wonderful

Of course, will get to it tonight

Here is a smallish repro:


import org.specs2.execute.{AsResult, Result}

class ThreadRegressionSpec
    extends org.specs2.mutable.Specification
    with org.specs2.specification.AroundEach {

  private[this] var thread: Thread = _

  override def around[R: AsResult](r: => R): Result = {
    thread = Thread.currentThread
    AsResult(r)
  }

  "Around should use the same thread" >> {
    Thread.currentThread must be(thread)
  }
}

Regression was introduced in 4.12.7, threading worked with <= 4.12.6

Please have a go at 4.12.9 and tell me how it works for you.

There seem to still be a lot of errors. Will try to make another repro.

Here, similar example, but when overriding is:

import org.specs2.execute.{AsResult, Result}

class ThreadRegressionSpec
    extends org.specs2.Specification // also errors for mutable.Specification
    with org.specs2.specification.AroundEach {

  override def is = s2"""
    Around should use the same thread $aroundTest
  """

  private[this] var thread: Thread = _

  override def around[R: AsResult](r: => R): Result = {
    thread = Thread.currentThread
    AsResult(r)
  }

  def aroundTest = {
    Thread.currentThread must be(thread)
  }
}

I just released 4.12.10 which is reverting 2 changes which started many of those issues:

  • PendingUntilFixed had been generalized to return an Execution instead of a Result in order to better catch TimeoutExceptions

  • the implicit definition for AsExecution[Execution] was improved to catch exceptions

Unfortunately those 2 changes combined to the original implicits for creating a mutable specification have all sort of side effects, classcast exceptions at runtime or variables capture in closure. I don't quite understand what's going on there and could not stabilize anything so I decided to rollback to a previously working state

Hey Eric, thank you for the revert.
I'm happy to inform you that all our tests are now passing on CI and there is no more library dependency shenanigans.
Much obliged!

That's good to know :-). I'm sorry that what I thought would be an improvement turned out to be such a puzzling series of side-effects. I wish I had more time to understand exactly what happened with the classcast exception and variable captures. At the same time I am quite relieved to see that none of these issues happen on Scala 3 ๐ŸŽ‰ .