Skip to content

Commit

Permalink
Restrict '@ExclusiveResources' target to 'TYPE'.
Browse files Browse the repository at this point in the history
Issue: #2677
  • Loading branch information
Vladimir Dmitrienko committed Jul 22, 2024
1 parent b55a937 commit b703172
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 204 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@

import org.apiguardian.api.API;

// Which 'status' and 'since' values should I use?
@API(status = STABLE, since = "?")
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Target(ElementType.TYPE)
@Inherited
public @interface ExclusiveResources {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@

import org.apiguardian.api.API;

// Which 'status' and 'since' values should I use?
@API(status = STABLE, since = "?")
public interface ExclusiveResourcesProvider {
default Set<ExclusiveResource> provideForClass(Class<?> testClass) {
return Collections.emptySet();
}

default Set<ExclusiveResource> provideForMethod(Class<?> testClass, Method testMethod) {
default Set<ExclusiveResource> provideForMethod(Method testMethod) {
return Collections.emptySet();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2015-2024 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.jupiter.api.parallel;

import static org.apiguardian.api.API.Status.STABLE;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;

import org.apiguardian.api.API;

// Which 'status' and 'since' values should I use?
@API(status = STABLE, since = "?")
public final class MethodNameBasedExclusiveResourcesProvider implements ExclusiveResourcesProvider {

private static final ExclusiveResource LOCK = ExclusiveResource.readWriteLockOf("method_lock");

public MethodNameBasedExclusiveResourcesProvider() {
}

@Override
public Set<ExclusiveResource> provideForMethod(Method testMethod) {
if (testMethod.getName().contains("give_me_lock")) {
return Collections.singleton(LOCK);
}
return Collections.emptySet();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,10 @@ Set<ExclusiveResource> getExclusiveResourcesFromAnnotation(AnnotatedElement elem
}

@SuppressWarnings("Convert2MethodRef")
Set<ExclusiveResource> getExclusiveResourcesFromProvider(AnnotatedElement element,
Set<ExclusiveResource> getExclusiveResourcesFromProvider(Class<?> testClass,
Function<ExclusiveResourcesProvider, Set<ExclusiveResourcesProvider.ExclusiveResource>> providerToResources) {
// @formatter:off
return findAnnotation(element, ExclusiveResources.class)
return findAnnotation(testClass, ExclusiveResources.class)
.map(annotation -> Stream.of(annotation.value())
.map(providerClass -> ReflectionUtils.newInstance(providerClass))
.map(providerToResources)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ public Set<ExclusiveResource> getExclusiveResources() {
// @formatter:off
Set<ExclusiveResource> resourcesFromAnnotation = getExclusiveResourcesFromAnnotation(getTestMethod());
Set<ExclusiveResource> resourcesFromProvider = getExclusiveResourcesFromProvider(
getTestMethod(),
provider -> provider.provideForMethod(getTestClass(), getTestMethod())
getTestClass(),
provider -> provider.provideForMethod(getTestMethod())
);

return Stream.concat(resourcesFromAnnotation.stream(), resourcesFromProvider.stream()).collect(toSet());
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,45 @@
import org.junit.jupiter.api.parallel.ExclusiveResources;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import org.junit.jupiter.api.parallel.MyExclusiveResourcesProvider;
import org.junit.jupiter.api.parallel.MethodNameBasedExclusiveResourcesProvider;

@Execution(ExecutionMode.CONCURRENT)
@ExclusiveResources(MyExclusiveResourcesProvider.class)
class ExclusiveResourcesProviderOnClassTests {
@ExclusiveResources(MethodNameBasedExclusiveResourcesProvider.class)
class MethodNameBasedExclusiveResourcesProviderTests {

@Test
void a() {
sleep();
}

@Test
void b() {
sleep();
}
// 'give_me_lock' tests expected to be executed sequentially to each other
// but free to be executed in parallel with 'no_lock' tests.

@Test
void c() {
void give_me_lock_1() {
System.out.println("'give_me_lock_1' started at " + System.currentTimeMillis());
sleep();
}

@Test
void d() {
void give_me_lock_2() {
System.out.println("'give_me_lock_2' started at " + System.currentTimeMillis());
sleep();
}

@Test
void e() {
void give_me_lock_3() {
System.out.println("'give_me_lock_3' started at " + System.currentTimeMillis());
sleep();
}

@Test
void f() {
void no_lock_1() {
sleep();
}

@Test
void g() {
void no_lock_2() {
sleep();
}

@Test
void h() {
void no_lock_3() {
sleep();
}

Expand Down

0 comments on commit b703172

Please sign in to comment.