Skip to content

Commit

Permalink
Merge pull request apache#7979 from petrovic-d/action-for-running-tes…
Browse files Browse the repository at this point in the history
…ts-in-parallel

Action for running tests in parallel
  • Loading branch information
sdedic authored Dec 19, 2024
2 parents 22172a9 + 40bae1a commit 9d5bc1e
Show file tree
Hide file tree
Showing 65 changed files with 1,679 additions and 309 deletions.
2 changes: 1 addition & 1 deletion enterprise/micronaut/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
release.external/spring-boot-configuration-metadata-2.4.4.jar=modules/ext/spring-boot-configuration-metadata-2.4.4.jar
release.external/android-json-0.0.20131108.vaadin1.jar=modules/ext/android-json-0.0.20131108.vaadin1.jar
spec.version.base=1.16.0
spec.version.base=1.17.0
requires.nb.javac=true
test-unit-sys-prop.test.netbeans.dest.dir=${netbeans.dest.dir}
test.unit.cp.extra=${tools.jar}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@
<packaging>native-image</packaging>
</properties>
</action>
<action>
<actionName>test.single</actionName>
<packagings>
<packaging>*</packaging>
</packagings>
<goals>
<goal>io.micronaut.maven:micronaut-maven-plugin:start-testresources-service</goal>
<goal>process-test-classes</goal>
<goal>surefire:test</goal>
</goals>
<properties>
<test>${packageClassName}</test>
</properties>
</action>

<profiles>
<profile>
Expand Down
12 changes: 12 additions & 0 deletions extide/gradle/apichanges.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ is the proper place.
<!-- ACTUAL CHANGES BEGIN HERE: -->

<changes>
<change id="action-for-running-tests-in-parallel">
<api name="general"/>
<summary>Added action for running tests in parallel</summary>
<version major="2" minor="45"/>
<date day="18" month="12" year="2024"/>
<author login="petrovic-d"/>
<compatibility semantic="compatible" addition="yes" deprecation="yes"/>
<description>
Added action for running tests in parallel with ability to specify the projects on which
the action will be applied.
</description>
</change>
<change id="load-options-lookup">
<api name="general"/>
<summary>LoadOptions object replaces growing number of argumetns to project load APIs. Access to current Lookup added.</summary>
Expand Down
2 changes: 1 addition & 1 deletion extide/gradle/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ javadoc.apichanges=${basedir}/apichanges.xml
nbm.module.author=Laszlo Kishalmi
source.reference.netbeans-gradle-tooling.jar=netbeans-gradle-tooling/src/main/groovy

spec.version.base=2.44.0
spec.version.base=2.45.0
test-unit-sys-prop.test.netbeans.dest.dir=${netbeans.dest.dir}
test-unit-sys-prop.java.awt.headless=true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.netbeans.modules.gradle.api.execute.RunUtils;
import org.netbeans.modules.gradle.actions.ActionToTaskUtils;
import org.netbeans.modules.gradle.execute.GradleExecutorOptionsPanel;
import org.netbeans.modules.gradle.spi.actions.GradleActionsProvider;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -189,6 +188,7 @@ public boolean isActionEnabled(String command, Lookup context) throws IllegalArg
"# {0} - artifactId", "TXT_ApplyCodeChanges=Apply Code Changes ({0})",
"# {0} - artifactId", "TXT_Profile=Profile ({0})",
"# {0} - artifactId", "TXT_Test=Test ({0})",
"# {0} - artifactId", "TXT_Test_Parallel=Test In Parallel ({0})",
"# {0} - artifactId", "TXT_Build=Build ({0})",
"# {0} - artifactId", "TXT_Delete=Delete ({0})",
})
Expand All @@ -215,6 +215,9 @@ static String taskName(Project project, String action, Lookup lkp) {
case ActionProvider.COMMAND_TEST:
title = TXT_Test(prjLabel);
break;
case ActionProvider.COMMAND_TEST_PARALLEL:
title = TXT_Test_Parallel(prjLabel);
break;
case ActionProvider.COMMAND_RUN_SINGLE:
title = TXT_Run(dobjName);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
</profiles>
<!-- @end region="configuration-declaration-xml" -->

<action name="test.parallel">
<args>--parallel --rerun-tasks ${taskWithProjects}</args>
</action>
<apply-for plugins="java">
<action name="test.single">
<args>cleanTest test --tests "${selectedClass}"</args>
Expand Down
21 changes: 21 additions & 0 deletions ide/projectapi/apichanges.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,27 @@ is the proper place.
<!-- ACTUAL CHANGES BEGIN HERE: -->

<changes>
<change id="run-test-in-parallel-action">
<api name="general"/>
<summary>Added action for running tests in parallel</summary>
<version major="1" minor="99"/>
<date day="2" month="12" year="2024"/>
<author login="petrovic-d"/>
<compatibility addition="yes"/>
<description>
<p>
<code><a href="@TOP@/org/netbeans/spi/project/ActionProvider.html">ActionProvider.COMMAND_TEST_PARALLEL</a></code> was introduced in order to
allow running tests in parallel.
<code><a href="@TOP@/org/netbeans/api/project/ContainedProjectFilter.html">ContainedProjectFilter</a></code> was added and
it can be used to pass list of projects the project action should apply to.
<code><a href="@TOP@/org/netbeans/spi/project/NestedClass">NestedClass</a></code> was added in order to support
nested classes.
</p>
</description>
<class package="org.netbeans.api.project" name="ContainedProjectFilter"/>
<class package="org.netbeans.spi.project" name="ActionProvider"/>
<class package="org.netbeans.spi.project" name="NestedClass"/>
</change>
<change id="project-action-context">
<api name="general"/>
<summary>Added <code>ProjectActionContext</code> that can pass action-like environment to project queries</summary>
Expand Down
2 changes: 1 addition & 1 deletion ide/projectapi/manifest.mf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.modules.projectapi/1
OpenIDE-Module-Specification-Version: 1.98
OpenIDE-Module-Specification-Version: 1.99
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/projectapi/Bundle.properties
OpenIDE-Module-Layer: org/netbeans/modules/projectapi/layer.xml
OpenIDE-Module-Needs: org.netbeans.spi.project.ProjectManagerImplementation
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.api.project;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
* Provides list of projects the project action should apply to
*
* <p>
* An action that processes multiple projects might use <code>ContainedProjectFilter</code>
* to operate only on a specific subset of projects.
* The use of <code>ContainedProjectFilter</code> is optional and determined
* by the requirements of individual actions.
* Actions employing this class must document their specific filtering logic
* and behavior.
* </p>
*
* @author Dusan Petrovic
*
* @since 1.99
*/
public final class ContainedProjectFilter {

private final List<Project> projectsToProcess;

private ContainedProjectFilter(List<Project> projectsToProcess) {
this.projectsToProcess = projectsToProcess;
}

/**
* Static factory method to create an instance of ContainedProjectFilter.
*
* @param projectsToProcess the list of projects to include in the filter
* @return an Optional containing ContainedProjectFilter, or Optional.empty() if the list is null or empty
*/
public static Optional<ContainedProjectFilter> of(List<Project> projectsToProcess) {
if (projectsToProcess == null || projectsToProcess.isEmpty()) {
return Optional.empty();
}
return Optional.of(new ContainedProjectFilter(projectsToProcess));
}

public List<Project> getProjectsToProcess() {
return Collections.unmodifiableList(projectsToProcess);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ public interface ActionProvider {
*/
String COMMAND_TEST_SINGLE = "test.single"; // NOI18N

/**
* Standard command for running tests in parallel on given projects sub-modules
*
* @since 1.99
*/
String COMMAND_TEST_PARALLEL = "test.parallel"; // NOI18N

/**
* Standard command for running the project in debugger
*/
Expand Down
147 changes: 147 additions & 0 deletions ide/projectapi/src/org/netbeans/spi/project/NestedClass.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.spi.project;

import java.util.Objects;
import org.openide.filesystems.FileObject;

/**
* Structure representing an identification of a nested class in a file.
*
* <p>
* <code>NestedClass</code> can be used to represent nested classes within parent class
* Example:
* If we have following structure: ParentClass (parent-of) ChildClass1 (parent-of) ChildClass2,
* for ChildClass1 className field would contain "ChildClass1" and topLevelClassName would contain "ParentClass",
* for ChildClass2 className field would contain "ChildClass1.ChildClass2" and topLevelClassName would contain "ParentClass"
* </p>
*
* @author Dusan Petrovic
*
* @since 1.99
*/
public final class NestedClass {

private final FileObject file;
private final String className;
private final String topLevelClassName;

/**
* Creates a new instance holding the specified identification
* of a nested class.
*
* @param className name of a class inside the file
* @param topLevelClassName top level name of a class inside the file
* @param file file to be kept in the object
* @exception java.lang.IllegalArgumentException
* if the file or class name is {@code null}
* @since 1.99
*/
public NestedClass(String className, String topLevelClassName, FileObject file) {
super();
if (className == null) {
throw new IllegalArgumentException("className is <null>");
}
if (topLevelClassName == null) {
throw new IllegalArgumentException("topLevelClassName is <null>");
}
if (file == null) {
throw new IllegalArgumentException("file is <null>");
}
this.className = className;
this.topLevelClassName = topLevelClassName;
this.file = file;
}

/**
* Returns the file identification.
*
* @return file held by this object
* @since 1.99
*/
public FileObject getFile() {
return file;
}

/**
* Returns name of a nested class within a file.
*
* @return class name held by this object
* @since 1.99
*/
public String getClassName() {
return className;
}

/**
* Returns name of a top level class within a file.
*
* @return top level class name held by this object
* @since 1.99
*/
public String getTopLevelClassName() {
return topLevelClassName;
}

/**
* Returns fully qualified name.
*
* @param packageName name of the package where the class is
*
* @return fully qualified name held by this object
* @since 1.99
*/
public String getFQN(String packageName) {
return String.join(".", packageName, topLevelClassName, className);
}

/**
* Returns fully qualified name.
*
* @param packageName name of the package where the class is
* @param nestedClassSeparator separator for the nested classes
*
* @return fully qualified name held by this object
* @since 1.99
*/
public String getFQN(String packageName, String nestedClassSeparator) {
return String.join(".", packageName, String.join(nestedClassSeparator, topLevelClassName, className.replace(".", nestedClassSeparator)));
}

@Override
public int hashCode() {
int hash = 3;
hash = 41 * hash + Objects.hashCode(this.className);
hash = 41 * hash + Objects.hashCode(this.topLevelClassName);
hash = 41 * hash + Objects.hashCode(this.file);
return hash;
}

@Override
public boolean equals(Object obj) {
if ((obj == null) || (obj.getClass() != NestedClass.class)) {
return false;
}
if (this == obj) {
return true;
}
final NestedClass other = (NestedClass) obj;
return other.file.equals(file) && other.className.equals(className) && other.topLevelClassName.equals(topLevelClassName);
}
}
Loading

0 comments on commit 9d5bc1e

Please sign in to comment.