Skip to content

Commit eb000cf

Browse files
authored
Move ComponentsTest.java to the new testsuite (#41169)
Part of: #34494 Signed-off-by: Simon Vacek <[email protected]>
1 parent 57d26fb commit eb000cf

File tree

10 files changed

+143
-94
lines changed

10 files changed

+143
-94
lines changed

testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ComponentsTest.java renamed to tests/base/src/test/java/org/keycloak/tests/admin/ComponentsTest.java

Lines changed: 113 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,43 @@
1515
* limitations under the License.
1616
*/
1717

18-
package org.keycloak.testsuite.admin;
18+
package org.keycloak.tests.admin;
1919

20+
import jakarta.ws.rs.core.Response;
2021
import org.apache.commons.lang3.RandomStringUtils;
2122
import org.apache.commons.lang3.StringUtils;
2223
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
2324
import org.hamcrest.Matchers;
24-
import org.junit.Before;
25-
import org.junit.Test;
25+
import org.jboss.logging.Logger;
26+
import org.junit.jupiter.api.BeforeEach;
27+
import org.junit.jupiter.api.Test;
2628
import org.keycloak.admin.client.resource.ComponentResource;
2729
import org.keycloak.admin.client.resource.ComponentsResource;
2830
import org.keycloak.admin.client.resource.RealmResource;
2931
import org.keycloak.common.util.MultivaluedHashMap;
32+
import org.keycloak.component.ComponentModel;
33+
import org.keycloak.models.RealmModel;
3034
import org.keycloak.models.utils.KeycloakModelUtils;
31-
import org.keycloak.representations.idm.*;
32-
import org.keycloak.testsuite.components.TestProvider;
35+
import org.keycloak.provider.ProviderFactory;
36+
import org.keycloak.representations.idm.AdminEventRepresentation;
37+
import org.keycloak.representations.idm.ComponentRepresentation;
38+
import org.keycloak.representations.idm.ErrorRepresentation;
39+
import org.keycloak.testframework.annotations.InjectAdminEvents;
40+
import org.keycloak.testframework.annotations.InjectRealm;
41+
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
42+
import org.keycloak.testframework.events.AdminEvents;
43+
import org.keycloak.testframework.injection.LifeCycle;
44+
import org.keycloak.testframework.realm.ManagedRealm;
45+
import org.keycloak.testframework.remote.providers.runonserver.FetchOnServer;
46+
import org.keycloak.testframework.remote.providers.runonserver.FetchOnServerWrapper;
47+
import org.keycloak.testframework.remote.runonserver.InjectRunOnServer;
48+
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
49+
import org.keycloak.testframework.server.KeycloakServerConfig;
50+
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
51+
import org.keycloak.testsuite.components.TestComponentProvider;
52+
import org.keycloak.testsuite.components.TestComponentProviderFactory;
53+
import org.keycloak.tests.utils.admin.ApiUtil;
3354

34-
import jakarta.ws.rs.WebApplicationException;
35-
import jakarta.ws.rs.core.Response;
3655
import java.util.Collections;
3756
import java.util.List;
3857
import java.util.Map;
@@ -41,28 +60,41 @@
4160
import java.util.concurrent.Executors;
4261
import java.util.concurrent.TimeUnit;
4362
import java.util.function.BiConsumer;
63+
import java.util.stream.Collectors;
4464

4565
import static org.hamcrest.MatcherAssert.assertThat;
4666
import static org.hamcrest.Matchers.contains;
4767
import static org.hamcrest.Matchers.containsString;
4868
import static org.hamcrest.Matchers.equalTo;
4969
import static org.hamcrest.Matchers.not;
50-
import static org.junit.Assert.assertEquals;
51-
import static org.junit.Assert.assertFalse;
52-
import static org.junit.Assert.assertNotNull;
53-
import static org.junit.Assert.assertTrue;
54-
import static org.junit.Assert.fail;
70+
import static org.junit.jupiter.api.Assertions.assertEquals;
71+
import static org.junit.jupiter.api.Assertions.assertFalse;
72+
import static org.junit.jupiter.api.Assertions.assertNotNull;
73+
import static org.junit.jupiter.api.Assertions.assertTrue;
74+
import static org.junit.jupiter.api.Assertions.fail;
5575

5676
/**
5777
* @author <a href="mailto:[email protected]">Stian Thorgersen</a>
5878
*/
59-
public class ComponentsTest extends AbstractAdminTest {
79+
@KeycloakIntegrationTest(config = ComponentsTest.ComponentsTestServerConfig.class)
80+
public class ComponentsTest {
81+
82+
@InjectRealm(lifecycle = LifeCycle.METHOD)
83+
ManagedRealm managedRealm;
84+
85+
@InjectRunOnServer
86+
RunOnServerClient runOnServer;
87+
88+
@InjectAdminEvents
89+
AdminEvents adminEvents;
90+
91+
private static final Logger log = Logger.getLogger(ComponentsTest.class);
6092

6193
private ComponentsResource components;
6294

63-
@Before
95+
@BeforeEach
6496
public void before() throws Exception {
65-
components = adminClient.realm(REALM_NAME).components();
97+
components = managedRealm.admin().components();
6698
}
6799

68100
private volatile CountDownLatch remainingDeleteSubmissions;
@@ -81,9 +113,9 @@ private void testConcurrency(BiConsumer<ExecutorService, Integer> taskCreator) t
81113
}
82114

83115
try {
84-
assertTrue("Did not create all components in time", this.remainingDeleteSubmissions.await(100, TimeUnit.SECONDS));
116+
assertTrue(this.remainingDeleteSubmissions.await(100, TimeUnit.SECONDS), "Did not create all components in time");
85117
s.shutdown();
86-
assertTrue("Did not finish before timeout", s.awaitTermination(100, TimeUnit.SECONDS));
118+
assertTrue(s.awaitTermination(100, TimeUnit.SECONDS), "Did not finish before timeout");
87119
} finally {
88120
s.shutdownNow();
89121
}
@@ -116,7 +148,7 @@ public void testNotDeadlocked() {
116148
rep.getConfig().putSingle("required", "required-value");
117149
createComponent(rep);
118150

119-
List<ComponentRepresentation> list = realm.components().query(realmId, TestProvider.class.getName());
151+
List<ComponentRepresentation> list = components.query(managedRealm.getId(), TestComponentProvider.class.getName());
120152
assertEquals(i + 1, list.size());
121153
}
122154
}
@@ -126,21 +158,13 @@ public void testCreateValidation() {
126158
ComponentRepresentation rep = createComponentRepresentation("mycomponent");
127159

128160
// Check validation is invoked
129-
try {
130-
createComponent(rep);
131-
} catch (WebApplicationException e) {
132-
assertError(e.getResponse(), "'Required' is required");
133-
}
161+
createComponentAndAssertError(rep, "'Required' is required");
134162

135163
rep.getConfig().putSingle("required", "Required");
136164
rep.getConfig().putSingle("number", "invalid");
137165

138166
// Check validation is invoked
139-
try {
140-
createComponent(rep);
141-
} catch (WebApplicationException e) {
142-
assertError(e.getResponse(), "'Number' should be a number");
143-
}
167+
createComponentAndAssertError(rep, "'Number' should be a number");
144168
}
145169

146170
@Test
@@ -193,8 +217,6 @@ public void failCreateWithLongName() {
193217

194218
rep.getConfig().addFirst("required", "foo");
195219

196-
ComponentsResource components = realm.components();
197-
198220
try (Response response = components.add(rep)) {
199221
if (Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() == response.getStatus()) {
200222
// using database should fail due to constraint violations
@@ -290,11 +312,11 @@ public void testSecretConfig() throws Exception {
290312
assertEquals(ComponentRepresentation.SECRET_VALUE, returned.getConfig().getFirst("secret"));
291313

292314
// Check secret not leaked in admin events
293-
AdminEventRepresentation event = testingClient.testing().pollAdminEvent();
315+
AdminEventRepresentation event = adminEvents.poll();
294316
assertFalse(event.getRepresentation().contains("some secret value!!"));
295317
assertTrue(event.getRepresentation().contains(ComponentRepresentation.SECRET_VALUE));
296318

297-
Map<String, TestProvider.DetailsRepresentation> details = testingClient.testing(REALM_NAME).getTestComponentDetails();
319+
Map<String, TestComponentProvider.DetailsRepresentation> details = runOnServer.fetch(new TestComponents()).componentsDetailsMap();
298320

299321
// Check value is set correctly
300322
assertEquals("some secret value!!", details.get("mycomponent").getConfig().get("secret").get(0));
@@ -306,19 +328,19 @@ public void testSecretConfig() throws Exception {
306328
assertEquals(ComponentRepresentation.SECRET_VALUE, returned2.getConfig().getFirst("secret"));
307329

308330
// Check secret not leaked in admin events
309-
event = testingClient.testing().pollAdminEvent();
331+
event = adminEvents.poll();
310332
assertThat(event.getRepresentation(), not(containsString("some secret value!!")));
311333
assertThat(event.getRepresentation(), containsString(ComponentRepresentation.SECRET_VALUE));
312334

313335
// Check secret value is not set to '*********'
314-
details = testingClient.testing(REALM_NAME).getTestComponentDetails();
336+
details = runOnServer.fetch(new TestComponents()).componentsDetailsMap();
315337
assertEquals("some secret value!!", details.get("mycomponent").getConfig().get("secret").get(0));
316338

317339
returned2.getConfig().putSingle("secret", "updated secret value!!");
318340
components.component(id).update(returned2);
319341

320342
// Check secret value is updated
321-
details = testingClient.testing(REALM_NAME).getTestComponentDetails();
343+
details = runOnServer.fetch(new TestComponents()).componentsDetailsMap();
322344
assertEquals("updated secret value!!", details.get("mycomponent").getConfig().get("secret").get(0));
323345

324346
ComponentRepresentation returned3 = components.query().stream().filter(c -> c.getId().equals(returned2.getId())).findFirst().get();
@@ -329,7 +351,7 @@ public void testSecretConfig() throws Exception {
329351
components.component(id).update(returned2);
330352

331353
// Check secret value is updated
332-
details = testingClient.testing(REALM_NAME).getTestComponentDetails();
354+
details = runOnServer.fetch(new TestComponents()).componentsDetailsMap();
333355
assertThat(details.get("mycomponent").getConfig().get("secret"), contains("${vault.value}"));
334356

335357
ComponentRepresentation returned4 = components.query().stream().filter(c -> c.getId().equals(returned2.getId())).findFirst().get();
@@ -381,27 +403,20 @@ public void testLongValueInComponentConfigExtLatin() throws Exception {
381403
assertEquals(value, returned.getConfig().getFirst("val1"));
382404
}
383405

384-
private java.lang.String createComponent(ComponentRepresentation rep) {
385-
return createComponent(realm, rep);
406+
private String createComponent(ComponentRepresentation rep) {
407+
return createComponent(managedRealm.admin(), rep);
386408
}
387409

388410
private String createComponent(RealmResource realm, ComponentRepresentation rep) {
389-
Response response = null;
390-
try {
391-
ComponentsResource components = realm.components();
392-
response = components.add(rep);
393-
String id = ApiUtil.getCreatedId(response);
394-
getCleanup(realm.toRepresentation().getRealm()).addComponentId(id);
395-
return id;
396-
} finally {
397-
if (response != null) {
398-
response.bufferEntity();
399-
response.close();
400-
}
401-
}
411+
ComponentsResource components = realm.components();
412+
Response response = components.add(rep);
413+
return ApiUtil.getCreatedId(response);
402414
}
403415

404-
private void assertError(Response response, String error) {
416+
private void createComponentAndAssertError(ComponentRepresentation rep, String error) {
417+
ComponentsResource components = managedRealm.admin().components();
418+
Response response = components.add(rep);
419+
405420
if (!response.hasEntity()) {
406421
fail("No error message set");
407422
}
@@ -413,9 +428,9 @@ private void assertError(Response response, String error) {
413428
private ComponentRepresentation createComponentRepresentation(String name) {
414429
ComponentRepresentation rep = new ComponentRepresentation();
415430
rep.setName(name);
416-
rep.setParentId(realmId);
417-
rep.setProviderId("test");
418-
rep.setProviderType(TestProvider.class.getName());
431+
rep.setParentId(managedRealm.getId());
432+
rep.setProviderId("test-component");
433+
rep.setProviderType(TestComponentProvider.class.getName());
419434
rep.setSubType("foo");
420435

421436
MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
@@ -436,7 +451,7 @@ public CreateComponent(ExecutorService s, int i, RealmResource realm) {
436451
}
437452

438453
public CreateComponent(ExecutorService s, int i) {
439-
this(s, i, ComponentsTest.this.realm);
454+
this(s, i, ComponentsTest.this.managedRealm.admin());
440455
}
441456

442457
@Override
@@ -530,12 +545,53 @@ public DeleteComponent(String id) {
530545
public void run() {
531546
log.debugf("Started, id=%s", id);
532547

533-
ComponentResource c = realm.components().component(id);
548+
ComponentResource c = managedRealm.admin().components().component(id);
534549
assertThat(c.toRepresentation(), Matchers.notNullValue());
535550
c.remove();
536551

537552
log.debugf("Finished, id=%s", id);
538553
}
539554
}
540555

556+
public static class TestComponents implements FetchOnServerWrapper<ComponentsDetails> {
557+
558+
@Override
559+
public FetchOnServer getRunOnServer() {
560+
return session -> {
561+
RealmModel realm = session.getContext().getRealm();
562+
return new ComponentsDetails(
563+
realm.getComponentsStream(realm.getId(), TestComponentProvider.class.getName())
564+
.collect(Collectors.toMap(ComponentModel::getName,
565+
componentModel -> {
566+
ProviderFactory<TestComponentProvider> f = session.getKeycloakSessionFactory()
567+
.getProviderFactory(TestComponentProvider.class, componentModel.getProviderId());
568+
TestComponentProviderFactory factory = (TestComponentProviderFactory) f;
569+
TestComponentProvider p = (TestComponentProvider) factory.create(session, componentModel);
570+
return p.getDetails();
571+
}))
572+
);
573+
};
574+
}
575+
576+
@Override
577+
public Class<ComponentsDetails> getResultClass() {
578+
return ComponentsDetails.class;
579+
}
580+
}
581+
582+
/**
583+
* This class serves only as a wrapper for a {@code Map<String, TestProvider.DetailsRepresentation>}
584+
* This is crucial for deserialization to correctly reconstruct {@link TestComponentProvider.DetailsRepresentation}
585+
* objects, as {@link FetchOnServerWrapper#getResultClass()} cannot retain generic map type information at runtime.
586+
*/
587+
private record ComponentsDetails(Map<String, TestComponentProvider.DetailsRepresentation> componentsDetailsMap) {
588+
}
589+
590+
public static class ComponentsTestServerConfig implements KeycloakServerConfig {
591+
592+
@Override
593+
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
594+
return config.dependency("org.keycloak.tests", "keycloak-tests-custom-providers");
595+
}
596+
}
541597
}

testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestImplProviderFactory.java renamed to tests/custom-providers/src/main/java/org/keycloak/testsuite/components/TestComponentImplProviderFactory.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
/**
3535
* @author <a href="mailto:[email protected]">Stian Thorgersen</a>
3636
*/
37-
public class TestImplProviderFactory implements TestProviderFactory {
37+
public class TestComponentImplProviderFactory implements TestComponentProviderFactory {
3838

3939
private List<ProviderConfigProperty> config = ProviderConfigurationBuilder.create()
4040
.property("secret", "Secret", "A secret value", STRING_TYPE, null, null, true)
@@ -47,7 +47,7 @@ public class TestImplProviderFactory implements TestProviderFactory {
4747

4848
@Override
4949
public Object create(KeycloakSession session, ComponentModel model) {
50-
return new TestImplProvider(model);
50+
return new TestComponentImplProvider(model);
5151
}
5252

5353
@Override
@@ -81,14 +81,14 @@ public void close() {
8181

8282
@Override
8383
public String getId() {
84-
return "test";
84+
return "test-component";
8585
}
8686

87-
public static class TestImplProvider implements TestProvider {
87+
public static class TestComponentImplProvider implements TestComponentProvider {
8888

8989
private ComponentModel model;
9090

91-
public TestImplProvider(ComponentModel model) {
91+
public TestComponentImplProvider(ComponentModel model) {
9292
this.model = model;
9393
}
9494

testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestProvider.java renamed to tests/custom-providers/src/main/java/org/keycloak/testsuite/components/TestComponentProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
/**
2626
* @author <a href="mailto:[email protected]">Stian Thorgersen</a>
2727
*/
28-
public interface TestProvider extends Provider {
28+
public interface TestComponentProvider extends Provider {
2929

3030
DetailsRepresentation getDetails();
3131

testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestProviderFactory.java renamed to tests/custom-providers/src/main/java/org/keycloak/testsuite/components/TestComponentProviderFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@
2222
/**
2323
* @author <a href="mailto:[email protected]">Stian Thorgersen</a>
2424
*/
25-
public interface TestProviderFactory<T extends TestProvider> extends ComponentFactory<T, TestProvider> {
25+
public interface TestComponentProviderFactory<T extends TestComponentProvider> extends ComponentFactory<T, TestComponentProvider> {
2626
}

testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestSpi.java renamed to tests/custom-providers/src/main/java/org/keycloak/testsuite/components/TestComponentSpi.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,24 @@
2424
/**
2525
* @author <a href="mailto:[email protected]">Stian Thorgersen</a>
2626
*/
27-
public class TestSpi implements Spi {
27+
public class TestComponentSpi implements Spi {
2828
@Override
2929
public boolean isInternal() {
3030
return false;
3131
}
3232

3333
@Override
3434
public String getName() {
35-
return "test";
35+
return "test-component";
3636
}
3737

3838
@Override
3939
public Class<? extends Provider> getProviderClass() {
40-
return TestProvider.class;
40+
return TestComponentProvider.class;
4141
}
4242

4343
@Override
4444
public Class<? extends ProviderFactory> getProviderFactoryClass() {
45-
return TestProviderFactory.class;
45+
return TestComponentProviderFactory.class;
4646
}
4747
}

0 commit comments

Comments
 (0)