Skip to content

Commit a92ccdb

Browse files
gdanielAxelRICHARD
authored andcommitted
[2139] Improve performances of integration tests
Bug: #2139 Signed-off-by: Gwendal Daniel <gwendal.daniel@obeosoft.com>
1 parent b3be9f5 commit a92ccdb

24 files changed

Lines changed: 706 additions & 214 deletions

CHANGELOG.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ Stakeholders are by default represented with a dedicated graphical node connecte
7373
- https://github.com/eclipse-syson/syson/issues/2129[#2129] [diagrams] Leverage the latest change of the selection dialog to allow creating a `FlowUsage` from a `ConnectionUsage` without selection a `PayloadFeature`
7474
- https://github.com/eclipse-syson/syson/issues/2105[#2105] [explorer] In the _Explorer_ view, `Expression` elements now display their full textual representation.
7575
- https://github.com/eclipse-syson/syson/issues/2137[#2137] [diagrams] Merge the two objective creation tools into a single tool, leveraging the updated selection dialog.
76+
- https://github.com/eclipse-syson/syson/issues/2139[#2139] [syson] Improve performances of integration tests.
77+
Standard libraries are now cached between tests to speed up editing context creation.
78+
This feature can be de-activated by setting the property `org.eclipse.syson.test.cacheStandardLibraries` to `false` in `application.properties`.
79+
The cache holding standard libraries can be invalidated for a specific test method or test class by using the `@InvalidateStandardLibrariesCache` annotation, ensuring the editing contexts are loaded from scratch.
7680

7781
=== New features
7882

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2024, 2025 Obeo.
2+
* Copyright (c) 2024, 2026 Obeo.
33
* This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -14,24 +14,15 @@
1414

1515
import java.time.Duration;
1616
import java.time.Instant;
17-
import java.util.HashMap;
18-
import java.util.Map;
1917
import java.util.Objects;
20-
import java.util.Optional;
2118

22-
import org.eclipse.emf.common.util.EList;
23-
import org.eclipse.emf.ecore.EObject;
2419
import org.eclipse.emf.ecore.resource.Resource;
2520
import org.eclipse.emf.ecore.resource.ResourceSet;
26-
import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
2721
import org.eclipse.sirius.components.core.api.IEditingContext;
2822
import org.eclipse.sirius.components.core.api.IEditingContextProcessor;
29-
import org.eclipse.sirius.components.emf.ResourceMetadataAdapter;
30-
import org.eclipse.sirius.components.emf.services.IDAdapter;
31-
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
3223
import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext;
33-
import org.eclipse.sirius.emfjson.resource.JsonResource;
3424
import org.eclipse.sirius.web.application.studio.services.api.IStudioCapableEditingContextPredicate;
25+
import org.eclipse.syson.application.services.api.IStandardLibrariesLoader;
3526
import org.eclipse.syson.sysml.util.LibraryNamespaceProvider;
3627
import org.eclipse.syson.util.SysONEContentAdapter;
3728
import org.slf4j.Logger;
@@ -49,12 +40,12 @@ public class SysMLEditingContextProcessor implements IEditingContextProcessor {
4940

5041
private final Logger logger = LoggerFactory.getLogger(SysMLEditingContextProcessor.class);
5142

52-
private final SysONDefaultLibrariesConfiguration defaultLibraries;
53-
5443
private final IStudioCapableEditingContextPredicate studioCapableEditingContextPredicate;
5544

56-
public SysMLEditingContextProcessor(SysONDefaultLibrariesConfiguration standardLibraries, IStudioCapableEditingContextPredicate studioCapableEditingContextPredicate) {
57-
this.defaultLibraries = Objects.requireNonNull(standardLibraries);
45+
private final IStandardLibrariesLoader standardLibrariesLoader;
46+
47+
public SysMLEditingContextProcessor(IStandardLibrariesLoader standardLibrariesLoader, IStudioCapableEditingContextPredicate studioCapableEditingContextPredicate) {
48+
this.standardLibrariesLoader = Objects.requireNonNull(standardLibrariesLoader);
5849
this.studioCapableEditingContextPredicate = Objects.requireNonNull(studioCapableEditingContextPredicate);
5950
}
6051

@@ -65,103 +56,24 @@ public void preProcess(IEditingContext editingContext) {
6556
&& !this.studioCapableEditingContextPredicate.test(editingContext.getId())) {
6657

6758
Instant start = Instant.now();
68-
ResourceSet sourceResourceSet = this.defaultLibraries.getLibrariesResourceSet();
6959
ResourceSet targetResourceSet = siriusWebEditingContext.getDomain().getResourceSet();
7060
targetResourceSet.eAdapters().add(new SysONEContentAdapter());
7161

7262
// Register an adapter to ease the access to Namespaces using their full qualified name stored in Libraries
7363
LibraryNamespaceProvider libraryNamespaceProvider = new LibraryNamespaceProvider(targetResourceSet);
7464
targetResourceSet.eAdapters().add(libraryNamespaceProvider);
7565

76-
// Use a common copier for all the resources to make sure cross-references are correctly copied.
77-
SysONCopier copier = new SysONCopier();
78-
sourceResourceSet.getResources().forEach(sourceResource -> {
79-
Resource targetResource = targetResourceSet.getResource(sourceResource.getURI(), false);
80-
if (targetResource == null) {
81-
Map<String, Object> options = new HashMap<>();
82-
// allows to persist references to standard libraries elements with URI containing elementId instead
83-
// of id from SiriusWeb
84-
options.put(JsonResource.OPTION_FORCE_DEFAULT_REFERENCE_SERIALIZATION, Boolean.TRUE);
85-
targetResource = new JSONResourceFactory().createResource(sourceResource.getURI(), options);
86-
Optional<ResourceMetadataAdapter> resourceAdapter = sourceResource.eAdapters().stream()
87-
.filter(ResourceMetadataAdapter.class::isInstance)
88-
.map(ResourceMetadataAdapter.class::cast)
89-
.findFirst();
90-
if (resourceAdapter.isPresent()) {
91-
targetResource.eAdapters().add(new ResourceMetadataAdapter(resourceAdapter.get().getName(), true));
92-
}
93-
targetResourceSet.getResources().add(targetResource);
94-
EList<EObject> contents = sourceResource.getContents();
95-
for (EObject eObject : contents) {
96-
targetResource.getContents().add(this.copy(eObject, (JsonResource) targetResource, copier));
97-
}
98-
}
99-
});
100-
101-
// Copy all the references after the elements to make sure cross-references are correctly copied.
102-
copier.copyReferences();
66+
this.standardLibrariesLoader.loadStandardLibraries(targetResourceSet);
10367

10468
// At this point only immutable PackageLibraries are present in the ResourceSet so can we register them as
10569
// immutable in the LibraryNamespaceProvider
10670
for (Resource r : targetResourceSet.getResources()) {
10771
libraryNamespaceProvider.addImmutableLibrariesNamespaces(r);
10872
}
73+
10974
Instant finish = Instant.now();
11075
long timeElapsed = Duration.between(start, finish).toMillis();
11176
this.logger.info("Copied all default libraries in the editing context in {} ms", timeElapsed);
11277
}
11378
}
114-
115-
@Override
116-
public void postProcess(IEditingContext editingContext) {
117-
}
118-
119-
private EObject copy(EObject eObject, JsonResource resource, SysONCopier copier) {
120-
copier.setResource(resource);
121-
var result = copier.copy(eObject);
122-
return result;
123-
}
124-
125-
/**
126-
* Copier that also copies the IDAdapter.
127-
*
128-
* @author arichard
129-
*/
130-
private final class SysONCopier extends Copier {
131-
132-
private static final long serialVersionUID = 1L;
133-
134-
private final Logger logger = LoggerFactory.getLogger(SysONCopier.class);
135-
136-
private JsonResource resource;
137-
138-
public void setResource(JsonResource resource) {
139-
this.resource = resource;
140-
}
141-
142-
@Override
143-
public EObject copy(EObject eObject) {
144-
EObject copy = null;
145-
if (this.resource != null) {
146-
copy = super.copy(eObject);
147-
var adapter = this.findIDAdapter(eObject);
148-
if (adapter != null) {
149-
var oldId = adapter.getId().toString();
150-
this.resource.setID(copy, oldId);
151-
}
152-
} else {
153-
this.logger.error("SysONCopier requires a JsonResource to make a copy");
154-
}
155-
return copy;
156-
}
157-
158-
private IDAdapter findIDAdapter(EObject eObject) {
159-
for (var adapter : eObject.eAdapters()) {
160-
if (adapter instanceof IDAdapter idAdapter) {
161-
return idAdapter;
162-
}
163-
}
164-
return null;
165-
}
166-
}
16779
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.application.services;
14+
15+
import java.util.HashMap;
16+
import java.util.Map;
17+
import java.util.Objects;
18+
import java.util.Optional;
19+
20+
import org.eclipse.emf.common.util.EList;
21+
import org.eclipse.emf.ecore.EObject;
22+
import org.eclipse.emf.ecore.resource.Resource;
23+
import org.eclipse.emf.ecore.resource.ResourceSet;
24+
import org.eclipse.emf.ecore.util.EcoreUtil;
25+
import org.eclipse.sirius.components.emf.ResourceMetadataAdapter;
26+
import org.eclipse.sirius.components.emf.services.IDAdapter;
27+
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
28+
import org.eclipse.sirius.emfjson.resource.JsonResource;
29+
import org.eclipse.syson.application.configuration.SysONDefaultLibrariesConfiguration;
30+
import org.eclipse.syson.application.services.api.IStandardLibrariesLoader;
31+
import org.slf4j.Logger;
32+
import org.slf4j.LoggerFactory;
33+
import org.springframework.stereotype.Service;
34+
35+
/**
36+
* Loads SysML and KerML standard libraries into a resource set.
37+
*
38+
* @author gdaniel
39+
*/
40+
@Service
41+
public class StandardLibrariesLoader implements IStandardLibrariesLoader {
42+
43+
private final SysONDefaultLibrariesConfiguration defaultLibraries;
44+
45+
public StandardLibrariesLoader(SysONDefaultLibrariesConfiguration defaultLibraries) {
46+
this.defaultLibraries = Objects.requireNonNull(defaultLibraries);
47+
}
48+
49+
@Override
50+
public void loadStandardLibraries(ResourceSet targetResourceSet) {
51+
ResourceSet sourceResourceSet = this.defaultLibraries.getLibrariesResourceSet();
52+
53+
// Use a common copier for all the resources to make sure cross-references are correctly copied.
54+
SysONCopier copier = new SysONCopier();
55+
sourceResourceSet.getResources().forEach(sourceResource -> {
56+
Resource targetResource = targetResourceSet.getResource(sourceResource.getURI(), false);
57+
if (targetResource == null) {
58+
Map<String, Object> options = new HashMap<>();
59+
// allows to persist references to standard libraries elements with URI containing elementId instead
60+
// of id from SiriusWeb
61+
options.put(JsonResource.OPTION_FORCE_DEFAULT_REFERENCE_SERIALIZATION, Boolean.TRUE);
62+
targetResource = new JSONResourceFactory().createResource(sourceResource.getURI(), options);
63+
Optional<ResourceMetadataAdapter> resourceAdapter = sourceResource.eAdapters().stream()
64+
.filter(ResourceMetadataAdapter.class::isInstance)
65+
.map(ResourceMetadataAdapter.class::cast)
66+
.findFirst();
67+
if (resourceAdapter.isPresent()) {
68+
targetResource.eAdapters().add(new ResourceMetadataAdapter(resourceAdapter.get().getName(), true));
69+
}
70+
targetResourceSet.getResources().add(targetResource);
71+
EList<EObject> contents = sourceResource.getContents();
72+
for (EObject eObject : contents) {
73+
targetResource.getContents().add(this.copy(eObject, (JsonResource) targetResource, copier));
74+
}
75+
}
76+
});
77+
78+
// Copy all the references after the elements to make sure cross-references are correctly copied.
79+
copier.copyReferences();
80+
}
81+
82+
private EObject copy(EObject eObject, JsonResource resource, SysONCopier copier) {
83+
copier.setResource(resource);
84+
var result = copier.copy(eObject);
85+
return result;
86+
}
87+
88+
/**
89+
* Copier that also copies the IDAdapter.
90+
*
91+
* @author arichard
92+
*/
93+
private final class SysONCopier extends EcoreUtil.Copier {
94+
95+
private static final long serialVersionUID = 1L;
96+
97+
private final Logger logger = LoggerFactory.getLogger(SysONCopier.class);
98+
99+
private JsonResource resource;
100+
101+
public void setResource(JsonResource resource) {
102+
this.resource = resource;
103+
}
104+
105+
@Override
106+
public EObject copy(EObject eObject) {
107+
EObject copy = null;
108+
if (this.resource != null) {
109+
copy = super.copy(eObject);
110+
var adapter = this.findIDAdapter(eObject);
111+
if (adapter != null) {
112+
var oldId = adapter.getId().toString();
113+
this.resource.setID(copy, oldId);
114+
}
115+
} else {
116+
this.logger.error("SysONCopier requires a JsonResource to make a copy");
117+
}
118+
return copy;
119+
}
120+
121+
private IDAdapter findIDAdapter(EObject eObject) {
122+
for (var adapter : eObject.eAdapters()) {
123+
if (adapter instanceof IDAdapter idAdapter) {
124+
return idAdapter;
125+
}
126+
}
127+
return null;
128+
}
129+
}
130+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.application.services.api;
14+
15+
import org.eclipse.emf.ecore.resource.ResourceSet;
16+
17+
/**
18+
* Loads SysML and KerML standard libraries into a resource set.
19+
*
20+
* @author gdaniel
21+
*/
22+
public interface IStandardLibrariesLoader {
23+
24+
void loadStandardLibraries(ResourceSet targetResourceSet);
25+
}

backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/configuration/SysMLEditingContextProcessorTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2024, 2025 Obeo.
2+
* Copyright (c) 2024, 2026 Obeo.
33
* This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -35,6 +35,7 @@
3535
import org.eclipse.sirius.components.emf.ResourceMetadataAdapter;
3636
import org.eclipse.sirius.web.application.editingcontext.EditingContext;
3737
import org.eclipse.syson.application.libraries.SysONLibraryLoader;
38+
import org.eclipse.syson.application.services.StandardLibrariesLoader;
3839
import org.eclipse.syson.util.SysONEContentAdapter;
3940
import org.junit.jupiter.api.BeforeAll;
4041
import org.junit.jupiter.api.Test;
@@ -63,7 +64,7 @@ static void loadLibraries() {
6364
resourceSet.setPackageRegistry(ePackageRegistry);
6465
resourceSet.eAdapters().add(new ECrossReferenceAdapter());
6566
EditingContext editingContext = new EditingContext(UUID.randomUUID().toString(), editingDomain, Map.of(), List.of());
66-
SysMLEditingContextProcessor editingContextProcessor = new SysMLEditingContextProcessor(new SysONDefaultLibrariesConfiguration(new SysONLoadDefaultLibrariesOnApplicationStartConfiguration()),
67+
SysMLEditingContextProcessor editingContextProcessor = new SysMLEditingContextProcessor(new StandardLibrariesLoader(new SysONDefaultLibrariesConfiguration(new SysONLoadDefaultLibrariesOnApplicationStartConfiguration())),
6768
e -> false);
6869
editingContextProcessor.preProcess(editingContext);
6970
assertNotNull(resourceSet);
@@ -113,7 +114,7 @@ public void preProcessStudioEditingContext() {
113114
rSet.setPackageRegistry(ePackageRegistry);
114115
rSet.eAdapters().add(new ECrossReferenceAdapter());
115116
EditingContext editingContext = new EditingContext(UUID.randomUUID().toString(), editingDomain, Map.of(), List.of());
116-
SysMLEditingContextProcessor editingContextProcessor = new SysMLEditingContextProcessor(new SysONDefaultLibrariesConfiguration(new SysONLoadDefaultLibrariesOnApplicationStartConfiguration()),
117+
SysMLEditingContextProcessor editingContextProcessor = new SysMLEditingContextProcessor(new StandardLibrariesLoader(new SysONDefaultLibrariesConfiguration(new SysONLoadDefaultLibrariesOnApplicationStartConfiguration())),
117118
e -> true);
118119
editingContextProcessor.preProcess(editingContext);
119120

backend/application/syson-application/src/main/resources/application-dev.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
server.port=8080
2121
spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
22+
logging.level.org.eclipse.sirius.web=debug
23+
logging.level.org.eclipse.syson.test.performance=debug
2224
logging.level.org.eclipse.sirius.web.diagrams.layout.LayoutService=OFF
2325

2426
##################################################

backend/application/syson-application/src/main/resources/application.properties

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ spring.servlet.multipart.max-file-size=256MB
2626
spring.servlet.multipart.max-request-size=256MB
2727
spring.servlet.multipart.enabled=true
2828

29-
logging.level.org.eclipse.sirius.web=debug
30-
3129
sirius.components.cors.allowedOriginPatterns=*
3230
sirius.components.cors.allowedCredentials=true
3331
logging.level.org.eclipse.sirius.web.diagrams.layout.LayoutService=OFF
@@ -69,3 +67,18 @@ org.eclipse.syson.show.diagrams.inherited.members.from.standard.libraries=false
6967
# rights.
7068
##################################################
7169
#org.eclipse.syson.syside.path=add_path_to_your_syside-cli.js
70+
71+
##################################################
72+
#
73+
# SYSON OPTION TO CACHE STANDARD LIBRARIES IN TESTS
74+
#
75+
##################################################
76+
org.eclipse.syson.test.cacheStandardLibraries=true
77+
78+
##################################################
79+
#
80+
# Logging group for test performances
81+
#
82+
##################################################
83+
logging.group.org.eclipse.syson.test.performance=org.eclipse.syson.services.EditingContextCachingService,org.eclipse.syson.services.CachedStandardLibrariesLoader
84+

0 commit comments

Comments
 (0)