blob: f57f504d795bd37fbd17c2e649a9c0942232c315 [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"
Paul Duffin803876aa2021-03-17 22:38:23 +000021 "regexp"
Nan Zhangdb0b9a32017-02-27 10:12:13 -080022 "testing"
23
24 "android/soong/android"
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 (
36 buildNamePrefix = "soong_python_test"
37 moduleVariantErrTemplate = "%s: module %q variant %q: "
38 pkgPathErrTemplate = moduleVariantErrTemplate +
Nan Zhangd4e641b2017-07-12 12:55:28 -070039 "pkg_path: %q must be a relative path contained in par file."
Nan Zhangdb0b9a32017-02-27 10:12:13 -080040 badIdentifierErrTemplate = moduleVariantErrTemplate +
Liz Kammerd737d022020-11-16 15:42:51 -080041 "srcs: the path %q contains invalid subpath %q."
Nan Zhangdb0b9a32017-02-27 10:12:13 -080042 dupRunfileErrTemplate = moduleVariantErrTemplate +
Nan Zhangbea09752018-05-31 12:49:33 -070043 "found two files to be placed at the same location within zip %q." +
Nan Zhangdb0b9a32017-02-27 10:12:13 -080044 " First file: in module %s at path %q." +
45 " Second file: in module %s at path %q."
46 noSrcFileErr = moduleVariantErrTemplate + "doesn't have any source files!"
Nan Zhangb8fa1972017-12-22 16:12:00 -080047 badSrcFileExtErr = moduleVariantErrTemplate + "srcs: found non (.py|.proto) file: %q!"
48 badDataFileExtErr = moduleVariantErrTemplate + "data: found (.py|.proto) file: %q!"
Colin Cross98be1bb2019-12-13 20:41:13 -080049 bpFile = "Android.bp"
Nan Zhangdb0b9a32017-02-27 10:12:13 -080050
51 data = []struct {
52 desc string
Paul Duffin803876aa2021-03-17 22:38:23 +000053 mockFiles android.MockFS
Nan Zhangdb0b9a32017-02-27 10:12:13 -080054
55 errors []string
Nan Zhangd4e641b2017-07-12 12:55:28 -070056 expectedBinaries []pyModule
Nan Zhangdb0b9a32017-02-27 10:12:13 -080057 }{
58 {
59 desc: "module without any src files",
60 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -080061 filepath.Join("dir", bpFile): []byte(
62 `python_library_host {
63 name: "lib1",
64 }`,
65 ),
66 },
67 errors: []string{
68 fmt.Sprintf(noSrcFileErr,
Colin Cross98be1bb2019-12-13 20:41:13 -080069 "dir/Android.bp:1:1", "lib1", "PY3"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -080070 },
71 },
72 {
73 desc: "module with bad src file ext",
74 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -080075 filepath.Join("dir", bpFile): []byte(
76 `python_library_host {
77 name: "lib1",
78 srcs: [
79 "file1.exe",
80 ],
81 }`,
82 ),
83 "dir/file1.exe": nil,
84 },
85 errors: []string{
86 fmt.Sprintf(badSrcFileExtErr,
Colin Cross98be1bb2019-12-13 20:41:13 -080087 "dir/Android.bp:3:11", "lib1", "PY3", "dir/file1.exe"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -080088 },
89 },
90 {
91 desc: "module with bad data file ext",
92 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -080093 filepath.Join("dir", bpFile): []byte(
94 `python_library_host {
95 name: "lib1",
96 srcs: [
97 "file1.py",
98 ],
99 data: [
100 "file2.py",
101 ],
102 }`,
103 ),
104 "dir/file1.py": nil,
105 "dir/file2.py": nil,
106 },
107 errors: []string{
108 fmt.Sprintf(badDataFileExtErr,
Colin Cross98be1bb2019-12-13 20:41:13 -0800109 "dir/Android.bp:6:11", "lib1", "PY3", "dir/file2.py"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800110 },
111 },
112 {
113 desc: "module with bad pkg_path format",
114 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800115 filepath.Join("dir", bpFile): []byte(
116 `python_library_host {
117 name: "lib1",
118 pkg_path: "a/c/../../",
119 srcs: [
120 "file1.py",
121 ],
122 }
123
124 python_library_host {
125 name: "lib2",
126 pkg_path: "a/c/../../../",
127 srcs: [
128 "file1.py",
129 ],
130 }
131
132 python_library_host {
133 name: "lib3",
134 pkg_path: "/a/c/../../",
135 srcs: [
136 "file1.py",
137 ],
138 }`,
139 ),
140 "dir/file1.py": nil,
141 },
142 errors: []string{
143 fmt.Sprintf(pkgPathErrTemplate,
Colin Cross98be1bb2019-12-13 20:41:13 -0800144 "dir/Android.bp:11:15", "lib2", "PY3", "a/c/../../../"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800145 fmt.Sprintf(pkgPathErrTemplate,
Colin Cross98be1bb2019-12-13 20:41:13 -0800146 "dir/Android.bp:19:15", "lib3", "PY3", "/a/c/../../"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800147 },
148 },
149 {
150 desc: "module with bad runfile src path format",
151 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800152 filepath.Join("dir", bpFile): []byte(
153 `python_library_host {
154 name: "lib1",
155 pkg_path: "a/b/c/",
156 srcs: [
157 ".file1.py",
158 "123/file1.py",
159 "-e/f/file1.py",
160 ],
161 }`,
162 ),
163 "dir/.file1.py": nil,
164 "dir/123/file1.py": nil,
165 "dir/-e/f/file1.py": nil,
166 },
167 errors: []string{
Colin Cross98be1bb2019-12-13 20:41:13 -0800168 fmt.Sprintf(badIdentifierErrTemplate, "dir/Android.bp:4:11",
Nan Zhangbea09752018-05-31 12:49:33 -0700169 "lib1", "PY3", "a/b/c/-e/f/file1.py", "-e"),
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/.file1.py", ".file1"),
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/123/file1.py", "123"),
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800174 },
175 },
176 {
177 desc: "module with duplicate runfile path",
178 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800179 filepath.Join("dir", bpFile): []byte(
180 `python_library_host {
181 name: "lib1",
182 pkg_path: "a/b/",
183 srcs: [
184 "c/file1.py",
185 ],
186 }
187
188 python_library_host {
189 name: "lib2",
190 pkg_path: "a/b/c/",
191 srcs: [
192 "file1.py",
193 ],
194 libs: [
195 "lib1",
196 ],
197 }
Paul Duffinc60dd802021-03-17 23:01:06 +0000198
199 python_binary_host {
200 name: "bin",
201 pkg_path: "e/",
202 srcs: [
203 "bin.py",
204 ],
205 libs: [
206 "lib2",
207 ],
208 }
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800209 `,
210 ),
211 "dir/c/file1.py": nil,
212 "dir/file1.py": nil,
Paul Duffinc60dd802021-03-17 23:01:06 +0000213 "dir/bin.py": nil,
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800214 },
215 errors: []string{
Paul Duffinc60dd802021-03-17 23:01:06 +0000216 fmt.Sprintf(dupRunfileErrTemplate, "dir/Android.bp:20:6",
217 "bin", "PY3", "a/b/c/file1.py", "bin", "dir/file1.py",
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800218 "lib1", "dir/c/file1.py"),
219 },
220 },
221 {
222 desc: "module for testing dependencies",
223 mockFiles: map[string][]byte{
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800224 filepath.Join("dir", bpFile): []byte(
Nan Zhanga3fc4ba2017-07-20 17:43:37 -0700225 `python_defaults {
226 name: "default_lib",
227 srcs: [
228 "default.py",
229 ],
230 version: {
231 py2: {
232 enabled: true,
233 srcs: [
234 "default_py2.py",
235 ],
236 },
237 py3: {
238 enabled: false,
239 srcs: [
240 "default_py3.py",
241 ],
242 },
243 },
244 }
245
246 python_library_host {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800247 name: "lib5",
248 pkg_path: "a/b/",
249 srcs: [
250 "file1.py",
251 ],
252 version: {
253 py2: {
254 enabled: true,
255 },
256 py3: {
257 enabled: true,
258 },
259 },
260 }
261
262 python_library_host {
263 name: "lib6",
264 pkg_path: "c/d/",
265 srcs: [
266 "file2.py",
267 ],
268 libs: [
269 "lib5",
270 ],
271 }
272
273 python_binary_host {
274 name: "bin",
Nan Zhanga3fc4ba2017-07-20 17:43:37 -0700275 defaults: ["default_lib"],
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800276 pkg_path: "e/",
277 srcs: [
278 "bin.py",
279 ],
280 libs: [
281 "lib5",
282 ],
283 version: {
284 py3: {
285 enabled: true,
286 srcs: [
287 "file4.py",
288 ],
289 libs: [
290 "lib6",
291 ],
292 },
293 },
294 }`,
295 ),
Nan Zhanga3fc4ba2017-07-20 17:43:37 -0700296 filepath.Join("dir", "default.py"): nil,
297 filepath.Join("dir", "default_py2.py"): nil,
298 filepath.Join("dir", "default_py3.py"): nil,
299 filepath.Join("dir", "file1.py"): nil,
300 filepath.Join("dir", "file2.py"): nil,
301 filepath.Join("dir", "bin.py"): nil,
302 filepath.Join("dir", "file4.py"): nil,
Liz Kammerdd849a82020-06-12 16:38:45 -0700303 StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800304 MAIN_FILE = '%main%'`),
305 },
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 Zhang1db85402017-12-18 13:20:23 -0800317 depsSrcsZips: []string{
Paul Duffin803876aa2021-03-17 22:38:23 +0000318 "out/soong/.intermediates/dir/lib5/PY3/lib5.py.srcszip",
319 "out/soong/.intermediates/dir/lib6/PY3/lib6.py.srcszip",
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800320 },
321 },
322 },
323 },
324 }
325)
326
327func TestPythonModule(t *testing.T) {
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800328 for _, d := range data {
Paul Duffin803876aa2021-03-17 22:38:23 +0000329 if d.desc != "module with duplicate runfile path" {
330 continue
331 }
332 errorPatterns := make([]string, len(d.errors))
333 for i, s := range d.errors {
334 errorPatterns[i] = regexp.QuoteMeta(s)
335 }
336
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800337 t.Run(d.desc, func(t *testing.T) {
Paul Duffin89648f92021-03-20 00:36:55 +0000338 result := android.GroupFixturePreparers(
339 android.PrepareForTestWithDefaults,
340 PrepareForTestWithPythonBuildComponents,
341 d.mockFiles.AddToFixture(),
342 ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(errorPatterns)).
343 RunTest(t)
Paul Duffin803876aa2021-03-17 22:38:23 +0000344
345 if len(result.Errs) > 0 {
346 return
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800347 }
Paul Duffin803876aa2021-03-17 22:38:23 +0000348
349 for _, e := range d.expectedBinaries {
350 t.Run(e.name, func(t *testing.T) {
351 expectModule(t, result.TestContext, e.name, e.actualVersion, e.srcsZip, e.pyRunfiles, e.depsSrcsZips)
352 })
353 }
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800354 })
355 }
356}
357
Paul Duffin803876aa2021-03-17 22:38:23 +0000358func expectModule(t *testing.T, ctx *android.TestContext, name, variant, expectedSrcsZip string, expectedPyRunfiles, expectedDepsSrcsZips []string) {
Colin Crosscec81712017-07-13 14:43:27 -0700359 module := ctx.ModuleForTests(name, variant)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800360
Nan Zhangd4e641b2017-07-12 12:55:28 -0700361 base, baseOk := module.Module().(*Module)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800362 if !baseOk {
363 t.Fatalf("%s is not Python module!", name)
364 }
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800365
Nan Zhang1db85402017-12-18 13:20:23 -0800366 actualPyRunfiles := []string{}
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800367 for _, path := range base.srcsPathMappings {
Nan Zhang1db85402017-12-18 13:20:23 -0800368 actualPyRunfiles = append(actualPyRunfiles, path.dest)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800369 }
370
Paul Duffin803876aa2021-03-17 22:38:23 +0000371 android.AssertDeepEquals(t, "pyRunfiles", expectedPyRunfiles, actualPyRunfiles)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800372
Paul Duffin803876aa2021-03-17 22:38:23 +0000373 android.AssertPathRelativeToTopEquals(t, "srcsZip", expectedSrcsZip, base.srcsZip)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800374
Paul Duffin803876aa2021-03-17 22:38:23 +0000375 android.AssertPathsRelativeToTopEquals(t, "depsSrcsZips", expectedDepsSrcsZips, base.depsSrcsZips)
Nan Zhangdb0b9a32017-02-27 10:12:13 -0800376}
377
Colin Cross98be1bb2019-12-13 20:41:13 -0800378func TestMain(m *testing.M) {
Paul Duffin803876aa2021-03-17 22:38:23 +0000379 os.Exit(m.Run())
Colin Cross98be1bb2019-12-13 20:41:13 -0800380}