# Copyright 2017 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import print_function import os.path import re import subprocess import sys import tempfile import unittest from src.test.skylark import testenv class SkylarkTest(unittest.TestCase): """Tests for Skylark. In a test file, chunks are separated by "---". Each chunk is evaluated separately. Use "###" to specify the expected error. If there is no "###", the test will succeed iff there is no error. """ CHUNK_SEP = "---" ERR_SEP = "###" seen_error = False def chunks(self, path): code = [] expected_errors = [] with open(path, mode="rb") as f: for line in f: line = line.decode("utf-8") if line.strip() == self.CHUNK_SEP: yield code, expected_errors expected_errors = [] code = [] else: code.append(line) i = line.find(self.ERR_SEP) if i >= 0: expected_errors.append(line[i + len(self.ERR_SEP):].strip()) yield code, expected_errors def evaluate(self, f): """Execute Skylark file, return stderr.""" proc = subprocess.Popen( [testenv.SKYLARK_BINARY_PATH, f], stderr=subprocess.PIPE) _, stderr = proc.communicate() return stderr def check_output(self, output, expected): if expected and not output: self.seen_error = True print("Expected error:", expected) if output and not expected: self.seen_error = True print("Unexpected error:", output) for exp in expected: # Try both substring and regex matching. if exp not in output and not re.search(exp, output): self.seen_error = True print("Error `{}` not found, got: `{}`".format(exp, output)) PRELUDE = """ def assert_eq(x, y): if x != y: fail("%r != %r" % (x, y)) def assert_(cond, msg="assertion failed"): if not cond: fail(msg) """ def testFile(self): t = test_file print("===", t, "===") f = os.path.join(testenv.SKYLARK_TESTDATA_PATH, t) for chunk, expected in self.chunks(f): with tempfile.NamedTemporaryFile( mode="wb", suffix=".sky", delete=False) as tmp: lines = [line.encode("utf-8") for line in [self.PRELUDE] + chunk] tmp.writelines(lines) output = self.evaluate(tmp.name).decode("utf-8") os.unlink(tmp.name) self.check_output(output, expected) if self.seen_error: raise Exception("Test failed") if __name__ == "__main__": # Test filename is the last argument on the command-line. test_file = sys.argv[-1] unittest.main(argv=sys.argv[1:])