1// Copyright 2018 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 java 16 17import ( 18 "reflect" 19 "testing" 20 21 "android/soong/android" 22) 23 24func TestJarGenruleCombinerSingle(t *testing.T) { 25 t.Parallel() 26 t.Helper() 27 ctx := prepareForJavaTest.RunTestWithBp(t, ` 28 java_library { 29 name: "foo", 30 srcs: ["a.java"], 31 } 32 33 java_genrule { 34 name: "gen", 35 tool_files: ["b.java"], 36 cmd: "$(location b.java) $(in) $(out)", 37 out: ["gen.jar"], 38 srcs: [":foo"], 39 } 40 41 java_genrule_combiner { 42 name: "jarcomb", 43 static_libs: ["gen"], 44 headers: ["foo"], 45 } 46 47 java_library { 48 name: "bar", 49 static_libs: ["jarcomb"], 50 srcs: ["c.java"], 51 } 52 53 java_library { 54 name: "baz", 55 libs: ["jarcomb"], 56 srcs: ["c.java"], 57 } 58 `).TestContext 59 60 fooMod := ctx.ModuleForTests(t, "foo", "android_common") 61 fooCombined := fooMod.Output("turbine-combined/foo.jar") 62 fooOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), fooMod.Module(), android.OutputFilesProvider) 63 fooHeaderJars := fooOutputFiles.TaggedOutputFiles[".hjar"] 64 65 genMod := ctx.ModuleForTests(t, "gen", "android_common") 66 gen := genMod.Output("gen.jar") 67 68 jarcombMod := ctx.ModuleForTests(t, "jarcomb", "android_common") 69 jarcombInfo, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), JavaInfoProvider) 70 jarcombOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), android.OutputFilesProvider) 71 72 // Confirm that jarcomb simply forwards the jarcomb implementation and the foo headers. 73 if len(jarcombOutputFiles.DefaultOutputFiles) != 1 || 74 android.PathRelativeToTop(jarcombOutputFiles.DefaultOutputFiles[0]) != android.PathRelativeToTop(gen.Output) { 75 t.Errorf("jarcomb Implementation %v is not [%q]", 76 android.PathsRelativeToTop(jarcombOutputFiles.DefaultOutputFiles), android.PathRelativeToTop(gen.Output)) 77 } 78 jarcombHeaderJars := jarcombOutputFiles.TaggedOutputFiles[".hjar"] 79 if !reflect.DeepEqual(jarcombHeaderJars, fooHeaderJars) { 80 t.Errorf("jarcomb Header jar %v is not %q", 81 jarcombHeaderJars, fooHeaderJars) 82 } 83 84 // Confirm that JavaInfoProvider agrees. 85 if len(jarcombInfo.ImplementationJars) != 1 || 86 android.PathRelativeToTop(jarcombInfo.ImplementationJars[0]) != android.PathRelativeToTop(gen.Output) { 87 t.Errorf("jarcomb ImplementationJars %v is not [%q]", 88 android.PathsRelativeToTop(jarcombInfo.ImplementationJars), android.PathRelativeToTop(gen.Output)) 89 } 90 if len(jarcombInfo.HeaderJars) != 1 || 91 android.PathRelativeToTop(jarcombInfo.HeaderJars[0]) != android.PathRelativeToTop(fooCombined.Output) { 92 t.Errorf("jarcomb HeaderJars %v is not [%q]", 93 android.PathsRelativeToTop(jarcombInfo.HeaderJars), android.PathRelativeToTop(fooCombined.Output)) 94 } 95 96 barMod := ctx.ModuleForTests(t, "bar", "android_common") 97 bar := barMod.Output("javac/bar.jar") 98 barCombined := barMod.Output("combined/bar.jar") 99 100 // Confirm that bar uses the Implementation from gen and headerJars from foo. 101 if len(barCombined.Inputs) != 2 || 102 barCombined.Inputs[0].String() != bar.Output.String() || 103 barCombined.Inputs[1].String() != gen.Output.String() { 104 t.Errorf("bar combined jar inputs %v is not [%q, %q]", 105 barCombined.Inputs.Strings(), bar.Output.String(), gen.Output.String()) 106 } 107 108 bazMod := ctx.ModuleForTests(t, "baz", "android_common") 109 baz := bazMod.Output("javac/baz.jar") 110 111 string_in_list := func(s string, l []string) bool { 112 for _, v := range l { 113 if s == v { 114 return true 115 } 116 } 117 return false 118 } 119 120 // Confirm that baz uses the headerJars from foo. 121 bazImplicitsRel := android.PathsRelativeToTop(baz.Implicits) 122 for _, v := range android.PathsRelativeToTop(fooHeaderJars) { 123 if !string_in_list(v, bazImplicitsRel) { 124 t.Errorf("baz Implicits %v does not contain %q", bazImplicitsRel, v) 125 } 126 } 127} 128 129func TestJarGenruleCombinerMulti(t *testing.T) { 130 t.Parallel() 131 t.Helper() 132 ctx := prepareForJavaTest.RunTestWithBp(t, ` 133 java_library { 134 name: "foo1", 135 srcs: ["foo1_a.java"], 136 } 137 138 java_library { 139 name: "foo2", 140 srcs: ["foo2_a.java"], 141 } 142 143 java_genrule { 144 name: "gen1", 145 tool_files: ["b.java"], 146 cmd: "$(location b.java) $(in) $(out)", 147 out: ["gen1.jar"], 148 srcs: [":foo1"], 149 } 150 151 java_genrule { 152 name: "gen2", 153 tool_files: ["b.java"], 154 cmd: "$(location b.java) $(in) $(out)", 155 out: ["gen2.jar"], 156 srcs: [":foo2"], 157 } 158 159 // Combine multiple java_genrule modules. 160 java_genrule_combiner { 161 name: "jarcomb", 162 static_libs: ["gen1", "gen2"], 163 headers: ["foo1", "foo2"], 164 } 165 166 java_library { 167 name: "bar", 168 static_libs: ["jarcomb"], 169 srcs: ["c.java"], 170 } 171 172 java_library { 173 name: "baz", 174 libs: ["jarcomb"], 175 srcs: ["c.java"], 176 } 177 `).TestContext 178 179 gen1Mod := ctx.ModuleForTests(t, "gen1", "android_common") 180 gen1 := gen1Mod.Output("gen1.jar") 181 gen2Mod := ctx.ModuleForTests(t, "gen2", "android_common") 182 gen2 := gen2Mod.Output("gen2.jar") 183 184 jarcombMod := ctx.ModuleForTests(t, "jarcomb", "android_common") 185 jarcomb := jarcombMod.Output("combined/jarcomb.jar") 186 jarcombTurbine := jarcombMod.Output("turbine-combined/jarcomb.jar") 187 _ = jarcombTurbine 188 jarcombInfo, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), JavaInfoProvider) 189 _ = jarcombInfo 190 jarcombOutputFiles, _ := android.OtherModuleProvider(ctx.OtherModuleProviderAdaptor(), jarcombMod.Module(), android.OutputFilesProvider) 191 jarcombHeaderJars := jarcombOutputFiles.TaggedOutputFiles[".hjar"] 192 193 if len(jarcomb.Inputs) != 2 || 194 jarcomb.Inputs[0].String() != gen1.Output.String() || 195 jarcomb.Inputs[1].String() != gen2.Output.String() { 196 t.Errorf("jarcomb inputs %v are not [%q, %q]", 197 jarcomb.Inputs.Strings(), gen1.Output.String(), gen2.Output.String()) 198 } 199 200 if len(jarcombHeaderJars) != 1 || 201 android.PathRelativeToTop(jarcombHeaderJars[0]) != android.PathRelativeToTop(jarcombTurbine.Output) { 202 t.Errorf("jarcomb Header jars %v is not [%q]", 203 android.PathsRelativeToTop(jarcombHeaderJars), android.PathRelativeToTop(jarcombTurbine.Output)) 204 } 205 206 barMod := ctx.ModuleForTests(t, "bar", "android_common") 207 bar := barMod.Output("javac/bar.jar") 208 barCombined := barMod.Output("combined/bar.jar") 209 210 // Confirm that bar uses the Implementation and Headers from jarcomb. 211 if len(barCombined.Inputs) != 2 || 212 barCombined.Inputs[0].String() != bar.Output.String() || 213 barCombined.Inputs[1].String() != jarcomb.Output.String() { 214 t.Errorf("bar combined jar inputs %v is not [%q, %q]", 215 barCombined.Inputs.Strings(), bar.Output.String(), jarcomb.Output.String()) 216 } 217 218 bazMod := ctx.ModuleForTests(t, "baz", "android_common") 219 baz := bazMod.Output("javac/baz.jar") 220 221 string_in_list := func(s string, l []string) bool { 222 for _, v := range l { 223 if s == v { 224 return true 225 } 226 } 227 return false 228 } 229 230 // Confirm that baz uses the headerJars from foo. 231 bazImplicitsRel := android.PathsRelativeToTop(baz.Implicits) 232 for _, v := range android.PathsRelativeToTop(jarcombHeaderJars) { 233 if !string_in_list(v, bazImplicitsRel) { 234 t.Errorf("baz Implicits %v does not contain %q", bazImplicitsRel, v) 235 } 236 } 237} 238