# 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.

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


class CcImportTest(test_base.TestBase):

  def createProjectFiles(self,
                         alwayslink=0,
                         system_provided=0,
                         linkstatic=1,
                         provide_header=True):
    self.AddBazelDep('rules_cc')
    # We use the outputs of cc_binary and cc_library as precompiled
    # libraries for cc_import
    self.ScratchFile(
        'lib/BUILD',
        [
            'package(default_visibility = ["//visibility:public"])',
            '',
            'load("@rules_cc//cc:cc_binary.bzl", "cc_binary")',
            'load("@rules_cc//cc:cc_import.bzl", "cc_import")',
            'load("@rules_cc//cc:cc_library.bzl", "cc_library")',
            'cc_binary(',
            '  name = "libA.so",',
            '  srcs = ["a.cc"],',
            '  linkshared = 1,',
            ')',
            '',
            'filegroup(',
            '  name = "libA_ifso",',
            '  srcs = [":libA.so"],',
            '  output_group = "interface_library",',
            ')',
            '',
            'cc_library(',
            '  name = "libA",',
            '  srcs = ["a.cc", "a_al.cc"],',
            ')',
            '',
            'filegroup(',
            '  name = "libA_archive",',
            '  srcs = [":libA"],',
            '  output_group = "archive",',
            ')',
            '',
            'cc_import(',
            '  name = "A",',
            '  static_library = "//lib:libA_archive",',
            '  shared_library = "//lib:libA.so",'
            if not system_provided
            else '',
            # On Windows, we always need the interface library
            '  interface_library = "//lib:libA_ifso",'
            if self.IsWindows()
            else (
                # On Unix, we use .so file as interface library
                # if system_provided is true
                '  interface_library = "//lib:libA.so",'
                if system_provided
                else ''
            ),
            '  hdrs = ["a.h"],' if provide_header else '',
            '  alwayslink = %s,' % str(alwayslink),
            '  system_provided = %s,' % str(system_provided),
            ')',
        ],
    )

    self.ScratchFile('lib/a.cc', [
        '#include <stdio.h>',
        '',
        '#ifdef _WIN32',
        '  #define DLLEXPORT __declspec(dllexport)',
        '#else',
        '  #define DLLEXPORT',
        '#endif',
        '',
        'DLLEXPORT void HelloWorld() {',
        '  printf("HelloWorld\\n");',
        '}',
    ])

    # For testing alwayslink=1
    self.ScratchFile('lib/a_al.cc', [
        'extern int global_variable;',
        'int init() {',
        '    ++global_variable;',
        '    return global_variable;',
        '}',
        'int x = init();',
        'int y = init();',
    ])

    self.ScratchFile('lib/a.h', [
        'void HelloWorld();',
    ])

    self.ScratchFile(
        'main/BUILD',
        [
            'load("@rules_cc//cc:cc_binary.bzl", "cc_binary")',
            'cc_binary(',
            '  name = "B",',
            '  srcs = ["b.cc"],',
            '  deps = ["//lib:A",],',
            '  linkstatic = %s,' % str(linkstatic),
            ')',
        ],
    )

    self.ScratchFile('main/b.cc', [
        '#include <stdio.h>',
        '#include "lib/a.h"',
        'int global_variable = 0;',
        'int main() {',
        '  HelloWorld();',
        '  printf("global : %d\\n", global_variable);',
        '  return 0;',
        '}',
    ])

  def getBazelInfo(self, info_key):
    _, stdout, _ = self.RunBazel(['info', info_key])
    return stdout[0]

  def testLinkStaticLibrary(self):
    self.createProjectFiles(alwayslink=0, linkstatic=1)
    bazel_bin = self.getBazelInfo('bazel-bin')
    suffix = '.exe' if self.IsWindows() else ''

    self.RunBazel(['build', '//main:B'])

    b_bin = os.path.join(bazel_bin, 'main/B' + suffix)
    self.assertTrue(os.path.exists(b_bin))
    _, stdout, _ = self.RunProgram([b_bin])
    self.assertEqual(stdout[0], 'HelloWorld')
    self.assertEqual(stdout[1], 'global : 0')

  def testAlwayslinkStaticLibrary(self):
    self.createProjectFiles(alwayslink=1, linkstatic=1)
    bazel_bin = self.getBazelInfo('bazel-bin')
    suffix = '.exe' if self.IsWindows() else ''

    self.RunBazel(['build', '//main:B'])

    b_bin = os.path.join(bazel_bin, 'main/B' + suffix)
    self.assertTrue(os.path.exists(b_bin))
    _, stdout, _ = self.RunProgram([b_bin])
    self.assertEqual(stdout[0], 'HelloWorld')
    self.assertEqual(stdout[1], 'global : 2')

  def testLinkSharedLibrary(self):
    self.createProjectFiles(linkstatic=0)
    bazel_bin = self.getBazelInfo('bazel-bin')
    suffix = '.exe' if self.IsWindows() else ''

    self.RunBazel(['build', '//main:B'])

    b_bin = os.path.join(bazel_bin, 'main/B' + suffix)
    self.assertTrue(os.path.exists(b_bin))
    if self.IsWindows():
      self.assertTrue(os.path.exists(os.path.join(bazel_bin, 'main/libA.so')))
    _, stdout, _ = self.RunProgram([b_bin])
    self.assertEqual(stdout[0], 'HelloWorld')

  def testSystemProvidedSharedLibraryOnWinodws(self):
    if not self.IsWindows():
      return
    self.createProjectFiles(system_provided=1, linkstatic=0)
    bazel_bin = self.getBazelInfo('bazel-bin')

    self.RunBazel(['build', '//main:B'])

    b_bin = os.path.join(bazel_bin, 'main/B.exe')
    exit_code, _, _ = self.RunProgram([b_bin], allow_failure=True)
    # Should fail because missing libA.so
    self.assertFalse(exit_code == 0)

    # Let's build libA.so and add it into PATH
    self.RunBazel(['build', '//lib:libA.so'])

    _, stdout, _ = self.RunProgram(
        [b_bin], env_add={'PATH': str(os.path.join(bazel_bin, 'lib'))}
    )
    self.assertEqual(stdout[0], 'HelloWorld')

  def testSystemProvidedSharedLibraryOnUnix(self):
    if not self.IsLinux():
      return
    self.createProjectFiles(system_provided=1, linkstatic=0)
    bazel_bin = self.getBazelInfo('bazel-bin')

    self.RunBazel(['build', '//main:B'])

    b_bin = os.path.join(bazel_bin, 'main/B')
    tmp_dir = self.ScratchDir('temp_dir_for_run_b_bin')
    b_bin_tmp = os.path.join(tmp_dir, 'B')
    # Copy the binary to a temp directory to make sure it cannot find
    # libA.so
    shutil.copyfile(b_bin, b_bin_tmp)
    os.chmod(b_bin_tmp, stat.S_IRWXU)
    exit_code, _, _ = self.RunProgram([b_bin_tmp], allow_failure=True)
    # Should fail because missing libA.so
    self.assertFalse(exit_code == 0)

    # Let's build libA.so and add it into PATH
    self.RunBazel(['build', '//lib:libA.so'])

    _, stdout, _ = self.RunProgram(
        [b_bin_tmp],
        env_add={
            # For Linux
            'LD_LIBRARY_PATH': str(os.path.join(bazel_bin, 'lib')),
            # For Mac
            'DYLD_LIBRARY_PATH': str(os.path.join(bazel_bin, 'lib')),
        },
    )
    self.assertEqual(stdout[0], 'HelloWorld')

  def testCcImportHeaderCheck(self):
    self.createProjectFiles(provide_header=False)
    # Build should fail, because lib/a.h is not declared in BUILD file, disable
    # sandbox so that bazel produces same error across different platforms.
    exit_code, _, stderr = self.RunBazel(
        ['build', '//main:B', '--spawn_strategy=standalone'], allow_failure=True
    )
    self.AssertExitCode(exit_code, 1, stderr)
    self.assertIn('this rule is missing dependency declarations for the'
                  ' following files included by \'main/b.cc\':',
                  ''.join(stderr))


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