VpnTest.java revision 4d03abcd49af490dba3850d341b955dd72f24959
1/* 2 * Copyright (C) 2016 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 17package com.android.server.connectivity; 18 19import static android.content.pm.UserInfo.FLAG_ADMIN; 20import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; 21import static android.content.pm.UserInfo.FLAG_PRIMARY; 22import static android.content.pm.UserInfo.FLAG_RESTRICTED; 23import static org.mockito.Mockito.*; 24 25import android.annotation.UserIdInt; 26import android.content.Context; 27import android.content.pm.PackageManager; 28import android.content.pm.UserInfo; 29import android.net.UidRange; 30import android.os.INetworkManagementService; 31import android.os.Looper; 32import android.os.UserHandle; 33import android.os.UserManager; 34import android.test.AndroidTestCase; 35import android.test.suitebuilder.annotation.SmallTest; 36import android.util.ArrayMap; 37import android.util.ArraySet; 38 39import java.util.ArrayList; 40import java.util.Arrays; 41import java.util.Map; 42import java.util.Set; 43 44import org.mockito.Mock; 45import org.mockito.MockitoAnnotations; 46 47/** 48 * Tests for {@link Vpn}. 49 * 50 * Build, install and run with: 51 * runtest --path src/com/android/server/connectivity/VpnTest.java 52 */ 53public class VpnTest extends AndroidTestCase { 54 private static final String TAG = "VpnTest"; 55 56 // Mock users 57 static final UserInfo primaryUser = new UserInfo(27, "Primary", FLAG_ADMIN | FLAG_PRIMARY); 58 static final UserInfo secondaryUser = new UserInfo(15, "Secondary", FLAG_ADMIN); 59 static final UserInfo restrictedProfileA = new UserInfo(40, "RestrictedA", FLAG_RESTRICTED); 60 static final UserInfo restrictedProfileB = new UserInfo(42, "RestrictedB", FLAG_RESTRICTED); 61 static final UserInfo managedProfileA = new UserInfo(45, "ManagedA", FLAG_MANAGED_PROFILE); 62 static { 63 restrictedProfileA.restrictedProfileParentId = primaryUser.id; 64 restrictedProfileB.restrictedProfileParentId = secondaryUser.id; 65 managedProfileA.profileGroupId = primaryUser.id; 66 } 67 68 @Mock private Context mContext; 69 @Mock private UserManager mUserManager; 70 @Mock private PackageManager mPackageManager; 71 @Mock private INetworkManagementService mNetService; 72 73 @Override 74 public void setUp() throws Exception { 75 MockitoAnnotations.initMocks(this); 76 when(mContext.getPackageManager()).thenReturn(mPackageManager); 77 when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); 78 doNothing().when(mNetService).registerObserver(any()); 79 } 80 81 @SmallTest 82 public void testRestrictedProfilesAreAddedToVpn() { 83 setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); 84 85 final Vpn vpn = createVpn(primaryUser.id); 86 final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 87 null, null); 88 89 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 90 UidRange.createForUser(primaryUser.id), 91 UidRange.createForUser(restrictedProfileA.id) 92 })), ranges); 93 } 94 95 @SmallTest 96 public void testManagedProfilesAreNotAddedToVpn() { 97 setMockedUsers(primaryUser, managedProfileA); 98 99 final Vpn vpn = createVpn(primaryUser.id); 100 final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 101 null, null); 102 103 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 104 UidRange.createForUser(primaryUser.id) 105 })), ranges); 106 } 107 108 @SmallTest 109 public void testAddUserToVpnOnlyAddsOneUser() { 110 setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); 111 112 final Vpn vpn = createVpn(primaryUser.id); 113 final Set<UidRange> ranges = new ArraySet<>(); 114 vpn.addUserToRanges(ranges, primaryUser.id, null, null); 115 116 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 117 UidRange.createForUser(primaryUser.id) 118 })), ranges); 119 } 120 121 @SmallTest 122 public void testUidWhiteAndBlacklist() throws Exception { 123 final Map<String, Integer> packages = new ArrayMap<>(); 124 packages.put("com.example", 66); 125 packages.put("org.example", 77); 126 packages.put("net.example", 78); 127 setMockedPackages(packages); 128 129 final Vpn vpn = createVpn(primaryUser.id); 130 final UidRange user = UidRange.createForUser(primaryUser.id); 131 132 // Whitelist 133 final Set<UidRange> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 134 new ArrayList<String>(packages.keySet()), null); 135 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 136 new UidRange(user.start + 66, user.start + 66), 137 new UidRange(user.start + 77, user.start + 78) 138 })), allow); 139 140 // Blacklist 141 final Set<UidRange> disallow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 142 null, new ArrayList<String>(packages.keySet())); 143 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 144 new UidRange(user.start, user.start + 65), 145 new UidRange(user.start + 67, user.start + 76), 146 new UidRange(user.start + 79, user.stop) 147 })), disallow); 148 } 149 150 /** 151 * @return A subclass of {@link Vpn} which is reliably: 152 * <ul> 153 * <li>Associated with a specific user ID</li> 154 * <li>Not in always-on mode</li> 155 * </ul> 156 */ 157 private Vpn createVpn(@UserIdInt int userId) { 158 return new Vpn(Looper.myLooper(), mContext, mNetService, userId); 159 } 160 161 /** 162 * Populate {@link #mUserManager} with a list of fake users. 163 */ 164 private void setMockedUsers(UserInfo... users) { 165 final Map<Integer, UserInfo> userMap = new ArrayMap<>(); 166 for (UserInfo user : users) { 167 userMap.put(user.id, user); 168 } 169 170 doAnswer(invocation -> { 171 return new ArrayList(userMap.values()); 172 }).when(mUserManager).getUsers(); 173 174 doAnswer(invocation -> { 175 final int id = (int) invocation.getArguments()[0]; 176 return userMap.get(id); 177 }).when(mUserManager).getUserInfo(anyInt()); 178 179 doAnswer(invocation -> { 180 final int id = (int) invocation.getArguments()[0]; 181 return (userMap.get(id).flags & UserInfo.FLAG_ADMIN) != 0; 182 }).when(mUserManager).canHaveRestrictedProfile(anyInt()); 183 } 184 185 /** 186 * Populate {@link #mPackageManager} with a fake packageName-to-UID mapping. 187 */ 188 private void setMockedPackages(final Map<String, Integer> packages) { 189 try { 190 doAnswer(invocation -> { 191 final String appName = (String) invocation.getArguments()[0]; 192 final int userId = (int) invocation.getArguments()[1]; 193 return UserHandle.getUid(userId, packages.get(appName)); 194 }).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt()); 195 } catch (Exception e) { 196 } 197 } 198} 199