blob: 75a6a899b6a552ee31c9d6e380ad7cd254a3b6f1 [file] [log] [blame]
Nan Zhangdb0b9a32017-02-27 10:12:13 -08001// Copyright 2017 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 python
16
17import (
Nan Zhangdb0b9a32017-02-27 10:12:13 -080018 "fmt"
Nan Zhangdb0b9a32017-02-27 10:12:13 -080019 "os"
20 "path/filepath"
Nan Zhangdb0b9a32017-02-27 10:12:13 -080021 "testing"
22
23 "android/soong/android"
Cole Faust5c503d12023-01-24 11:48:08 -080024 "android/soong/cc"
Nan Zhangdb0b9a32017-02-27 10:12:13 -080025)
26
Nan Zhangd4e641b2017-07-12 12:55:28 -070027type pyModule struct {
Nan Zhang1db85402017-12-18 13:20:23 -080028 name string
29 actualVersion string
30 pyRunfiles []string
31 srcsZip string
32 depsSrcsZips []string
Nan Zhangdb0b9a32017-02-27 10:12:13 -080033}
34
35var (
Cole Faust5c503d12023-01-24 11:48:08 -080036 buildNamePrefix = "soong_python_test"
37 // We allow maching almost anything before the actual variant so that the os/arch variant
38 // is matched.
39 moduleVariantErrTemplate = `%s: module %q variant "[a-zA-Z0-9_]*%s": `
Nan Zhangdb0b9a32017-02-27 10:12:13 -080040 pkgPathErrTemplate = moduleVariantErrTemplate +
Nan Zhangd4e641b2017-07-12 12:55:28 -070041 "pkg_path: %q must be a relative path contained in par file."
Nan Zhangdb0b9a32017-02-27 10:12:13 -080042 badIdentifierErrTemplate = moduleVariantErrTemplate +
Liz Kammerd737d022020-11-16 15:42:51 -080043 "srcs: the path %q contains invalid subpath %q."
Nan Zhangdb0b9a32017-02-27 10:12:13 -080044 dupRunfileErrTemplate = moduleVariantErrTemplate +
Nan Zhangbea09752018-05-31 12:49:33 -070045 "found two files to be placed at the same location within zip %q." +
Nan Zhangdb0b9a32017-02-27 10:12:13 -080046 " First file: in module %s at path %q." +
47 " Second file: in module %s at path %q."
48 noSrcFileErr = moduleVariantErrTemplate + "doesn't have any source files!"
Nan Zhangb8fa1972017-12-22 16:12:00 -080049 badSrcFileExtErr = moduleVariantErrTemplate + "srcs: found non (.py|.proto) file: %q!"
50 badDataFileExtErr = moduleVariantErrTemplate + "data: found (.py|.proto) file: %q!"
Colin Cross98be1bb2019-12-13 20:41:13 -080051 bpFile = "Android.bp"
Nan Zhangdb0b9a32017-02-27 10:12:13 -080052
53 data = []struct {
54 desc string
Paul Duffin803876aa2021-03-17 22:38:23 +000055 mockFiles android.MockFS
Nan Zhangdb0b9a32017-02-27 10:12:13 -080056
57 errors []string
Nan Zhangd4e641b2017-07-12 12:55:28 -070058 expectedBinaries []pyModule
Nan Zhangdb0b9a32017-02-27 10:12:13 -080059 }{
60 {
61 desc: "module without any src files",
62 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -080063 filepath.Join("dir", bpFile): []byte(
64 `python_library_host {
65 name: "lib1",
66 }`,
67 ),
68 },
69 errors: []string{
70 fmt.Sprintf(noSrcFileErr,
Colin Cross98be1bb2019-12-13 20:41:13 -080071 "dir/Android.bp:1:1", "lib1", "PY3"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -080072 },
73 },
74 {
75 desc: "module with bad src file ext",
76 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -080077 filepath.Join("dir", bpFile): []byte(
78 `python_library_host {
79 name: "lib1",
80 srcs: [
81 "file1.exe",
82 ],
83 }`,
84 ),
85 "dir/file1.exe": nil,
86 },
87 errors: []string{
88 fmt.Sprintf(badSrcFileExtErr,
Colin Cross98be1bb2019-12-13 20:41:13 -080089 "dir/Android.bp:3:11", "lib1", "PY3", "dir/file1.exe"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -080090 },
91 },
92 {
93 desc: "module with bad data file ext",
94 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -080095 filepath.Join("dir", bpFile): []byte(
96 `python_library_host {
97 name: "lib1",
98 srcs: [
99 "file1.py",
100 ],
101 data: [
102 "file2.py",
103 ],
104 }`,
105 ),
106 "dir/file1.py": nil,
107 "dir/file2.py": nil,
108 },
109 errors: []string{
110 fmt.Sprintf(badDataFileExtErr,
Colin Cross98be1bb2019-12-13 20:41:13 -0800111 "dir/Android.bp:6:11", "lib1", "PY3", "dir/file2.py"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800112 },
113 },
114 {
115 desc: "module with bad pkg_path format",
116 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800117 filepath.Join("dir", bpFile): []byte(
118 `python_library_host {
119 name: "lib1",
120 pkg_path: "a/c/../../",
121 srcs: [
122 "file1.py",
123 ],
124 }
125
126 python_library_host {
127 name: "lib2",
128 pkg_path: "a/c/../../../",
129 srcs: [
130 "file1.py",
131 ],
132 }
133
134 python_library_host {
135 name: "lib3",
136 pkg_path: "/a/c/../../",
137 srcs: [
138 "file1.py",
139 ],
140 }`,
141 ),
142 "dir/file1.py": nil,
143 },
144 errors: []string{
145 fmt.Sprintf(pkgPathErrTemplate,
Colin Cross98be1bb2019-12-13 20:41:13 -0800146 "dir/Android.bp:11:15", "lib2", "PY3", "a/c/../../../"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800147 fmt.Sprintf(pkgPathErrTemplate,
Colin Cross98be1bb2019-12-13 20:41:13 -0800148 "dir/Android.bp:19:15", "lib3", "PY3", "/a/c/../../"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800149 },
150 },
151 {
152 desc: "module with bad runfile src path format",
153 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800154 filepath.Join("dir", bpFile): []byte(
155 `python_library_host {
156 name: "lib1",
157 pkg_path: "a/b/c/",
158 srcs: [
159 ".file1.py",
160 "123/file1.py",
161 "-e/f/file1.py",
162 ],
163 }`,
164 ),
165 "dir/.file1.py": nil,
166 "dir/123/file1.py": nil,
167 "dir/-e/f/file1.py": nil,
168 },
169 errors: []string{
Colin Cross98be1bb2019-12-13 20:41:13 -0800170 fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
Nan Zhangbea09752018-05-31 12:49:33 -0700171 "lib1", "PY3", "a/b/c/-e/f/file1.py", "-e"),
Colin Cross98be1bb2019-12-13 20:41:13 -0800172 fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
Nan Zhangbea09752018-05-31 12:49:33 -0700173 "lib1", "PY3", "a/b/c/.file1.py", ".file1"),
Colin Cross98be1bb2019-12-13 20:41:13 -0800174 fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
Nan Zhangbea09752018-05-31 12:49:33 -0700175 "lib1", "PY3", "a/b/c/123/file1.py", "123"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800176 },
177 },
178 {
179 desc: "module with duplicate runfile path",
180 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800181 filepath.Join("dir", bpFile): []byte(
182 `python_library_host {
183 name: "lib1",
184 pkg_path: "a/b/",
185 srcs: [
186 "c/file1.py",
187 ],
188 }
189
190 python_library_host {
191 name: "lib2",
192 pkg_path: "a/b/c/",
193 srcs: [
194 "file1.py",
195 ],
196 libs: [
197 "lib1",
198 ],
199 }
Paul Duffinc60dd802021-03-17 23:01:06 +0000200
201 python_binary_host {
202 name: "bin",
203 pkg_path: "e/",
204 srcs: [
205 "bin.py",
206 ],
207 libs: [
208 "lib2",
209 ],
210 }
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800211 `,
212 ),
213 "dir/c/file1.py": nil,
214 "dir/file1.py": nil,
Paul Duffinc60dd802021-03-17 23:01:06 +0000215 "dir/bin.py": nil,
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800216 },
217 errors: []string{
Paul Duffinc60dd802021-03-17 23:01:06 +0000218 fmt.Sprintf(dupRunfileErrTemplate, "dir/Android.bp:20:6",
219 "bin", "PY3", "a/b/c/file1.py", "bin", "dir/file1.py",
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800220 "lib1", "dir/c/file1.py"),
221 },
222 },
223 {
224 desc: "module for testing dependencies",
225 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800226 filepath.Join("dir", bpFile): []byte(
Nan Zhanga3fc4ba2017-07-20 17:43:37 -0700227 `python_defaults {
228 name: "default_lib",
229 srcs: [
230 "default.py",
231 ],
232 version: {
233 py2: {
234 enabled: true,
235 srcs: [
236 "default_py2.py",
237 ],
238 },
239 py3: {
240 enabled: false,
241 srcs: [
242 "default_py3.py",
243 ],
244 },
245 },
246 }
247
248 python_library_host {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800249 name: "lib5",
250 pkg_path: "a/b/",
251 srcs: [
252 "file1.py",
253 ],
254 version: {
255 py2: {
256 enabled: true,
257 },
258 py3: {
259 enabled: true,
260 },
261 },
262 }
263
264 python_library_host {
265 name: "lib6",
266 pkg_path: "c/d/",
267 srcs: [
268 "file2.py",
269 ],
270 libs: [
271 "lib5",
272 ],
273 }
274
275 python_binary_host {
276 name: "bin",
Nan Zhanga3fc4ba2017-07-20 17:43:37 -0700277 defaults: ["default_lib"],
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800278 pkg_path: "e/",
279 srcs: [
280 "bin.py",
281 ],
282 libs: [
283 "lib5",
284 ],
285 version: {
286 py3: {
287 enabled: true,
288 srcs: [
289 "file4.py",
290 ],
291 libs: [
292 "lib6",
293 ],
294 },
295 },
296 }`,
297 ),
Nan Zhanga3fc4ba2017-07-20 17:43:37 -0700298 filepath.Join("dir", "default.py"): nil,
299 filepath.Join("dir", "default_py2.py"): nil,
300 filepath.Join("dir", "default_py3.py"): nil,
301 filepath.Join("dir", "file1.py"): nil,
302 filepath.Join("dir", "file2.py"): nil,
303 filepath.Join("dir", "bin.py"): nil,
304 filepath.Join("dir", "file4.py"): nil,
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800305 },
Nan Zhangd4e641b2017-07-12 12:55:28 -0700306 expectedBinaries: []pyModule{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800307 {
308 name: "bin",
309 actualVersion: "PY3",
310 pyRunfiles: []string{
Nan Zhangbea09752018-05-31 12:49:33 -0700311 "e/default.py",
312 "e/bin.py",
313 "e/default_py3.py",
314 "e/file4.py",
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800315 },
Paul Duffin803876aa2021-03-17 22:38:23 +0000316 srcsZip: "out/soong/.intermediates/dir/bin/PY3/bin.py.srcszip",
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800317 },
318 },
319 },
320 }
321)
322
323func TestPythonModule(t *testing.T) {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800324 for _, d := range data {
Paul Duffin803876aa2021-03-17 22:38:23 +0000325 if d.desc != "module with duplicate runfile path" {
326 continue
327 }
Cole Faust5c503d12023-01-24 11:48:08 -0800328 d.mockFiles[filepath.Join("common", bpFile)] = []byte(`
329python_library {
330 name: "py3-stdlib",
331 host_supported: true,
332}
333cc_binary {
334 name: "py3-launcher",
335 host_supported: true,
336}
337`)
Paul Duffin803876aa2021-03-17 22:38:23 +0000338
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800339 t.Run(d.desc, func(t *testing.T) {
Paul Duffin89648f92021-03-20 00:36:55 +0000340 result := android.GroupFixturePreparers(
341 android.PrepareForTestWithDefaults,
Cole Faust5c503d12023-01-24 11:48:08 -0800342 android.PrepareForTestWithArchMutator,
343 android.PrepareForTestWithAllowMissingDependencies,
344 cc.PrepareForTestWithCcDefaultModules,
Paul Duffin89648f92021-03-20 00:36:55 +0000345 PrepareForTestWithPythonBuildComponents,
346 d.mockFiles.AddToFixture(),
Cole Faust5c503d12023-01-24 11:48:08 -0800347 ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(d.errors)).
Paul Duffin89648f92021-03-20 00:36:55 +0000348 RunTest(t)
Paul Duffin803876aa2021-03-17 22:38:23 +0000349
350 if len(result.Errs) > 0 {
351 return
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800352 }
Paul Duffin803876aa2021-03-17 22:38:23 +0000353
354 for _, e := range d.expectedBinaries {
355 t.Run(e.name, func(t *testing.T) {
Cole Faust4d247e62023-01-23 10:14:58 -0800356 expectModule(t, result.TestContext, e.name, e.actualVersion, e.srcsZip, e.pyRunfiles)
Paul Duffin803876aa2021-03-17 22:38:23 +0000357 })
358 }
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800359 })
360 }
361}
362
Cole Faust4d247e62023-01-23 10:14:58 -0800363func expectModule(t *testing.T, ctx *android.TestContext, name, variant, expectedSrcsZip string, expectedPyRunfiles []string) {
Colin Crosscec81712017-07-13 14:43:27 -0700364 module := ctx.ModuleForTests(name, variant)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800365
Cole Faust4d247e62023-01-23 10:14:58 -0800366 base, baseOk := module.Module().(*PythonLibraryModule)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800367 if !baseOk {
368 t.Fatalf("%s is not Python module!", name)
369 }
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800370
Nan Zhang1db85402017-12-18 13:20:23 -0800371 actualPyRunfiles := []string{}
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800372 for _, path := range base.srcsPathMappings {
Nan Zhang1db85402017-12-18 13:20:23 -0800373 actualPyRunfiles = append(actualPyRunfiles, path.dest)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800374 }
375
Paul Duffin803876aa2021-03-17 22:38:23 +0000376 android.AssertDeepEquals(t, "pyRunfiles", expectedPyRunfiles, actualPyRunfiles)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800377
Paul Duffin803876aa2021-03-17 22:38:23 +0000378 android.AssertPathRelativeToTopEquals(t, "srcsZip", expectedSrcsZip, base.srcsZip)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800379}
380
Colin Cross98be1bb2019-12-13 20:41:13 -0800381func TestMain(m *testing.M) {
Paul Duffin803876aa2021-03-17 22:38:23 +0000382 os.Exit(m.Run())
Colin Cross98be1bb2019-12-13 20:41:13 -0800383}