@@ -34,6 +34,7 @@ import com.google.android.play.core.integrity.StandardIntegrityManager
3434import com.google.android.play.core.integrity.StandardIntegrityManager.StandardIntegrityToken
3535import com.google.android.play.core.integrity.StandardIntegrityManager.StandardIntegrityTokenProvider
3636import com.google.android.play.core.integrity.model.StandardIntegrityErrorCode.INTEGRITY_TOKEN_PROVIDER_INVALID
37+ import com.google.android.play.core.integrity.model.StandardIntegrityErrorCode.INTERNAL_ERROR
3738import com.salesforce.androidsdk.rest.RestClient
3839import com.salesforce.androidsdk.rest.RestResponse
3940import io.mockk.coEvery
@@ -45,6 +46,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
4546import kotlinx.coroutines.tasks.await
4647import kotlinx.coroutines.test.advanceUntilIdle
4748import kotlinx.coroutines.test.runTest
49+ import kotlinx.serialization.json.Json
4850import org.junit.Assert.assertEquals
4951import org.junit.Assert.assertNull
5052import org.junit.Test
@@ -68,19 +70,16 @@ class AppAttestationClientTest {
6870 val integrityManager = mockk<StandardIntegrityManager >(relaxed = true )
6971 every { integrityManager.prepareIntegrityToken(any()) } returns integrityTokenProviderTask
7072
71- val appAttestationClient = AppAttestationClient (
73+ AppAttestationClient (
7274 apiHostName = " login.example.com" ,
7375 context = context,
7476 deviceId = deviceId,
7577 googleCloudProjectId = googleCloudProjectId,
78+ integrityManager = integrityManager,
7679 remoteAccessConsumerKey = remoteAccessConsumerKey,
7780 restClient = restClient
7881 )
7982
80- appAttestationClient.prepareIntegrityTokenProvider(
81- integrityManager = integrityManager
82- )
83-
8483 verify(exactly = 1 ) {
8584 integrityManager.prepareIntegrityToken(match {
8685 it.toString().contains(" cloudProjectNumber=654321" )
@@ -175,6 +174,9 @@ class AppAttestationClientTest {
175174 restClient = restClient
176175 )
177176
177+ // TODO: Consider refactoring this statement once it proves coverage for AppAttestationClient#145 ECJ20260416
178+ // appAttestationClient.createSalesforceOAuthAuthorizationAppAttestation() // TODO: This won't run without mocks. ECJ20260416
179+
178180 val result = appAttestationClient.createSalesforceOAuthAuthorizationAppAttestation(
179181 integrityTokenProvider = integrityTokenProvider
180182 )
@@ -229,12 +231,12 @@ class AppAttestationClientTest {
229231 context = context,
230232 deviceId = deviceId,
231233 googleCloudProjectId = googleCloudProjectId,
234+ integrityManager = integrityManager,
232235 remoteAccessConsumerKey = remoteAccessConsumerKey,
233- restClient = restClient
236+ restClient = restClient,
234237 )
235238
236239 val result = appAttestationClient.createSalesforceOAuthAuthorizationAppAttestation(
237- integrityManager = integrityManager,
238240 integrityTokenProvider = throwingIntegrityTokenProvider
239241 )
240242
@@ -243,6 +245,65 @@ class AppAttestationClientTest {
243245 assertEquals(" eyJhdHRlc3RhdGlvbklkIjoiMTIzNDU2IiwiYXR0ZXN0YXRpb25EYXRhIjoiWDE5VVJWTlVYMGxPVkVWSFVrbFVXVjlVVDB0RlRsOWYifQ==" , result)
244246 }
245247
248+ @OptIn(ExperimentalCoroutinesApi ::class )
249+ @Test
250+ fun appAttestationClient_createSalesforceOAuthAuthorizationAppAttestationThrowingForUnknownIntegrityServiceException_returnsSuccessfully () = runTest {
251+
252+ val context = mockk<Context >(relaxed = true )
253+ val deviceId = " 123456"
254+ val googleCloudProjectId = 654321L
255+ val remoteAccessConsumerKey = " 13579"
256+ val restResponse = mockk<RestResponse >(relaxed = true )
257+ every { restResponse.asString() } returns " __TEST_CHALLENGE_VALUE__"
258+ every { restResponse.isSuccess } returns true
259+ val restClient = mockk<RestClient >(relaxed = true )
260+ every { restClient.sendSync(any()) } returns restResponse
261+
262+ val integrityToken = mockk<StandardIntegrityToken >(relaxed = true )
263+ every { integrityToken.token() } returns " __TEST_INTEGRITY_TOKEN__"
264+ val throwingIntegrityTokenTask = mockk<Task <StandardIntegrityToken >>(relaxed = true )
265+ every { throwingIntegrityTokenTask.addOnFailureListener(any()) } returns throwingIntegrityTokenTask
266+ every { throwingIntegrityTokenTask.getResult() } returns integrityToken
267+ mockkStatic(" kotlinx.coroutines.tasks.TasksKt" )
268+ val integrityServiceException = mockk<IntegrityServiceException >(relaxed = true )
269+ every { integrityServiceException.errorCode } returns INTERNAL_ERROR
270+ coEvery { throwingIntegrityTokenTask.await() } throws integrityServiceException
271+ val throwingIntegrityTokenProvider = mockk<StandardIntegrityTokenProvider >(relaxed = true )
272+ every { throwingIntegrityTokenProvider.request(any()) } returns throwingIntegrityTokenTask
273+
274+ val successfulIntegrityTokenTask = mockk<Task <StandardIntegrityToken >>(relaxed = true )
275+ every { successfulIntegrityTokenTask.addOnFailureListener(any()) } returns successfulIntegrityTokenTask
276+ every { successfulIntegrityTokenTask.getResult() } returns integrityToken
277+ coEvery { successfulIntegrityTokenTask.await() } returns integrityToken
278+ val successfulIntegrityTokenProvider = mockk<StandardIntegrityTokenProvider >(relaxed = true )
279+ every { successfulIntegrityTokenProvider.request(any()) } returns successfulIntegrityTokenTask
280+
281+ val integrityTokenProviderTask = mockk<Task <StandardIntegrityTokenProvider >>(relaxed = true )
282+ every { integrityTokenProviderTask.addOnSuccessListener(any()) } returns integrityTokenProviderTask
283+ every { integrityTokenProviderTask.addOnFailureListener(any()) } returns integrityTokenProviderTask
284+ coEvery { integrityTokenProviderTask.result } returns successfulIntegrityTokenProvider
285+ val integrityManager = mockk<StandardIntegrityManager >(relaxed = true )
286+ every { integrityManager.prepareIntegrityToken(any()) } returns integrityTokenProviderTask
287+
288+ val appAttestationClient = AppAttestationClient (
289+ apiHostName = " login.example.com" ,
290+ context = context,
291+ deviceId = deviceId,
292+ googleCloudProjectId = googleCloudProjectId,
293+ integrityManager = integrityManager,
294+ remoteAccessConsumerKey = remoteAccessConsumerKey,
295+ restClient = restClient,
296+ )
297+
298+ val result = appAttestationClient.createSalesforceOAuthAuthorizationAppAttestation(
299+ integrityTokenProvider = throwingIntegrityTokenProvider
300+ )
301+
302+ advanceUntilIdle()
303+
304+ assertNull(result)
305+ }
306+
246307 @OptIn(ExperimentalCoroutinesApi ::class )
247308 @Test
248309 fun appAttestationClient_createSalesforceOAuthAuthorizationAppAttestationThrowingUnknownException_returnsNull () = runTest {
@@ -286,12 +347,12 @@ class AppAttestationClientTest {
286347 context = context,
287348 deviceId = deviceId,
288349 googleCloudProjectId = googleCloudProjectId,
350+ integrityManager = integrityManager,
289351 remoteAccessConsumerKey = remoteAccessConsumerKey,
290- restClient = restClient
352+ restClient = restClient,
291353 )
292354
293355 val result = appAttestationClient.createSalesforceOAuthAuthorizationAppAttestation(
294- integrityManager = integrityManager,
295356 integrityTokenProvider = throwingIntegrityTokenProvider
296357 )
297358
@@ -337,17 +398,77 @@ class AppAttestationClientTest {
337398 context = context,
338399 deviceId = deviceId,
339400 googleCloudProjectId = googleCloudProjectId,
401+ integrityManager = integrityManager,
340402 remoteAccessConsumerKey = remoteAccessConsumerKey,
341- restClient = restClient
403+ restClient = restClient,
342404 )
343405
344406 val result = appAttestationClient.createSalesforceOAuthAuthorizationAppAttestation(
345- integrityManager = integrityManager,
346407 integrityTokenProvider = null
347408 )
348409
349410 advanceUntilIdle()
350411
351412 assertEquals(" eyJhdHRlc3RhdGlvbklkIjoiMTIzNDU2IiwiYXR0ZXN0YXRpb25EYXRhIjoiWDE5VVJWTlVYMGxPVkVWSFVrbFVXVjlVVDB0RlRsOWYifQ==" , result)
352413 }
414+
415+ @OptIn(ExperimentalCoroutinesApi ::class )
416+ @Test
417+ fun appAttestationClient_createSalesforceOAuthAuthorizationAppAttestationBlocking_returnsSuccessfully () = runTest {
418+
419+ val context = mockk<Context >(relaxed = true )
420+ val deviceId = " 123456"
421+ val googleCloudProjectId = 654321L
422+ val remoteAccessConsumerKey = " 13579"
423+ val restResponse = mockk<RestResponse >(relaxed = true )
424+ every { restResponse.asString() } returns " __TEST_CHALLENGE_VALUE__"
425+ every { restResponse.isSuccess } returns true
426+ val restClient = mockk<RestClient >(relaxed = true )
427+ every { restClient.sendSync(any()) } returns restResponse
428+
429+ val integrityToken = mockk<StandardIntegrityToken >(relaxed = true )
430+ every { integrityToken.token() } returns " __TEST_INTEGRITY_TOKEN__"
431+ val integrityTokenTask = mockk<Task <StandardIntegrityToken >>(relaxed = true )
432+ every { integrityTokenTask.addOnFailureListener(any()) } returns integrityTokenTask
433+ every { integrityTokenTask.getResult() } returns integrityToken
434+ mockkStatic(" kotlinx.coroutines.tasks.TasksKt" )
435+ coEvery { integrityTokenTask.await() } returns integrityToken
436+ val integrityTokenProvider = mockk<StandardIntegrityTokenProvider >(relaxed = true )
437+ every { integrityTokenProvider.request(any()) } returns integrityTokenTask
438+
439+ val integrityTokenProviderTask = mockk<Task <StandardIntegrityTokenProvider >>(relaxed = true )
440+ every { integrityTokenProviderTask.addOnSuccessListener(any()) } returns integrityTokenProviderTask
441+ every { integrityTokenProviderTask.addOnFailureListener(any()) } returns integrityTokenProviderTask
442+ coEvery { integrityTokenProviderTask.result } returns integrityTokenProvider
443+ val integrityManager = mockk<StandardIntegrityManager >(relaxed = true )
444+ every { integrityManager.prepareIntegrityToken(any()) } returns integrityTokenProviderTask
445+
446+ val appAttestationClient = AppAttestationClient (
447+ apiHostName = " login.example.com" ,
448+ context = context,
449+ deviceId = deviceId,
450+ googleCloudProjectId = googleCloudProjectId,
451+ integrityManager = integrityManager,
452+ remoteAccessConsumerKey = remoteAccessConsumerKey,
453+ restClient = restClient
454+ )
455+
456+ val result = appAttestationClient.createSalesforceOAuthAuthorizationAppAttestationBlocking()
457+
458+ advanceUntilIdle()
459+
460+ assertEquals(" eyJhdHRlc3RhdGlvbklkIjoiMTIzNDU2IiwiYXR0ZXN0YXRpb25EYXRhIjoiWDE5VVJWTlVYMGxPVkVWSFVrbFVXVjlVVDB0RlRsOWYifQ==" , result)
461+ }
462+
463+ @Test
464+ fun oAuthAuthorizationAttestationData_encode_returnsSuccessfully () {
465+
466+ val result = Json .decodeFromString(
467+ OAuthAuthorizationAttestation .serializer(),
468+ " { \" attestationId\" : \" 123456\" , \" attestationData\" : \" W19VVlJTVVhNbExPVkVWSFVrbFVXVjlVVDB0RlRsOWYifQ==\" }"
469+ )
470+
471+ assertEquals(" 123456" , result.attestationId)
472+ assertEquals(" W19VVlJTVVhNbExPVkVWSFVrbFVXVjlVVDB0RlRsOWYifQ==" , result.attestationData)
473+ }
353474}
0 commit comments