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 "bytes" 19 "fmt" 20 "os" 21 "strings" 22 "testing" 23 24 "android/soong/tools/compliance" 25) 26 27func TestMain(m *testing.M) { 28 // Change into the parent directory before running the tests 29 // so they can find the testdata directory. 30 if err := os.Chdir(".."); err != nil { 31 fmt.Printf("failed to change to testdata directory: %s\n", err) 32 os.Exit(1) 33 } 34 os.Exit(m.Run()) 35} 36 37type outcome struct { 38 target string 39 privacyCondition string 40 shareCondition string 41} 42 43func (o *outcome) String() string { 44 return fmt.Sprintf("%s %s and must share from %s", o.target, o.privacyCondition, o.shareCondition) 45} 46 47type outcomeList []*outcome 48 49func (ol outcomeList) String() string { 50 result := "" 51 for _, o := range ol { 52 result = result + o.String() + "\n" 53 } 54 return result 55} 56 57func Test(t *testing.T) { 58 tests := []struct { 59 condition string 60 name string 61 outDir string 62 roots []string 63 expectedStdout string 64 expectedOutcomes outcomeList 65 }{ 66 { 67 condition: "firstparty", 68 name: "apex", 69 roots: []string{"highest.apex.meta_lic"}, 70 expectedStdout: "PASS", 71 }, 72 { 73 condition: "firstparty", 74 name: "container", 75 roots: []string{"container.zip.meta_lic"}, 76 expectedStdout: "PASS", 77 }, 78 { 79 condition: "firstparty", 80 name: "application", 81 roots: []string{"application.meta_lic"}, 82 expectedStdout: "PASS", 83 }, 84 { 85 condition: "firstparty", 86 name: "binary", 87 roots: []string{"bin/bin2.meta_lic"}, 88 expectedStdout: "PASS", 89 }, 90 { 91 condition: "firstparty", 92 name: "library", 93 roots: []string{"lib/libd.so.meta_lic"}, 94 expectedStdout: "PASS", 95 }, 96 { 97 condition: "notice", 98 name: "apex", 99 roots: []string{"highest.apex.meta_lic"}, 100 expectedStdout: "PASS", 101 }, 102 { 103 condition: "notice", 104 name: "container", 105 roots: []string{"container.zip.meta_lic"}, 106 expectedStdout: "PASS", 107 }, 108 { 109 condition: "notice", 110 name: "application", 111 roots: []string{"application.meta_lic"}, 112 expectedStdout: "PASS", 113 }, 114 { 115 condition: "notice", 116 name: "binary", 117 roots: []string{"bin/bin2.meta_lic"}, 118 expectedStdout: "PASS", 119 }, 120 { 121 condition: "notice", 122 name: "library", 123 roots: []string{"lib/libd.so.meta_lic"}, 124 expectedStdout: "PASS", 125 }, 126 { 127 condition: "reciprocal", 128 name: "apex", 129 roots: []string{"highest.apex.meta_lic"}, 130 expectedStdout: "PASS", 131 }, 132 { 133 condition: "reciprocal", 134 name: "container", 135 roots: []string{"container.zip.meta_lic"}, 136 expectedStdout: "PASS", 137 }, 138 { 139 condition: "reciprocal", 140 name: "application", 141 roots: []string{"application.meta_lic"}, 142 expectedStdout: "PASS", 143 }, 144 { 145 condition: "reciprocal", 146 name: "binary", 147 roots: []string{"bin/bin2.meta_lic"}, 148 expectedStdout: "PASS", 149 }, 150 { 151 condition: "reciprocal", 152 name: "library", 153 roots: []string{"lib/libd.so.meta_lic"}, 154 expectedStdout: "PASS", 155 }, 156 { 157 condition: "restricted", 158 name: "apex", 159 roots: []string{"highest.apex.meta_lic"}, 160 expectedStdout: "PASS", 161 }, 162 { 163 condition: "restricted", 164 name: "container", 165 roots: []string{"container.zip.meta_lic"}, 166 expectedStdout: "PASS", 167 }, 168 { 169 condition: "restricted", 170 name: "application", 171 roots: []string{"application.meta_lic"}, 172 expectedStdout: "PASS", 173 }, 174 { 175 condition: "restricted", 176 name: "binary", 177 roots: []string{"bin/bin2.meta_lic"}, 178 expectedStdout: "PASS", 179 }, 180 { 181 condition: "restricted", 182 name: "library", 183 roots: []string{"lib/libd.so.meta_lic"}, 184 expectedStdout: "PASS", 185 }, 186 { 187 condition: "proprietary", 188 name: "apex", 189 roots: []string{"highest.apex.meta_lic"}, 190 expectedStdout: "FAIL", 191 expectedOutcomes: outcomeList{ 192 &outcome{ 193 target: "testdata/proprietary/bin/bin2.meta_lic", 194 privacyCondition: "proprietary", 195 shareCondition: "restricted", 196 }, 197 }, 198 }, 199 { 200 condition: "proprietary", 201 name: "container", 202 roots: []string{"container.zip.meta_lic"}, 203 expectedStdout: "FAIL", 204 expectedOutcomes: outcomeList{ 205 &outcome{ 206 target: "testdata/proprietary/bin/bin2.meta_lic", 207 privacyCondition: "proprietary", 208 shareCondition: "restricted", 209 }, 210 }, 211 }, 212 { 213 condition: "proprietary", 214 name: "application", 215 roots: []string{"application.meta_lic"}, 216 expectedStdout: "FAIL", 217 expectedOutcomes: outcomeList{ 218 &outcome{ 219 target: "testdata/proprietary/lib/liba.so.meta_lic", 220 privacyCondition: "proprietary", 221 shareCondition: "restricted", 222 }, 223 }, 224 }, 225 { 226 condition: "proprietary", 227 name: "binary", 228 roots: []string{"bin/bin2.meta_lic", "lib/libb.so.meta_lic"}, 229 expectedStdout: "FAIL", 230 expectedOutcomes: outcomeList{ 231 &outcome{ 232 target: "testdata/proprietary/bin/bin2.meta_lic", 233 privacyCondition: "proprietary", 234 shareCondition: "restricted", 235 }, 236 }, 237 }, 238 { 239 condition: "proprietary", 240 name: "library", 241 roots: []string{"lib/libd.so.meta_lic"}, 242 expectedStdout: "PASS", 243 }, 244 { 245 condition: "regressconcur", 246 name: "container", 247 roots: []string{"container.zip.meta_lic"}, 248 expectedStdout: "FAIL", 249 expectedOutcomes: outcomeList{ 250 &outcome{ 251 target: "testdata/regressconcur/bin/bin1.meta_lic", 252 privacyCondition: "proprietary", 253 shareCondition: "restricted", 254 }, 255 &outcome{ 256 target: "testdata/regressconcur/bin/bin2.meta_lic", 257 privacyCondition: "proprietary", 258 shareCondition: "restricted", 259 }, 260 &outcome{ 261 target: "testdata/regressconcur/bin/bin3.meta_lic", 262 privacyCondition: "proprietary", 263 shareCondition: "restricted", 264 }, 265 &outcome{ 266 target: "testdata/regressconcur/bin/bin4.meta_lic", 267 privacyCondition: "proprietary", 268 shareCondition: "restricted", 269 }, 270 &outcome{ 271 target: "testdata/regressconcur/bin/bin5.meta_lic", 272 privacyCondition: "proprietary", 273 shareCondition: "restricted", 274 }, 275 &outcome{ 276 target: "testdata/regressconcur/bin/bin6.meta_lic", 277 privacyCondition: "proprietary", 278 shareCondition: "restricted", 279 }, 280 &outcome{ 281 target: "testdata/regressconcur/bin/bin7.meta_lic", 282 privacyCondition: "proprietary", 283 shareCondition: "restricted", 284 }, 285 &outcome{ 286 target: "testdata/regressconcur/bin/bin8.meta_lic", 287 privacyCondition: "proprietary", 288 shareCondition: "restricted", 289 }, 290 &outcome{ 291 target: "testdata/regressconcur/bin/bin9.meta_lic", 292 privacyCondition: "proprietary", 293 shareCondition: "restricted", 294 }, 295 }, 296 }, 297 } 298 for _, tt := range tests { 299 t.Run(tt.condition+" "+tt.name, func(t *testing.T) { 300 stdout := &bytes.Buffer{} 301 stderr := &bytes.Buffer{} 302 303 rootFiles := make([]string, 0, len(tt.roots)) 304 for _, r := range tt.roots { 305 rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r) 306 } 307 err := checkShare(stdout, stderr, compliance.GetFS(tt.outDir), rootFiles...) 308 if err != nil && err != failConflicts { 309 t.Fatalf("checkshare: error = %v, stderr = %v", err, stderr) 310 return 311 } 312 var actualStdout string 313 for _, s := range strings.Split(stdout.String(), "\n") { 314 ts := strings.TrimLeft(s, " \t") 315 if len(ts) < 1 { 316 continue 317 } 318 if len(actualStdout) > 0 { 319 t.Errorf("checkshare: unexpected multiple output lines %q, want %q", actualStdout+"\n"+ts, tt.expectedStdout) 320 } 321 actualStdout = ts 322 } 323 if actualStdout != tt.expectedStdout { 324 t.Errorf("checkshare: unexpected stdout %q, want %q", actualStdout, tt.expectedStdout) 325 } 326 errList := strings.Split(stderr.String(), "\n") 327 actualOutcomes := make(outcomeList, 0, len(errList)) 328 for _, cstring := range errList { 329 ts := strings.TrimLeft(cstring, " \t") 330 if len(ts) < 1 { 331 continue 332 } 333 cFields := strings.Split(ts, " ") 334 actualOutcomes = append(actualOutcomes, &outcome{ 335 target: cFields[0], 336 privacyCondition: cFields[1], 337 shareCondition: cFields[6], 338 }) 339 } 340 if len(actualOutcomes) != len(tt.expectedOutcomes) { 341 t.Errorf("checkshare: unexpected got %d outcomes %s, want %d outcomes %s", 342 len(actualOutcomes), actualOutcomes, len(tt.expectedOutcomes), tt.expectedOutcomes) 343 return 344 } 345 for i := range actualOutcomes { 346 if actualOutcomes[i].String() != tt.expectedOutcomes[i].String() { 347 t.Errorf("checkshare: unexpected outcome #%d, got %q, want %q", 348 i+1, actualOutcomes[i], tt.expectedOutcomes[i]) 349 } 350 } 351 }) 352 } 353} 354