Skip to content
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

Template healthcheck + integration test improvements and fixes #3616 #3822

Merged
merged 13 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions gradle/build-java.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,6 @@ subprojects{
}

test {
filter {
excludeTestsMatching "*ManualTest"
excludeTestsMatching "*IntTest"
}

/* Per default GRADLE stops the build if one single test fails. We want to have all tests executed. */
ignoreFailures = true
Expand Down
6 changes: 4 additions & 2 deletions sechub-api-java/fullRegenerateOpenAPIClassFiles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
# again with necessary system properties defined!
set -e


echo "-----------------------------------"
echo "Regenerate OpenAPI class files"
echo "-----------------------------------"
Expand All @@ -29,5 +28,8 @@ echo "- generate open api file"
echo "- generate sechub java api"

cd ..
./gradlew spotlessApply generateOpenapi
echo ">> Generate OpenAPI (sechub-openapi-java-client)"
./gradlew spotlessApply generateOpenapi

echo ">> Generate OpenAPI (sechub-api-java) [DEPRECATED]"
./gradlew :sechub-api-java:build -Dsechub.build.stage=all
Original file line number Diff line number Diff line change
Expand Up @@ -858,4 +858,12 @@ public File downloadAssetFile(String assetId, String fileName) {
return asTestUser().downloadAssetFile(assetId, fileName);
}

public String executeTemplatesHealthCheck() {
return asTestUser().executeTemplatesHealthcheck().toFormattedJSON();
}

public void deleteTemplate(String templateId) {
asTestUser().deleteTemplate(templateId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ public class DeveloperProjectDetailInformation implements JSONable<DeveloperProj
public static final String PROPERTY_OWNER = "owner";
public static final String PROPERTY_ACCESSLEVEL = "accessLevel";
public static final String PROPERTY_DESCRIPTION = "description";
public static final String PROPERTY_TEMPLATE_IDS = "templateIds";

private String projectId;

private List<String> users = new ArrayList<>();
private List<String> whitelist = new ArrayList<>();
private Map<String, String> metaData = new HashMap<>();
private List<String> templateIds = new ArrayList<>();;
private String owner;
private String description;
private String accessLevel;
Expand Down Expand Up @@ -58,6 +60,10 @@ public String getAccessLevel() {
return accessLevel;
}

public List<String> getTemplateIds() {
return templateIds;
}

@Override
public Class<DeveloperProjectDetailInformation> getJSONTargetClass() {
return DeveloperProjectDetailInformation.class;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@
import com.mercedesbenz.sechub.developertools.admin.ui.action.status.ListStatusEntriesAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.template.AssignTemplateToProjectAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.template.CreateOrUpdateTemplateAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.template.DeleteTemplateAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.template.ExecuteTemplatesHealthcheckAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.template.FetchAllTemplateIdentifiersAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.template.ShowTemplatesOverviewAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.template.UnassignTemplateFromProjectAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.user.AcceptUserSignupAction;
import com.mercedesbenz.sechub.developertools.admin.ui.action.user.AnonymousRequestNewAPITokenUserAction;
Expand Down Expand Up @@ -260,10 +263,14 @@ public void createConfigMenu() {
menu.add(templatesMenu);
add(templatesMenu, new CreateOrUpdateTemplateAction(context));
add(templatesMenu, new FetchAllTemplateIdentifiersAction(context));

templatesMenu.addSeparator();
add(templatesMenu, new AssignTemplateToProjectAction(context));
add(templatesMenu, new UnassignTemplateFromProjectAction(context));

templatesMenu.addSeparator();
add(templatesMenu, new DeleteTemplateAction(context));
templatesMenu.addSeparator();
add(templatesMenu, new ShowTemplatesOverviewAction(context));
add(templatesMenu, new ExecuteTemplatesHealthcheckAction(context));
menu.add(new ManageAssetsAction(context));

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.slf4j.LoggerFactory;

import com.mercedesbenz.sechub.developertools.JSONDeveloperHelper;
import com.mercedesbenz.sechub.developertools.admin.DeveloperAdministration;
import com.mercedesbenz.sechub.developertools.admin.ErrorHandler;
import com.mercedesbenz.sechub.developertools.admin.ui.ConfigurationSetup;
import com.mercedesbenz.sechub.developertools.admin.ui.OutputUI;
Expand Down Expand Up @@ -58,6 +59,10 @@ protected UIContext getContext() {
return context;
}

protected DeveloperAdministration getAdministration() {
return getContext().getAdministration();
}

/**
* SecHub uses always lower cased identifier - this method is a helper.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import com.mercedesbenz.sechub.developertools.admin.ui.UIContext;
import com.mercedesbenz.sechub.developertools.admin.ui.action.AbstractUIAction;
import com.mercedesbenz.sechub.integrationtest.api.IntegrationTestSetup;
import com.mercedesbenz.sechub.integrationtest.api.IntegrationTestSupport;
import com.mercedesbenz.sechub.integrationtest.internal.IntegrationTestContext;

/**
Expand Down Expand Up @@ -46,7 +46,7 @@ private boolean checkIntegrationTestServerRunning() {
integrationTestContext.setPort(getContext().getPort());

String isAliveURL = integrationTestContext.getUrlBuilder().buildIntegrationTestIsAliveUrl();
if (!Boolean.TRUE.equals(IntegrationTestSetup.fetchTestServerStatus(isAliveURL))) {
if (!Boolean.TRUE.equals(IntegrationTestSupport.fetchTestServerStatus(isAliveURL))) {
warn("You are not running an integration test server, so cannot exeucte action!");
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.developertools.admin.ui.action.template;

import java.awt.event.ActionEvent;
import java.util.Optional;

import com.mercedesbenz.sechub.developertools.admin.ui.UIContext;
import com.mercedesbenz.sechub.developertools.admin.ui.action.AbstractUIAction;
import com.mercedesbenz.sechub.developertools.admin.ui.cache.InputCacheIdentifier;

public class DeleteTemplateAction extends AbstractUIAction {
private static final long serialVersionUID = 1L;

public DeleteTemplateAction(UIContext context) {
super("Delete template", context);
}

@Override
public void execute(ActionEvent e) {
Optional<String> templateIdOpt = getUserInput("Please enter templateId", InputCacheIdentifier.TEMPLATE_ID);
if (!templateIdOpt.isPresent()) {
return;
}
String templateId = templateIdOpt.get();
boolean confirmed = confirm("Do you really want to delete template '" + templateId + "' ?");
if (!confirmed) {
output("Canceled by user");
return;
}
getContext().getAdministration().deleteTemplate(templateId);

outputAsTextOnSuccess("Template: " + templateId + " was deleted!");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.developertools.admin.ui.action.template;

import java.awt.event.ActionEvent;

import com.mercedesbenz.sechub.developertools.admin.ui.UIContext;
import com.mercedesbenz.sechub.developertools.admin.ui.action.AbstractUIAction;

public class ExecuteTemplatesHealthcheckAction extends AbstractUIAction {
private static final long serialVersionUID = 1L;

public ExecuteTemplatesHealthcheckAction(UIContext context) {
super("Execute templates healthcheck", context);
}

@Override
public void execute(ActionEvent e) {

String data = getContext().getAdministration().executeTemplatesHealthCheck();
outputAsBeautifiedJSONOnSuccess(data);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.developertools.admin.ui.action.template;

import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;

import com.mercedesbenz.sechub.commons.model.template.TemplateDefinition;
import com.mercedesbenz.sechub.developertools.admin.DeveloperProjectDetailInformation;
import com.mercedesbenz.sechub.developertools.admin.ui.UIContext;
import com.mercedesbenz.sechub.developertools.admin.ui.action.AbstractUIAction;

public class ShowTemplatesOverviewAction extends AbstractUIAction {
private static final long serialVersionUID = 1L;

public ShowTemplatesOverviewAction(UIContext context) {
super("Create template overview", context);
}

@Override
public void execute(ActionEvent e) {

List<String> projects = getAdministration().fetchProjectIdList();
List<DeveloperProjectDetailInformation> projectDetails = new ArrayList<>();
List<String> templates = getAdministration().fetchAllTemplateIdentifiers();

for (String projectId : projects) {
DeveloperProjectDetailInformation detail = getAdministration().fetchProjectDetailInformation(projectId);
projectDetails.add(detail);
}
output("Templates:");

for (String templateId : templates) {
output(" templateId:'" + templateId + "'");
List<String> templateAssginedToProjects = new ArrayList<>();
TemplateDefinition templateDefinition = getContext().getAdministration().fetchTemplateOrNull(templateId);
if (templateDefinition == null) {
error("Template definition for template: " + templateId + " was not found!");
} else {
for (DeveloperProjectDetailInformation projectDetail : projectDetails) {
if (projectDetail.getTemplateIds().contains(templateId)) {
templateAssginedToProjects.add(projectDetail.getProjectId());
}
}
}
output(" assigned to projects: " + templateAssginedToProjects);

}

}

}
3 changes: 3 additions & 0 deletions sechub-doc/openapi-workaround.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ stringType.put("type", "string")
Remark: if you still find any `oneOf` elements inside the `openApi3.json` file you have
to fix another one this inside this gradle file!
Remark 2025-01-30, de-jcup: This ugly workaround gradle file will be removed completely
when we switch to use sechub-openapi-java-client only!!!
*/
void postProcessOpenApiGeneration(){

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,16 @@ with
-Dsechub.integrationtest.running=true
----
Some integration tests are long running. These tests are only run when you set
----
-Dsechub.integrationtest.longrunning=true
----
[TIP]
====
To make things easier there is the possibility to define system properties also
inside file:
`~/.sechub/sechub-developer.properties`
So you can easily switch or enable all by enabling dedicated system property.
This file is used inside integration tests automatically.
If you add a line with `sechub.integrationtest.running=true` to this file, you do not
need to set the system property for every integration test launch configuration...
====
====== Console
Next line starts integration test server, execute tests and automatically stops
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,15 +394,54 @@ TIP: For an example look into `JobRepositoryDBTest`
===== Integration tests
In project `sechub-integrationtest` full integration tests are settled.
The project needs a running server in profile `integrationtest`.
For more details about those tests read the `README.md` file inside

====== Example for an integration test
[source, java]
----
import static com.mercedesbenz.sechub.integrationtest.api.TestAPI.*;
import org.junit.jupiter.api.Test;
import com.mercedesbenz.sechub.integrationtest.api.IntegrationTestExtension;
import com.mercedesbenz.sechub.integrationtest.api.WithTestScenario;
@ExtendWith(IntegrationTestExtension.class)//<1>
@WithTestScenario(Scenario6.class)//<2>
public class ExampleIntTest {
@Test
void example_doing_some_test_stuff(){
// now use the TestAPI methods to test your wanted stuff
}
}
----
<1> Annotation used to mark this test as a {sechub} Integration Test
<2> Annotation used to select the scenario to use inside the integration test.
(Scenarios are predefined and use an automated setup with test data which
will be always cleaned up and provided automatically)

[TIP]
====
For more details about those tests inspect existing tests. You can also read the `README.md` file inside
projects root folder.
====

[IMPORTANT]
====
There are old existing integration tests which are not using the Junit5 extension `IntegrationTestExtension`
but the old Junit4 rule `IntegrationTestSetup`. Those old junit4 tests shall be replaced step by step (in future with
the new Junit5 way).
**New integration tests shall always use the new Junit5 annotations.**
New assert methods created for TestAPI shall use Junit5 only as well.
====


====== Integration tests using RestAPI
These tests will be called `${name}Scenario${n}IntTest.java`

====== Integration tests using SecHubClient
Some integration tests do need a build SecHub client and execute the client.
These tests will be called `${name}Scenario${n}SecHubClientIntTest.java`

TIP: If these tests are failing, please check you have called `gradlew buildGo` before,
otherwise no {sechub} client is available for testing...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,8 @@ Other SecHub server integration tests can be run in the same way.
+
image::eclipse-run-server-integrationtest.png[]
. Your first run will fail, as the run needs to be configured with the variables `-Dsechub.integrationtest.running=true` or `-Dsechub.integrationtest.longrunning=true`.
Therefor open the run configurations and select the `UserRegistrationScenario1IntTest`.
. Your first run will fail, as the run needs to be configured with the variables `-Dsechub.integrationtest.running=true`.
Therefore open the run configurations and select the `UserRegistrationScenario1IntTest`.
Click on the `Arguments` tab and paste the flag `-Dsechub.integrationtest.running=true` in the VM arguments field, click apply and run the test again.
image::eclipse-add-VM-argument-to-UnitTest.png[]
Expand Down Expand Up @@ -690,8 +690,8 @@ Other SecHub server integration tests can be run in the same way.
. Right-click on `UserRegistrationScenario1IntTest.java` to open the context menu and select `test`.
. Your first run will fail, as the run needs to be configured with the variables `-Dsechub.integrationtest.running=true` or `-Dsechub.integrationtest.longrunning=true`.
Therefor open the run configurations and select the `UserRegistrationScenario1IntTest`.
. Your first run will fail, as the run needs to be configured with the variables `-Dsechub.integrationtest.running=true`.
Therefore open the run configurations and select the `UserRegistrationScenario1IntTest`.
Click on the `Add VM options` tab and paste the flag `-Dsechub.integrationtest.running=true` in the VM arguments field, click apply and run the test again.
. Check the JUnit tab, the result should be green indicating a successful run.
Expand Down
Loading
Loading