44import com .salesforce .multicloudj .iam .driver .AbstractIam ;
55import com .salesforce .multicloudj .iam .model .PolicyDocument ;
66import com .salesforce .multicloudj .iam .model .Statement ;
7+ import com .salesforce .multicloudj .iam .model .CreateOptions ;
8+ import com .salesforce .multicloudj .iam .model .TrustConfiguration ;
79import org .junit .jupiter .api .AfterAll ;
810import org .junit .jupiter .api .AfterEach ;
911import org .junit .jupiter .api .Assertions ;
1315import org .junit .jupiter .api .TestInstance ;
1416
1517import java .util .List ;
18+ import java .util .Optional ;
1619
1720@ TestInstance (TestInstance .Lifecycle .PER_CLASS )
1821public abstract class AbstractIamIT {
@@ -33,6 +36,10 @@ public interface Harness extends AutoCloseable {
3336
3437 String getIamEndpoint ();
3538
39+ String getTrustedPrincipal ();
40+
41+ String getTestIdentityName ();
42+
3643 default String getPolicyVersion () {
3744 return "" ;
3845 }
@@ -41,12 +48,14 @@ default String getPolicyVersion() {
4148
4249 List <String > getTestPolicyActions ();
4350
44- String getTestPolicyName ();
45- }
51+ String getTestPolicyName ();
52+ }
4653
4754 protected abstract Harness createHarness ();
4855
4956 private Harness harness ;
57+ private AbstractIam iam ;
58+ private IamClient iamClient ;
5059
5160 /**
5261 * Initializes the WireMock server before all tests.
@@ -73,27 +82,29 @@ public void shutdownWireMockServer() throws Exception {
7382 @ BeforeEach
7483 public void setupTestEnvironment () {
7584 TestsUtil .startWireMockRecording (harness .getIamEndpoint ());
85+ iam = harness .createIamDriver (true );
86+ iamClient = new IamClient (iam );
7687 }
7788
7889 /**
7990 * Cleans up the test environment after each test.
8091 */
8192 @ AfterEach
82- public void cleanupTestEnvironment () {
93+ public void cleanupTestEnvironment () throws Exception {
8394 TestsUtil .stopWireMockRecording ();
95+ if (iamClient != null ) {
96+ iamClient .close (); // closes underlying AbstractIam
97+ }
8498 }
8599
86100 @ Test
87101 public void testAttachInlinePolicy () {
88- AbstractIam iam = harness .createIamDriver (true );
89- IamClient iamClient = new IamClient (iam );
90-
91- Statement .StatementBuilder statementBuilder = Statement .builder ()
102+ Statement .StatementBuilder statementBuilder = Statement .builder ()
92103 .effect (harness .getTestPolicyEffect ());
93104 for (String action : harness .getTestPolicyActions ()) {
94105 statementBuilder .action (action );
95106 }
96-
107+
97108 PolicyDocument policyDocument = PolicyDocument .builder ()
98109 .version (harness .getPolicyVersion ())
99110 .statement (statementBuilder .build ())
@@ -109,10 +120,7 @@ public void testAttachInlinePolicy() {
109120
110121 @ Test
111122 public void testGetInlinePolicyDetails () {
112- AbstractIam iam = harness .createIamDriver (true );
113- IamClient iamClient = new IamClient (iam );
114-
115- PolicyDocument policyDocument = PolicyDocument .builder ()
123+ PolicyDocument policyDocument = PolicyDocument .builder ()
116124 .version (harness .getPolicyVersion ())
117125 .statement (Statement .builder ()
118126 .effect (harness .getTestPolicyEffect ())
@@ -139,15 +147,12 @@ public void testGetInlinePolicyDetails() {
139147
140148 @ Test
141149 public void testGetAttachedPolicies () {
142- AbstractIam iam = harness .createIamDriver (true );
143- IamClient iamClient = new IamClient (iam );
144-
145- Statement .StatementBuilder statementBuilder = Statement .builder ()
150+ Statement .StatementBuilder statementBuilder = Statement .builder ()
146151 .effect (harness .getTestPolicyEffect ());
147152 for (String action : harness .getTestPolicyActions ()) {
148153 statementBuilder .action (action );
149154 }
150-
155+
151156 PolicyDocument policyDocument = PolicyDocument .builder ()
152157 .version (harness .getPolicyVersion ())
153158 .statement (statementBuilder .build ())
@@ -171,10 +176,7 @@ public void testGetAttachedPolicies() {
171176
172177 @ Test
173178 public void testRemovePolicy () {
174- AbstractIam iam = harness .createIamDriver (true );
175- IamClient iamClient = new IamClient (iam );
176-
177- PolicyDocument policyDocument = PolicyDocument .builder ()
179+ PolicyDocument policyDocument = PolicyDocument .builder ()
178180 .version (harness .getPolicyVersion ())
179181 .statement (Statement .builder ()
180182 .effect (harness .getTestPolicyEffect ())
@@ -189,11 +191,244 @@ public void testRemovePolicy() {
189191 harness .getIdentityName ()
190192 );
191193
192- iamClient .removePolicy (
193- harness .getIdentityName (),
194- harness .getTestPolicyName (),
195- harness .getTenantId (),
196- harness .getRegion ()
197- );
198- }
194+ iamClient .removePolicy (
195+ harness .getIdentityName (),
196+ harness .getTestPolicyName (),
197+ harness .getTenantId (),
198+ harness .getRegion ()
199+ );
200+ }
201+
202+ private void cleanUpIdentity (String identity ) {
203+ try {
204+ iamClient .deleteIdentity (
205+ identity ,
206+ harness .getTenantId (),
207+ harness .getRegion ()
208+ );
209+ } catch (Exception e ) {
210+ // Ignore
211+ }
212+ }
213+
214+ /**
215+ * Tests creating an identity without trust configuration.
216+ */
217+ @ Test
218+ public void testCreateIdentityWithoutTrustConfig () {
219+ String identityName = harness .getTestIdentityName ();
220+ String identityId = iamClient .createIdentity (
221+ identityName ,
222+ "Test identity for MultiCloudJ integration tests" ,
223+ harness .getTenantId (),
224+ harness .getRegion (),
225+ Optional .empty (),
226+ Optional .empty ()
227+ );
228+
229+ Assertions .assertNotNull (identityId , "Identity ID should not be null" );
230+ Assertions .assertFalse (identityId .isEmpty (), "Identity ID should not be empty" );
231+
232+ cleanUpIdentity (identityName );
233+ }
234+
235+ /**
236+ * Tests creating an identity with trust configuration.
237+ */
238+ @ Test
239+ public void testCreateIdentityWithTrustConfig () {
240+ String identityName = harness .getTestIdentityName () + "Trusted" ;
241+ TrustConfiguration trustConfig = TrustConfiguration .builder ()
242+ .addTrustedPrincipal (harness .getTrustedPrincipal ())
243+ .build ();
244+
245+ String identityId = iamClient .createIdentity (
246+ identityName ,
247+ "Test identity with trust configuration" ,
248+ harness .getTenantId (),
249+ harness .getRegion (),
250+ Optional .of (trustConfig ),
251+ Optional .empty ()
252+ );
253+
254+ Assertions .assertNotNull (identityId , "Identity ID should not be null" );
255+ Assertions .assertFalse (identityId .isEmpty (), "Identity ID should not be empty" );
256+
257+ cleanUpIdentity (identityName );
258+ }
259+
260+ /**
261+ * Tests creating an identity with CreateOptions.
262+ */
263+ @ Test
264+ public void testCreateIdentityWithOptions () {
265+ String identityName = harness .getTestIdentityName () + "Options" ;
266+ CreateOptions options = CreateOptions .builder ().build ();
267+
268+ String identityId = iamClient .createIdentity (
269+ identityName ,
270+ "Test identity with options" ,
271+ harness .getTenantId (),
272+ harness .getRegion (),
273+ Optional .empty (),
274+ Optional .of (options )
275+ );
276+
277+ Assertions .assertNotNull (identityId , "Identity ID should not be null" );
278+ Assertions .assertFalse (identityId .isEmpty (), "Identity ID should not be empty" );
279+
280+ cleanUpIdentity (identityName );
281+ }
282+
283+ /**
284+ * Tests creating an identity with null description.
285+ */
286+ @ Test
287+ public void testCreateIdentityWithNullDescription () {
288+ String identityName = harness .getTestIdentityName () + "NoDesc" ;
289+
290+ String identityId = iamClient .createIdentity (
291+ identityName ,
292+ null ,
293+ harness .getTenantId (),
294+ harness .getRegion (),
295+ Optional .empty (),
296+ Optional .empty ()
297+ );
298+
299+ Assertions .assertNotNull (identityId , "Identity ID should not be null" );
300+ Assertions .assertFalse (identityId .isEmpty (), "Identity ID should not be empty" );
301+
302+ cleanUpIdentity (identityName );
303+ }
304+
305+ /**
306+ * Tests getting an identity by name.
307+ */
308+ @ Test
309+ public void testGetIdentity () throws InterruptedException {
310+ String identityName = harness .getTestIdentityName () + "Get" ;
311+ // First create an identity
312+ String identityId = iamClient .createIdentity (
313+ identityName ,
314+ "Test identity for get operation" ,
315+ harness .getTenantId (),
316+ harness .getRegion (),
317+ Optional .empty (),
318+ Optional .empty ()
319+ );
320+
321+ // sleep for 500ms
322+ Thread .sleep (500 );
323+
324+ // Then retrieve it
325+ String retrievedIdentity = iamClient .getIdentity (
326+ harness .getTestIdentityName () + "Get" ,
327+ harness .getTenantId (),
328+ harness .getRegion ()
329+ );
330+
331+ Assertions .assertNotNull (retrievedIdentity , "Retrieved identity should not be null" );
332+ Assertions .assertFalse (retrievedIdentity .isEmpty (), "Retrieved identity should not be empty" );
333+
334+ cleanUpIdentity (identityName );
335+ }
336+
337+ /**
338+ * Tests that the provider ID is correctly set.
339+ */
340+ @ Test
341+ public void testProviderId () {
342+ Assertions .assertNotNull (iam .getProviderId (), "Provider ID should not be null" );
343+ Assertions .assertEquals (harness .getProviderId (), iam .getProviderId (),
344+ "Provider ID should match the expected value" );
345+ }
346+
347+ /**
348+ * Tests exception mapping for provider-specific exceptions.
349+ */
350+ @ Test
351+ public void testExceptionMapping () {
352+ // Test with a generic exception
353+ Throwable genericException = new RuntimeException ("Generic error" );
354+ Class <? extends com .salesforce .multicloudj .common .exceptions .SubstrateSdkException > exceptionClass =
355+ iam .getException (genericException );
356+
357+ Assertions .assertNotNull (exceptionClass , "Exception class should not be null" );
358+ Assertions .assertEquals (
359+ com .salesforce .multicloudj .common .exceptions .UnknownException .class ,
360+ exceptionClass ,
361+ "Generic exceptions should map to UnknownException"
362+ );
363+ }
364+
365+ /**
366+ * Tests deleting an identity.
367+ */
368+ @ Test
369+ public void testDeleteIdentity () {
370+ // First create an identity
371+ String identityId = iamClient .createIdentity (
372+ harness .getTestIdentityName () + "Delete" ,
373+ "Test identity for delete operation" ,
374+ harness .getTenantId (),
375+ harness .getRegion (),
376+ Optional .empty (),
377+ Optional .empty ()
378+ );
379+
380+ Assertions .assertNotNull (identityId , "Identity ID should not be null" );
381+
382+ // Then delete it - should not throw any exception
383+ Assertions .assertDoesNotThrow (() ->
384+ iamClient .deleteIdentity (
385+ harness .getTestIdentityName () + "Delete" ,
386+ harness .getTenantId (),
387+ harness .getRegion ()
388+ )
389+ );
390+ }
391+
392+ /**
393+ * Tests the complete lifecycle: create, get, and delete an identity.
394+ */
395+ @ Test
396+ public void testIdentityLifecycle () throws InterruptedException {
397+ String testIdentityName = harness .getTestIdentityName () + "LifeCycle" ;
398+
399+ // Step 1: Create an identity
400+ String identityId = iamClient .createIdentity (
401+ testIdentityName ,
402+ "Test identity for lifecycle test" ,
403+ harness .getTenantId (),
404+ harness .getRegion (),
405+ Optional .empty (),
406+ Optional .empty ()
407+ );
408+
409+ Assertions .assertNotNull (identityId , "Identity ID should not be null after creation" );
410+ Assertions .assertFalse (identityId .isEmpty (), "Identity ID should not be empty after creation" );
411+
412+ // Step 2: Get the identity to verify it exists
413+ Thread .sleep (500 );
414+
415+ String retrievedIdentity = iamClient .getIdentity (
416+ testIdentityName ,
417+ harness .getTenantId (),
418+ harness .getRegion ()
419+ );
420+
421+ Assertions .assertNotNull (retrievedIdentity , "Retrieved identity should not be null" );
422+ Assertions .assertFalse (retrievedIdentity .isEmpty (), "Retrieved identity should not be empty" );
423+
424+ // Step 3: Delete the identity
425+ Assertions .assertDoesNotThrow (() ->
426+ iamClient .deleteIdentity (
427+ testIdentityName ,
428+ harness .getTenantId (),
429+ harness .getRegion ()
430+ ),
431+ "Deleting identity should not throw an exception"
432+ );
433+ }
199434}
0 commit comments