Skip to content

Commit

Permalink
Merge pull request #3668 from nscuro/jerseytest-speedup
Browse files Browse the repository at this point in the history
Start Jersey `TestContainer` once per class vs. once per test method
  • Loading branch information
nscuro authored May 2, 2024
2 parents 214ca77 + e57beda commit 1edf31b
Show file tree
Hide file tree
Showing 36 changed files with 879 additions and 924 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void contextDestroyed(final ServletContextEvent event) {
/**
* Loads the default licenses into the database if no license data exists.
*/
private void loadDefaultLicenses() {
public void loadDefaultLicenses() {
try (QueryManager qm = new QueryManager()) {
LOGGER.info("Synchronizing SPDX license definitions to datastore");

Expand Down Expand Up @@ -120,7 +120,7 @@ private void loadDefaultLicenseGroups() {
/**
* Loads the default permissions
*/
private void loadDefaultPermissions() {
public void loadDefaultPermissions() {
try (QueryManager qm = new QueryManager()) {
LOGGER.info("Synchronizing permissions to datastore");
for (final Permissions permission : Permissions.values()) {
Expand Down Expand Up @@ -197,7 +197,7 @@ private List<Permission> getAutomationPermissions(final List<Permission> fullLis
/**
* Loads the default repositories
*/
private void loadDefaultRepositories() {
public void loadDefaultRepositories() {
try (QueryManager qm = new QueryManager()) {
LOGGER.info("Synchronizing default repositories to datastore");
qm.createRepository(RepositoryType.CPAN, "cpan-public-registry", "https://fastapi.metacpan.org/v1/", true, false, false, null, null);
Expand Down Expand Up @@ -236,7 +236,7 @@ private void loadDefaultConfigProperties() {
/**
* Loads the default notification publishers
*/
private void loadDefaultNotificationPublishers() {
public void loadDefaultNotificationPublishers() {
try (QueryManager qm = new QueryManager()) {
LOGGER.info("Synchronizing notification publishers to datastore");
for (final DefaultNotificationPublishers publisher : DefaultNotificationPublishers.values()) {
Expand Down
87 changes: 87 additions & 0 deletions src/test/java/org/dependencytrack/JerseyTestRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* This file is part of Dependency-Track.
*
* Licensed 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.
*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) OWASP Foundation. All Rights Reserved.
*/
package org.dependencytrack;

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.rules.ExternalResource;

import javax.ws.rs.client.WebTarget;

/**
* @since 4.11.0
*/
public class JerseyTestRule extends ExternalResource {

private final JerseyTest jerseyTest;

public JerseyTestRule(final ResourceConfig resourceConfig) {
this.jerseyTest = new JerseyTest() {

@Override
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new DTGrizzlyWebTestContainerFactory();
}

@Override
protected void configureClient(final ClientConfig config) {
// Prevent InaccessibleObjectException with JDK >= 16 when performing PATCH requests
// using the default HttpUrlConnection connector provider.
// See https://github.com/eclipse-ee4j/jersey/issues/4825
config.connectorProvider(new GrizzlyConnectorProvider());
}

@Override
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext.forServlet(new ServletContainer(resourceConfig)).build();
}

};
}

@Override
protected void before() throws Throwable {
jerseyTest.setUp();
}

@Override
protected void after() {
try {
jerseyTest.tearDown();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public WebTarget target() {
return jerseyTest.target();
}

public final WebTarget target(final String path) {
return jerseyTest.target(path);
}

}
34 changes: 5 additions & 29 deletions src/test/java/org/dependencytrack/ResourceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,12 @@
package org.dependencytrack;

import alpine.Config;
import alpine.model.ManagedUser;
import alpine.model.Permission;
import alpine.model.Team;
import alpine.server.auth.JsonWebToken;
import alpine.server.auth.PasswordService;
import alpine.server.persistence.PersistenceManagerFactory;
import org.dependencytrack.auth.Permissions;
import org.dependencytrack.persistence.QueryManager;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
Expand All @@ -44,7 +38,7 @@
import java.util.ArrayList;
import java.util.List;

public abstract class ResourceTest extends JerseyTest {
public abstract class ResourceTest {

protected final String V1_ANALYSIS = "/v1/analysis";
protected final String V1_BADGE = "/v1/badge";
Expand Down Expand Up @@ -84,12 +78,12 @@ public abstract class ResourceTest extends JerseyTest {
protected final String SIZE = "size";
protected final String TOTAL_COUNT_HEADER = "X-Total-Count";
protected final String X_API_KEY = "X-Api-Key";

protected final String V1_TAG = "/v1/tag";

// Hashing is expensive. Do it once and re-use across tests as much as possible.
protected static final String TEST_USER_PASSWORD_HASH = new String(PasswordService.createHash("testuser".toCharArray()));

protected QueryManager qm;
protected ManagedUser testUser;
protected String jwt;
protected Team team;
protected String apiKey;

Expand All @@ -102,15 +96,12 @@ public static void init() {
public void before() throws Exception {
// Add a test user and team with API key. Optional if this is used, but its available to all tests.
this.qm = new QueryManager();
testUser = qm.createManagedUser("testuser", String.valueOf(PasswordService.createHash("testuser".toCharArray())));
this.jwt = new JsonWebToken().createToken(testUser);
team = qm.createTeam("Test Users", true);
qm.addUserToTeam(testUser, team);
this.apiKey = team.getApiKeys().get(0).getKey();
}

@After
public void after() {
public void after() throws Exception {
// PersistenceManager will refuse to close when there's an active transaction
// that was neither committed nor rolled back. Unfortunately some areas of the
// code base can leave such a broken state behind if they run into unexpected
Expand All @@ -123,28 +114,13 @@ public void after() {
PersistenceManagerFactory.tearDown();
}

@Override
protected TestContainerFactory getTestContainerFactory() {
return new DTGrizzlyWebTestContainerFactory();
}

@Override
protected void configureClient(final ClientConfig config) {
// Prevent InaccessibleObjectException with JDK >= 16 when performing PATCH requests
// using the default HttpUrlConnection connector provider.
// See https://github.com/eclipse-ee4j/jersey/issues/4825
config.connectorProvider(new GrizzlyConnectorProvider());
}

public void initializeWithPermissions(Permissions... permissions) {
List<Permission> permissionList = new ArrayList<>();
for (Permissions permission: permissions) {
permissionList.add(qm.createPermission(permission.name(), null));
}
testUser.setPermissions(permissionList);
team.setPermissions(permissionList);
qm.persist(team);
testUser = qm.persist(testUser);
}

protected String getPlainTextBody(Response response) {
Expand Down
Loading

0 comments on commit 1edf31b

Please sign in to comment.