1/*
2 * Copyright 2018, 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 */
16package com.android.managedprovisioning.task;
17
18import static junit.framework.Assert.assertEquals;
19import static junit.framework.Assert.assertFalse;
20import static junit.framework.Assert.assertTrue;
21
22import static org.mockito.Mockito.when;
23
24import android.content.Context;
25import android.os.FileUtils;
26import android.os.UserHandle;
27import android.os.UserManager;
28import android.support.test.InstrumentationRegistry;
29
30import com.android.managedprovisioning.task.nonrequiredapps.SystemAppsSnapshot;
31import com.android.managedprovisioning.tests.R;
32
33import org.junit.After;
34import org.junit.Assert;
35import org.junit.Before;
36import org.junit.Test;
37import org.junit.runner.RunWith;
38import org.mockito.Mock;
39import org.mockito.junit.MockitoJUnitRunner;
40
41import java.io.File;
42import java.io.FileOutputStream;
43import java.io.InputStream;
44import java.util.Arrays;
45import java.util.HashSet;
46import java.util.Set;
47
48@RunWith(MockitoJUnitRunner.class)
49public class MigrateSystemAppsSnapshotTaskTest {
50    private static final int USER_A_ID = 10;
51    private static final int USER_A_SERIAL_NUMBER = 20;
52    private static final int USER_A_SNAPSHOT_FILE = R.raw.snapshot;
53
54    private static final int USER_B_ID = 11;
55    private static final int USER_B_SERIAL_NUMBER = 21;
56    private static final int USER_B_SNAPSHOT_FILE = R.raw.snapshot2;
57
58    private static final int NOT_EXIST_USER_ID = 99;
59    private static final int INVALID_SERIAL_NUMBER = -1;
60
61    private static final Set<String> SNAPSHOT_A = new HashSet<>();
62    static {
63        SNAPSHOT_A.add("com.app.a");
64        SNAPSHOT_A.add("com.app.b");
65    }
66
67    private static final Set<String> SNAPSHOT_B = new HashSet<>();
68    static {
69        SNAPSHOT_B.add("com.app.a");
70        SNAPSHOT_B.add("com.app.c");
71    }
72
73    private MigrateSystemAppsSnapshotTask mMigrateSystemAppsSnapshotTask;
74    private SystemAppsSnapshot mSystemAppsSnapshot;
75    @Mock
76    private Context mContext;
77    @Mock
78    private AbstractProvisioningTask.Callback mCallback;
79    @Mock
80    private UserManager mUserManager;
81
82    @Before
83    public void setup() {
84        when(mContext.getFilesDir())
85                .thenReturn(
86                        new File(InstrumentationRegistry.getTargetContext().getFilesDir(), "test"));
87        mMigrateSystemAppsSnapshotTask = new MigrateSystemAppsSnapshotTask(mContext, mCallback);
88        mSystemAppsSnapshot = new SystemAppsSnapshot(mContext);
89    }
90
91    @Before
92    public void setupUserManager() {
93        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
94        when(mUserManager.getUserSerialNumber(USER_A_ID)).thenReturn(USER_A_SERIAL_NUMBER);
95        when(mUserManager.getUserSerialNumber(USER_B_ID)).thenReturn(USER_B_SERIAL_NUMBER);
96        when(mUserManager.getUserSerialNumber(NOT_EXIST_USER_ID)).thenReturn(INVALID_SERIAL_NUMBER);
97    }
98
99    @After
100    public void tearDown() {
101        FileUtils.deleteContentsAndDir(SystemAppsSnapshot.getFolder(mContext));
102        FileUtils.deleteContentsAndDir(SystemAppsSnapshot.getLegacyFolder(mContext));
103    }
104
105    @Test
106    public void testRun_nothingToMigrate() {
107        mMigrateSystemAppsSnapshotTask.run(UserHandle.USER_SYSTEM);
108
109        assertFalse(SystemAppsSnapshot.getFolder(mContext).exists());
110    }
111
112    @Test
113    public void testRun_alreadyMigrated() throws Exception {
114        copyTestFileTo(USER_A_SNAPSHOT_FILE, SystemAppsSnapshot.getFolder(mContext), "20.xml");
115
116        mMigrateSystemAppsSnapshotTask.run(UserHandle.USER_SYSTEM);
117
118        assertFilesAreMigrated(new String[]{"20.xml"});
119    }
120
121    @Test
122    public void testRun_migrate_userExists() throws Exception {
123        File legacyFolder = SystemAppsSnapshot.getLegacyFolder(mContext);
124        copyTestFileTo(USER_A_SNAPSHOT_FILE, legacyFolder, "10.xml");
125        copyTestFileTo(USER_B_SNAPSHOT_FILE, legacyFolder, "11.xml");
126
127        mMigrateSystemAppsSnapshotTask.run(UserHandle.USER_SYSTEM);
128
129        assertFilesAreMigrated(new String[] {"20.xml", "21.xml"});
130        assertSnapshotFileContent(10, SNAPSHOT_A);
131        assertSnapshotFileContent(11, SNAPSHOT_B);
132    }
133
134    @Test
135    public void testRun_migrate_userDoesNotExists() throws Exception {
136        File legacyFolder = SystemAppsSnapshot.getLegacyFolder(mContext);
137        copyTestFileTo(USER_A_SNAPSHOT_FILE, legacyFolder, "99.xml");
138
139        mMigrateSystemAppsSnapshotTask.run(UserHandle.USER_SYSTEM);
140
141        assertFilesAreMigrated(new String[] {});
142    }
143
144    @Test
145    public void testRun_migrate_invalidFileName() throws Exception {
146        File legacyFolder = SystemAppsSnapshot.getLegacyFolder(mContext);
147        copyTestFileTo(USER_A_SNAPSHOT_FILE, legacyFolder, "random.xml");
148
149        mMigrateSystemAppsSnapshotTask.run(UserHandle.USER_SYSTEM);
150
151        assertFilesAreMigrated(new String[] {});
152    }
153
154    private void copyTestFileTo(
155            int fileToBeCopied, File destinationFolder, String fileName) throws Exception {
156        File destination = new File(destinationFolder, fileName);
157        destination.getParentFile().mkdirs();
158        destination.createNewFile();
159        FileUtils.copy(getTestFile(fileToBeCopied), new FileOutputStream(destination));
160    }
161
162    private void assertSnapshotFileContent(int userId, Set<String> expected) {
163        Set<String> actual = mSystemAppsSnapshot.getSnapshot(userId);
164        assertEquals(expected, actual);
165    }
166
167    private InputStream getTestFile(int resId) {
168        return InstrumentationRegistry.getContext().getResources().openRawResource(resId);
169    }
170
171    private void assertFilesAreMigrated(String[] expectedFileNames) {
172        File legacyFolder = SystemAppsSnapshot.getLegacyFolder(mContext);
173        File newFolder = SystemAppsSnapshot.getFolder(mContext);
174
175        assertFalse(legacyFolder.exists());
176        assertTrue(newFolder.exists());
177
178        File[] files = newFolder.listFiles();
179        assertEquals(expectedFileNames.length, files.length);
180
181        String[] actualFilesNames =
182                Arrays.stream(files).map(file -> file.getName()).toArray(String[]::new);
183
184        Arrays.sort(expectedFileNames);
185        Arrays.sort(actualFilesNames);
186        Assert.assertArrayEquals(expectedFileNames, actualFilesNames);
187    }
188}
189