#!/usr/bin/env python3
# Copyright 2020 The Pigweed Authors
#
# 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
#
#     https://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.
"""Tests for the Python runner."""

import os
from pathlib import Path
import platform
import tempfile
import unittest

from pw_build.python_runner import ExpressionError, GnPaths, Label, TargetInfo
from pw_build.python_runner import expand_expressions

ROOT = Path(r'C:\gn_root' if platform.system() == 'Windows' else '/gn_root')

TEST_PATHS = GnPaths(
    ROOT,
    ROOT / 'out',
    ROOT / 'some' / 'cwd',
    '//toolchains/cool:ToolChain',
)


class LabelTest(unittest.TestCase):
    """Tests GN label parsing."""
    def setUp(self):
        self._paths_and_toolchain_name = [
            (TEST_PATHS, 'ToolChain'),
            (GnPaths(*TEST_PATHS[:3], ''), ''),
        ]

    def test_root(self):
        for paths, toolchain in self._paths_and_toolchain_name:
            label = Label(paths, '//')
            self.assertEqual(label.name, '')
            self.assertEqual(label.dir, ROOT)
            self.assertEqual(label.out_dir,
                             ROOT.joinpath('out', toolchain, 'obj'))
            self.assertEqual(label.gen_dir,
                             ROOT.joinpath('out', toolchain, 'gen'))

    def test_absolute(self):
        for paths, toolchain in self._paths_and_toolchain_name:
            label = Label(paths, '//foo/bar:baz')
            self.assertEqual(label.name, 'baz')
            self.assertEqual(label.dir, ROOT.joinpath('foo/bar'))
            self.assertEqual(label.out_dir,
                             ROOT.joinpath('out', toolchain, 'obj/foo/bar'))
            self.assertEqual(label.gen_dir,
                             ROOT.joinpath('out', toolchain, 'gen/foo/bar'))

    def test_absolute_implicit_target(self):
        for paths, toolchain in self._paths_and_toolchain_name:
            label = Label(paths, '//foo/bar')
            self.assertEqual(label.name, 'bar')
            self.assertEqual(label.dir, ROOT.joinpath('foo/bar'))
            self.assertEqual(label.out_dir,
                             ROOT.joinpath('out', toolchain, 'obj/foo/bar'))
            self.assertEqual(label.gen_dir,
                             ROOT.joinpath('out', toolchain, 'gen/foo/bar'))

    def test_relative(self):
        for paths, toolchain in self._paths_and_toolchain_name:
            label = Label(paths, ':tgt')
            self.assertEqual(label.name, 'tgt')
            self.assertEqual(label.dir, ROOT.joinpath('some/cwd'))
            self.assertEqual(label.out_dir,
                             ROOT.joinpath('out', toolchain, 'obj/some/cwd'))
            self.assertEqual(label.gen_dir,
                             ROOT.joinpath('out', toolchain, 'gen/some/cwd'))

    def test_relative_subdir(self):
        for paths, toolchain in self._paths_and_toolchain_name:
            label = Label(paths, 'tgt')
            self.assertEqual(label.name, 'tgt')
            self.assertEqual(label.dir, ROOT.joinpath('some/cwd/tgt'))
            self.assertEqual(
                label.out_dir,
                ROOT.joinpath('out', toolchain, 'obj/some/cwd/tgt'))
            self.assertEqual(
                label.gen_dir,
                ROOT.joinpath('out', toolchain, 'gen/some/cwd/tgt'))

    def test_relative_parent_dir(self):
        for paths, toolchain in self._paths_and_toolchain_name:
            label = Label(paths, '..:tgt')
            self.assertEqual(label.name, 'tgt')
            self.assertEqual(label.dir, ROOT.joinpath('some'))
            self.assertEqual(label.out_dir,
                             ROOT.joinpath('out', toolchain, 'obj/some'))
            self.assertEqual(label.gen_dir,
                             ROOT.joinpath('out', toolchain, 'gen/some'))


class ResolvePathTest(unittest.TestCase):
    """Tests GN path resolution."""
    def test_resolve_absolute(self):
        self.assertEqual(TEST_PATHS.resolve('//'), TEST_PATHS.root)
        self.assertEqual(TEST_PATHS.resolve('//foo/bar'),
                         TEST_PATHS.root / 'foo' / 'bar')
        self.assertEqual(TEST_PATHS.resolve('//foo/../baz'),
                         TEST_PATHS.root / 'baz')

    def test_resolve_relative(self):
        self.assertEqual(TEST_PATHS.resolve(''), TEST_PATHS.cwd)
        self.assertEqual(TEST_PATHS.resolve('foo'), TEST_PATHS.cwd / 'foo')
        self.assertEqual(TEST_PATHS.resolve('..'), TEST_PATHS.root / 'some')


NINJA_EXECUTABLE = '''\
defines =
framework_dirs =
include_dirs = -I../fake_module/public
cflags = -g3 -Og -fdiagnostics-color -g -fno-common -Wall -Wextra -Werror
cflags_c =
cflags_cc = -fno-rtti -Wnon-virtual-dtor -std=c++17 -Wno-register
target_output_name = this_is_a_test

build fake_toolchain/obj/fake_module/fake_test.fake_test.cc.o: fake_toolchain_cxx ../fake_module/fake_test.cc
build fake_toolchain/obj/fake_module/fake_test.fake_test_c.c.o: fake_toolchain_cc ../fake_module/fake_test_c.c

build fake_toolchain/obj/fake_module/test/fake_test.elf fake_toolchain/obj/fake_module/test/fake_test.map: fake_toolchain_link fake_toolchain/obj/fake_module/fake_test.fake_test.cc.o fake_toolchain/obj/fake_module/fake_test.fake_test_c.c.o
  ldflags = -Og -fdiagnostics-color
  libs =
  frameworks =
  output_extension =
  output_dir = host_clang_debug/obj/fake_module/test
'''

_SOURCE_SET_TEMPLATE = '''\
defines =
framework_dirs =
include_dirs = -I../fake_module/public
cflags = -g3 -Og -fdiagnostics-color -g -fno-common -Wall -Wextra -Werror
cflags_c =
cflags_cc = -fno-rtti -Wnon-virtual-dtor -std=c++17 -Wno-register
target_output_name = this_is_a_test

build fake_toolchain/obj/fake_module/fake_source_set.file_a.cc.o: fake_toolchain_cxx ../fake_module/file_a.cc
build fake_toolchain/obj/fake_module/fake_source_set.file_b.c.o: fake_toolchain_cc ../fake_module/file_b.c

build {path} fake_toolchain/obj/fake_module/fake_source_set.file_a.cc.o fake_toolchain/obj/fake_module/fake_source_set.file_b.c.o
  ldflags = -Og -fdiagnostics-color -Wno-error=deprecated
  libs =
  frameworks =
  output_extension =
  output_dir = host_clang_debug/obj/fake_module
'''

# GN originally used empty .stamp files to mark the completion of a group of
# dependencies. GN switched to using 'phony' Ninja targets instead, which don't
# require creating a new file.
_PHONY_BUILD_PATH = 'fake_toolchain/phony/fake_module/fake_source_set: phony'
_STAMP_BUILD_PATH = 'fake_toolchain/obj/fake_module/fake_source_set.stamp:'

NINJA_SOURCE_SET = _SOURCE_SET_TEMPLATE.format(path=_PHONY_BUILD_PATH)
NINJA_SOURCE_SET_STAMP = _SOURCE_SET_TEMPLATE.format(path=_STAMP_BUILD_PATH)


def _create_ninja_files(source_set: str) -> tuple:
    tempdir = tempfile.TemporaryDirectory(prefix='pw_build_test_')

    module = Path(tempdir.name, 'out', 'fake_toolchain', 'obj', 'fake_module')
    os.makedirs(module)
    module.joinpath('fake_test.ninja').write_text(NINJA_EXECUTABLE)
    module.joinpath('fake_source_set.ninja').write_text(source_set)
    module.joinpath('fake_no_objects.ninja').write_text('\n')

    outdir = Path(tempdir.name, 'out', 'fake_toolchain', 'obj', 'fake_module')

    paths = GnPaths(root=Path(tempdir.name),
                    build=Path(tempdir.name, 'out'),
                    cwd=Path(tempdir.name, 'some', 'module'),
                    toolchain='//tools:fake_toolchain')

    return tempdir, outdir, paths


class TargetTest(unittest.TestCase):
    """Tests querying GN target information."""
    def setUp(self):
        self._tempdir, self._outdir, self._paths = _create_ninja_files(
            NINJA_SOURCE_SET)

        self._rel_outdir = self._outdir.relative_to(self._paths.build)

    def tearDown(self):
        self._tempdir.cleanup()

    def test_source_set_artifact(self):
        target = TargetInfo(self._paths, '//fake_module:fake_source_set')
        self.assertTrue(target.generated)
        self.assertIsNone(target.artifact)

    def test_source_set_object_files(self):
        target = TargetInfo(self._paths, '//fake_module:fake_source_set')
        self.assertTrue(target.generated)
        self.assertEqual(
            set(target.object_files), {
                self._rel_outdir / 'fake_source_set.file_a.cc.o',
                self._rel_outdir / 'fake_source_set.file_b.c.o',
            })

    def test_executable_object_files(self):
        target = TargetInfo(self._paths, '//fake_module:fake_test')
        self.assertEqual(
            set(target.object_files), {
                self._rel_outdir / 'fake_test.fake_test.cc.o',
                self._rel_outdir / 'fake_test.fake_test_c.c.o',
            })

    def test_executable_artifact(self):
        target = TargetInfo(self._paths, '//fake_module:fake_test')
        self.assertEqual(target.artifact,
                         self._rel_outdir / 'test' / 'fake_test.elf')

    def test_non_existent_target(self):
        target = TargetInfo(self._paths,
                            '//fake_module:definitely_not_a_real_target')
        self.assertFalse(target.generated)
        self.assertIsNone(target.artifact)

    def test_non_existent_toolchain(self):
        target = TargetInfo(
            self._paths, '//fake_module:fake_source_set(//not_a:toolchain)')
        self.assertFalse(target.generated)
        self.assertIsNone(target.artifact)


class StampTargetTest(TargetTest):
    """Test with old-style .stamp files instead of phony Ninja targets."""
    def setUp(self):
        self._tempdir, self._outdir, self._paths = _create_ninja_files(
            NINJA_SOURCE_SET_STAMP)

        self._rel_outdir = self._outdir.relative_to(self._paths.build)


class ExpandExpressionsTest(unittest.TestCase):
    """Tests expansion of expressions like <TARGET_FILE(//foo)>."""
    def setUp(self):
        self._tempdir, self._outdir, self._paths = _create_ninja_files(
            NINJA_SOURCE_SET)

    def tearDown(self):
        self._tempdir.cleanup()

    def _path(self, *segments: str, create: bool = False) -> str:
        path = Path(self._outdir, *segments)
        if create:
            os.makedirs(path.parent)
            path.touch()
        else:
            assert not path.exists()
        return str(path.relative_to(self._paths.build))

    def test_empty(self):
        self.assertEqual(list(expand_expressions(self._paths, '')), [''])

    def test_no_expressions(self):
        self.assertEqual(list(expand_expressions(self._paths, 'foobar')),
                         ['foobar'])
        self.assertEqual(
            list(expand_expressions(self._paths, '<NOT_AN_EXPRESSION()>')),
            ['<NOT_AN_EXPRESSION()>'])

    def test_incomplete_expression(self):
        for incomplete_expression in [
                '<TARGET_FILE(',
                '<TARGET_FILE(//foo)',
                '<TARGET_FILE(//foo>',
                '<TARGET_FILE(//foo) >',
                '--arg=<TARGET_FILE_IF_EXISTS(//foo) Hello>',
        ]:
            with self.assertRaises(ExpressionError):
                expand_expressions(self._paths, incomplete_expression)

    def test_target_file(self):
        path = self._path('test', 'fake_test.elf')

        for expr, expected in [
            ('<TARGET_FILE(//fake_module:fake_test)>', path),
            ('--arg=<TARGET_FILE(//fake_module:fake_test)>', f'--arg={path}'),
            ('--argument=<TARGET_FILE(//fake_module:fake_test)>;'
             '<TARGET_FILE(//fake_module:fake_test)>',
             f'--argument={path};{path}'),
        ]:
            self.assertEqual(list(expand_expressions(self._paths, expr)),
                             [expected])

    def test_target_objects_no_target_file(self):
        with self.assertRaisesRegex(ExpressionError, 'no output file'):
            expand_expressions(self._paths,
                               '<TARGET_FILE(//fake_module:fake_source_set)>')

    def test_target_file_non_existent_target(self):
        with self.assertRaisesRegex(ExpressionError, 'generated'):
            expand_expressions(self._paths, '<TARGET_FILE(//not_real:abc123)>')

    def test_target_file_if_exists(self):
        path = self._path('test', 'fake_test.elf', create=True)

        for expr, expected in [
            ('<TARGET_FILE_IF_EXISTS(//fake_module:fake_test)>', path),
            ('--arg=<TARGET_FILE_IF_EXISTS(//fake_module:fake_test)>',
             f'--arg={path}'),
            ('--argument=<TARGET_FILE_IF_EXISTS(//fake_module:fake_test)>;'
             '<TARGET_FILE_IF_EXISTS(//fake_module:fake_test)>',
             f'--argument={path};{path}'),
        ]:
            self.assertEqual(list(expand_expressions(self._paths, expr)),
                             [expected])

    def test_target_file_if_exists_arg_omitted(self):
        for expr in [
                '<TARGET_FILE_IF_EXISTS(//fake_module:fake_test)>',
                '<TARGET_FILE_IF_EXISTS(//fake_module:fake_test(fake)>',
                '<TARGET_FILE_IF_EXISTS(//not_a_module:nothing)>',
                '--arg=<TARGET_FILE_IF_EXISTS(//fake_module:fake_test)>',
                '--argument=<TARGET_FILE_IF_EXISTS(//fake_module:fake_test)>;'
                '<TARGET_FILE_IF_EXISTS(//fake_module:fake_test)>',
        ]:
            self.assertEqual(list(expand_expressions(self._paths, expr)), [])

    def test_target_file_if_exists_error_if_never_has_artifact(self):
        for expr in [
                '<TARGET_FILE_IF_EXISTS(//fake_module:fake_source_set)>'
                'bar=<TARGET_FILE_IF_EXISTS(//fake_module:fake_source_set)>'
                '<TARGET_FILE_IF_EXISTS(//fake_module:fake_no_objects)>',
                '--foo=<TARGET_FILE_IF_EXISTS(//fake_module:fake_no_objects)>',
        ]:
            with self.assertRaises(ExpressionError):
                expand_expressions(self._paths, expr)

    def test_target_objects(self):
        self.assertEqual(
            set(
                expand_expressions(
                    self._paths,
                    '<TARGET_OBJECTS(//fake_module:fake_source_set)>')), {
                        self._path('fake_source_set.file_a.cc.o'),
                        self._path('fake_source_set.file_b.c.o')
                    })
        self.assertEqual(
            set(
                expand_expressions(
                    self._paths, '<TARGET_OBJECTS(//fake_module:fake_test)>')),
            {
                self._path('fake_test.fake_test.cc.o'),
                self._path('fake_test.fake_test_c.c.o')
            })

    def test_target_objects_no_objects(self):
        self.assertEqual(
            list(
                expand_expressions(
                    self._paths,
                    '<TARGET_OBJECTS(//fake_module:fake_no_objects)>')), [])

    def test_target_objects_other_content_in_arg(self):
        for arg in [
                '--foo=<TARGET_OBJECTS(//fake_module:fake_no_objects)>',
                '<TARGET_OBJECTS(//fake_module:fake_no_objects)>bar',
                '--foo<TARGET_OBJECTS(//fake_module:fake_no_objects)>bar',
                '<TARGET_OBJECTS(//fake_module:fake_no_objects)>'
                '<TARGET_OBJECTS(//fake_module:fake_no_objects)>',
                '<TARGET_OBJECTS(//fake_module:fake_source_set)>'
                '<TARGET_OBJECTS(//fake_module:fake_source_set)>',
        ]:
            with self.assertRaises(ExpressionError):
                expand_expressions(self._paths, arg)

    def test_target_objects_non_existent_target(self):
        with self.assertRaisesRegex(ExpressionError, 'generated'):
            expand_expressions(self._paths, '<TARGET_OBJECTS(//not_real)>')


class StampExpandExpressionsTest(TargetTest):
    """Test with old-style .stamp files instead of phony Ninja targets."""
    def setUp(self):
        self._tempdir, self._outdir, self._paths = _create_ninja_files(
            NINJA_SOURCE_SET_STAMP)

        self._rel_outdir = self._outdir.relative_to(self._paths.build)


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