blob: 754b7ef83098623997f451cc51f987d122e060e3 [file] [log] [blame]
Colin Cross36f55aa2022-03-21 18:46:41 -07001// Copyright 2022 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 main
16
17import (
18 "io/ioutil"
19 "os"
20 "path/filepath"
21 "strings"
22 "testing"
23
24 "android/soong/cmd/symbols_map/symbols_map_proto"
25
26 "google.golang.org/protobuf/encoding/prototext"
27 "google.golang.org/protobuf/proto"
28)
29
30func Test_mergeProtos(t *testing.T) {
31 type testFile struct {
32 filename string
33 contents *symbols_map_proto.Mapping
34 missing bool
35 }
36
37 tests := []struct {
38 name string
39 inputs []testFile
40 stripPrefix string
41 writeIfChanged bool
42 ignoreMissingFiles bool
43
44 error string
45 output *symbols_map_proto.Mappings
46 }{
47 {
48 name: "empty",
49 output: &symbols_map_proto.Mappings{},
50 },
51 {
52 name: "merge",
53 inputs: []testFile{
54 {
55 filename: "foo",
56 contents: &symbols_map_proto.Mapping{
57 Identifier: proto.String("foo"),
58 Location: proto.String("symbols/foo"),
59 Type: symbols_map_proto.Mapping_ELF.Enum(),
60 },
61 },
62 {
63 filename: "bar",
64 contents: &symbols_map_proto.Mapping{
65 Identifier: proto.String("bar"),
66 Location: proto.String("symbols/bar"),
67 Type: symbols_map_proto.Mapping_R8.Enum(),
68 },
69 },
70 },
71 output: &symbols_map_proto.Mappings{
72 Mappings: []*symbols_map_proto.Mapping{
73 {
74 Identifier: proto.String("foo"),
75 Location: proto.String("symbols/foo"),
76 Type: symbols_map_proto.Mapping_ELF.Enum(),
77 },
78 {
79 Identifier: proto.String("bar"),
80 Location: proto.String("symbols/bar"),
81 Type: symbols_map_proto.Mapping_R8.Enum(),
82 },
83 },
84 },
85 },
86 {
87 name: "strip prefix",
88 inputs: []testFile{
89 {
90 filename: "foo",
91 contents: &symbols_map_proto.Mapping{
92 Identifier: proto.String("foo"),
93 Location: proto.String("symbols/foo"),
94 Type: symbols_map_proto.Mapping_ELF.Enum(),
95 },
96 },
97 {
98 filename: "bar",
99 contents: &symbols_map_proto.Mapping{
100 Identifier: proto.String("bar"),
101 Location: proto.String("symbols/bar"),
102 Type: symbols_map_proto.Mapping_R8.Enum(),
103 },
104 },
105 },
106 stripPrefix: "symbols/",
107 output: &symbols_map_proto.Mappings{
108 Mappings: []*symbols_map_proto.Mapping{
109 {
110 Identifier: proto.String("foo"),
111 Location: proto.String("foo"),
112 Type: symbols_map_proto.Mapping_ELF.Enum(),
113 },
114 {
115 Identifier: proto.String("bar"),
116 Location: proto.String("bar"),
117 Type: symbols_map_proto.Mapping_R8.Enum(),
118 },
119 },
120 },
121 },
122 {
123 name: "missing",
124 inputs: []testFile{
125 {
126 filename: "foo",
127 contents: &symbols_map_proto.Mapping{
128 Identifier: proto.String("foo"),
129 Location: proto.String("symbols/foo"),
130 Type: symbols_map_proto.Mapping_ELF.Enum(),
131 },
132 },
133 {
134 filename: "bar",
135 missing: true,
136 },
137 },
138 error: "no such file or directory",
139 },
140 {
141 name: "ignore missing",
142 inputs: []testFile{
143 {
144 filename: "foo",
145 contents: &symbols_map_proto.Mapping{
146 Identifier: proto.String("foo"),
147 Location: proto.String("symbols/foo"),
148 Type: symbols_map_proto.Mapping_ELF.Enum(),
149 },
150 },
151 {
152 filename: "bar",
153 missing: true,
154 },
155 },
156 ignoreMissingFiles: true,
157 output: &symbols_map_proto.Mappings{
158 Mappings: []*symbols_map_proto.Mapping{
159 {
160 Identifier: proto.String("foo"),
161 Location: proto.String("symbols/foo"),
162 Type: symbols_map_proto.Mapping_ELF.Enum(),
163 },
164 },
165 },
166 },
167 }
168 for _, tt := range tests {
169 t.Run(tt.name, func(t *testing.T) {
170 dir, err := os.MkdirTemp("", "test_mergeProtos")
171 if err != nil {
172 t.Fatalf("failed to create temporary directory: %s", err)
173 }
174 defer os.RemoveAll(dir)
175
176 var inputs []string
177 for _, in := range tt.inputs {
178 path := filepath.Join(dir, in.filename)
179 inputs = append(inputs, path)
180 if !in.missing {
181 err := writeTextProto(path, in.contents, false)
182 if err != nil {
183 t.Fatalf("failed to create input file %s: %s", path, err)
184 }
185 }
186 }
187 output := filepath.Join(dir, "out")
188
189 err = mergeProtos(output, inputs, tt.stripPrefix, tt.writeIfChanged, tt.ignoreMissingFiles)
190 if err != nil {
191 if tt.error != "" {
192 if !strings.Contains(err.Error(), tt.error) {
193 t.Fatalf("expected error %q, got %s", tt.error, err.Error())
194 }
195 } else {
196 t.Fatalf("unexpected error %q", err)
197 }
198 } else if tt.error != "" {
199 t.Fatalf("missing error %q", tt.error)
200 } else {
201 data, err := ioutil.ReadFile(output)
202 if err != nil {
203 t.Fatalf("failed to read output file %s: %s", output, err)
204 }
205 var got symbols_map_proto.Mappings
206 err = prototext.Unmarshal(data, &got)
207 if err != nil {
208 t.Fatalf("failed to unmarshal textproto %s: %s", output, err)
209 }
210
211 if !proto.Equal(tt.output, &got) {
212 t.Fatalf("expected output %q, got %q", tt.output.String(), got.String())
213 }
214 }
215 })
216 }
217}