# pylint: disable=g-bad-file-header
# Copyright 2018 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.

import os
import tempfile
from absl.testing import absltest
from src.test.py.bazel import test_base


class QueryTest(test_base.TestBase):

  def testSimpleQuery(self):
    self.ScratchFile('MODULE.bazel')
    self.ScratchFile('foo/BUILD', [
        'exports_files(["exported.txt"])',
        'filegroup(name = "top-rule", srcs = [":dep-rule"])',
        'filegroup(name = "dep-rule", srcs = ["src.txt"])',
    ])
    self.ScratchFile('foo/src.txt')
    self.ScratchFile('foo/exported.txt')
    self.ScratchFile('foo/non-exported.txt')
    self._AssertQueryOutput('//foo:top-rule', '//foo:top-rule')
    self._AssertQueryOutput('//foo:*', '//foo:top-rule', '//foo:dep-rule',
                            '//foo:src.txt', '//foo:exported.txt',
                            '//foo:BUILD')
    self._AssertQueryOutput('deps(//foo:top-rule)', '//foo:top-rule',
                            '//foo:dep-rule', '//foo:src.txt')
    self._AssertQueryOutput('deps(//foo:top-rule, 1)', '//foo:top-rule',
                            '//foo:dep-rule')

  def testQueryFilesUsedByRepositoryRules(self):
    self.ScratchFile('MODULE.bazel')
    self._AssertQueryOutputContains(
        "kind('source file', deps(//external:*))",
        '@bazel_tools//tools/genrule:genrule-setup.sh',
    )

  def testBuildFilesForExternalRepos_Simple(self):
    self.ScratchFile('MODULE.bazel')
    self.ScratchFile('WORKSPACE', [
        'load("//:deps.bzl", "repos")',
        'repos()',
    ])
    self.ScratchFile('BUILD.bazel')
    self.ScratchFile('deps.bzl', [
        'def repos():',
        '    native.new_local_repository(',
        '        name = "io_bazel_rules_go",',
        '        path = ".",',
        """        build_file_content = "exports_files(glob(['*.go']))",""",
        '    )',
    ])
    self._AssertQueryOutputContains('buildfiles(//external:io_bazel_rules_go)',
                                    '//external:WORKSPACE', '//:deps.bzl',
                                    '//:BUILD.bazel')

  def testBuildFilesForExternalRepos_IndirectLoads(self):
    self.ScratchFile('MODULE.bazel')
    self.ScratchFile('WORKSPACE', [
        'load("//:deps.bzl", "repos")',
        'repos()',
    ])
    self.ScratchFile('BUILD.bazel')
    self.ScratchFile('deps.bzl', [
        'load("//:private_deps.bzl", "other_repos")',
        'def repos():',
        '    native.new_local_repository(',
        '        name = "io_bazel_rules_go",',
        '        path = ".",',
        """        build_file_content = "exports_files(glob(['*.go']))",""",
        '    )',
        '    other_repos()',
        '',
    ])
    self.ScratchFile('private_deps.bzl', [
        'def other_repos():',
        '    native.new_local_repository(',
        '        name = "io_bazel_rules_python",',
        '        path = ".",',
        """        build_file_content = "exports_files(glob(['*.py']))",""",
        '    )',
    ])

    self._AssertQueryOutputContains(
        'buildfiles(//external:io_bazel_rules_python)', '//external:WORKSPACE',
        '//:deps.bzl', '//:private_deps.bzl', '//:BUILD.bazel')

  def testBuildFilesForExternalRepos_NoDuplicates(self):
    self.ScratchFile('MODULE.bazel')
    self.ScratchFile('WORKSPACE', [
        'load("//:deps.bzl", "repos")',
        'repos()',
    ])
    self.ScratchFile('BUILD.bazel')
    self.ScratchFile('deps.bzl', [
        'def repos():',
        '    native.new_local_repository(',
        '        name = "io_bazel_rules_go",',
        '        path = ".",',
        """        build_file_content = "exports_files(glob(['*.go']))",""",
        '    )',
        '    other_repos()',
        '',
        'def other_repos():',
        '    native.new_local_repository(',
        '        name = "io_bazel_rules_python",',
        '        path = ".",',
        """        build_file_content = "exports_files(glob(['*.py']))",""",
        '    )',
    ])

    _, stdout, _ = self.RunBazel(
        ['query', 'buildfiles(//external:io_bazel_rules_python)']
    )
    result = set()
    for item in stdout:
      if not item:
        continue
      self.assertNotIn(item, result)
      result.add(item)

  def testQueryWithDifferentOutputBaseAfterBuilding(self):
    output_base = tempfile.mkdtemp(dir=os.getenv('TEST_TMPDIR'))

    self.ScratchFile('MODULE.bazel')
    self.ScratchFile(
        'BUILD',
        [
            'py_binary(name="a", srcs=["a.py"])',
        ],
    )
    self.ScratchFile('a.py')
    self.RunBazel(['build', '//...'])
    self.RunBazel([f'--output_base={output_base}', 'query', '//...'])

  def _AssertQueryOutput(self, query_expr, *expected_results):
    _, stdout, _ = self.RunBazel(['query', query_expr])

    stdout = sorted(x for x in stdout if x)
    self.assertEqual(len(stdout), len(expected_results))
    self.assertListEqual(stdout, sorted(expected_results))

  def _AssertQueryOutputContains(self, query_expr, *expected_content):
    _, stdout, _ = self.RunBazel(['query', query_expr])

    stdout = {x for x in stdout if x}
    for item in expected_content:
      self.assertIn(item, stdout)


if __name__ == '__main__':
  absltest.main()
