1#!/usr/bin/env python 2# 3# Copyright (C) 2023 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17"""Unit tests for conv_linker_config.py.""" 18 19import io 20import os 21import shutil 22import tempfile 23import unittest 24 25import conv_linker_config 26from contextlib import redirect_stderr 27from linker_config_pb2 import LinkerConfig 28 29class FileArgs: 30 def __init__(self, files, sep = ':'): 31 self.files = files 32 self.sep = sep 33 34 35class FileArg: 36 def __init__(self, file): 37 self.file = file 38 39 40class TempDirTest(unittest.TestCase): 41 42 def setUp(self): 43 self.tempdir = tempfile.mkdtemp() 44 45 46 def tearDown(self): 47 shutil.rmtree(self.tempdir) 48 49 50 def write(self, name, contents): 51 with open(os.path.join(self.tempdir, name), 'wb') as f: 52 f.write(contents) 53 54 55 def read(self, name): 56 with open(os.path.join(self.tempdir, name), 'rb') as f: 57 return f.read() 58 59 60 def resolve_paths(self, args): 61 for i in range(len(args)): 62 if isinstance(args[i], FileArgs): 63 args[i] = args[i].sep.join(os.path.join(self.tempdir, f.file) for f in args[i].files) 64 elif isinstance(args[i], FileArg): 65 args[i] = os.path.join(self.tempdir, args[i].file) 66 return args 67 68 69class ConvLinkerConfigTest(TempDirTest): 70 """Unit tests for conv_linker_config.""" 71 72 73 def test_Proto_empty_input(self): 74 self.command(['proto', '-s', '-o', FileArg('out.pb')]) 75 pb = LinkerConfig() 76 pb.ParseFromString(self.read('out.pb')) 77 self.assertEqual(pb, LinkerConfig()) 78 79 80 def test_Proto_single_input(self): 81 self.write('foo.json', b'{ "provideLibs": ["libfoo.so"]}') 82 self.command(['proto', '-s', FileArg('foo.json'), '-o', FileArg('out.pb')]) 83 pb = LinkerConfig() 84 pb.ParseFromString(self.read('out.pb')) 85 self.assertSequenceEqual(pb.provideLibs, ['libfoo.so']) 86 87 88 def test_Proto_with_multiple_input(self): 89 self.write('foo.json', b'{ "provideLibs": ["libfoo.so"]}') 90 self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}') 91 self.command(['proto', '-s', FileArgs([FileArg('foo.json'), FileArg('bar.json')]), '-o', FileArg('out.pb')]) 92 pb = LinkerConfig() 93 pb.ParseFromString(self.read('out.pb')) 94 self.assertSetEqual(set(pb.provideLibs), set(['libfoo.so', 'libbar.so'])) 95 96 97 def test_Proto_with_existing_output(self): 98 self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString()) 99 buf = io.StringIO() 100 with self.assertRaises(SystemExit) as err: 101 with redirect_stderr(buf): 102 self.command(['proto', '-o', FileArg('out.pb')]) 103 self.assertEqual(err.exception.code, 1) 104 self.assertRegex(buf.getvalue(), r'.*out\.pb exists') 105 106 107 def test_Proto_with_append(self): 108 self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString()) 109 self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}') 110 self.command(['proto', '-s', FileArg('bar.json'), '-o', FileArg('out.pb'), '-a']) 111 pb = LinkerConfig() 112 pb.ParseFromString(self.read('out.pb')) 113 self.assertSetEqual(set(pb.provideLibs), set(['libfoo.so', 'libbar.so'])) 114 115 116 def test_Proto_with_force(self): 117 self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString()) 118 self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}') 119 self.command(['proto', '-s', FileArg('bar.json'), '-o', FileArg('out.pb'), '-f']) 120 pb = LinkerConfig() 121 pb.ParseFromString(self.read('out.pb')) 122 self.assertSetEqual(set(pb.provideLibs), set(['libbar.so'])) 123 124 125 def command(self, args): 126 parser = conv_linker_config.GetArgParser() 127 parsed_args = parser.parse_args(self.resolve_paths(args)) 128 parsed_args.func(parsed_args) 129 130 131if __name__ == '__main__': 132 unittest.main(verbosity=2) 133