droidstubs_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // Copyright 2021 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 java
  15. import (
  16. "fmt"
  17. "reflect"
  18. "regexp"
  19. "strings"
  20. "testing"
  21. "android/soong/android"
  22. )
  23. func TestDroidstubs(t *testing.T) {
  24. ctx, _ := testJavaWithFS(t, `
  25. droiddoc_exported_dir {
  26. name: "droiddoc-templates-sdk",
  27. path: ".",
  28. }
  29. droidstubs {
  30. name: "bar-stubs",
  31. srcs: ["bar-doc/a.java"],
  32. api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
  33. api_levels_annotations_enabled: true,
  34. }
  35. droidstubs {
  36. name: "bar-stubs-other",
  37. srcs: ["bar-doc/a.java"],
  38. high_mem: true,
  39. api_levels_annotations_dirs: ["droiddoc-templates-sdk"],
  40. api_levels_annotations_enabled: true,
  41. api_levels_jar_filename: "android.other.jar",
  42. }
  43. droidstubs {
  44. name: "stubs-applying-api-versions",
  45. srcs: ["bar-doc/a.java"],
  46. api_levels_module: "bar-stubs-other",
  47. }
  48. `,
  49. map[string][]byte{
  50. "bar-doc/a.java": nil,
  51. })
  52. testcases := []struct {
  53. moduleName string
  54. expectedJarFilename string
  55. generate_xml bool
  56. high_mem bool
  57. }{
  58. {
  59. moduleName: "bar-stubs",
  60. generate_xml: true,
  61. expectedJarFilename: "android.jar",
  62. high_mem: false,
  63. },
  64. {
  65. moduleName: "bar-stubs-other",
  66. generate_xml: true,
  67. expectedJarFilename: "android.other.jar",
  68. high_mem: true,
  69. },
  70. {
  71. moduleName: "stubs-applying-api-versions",
  72. generate_xml: false,
  73. },
  74. }
  75. for _, c := range testcases {
  76. m := ctx.ModuleForTests(c.moduleName, "android_common")
  77. manifest := m.Output("metalava.sbox.textproto")
  78. sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
  79. cmdline := String(sboxProto.Commands[0].Command)
  80. android.AssertStringContainsEquals(t, "api-versions generation flag", cmdline, "--generate-api-levels", c.generate_xml)
  81. if c.expectedJarFilename != "" {
  82. expected := "--android-jar-pattern ./%/public/" + c.expectedJarFilename
  83. if !strings.Contains(cmdline, expected) {
  84. t.Errorf("For %q, expected metalava argument %q, but was not found %q", c.moduleName, expected, cmdline)
  85. }
  86. }
  87. metalava := m.Rule("metalava")
  88. rp := metalava.RuleParams
  89. if actual := rp.Pool != nil && strings.Contains(rp.Pool.String(), "highmem"); actual != c.high_mem {
  90. t.Errorf("Expected %q high_mem to be %v, was %v", c.moduleName, c.high_mem, actual)
  91. }
  92. }
  93. }
  94. // runs a test for droidstubs with a customizable sdkType argument and returns
  95. // the list of jar patterns that is passed as `--android-jar-pattern`
  96. func getAndroidJarPatternsForDroidstubs(t *testing.T, sdkType string) []string {
  97. ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
  98. droiddoc_exported_dir {
  99. name: "some-exported-dir",
  100. path: "somedir",
  101. }
  102. droiddoc_exported_dir {
  103. name: "some-other-exported-dir",
  104. path: "someotherdir",
  105. }
  106. droidstubs {
  107. name: "foo-stubs",
  108. srcs: ["foo-doc/a.java"],
  109. api_levels_annotations_dirs: [
  110. "some-exported-dir",
  111. "some-other-exported-dir",
  112. ],
  113. api_levels_annotations_enabled: true,
  114. api_levels_sdk_type: "%s",
  115. }
  116. `, sdkType),
  117. map[string][]byte{
  118. "foo-doc/a.java": nil,
  119. })
  120. m := ctx.ModuleForTests("foo-stubs", "android_common")
  121. manifest := m.Output("metalava.sbox.textproto")
  122. cmd := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
  123. r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`)
  124. return r.FindAllString(cmd, -1)
  125. }
  126. func TestPublicDroidstubs(t *testing.T) {
  127. patterns := getAndroidJarPatternsForDroidstubs(t, "public")
  128. android.AssertArrayString(t, "order of patterns", []string{
  129. "--android-jar-pattern somedir/%/public/android.jar",
  130. "--android-jar-pattern someotherdir/%/public/android.jar",
  131. }, patterns)
  132. }
  133. func TestSystemDroidstubs(t *testing.T) {
  134. patterns := getAndroidJarPatternsForDroidstubs(t, "system")
  135. android.AssertArrayString(t, "order of patterns", []string{
  136. "--android-jar-pattern somedir/%/system/android.jar",
  137. "--android-jar-pattern someotherdir/%/system/android.jar",
  138. "--android-jar-pattern somedir/%/public/android.jar",
  139. "--android-jar-pattern someotherdir/%/public/android.jar",
  140. }, patterns)
  141. }
  142. func TestModuleLibDroidstubs(t *testing.T) {
  143. patterns := getAndroidJarPatternsForDroidstubs(t, "module-lib")
  144. android.AssertArrayString(t, "order of patterns", []string{
  145. "--android-jar-pattern somedir/%/module-lib/android.jar",
  146. "--android-jar-pattern someotherdir/%/module-lib/android.jar",
  147. "--android-jar-pattern somedir/%/system/android.jar",
  148. "--android-jar-pattern someotherdir/%/system/android.jar",
  149. "--android-jar-pattern somedir/%/public/android.jar",
  150. "--android-jar-pattern someotherdir/%/public/android.jar",
  151. }, patterns)
  152. }
  153. func TestSystemServerDroidstubs(t *testing.T) {
  154. patterns := getAndroidJarPatternsForDroidstubs(t, "system-server")
  155. android.AssertArrayString(t, "order of patterns", []string{
  156. "--android-jar-pattern somedir/%/system-server/android.jar",
  157. "--android-jar-pattern someotherdir/%/system-server/android.jar",
  158. "--android-jar-pattern somedir/%/module-lib/android.jar",
  159. "--android-jar-pattern someotherdir/%/module-lib/android.jar",
  160. "--android-jar-pattern somedir/%/system/android.jar",
  161. "--android-jar-pattern someotherdir/%/system/android.jar",
  162. "--android-jar-pattern somedir/%/public/android.jar",
  163. "--android-jar-pattern someotherdir/%/public/android.jar",
  164. }, patterns)
  165. }
  166. func TestDroidstubsSandbox(t *testing.T) {
  167. ctx, _ := testJavaWithFS(t, `
  168. genrule {
  169. name: "foo",
  170. out: ["foo.txt"],
  171. cmd: "touch $(out)",
  172. }
  173. droidstubs {
  174. name: "bar-stubs",
  175. srcs: ["bar-doc/a.java"],
  176. args: "--reference $(location :foo)",
  177. arg_files: [":foo"],
  178. }
  179. `,
  180. map[string][]byte{
  181. "bar-doc/a.java": nil,
  182. })
  183. m := ctx.ModuleForTests("bar-stubs", "android_common")
  184. metalava := m.Rule("metalava")
  185. if g, w := metalava.Inputs.Strings(), []string{"bar-doc/a.java"}; !reflect.DeepEqual(w, g) {
  186. t.Errorf("Expected inputs %q, got %q", w, g)
  187. }
  188. manifest := android.RuleBuilderSboxProtoForTests(t, m.Output("metalava.sbox.textproto"))
  189. if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
  190. t.Errorf("Expected command to contain %q, got %q", w, g)
  191. }
  192. }
  193. func TestDroidstubsWithSystemModules(t *testing.T) {
  194. ctx, _ := testJava(t, `
  195. droidstubs {
  196. name: "stubs-source-system-modules",
  197. srcs: [
  198. "bar-doc/a.java",
  199. ],
  200. sdk_version: "none",
  201. system_modules: "source-system-modules",
  202. }
  203. java_library {
  204. name: "source-jar",
  205. srcs: [
  206. "a.java",
  207. ],
  208. }
  209. java_system_modules {
  210. name: "source-system-modules",
  211. libs: ["source-jar"],
  212. }
  213. droidstubs {
  214. name: "stubs-prebuilt-system-modules",
  215. srcs: [
  216. "bar-doc/a.java",
  217. ],
  218. sdk_version: "none",
  219. system_modules: "prebuilt-system-modules",
  220. }
  221. java_import {
  222. name: "prebuilt-jar",
  223. jars: ["a.jar"],
  224. }
  225. java_system_modules_import {
  226. name: "prebuilt-system-modules",
  227. libs: ["prebuilt-jar"],
  228. }
  229. `)
  230. checkSystemModulesUseByDroidstubs(t, ctx, "stubs-source-system-modules", "source-jar.jar")
  231. checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar")
  232. }
  233. func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) {
  234. metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava")
  235. var systemJars []string
  236. for _, i := range metalavaRule.Implicits {
  237. systemJars = append(systemJars, i.Base())
  238. }
  239. if len(systemJars) < 1 || systemJars[0] != systemJar {
  240. t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars)
  241. }
  242. }
  243. func TestDroidstubsWithSdkExtensions(t *testing.T) {
  244. ctx, _ := testJavaWithFS(t, `
  245. droiddoc_exported_dir {
  246. name: "sdk-dir",
  247. path: "sdk",
  248. }
  249. droidstubs {
  250. name: "baz-stubs",
  251. api_levels_annotations_dirs: ["sdk-dir"],
  252. api_levels_annotations_enabled: true,
  253. extensions_info_file: ":info-file",
  254. }
  255. filegroup {
  256. name: "info-file",
  257. srcs: ["sdk/extensions/info.txt"],
  258. }
  259. `,
  260. map[string][]byte{
  261. "sdk/extensions/1/public/some-mainline-module-stubs.jar": nil,
  262. "sdk/extensions/info.txt": nil,
  263. })
  264. m := ctx.ModuleForTests("baz-stubs", "android_common")
  265. manifest := m.Output("metalava.sbox.textproto")
  266. cmdline := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
  267. android.AssertStringDoesContain(t, "sdk-extensions-root present", cmdline, "--sdk-extensions-root sdk/extensions")
  268. android.AssertStringDoesContain(t, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt")
  269. }
  270. func TestApiSurfaceFromDroidStubsName(t *testing.T) {
  271. testCases := []struct {
  272. desc string
  273. name string
  274. expectedApiSurface string
  275. }{
  276. {
  277. desc: "Default is publicapi",
  278. name: "mydroidstubs",
  279. expectedApiSurface: "publicapi",
  280. },
  281. {
  282. desc: "name contains system substring",
  283. name: "mydroidstubs.system.suffix",
  284. expectedApiSurface: "systemapi",
  285. },
  286. {
  287. desc: "name contains system_server substring",
  288. name: "mydroidstubs.system_server.suffix",
  289. expectedApiSurface: "system-serverapi",
  290. },
  291. {
  292. desc: "name contains module_lib substring",
  293. name: "mydroidstubs.module_lib.suffix",
  294. expectedApiSurface: "module-libapi",
  295. },
  296. {
  297. desc: "name contains test substring",
  298. name: "mydroidstubs.test.suffix",
  299. expectedApiSurface: "testapi",
  300. },
  301. {
  302. desc: "name contains intra.core substring",
  303. name: "mydroidstubs.intra.core.suffix",
  304. expectedApiSurface: "intracoreapi",
  305. },
  306. }
  307. for _, tc := range testCases {
  308. android.AssertStringEquals(t, tc.desc, tc.expectedApiSurface, bazelApiSurfaceName(tc.name))
  309. }
  310. }
  311. func TestDroidStubsApiContributionGeneration(t *testing.T) {
  312. ctx, _ := testJavaWithFS(t, `
  313. droidstubs {
  314. name: "foo",
  315. srcs: ["A/a.java"],
  316. api_surface: "public",
  317. check_api: {
  318. current: {
  319. api_file: "A/current.txt",
  320. removed_api_file: "A/removed.txt",
  321. }
  322. }
  323. }
  324. `,
  325. map[string][]byte{
  326. "A/a.java": nil,
  327. "A/current.txt": nil,
  328. "A/removed.txt": nil,
  329. },
  330. )
  331. ctx.ModuleForTests("foo.api.contribution", "")
  332. }
  333. func TestGeneratedApiContributionVisibilityTest(t *testing.T) {
  334. library_bp := `
  335. java_api_library {
  336. name: "bar",
  337. api_surface: "public",
  338. api_contributions: ["foo.api.contribution"],
  339. }
  340. `
  341. ctx, _ := testJavaWithFS(t, `
  342. droidstubs {
  343. name: "foo",
  344. srcs: ["A/a.java"],
  345. api_surface: "public",
  346. check_api: {
  347. current: {
  348. api_file: "A/current.txt",
  349. removed_api_file: "A/removed.txt",
  350. }
  351. },
  352. visibility: ["//a"],
  353. }
  354. `,
  355. map[string][]byte{
  356. "a/a.java": nil,
  357. "a/current.txt": nil,
  358. "a/removed.txt": nil,
  359. "b/Android.bp": []byte(library_bp),
  360. },
  361. )
  362. ctx.ModuleForTests("bar", "android_common")
  363. }