paths_test.go 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591
  1. // Copyright 2015 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. package android
  15. import (
  16. "errors"
  17. "fmt"
  18. "reflect"
  19. "strconv"
  20. "strings"
  21. "testing"
  22. "github.com/google/blueprint/proptools"
  23. )
  24. type strsTestCase struct {
  25. in []string
  26. out string
  27. err []error
  28. }
  29. var commonValidatePathTestCases = []strsTestCase{
  30. {
  31. in: []string{""},
  32. out: "",
  33. },
  34. {
  35. in: []string{"a/b"},
  36. out: "a/b",
  37. },
  38. {
  39. in: []string{"a/b", "c"},
  40. out: "a/b/c",
  41. },
  42. {
  43. in: []string{"a/.."},
  44. out: ".",
  45. },
  46. {
  47. in: []string{"."},
  48. out: ".",
  49. },
  50. {
  51. in: []string{".."},
  52. out: "",
  53. err: []error{errors.New("Path is outside directory: ..")},
  54. },
  55. {
  56. in: []string{"../a"},
  57. out: "",
  58. err: []error{errors.New("Path is outside directory: ../a")},
  59. },
  60. {
  61. in: []string{"b/../../a"},
  62. out: "",
  63. err: []error{errors.New("Path is outside directory: ../a")},
  64. },
  65. {
  66. in: []string{"/a"},
  67. out: "",
  68. err: []error{errors.New("Path is outside directory: /a")},
  69. },
  70. {
  71. in: []string{"a", "../b"},
  72. out: "",
  73. err: []error{errors.New("Path is outside directory: ../b")},
  74. },
  75. {
  76. in: []string{"a", "b/../../c"},
  77. out: "",
  78. err: []error{errors.New("Path is outside directory: ../c")},
  79. },
  80. {
  81. in: []string{"a", "./.."},
  82. out: "",
  83. err: []error{errors.New("Path is outside directory: ..")},
  84. },
  85. }
  86. var validateSafePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
  87. {
  88. in: []string{"$host/../$a"},
  89. out: "$a",
  90. },
  91. }...)
  92. var validatePathTestCases = append(commonValidatePathTestCases, []strsTestCase{
  93. {
  94. in: []string{"$host/../$a"},
  95. out: "",
  96. err: []error{errors.New("Path contains invalid character($): $host/../$a")},
  97. },
  98. {
  99. in: []string{"$host/.."},
  100. out: "",
  101. err: []error{errors.New("Path contains invalid character($): $host/..")},
  102. },
  103. }...)
  104. func TestValidateSafePath(t *testing.T) {
  105. for _, testCase := range validateSafePathTestCases {
  106. t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
  107. ctx := &configErrorWrapper{}
  108. out, err := validateSafePath(testCase.in...)
  109. if err != nil {
  110. reportPathError(ctx, err)
  111. }
  112. check(t, "validateSafePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
  113. })
  114. }
  115. }
  116. func TestValidatePath(t *testing.T) {
  117. for _, testCase := range validatePathTestCases {
  118. t.Run(strings.Join(testCase.in, ","), func(t *testing.T) {
  119. ctx := &configErrorWrapper{}
  120. out, err := validatePath(testCase.in...)
  121. if err != nil {
  122. reportPathError(ctx, err)
  123. }
  124. check(t, "validatePath", p(testCase.in), out, ctx.errors, testCase.out, testCase.err)
  125. })
  126. }
  127. }
  128. func TestOptionalPath(t *testing.T) {
  129. var path OptionalPath
  130. checkInvalidOptionalPath(t, path, "unknown")
  131. path = OptionalPathForPath(nil)
  132. checkInvalidOptionalPath(t, path, "unknown")
  133. path = InvalidOptionalPath("foo")
  134. checkInvalidOptionalPath(t, path, "foo")
  135. path = InvalidOptionalPath("")
  136. checkInvalidOptionalPath(t, path, "unknown")
  137. path = OptionalPathForPath(PathForTesting("path"))
  138. checkValidOptionalPath(t, path, "path")
  139. }
  140. func checkInvalidOptionalPath(t *testing.T, path OptionalPath, expectedInvalidReason string) {
  141. t.Helper()
  142. if path.Valid() {
  143. t.Errorf("Invalid OptionalPath should not be valid")
  144. }
  145. if path.InvalidReason() != expectedInvalidReason {
  146. t.Errorf("Wrong invalid reason: expected %q, got %q", expectedInvalidReason, path.InvalidReason())
  147. }
  148. if path.String() != "" {
  149. t.Errorf("Invalid OptionalPath String() should return \"\", not %q", path.String())
  150. }
  151. paths := path.AsPaths()
  152. if len(paths) != 0 {
  153. t.Errorf("Invalid OptionalPath AsPaths() should return empty Paths, not %q", paths)
  154. }
  155. defer func() {
  156. if r := recover(); r == nil {
  157. t.Errorf("Expected a panic when calling Path() on an uninitialized OptionalPath")
  158. }
  159. }()
  160. path.Path()
  161. }
  162. func checkValidOptionalPath(t *testing.T, path OptionalPath, expectedString string) {
  163. t.Helper()
  164. if !path.Valid() {
  165. t.Errorf("Initialized OptionalPath should not be invalid")
  166. }
  167. if path.InvalidReason() != "" {
  168. t.Errorf("Initialized OptionalPath should not have an invalid reason, got: %q", path.InvalidReason())
  169. }
  170. if path.String() != expectedString {
  171. t.Errorf("Initialized OptionalPath String() should return %q, not %q", expectedString, path.String())
  172. }
  173. paths := path.AsPaths()
  174. if len(paths) != 1 {
  175. t.Errorf("Initialized OptionalPath AsPaths() should return Paths with length 1, not %q", paths)
  176. }
  177. path.Path()
  178. }
  179. func check(t *testing.T, testType, testString string,
  180. got interface{}, err []error,
  181. expected interface{}, expectedErr []error) {
  182. t.Helper()
  183. printedTestCase := false
  184. e := func(s string, expected, got interface{}) {
  185. t.Helper()
  186. if !printedTestCase {
  187. t.Errorf("test case %s: %s", testType, testString)
  188. printedTestCase = true
  189. }
  190. t.Errorf("incorrect %s", s)
  191. t.Errorf(" expected: %s", p(expected))
  192. t.Errorf(" got: %s", p(got))
  193. }
  194. if !reflect.DeepEqual(expectedErr, err) {
  195. e("errors:", expectedErr, err)
  196. }
  197. if !reflect.DeepEqual(expected, got) {
  198. e("output:", expected, got)
  199. }
  200. }
  201. func p(in interface{}) string {
  202. if v, ok := in.([]interface{}); ok {
  203. s := make([]string, len(v))
  204. for i := range v {
  205. s[i] = fmt.Sprintf("%#v", v[i])
  206. }
  207. return "[" + strings.Join(s, ", ") + "]"
  208. } else {
  209. return fmt.Sprintf("%#v", in)
  210. }
  211. }
  212. func pathTestConfig(buildDir string) Config {
  213. return TestConfig(buildDir, nil, "", nil)
  214. }
  215. func TestPathForModuleInstall(t *testing.T) {
  216. testConfig := pathTestConfig("")
  217. hostTarget := Target{Os: Linux, Arch: Arch{ArchType: X86}}
  218. deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
  219. testCases := []struct {
  220. name string
  221. ctx *testModuleInstallPathContext
  222. in []string
  223. out string
  224. partitionDir string
  225. }{
  226. {
  227. name: "host binary",
  228. ctx: &testModuleInstallPathContext{
  229. baseModuleContext: baseModuleContext{
  230. os: hostTarget.Os,
  231. target: hostTarget,
  232. },
  233. },
  234. in: []string{"bin", "my_test"},
  235. out: "host/linux-x86/bin/my_test",
  236. partitionDir: "host/linux-x86",
  237. },
  238. {
  239. name: "system binary",
  240. ctx: &testModuleInstallPathContext{
  241. baseModuleContext: baseModuleContext{
  242. os: deviceTarget.Os,
  243. target: deviceTarget,
  244. },
  245. },
  246. in: []string{"bin", "my_test"},
  247. out: "target/product/test_device/system/bin/my_test",
  248. partitionDir: "target/product/test_device/system",
  249. },
  250. {
  251. name: "vendor binary",
  252. ctx: &testModuleInstallPathContext{
  253. baseModuleContext: baseModuleContext{
  254. os: deviceTarget.Os,
  255. target: deviceTarget,
  256. earlyModuleContext: earlyModuleContext{
  257. kind: socSpecificModule,
  258. },
  259. },
  260. },
  261. in: []string{"bin", "my_test"},
  262. out: "target/product/test_device/vendor/bin/my_test",
  263. partitionDir: "target/product/test_device/vendor",
  264. },
  265. {
  266. name: "odm binary",
  267. ctx: &testModuleInstallPathContext{
  268. baseModuleContext: baseModuleContext{
  269. os: deviceTarget.Os,
  270. target: deviceTarget,
  271. earlyModuleContext: earlyModuleContext{
  272. kind: deviceSpecificModule,
  273. },
  274. },
  275. },
  276. in: []string{"bin", "my_test"},
  277. out: "target/product/test_device/odm/bin/my_test",
  278. partitionDir: "target/product/test_device/odm",
  279. },
  280. {
  281. name: "product binary",
  282. ctx: &testModuleInstallPathContext{
  283. baseModuleContext: baseModuleContext{
  284. os: deviceTarget.Os,
  285. target: deviceTarget,
  286. earlyModuleContext: earlyModuleContext{
  287. kind: productSpecificModule,
  288. },
  289. },
  290. },
  291. in: []string{"bin", "my_test"},
  292. out: "target/product/test_device/product/bin/my_test",
  293. partitionDir: "target/product/test_device/product",
  294. },
  295. {
  296. name: "system_ext binary",
  297. ctx: &testModuleInstallPathContext{
  298. baseModuleContext: baseModuleContext{
  299. os: deviceTarget.Os,
  300. target: deviceTarget,
  301. earlyModuleContext: earlyModuleContext{
  302. kind: systemExtSpecificModule,
  303. },
  304. },
  305. },
  306. in: []string{"bin", "my_test"},
  307. out: "target/product/test_device/system_ext/bin/my_test",
  308. partitionDir: "target/product/test_device/system_ext",
  309. },
  310. {
  311. name: "root binary",
  312. ctx: &testModuleInstallPathContext{
  313. baseModuleContext: baseModuleContext{
  314. os: deviceTarget.Os,
  315. target: deviceTarget,
  316. },
  317. inRoot: true,
  318. },
  319. in: []string{"my_test"},
  320. out: "target/product/test_device/root/my_test",
  321. partitionDir: "target/product/test_device/root",
  322. },
  323. {
  324. name: "recovery binary",
  325. ctx: &testModuleInstallPathContext{
  326. baseModuleContext: baseModuleContext{
  327. os: deviceTarget.Os,
  328. target: deviceTarget,
  329. },
  330. inRecovery: true,
  331. },
  332. in: []string{"bin/my_test"},
  333. out: "target/product/test_device/recovery/root/system/bin/my_test",
  334. partitionDir: "target/product/test_device/recovery/root/system",
  335. },
  336. {
  337. name: "recovery root binary",
  338. ctx: &testModuleInstallPathContext{
  339. baseModuleContext: baseModuleContext{
  340. os: deviceTarget.Os,
  341. target: deviceTarget,
  342. },
  343. inRecovery: true,
  344. inRoot: true,
  345. },
  346. in: []string{"my_test"},
  347. out: "target/product/test_device/recovery/root/my_test",
  348. partitionDir: "target/product/test_device/recovery/root",
  349. },
  350. {
  351. name: "ramdisk binary",
  352. ctx: &testModuleInstallPathContext{
  353. baseModuleContext: baseModuleContext{
  354. os: deviceTarget.Os,
  355. target: deviceTarget,
  356. },
  357. inRamdisk: true,
  358. },
  359. in: []string{"my_test"},
  360. out: "target/product/test_device/ramdisk/system/my_test",
  361. partitionDir: "target/product/test_device/ramdisk/system",
  362. },
  363. {
  364. name: "ramdisk root binary",
  365. ctx: &testModuleInstallPathContext{
  366. baseModuleContext: baseModuleContext{
  367. os: deviceTarget.Os,
  368. target: deviceTarget,
  369. },
  370. inRamdisk: true,
  371. inRoot: true,
  372. },
  373. in: []string{"my_test"},
  374. out: "target/product/test_device/ramdisk/my_test",
  375. partitionDir: "target/product/test_device/ramdisk",
  376. },
  377. {
  378. name: "vendor_ramdisk binary",
  379. ctx: &testModuleInstallPathContext{
  380. baseModuleContext: baseModuleContext{
  381. os: deviceTarget.Os,
  382. target: deviceTarget,
  383. },
  384. inVendorRamdisk: true,
  385. },
  386. in: []string{"my_test"},
  387. out: "target/product/test_device/vendor_ramdisk/system/my_test",
  388. partitionDir: "target/product/test_device/vendor_ramdisk/system",
  389. },
  390. {
  391. name: "vendor_ramdisk root binary",
  392. ctx: &testModuleInstallPathContext{
  393. baseModuleContext: baseModuleContext{
  394. os: deviceTarget.Os,
  395. target: deviceTarget,
  396. },
  397. inVendorRamdisk: true,
  398. inRoot: true,
  399. },
  400. in: []string{"my_test"},
  401. out: "target/product/test_device/vendor_ramdisk/my_test",
  402. partitionDir: "target/product/test_device/vendor_ramdisk",
  403. },
  404. {
  405. name: "debug_ramdisk binary",
  406. ctx: &testModuleInstallPathContext{
  407. baseModuleContext: baseModuleContext{
  408. os: deviceTarget.Os,
  409. target: deviceTarget,
  410. },
  411. inDebugRamdisk: true,
  412. },
  413. in: []string{"my_test"},
  414. out: "target/product/test_device/debug_ramdisk/my_test",
  415. partitionDir: "target/product/test_device/debug_ramdisk",
  416. },
  417. {
  418. name: "system native test binary",
  419. ctx: &testModuleInstallPathContext{
  420. baseModuleContext: baseModuleContext{
  421. os: deviceTarget.Os,
  422. target: deviceTarget,
  423. },
  424. inData: true,
  425. },
  426. in: []string{"nativetest", "my_test"},
  427. out: "target/product/test_device/data/nativetest/my_test",
  428. partitionDir: "target/product/test_device/data",
  429. },
  430. {
  431. name: "vendor native test binary",
  432. ctx: &testModuleInstallPathContext{
  433. baseModuleContext: baseModuleContext{
  434. os: deviceTarget.Os,
  435. target: deviceTarget,
  436. earlyModuleContext: earlyModuleContext{
  437. kind: socSpecificModule,
  438. },
  439. },
  440. inData: true,
  441. },
  442. in: []string{"nativetest", "my_test"},
  443. out: "target/product/test_device/data/nativetest/my_test",
  444. partitionDir: "target/product/test_device/data",
  445. },
  446. {
  447. name: "odm native test binary",
  448. ctx: &testModuleInstallPathContext{
  449. baseModuleContext: baseModuleContext{
  450. os: deviceTarget.Os,
  451. target: deviceTarget,
  452. earlyModuleContext: earlyModuleContext{
  453. kind: deviceSpecificModule,
  454. },
  455. },
  456. inData: true,
  457. },
  458. in: []string{"nativetest", "my_test"},
  459. out: "target/product/test_device/data/nativetest/my_test",
  460. partitionDir: "target/product/test_device/data",
  461. },
  462. {
  463. name: "product native test binary",
  464. ctx: &testModuleInstallPathContext{
  465. baseModuleContext: baseModuleContext{
  466. os: deviceTarget.Os,
  467. target: deviceTarget,
  468. earlyModuleContext: earlyModuleContext{
  469. kind: productSpecificModule,
  470. },
  471. },
  472. inData: true,
  473. },
  474. in: []string{"nativetest", "my_test"},
  475. out: "target/product/test_device/data/nativetest/my_test",
  476. partitionDir: "target/product/test_device/data",
  477. },
  478. {
  479. name: "system_ext native test binary",
  480. ctx: &testModuleInstallPathContext{
  481. baseModuleContext: baseModuleContext{
  482. os: deviceTarget.Os,
  483. target: deviceTarget,
  484. earlyModuleContext: earlyModuleContext{
  485. kind: systemExtSpecificModule,
  486. },
  487. },
  488. inData: true,
  489. },
  490. in: []string{"nativetest", "my_test"},
  491. out: "target/product/test_device/data/nativetest/my_test",
  492. partitionDir: "target/product/test_device/data",
  493. },
  494. {
  495. name: "sanitized system binary",
  496. ctx: &testModuleInstallPathContext{
  497. baseModuleContext: baseModuleContext{
  498. os: deviceTarget.Os,
  499. target: deviceTarget,
  500. },
  501. inSanitizerDir: true,
  502. },
  503. in: []string{"bin", "my_test"},
  504. out: "target/product/test_device/data/asan/system/bin/my_test",
  505. partitionDir: "target/product/test_device/data/asan/system",
  506. },
  507. {
  508. name: "sanitized vendor binary",
  509. ctx: &testModuleInstallPathContext{
  510. baseModuleContext: baseModuleContext{
  511. os: deviceTarget.Os,
  512. target: deviceTarget,
  513. earlyModuleContext: earlyModuleContext{
  514. kind: socSpecificModule,
  515. },
  516. },
  517. inSanitizerDir: true,
  518. },
  519. in: []string{"bin", "my_test"},
  520. out: "target/product/test_device/data/asan/vendor/bin/my_test",
  521. partitionDir: "target/product/test_device/data/asan/vendor",
  522. },
  523. {
  524. name: "sanitized odm binary",
  525. ctx: &testModuleInstallPathContext{
  526. baseModuleContext: baseModuleContext{
  527. os: deviceTarget.Os,
  528. target: deviceTarget,
  529. earlyModuleContext: earlyModuleContext{
  530. kind: deviceSpecificModule,
  531. },
  532. },
  533. inSanitizerDir: true,
  534. },
  535. in: []string{"bin", "my_test"},
  536. out: "target/product/test_device/data/asan/odm/bin/my_test",
  537. partitionDir: "target/product/test_device/data/asan/odm",
  538. },
  539. {
  540. name: "sanitized product binary",
  541. ctx: &testModuleInstallPathContext{
  542. baseModuleContext: baseModuleContext{
  543. os: deviceTarget.Os,
  544. target: deviceTarget,
  545. earlyModuleContext: earlyModuleContext{
  546. kind: productSpecificModule,
  547. },
  548. },
  549. inSanitizerDir: true,
  550. },
  551. in: []string{"bin", "my_test"},
  552. out: "target/product/test_device/data/asan/product/bin/my_test",
  553. partitionDir: "target/product/test_device/data/asan/product",
  554. },
  555. {
  556. name: "sanitized system_ext binary",
  557. ctx: &testModuleInstallPathContext{
  558. baseModuleContext: baseModuleContext{
  559. os: deviceTarget.Os,
  560. target: deviceTarget,
  561. earlyModuleContext: earlyModuleContext{
  562. kind: systemExtSpecificModule,
  563. },
  564. },
  565. inSanitizerDir: true,
  566. },
  567. in: []string{"bin", "my_test"},
  568. out: "target/product/test_device/data/asan/system_ext/bin/my_test",
  569. partitionDir: "target/product/test_device/data/asan/system_ext",
  570. },
  571. {
  572. name: "sanitized system native test binary",
  573. ctx: &testModuleInstallPathContext{
  574. baseModuleContext: baseModuleContext{
  575. os: deviceTarget.Os,
  576. target: deviceTarget,
  577. },
  578. inData: true,
  579. inSanitizerDir: true,
  580. },
  581. in: []string{"nativetest", "my_test"},
  582. out: "target/product/test_device/data/asan/data/nativetest/my_test",
  583. partitionDir: "target/product/test_device/data/asan/data",
  584. },
  585. {
  586. name: "sanitized vendor native test binary",
  587. ctx: &testModuleInstallPathContext{
  588. baseModuleContext: baseModuleContext{
  589. os: deviceTarget.Os,
  590. target: deviceTarget,
  591. earlyModuleContext: earlyModuleContext{
  592. kind: socSpecificModule,
  593. },
  594. },
  595. inData: true,
  596. inSanitizerDir: true,
  597. },
  598. in: []string{"nativetest", "my_test"},
  599. out: "target/product/test_device/data/asan/data/nativetest/my_test",
  600. partitionDir: "target/product/test_device/data/asan/data",
  601. },
  602. {
  603. name: "sanitized odm native test binary",
  604. ctx: &testModuleInstallPathContext{
  605. baseModuleContext: baseModuleContext{
  606. os: deviceTarget.Os,
  607. target: deviceTarget,
  608. earlyModuleContext: earlyModuleContext{
  609. kind: deviceSpecificModule,
  610. },
  611. },
  612. inData: true,
  613. inSanitizerDir: true,
  614. },
  615. in: []string{"nativetest", "my_test"},
  616. out: "target/product/test_device/data/asan/data/nativetest/my_test",
  617. partitionDir: "target/product/test_device/data/asan/data",
  618. },
  619. {
  620. name: "sanitized product native test binary",
  621. ctx: &testModuleInstallPathContext{
  622. baseModuleContext: baseModuleContext{
  623. os: deviceTarget.Os,
  624. target: deviceTarget,
  625. earlyModuleContext: earlyModuleContext{
  626. kind: productSpecificModule,
  627. },
  628. },
  629. inData: true,
  630. inSanitizerDir: true,
  631. },
  632. in: []string{"nativetest", "my_test"},
  633. out: "target/product/test_device/data/asan/data/nativetest/my_test",
  634. partitionDir: "target/product/test_device/data/asan/data",
  635. },
  636. {
  637. name: "sanitized system_ext native test binary",
  638. ctx: &testModuleInstallPathContext{
  639. baseModuleContext: baseModuleContext{
  640. os: deviceTarget.Os,
  641. target: deviceTarget,
  642. earlyModuleContext: earlyModuleContext{
  643. kind: systemExtSpecificModule,
  644. },
  645. },
  646. inData: true,
  647. inSanitizerDir: true,
  648. },
  649. in: []string{"nativetest", "my_test"},
  650. out: "target/product/test_device/data/asan/data/nativetest/my_test",
  651. partitionDir: "target/product/test_device/data/asan/data",
  652. }, {
  653. name: "device testcases",
  654. ctx: &testModuleInstallPathContext{
  655. baseModuleContext: baseModuleContext{
  656. os: deviceTarget.Os,
  657. target: deviceTarget,
  658. },
  659. inTestcases: true,
  660. },
  661. in: []string{"my_test", "my_test_bin"},
  662. out: "target/product/test_device/testcases/my_test/my_test_bin",
  663. partitionDir: "target/product/test_device/testcases",
  664. }, {
  665. name: "host testcases",
  666. ctx: &testModuleInstallPathContext{
  667. baseModuleContext: baseModuleContext{
  668. os: hostTarget.Os,
  669. target: hostTarget,
  670. },
  671. inTestcases: true,
  672. },
  673. in: []string{"my_test", "my_test_bin"},
  674. out: "host/linux-x86/testcases/my_test/my_test_bin",
  675. partitionDir: "host/linux-x86/testcases",
  676. }, {
  677. name: "forced host testcases",
  678. ctx: &testModuleInstallPathContext{
  679. baseModuleContext: baseModuleContext{
  680. os: deviceTarget.Os,
  681. target: deviceTarget,
  682. },
  683. inTestcases: true,
  684. forceOS: &Linux,
  685. forceArch: &X86,
  686. },
  687. in: []string{"my_test", "my_test_bin"},
  688. out: "host/linux-x86/testcases/my_test/my_test_bin",
  689. partitionDir: "host/linux-x86/testcases",
  690. },
  691. }
  692. for _, tc := range testCases {
  693. t.Run(tc.name, func(t *testing.T) {
  694. tc.ctx.baseModuleContext.config = testConfig
  695. output := PathForModuleInstall(tc.ctx, tc.in...)
  696. if output.basePath.path != tc.out {
  697. t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
  698. output.basePath.path,
  699. tc.out)
  700. }
  701. if output.partitionDir != tc.partitionDir {
  702. t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
  703. output.partitionDir, tc.partitionDir)
  704. }
  705. })
  706. }
  707. }
  708. func TestPathForModuleInstallRecoveryAsBoot(t *testing.T) {
  709. testConfig := pathTestConfig("")
  710. testConfig.TestProductVariables.BoardUsesRecoveryAsBoot = proptools.BoolPtr(true)
  711. testConfig.TestProductVariables.BoardMoveRecoveryResourcesToVendorBoot = proptools.BoolPtr(true)
  712. deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
  713. testCases := []struct {
  714. name string
  715. ctx *testModuleInstallPathContext
  716. in []string
  717. out string
  718. partitionDir string
  719. }{
  720. {
  721. name: "ramdisk binary",
  722. ctx: &testModuleInstallPathContext{
  723. baseModuleContext: baseModuleContext{
  724. os: deviceTarget.Os,
  725. target: deviceTarget,
  726. },
  727. inRamdisk: true,
  728. inRoot: true,
  729. },
  730. in: []string{"my_test"},
  731. out: "target/product/test_device/recovery/root/first_stage_ramdisk/my_test",
  732. partitionDir: "target/product/test_device/recovery/root/first_stage_ramdisk",
  733. },
  734. {
  735. name: "vendor_ramdisk binary",
  736. ctx: &testModuleInstallPathContext{
  737. baseModuleContext: baseModuleContext{
  738. os: deviceTarget.Os,
  739. target: deviceTarget,
  740. },
  741. inVendorRamdisk: true,
  742. inRoot: true,
  743. },
  744. in: []string{"my_test"},
  745. out: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk/my_test",
  746. partitionDir: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk",
  747. },
  748. }
  749. for _, tc := range testCases {
  750. t.Run(tc.name, func(t *testing.T) {
  751. tc.ctx.baseModuleContext.config = testConfig
  752. output := PathForModuleInstall(tc.ctx, tc.in...)
  753. if output.basePath.path != tc.out {
  754. t.Errorf("unexpected path:\n got: %q\nwant: %q\n",
  755. output.basePath.path,
  756. tc.out)
  757. }
  758. if output.partitionDir != tc.partitionDir {
  759. t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n",
  760. output.partitionDir, tc.partitionDir)
  761. }
  762. })
  763. }
  764. }
  765. func TestBaseDirForInstallPath(t *testing.T) {
  766. testConfig := pathTestConfig("")
  767. deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
  768. ctx := &testModuleInstallPathContext{
  769. baseModuleContext: baseModuleContext{
  770. os: deviceTarget.Os,
  771. target: deviceTarget,
  772. },
  773. }
  774. ctx.baseModuleContext.config = testConfig
  775. actual := PathForModuleInstall(ctx, "foo", "bar")
  776. expectedBaseDir := "target/product/test_device/system"
  777. if actual.partitionDir != expectedBaseDir {
  778. t.Errorf("unexpected partitionDir:\n got: %q\nwant: %q\n", actual.partitionDir, expectedBaseDir)
  779. }
  780. expectedRelPath := "foo/bar"
  781. if actual.Rel() != expectedRelPath {
  782. t.Errorf("unexpected Rel():\n got: %q\nwant: %q\n", actual.Rel(), expectedRelPath)
  783. }
  784. actualAfterJoin := actual.Join(ctx, "baz")
  785. // partitionDir is preserved even after joining
  786. if actualAfterJoin.partitionDir != expectedBaseDir {
  787. t.Errorf("unexpected partitionDir after joining:\n got: %q\nwant: %q\n", actualAfterJoin.partitionDir, expectedBaseDir)
  788. }
  789. // Rel() is updated though
  790. expectedRelAfterJoin := "baz"
  791. if actualAfterJoin.Rel() != expectedRelAfterJoin {
  792. t.Errorf("unexpected Rel() after joining:\n got: %q\nwant: %q\n", actualAfterJoin.Rel(), expectedRelAfterJoin)
  793. }
  794. }
  795. func TestDirectorySortedPaths(t *testing.T) {
  796. config := TestConfig("out", nil, "", map[string][]byte{
  797. "Android.bp": nil,
  798. "a.txt": nil,
  799. "a/txt": nil,
  800. "a/b/c": nil,
  801. "a/b/d": nil,
  802. "b": nil,
  803. "b/b.txt": nil,
  804. "a/a.txt": nil,
  805. })
  806. ctx := PathContextForTesting(config)
  807. makePaths := func() Paths {
  808. return Paths{
  809. PathForSource(ctx, "a.txt"),
  810. PathForSource(ctx, "a/txt"),
  811. PathForSource(ctx, "a/b/c"),
  812. PathForSource(ctx, "a/b/d"),
  813. PathForSource(ctx, "b"),
  814. PathForSource(ctx, "b/b.txt"),
  815. PathForSource(ctx, "a/a.txt"),
  816. }
  817. }
  818. expected := []string{
  819. "a.txt",
  820. "a/a.txt",
  821. "a/b/c",
  822. "a/b/d",
  823. "a/txt",
  824. "b",
  825. "b/b.txt",
  826. }
  827. paths := makePaths()
  828. reversePaths := ReversePaths(paths)
  829. sortedPaths := PathsToDirectorySortedPaths(paths)
  830. reverseSortedPaths := PathsToDirectorySortedPaths(reversePaths)
  831. if !reflect.DeepEqual(Paths(sortedPaths).Strings(), expected) {
  832. t.Fatalf("sorted paths:\n %#v\n != \n %#v", paths.Strings(), expected)
  833. }
  834. if !reflect.DeepEqual(Paths(reverseSortedPaths).Strings(), expected) {
  835. t.Fatalf("sorted reversed paths:\n %#v\n !=\n %#v", reversePaths.Strings(), expected)
  836. }
  837. expectedA := []string{
  838. "a/a.txt",
  839. "a/b/c",
  840. "a/b/d",
  841. "a/txt",
  842. }
  843. inA := sortedPaths.PathsInDirectory("a")
  844. if !reflect.DeepEqual(inA.Strings(), expectedA) {
  845. t.Errorf("FilesInDirectory(a):\n %#v\n != \n %#v", inA.Strings(), expectedA)
  846. }
  847. expectedA_B := []string{
  848. "a/b/c",
  849. "a/b/d",
  850. }
  851. inA_B := sortedPaths.PathsInDirectory("a/b")
  852. if !reflect.DeepEqual(inA_B.Strings(), expectedA_B) {
  853. t.Errorf("FilesInDirectory(a/b):\n %#v\n != \n %#v", inA_B.Strings(), expectedA_B)
  854. }
  855. expectedB := []string{
  856. "b/b.txt",
  857. }
  858. inB := sortedPaths.PathsInDirectory("b")
  859. if !reflect.DeepEqual(inB.Strings(), expectedB) {
  860. t.Errorf("FilesInDirectory(b):\n %#v\n != \n %#v", inA.Strings(), expectedA)
  861. }
  862. }
  863. func TestMaybeRel(t *testing.T) {
  864. testCases := []struct {
  865. name string
  866. base string
  867. target string
  868. out string
  869. isRel bool
  870. }{
  871. {
  872. name: "normal",
  873. base: "a/b/c",
  874. target: "a/b/c/d",
  875. out: "d",
  876. isRel: true,
  877. },
  878. {
  879. name: "parent",
  880. base: "a/b/c/d",
  881. target: "a/b/c",
  882. isRel: false,
  883. },
  884. {
  885. name: "not relative",
  886. base: "a/b",
  887. target: "c/d",
  888. isRel: false,
  889. },
  890. {
  891. name: "abs1",
  892. base: "/a",
  893. target: "a",
  894. isRel: false,
  895. },
  896. {
  897. name: "abs2",
  898. base: "a",
  899. target: "/a",
  900. isRel: false,
  901. },
  902. }
  903. for _, testCase := range testCases {
  904. t.Run(testCase.name, func(t *testing.T) {
  905. ctx := &configErrorWrapper{}
  906. out, isRel := MaybeRel(ctx, testCase.base, testCase.target)
  907. if len(ctx.errors) > 0 {
  908. t.Errorf("MaybeRel(..., %s, %s) reported unexpected errors %v",
  909. testCase.base, testCase.target, ctx.errors)
  910. }
  911. if isRel != testCase.isRel || out != testCase.out {
  912. t.Errorf("MaybeRel(..., %s, %s) want %v, %v got %v, %v",
  913. testCase.base, testCase.target, testCase.out, testCase.isRel, out, isRel)
  914. }
  915. })
  916. }
  917. }
  918. func TestPathForSource(t *testing.T) {
  919. testCases := []struct {
  920. name string
  921. buildDir string
  922. src string
  923. err string
  924. }{
  925. {
  926. name: "normal",
  927. buildDir: "out",
  928. src: "a/b/c",
  929. },
  930. {
  931. name: "abs",
  932. buildDir: "out",
  933. src: "/a/b/c",
  934. err: "is outside directory",
  935. },
  936. {
  937. name: "in out dir",
  938. buildDir: "out",
  939. src: "out/soong/a/b/c",
  940. err: "is in output",
  941. },
  942. }
  943. funcs := []struct {
  944. name string
  945. f func(ctx PathContext, pathComponents ...string) (SourcePath, error)
  946. }{
  947. {"pathForSource", pathForSource},
  948. {"safePathForSource", safePathForSource},
  949. }
  950. for _, f := range funcs {
  951. t.Run(f.name, func(t *testing.T) {
  952. for _, test := range testCases {
  953. t.Run(test.name, func(t *testing.T) {
  954. testConfig := pathTestConfig(test.buildDir)
  955. ctx := &configErrorWrapper{config: testConfig}
  956. _, err := f.f(ctx, test.src)
  957. if len(ctx.errors) > 0 {
  958. t.Fatalf("unexpected errors %v", ctx.errors)
  959. }
  960. if err != nil {
  961. if test.err == "" {
  962. t.Fatalf("unexpected error %q", err.Error())
  963. } else if !strings.Contains(err.Error(), test.err) {
  964. t.Fatalf("incorrect error, want substring %q got %q", test.err, err.Error())
  965. }
  966. } else {
  967. if test.err != "" {
  968. t.Fatalf("missing error %q", test.err)
  969. }
  970. }
  971. })
  972. }
  973. })
  974. }
  975. }
  976. type pathForModuleSrcTestModule struct {
  977. ModuleBase
  978. props struct {
  979. Srcs []string `android:"path"`
  980. Exclude_srcs []string `android:"path"`
  981. Src *string `android:"path"`
  982. Module_handles_missing_deps bool
  983. }
  984. src string
  985. rel string
  986. srcs []string
  987. rels []string
  988. missingDeps []string
  989. }
  990. func pathForModuleSrcTestModuleFactory() Module {
  991. module := &pathForModuleSrcTestModule{}
  992. module.AddProperties(&module.props)
  993. InitAndroidModule(module)
  994. return module
  995. }
  996. func (p *pathForModuleSrcTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
  997. var srcs Paths
  998. if p.props.Module_handles_missing_deps {
  999. srcs, p.missingDeps = PathsAndMissingDepsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
  1000. } else {
  1001. srcs = PathsForModuleSrcExcludes(ctx, p.props.Srcs, p.props.Exclude_srcs)
  1002. }
  1003. p.srcs = srcs.Strings()
  1004. for _, src := range srcs {
  1005. p.rels = append(p.rels, src.Rel())
  1006. }
  1007. if p.props.Src != nil {
  1008. src := PathForModuleSrc(ctx, *p.props.Src)
  1009. if src != nil {
  1010. p.src = src.String()
  1011. p.rel = src.Rel()
  1012. }
  1013. }
  1014. if !p.props.Module_handles_missing_deps {
  1015. p.missingDeps = ctx.GetMissingDependencies()
  1016. }
  1017. ctx.Build(pctx, BuildParams{
  1018. Rule: Touch,
  1019. Output: PathForModuleOut(ctx, "output"),
  1020. })
  1021. }
  1022. type pathForModuleSrcOutputFileProviderModule struct {
  1023. ModuleBase
  1024. props struct {
  1025. Outs []string
  1026. Tagged []string
  1027. }
  1028. outs Paths
  1029. tagged Paths
  1030. }
  1031. func pathForModuleSrcOutputFileProviderModuleFactory() Module {
  1032. module := &pathForModuleSrcOutputFileProviderModule{}
  1033. module.AddProperties(&module.props)
  1034. InitAndroidModule(module)
  1035. return module
  1036. }
  1037. func (p *pathForModuleSrcOutputFileProviderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
  1038. for _, out := range p.props.Outs {
  1039. p.outs = append(p.outs, PathForModuleOut(ctx, out))
  1040. }
  1041. for _, tagged := range p.props.Tagged {
  1042. p.tagged = append(p.tagged, PathForModuleOut(ctx, tagged))
  1043. }
  1044. }
  1045. func (p *pathForModuleSrcOutputFileProviderModule) OutputFiles(tag string) (Paths, error) {
  1046. switch tag {
  1047. case "":
  1048. return p.outs, nil
  1049. case ".tagged":
  1050. return p.tagged, nil
  1051. default:
  1052. return nil, fmt.Errorf("unsupported tag %q", tag)
  1053. }
  1054. }
  1055. type pathForModuleSrcTestCase struct {
  1056. name string
  1057. bp string
  1058. srcs []string
  1059. rels []string
  1060. src string
  1061. rel string
  1062. // Make test specific preparations to the test fixture.
  1063. preparer FixturePreparer
  1064. // A test specific error handler.
  1065. errorHandler FixtureErrorHandler
  1066. }
  1067. func testPathForModuleSrc(t *testing.T, tests []pathForModuleSrcTestCase) {
  1068. for _, test := range tests {
  1069. t.Run(test.name, func(t *testing.T) {
  1070. fgBp := `
  1071. filegroup {
  1072. name: "a",
  1073. srcs: ["src/a"],
  1074. }
  1075. `
  1076. ofpBp := `
  1077. output_file_provider {
  1078. name: "b",
  1079. outs: ["gen/b"],
  1080. tagged: ["gen/c"],
  1081. }
  1082. `
  1083. mockFS := MockFS{
  1084. "fg/Android.bp": []byte(fgBp),
  1085. "foo/Android.bp": []byte(test.bp),
  1086. "ofp/Android.bp": []byte(ofpBp),
  1087. "fg/src/a": nil,
  1088. "foo/src/b": nil,
  1089. "foo/src/c": nil,
  1090. "foo/src/d": nil,
  1091. "foo/src/e/e": nil,
  1092. "foo/src_special/$": nil,
  1093. }
  1094. errorHandler := test.errorHandler
  1095. if errorHandler == nil {
  1096. errorHandler = FixtureExpectsNoErrors
  1097. }
  1098. result := GroupFixturePreparers(
  1099. FixtureRegisterWithContext(func(ctx RegistrationContext) {
  1100. ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
  1101. ctx.RegisterModuleType("output_file_provider", pathForModuleSrcOutputFileProviderModuleFactory)
  1102. }),
  1103. PrepareForTestWithFilegroup,
  1104. PrepareForTestWithNamespace,
  1105. mockFS.AddToFixture(),
  1106. OptionalFixturePreparer(test.preparer),
  1107. ).
  1108. ExtendWithErrorHandler(errorHandler).
  1109. RunTest(t)
  1110. m := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
  1111. AssertStringPathsRelativeToTopEquals(t, "srcs", result.Config, test.srcs, m.srcs)
  1112. AssertStringPathsRelativeToTopEquals(t, "rels", result.Config, test.rels, m.rels)
  1113. AssertStringPathRelativeToTopEquals(t, "src", result.Config, test.src, m.src)
  1114. AssertStringPathRelativeToTopEquals(t, "rel", result.Config, test.rel, m.rel)
  1115. })
  1116. }
  1117. }
  1118. func TestPathsForModuleSrc(t *testing.T) {
  1119. tests := []pathForModuleSrcTestCase{
  1120. {
  1121. name: "path",
  1122. bp: `
  1123. test {
  1124. name: "foo",
  1125. srcs: ["src/b"],
  1126. }`,
  1127. srcs: []string{"foo/src/b"},
  1128. rels: []string{"src/b"},
  1129. },
  1130. {
  1131. name: "glob",
  1132. bp: `
  1133. test {
  1134. name: "foo",
  1135. srcs: [
  1136. "src/*",
  1137. "src/e/*",
  1138. ],
  1139. }`,
  1140. srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
  1141. rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
  1142. },
  1143. {
  1144. name: "recursive glob",
  1145. bp: `
  1146. test {
  1147. name: "foo",
  1148. srcs: ["src/**/*"],
  1149. }`,
  1150. srcs: []string{"foo/src/b", "foo/src/c", "foo/src/d", "foo/src/e/e"},
  1151. rels: []string{"src/b", "src/c", "src/d", "src/e/e"},
  1152. },
  1153. {
  1154. name: "filegroup",
  1155. bp: `
  1156. test {
  1157. name: "foo",
  1158. srcs: [":a"],
  1159. }`,
  1160. srcs: []string{"fg/src/a"},
  1161. rels: []string{"src/a"},
  1162. },
  1163. {
  1164. name: "output file provider",
  1165. bp: `
  1166. test {
  1167. name: "foo",
  1168. srcs: [":b"],
  1169. }`,
  1170. srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
  1171. rels: []string{"gen/b"},
  1172. },
  1173. {
  1174. name: "output file provider tagged",
  1175. bp: `
  1176. test {
  1177. name: "foo",
  1178. srcs: [":b{.tagged}"],
  1179. }`,
  1180. srcs: []string{"out/soong/.intermediates/ofp/b/gen/c"},
  1181. rels: []string{"gen/c"},
  1182. },
  1183. {
  1184. name: "output file provider with exclude",
  1185. bp: `
  1186. test {
  1187. name: "foo",
  1188. srcs: [":b", ":c"],
  1189. exclude_srcs: [":c"]
  1190. }
  1191. output_file_provider {
  1192. name: "c",
  1193. outs: ["gen/c"],
  1194. }`,
  1195. srcs: []string{"out/soong/.intermediates/ofp/b/gen/b"},
  1196. rels: []string{"gen/b"},
  1197. },
  1198. {
  1199. name: "special characters glob",
  1200. bp: `
  1201. test {
  1202. name: "foo",
  1203. srcs: ["src_special/*"],
  1204. }`,
  1205. srcs: []string{"foo/src_special/$"},
  1206. rels: []string{"src_special/$"},
  1207. },
  1208. }
  1209. testPathForModuleSrc(t, tests)
  1210. }
  1211. func TestPathForModuleSrc(t *testing.T) {
  1212. tests := []pathForModuleSrcTestCase{
  1213. {
  1214. name: "path",
  1215. bp: `
  1216. test {
  1217. name: "foo",
  1218. src: "src/b",
  1219. }`,
  1220. src: "foo/src/b",
  1221. rel: "src/b",
  1222. },
  1223. {
  1224. name: "glob",
  1225. bp: `
  1226. test {
  1227. name: "foo",
  1228. src: "src/e/*",
  1229. }`,
  1230. src: "foo/src/e/e",
  1231. rel: "src/e/e",
  1232. },
  1233. {
  1234. name: "filegroup",
  1235. bp: `
  1236. test {
  1237. name: "foo",
  1238. src: ":a",
  1239. }`,
  1240. src: "fg/src/a",
  1241. rel: "src/a",
  1242. },
  1243. {
  1244. name: "output file provider",
  1245. bp: `
  1246. test {
  1247. name: "foo",
  1248. src: ":b",
  1249. }`,
  1250. src: "out/soong/.intermediates/ofp/b/gen/b",
  1251. rel: "gen/b",
  1252. },
  1253. {
  1254. name: "output file provider tagged",
  1255. bp: `
  1256. test {
  1257. name: "foo",
  1258. src: ":b{.tagged}",
  1259. }`,
  1260. src: "out/soong/.intermediates/ofp/b/gen/c",
  1261. rel: "gen/c",
  1262. },
  1263. {
  1264. name: "special characters glob",
  1265. bp: `
  1266. test {
  1267. name: "foo",
  1268. src: "src_special/*",
  1269. }`,
  1270. src: "foo/src_special/$",
  1271. rel: "src_special/$",
  1272. },
  1273. {
  1274. // This test makes sure that an unqualified module name cannot contain characters that make
  1275. // it appear as a qualified module name.
  1276. name: "output file provider, invalid fully qualified name",
  1277. bp: `
  1278. test {
  1279. name: "foo",
  1280. src: "://other:b",
  1281. srcs: ["://other:c"],
  1282. }`,
  1283. preparer: FixtureAddTextFile("other/Android.bp", `
  1284. soong_namespace {}
  1285. output_file_provider {
  1286. name: "b",
  1287. outs: ["gen/b"],
  1288. }
  1289. output_file_provider {
  1290. name: "c",
  1291. outs: ["gen/c"],
  1292. }
  1293. `),
  1294. src: "foo/:/other:b",
  1295. rel: ":/other:b",
  1296. srcs: []string{"foo/:/other:c"},
  1297. rels: []string{":/other:c"},
  1298. },
  1299. {
  1300. name: "output file provider, missing fully qualified name",
  1301. bp: `
  1302. test {
  1303. name: "foo",
  1304. src: "//other:b",
  1305. srcs: ["//other:c"],
  1306. }`,
  1307. errorHandler: FixtureExpectsAllErrorsToMatchAPattern([]string{
  1308. `"foo" depends on undefined module "//other:b"`,
  1309. `"foo" depends on undefined module "//other:c"`,
  1310. }),
  1311. },
  1312. {
  1313. name: "output file provider, fully qualified name",
  1314. bp: `
  1315. test {
  1316. name: "foo",
  1317. src: "//other:b",
  1318. srcs: ["//other:c"],
  1319. }`,
  1320. src: "out/soong/.intermediates/other/b/gen/b",
  1321. rel: "gen/b",
  1322. srcs: []string{"out/soong/.intermediates/other/c/gen/c"},
  1323. rels: []string{"gen/c"},
  1324. preparer: FixtureAddTextFile("other/Android.bp", `
  1325. soong_namespace {}
  1326. output_file_provider {
  1327. name: "b",
  1328. outs: ["gen/b"],
  1329. }
  1330. output_file_provider {
  1331. name: "c",
  1332. outs: ["gen/c"],
  1333. }
  1334. `),
  1335. },
  1336. }
  1337. testPathForModuleSrc(t, tests)
  1338. }
  1339. func TestPathsForModuleSrc_AllowMissingDependencies(t *testing.T) {
  1340. bp := `
  1341. test {
  1342. name: "foo",
  1343. srcs: [":a"],
  1344. exclude_srcs: [":b"],
  1345. src: ":c",
  1346. }
  1347. test {
  1348. name: "bar",
  1349. srcs: [":d"],
  1350. exclude_srcs: [":e"],
  1351. module_handles_missing_deps: true,
  1352. }
  1353. `
  1354. result := GroupFixturePreparers(
  1355. PrepareForTestWithAllowMissingDependencies,
  1356. FixtureRegisterWithContext(func(ctx RegistrationContext) {
  1357. ctx.RegisterModuleType("test", pathForModuleSrcTestModuleFactory)
  1358. }),
  1359. FixtureWithRootAndroidBp(bp),
  1360. ).RunTest(t)
  1361. foo := result.ModuleForTests("foo", "").Module().(*pathForModuleSrcTestModule)
  1362. AssertArrayString(t, "foo missing deps", []string{"a", "b", "c"}, foo.missingDeps)
  1363. AssertArrayString(t, "foo srcs", []string{}, foo.srcs)
  1364. AssertStringEquals(t, "foo src", "", foo.src)
  1365. bar := result.ModuleForTests("bar", "").Module().(*pathForModuleSrcTestModule)
  1366. AssertArrayString(t, "bar missing deps", []string{"d", "e"}, bar.missingDeps)
  1367. AssertArrayString(t, "bar srcs", []string{}, bar.srcs)
  1368. }
  1369. func TestPathRelativeToTop(t *testing.T) {
  1370. testConfig := pathTestConfig("/tmp/build/top")
  1371. deviceTarget := Target{Os: Android, Arch: Arch{ArchType: Arm64}}
  1372. ctx := &testModuleInstallPathContext{
  1373. baseModuleContext: baseModuleContext{
  1374. os: deviceTarget.Os,
  1375. target: deviceTarget,
  1376. },
  1377. }
  1378. ctx.baseModuleContext.config = testConfig
  1379. t.Run("install for soong", func(t *testing.T) {
  1380. p := PathForModuleInstall(ctx, "install/path")
  1381. AssertPathRelativeToTopEquals(t, "install path for soong", "out/soong/target/product/test_device/system/install/path", p)
  1382. })
  1383. t.Run("install for make", func(t *testing.T) {
  1384. p := PathForModuleInstall(ctx, "install/path")
  1385. p.makePath = true
  1386. AssertPathRelativeToTopEquals(t, "install path for make", "out/target/product/test_device/system/install/path", p)
  1387. })
  1388. t.Run("output", func(t *testing.T) {
  1389. p := PathForOutput(ctx, "output/path")
  1390. AssertPathRelativeToTopEquals(t, "output path", "out/soong/output/path", p)
  1391. })
  1392. t.Run("source", func(t *testing.T) {
  1393. p := PathForSource(ctx, "source/path")
  1394. AssertPathRelativeToTopEquals(t, "source path", "source/path", p)
  1395. })
  1396. t.Run("mixture", func(t *testing.T) {
  1397. paths := Paths{
  1398. PathForModuleInstall(ctx, "install/path"),
  1399. PathForOutput(ctx, "output/path"),
  1400. PathForSource(ctx, "source/path"),
  1401. }
  1402. expected := []string{
  1403. "out/soong/target/product/test_device/system/install/path",
  1404. "out/soong/output/path",
  1405. "source/path",
  1406. }
  1407. AssertPathsRelativeToTopEquals(t, "mixture", expected, paths)
  1408. })
  1409. }
  1410. func ExampleOutputPath_ReplaceExtension() {
  1411. ctx := &configErrorWrapper{
  1412. config: TestConfig("out", nil, "", nil),
  1413. }
  1414. p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
  1415. p2 := p.ReplaceExtension(ctx, "oat")
  1416. fmt.Println(p, p2)
  1417. fmt.Println(p.Rel(), p2.Rel())
  1418. // Output:
  1419. // out/soong/system/framework/boot.art out/soong/system/framework/boot.oat
  1420. // boot.art boot.oat
  1421. }
  1422. func ExampleOutputPath_InSameDir() {
  1423. ctx := &configErrorWrapper{
  1424. config: TestConfig("out", nil, "", nil),
  1425. }
  1426. p := PathForOutput(ctx, "system/framework").Join(ctx, "boot.art")
  1427. p2 := p.InSameDir(ctx, "oat", "arm", "boot.vdex")
  1428. fmt.Println(p, p2)
  1429. fmt.Println(p.Rel(), p2.Rel())
  1430. // Output:
  1431. // out/soong/system/framework/boot.art out/soong/system/framework/oat/arm/boot.vdex
  1432. // boot.art oat/arm/boot.vdex
  1433. }
  1434. func BenchmarkFirstUniquePaths(b *testing.B) {
  1435. implementations := []struct {
  1436. name string
  1437. f func(Paths) Paths
  1438. }{
  1439. {
  1440. name: "list",
  1441. f: firstUniquePathsList,
  1442. },
  1443. {
  1444. name: "map",
  1445. f: firstUniquePathsMap,
  1446. },
  1447. }
  1448. const maxSize = 1024
  1449. uniquePaths := make(Paths, maxSize)
  1450. for i := range uniquePaths {
  1451. uniquePaths[i] = PathForTesting(strconv.Itoa(i))
  1452. }
  1453. samePath := make(Paths, maxSize)
  1454. for i := range samePath {
  1455. samePath[i] = uniquePaths[0]
  1456. }
  1457. f := func(b *testing.B, imp func(Paths) Paths, paths Paths) {
  1458. for i := 0; i < b.N; i++ {
  1459. b.ReportAllocs()
  1460. paths = append(Paths(nil), paths...)
  1461. imp(paths)
  1462. }
  1463. }
  1464. for n := 1; n <= maxSize; n <<= 1 {
  1465. b.Run(strconv.Itoa(n), func(b *testing.B) {
  1466. for _, implementation := range implementations {
  1467. b.Run(implementation.name, func(b *testing.B) {
  1468. b.Run("same", func(b *testing.B) {
  1469. f(b, implementation.f, samePath[:n])
  1470. })
  1471. b.Run("unique", func(b *testing.B) {
  1472. f(b, implementation.f, uniquePaths[:n])
  1473. })
  1474. })
  1475. }
  1476. })
  1477. }
  1478. }