xref: /aosp_15_r20/external/bazelbuild-rules_android/src/tools/ak/repack/repack_test.go (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1// Copyright 2018 The Bazel Authors. 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 repack
16
17import (
18	"archive/zip"
19	"bytes"
20	"io/ioutil"
21	"log"
22	"os"
23	"path/filepath"
24	"testing"
25)
26
27type test struct {
28	name     string
29	testData []testData
30	filter   filterFunc
31}
32
33type testData struct {
34	name  string
35	match bool
36}
37
38var (
39	filterNoneData = []testData{
40		{
41			name:  "META-INF/MANIFEST.MF",
42			match: false,
43		},
44		{
45			name:  "com/google/android/test/TestActivity.class",
46			match: false,
47		},
48		{
49			name:  "googledata/data.txt",
50			match: false,
51		},
52	}
53	filterJarResData = []testData{
54		{
55			name:  "META-INF/MANIFEST.MF",
56			match: false,
57		},
58		{
59			name:  "com/google/android/test/TestActivity.class",
60			match: false,
61		},
62		{
63			name:  "googledata/data.txt",
64			match: true,
65		},
66	}
67	filterRData = []testData{
68		{
69			name:  "META-INF/MANIFEST.MF",
70			match: false,
71		},
72		{
73			name:  "com/google/android/test/TestActivity.class",
74			match: false,
75		},
76		{
77			name:  "com/google/android/test/R.class",
78			match: true,
79		},
80		{
81			name:  "com/google/android/test/R$string.class",
82			match: true,
83		},
84		{
85			name:  "com/google/android/test/R$attr.class",
86			match: true,
87		},
88	}
89	filterManifestData = []testData{
90		{
91			name:  "AndroidManifest.xml",
92			match: true,
93		},
94		{
95			name:  "res/drawable/icon.png",
96			match: false,
97		},
98		{
99			name:  "res/layout/skeleton_activity.xml",
100			match: false,
101		},
102		{
103			name:  "resources.arsc",
104			match: false,
105		},
106	}
107	tests = []test{
108		{
109			name:     "filterNone",
110			testData: filterNoneData,
111			filter:   filterNone,
112		},
113		{
114			name:     "isJavaRes",
115			testData: filterJarResData,
116			filter:   isJavaRes,
117		},
118		{
119			name:     "isRClass",
120			testData: filterRData,
121			filter:   isRClass,
122		},
123		{
124			name:     "isManifest",
125			testData: filterManifestData,
126			filter:   isManifest,
127		},
128	}
129)
130
131func TestRepackZip(t *testing.T) {
132	for _, test := range tests {
133		t.Run(test.name, func(t *testing.T) {
134			bufIn := new(bytes.Buffer)
135			zipIn := zip.NewWriter(bufIn)
136			createZip(zipIn, test.testData)
137
138			if err := zipIn.Close(); err != nil {
139				log.Fatal(err)
140			}
141
142			inReader, err := zip.NewReader(bytes.NewReader(bufIn.Bytes()), int64(bufIn.Len()))
143			if err != nil {
144				t.Fatal(err)
145			}
146
147			in := &zip.ReadCloser{
148				Reader: *inReader,
149			}
150
151			repackZipTest(t, in, test)
152			repackZipWithFiletedOutTest(t, in, test)
153		})
154	}
155}
156
157func TestFilterZip(t *testing.T) {
158	for _, test := range tests {
159		t.Run(test.name, func(t *testing.T) {
160			for _, testData := range test.testData {
161				if test.filter(testData.name) != testData.match {
162					t.Errorf("Filter applied on: %q got: %v wanted: %v", testData.name, test.filter(testData.name), testData.match)
163				}
164			}
165		})
166	}
167}
168
169func TestRepackDir(t *testing.T) {
170	for _, test := range tests {
171		t.Run(test.name, func(t *testing.T) {
172			dir, err := ioutil.TempDir("", "repack_dir_")
173			if err != nil {
174				log.Fatal(err)
175			}
176			defer os.RemoveAll(dir)
177
178			createDir(dir, test.testData)
179			repackDirTest(t, dir, test)
180		})
181	}
182}
183
184func repackZipTest(t *testing.T, in *zip.ReadCloser, test test) {
185	bufOut := new(bytes.Buffer)
186	zipOut := zip.NewWriter(bufOut)
187
188	seen = make(map[string]bool)
189	if err := repackZip(&in.Reader, zipOut, nil, test.filter, zip.Store); err != nil {
190		t.Fatal(err)
191	}
192
193	if err := zipOut.Close(); err != nil {
194		log.Fatal(err)
195	}
196
197	r, err := zip.NewReader(bytes.NewReader(bufOut.Bytes()), int64(bufOut.Len()))
198	if err != nil {
199		t.Fatal(err)
200	}
201
202	files := []string{}
203	for _, testData := range test.testData {
204		if !testData.match {
205			files = append(files, testData.name)
206		}
207	}
208
209	if len(r.File) != len(files) {
210		t.Fatalf("Output file number differ, got: %v wanted: %v", len(r.File), len(files))
211	}
212
213	for i, fileName := range files {
214		if r.File[i].Name != fileName {
215			t.Errorf("Filename differ, got: %q wanted: %q", r.File[i].Name, fileName)
216		}
217	}
218}
219
220func repackZipWithFiletedOutTest(t *testing.T, in *zip.ReadCloser, test test) {
221	bufOut := new(bytes.Buffer)
222	zipOut := zip.NewWriter(bufOut)
223
224	buffilteredOut := new(bytes.Buffer)
225	zipfilteredOut := zip.NewWriter(buffilteredOut)
226
227	seen = make(map[string]bool)
228	if err := repackZip(&in.Reader, zipOut, zipfilteredOut, test.filter, zip.Store); err != nil {
229		t.Fatal(err)
230	}
231
232	if err := zipOut.Close(); err != nil {
233		log.Fatal(err)
234	}
235	if err := zipfilteredOut.Close(); err != nil {
236		log.Fatal(err)
237	}
238
239	r, err := zip.NewReader(bytes.NewReader(bufOut.Bytes()), int64(bufOut.Len()))
240	if err != nil {
241		t.Fatal(err)
242	}
243	rfiltered, err := zip.NewReader(bytes.NewReader(buffilteredOut.Bytes()), int64(buffilteredOut.Len()))
244	if err != nil {
245		t.Fatal(err)
246	}
247
248	files := []string{}
249	filesfiltered := []string{}
250	for _, testData := range test.testData {
251		if !testData.match {
252			files = append(files, testData.name)
253		} else {
254			filesfiltered = append(filesfiltered, testData.name)
255		}
256	}
257
258	if len(r.File) != len(files) {
259		t.Fatalf("Output file number differ, got: %v wanted: %v", len(r.File), len(files))
260	}
261
262	if len(rfiltered.File) != (len(filesfiltered)) {
263		t.Fatalf("Filtered output file number differ, got: %v wanted: %v", len(rfiltered.File), len(files))
264	}
265
266	for i, fileName := range files {
267		if r.File[i].Name != fileName {
268			t.Errorf("Filename differ, got: %q wanted: %q", r.File[i].Name, fileName)
269		}
270	}
271
272	for i, fileName := range filesfiltered {
273		if rfiltered.File[i].Name != fileName {
274			t.Errorf("Filtered filename differ, got: %q wanted: %q", rfiltered.File[i].Name, fileName)
275		}
276	}
277}
278
279func repackDirTest(t *testing.T, dir string, test test) {
280	removeDirs = true
281	bufOut := new(bytes.Buffer)
282	zipOut := zip.NewWriter(bufOut)
283
284	seen = make(map[string]bool)
285	if err := repackDir(dir, zipOut, nil, test.filter, zip.Store); err != nil {
286		log.Fatal(err)
287	}
288
289	if err := zipOut.Close(); err != nil {
290		log.Fatal(err)
291	}
292
293	r, err := zip.NewReader(bytes.NewReader(bufOut.Bytes()), int64(bufOut.Len()))
294	if err != nil {
295		t.Fatal(err)
296	}
297
298	files := []string{}
299	for _, testData := range test.testData {
300		if !testData.match {
301			files = append(files, testData.name)
302		}
303	}
304
305	if len(r.File) != len(files) {
306		t.Fatalf("Output file number differ, got: %v wanted: %v", len(r.File), len(files))
307	}
308
309	for i, fileName := range files {
310		if r.File[i].Name != fileName {
311			t.Errorf("Filename differ, got: %q wanted: %q", r.File[i].Name, fileName)
312		}
313	}
314}
315
316func createZip(w *zip.Writer, testDatas []testData) {
317	for _, testData := range testDatas {
318		f, err := w.Create(testData.name)
319		if err != nil {
320			log.Fatal(err)
321		}
322		_, err = f.Write([]byte{42})
323		if err != nil {
324			log.Fatal(err)
325		}
326	}
327}
328
329func createDir(base string, testDatas []testData) {
330	for _, testData := range testDatas {
331		path := filepath.Join(base, testData.name)
332		if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
333			log.Fatal(err)
334		}
335		if err := ioutil.WriteFile(path, []byte{1, 2, 3}, 0777); err != nil {
336			log.Fatal(err)
337		}
338	}
339}
340