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.intentresolver
18 
19 import com.google.common.truth.Truth.assertThat
20 import org.junit.Test
21 
22 /**
23  * Unit tests for the various implementations of {@link TargetPresentationGetter}.
24  *
25  * TODO: consider expanding to cover icon logic (not just labels/sublabels).
26  * TODO: these are conceptually "acceptance tests" that provide comprehensive coverage of the
27  *   apparent variations in the legacy implementation. The tests probably don't have to be so
28  *   exhaustive if we're able to impose a simpler design on the implementation.
29  */
30 class TargetPresentationGetterTest {
makeResolveInfoPresentationGetternull31     fun makeResolveInfoPresentationGetter(
32         withSubstitutePermission: Boolean,
33         appLabel: String,
34         activityLabel: String,
35         resolveInfoLabel: String
36     ): TargetPresentationGetter {
37         val testPackageInfo =
38             ResolverDataProvider.createPackageManagerMockedInfo(
39                 withSubstitutePermission,
40                 appLabel,
41                 activityLabel,
42                 resolveInfoLabel
43             )
44         val factory = TargetPresentationGetter.Factory(testPackageInfo.ctx, 100)
45         return factory.makePresentationGetter(testPackageInfo.resolveInfo)
46     }
47 
makeActivityInfoPresentationGetternull48     fun makeActivityInfoPresentationGetter(
49         withSubstitutePermission: Boolean,
50         appLabel: String?,
51         activityLabel: String?
52     ): TargetPresentationGetter {
53         val testPackageInfo =
54             ResolverDataProvider.createPackageManagerMockedInfo(
55                 withSubstitutePermission,
56                 appLabel,
57                 activityLabel,
58                 ""
59             )
60         val factory = TargetPresentationGetter.Factory(testPackageInfo.ctx, 100)
61         return factory.makePresentationGetter(testPackageInfo.activityInfo)
62     }
63 
64     @Test
testActivityInfoLabels_noSubstitutePermission_distinctRequestedLabelAndSublabelnull65     fun testActivityInfoLabels_noSubstitutePermission_distinctRequestedLabelAndSublabel() {
66         val presentationGetter =
67             makeActivityInfoPresentationGetter(false, "app_label", "activity_label")
68         assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
69         assertThat(presentationGetter.getSubLabel()).isEqualTo("activity_label")
70     }
71 
72     @Test
testActivityInfoLabels_noSubstitutePermission_sameRequestedLabelAndSublabelnull73     fun testActivityInfoLabels_noSubstitutePermission_sameRequestedLabelAndSublabel() {
74         val presentationGetter = makeActivityInfoPresentationGetter(false, "app_label", "app_label")
75         assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
76         // Without the substitute permission, there's no logic to dedupe the labels.
77         // TODO: this matches our observations in the legacy code, but is it the right behavior? It
78         // seems like {@link ResolverListAdapter.ViewHolder#bindLabel()} has some logic to dedupe in
79         // the UI at least, but maybe that logic should be pulled back to the "presentation"?
80         assertThat(presentationGetter.getSubLabel()).isEqualTo("app_label")
81     }
82 
83     @Test
testActivityInfoLabels_noSubstitutePermission_nullRequestedLabelnull84     fun testActivityInfoLabels_noSubstitutePermission_nullRequestedLabel() {
85         val presentationGetter = makeActivityInfoPresentationGetter(false, null, "activity_label")
86         assertThat(presentationGetter.getLabel()).isNull()
87         assertThat(presentationGetter.getSubLabel()).isEqualTo("activity_label")
88     }
89 
90     @Test
testActivityInfoLabels_noSubstitutePermission_emptyRequestedLabelnull91     fun testActivityInfoLabels_noSubstitutePermission_emptyRequestedLabel() {
92         val presentationGetter = makeActivityInfoPresentationGetter(false, "", "activity_label")
93         assertThat(presentationGetter.getLabel()).isEqualTo("")
94         assertThat(presentationGetter.getSubLabel()).isEqualTo("activity_label")
95     }
96 
97     @Test
testActivityInfoLabels_noSubstitutePermission_emptyRequestedSublabelnull98     fun testActivityInfoLabels_noSubstitutePermission_emptyRequestedSublabel() {
99         val presentationGetter = makeActivityInfoPresentationGetter(false, "app_label", "")
100         assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
101         // Without the substitute permission, empty sublabels are passed through as-is.
102         assertThat(presentationGetter.getSubLabel()).isEqualTo("")
103     }
104 
105     @Test
testActivityInfoLabels_withSubstitutePermission_distinctRequestedLabelAndSublabelnull106     fun testActivityInfoLabels_withSubstitutePermission_distinctRequestedLabelAndSublabel() {
107         val presentationGetter =
108             makeActivityInfoPresentationGetter(true, "app_label", "activity_label")
109         assertThat(presentationGetter.getLabel()).isEqualTo("activity_label")
110         // With the substitute permission, the same ("activity") label is requested as both the
111         // label
112         // and sublabel, even though the other value ("app_label") was distinct. Thus this behaves
113         // the
114         // same as a dupe.
115         assertThat(presentationGetter.getSubLabel()).isEqualTo(null)
116     }
117 
118     @Test
testActivityInfoLabels_withSubstitutePermission_sameRequestedLabelAndSublabelnull119     fun testActivityInfoLabels_withSubstitutePermission_sameRequestedLabelAndSublabel() {
120         val presentationGetter = makeActivityInfoPresentationGetter(true, "app_label", "app_label")
121         assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
122         // With the substitute permission, duped sublabels get converted to nulls.
123         assertThat(presentationGetter.getSubLabel()).isNull()
124     }
125 
126     @Test
testActivityInfoLabels_withSubstitutePermission_nullRequestedLabelnull127     fun testActivityInfoLabels_withSubstitutePermission_nullRequestedLabel() {
128         val presentationGetter = makeActivityInfoPresentationGetter(true, "app_label", null)
129         assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
130         // With the substitute permission, null inputs are a special case that produces null outputs
131         // (i.e., they're not simply passed-through from the inputs).
132         assertThat(presentationGetter.getSubLabel()).isNull()
133     }
134 
135     @Test
testActivityInfoLabels_withSubstitutePermission_emptyRequestedLabelnull136     fun testActivityInfoLabels_withSubstitutePermission_emptyRequestedLabel() {
137         val presentationGetter = makeActivityInfoPresentationGetter(true, "app_label", "")
138         // Empty "labels" are taken as-is and (unlike nulls) don't prompt a fallback to the
139         // sublabel.
140         // Thus (as in the previous case with substitute permission & "distinct" labels), this is
141         // treated as a dupe.
142         assertThat(presentationGetter.getLabel()).isEqualTo("")
143         assertThat(presentationGetter.getSubLabel()).isNull()
144     }
145 
146     @Test
testActivityInfoLabels_withSubstitutePermission_emptyRequestedSublabelnull147     fun testActivityInfoLabels_withSubstitutePermission_emptyRequestedSublabel() {
148         val presentationGetter = makeActivityInfoPresentationGetter(true, "", "activity_label")
149         assertThat(presentationGetter.getLabel()).isEqualTo("activity_label")
150         // With the substitute permission, empty sublabels get converted to nulls.
151         assertThat(presentationGetter.getSubLabel()).isNull()
152     }
153 
154     @Test
testResolveInfoLabels_noSubstitutePermission_distinctRequestedLabelAndSublabelnull155     fun testResolveInfoLabels_noSubstitutePermission_distinctRequestedLabelAndSublabel() {
156         val presentationGetter =
157             makeResolveInfoPresentationGetter(
158                 false,
159                 "app_label",
160                 "activity_label",
161                 "resolve_info_label"
162             )
163         assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
164         assertThat(presentationGetter.getSubLabel()).isEqualTo("resolve_info_label")
165     }
166 
167     @Test
testResolveInfoLabels_noSubstitutePermission_sameRequestedLabelAndSublabelnull168     fun testResolveInfoLabels_noSubstitutePermission_sameRequestedLabelAndSublabel() {
169         val presentationGetter =
170             makeResolveInfoPresentationGetter(false, "app_label", "activity_label", "app_label")
171         assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
172         // Without the substitute permission, there's no logic to dedupe the labels.
173         // TODO: this matches our observations in the legacy code, but is it the right behavior? It
174         // seems like {@link ResolverListAdapter.ViewHolder#bindLabel()} has some logic to dedupe in
175         // the UI at least, but maybe that logic should be pulled back to the "presentation"?
176         assertThat(presentationGetter.getSubLabel()).isEqualTo("app_label")
177     }
178 
179     @Test
testResolveInfoLabels_noSubstitutePermission_emptyRequestedSublabelnull180     fun testResolveInfoLabels_noSubstitutePermission_emptyRequestedSublabel() {
181         val presentationGetter =
182             makeResolveInfoPresentationGetter(false, "app_label", "activity_label", "")
183         assertThat(presentationGetter.getLabel()).isEqualTo("app_label")
184         // Without the substitute permission, empty sublabels are passed through as-is.
185         assertThat(presentationGetter.getSubLabel()).isEqualTo("")
186     }
187 
188     @Test
testResolveInfoLabels_withSubstitutePermission_distinctRequestedLabelAndSublabelnull189     fun testResolveInfoLabels_withSubstitutePermission_distinctRequestedLabelAndSublabel() {
190         val presentationGetter =
191             makeResolveInfoPresentationGetter(
192                 true,
193                 "app_label",
194                 "activity_label",
195                 "resolve_info_label"
196             )
197         assertThat(presentationGetter.getLabel()).isEqualTo("activity_label")
198         assertThat(presentationGetter.getSubLabel()).isEqualTo("resolve_info_label")
199     }
200 
201     @Test
testResolveInfoLabels_withSubstitutePermission_sameRequestedLabelAndSublabelnull202     fun testResolveInfoLabels_withSubstitutePermission_sameRequestedLabelAndSublabel() {
203         val presentationGetter =
204             makeResolveInfoPresentationGetter(true, "app_label", "activity_label", "activity_label")
205         assertThat(presentationGetter.getLabel()).isEqualTo("activity_label")
206         // With the substitute permission, duped sublabels get converted to nulls.
207         assertThat(presentationGetter.getSubLabel()).isNull()
208     }
209 
210     @Test
testResolveInfoLabels_withSubstitutePermission_emptyRequestedSublabelnull211     fun testResolveInfoLabels_withSubstitutePermission_emptyRequestedSublabel() {
212         val presentationGetter =
213             makeResolveInfoPresentationGetter(true, "app_label", "activity_label", "")
214         assertThat(presentationGetter.getLabel()).isEqualTo("activity_label")
215         // With the substitute permission, empty sublabels get converted to nulls.
216         assertThat(presentationGetter.getSubLabel()).isNull()
217     }
218 
219     @Test
testResolveInfoLabels_withSubstitutePermission_emptyRequestedLabelAndSublabelnull220     fun testResolveInfoLabels_withSubstitutePermission_emptyRequestedLabelAndSublabel() {
221         val presentationGetter = makeResolveInfoPresentationGetter(true, "app_label", "", "")
222         assertThat(presentationGetter.getLabel()).isEqualTo("")
223         // With the substitute permission, empty sublabels get converted to nulls.
224         assertThat(presentationGetter.getSubLabel()).isNull()
225     }
226 }
227