1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.carrierdefaultapp; 18 19 import static org.mockito.ArgumentMatchers.anyInt; 20 import static org.mockito.ArgumentMatchers.anyString; 21 import static org.mockito.ArgumentMatchers.eq; 22 import static org.mockito.Mockito.doReturn; 23 import static org.mockito.Mockito.spy; 24 import static org.mockito.Mockito.times; 25 import static org.mockito.Mockito.verify; 26 27 import android.app.NotificationManager; 28 import android.app.PendingIntent; 29 import android.content.Context; 30 import android.content.Intent; 31 import android.os.Looper; 32 import android.os.PersistableBundle; 33 import android.telephony.CarrierConfigManager; 34 import android.telephony.SubscriptionManager; 35 import android.telephony.TelephonyManager; 36 import android.test.ActivityUnitTestCase; 37 import android.webkit.WebView; 38 39 import androidx.test.platform.app.InstrumentationRegistry; 40 import androidx.test.runner.AndroidJUnit4; 41 42 import com.android.phone.slice.SlicePurchaseController; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.ArgumentCaptor; 48 import org.mockito.Mock; 49 import org.mockito.MockitoAnnotations; 50 51 import java.util.Base64; 52 53 @RunWith(AndroidJUnit4.class) 54 public class SlicePurchaseActivityTest extends ActivityUnitTestCase<SlicePurchaseActivity> { 55 private static final String CARRIER = "Some Carrier"; 56 private static final String URL = "file:///android_asset/slice_purchase_test.html"; 57 private static final int PHONE_ID = 0; 58 59 @Mock PendingIntent mPendingIntent; 60 @Mock PendingIntent mSuccessfulIntent; 61 @Mock PendingIntent mCanceledIntent; 62 @Mock PendingIntent mRequestFailedIntent; 63 @Mock CarrierConfigManager mCarrierConfigManager; 64 @Mock NotificationManager mNotificationManager; 65 @Mock PersistableBundle mPersistableBundle; 66 @Mock WebView mWebView; 67 68 private SlicePurchaseActivity mSlicePurchaseActivity; 69 private Context mContext; 70 SlicePurchaseActivityTest()71 public SlicePurchaseActivityTest() { 72 super(SlicePurchaseActivity.class); 73 } 74 75 @Before setUp()76 public void setUp() throws Exception { 77 injectInstrumentation(InstrumentationRegistry.getInstrumentation()); 78 if (Looper.myLooper() == null) { 79 Looper.prepare(); 80 } 81 super.setUp(); 82 MockitoAnnotations.initMocks(this); 83 84 // setup context 85 mContext = spy(getInstrumentation().getTargetContext()); 86 doReturn(mCarrierConfigManager).when(mContext) 87 .getSystemService(eq(CarrierConfigManager.class)); 88 doReturn(URL).when(mPersistableBundle).getString( 89 CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING); 90 doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt()); 91 doReturn(mNotificationManager).when(mContext) 92 .getSystemService(eq(NotificationManager.class)); 93 doReturn(mContext).when(mContext).getApplicationContext(); 94 setActivityContext(mContext); 95 96 // set up intent 97 Intent intent = new Intent(); 98 intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID); 99 intent.putExtra(SlicePurchaseController.EXTRA_SUB_ID, 100 SubscriptionManager.getDefaultDataSubscriptionId()); 101 intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY, 102 TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY); 103 intent.putExtra(SlicePurchaseController.EXTRA_PURCHASE_URL, 104 SlicePurchaseController.SLICE_PURCHASE_TEST_FILE); 105 intent.putExtra(SlicePurchaseController.EXTRA_CARRIER, CARRIER); 106 Intent spiedIntent = spy(intent); 107 108 // set up pending intents 109 doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mPendingIntent).getCreatorPackage(); 110 doReturn(true).when(mPendingIntent).isBroadcast(); 111 doReturn(mPendingIntent).when(spiedIntent).getParcelableExtra( 112 anyString(), eq(PendingIntent.class)); 113 doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mCanceledIntent).getCreatorPackage(); 114 doReturn(true).when(mCanceledIntent).isBroadcast(); 115 doReturn(mCanceledIntent).when(spiedIntent).getParcelableExtra( 116 eq(SlicePurchaseController.EXTRA_INTENT_CANCELED), eq(PendingIntent.class)); 117 doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mSuccessfulIntent).getCreatorPackage(); 118 doReturn(true).when(mSuccessfulIntent).isBroadcast(); 119 doReturn(mSuccessfulIntent).when(spiedIntent).getParcelableExtra( 120 eq(SlicePurchaseController.EXTRA_INTENT_SUCCESS), eq(PendingIntent.class)); 121 doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mRequestFailedIntent) 122 .getCreatorPackage(); 123 doReturn(true).when(mRequestFailedIntent).isBroadcast(); 124 doReturn(mRequestFailedIntent).when(spiedIntent).getParcelableExtra( 125 eq(SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED), eq(PendingIntent.class)); 126 127 mSlicePurchaseActivity = startActivity(spiedIntent, null, null); 128 } 129 130 @Test testOnPurchaseSuccessful()131 public void testOnPurchaseSuccessful() throws Exception { 132 mSlicePurchaseActivity.onPurchaseSuccessful(); 133 verify(mSuccessfulIntent).send(); 134 } 135 136 @Test testOnPurchaseFailed()137 public void testOnPurchaseFailed() throws Exception { 138 int failureCode = SlicePurchaseController.FAILURE_CODE_CARRIER_URL_UNAVAILABLE; 139 String failureReason = "Server unreachable"; 140 mSlicePurchaseActivity.onPurchaseFailed(failureCode, failureReason); 141 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 142 verify(mPendingIntent).send(eq(mContext), eq(0), intentCaptor.capture()); 143 Intent intent = intentCaptor.getValue(); 144 assertEquals(failureCode, intent.getIntExtra( 145 SlicePurchaseController.EXTRA_FAILURE_CODE, failureCode)); 146 assertEquals(failureReason, intent.getStringExtra( 147 SlicePurchaseController.EXTRA_FAILURE_REASON)); 148 } 149 150 @Test testOnUserCanceled()151 public void testOnUserCanceled() throws Exception { 152 mSlicePurchaseActivity.onDestroy(); 153 verify(mCanceledIntent).send(); 154 } 155 156 @Test testOnDismissFlow()157 public void testOnDismissFlow() throws Exception { 158 mSlicePurchaseActivity.onDismissFlow(); 159 verify(mRequestFailedIntent).send(); 160 } 161 162 @Test testStartWebView()163 public void testStartWebView() { 164 // unspecified contents type 165 SlicePurchaseActivity.startWebView(mWebView, URL, 0 /* CONTENTS_TYPE_UNSPECIFIED */, null); 166 verify(mWebView).loadUrl(eq(URL)); 167 168 // specified contents type with user data 169 String userData = "userData"; 170 byte[] userDataBytes = userData.getBytes(); 171 SlicePurchaseActivity.startWebView(mWebView, URL, 1 /* CONTENTS_TYPE_JSON */, userData); 172 verify(mWebView).postUrl(eq(URL), eq(userDataBytes)); 173 174 // specified contents type with encoded user data 175 byte[] encodedUserData = Base64.getEncoder().encode(userDataBytes); 176 userData = "encodedValue=" + new String(encodedUserData); 177 SlicePurchaseActivity.startWebView(mWebView, URL, 1 /* CONTENTS_TYPE_JSON */, userData); 178 verify(mWebView, times(2)).postUrl(eq(URL), eq(userDataBytes)); 179 } 180 } 181