-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Allow @ResourceLock and @Isolated to work across processes #4211
Comments
You are right in pointing out that there is currently no way to achieve that and it would certainly be non-trivial to implement. Can you elaborate more on your use case? What kind of external resource do you require exclusive access to across subprojects? |
In my case it's access to certain tables in a test database and a custom data server. I could always spin up another test DB and another data server but they can be a pain to manage. I had a different idea on implementation. If specified, then Junit would use |
I think using a separate file lock for each resource can lead to deadlock. For example, when two processes A and B hold the global read lock (which is done on the engine level), A has a read lock for |
With both a external resource that can't be shared, and a project with independent modules that can't communicate you have an architecture with conflicting modes of concurrency. This makes me think you need to wag the dog a bit and change your architecture. Either by:
For the latter, without knowing any more specifics, this sounds like a problem TestContainers could solve. |
Do you mean something like...
If both process A and B are running this same test then they could both start the class test suite How does that not deadlock at the moment with JUnit tests running in parallel in a single process? Or does JUnit work out their lock requirements in a pre-run phase and make sure that they're not run in parallel? I guess if file locking were used in the above scenario, the pre-run phase could identify any mid-test switches from Read to Read/Write and change them to run only as Read/Write. It would cut down on concurrency but it would prevent deadlocks. If |
Setting up multiple duplicate test databases is another option and probably what I'll have to do if this comes to nothing. Ideally JUnit would handle this - I don't think inter-process resource locking is out of scope for unit testing (especially when that resource is a database) but I haven't seen any requests for it in the issues before so maybe it is a niche requirement. |
That is correct. For your example the
I don't think it is possible for n arbitrary Java processes to coordinate usage of an arbitrary number of resources without either a n+1 process to arbitrate or by electing a leader from the n processes. The first isn't possible, the second rather complicated. Probably out of scope for a test framework. |
Ah - and it's done this way because purely using locks would lead to a situation where you could have all but 1 of your threads waiting on the resource to be unlocked? So you could massively underuse your CPU. I guess that does make it difficult to have inter-process locks without some process mediating. Are there other reasons for choosing this design of forcing tests using a Read/Write resourceLock onto a single thread and ensuring that tests using a Read resourceLock didn't run concurrently with that thread? |
@marcphilipp I see you're ex-Gradle. The reason this issue hit me is that I enabled the Gradle configuration cache. Although it's not enabled by default, it seems like it's eventually going to be. |
I agree with @mpkorstanje on this.
That's a good point. However, resource locks were not intended to provide cross-process synchronization. You'd have the same problem in a single project if you set Using separate test databases would be my recommendation for addressing this. If there's only a few tasks and you're not using |
@ResourceLock
is great for ensuring tests run with as much concurrency as possible while protecting exclusive access to resources for the duration of a single test method/class.My issue is that it only protects the resource within that single JUnit test run. If I execute a number of different test runs simultaneously (in different processes) and those test runs have tests that use
@ResourceLock("foo")
thenfoo
can be accessed at the same time from the different test runs.This happens for me as I use Gradle and have many subprojects. Gradle allows running subprojects tests in parallel or sequentially. Running tests in parallel means each project will run its tests in its own process and so
@ResourceLock("foo")
will not be respected across subprojects.Because of this I have to run each subproject's test task sequentially which is slower.
Deliverables
Ideally there would be an option on
@ResourceLock
to specify the level of the lock e.g.@ResourceLock(level = LOCAL | MACHINE)
.For
@ResourceLock("Foo", level = LOCAL)
, the locking would behave as it currently is and this would be the default.For
@ResourceLock("Foo", level = MACHINE)
the lock onFoo
would prevent any junit runs on that machine from simultaneously accessingFoo
. (Perhaps usingjava.nio.channels.FileLock
)It would be good if this could be extended to
@Isolated(level = LOCAL | MACHINE)
to allow only a single test to run concurrently even during multiple simultaneous test runs.Or is there already a way to do this?
The text was updated successfully, but these errors were encountered: