1 /*
2  * Copyright (C) 2019 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.pm;
18 
19 import static org.hamcrest.MatcherAssert.assertThat;
20 import static org.hamcrest.core.Is.is;
21 import static org.mockito.ArgumentMatchers.argThat;
22 import static org.mockito.ArgumentMatchers.eq;
23 import static org.mockito.Mockito.when;
24 
25 import android.os.Build;
26 import android.platform.test.annotations.Presubmit;
27 
28 import com.android.server.compat.PlatformCompat;
29 import com.android.server.pm.parsing.pkg.PackageImpl;
30 import com.android.server.pm.parsing.pkg.ParsedPackage;
31 import com.android.server.pm.pkg.PackageState;
32 
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.mockito.Mock;
36 import org.mockito.Mockito;
37 import org.mockito.junit.MockitoJUnitRunner;
38 
39 
40 /**
41  * {@link SELinuxMMAC} tests.
42  */
43 @RunWith(MockitoJUnitRunner.class)
44 @Presubmit
45 public class SELinuxMMACTest {
46 
47     private static final String PACKAGE_NAME = "my.package";
48     private static final int LATEST_OPT_IN_VERSION = Build.VERSION_CODES.CUR_DEVELOPMENT;
49     private static final int R_OPT_IN_VERSION = Build.VERSION_CODES.R;
50 
51     @Mock
52     PlatformCompat mMockCompatibility;
53 
54     @Test
getSeInfoOptInToLatest()55     public void getSeInfoOptInToLatest() {
56         var packageState = makePackageState(Build.VERSION_CODES.P);
57         when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
58                 argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
59                 .thenReturn(true);
60         assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
61                         mMockCompatibility),
62                 is("default:targetSdkVersion=" + LATEST_OPT_IN_VERSION));
63     }
64 
65     @Test
getSeInfoOptInToR()66     public void getSeInfoOptInToR() {
67         var packageState = makePackageState(Build.VERSION_CODES.P);
68         when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
69                 argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
70                 .thenReturn(true);
71         assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
72                         mMockCompatibility),
73                 is("default:targetSdkVersion=" + R_OPT_IN_VERSION));
74     }
75 
76     @Test
getSeInfoNoOptIn()77     public void getSeInfoNoOptIn() {
78         var packageState = makePackageState(Build.VERSION_CODES.P);
79         when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
80                 argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
81                 .thenReturn(false);
82         assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
83                         mMockCompatibility),
84                 is("default:targetSdkVersion=28"));
85     }
86 
87     @Test
getSeInfoNoOptInButAlreadyLatest()88     public void getSeInfoNoOptInButAlreadyLatest() {
89         var packageState = makePackageState(LATEST_OPT_IN_VERSION);
90         when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
91                 argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
92                 .thenReturn(false);
93         assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
94                         mMockCompatibility),
95                 is("default:targetSdkVersion=" + LATEST_OPT_IN_VERSION));
96     }
97 
98     @Test
getSeInfoTargetingCurDevelopment()99     public void getSeInfoTargetingCurDevelopment() {
100         var packageState = makePackageState(Build.VERSION_CODES.CUR_DEVELOPMENT);
101         when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_LATEST_CHANGES),
102                 argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
103                 .thenReturn(true);
104         assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
105                         mMockCompatibility),
106                 is("default:targetSdkVersion=" + Build.VERSION_CODES.CUR_DEVELOPMENT));
107     }
108 
109     @Test
getSeInfoNoOptInButAlreadyR()110     public void getSeInfoNoOptInButAlreadyR() {
111         var packageState = makePackageState(R_OPT_IN_VERSION);
112         when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
113                 argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
114                 .thenReturn(false);
115         assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
116                         mMockCompatibility),
117                 is("default:targetSdkVersion=" + R_OPT_IN_VERSION));
118     }
119 
120     @Test
getSeInfoOptInRButLater()121     public void getSeInfoOptInRButLater() {
122         var packageState = makePackageState(R_OPT_IN_VERSION + 1);
123         when(mMockCompatibility.isChangeEnabledInternal(eq(SELinuxMMAC.SELINUX_R_CHANGES),
124                 argThat(argument -> argument.packageName.equals(packageState.getPackageName()))))
125                 .thenReturn(true);
126         assertThat(SELinuxMMAC.getSeInfo(packageState, packageState.getAndroidPackage(), null,
127                         mMockCompatibility),
128                 is("default:targetSdkVersion=" + (R_OPT_IN_VERSION + 1)));
129     }
130 
makePackageState(int targetSdkVersion)131     private PackageState makePackageState(int targetSdkVersion) {
132         var packageState = Mockito.mock(PackageState.class);
133         when(packageState.getPackageName()).thenReturn(PACKAGE_NAME);
134         when(packageState.getAndroidPackage()).thenReturn(
135                 ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
136                         .setTargetSdkVersion(targetSdkVersion)
137                         .hideAsParsed())
138                         .hideAsFinal()
139         );
140         return packageState;
141     }
142 }
143