blob: 614681f506cabd98ed3cc8d24d20e97ed21a8db3 [file] [log] [blame]
Ulya Trafimovich69612672020-10-20 17:41:54 +01001// Copyright 2020 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package dexpreopt
16
17// This file contains unit tests for class loader context structure.
18// For class loader context tests involving .bp files, see TestUsesLibraries in java package.
19
20import (
Ulya Trafimovich7bc1cf52021-01-05 15:41:55 +000021 "fmt"
Ulya Trafimovich69612672020-10-20 17:41:54 +010022 "reflect"
23 "strings"
24 "testing"
25
26 "android/soong/android"
27)
28
29func TestCLC(t *testing.T) {
30 // Construct class loader context with the following structure:
31 // .
32 // ├── 29
33 // │   ├── android.hidl.manager
34 // │   └── android.hidl.base
35 // │
36 // └── any
37 // ├── a
38 // ├── b
39 // ├── c
40 // ├── d
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +000041 // │   ├── a2
42 // │   ├── b2
43 // │   └── c2
44 // │   ├── a1
45 // │   └── b1
Ulya Trafimovich69612672020-10-20 17:41:54 +010046 // ├── f
47 // ├── a3
48 // └── b3
49 //
50 ctx := testContext()
51
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +010052 optional := false
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010053 implicit := true
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +010054
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +000055 m := make(ClassLoaderContextMap)
Ulya Trafimovich69612672020-10-20 17:41:54 +010056
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010057 m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
58 m.AddContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
59 m.AddContext(ctx, AnySdkVersion, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
Ulya Trafimovich69612672020-10-20 17:41:54 +010060
61 // Add some libraries with nested subcontexts.
62
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +000063 m1 := make(ClassLoaderContextMap)
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010064 m1.AddContext(ctx, AnySdkVersion, "a1", optional, implicit, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
65 m1.AddContext(ctx, AnySdkVersion, "b1", optional, implicit, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
Ulya Trafimovich69612672020-10-20 17:41:54 +010066
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +000067 m2 := make(ClassLoaderContextMap)
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010068 m2.AddContext(ctx, AnySdkVersion, "a2", optional, implicit, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
69 m2.AddContext(ctx, AnySdkVersion, "b2", optional, implicit, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
70 m2.AddContext(ctx, AnySdkVersion, "c2", optional, implicit, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
Ulya Trafimovich69612672020-10-20 17:41:54 +010071
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +000072 m3 := make(ClassLoaderContextMap)
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010073 m3.AddContext(ctx, AnySdkVersion, "a3", optional, implicit, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
74 m3.AddContext(ctx, AnySdkVersion, "b3", optional, implicit, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
Ulya Trafimovich69612672020-10-20 17:41:54 +010075
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010076 m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +000077 // When the same library is both in conditional and unconditional context, it should be removed
78 // from conditional context.
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010079 m.AddContext(ctx, 42, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
80 m.AddContext(ctx, AnySdkVersion, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
Ulya Trafimovich18554242020-11-03 15:55:11 +000081
82 // Merge map with implicit root library that is among toplevel contexts => does nothing.
83 m.AddContextMap(m1, "c")
84 // Merge map with implicit root library that is not among toplevel contexts => all subcontexts
85 // of the other map are added as toplevel contexts.
86 m.AddContextMap(m3, "m_g")
Ulya Trafimovich69612672020-10-20 17:41:54 +010087
88 // Compatibility libraries with unknown install paths get default paths.
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010089 m.AddContext(ctx, 29, AndroidHidlManager, optional, implicit, buildPath(ctx, AndroidHidlManager), nil, nil)
90 m.AddContext(ctx, 29, AndroidHidlBase, optional, implicit, buildPath(ctx, AndroidHidlBase), nil, nil)
Ulya Trafimovich69612672020-10-20 17:41:54 +010091
92 // Add "android.test.mock" to conditional CLC, observe that is gets removed because it is only
93 // needed as a compatibility library if "android.test.runner" is in CLC as well.
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +010094 m.AddContext(ctx, 30, AndroidTestMock, optional, implicit, buildPath(ctx, AndroidTestMock), nil, nil)
Ulya Trafimovich69612672020-10-20 17:41:54 +010095
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +000096 valid, validationError := validateClassLoaderContext(m)
Ulya Trafimovich69612672020-10-20 17:41:54 +010097
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +000098 fixClassLoaderContext(m)
Ulya Trafimovich69612672020-10-20 17:41:54 +010099
100 var haveStr string
101 var havePaths android.Paths
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +0100102 var haveUsesLibsReq, haveUsesLibsOpt []string
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +0000103 if valid && validationError == nil {
104 haveStr, havePaths = ComputeClassLoaderContext(m)
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +0100105 haveUsesLibsReq, haveUsesLibsOpt = m.UsesLibs()
Ulya Trafimovich69612672020-10-20 17:41:54 +0100106 }
107
108 // Test that validation is successful (all paths are known).
109 t.Run("validate", func(t *testing.T) {
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +0000110 if !(valid && validationError == nil) {
Ulya Trafimovich69612672020-10-20 17:41:54 +0100111 t.Errorf("invalid class loader context")
112 }
113 })
114
115 // Test that class loader context structure is correct.
116 t.Run("string", func(t *testing.T) {
117 wantStr := " --host-context-for-sdk 29 " +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800118 "PCL[out/soong/" + AndroidHidlManager + ".jar]#" +
119 "PCL[out/soong/" + AndroidHidlBase + ".jar]" +
Ulya Trafimovich69612672020-10-20 17:41:54 +0100120 " --target-context-for-sdk 29 " +
121 "PCL[/system/framework/" + AndroidHidlManager + ".jar]#" +
122 "PCL[/system/framework/" + AndroidHidlBase + ".jar]" +
123 " --host-context-for-sdk any " +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800124 "PCL[out/soong/a.jar]#PCL[out/soong/b.jar]#PCL[out/soong/c.jar]#PCL[out/soong/d.jar]" +
125 "{PCL[out/soong/a2.jar]#PCL[out/soong/b2.jar]#PCL[out/soong/c2.jar]" +
126 "{PCL[out/soong/a1.jar]#PCL[out/soong/b1.jar]}}#" +
127 "PCL[out/soong/f.jar]#PCL[out/soong/a3.jar]#PCL[out/soong/b3.jar]" +
Ulya Trafimovich69612672020-10-20 17:41:54 +0100128 " --target-context-for-sdk any " +
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +0000129 "PCL[/system/a.jar]#PCL[/system/b.jar]#PCL[/system/c.jar]#PCL[/system/d.jar]" +
130 "{PCL[/system/a2.jar]#PCL[/system/b2.jar]#PCL[/system/c2.jar]" +
131 "{PCL[/system/a1.jar]#PCL[/system/b1.jar]}}#" +
Ulya Trafimovich69612672020-10-20 17:41:54 +0100132 "PCL[/system/f.jar]#PCL[/system/a3.jar]#PCL[/system/b3.jar]"
133 if wantStr != haveStr {
134 t.Errorf("\nwant class loader context: %s\nhave class loader context: %s", wantStr, haveStr)
135 }
136 })
137
138 // Test that all expected build paths are gathered.
139 t.Run("paths", func(t *testing.T) {
140 wantPaths := []string{
Colin Cross7b6a55f2021-11-09 12:34:39 -0800141 "out/soong/android.hidl.manager-V1.0-java.jar", "out/soong/android.hidl.base-V1.0-java.jar",
142 "out/soong/a.jar", "out/soong/b.jar", "out/soong/c.jar", "out/soong/d.jar",
143 "out/soong/a2.jar", "out/soong/b2.jar", "out/soong/c2.jar",
144 "out/soong/a1.jar", "out/soong/b1.jar",
145 "out/soong/f.jar", "out/soong/a3.jar", "out/soong/b3.jar",
Ulya Trafimovich69612672020-10-20 17:41:54 +0100146 }
147 if !reflect.DeepEqual(wantPaths, havePaths.Strings()) {
148 t.Errorf("\nwant paths: %s\nhave paths: %s", wantPaths, havePaths)
149 }
150 })
151
152 // Test for libraries that are added by the manifest_fixer.
153 t.Run("uses libs", func(t *testing.T) {
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +0100154 wantUsesLibsReq := []string{"a", "b", "c", "d", "f", "a3", "b3"}
155 wantUsesLibsOpt := []string{}
156 if !reflect.DeepEqual(wantUsesLibsReq, haveUsesLibsReq) {
157 t.Errorf("\nwant required uses libs: %s\nhave required uses libs: %s", wantUsesLibsReq, haveUsesLibsReq)
158 }
159 if !reflect.DeepEqual(wantUsesLibsOpt, haveUsesLibsOpt) {
160 t.Errorf("\nwant optional uses libs: %s\nhave optional uses libs: %s", wantUsesLibsOpt, haveUsesLibsOpt)
Ulya Trafimovich69612672020-10-20 17:41:54 +0100161 }
162 })
163}
164
Jeongik Cha19ade892021-04-22 20:55:21 +0900165func TestCLCJson(t *testing.T) {
166 ctx := testContext()
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +0100167 optional := false
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100168 implicit := true
Jeongik Cha19ade892021-04-22 20:55:21 +0900169 m := make(ClassLoaderContextMap)
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100170 m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
171 m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
172 m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
173 m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
Jeongik Cha19ade892021-04-22 20:55:21 +0900174 jsonCLC := toJsonClassLoaderContext(m)
175 restored := fromJsonClassLoaderContext(ctx, jsonCLC)
176 android.AssertIntEquals(t, "The size of the maps should be the same.", len(m), len(restored))
177 for k := range m {
178 a, _ := m[k]
179 b, ok := restored[k]
180 android.AssertBoolEquals(t, "The both maps should have the same keys.", ok, true)
181 android.AssertIntEquals(t, "The size of the elements should be the same.", len(a), len(b))
182 for i, elemA := range a {
183 before := fmt.Sprintf("%v", *elemA)
184 after := fmt.Sprintf("%v", *b[i])
185 android.AssertStringEquals(t, "The content should be the same.", before, after)
186 }
187 }
188}
189
Ulya Trafimovich7bc1cf52021-01-05 15:41:55 +0000190// Test that unknown library paths cause a validation error.
191func testCLCUnknownPath(t *testing.T, whichPath string) {
Ulya Trafimovich69612672020-10-20 17:41:54 +0100192 ctx := testContext()
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +0100193 optional := false
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100194 implicit := true
Ulya Trafimovich69612672020-10-20 17:41:54 +0100195
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +0000196 m := make(ClassLoaderContextMap)
Ulya Trafimovich7bc1cf52021-01-05 15:41:55 +0000197 if whichPath == "build" {
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100198 m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, nil, nil, nil)
Ulya Trafimovich7bc1cf52021-01-05 15:41:55 +0000199 } else {
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100200 m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), nil, nil)
Ulya Trafimovich7bc1cf52021-01-05 15:41:55 +0000201 }
Ulya Trafimovich69612672020-10-20 17:41:54 +0100202
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +0000203 // The library should be added to <uses-library> tags by the manifest_fixer.
Ulya Trafimovich7bc1cf52021-01-05 15:41:55 +0000204 t.Run("uses libs", func(t *testing.T) {
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +0100205 haveUsesLibsReq, haveUsesLibsOpt := m.UsesLibs()
206 wantUsesLibsReq := []string{"a"}
207 wantUsesLibsOpt := []string{}
208 if !reflect.DeepEqual(wantUsesLibsReq, haveUsesLibsReq) {
209 t.Errorf("\nwant required uses libs: %s\nhave required uses libs: %s", wantUsesLibsReq, haveUsesLibsReq)
210 }
211 if !reflect.DeepEqual(wantUsesLibsOpt, haveUsesLibsOpt) {
212 t.Errorf("\nwant optional uses libs: %s\nhave optional uses libs: %s", wantUsesLibsOpt, haveUsesLibsOpt)
Ulya Trafimovich8cbc5d22020-11-03 15:15:46 +0000213 }
214 })
Ulya Trafimovich69612672020-10-20 17:41:54 +0100215
Ulya Trafimovich7bc1cf52021-01-05 15:41:55 +0000216 // But CLC cannot be constructed: there is a validation error.
217 _, err := validateClassLoaderContext(m)
218 checkError(t, err, fmt.Sprintf("invalid %s path for <uses-library> \"a\"", whichPath))
219}
220
221// Test that unknown build path is an error.
222func TestCLCUnknownBuildPath(t *testing.T) {
223 testCLCUnknownPath(t, "build")
224}
225
226// Test that unknown install path is an error.
227func TestCLCUnknownInstallPath(t *testing.T) {
228 testCLCUnknownPath(t, "install")
Ulya Trafimovich69612672020-10-20 17:41:54 +0100229}
230
Ulya Trafimovich5e13a732020-11-03 15:33:03 +0000231// An attempt to add conditional nested subcontext should fail.
232func TestCLCNestedConditional(t *testing.T) {
233 ctx := testContext()
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +0100234 optional := false
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100235 implicit := true
Ulya Trafimovich5e13a732020-11-03 15:33:03 +0000236 m1 := make(ClassLoaderContextMap)
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100237 m1.AddContext(ctx, 42, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
Ulya Trafimovich5e13a732020-11-03 15:33:03 +0000238 m := make(ClassLoaderContextMap)
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100239 err := m.addContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
Ulya Trafimovich5e13a732020-11-03 15:33:03 +0000240 checkError(t, err, "nested class loader context shouldn't have conditional part")
241}
242
Ulya Trafimovichc9f2b942020-12-23 15:41:29 +0000243// Test for SDK version order in conditional CLC: no matter in what order the libraries are added,
244// they end up in the order that agrees with PackageManager.
245func TestCLCSdkVersionOrder(t *testing.T) {
246 ctx := testContext()
Ulya Trafimovichfc0f6e32021-08-12 16:16:11 +0100247 optional := false
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100248 implicit := true
Ulya Trafimovichc9f2b942020-12-23 15:41:29 +0000249 m := make(ClassLoaderContextMap)
Ulya Trafimovich0b1c70e2021-08-20 15:39:12 +0100250 m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
251 m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
252 m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
253 m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
Ulya Trafimovichc9f2b942020-12-23 15:41:29 +0000254
255 valid, validationError := validateClassLoaderContext(m)
256
257 fixClassLoaderContext(m)
258
259 var haveStr string
260 if valid && validationError == nil {
261 haveStr, _ = ComputeClassLoaderContext(m)
262 }
263
264 // Test that validation is successful (all paths are known).
265 t.Run("validate", func(t *testing.T) {
266 if !(valid && validationError == nil) {
267 t.Errorf("invalid class loader context")
268 }
269 })
270
271 // Test that class loader context structure is correct.
272 t.Run("string", func(t *testing.T) {
Colin Cross7b6a55f2021-11-09 12:34:39 -0800273 wantStr := " --host-context-for-sdk 30 PCL[out/soong/c.jar]" +
Ulya Trafimovichc9f2b942020-12-23 15:41:29 +0000274 " --target-context-for-sdk 30 PCL[/system/c.jar]" +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800275 " --host-context-for-sdk 29 PCL[out/soong/b.jar]" +
Ulya Trafimovichc9f2b942020-12-23 15:41:29 +0000276 " --target-context-for-sdk 29 PCL[/system/b.jar]" +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800277 " --host-context-for-sdk 28 PCL[out/soong/a.jar]" +
Ulya Trafimovichc9f2b942020-12-23 15:41:29 +0000278 " --target-context-for-sdk 28 PCL[/system/a.jar]" +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800279 " --host-context-for-sdk any PCL[out/soong/d.jar]" +
Ulya Trafimovichc9f2b942020-12-23 15:41:29 +0000280 " --target-context-for-sdk any PCL[/system/d.jar]"
281 if wantStr != haveStr {
282 t.Errorf("\nwant class loader context: %s\nhave class loader context: %s", wantStr, haveStr)
283 }
284 })
285}
286
Paul Duffin06530572022-02-03 17:54:15 +0000287func TestCLCMExcludeLibs(t *testing.T) {
288 ctx := testContext()
289 const optional = false
290 const implicit = true
291
292 excludeLibs := func(t *testing.T, m ClassLoaderContextMap, excluded_libs ...string) ClassLoaderContextMap {
293 // Dump the CLCM before creating a new copy that excludes a specific set of libraries.
294 before := m.Dump()
295
296 // Create a new CLCM that excludes some libraries.
297 c := m.ExcludeLibs(excluded_libs)
298
299 // Make sure that the original CLCM was not changed.
300 after := m.Dump()
301 android.AssertStringEquals(t, "input CLCM modified", before, after)
302
303 return c
304 }
305
306 t.Run("exclude nothing", func(t *testing.T) {
307 m := make(ClassLoaderContextMap)
308 m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
309
310 a := excludeLibs(t, m)
311
312 android.AssertStringEquals(t, "output CLCM ", `{
313 "28": [
314 {
315 "Name": "a",
316 "Optional": false,
317 "Implicit": true,
318 "Host": "out/soong/a.jar",
319 "Device": "/system/a.jar",
320 "Subcontexts": []
321 }
322 ]
323}`, a.Dump())
324 })
325
326 t.Run("one item from list", func(t *testing.T) {
327 m := make(ClassLoaderContextMap)
328 m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
329 m.AddContext(ctx, 28, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
330
331 a := excludeLibs(t, m, "a")
332
333 expected := `{
334 "28": [
335 {
336 "Name": "b",
337 "Optional": false,
338 "Implicit": true,
339 "Host": "out/soong/b.jar",
340 "Device": "/system/b.jar",
341 "Subcontexts": []
342 }
343 ]
344}`
345 android.AssertStringEquals(t, "output CLCM ", expected, a.Dump())
346 })
347
348 t.Run("all items from a list", func(t *testing.T) {
349 m := make(ClassLoaderContextMap)
350 m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
351 m.AddContext(ctx, 28, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
352
353 a := excludeLibs(t, m, "a", "b")
354
355 android.AssertStringEquals(t, "output CLCM ", `{}`, a.Dump())
356 })
357
358 t.Run("items from a subcontext", func(t *testing.T) {
359 s := make(ClassLoaderContextMap)
360 s.AddContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
361 s.AddContext(ctx, AnySdkVersion, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
362
363 m := make(ClassLoaderContextMap)
364 m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), s)
365
366 a := excludeLibs(t, m, "b")
367
368 android.AssertStringEquals(t, "output CLCM ", `{
369 "28": [
370 {
371 "Name": "a",
372 "Optional": false,
373 "Implicit": true,
374 "Host": "out/soong/a.jar",
375 "Device": "/system/a.jar",
376 "Subcontexts": [
377 {
378 "Name": "c",
379 "Optional": false,
380 "Implicit": true,
381 "Host": "out/soong/c.jar",
382 "Device": "/system/c.jar",
383 "Subcontexts": []
384 }
385 ]
386 }
387 ]
388}`, a.Dump())
389 })
390}
391
Ulya Trafimovich91f015e2022-04-27 17:51:49 +0100392// Test that CLC is correctly serialized to JSON.
393func TestCLCtoJSON(t *testing.T) {
394 ctx := testContext()
395 optional := false
396 implicit := true
397 m := make(ClassLoaderContextMap)
398 m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
399 m.AddContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
400 android.AssertStringEquals(t, "output CLCM ", `{
401 "28": [
402 {
403 "Name": "a",
404 "Optional": false,
405 "Implicit": true,
406 "Host": "out/soong/a.jar",
407 "Device": "/system/a.jar",
408 "Subcontexts": []
409 }
410 ],
411 "any": [
412 {
413 "Name": "b",
414 "Optional": false,
415 "Implicit": true,
416 "Host": "out/soong/b.jar",
417 "Device": "/system/b.jar",
418 "Subcontexts": []
419 }
420 ]
421}`, m.Dump())
422}
423
Ulya Trafimovich69612672020-10-20 17:41:54 +0100424func checkError(t *testing.T, have error, want string) {
425 if have == nil {
426 t.Errorf("\nwant error: '%s'\nhave: none", want)
427 } else if msg := have.Error(); !strings.HasPrefix(msg, want) {
428 t.Errorf("\nwant error: '%s'\nhave error: '%s'\n", want, msg)
429 }
430}
431
432func testContext() android.ModuleInstallPathContext {
433 config := android.TestConfig("out", nil, "", nil)
434 return android.ModuleInstallPathContextForTesting(config)
435}
436
437func buildPath(ctx android.PathContext, lib string) android.Path {
438 return android.PathForOutput(ctx, lib+".jar")
439}
440
441func installPath(ctx android.ModuleInstallPathContext, lib string) android.InstallPath {
442 return android.PathForModuleInstall(ctx, lib+".jar")
443}