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 compliance 16 17import ( 18 "bytes" 19 "sort" 20 "strings" 21 "testing" 22) 23 24func TestReadLicenseGraph(t *testing.T) { 25 tests := []struct { 26 name string 27 fs *testFS 28 roots []string 29 expectedError string 30 expectedEdges []edge 31 expectedTargets []string 32 }{ 33 { 34 name: "trivial", 35 fs: &testFS{ 36 "app.meta_lic": []byte("package_name: \"Android\"\n"), 37 }, 38 roots: []string{"app.meta_lic"}, 39 expectedEdges: []edge{}, 40 expectedTargets: []string{"app.meta_lic"}, 41 }, 42 { 43 name: "unterminated", 44 fs: &testFS{ 45 "app.meta_lic": []byte("package_name: \"Android\n"), 46 }, 47 roots: []string{"app.meta_lic"}, 48 expectedError: `invalid character '\n' in string`, 49 }, 50 { 51 name: "danglingref", 52 fs: &testFS{ 53 "app.meta_lic": []byte(AOSP + "deps: {\n file: \"lib.meta_lic\"\n}\n"), 54 }, 55 roots: []string{"app.meta_lic"}, 56 expectedError: `unknown file "lib.meta_lic"`, 57 }, 58 { 59 name: "singleedge", 60 fs: &testFS{ 61 "app.meta_lic": []byte(AOSP + "deps: {\n file: \"lib.meta_lic\"\n}\n"), 62 "lib.meta_lic": []byte(AOSP), 63 }, 64 roots: []string{"app.meta_lic"}, 65 expectedEdges: []edge{{"app.meta_lic", "lib.meta_lic"}}, 66 expectedTargets: []string{"app.meta_lic", "lib.meta_lic"}, 67 }, 68 { 69 name: "fullgraph", 70 fs: &testFS{ 71 "apex.meta_lic": []byte(AOSP + "deps: {\n file: \"app.meta_lic\"\n}\ndeps: {\n file: \"bin.meta_lic\"\n}\n"), 72 "app.meta_lic": []byte(AOSP), 73 "bin.meta_lic": []byte(AOSP + "deps: {\n file: \"lib.meta_lic\"\n}\n"), 74 "lib.meta_lic": []byte(AOSP), 75 }, 76 roots: []string{"apex.meta_lic"}, 77 expectedEdges: []edge{ 78 {"apex.meta_lic", "app.meta_lic"}, 79 {"apex.meta_lic", "bin.meta_lic"}, 80 {"bin.meta_lic", "lib.meta_lic"}, 81 }, 82 expectedTargets: []string{"apex.meta_lic", "app.meta_lic", "bin.meta_lic", "lib.meta_lic"}, 83 }, 84 } 85 for _, tt := range tests { 86 t.Run(tt.name, func(t *testing.T) { 87 stderr := &bytes.Buffer{} 88 lg, err := ReadLicenseGraph(tt.fs, stderr, tt.roots) 89 if err != nil { 90 if len(tt.expectedError) == 0 { 91 t.Errorf("unexpected error: got %s, want no error", err) 92 } else if !strings.Contains(err.Error(), tt.expectedError) { 93 t.Errorf("unexpected error: got %s, want %q", err, tt.expectedError) 94 } 95 return 96 } 97 if len(tt.expectedError) > 0 { 98 t.Errorf("unexpected success: got no error, want %q err", tt.expectedError) 99 return 100 } 101 if lg == nil { 102 t.Errorf("missing license graph: got nil, want license graph") 103 return 104 } 105 actualEdges := make([]edge, 0) 106 for _, e := range lg.Edges() { 107 actualEdges = append(actualEdges, edge{e.Target().Name(), e.Dependency().Name()}) 108 } 109 sort.Sort(byEdge(tt.expectedEdges)) 110 sort.Sort(byEdge(actualEdges)) 111 t.Logf("actualEdges:") 112 for _, edge := range actualEdges { 113 t.Logf(" %s", edge.String()) 114 } 115 t.Logf("expectedEdges:") 116 for _, edge := range actualEdges { 117 t.Logf(" %s", edge.String()) 118 } 119 if len(tt.expectedEdges) != len(actualEdges) { 120 t.Errorf("len(actualEdges): got %d, want %d", len(actualEdges), len(tt.expectedEdges)) 121 } else { 122 for i := 0; i < len(actualEdges); i++ { 123 if tt.expectedEdges[i] != actualEdges[i] { 124 t.Errorf("actualEdges[%d]: got %s, want %s", i, actualEdges[i], tt.expectedEdges[i]) 125 } 126 } 127 } 128 129 actualTargets := make([]string, 0) 130 for _, t := range lg.Targets() { 131 actualTargets = append(actualTargets, t.Name()) 132 } 133 sort.Strings(tt.expectedTargets) 134 sort.Strings(actualTargets) 135 136 t.Logf("actualTargets: %v", actualTargets) 137 t.Logf("expectedTargets: %v", tt.expectedTargets) 138 139 if len(tt.expectedTargets) != len(actualTargets) { 140 t.Errorf("len(actualTargets): got %d, want %d", len(actualTargets), len(tt.expectedTargets)) 141 } else { 142 for i := 0; i < len(actualTargets); i++ { 143 if tt.expectedTargets[i] != actualTargets[i] { 144 t.Errorf("actualTargets[%d]: got %s, want %s", i, actualTargets[i], tt.expectedTargets[i]) 145 } 146 } 147 } 148 }) 149 } 150} 151