# 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:])
