blob: b435cf0a5889b4ba66f4984ced8cbe792908fe79 [file] [log] [blame]
Zhuoyao Zhang82b83bb2016-08-12 15:15:19 -07001#!/usr/bin/env python
2#
3# Copyright 2016 - 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
17import filecmp
18import logging
19import os
20import shutil
21import subprocess
22import sys
23import unittest
24
25class Tester(unittest.TestCase):
26 """Integration test runner for hidl-gen.
27 Runs hidl-gen on a bunch of packages/files and compares the out results with
28 canonical ones. Exit code is 0 iff all tests pass.
29
30 Usage:
31 python test_output.py path_to_hidl_gen canonical_dir output_dir (interface_root)
32 If interface_root is not provided, the default package "andorid.hardwre" and
33 the path root defined in $TOP will be used.
34
35 Attributes:
36 _hidl_gen_path: the path to run hidl-gen.
37 _canonical_dir: root directory contains canonical files for comparison.
38 _output_dir: root directory that stores all output files.
39 _interface_root: package:path root for the interface.
40 e.g., android.hardware:hardware/interfaces
41 _errors: number of errors generates during the test.
42 """
43 def __init__(self, testName, hidl_gen_path, canonical_dir, output_dir, interface_root=''):
44 super(Tester, self).__init__(testName)
45 self._hidl_gen_path = hidl_gen_path
46 self._canonical_dir = canonical_dir
47 self._output_dir = output_dir
48 self._interface_root = interface_root
49 self._errors = 0
50
51 def setUp(self):
52 """Removes output dir to prevent interference from previous runs."""
53 self.RemoveOutputDir()
54
55 def tearDown(self):
56 """If successful, removes the output dir for clean-up."""
57 if self._errors == 0:
58 self.RemoveOutputDir()
59
60 def testAll(self):
61 """Run all tests. """
62 self.TestVtsOutput()
Yifan Hong57886972016-08-17 10:42:15 -070063 self.TestCppOutput()
Yifan Hong19ca75a2016-08-31 10:20:03 -070064 self.TestJavaOutput()
Zhuoyao Zhang82b83bb2016-08-12 15:15:19 -070065
66 def TestVtsOutput(self):
67 """Runs hidl-gen to generate vts file and verify the output."""
68 self.RunTest("vts", "android.hardware.nfc@1.0",
69 "android/hardware/nfc/1.0")
70 self.assertEqual(self._errors, 0)
71
72 def TestCppOutput(self):
73 """Runs hidl-gen to generate c++ file and verify the output."""
Yifan Hong57886972016-08-17 10:42:15 -070074 # self.RunTest("c++", "android.hardware.nfc@1.0",
75 # "android/hardware/nfc/1.0")
76 self.RunTest("c++", "android.hardware.tests.expression@1.0",
77 "android/hardware/tests/expression/1.0")
Zhuoyao Zhang82b83bb2016-08-12 15:15:19 -070078 self.assertEqual(self._errors, 0)
79
Yifan Hong19ca75a2016-08-31 10:20:03 -070080 def TestJavaOutput(self):
81 self.RunTest("java", "android.hardware.tests.expression@1.0",
82 "android/hardware/tests/expression/1.0")
83 self.assertEqual(self._errors, 0)
84
Zhuoyao Zhang82b83bb2016-08-12 15:15:19 -070085 def RunTest(self, language, fqname, package_path):
86 """Run hidl-gen with given language and fqname, and compare the results.
87
88 Args:
89 language: the target language for the output code. e.g. c++, vts.
90 fqname: fully qualified name of the input files.
91 For single file input, follow the format:
92 package@version::fileName.
93 For directory input, follow the format: package@version.
94 example: android.hardware.nfc@1.0::INfc.hal
95 package_path: path for the package in fqname.
96 example: android/hardware/nfc/1.0
97 """
98 if self._interface_root != '':
99 hidl_gen_cmd = [self._hidl_gen_path, "-o", self._output_dir, "-L",
100 language, "-r", self._interface_root, fqname]
101 else:
102 hidl_gen_cmd = [self._hidl_gen_path, "-o", self._output_dir, "-L",
103 language, fqname]
104 self.RunCommand(hidl_gen_cmd)
105
106 output_dir = os.path.join(self._output_dir, package_path)
107 canonical_dir = os.path.join(self._canonical_dir, package_path)
108 self.CompareOutput(output_dir, canonical_dir)
109
110 def RunCommand(self, command):
111 """Runs a unix command and stashes the result."""
112 proc = subprocess.Popen(command,
113 stdout=subprocess.PIPE,
114 stderr=subprocess.PIPE)
115 (stdout, stderr) = proc.communicate()
116 if proc.returncode != 0:
117 self.Error(("Fail to execute command: %s" % command +
118 (" (stdout: %s\n stderr: %s\n)" % (stdout, stderr))))
119
120 def CompareOutput(self, output_dir, canonical_dir):
121 """Compare the files under output_dir with those under canonical_dir.
122
123 Args:
124 output_dir: directory that stores output files.
125 canonical_dir: directory contains canonical files for comparison.
126 """
127 for file_name in os.listdir(output_dir):
128 logging.info("comparing file: %s" % file)
129 self.CompareFile(file_name, output_dir, canonical_dir)
130
131 def CompareFile(self, file_name, output_dir, canonical_dir):
132 """Compares a given file and the corresponding one under canonical_dir.
133
134 Args:
135 file_name: name of file for comparison.
136 output_dir: directory that stores output files.
137 canonical_dir: directory contains canonical files for comparison.
138 """
139 canonical_file = os.path.join(canonical_dir, file_name)
140 output_file = os.path.join(output_dir, file_name)
141 if not os.path.isfile(canonical_file):
142 self.Error("Generated unexpected file: %s" % output_file)
143 else:
144 if not filecmp.cmp(output_file, canonical_file):
145 self.Error("output file: %s does not match the canonical_file: "
146 "%s" % (output_file, canonical_file))
147
148 def Error(self, string):
149 """Prints an error message and increments error count."""
150 logging.error(string)
151 self._errors += 1
152
153 def RemoveOutputDir(self):
154 """Remove the output_dir if it exists."""
155 if os.path.exists(self._output_dir):
156 shutil.rmtree(self._output_dir)
157
158if __name__ == "__main__":
159 if len(sys.argv) != 5 and len(sys.argv) !=4:
160 print "Usage: python test_output.py hidl_gen_path canonical_dir " \
161 "output_dir (interface_root)"
162 sys.exit(1)
163 suite = unittest.TestSuite()
164 if len(sys.argv) == 5:
165 suite.addTest(Tester('testAll', sys.argv[1],sys.argv[2], sys.argv[3], sys.argv[4]))
166 else:
167 suite.addTest(Tester('testAll', sys.argv[1],sys.argv[2], sys.argv[3]))
168 result = unittest.TextTestRunner(verbosity=2).run(suite)
169 if not result.wasSuccessful():
170 sys.exit(-1)