• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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}
218