1// Copyright 2021 Google LLC 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 main 16 17import ( 18 "bufio" 19 "bytes" 20 "fmt" 21 "os" 22 "strings" 23 "testing" 24 25 "android/soong/tools/compliance" 26) 27 28func TestMain(m *testing.M) { 29 // Change into the parent directory before running the tests 30 // so they can find the testdata directory. 31 if err := os.Chdir(".."); err != nil { 32 fmt.Printf("failed to change to testdata directory: %s\n", err) 33 os.Exit(1) 34 } 35 os.Exit(m.Run()) 36} 37 38func Test(t *testing.T) { 39 tests := []struct { 40 condition string 41 name string 42 outDir string 43 roots []string 44 stripPrefix string 45 expectedOut []string 46 }{ 47 { 48 condition: "firstparty", 49 name: "apex", 50 roots: []string{"highest.apex.meta_lic"}, 51 stripPrefix: "out/target/product/fictional", 52 expectedOut: []string{ 53 "/system/apex/highest.apex", 54 "/system/apex/highest.apex/bin/bin1", 55 "/system/apex/highest.apex/bin/bin2", 56 "/system/apex/highest.apex/lib/liba.so", 57 "/system/apex/highest.apex/lib/libb.so", 58 }, 59 }, 60 { 61 condition: "firstparty", 62 name: "container", 63 roots: []string{"container.zip.meta_lic"}, 64 stripPrefix: "out/target/product/fictional/data/", 65 expectedOut: []string{ 66 "container.zip", 67 "container.zip/bin1", 68 "container.zip/bin2", 69 "container.zip/liba.so", 70 "container.zip/libb.so", 71 }, 72 }, 73 { 74 condition: "firstparty", 75 name: "application", 76 roots: []string{"application.meta_lic"}, 77 stripPrefix: "out/target/product/fictional/bin/", 78 expectedOut: []string{"application"}, 79 }, 80 { 81 condition: "firstparty", 82 name: "binary", 83 roots: []string{"bin/bin1.meta_lic"}, 84 stripPrefix: "out/target/product/fictional/system/", 85 expectedOut: []string{"bin/bin1"}, 86 }, 87 { 88 condition: "firstparty", 89 name: "library", 90 roots: []string{"lib/libd.so.meta_lic"}, 91 stripPrefix: "out/target/product/fictional/system/", 92 expectedOut: []string{"lib/libd.so"}, 93 }, 94 { 95 condition: "notice", 96 name: "apex", 97 roots: []string{"highest.apex.meta_lic"}, 98 expectedOut: []string{ 99 "out/target/product/fictional/system/apex/highest.apex", 100 "out/target/product/fictional/system/apex/highest.apex/bin/bin1", 101 "out/target/product/fictional/system/apex/highest.apex/bin/bin2", 102 "out/target/product/fictional/system/apex/highest.apex/lib/liba.so", 103 "out/target/product/fictional/system/apex/highest.apex/lib/libb.so", 104 }, 105 }, 106 { 107 condition: "notice", 108 name: "container", 109 roots: []string{"container.zip.meta_lic"}, 110 expectedOut: []string{ 111 "out/target/product/fictional/data/container.zip", 112 "out/target/product/fictional/data/container.zip/bin1", 113 "out/target/product/fictional/data/container.zip/bin2", 114 "out/target/product/fictional/data/container.zip/liba.so", 115 "out/target/product/fictional/data/container.zip/libb.so", 116 }, 117 }, 118 { 119 condition: "notice", 120 name: "application", 121 roots: []string{"application.meta_lic"}, 122 expectedOut: []string{"out/target/product/fictional/bin/application"}, 123 }, 124 { 125 condition: "notice", 126 name: "binary", 127 roots: []string{"bin/bin1.meta_lic"}, 128 expectedOut: []string{"out/target/product/fictional/system/bin/bin1"}, 129 }, 130 { 131 condition: "notice", 132 name: "library", 133 roots: []string{"lib/libd.so.meta_lic"}, 134 expectedOut: []string{"out/target/product/fictional/system/lib/libd.so"}, 135 }, 136 { 137 condition: "reciprocal", 138 name: "apex", 139 roots: []string{"highest.apex.meta_lic"}, 140 stripPrefix: "out/target/product/fictional/system/apex/", 141 expectedOut: []string{ 142 "highest.apex", 143 "highest.apex/bin/bin1", 144 "highest.apex/bin/bin2", 145 "highest.apex/lib/liba.so", 146 "highest.apex/lib/libb.so", 147 }, 148 }, 149 { 150 condition: "reciprocal", 151 name: "container", 152 roots: []string{"container.zip.meta_lic"}, 153 stripPrefix: "out/target/product/fictional/data/", 154 expectedOut: []string{ 155 "container.zip", 156 "container.zip/bin1", 157 "container.zip/bin2", 158 "container.zip/liba.so", 159 "container.zip/libb.so", 160 }, 161 }, 162 { 163 condition: "reciprocal", 164 name: "application", 165 roots: []string{"application.meta_lic"}, 166 stripPrefix: "out/target/product/fictional/bin/", 167 expectedOut: []string{"application"}, 168 }, 169 { 170 condition: "reciprocal", 171 name: "binary", 172 roots: []string{"bin/bin1.meta_lic"}, 173 stripPrefix: "out/target/product/fictional/system/", 174 expectedOut: []string{"bin/bin1"}, 175 }, 176 { 177 condition: "reciprocal", 178 name: "library", 179 roots: []string{"lib/libd.so.meta_lic"}, 180 stripPrefix: "out/target/product/fictional/system/", 181 expectedOut: []string{"lib/libd.so"}, 182 }, 183 { 184 condition: "restricted", 185 name: "apex", 186 roots: []string{"highest.apex.meta_lic"}, 187 stripPrefix: "out/target/product/fictional/system/apex/", 188 expectedOut: []string{ 189 "highest.apex", 190 "highest.apex/bin/bin1", 191 "highest.apex/bin/bin2", 192 "highest.apex/lib/liba.so", 193 "highest.apex/lib/libb.so", 194 }, 195 }, 196 { 197 condition: "restricted", 198 name: "container", 199 roots: []string{"container.zip.meta_lic"}, 200 stripPrefix: "out/target/product/fictional/data/", 201 expectedOut: []string{ 202 "container.zip", 203 "container.zip/bin1", 204 "container.zip/bin2", 205 "container.zip/liba.so", 206 "container.zip/libb.so", 207 }, 208 }, 209 { 210 condition: "restricted", 211 name: "application", 212 roots: []string{"application.meta_lic"}, 213 stripPrefix: "out/target/product/fictional/bin/", 214 expectedOut: []string{"application"}, 215 }, 216 { 217 condition: "restricted", 218 name: "binary", 219 roots: []string{"bin/bin1.meta_lic"}, 220 stripPrefix: "out/target/product/fictional/system/", 221 expectedOut: []string{"bin/bin1"}, 222 }, 223 { 224 condition: "restricted", 225 name: "library", 226 roots: []string{"lib/libd.so.meta_lic"}, 227 stripPrefix: "out/target/product/fictional/system/", 228 expectedOut: []string{"lib/libd.so"}, 229 }, 230 { 231 condition: "proprietary", 232 name: "apex", 233 roots: []string{"highest.apex.meta_lic"}, 234 stripPrefix: "out/target/product/fictional/system/apex/", 235 expectedOut: []string{ 236 "highest.apex", 237 "highest.apex/bin/bin1", 238 "highest.apex/bin/bin2", 239 "highest.apex/lib/liba.so", 240 "highest.apex/lib/libb.so", 241 }, 242 }, 243 { 244 condition: "proprietary", 245 name: "container", 246 roots: []string{"container.zip.meta_lic"}, 247 stripPrefix: "out/target/product/fictional/data/", 248 expectedOut: []string{ 249 "container.zip", 250 "container.zip/bin1", 251 "container.zip/bin2", 252 "container.zip/liba.so", 253 "container.zip/libb.so", 254 }, 255 }, 256 { 257 condition: "proprietary", 258 name: "application", 259 roots: []string{"application.meta_lic"}, 260 stripPrefix: "out/target/product/fictional/bin/", 261 expectedOut: []string{"application"}, 262 }, 263 { 264 condition: "proprietary", 265 name: "binary", 266 roots: []string{"bin/bin1.meta_lic"}, 267 stripPrefix: "out/target/product/fictional/system/", 268 expectedOut: []string{"bin/bin1"}, 269 }, 270 { 271 condition: "proprietary", 272 name: "library", 273 roots: []string{"lib/libd.so.meta_lic"}, 274 stripPrefix: "out/target/product/fictional/system/", 275 expectedOut: []string{"lib/libd.so"}, 276 }, 277 } 278 for _, tt := range tests { 279 t.Run(tt.condition+" "+tt.name, func(t *testing.T) { 280 stdout := &bytes.Buffer{} 281 stderr := &bytes.Buffer{} 282 283 rootFiles := make([]string, 0, len(tt.roots)) 284 for _, r := range tt.roots { 285 rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r) 286 } 287 288 ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), []string{tt.stripPrefix}} 289 290 err := billOfMaterials(&ctx, rootFiles...) 291 if err != nil { 292 t.Fatalf("bom: error = %v, stderr = %v", err, stderr) 293 return 294 } 295 if stderr.Len() > 0 { 296 t.Errorf("bom: gotStderr = %v, want none", stderr) 297 } 298 299 t.Logf("got stdout: %s", stdout.String()) 300 301 t.Logf("want stdout: %s", strings.Join(tt.expectedOut, "\n")) 302 303 out := bufio.NewScanner(stdout) 304 lineno := 0 305 for out.Scan() { 306 line := out.Text() 307 if strings.TrimLeft(line, " ") == "" { 308 continue 309 } 310 if len(tt.expectedOut) <= lineno { 311 t.Errorf("bom: unexpected output at line %d: got %q, want nothing (wanted %d lines)", lineno+1, line, len(tt.expectedOut)) 312 } else if tt.expectedOut[lineno] != line { 313 t.Errorf("bom: unexpected output at line %d: got %q, want %q", lineno+1, line, tt.expectedOut[lineno]) 314 } 315 lineno++ 316 } 317 for ; lineno < len(tt.expectedOut); lineno++ { 318 t.Errorf("bom: missing output line %d: ended early, want %q", lineno+1, tt.expectedOut[lineno]) 319 } 320 }) 321 } 322} 323