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.systemconfig
18 
19 import android.content.Context
20 import androidx.test.InstrumentationRegistry
21 import com.android.server.SystemConfig
22 import com.google.common.truth.Truth.assertThat
23 import org.junit.Rule
24 import org.junit.Test
25 import org.junit.rules.ExpectedException
26 import org.junit.rules.TemporaryFolder
27 
28 class SystemConfigNamedActorTest {
29 
30     companion object {
31         private const val NAMESPACE_TEST = "someTestNamespace"
32         private const val NAMESPACE_ANDROID = "android"
33         private const val ACTOR_ONE = "iconShaper"
34         private const val ACTOR_TWO = "colorChanger"
35         private const val PACKAGE_ONE = "com.test.actor.one"
36         private const val PACKAGE_TWO = "com.test.actor.two"
37     }
38 
39     private val context: Context = InstrumentationRegistry.getContext()
40 
41     @get:Rule
42     val tempFolder = TemporaryFolder(context.filesDir)
43 
44     @get:Rule
45     val expected = ExpectedException.none()
46 
47     private var uniqueCounter = 0
48 
49     @Test
50     fun twoUnique() {
51         """
52             <config>
53                 <named-actor
54                     namespace="$NAMESPACE_TEST"
55                     name="$ACTOR_ONE"
56                     package="$PACKAGE_ONE"
57                     />
58                 <named-actor
59                     namespace="$NAMESPACE_TEST"
60                     name="$ACTOR_TWO"
61                     package="$PACKAGE_TWO"
62                     />
63             </config>
64         """.write()
65 
66         assertPermissions().containsExactlyEntriesIn(
67                 mapOf(
68                         NAMESPACE_TEST to mapOf(
69                             ACTOR_ONE to PACKAGE_ONE,
70                             ACTOR_TWO to PACKAGE_TWO
71                         )
72                 )
73         )
74     }
75 
76     @Test
77     fun twoSamePackage() {
78         """
79             <config>
80                 <named-actor
81                     namespace="$NAMESPACE_TEST"
82                     name="$ACTOR_ONE"
83                     package="$PACKAGE_ONE"
84                     />
85                 <named-actor
86                     namespace="$NAMESPACE_TEST"
87                     name="$ACTOR_TWO"
88                     package="$PACKAGE_ONE"
89                     />
90             </config>
91         """.write()
92 
93         assertPermissions().containsExactlyEntriesIn(
94                 mapOf(
95                         NAMESPACE_TEST to mapOf(
96                             ACTOR_ONE to PACKAGE_ONE,
97                             ACTOR_TWO to PACKAGE_ONE
98                         )
99                 )
100         )
101     }
102 
103     @Test
104     fun missingNamespace() {
105         """
106             <config>
107                 <named-actor
108                     name="$ACTOR_ONE"
109                     package="$PACKAGE_ONE"
110                     />
111                 <named-actor
112                     namespace="$NAMESPACE_TEST"
113                     name="$ACTOR_TWO"
114                     package="$PACKAGE_TWO"
115                     />
116             </config>
117         """.write()
118 
119         assertPermissions().containsExactlyEntriesIn(
120                 mapOf(
121                         NAMESPACE_TEST to mapOf(
122                                 ACTOR_TWO to PACKAGE_TWO
123                         )
124                 )
125         )
126     }
127 
128     @Test
129     fun missingName() {
130         """
131             <config>
132                 <named-actor
133                     namespace="$NAMESPACE_TEST"
134                     package="$PACKAGE_ONE"
135                     />
136                 <named-actor
137                     namespace="$NAMESPACE_TEST"
138                     name="$ACTOR_TWO"
139                     package="$PACKAGE_TWO"
140                     />
141             </config>
142         """.write()
143 
144         assertPermissions().containsExactlyEntriesIn(
145                 mapOf(
146                         NAMESPACE_TEST to mapOf(
147                                 ACTOR_TWO to PACKAGE_TWO
148                         )
149                 )
150         )
151     }
152 
153     @Test
154     fun missingPackage() {
155         """
156             <config>
157                 <named-actor
158                     namespace="$NAMESPACE_TEST"
159                     name="$ACTOR_ONE"
160                     />
161                 <named-actor
162                     namespace="$NAMESPACE_TEST"
163                     name="$ACTOR_TWO"
164                     package="$PACKAGE_TWO"
165                     />
166             </config>
167         """.write()
168 
169         assertPermissions().containsExactlyEntriesIn(
170                 mapOf(
171                         NAMESPACE_TEST to mapOf(
172                                 ACTOR_TWO to PACKAGE_TWO
173                         )
174                 )
175         )
176     }
177 
178     @Test
179     fun androidNamespaceThrows() {
180         """
181             <config>
182                 <named-actor
183                     namespace="$NAMESPACE_TEST"
184                     name="$ACTOR_ONE"
185                     package="$PACKAGE_ONE"
186                     />
187                 <named-actor
188                     namespace="$NAMESPACE_ANDROID"
189                     name="$ACTOR_ONE"
190                     package="$PACKAGE_ONE"
191                     />
192             </config>
193         """.write()
194 
195         expected.expect(IllegalStateException::class.java)
196         expected.expectMessage("Defining $ACTOR_ONE as $PACKAGE_ONE " +
197                 "for the android namespace is not allowed")
198 
199         assertPermissions()
200     }
201 
202     @Test
203     fun duplicateActorNameThrows() {
204         """
205             <config>
206                 <named-actor
207                     namespace="$NAMESPACE_TEST"
208                     name="$ACTOR_ONE"
209                     package="$PACKAGE_ONE"
210                     />
211                 <named-actor
212                     namespace="$NAMESPACE_TEST"
213                     name="$ACTOR_ONE"
214                     package="$PACKAGE_TWO"
215                     />
216             </config>
217         """.write()
218 
219         expected.expect(IllegalStateException::class.java)
220         expected.expectMessage("Duplicate actor definition for $NAMESPACE_TEST/$ACTOR_ONE;" +
221                 " defined as both $PACKAGE_ONE and $PACKAGE_TWO")
222 
223         assertPermissions()
224     }
225 
226     private fun String.write() = tempFolder.root.resolve("${uniqueCounter++}.xml")
227             .writeText(this.trimIndent())
228 
229     private fun assertPermissions() = SystemConfig(false).apply {
230         readPermissions(tempFolder.root, 0)
231     }. let { assertThat(it.namedActors) }
232 }
233