classpath_element_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Copyright (C) 2021 The Android Open Source Project
  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 apex
  15. import (
  16. "reflect"
  17. "testing"
  18. "android/soong/android"
  19. "android/soong/java"
  20. "github.com/google/blueprint"
  21. )
  22. // Contains tests for java.CreateClasspathElements logic from java/classpath_element.go that
  23. // requires apexes.
  24. // testClasspathElementContext is a ClasspathElementContext suitable for use in tests.
  25. type testClasspathElementContext struct {
  26. testContext *android.TestContext
  27. module android.Module
  28. errs []error
  29. }
  30. func (t *testClasspathElementContext) OtherModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool {
  31. return t.testContext.ModuleHasProvider(module, provider)
  32. }
  33. func (t *testClasspathElementContext) OtherModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{} {
  34. return t.testContext.ModuleProvider(module, provider)
  35. }
  36. func (t *testClasspathElementContext) ModuleErrorf(fmt string, args ...interface{}) {
  37. t.errs = append(t.errs, t.testContext.ModuleErrorf(t.module, fmt, args...))
  38. }
  39. var _ java.ClasspathElementContext = (*testClasspathElementContext)(nil)
  40. func TestCreateClasspathElements(t *testing.T) {
  41. preparer := android.GroupFixturePreparers(
  42. prepareForTestWithPlatformBootclasspath,
  43. prepareForTestWithArtApex,
  44. prepareForTestWithMyapex,
  45. // For otherapex.
  46. android.FixtureMergeMockFs(android.MockFS{
  47. "system/sepolicy/apex/otherapex-file_contexts": nil,
  48. }),
  49. java.PrepareForTestWithJavaSdkLibraryFiles,
  50. java.FixtureWithLastReleaseApis("foo", "othersdklibrary"),
  51. java.FixtureConfigureApexBootJars("myapex:bar"),
  52. android.FixtureWithRootAndroidBp(`
  53. apex {
  54. name: "com.android.art",
  55. key: "com.android.art.key",
  56. bootclasspath_fragments: [
  57. "art-bootclasspath-fragment",
  58. ],
  59. java_libs: [
  60. "othersdklibrary",
  61. ],
  62. updatable: false,
  63. }
  64. apex_key {
  65. name: "com.android.art.key",
  66. public_key: "com.android.art.avbpubkey",
  67. private_key: "com.android.art.pem",
  68. }
  69. bootclasspath_fragment {
  70. name: "art-bootclasspath-fragment",
  71. image_name: "art",
  72. apex_available: [
  73. "com.android.art",
  74. ],
  75. contents: [
  76. "baz",
  77. "quuz",
  78. ],
  79. hidden_api: {
  80. split_packages: ["*"],
  81. },
  82. }
  83. java_library {
  84. name: "baz",
  85. apex_available: [
  86. "com.android.art",
  87. ],
  88. srcs: ["b.java"],
  89. installable: true,
  90. }
  91. java_library {
  92. name: "quuz",
  93. apex_available: [
  94. "com.android.art",
  95. ],
  96. srcs: ["b.java"],
  97. installable: true,
  98. }
  99. apex {
  100. name: "myapex",
  101. key: "myapex.key",
  102. bootclasspath_fragments: [
  103. "mybootclasspath-fragment",
  104. ],
  105. java_libs: [
  106. "othersdklibrary",
  107. ],
  108. updatable: false,
  109. }
  110. apex_key {
  111. name: "myapex.key",
  112. public_key: "testkey.avbpubkey",
  113. private_key: "testkey.pem",
  114. }
  115. bootclasspath_fragment {
  116. name: "mybootclasspath-fragment",
  117. apex_available: [
  118. "myapex",
  119. ],
  120. contents: [
  121. "bar",
  122. ],
  123. hidden_api: {
  124. split_packages: ["*"],
  125. },
  126. }
  127. java_library {
  128. name: "bar",
  129. srcs: ["b.java"],
  130. installable: true,
  131. apex_available: ["myapex"],
  132. permitted_packages: ["bar"],
  133. }
  134. java_sdk_library {
  135. name: "foo",
  136. srcs: ["b.java"],
  137. }
  138. java_sdk_library {
  139. name: "othersdklibrary",
  140. srcs: ["b.java"],
  141. shared_library: false,
  142. apex_available: [
  143. "com.android.art",
  144. "myapex",
  145. ],
  146. }
  147. apex {
  148. name: "otherapex",
  149. key: "otherapex.key",
  150. java_libs: [
  151. "otherapexlibrary",
  152. ],
  153. updatable: false,
  154. }
  155. apex_key {
  156. name: "otherapex.key",
  157. public_key: "testkey.avbpubkey",
  158. private_key: "testkey.pem",
  159. }
  160. java_library {
  161. name: "otherapexlibrary",
  162. srcs: ["b.java"],
  163. installable: true,
  164. apex_available: ["otherapex"],
  165. permitted_packages: ["otherapexlibrary"],
  166. }
  167. platform_bootclasspath {
  168. name: "myplatform-bootclasspath",
  169. fragments: [
  170. {
  171. apex: "com.android.art",
  172. module: "art-bootclasspath-fragment",
  173. },
  174. {
  175. apex: "myapex",
  176. module: "mybootclasspath-fragment",
  177. },
  178. ],
  179. }
  180. `),
  181. )
  182. result := preparer.RunTest(t)
  183. artFragment := result.Module("art-bootclasspath-fragment", "android_common_apex10000")
  184. artBaz := result.Module("baz", "android_common_apex10000")
  185. artQuuz := result.Module("quuz", "android_common_apex10000")
  186. myFragment := result.Module("mybootclasspath-fragment", "android_common_apex10000")
  187. myBar := result.Module("bar", "android_common_apex10000")
  188. other := result.Module("othersdklibrary", "android_common_apex10000")
  189. otherApexLibrary := result.Module("otherapexlibrary", "android_common_apex10000")
  190. platformFoo := result.Module("quuz", "android_common")
  191. bootclasspath := result.Module("myplatform-bootclasspath", "android_common")
  192. // Use a custom assertion method instead of AssertDeepEquals as the latter formats the output
  193. // using %#v which results in meaningless output as ClasspathElements are pointers.
  194. assertElementsEquals := func(t *testing.T, message string, expected, actual java.ClasspathElements) {
  195. if !reflect.DeepEqual(expected, actual) {
  196. t.Errorf("%s: expected:\n %s\n got:\n %s", message, expected, actual)
  197. }
  198. }
  199. expectFragmentElement := func(module android.Module, contents ...android.Module) java.ClasspathElement {
  200. return &java.ClasspathFragmentElement{module, contents}
  201. }
  202. expectLibraryElement := func(module android.Module) java.ClasspathElement {
  203. return &java.ClasspathLibraryElement{module}
  204. }
  205. newCtx := func() *testClasspathElementContext {
  206. return &testClasspathElementContext{testContext: result.TestContext, module: bootclasspath}
  207. }
  208. // Verify that CreateClasspathElements works when given valid input.
  209. t.Run("art:baz, art:quuz, my:bar, foo", func(t *testing.T) {
  210. ctx := newCtx()
  211. elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, artQuuz, myBar, platformFoo}, []android.Module{artFragment, myFragment})
  212. expectedElements := java.ClasspathElements{
  213. expectFragmentElement(artFragment, artBaz, artQuuz),
  214. expectFragmentElement(myFragment, myBar),
  215. expectLibraryElement(platformFoo),
  216. }
  217. assertElementsEquals(t, "elements", expectedElements, elements)
  218. })
  219. // Verify that CreateClasspathElements detects when an apex has multiple fragments.
  220. t.Run("multiple fragments for same apex", func(t *testing.T) {
  221. ctx := newCtx()
  222. elements := java.CreateClasspathElements(ctx, []android.Module{}, []android.Module{artFragment, artFragment})
  223. android.FailIfNoMatchingErrors(t, "apex com.android.art has multiple fragments, art-bootclasspath-fragment{.*} and art-bootclasspath-fragment{.*}", ctx.errs)
  224. expectedElements := java.ClasspathElements{}
  225. assertElementsEquals(t, "elements", expectedElements, elements)
  226. })
  227. // Verify that CreateClasspathElements detects when a library is in multiple fragments.
  228. t.Run("library from multiple fragments", func(t *testing.T) {
  229. ctx := newCtx()
  230. elements := java.CreateClasspathElements(ctx, []android.Module{other}, []android.Module{artFragment, myFragment})
  231. android.FailIfNoMatchingErrors(t, "library othersdklibrary{.*} is in two separate fragments, art-bootclasspath-fragment{.*} and mybootclasspath-fragment{.*}", ctx.errs)
  232. expectedElements := java.ClasspathElements{}
  233. assertElementsEquals(t, "elements", expectedElements, elements)
  234. })
  235. // Verify that CreateClasspathElements detects when a fragment's contents are not contiguous and
  236. // are separated by a library from another fragment.
  237. t.Run("discontiguous separated by fragment", func(t *testing.T) {
  238. ctx := newCtx()
  239. elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, myBar, artQuuz, platformFoo}, []android.Module{artFragment, myFragment})
  240. expectedElements := java.ClasspathElements{
  241. expectFragmentElement(artFragment, artBaz, artQuuz),
  242. expectFragmentElement(myFragment, myBar),
  243. expectLibraryElement(platformFoo),
  244. }
  245. assertElementsEquals(t, "elements", expectedElements, elements)
  246. android.FailIfNoMatchingErrors(t, "libraries from the same fragment must be contiguous, however baz{.*} and quuz{os:android,arch:common,apex:apex10000} from fragment art-bootclasspath-fragment{.*} are separated by libraries from fragment mybootclasspath-fragment{.*} like bar{.*}", ctx.errs)
  247. })
  248. // Verify that CreateClasspathElements detects when a fragment's contents are not contiguous and
  249. // are separated by a standalone library.
  250. t.Run("discontiguous separated by library", func(t *testing.T) {
  251. ctx := newCtx()
  252. elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, platformFoo, artQuuz, myBar}, []android.Module{artFragment, myFragment})
  253. expectedElements := java.ClasspathElements{
  254. expectFragmentElement(artFragment, artBaz, artQuuz),
  255. expectLibraryElement(platformFoo),
  256. expectFragmentElement(myFragment, myBar),
  257. }
  258. assertElementsEquals(t, "elements", expectedElements, elements)
  259. android.FailIfNoMatchingErrors(t, "libraries from the same fragment must be contiguous, however baz{.*} and quuz{os:android,arch:common,apex:apex10000} from fragment art-bootclasspath-fragment{.*} are separated by library quuz{.*}", ctx.errs)
  260. })
  261. // Verify that CreateClasspathElements detects when there a library on the classpath that
  262. // indicates it is from an apex the supplied fragments list does not contain a fragment for that
  263. // apex.
  264. t.Run("no fragment for apex", func(t *testing.T) {
  265. ctx := newCtx()
  266. elements := java.CreateClasspathElements(ctx, []android.Module{artBaz, otherApexLibrary}, []android.Module{artFragment})
  267. expectedElements := java.ClasspathElements{
  268. expectFragmentElement(artFragment, artBaz),
  269. }
  270. assertElementsEquals(t, "elements", expectedElements, elements)
  271. android.FailIfNoMatchingErrors(t, `library otherapexlibrary{.*} is from apexes \[otherapex\] which have no corresponding fragment in \[art-bootclasspath-fragment{.*}\]`, ctx.errs)
  272. })
  273. }