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.server.grammaticalinflection; 18 19 import static junit.framework.Assert.assertNull; 20 import static junit.framework.Assert.assertTrue; 21 22 import static org.mockito.ArgumentMatchers.any; 23 import static org.mockito.ArgumentMatchers.anyInt; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.verify; 27 28 import android.content.pm.ApplicationInfo; 29 import android.content.pm.PackageManager; 30 import android.content.res.Configuration; 31 32 import androidx.test.ext.junit.runners.AndroidJUnit4; 33 34 import com.google.common.collect.Maps; 35 36 import org.junit.Before; 37 import org.junit.Rule; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 import org.mockito.Mock; 41 import org.mockito.junit.MockitoJUnit; 42 import org.mockito.junit.MockitoRule; 43 44 import java.io.ByteArrayInputStream; 45 import java.io.ByteArrayOutputStream; 46 import java.io.IOException; 47 import java.io.ObjectInputStream; 48 import java.io.ObjectOutputStream; 49 import java.util.HashMap; 50 import java.util.List; 51 52 @RunWith(AndroidJUnit4.class) 53 public class GrammaticalInflectionBackupTest { 54 private static final int DEFAULT_USER_ID = 0; 55 private static final String DEFAULT_PACKAGE_NAME = "com.test.package.name"; 56 57 @Rule 58 public final MockitoRule mockito = MockitoJUnit.rule(); 59 60 @Mock 61 private PackageManager mMockPackageManager; 62 @Mock 63 private GrammaticalInflectionService mGrammaticalInflectionService; 64 65 private GrammaticalInflectionBackupHelper mBackupHelper; 66 67 @Before setUp()68 public void setUp() throws Exception { 69 mBackupHelper = new GrammaticalInflectionBackupHelper( 70 mGrammaticalInflectionService, mMockPackageManager); 71 } 72 73 @Test testBackupPayload_noAppsInstalled_returnsNull()74 public void testBackupPayload_noAppsInstalled_returnsNull() { 75 assertNull(mBackupHelper.getBackupPayload(DEFAULT_USER_ID)); 76 } 77 78 @Test testBackupPayload_AppsInstalled_returnsGender()79 public void testBackupPayload_AppsInstalled_returnsGender() 80 throws IOException, ClassNotFoundException { 81 mockAppInstalled(); 82 mockGetApplicationGrammaticalGender(Configuration.GRAMMATICAL_GENDER_MASCULINE); 83 84 HashMap<String, Integer> payload = 85 readFromByteArray(mBackupHelper.getBackupPayload(DEFAULT_USER_ID)); 86 87 // verify the payload 88 HashMap<String, Integer> expectationMap = new HashMap<>(); 89 expectationMap.put(DEFAULT_PACKAGE_NAME, Configuration.GRAMMATICAL_GENDER_MASCULINE); 90 assertTrue(Maps.difference(payload, expectationMap).areEqual()); 91 } 92 93 @Test testApplyPayload_onPackageAdded_setApplicationGrammaticalGender()94 public void testApplyPayload_onPackageAdded_setApplicationGrammaticalGender() 95 throws IOException { 96 mockAppInstalled(); 97 98 HashMap<String, Integer> testData = new HashMap<>(); 99 testData.put(DEFAULT_PACKAGE_NAME, Configuration.GRAMMATICAL_GENDER_NEUTRAL); 100 mBackupHelper.stageAndApplyRestoredPayload(convertToByteArray(testData), DEFAULT_USER_ID); 101 mBackupHelper.onPackageAdded(DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID); 102 103 verify(mGrammaticalInflectionService).setRequestedApplicationGrammaticalGender( 104 eq(DEFAULT_PACKAGE_NAME), 105 eq(DEFAULT_USER_ID), 106 eq(Configuration.GRAMMATICAL_GENDER_NEUTRAL)); 107 } 108 mockAppInstalled()109 private void mockAppInstalled() { 110 ApplicationInfo dummyApp = new ApplicationInfo(); 111 dummyApp.packageName = DEFAULT_PACKAGE_NAME; 112 doReturn(List.of(dummyApp)).when(mMockPackageManager) 113 .getInstalledApplicationsAsUser(any(), anyInt()); 114 } 115 mockGetApplicationGrammaticalGender(int grammaticalGender)116 private void mockGetApplicationGrammaticalGender(int grammaticalGender) { 117 doReturn(grammaticalGender).when(mGrammaticalInflectionService) 118 .getApplicationGrammaticalGender( 119 eq(DEFAULT_PACKAGE_NAME), eq(DEFAULT_USER_ID)); 120 } 121 convertToByteArray(HashMap<String, Integer> pkgGenderInfo)122 private byte[] convertToByteArray(HashMap<String, Integer> pkgGenderInfo) throws IOException{ 123 try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); 124 final ObjectOutputStream objStream = new ObjectOutputStream(out)) { 125 objStream.writeObject(pkgGenderInfo); 126 return out.toByteArray(); 127 } catch (IOException e) { 128 throw e; 129 } 130 } 131 readFromByteArray(byte[] payload)132 private HashMap<String, Integer> readFromByteArray(byte[] payload) 133 throws IOException, ClassNotFoundException { 134 HashMap<String, Integer> data; 135 136 try (ByteArrayInputStream byteIn = new ByteArrayInputStream(payload); 137 ObjectInputStream in = new ObjectInputStream(byteIn)) { 138 data = (HashMap<String, Integer>) in.readObject(); 139 } catch (IOException | ClassNotFoundException e) { 140 throw e; 141 } 142 return data; 143 } 144 } 145