Skip to content

Commit

Permalink
Improve unit test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderjordanbaker committed Oct 27, 2023
1 parent b157703 commit 75f7715
Show file tree
Hide file tree
Showing 44 changed files with 1,024 additions and 47 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

package com.apple.itunes.storekit.client;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.InputStream;

class BearerTokenAuthenticatorTest {

@Test
void testConstructor() throws Exception {
try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("testSigningKey.p8")) {
new BearerTokenAuthenticator(new String(key.readAllBytes()), "keyId", "issuerId", "bundleId");
void testCreatingToken() throws Exception {
try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) {
var tokenGenerator = new BearerTokenAuthenticator(new String(key.readAllBytes()), "keyId", "issuerId", "bundleId");
String token = tokenGenerator.generateToken();
Assertions.assertNotNull(token);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2023 Apple Inc. Licensed under MIT License.

package com.apple.itunes.storekit.migration;

import com.apple.itunes.storekit.util.TestingUtility;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.IOException;

public class ReceiptUtilityTest {

private static final String APP_RECEIPT_EXPECTED_TRANSACTION_ID = "0";
private static final String TRANSACTION_RECEIPT_EXPECTED_TRANSACTION_ID = "33993399";

@Test
public void testXcodeAppReceiptExtractionWithNoTransactions() throws IOException {
String receipt = TestingUtility.readFile("xcode/xcode-app-receipt-empty");

ReceiptUtility util = new ReceiptUtility();
String extractedTransactionId = util.extractTransactionIdFromAppReceipt(receipt);

Assertions.assertNull(extractedTransactionId);
}

@Test
public void testXcodeAppReceiptExtractionWithTransactions() throws IOException {
String receipt = TestingUtility.readFile("xcode/xcode-app-receipt-with-transaction");

ReceiptUtility util = new ReceiptUtility();
String extractedTransactionId = util.extractTransactionIdFromAppReceipt(receipt);

Assertions.assertEquals(APP_RECEIPT_EXPECTED_TRANSACTION_ID, extractedTransactionId);
}

@Test
public void testTransactionReceiptExtraction() throws IOException {
String receipt = TestingUtility.readFile("mock_signed_data/legacyTransaction");

ReceiptUtility util = new ReceiptUtility();
String extractedTransactionId = util.extractTransactionIdFromTransactionReceipt(receipt);

Assertions.assertEquals(TRANSACTION_RECEIPT_EXPECTED_TRANSACTION_ID, extractedTransactionId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2023 Apple Inc. Licensed under MIT License.

package com.apple.itunes.storekit.model;


import com.apple.itunes.storekit.util.SignedDataCreator;
import com.apple.itunes.storekit.util.TestingUtility;
import com.apple.itunes.storekit.verification.VerificationException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.UUID;

public class AppTransactionTest {

@Test
public void testAppReceiptDecoding() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, VerificationException {
String signedAppTransaction = SignedDataCreator.createSignedDataFromJson("models/appTransaction.json");

AppTransaction appTransaction = TestingUtility.getSignedPayloadVerifier().verifyAndDecodeAppTransaction(signedAppTransaction);

Assertions.assertEquals(Environment.LOCAL_TESTING, appTransaction.getReceiptType());
Assertions.assertEquals(531412, appTransaction.getAppAppleId());
Assertions.assertEquals("com.example", appTransaction.getBundleId());
Assertions.assertEquals("1.2.3", appTransaction.getApplicationVersion());
Assertions.assertEquals(512, appTransaction.versionExternalIdentifier());
Assertions.assertEquals(1698148900000L, appTransaction.getReceiptCreationDate());
Assertions.assertEquals(1698148800000L, appTransaction.originalPurchaseDate());
Assertions.assertEquals("1.1.2", appTransaction.getOriginalApplicationVersion());
Assertions.assertEquals("device_verification_value", appTransaction.getDeviceVerification());
Assertions.assertEquals(UUID.fromString("48ccfa42-7431-4f22-9908-7e88983e105a"), appTransaction.getDeviceVerificationNonce());
Assertions.assertEquals(1698148700000L, appTransaction.getPreorderDate());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2023 Apple Inc. Licensed under MIT License.

package com.apple.itunes.storekit.model;

import com.apple.itunes.storekit.util.SignedDataCreator;
import com.apple.itunes.storekit.util.TestingUtility;
import com.apple.itunes.storekit.verification.VerificationException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

public class JWSRenewalInfoDecodedPayloadTest {

@Test
public void testTransactionDecoding() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, VerificationException {
String signedRenewalInfo = SignedDataCreator.createSignedDataFromJson("models/signedRenewalInfo.json");

JWSRenewalInfoDecodedPayload renewalInfo = TestingUtility.getSignedPayloadVerifier().verifyAndDecodeRenewalInfo(signedRenewalInfo);

Assertions.assertEquals(ExpirationIntent.CUSTOMER_CANCELLED, renewalInfo.getExpirationIntent());
Assertions.assertEquals("12345", renewalInfo.getOriginalTransactionId());
Assertions.assertEquals("com.example.product.2", renewalInfo.getAutoRenewProductId());
Assertions.assertEquals("com.example.product", renewalInfo.getProductId());
Assertions.assertEquals(AutoRenewStatus.ON, renewalInfo.getAutoRenewStatus());
Assertions.assertTrue(renewalInfo.getIsInBillingRetryPeriod());
Assertions.assertEquals(PriceIncreaseStatus.CUSTOMER_HAS_NOT_RESPONDED, renewalInfo.getPriceIncreaseStatus());
Assertions.assertEquals(1698148900000L, renewalInfo.getGracePeriodExpiresDate());
Assertions.assertEquals(OfferType.PROMOTIONAL_OFFER, renewalInfo.getOfferType());
Assertions.assertEquals("abc.123", renewalInfo.getOfferIdentifier());
Assertions.assertEquals(1698148800000L, renewalInfo.getSignedDate());
Assertions.assertEquals(Environment.LOCAL_TESTING, renewalInfo.getEnvironment());
Assertions.assertEquals(1698148800000L, renewalInfo.getRecentSubscriptionStartDate());
Assertions.assertEquals(1698148850000L, renewalInfo.getRenewalDate());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) 2023 Apple Inc. Licensed under MIT License.

package com.apple.itunes.storekit.model;

import com.apple.itunes.storekit.util.SignedDataCreator;
import com.apple.itunes.storekit.util.TestingUtility;
import com.apple.itunes.storekit.verification.VerificationException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.UUID;

public class JWSTransactionDecodedPayloadTest {

@Test
public void testTransactionDecoding() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, VerificationException {
String signedTransaction = SignedDataCreator.createSignedDataFromJson("models/signedTransaction.json");

JWSTransactionDecodedPayload transaction = TestingUtility.getSignedPayloadVerifier().verifyAndDecodeTransaction(signedTransaction);

Assertions.assertEquals("12345", transaction.getOriginalTransactionId());
Assertions.assertEquals("23456", transaction.getTransactionId());
Assertions.assertEquals("34343", transaction.getWebOrderLineItemId());
Assertions.assertEquals("com.example", transaction.getBundleId());
Assertions.assertEquals("com.example.product", transaction.getProductId());
Assertions.assertEquals("55555", transaction.getSubscriptionGroupIdentifier());
Assertions.assertEquals(1698148800000L, transaction.getOriginalPurchaseDate());
Assertions.assertEquals(1698148900000L, transaction.getPurchaseDate());
Assertions.assertEquals(1698148950000L, transaction.getRevocationDate());
Assertions.assertEquals(1698149000000L, transaction.getExpiresDate());
Assertions.assertEquals(1, transaction.getQuantity());
Assertions.assertEquals(Type.AUTO_RENEWABLE_SUBSCRIPTION, transaction.getType());
Assertions.assertEquals(UUID.fromString("7e3fb20b-4cdb-47cc-936d-99d65f608138"), transaction.getAppAccountToken());
Assertions.assertEquals(InAppOwnershipType.PURCHASED, transaction.getInAppOwnershipType());
Assertions.assertEquals(1698148900000L, transaction.getSignedDate());
Assertions.assertEquals(RevocationReason.REFUNDED_DUE_TO_ISSUE, transaction.getRevocationReason());
Assertions.assertEquals("abc.123", transaction.getOfferIdentifier());
Assertions.assertTrue(transaction.getIsUpgraded());
Assertions.assertEquals(OfferType.INTRODUCTORY_OFFER, transaction.getOfferType());
Assertions.assertEquals("USA", transaction.getStorefront());
Assertions.assertEquals("143441", transaction.getStorefrontId());
Assertions.assertEquals(TransactionReason.PURCHASE, transaction.getTransactionReason());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.apple.itunes.storekit.model;

import com.apple.itunes.storekit.util.SignedDataCreator;
import com.apple.itunes.storekit.util.TestingUtility;
import com.apple.itunes.storekit.verification.VerificationException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.List;
import java.util.UUID;

public class ResponseBodyV2DecodedPayloadTest {

@Test
public void testNotificationDecoding() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, VerificationException {
String signedNotification = SignedDataCreator.createSignedDataFromJson("models/signedNotification.json");

ResponseBodyV2DecodedPayload notification = TestingUtility.getSignedPayloadVerifier().verifyAndDecodeNotification(signedNotification);

Assertions.assertEquals(NotificationTypeV2.SUBSCRIBED, notification.getNotificationType());
Assertions.assertEquals(Subtype.INITIAL_BUY, notification.getSubtype());
Assertions.assertEquals("002e14d5-51f5-4503-b5a8-c3a1af68eb20", notification.getNotificationUUID());
Assertions.assertEquals("2.0", notification.getVersion());
Assertions.assertEquals(1698148900000L, notification.getSignedDate());
Assertions.assertNotNull(notification.getData());
Assertions.assertNull(notification.getSummary());
Assertions.assertEquals(Environment.LOCAL_TESTING, notification.getData().getEnvironment());
Assertions.assertEquals(41234L, notification.getData().getAppAppleId());
Assertions.assertEquals("com.example", notification.getData().getBundleId());
Assertions.assertEquals("1.2.3", notification.getData().getBundleVersion());
Assertions.assertEquals("signed_transaction_info_value", notification.getData().getSignedTransactionInfo());
Assertions.assertEquals("signed_renewal_info_value", notification.getData().getSignedRenewalInfo());
Assertions.assertEquals(Status.ACTIVE, notification.getData().getStatus());
}

@Test
public void testSummaryNotificationDecoding() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, VerificationException {
String signedNotification = SignedDataCreator.createSignedDataFromJson("models/signedSummaryNotification.json");

ResponseBodyV2DecodedPayload notification = TestingUtility.getSignedPayloadVerifier().verifyAndDecodeNotification(signedNotification);

Assertions.assertEquals(NotificationTypeV2.RENEWAL_EXTENSION, notification.getNotificationType());
Assertions.assertEquals(Subtype.SUMMARY, notification.getSubtype());
Assertions.assertEquals("002e14d5-51f5-4503-b5a8-c3a1af68eb20", notification.getNotificationUUID());
Assertions.assertEquals("2.0", notification.getVersion());
Assertions.assertEquals(1698148900000L, notification.getSignedDate());
Assertions.assertNull(notification.getData());
Assertions.assertNotNull(notification.getSummary());
Assertions.assertEquals(Environment.LOCAL_TESTING, notification.getSummary().getEnvironment());
Assertions.assertEquals(41234L, notification.getSummary().getAppAppleId());
Assertions.assertEquals("com.example", notification.getSummary().getBundleId());
Assertions.assertEquals("com.example.product", notification.getSummary().getProductId());
Assertions.assertEquals("efb27071-45a4-4aca-9854-2a1e9146f265", notification.getSummary().getRequestIdentifier());
Assertions.assertEquals(List.of("CAN", "USA", "MEX"), notification.getSummary().getStorefrontCountryCodes());
Assertions.assertEquals(5, notification.getSummary().getSucceededCount());
Assertions.assertEquals(2, notification.getSummary().getFailedCount());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
import org.junit.jupiter.api.Test;

import java.io.InputStream;
import java.util.UUID;

class PromotionalOfferSignatureCreatorTest {

@Test
void testConstructor() throws Exception {
try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("testSigningKey.p8")) {
new PromotionalOfferSignatureCreator(new String(key.readAllBytes()), "keyId", "bundleId");
void testSignatureCreator() throws Exception {
try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) {
PromotionalOfferSignatureCreator signatureCreator = new PromotionalOfferSignatureCreator(new String(key.readAllBytes()), "keyId", "bundleId");
signatureCreator.createSignature("productId", "offerId", "applicationUsername", UUID.fromString("20fba8a0-2b80-4a7d-a17f-85c1854727f8"), 1698148900000L);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2023 Apple Inc. Licensed under MIT License.

package com.apple.itunes.storekit.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.ECDSAKeyProvider;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.ECPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Map;

public class SignedDataCreator {

public static String createSignedDataFromJson(String path) throws IOException, NoSuchAlgorithmException {
String json = TestingUtility.readFile(path);
KeyPairGenerator ec = KeyPairGenerator.getInstance("EC");
ec.initialize(256);
return JWT.create()
.withPayload(json)
.sign(Algorithm.ECDSA256((ECPrivateKey) ec.generateKeyPair().getPrivate()));
}
}
Loading

0 comments on commit 75f7715

Please sign in to comment.