1# Copyright (C) 2022 The Android Open Source Project
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
15"""Unit tests for difftool.py."""
16
17import os
18import pathlib
19import unittest
20import clangcompile
21import difftool
22
23
24def get_path(name):
25  return os.path.join(os.getenv("TEST_TMPDIR"), name)
26
27
28def create_file(name, content):
29  path = get_path(name)
30  with open(path, "w") as f:
31    f.write(content)
32  return pathlib.Path(path)
33
34
35def _substring_in_list(s, slist):
36  for elem in slist:
37    if s in elem:
38      return True
39  return False
40
41
42class DifftoolTest(unittest.TestCase):
43
44  def assertNotInErrors(self, expected, errorlist):
45    if _substring_in_list(expected, errorlist):
46      self.fail("{!r} found in errors: {!r}".format(expected, errorlist))
47
48  def assertInErrors(self, expected, errorlist):
49    if not _substring_in_list(expected, errorlist):
50      self.fail("{!r} not found in errors: {!r}".format(expected, errorlist))
51
52  def test_file_differences_not_exist(self):
53    obj_file = create_file("foo.o", "object contents")
54
55    diffs = difftool.file_differences(pathlib.Path("doesntexist.o"),
56                                      obj_file)
57    self.assertEqual(["doesntexist.o does not exist"], diffs)
58
59  @unittest.skip("TODO(usta)")
60  def test_file_differences_different_types(self):
61    obj_file = create_file("foo.o", "object contents")
62    obj_file_two = create_file("foo2.o", "object contents two")
63    txt_file = create_file("foo3.txt", "other")
64    so_file = create_file("bar.so", "shared lib contents")
65
66    diffs = difftool.file_differences(obj_file, so_file)
67    self.assertInErrors("file types differ", diffs)
68
69    diffs = difftool.file_differences(obj_file, txt_file)
70    self.assertInErrors("file types differ", diffs)
71
72    diffs = difftool.file_differences(so_file, obj_file)
73    self.assertInErrors("file types differ", diffs)
74
75    diffs = difftool.file_differences(obj_file, obj_file_two)
76    self.assertNotInErrors("file types differ", diffs)
77
78  @unittest.skip("TODO(usta)")
79  def test_object_contents_differ(self):
80    obj_file = create_file("foo.o", "object contents\none\n")
81    obj_file_two = create_file("foo2.o", "object contents\ntwo\n")
82
83    diffs = difftool.file_differences(obj_file, obj_file_two)
84    self.assertNotInErrors("object_contents", diffs)
85    self.assertInErrors("one", diffs)
86    self.assertInErrors("two", diffs)
87
88  def test_soong_clang_compile_info(self):
89    fake_cmd = ("PWD=/proc/self/cwd prebuilts/clang -c -Wall -Wno-unused " +
90                "foo.cpp -Iframeworks/av/include -Dsomedefine " +
91                "-misc_flag misc_arg " +
92                "-o foo.o # comment")
93    info = difftool.rich_command_info(fake_cmd)
94    self.assertIsInstance(info, clangcompile.ClangCompileInfo)
95    self.assertEqual([("I", "frameworks/av/include")], info.i_includes)
96    self.assertEqual(["-Dsomedefine"], info.defines)
97    self.assertEqual(["-Wall", "-Wno-unused"], info.warnings)
98    self.assertEqual(["-c", ("misc_flag", "misc_arg")], info.misc_flags)
99    self.assertEqual(["foo.cpp", ("o", "foo.o")], info.file_flags)
100
101  def test_bazel_clang_compile_info(self):
102    fake_cmd = ("cd out/bazel/execroot && rm -f foo.o &&  " +
103                "prebuilts/clang -MD -MF bazel-out/foo.d " +
104                "-iquote . -iquote bazel-out/foo/bin " +
105                "-I frameworks/av/include " +
106                "-I bazel-out/frameworks/av/include/bin " +
107                " -Dsomedefine " +
108                "-misc_flag misc_arg " +
109                "-Werror=int-conversion " +
110                "-Wno-reserved-id-macro "
111                "-o foo.o # comment")
112    info = difftool.rich_command_info(fake_cmd)
113    self.assertIsInstance(info, clangcompile.ClangCompileInfo)
114    self.assertEqual([("iquote", ".")], info.iquote_includes)
115    self.assertEqual([("I", "frameworks/av/include")], info.i_includes)
116    self.assertEqual(["-Dsomedefine"], info.defines)
117    self.assertEqual(["-Werror=int-conversion", "-Wno-reserved-id-macro"],
118                     info.warnings)
119    self.assertEqual(["-MD", ("misc_flag", "misc_arg")], info.misc_flags)
120    self.assertEqual([("MF", "bazel-out/foo.d"), ("o", "foo.o")], info.file_flags)
121
122
123if __name__ == "__main__":
124  unittest.main()
125