# Copyright (C) 2018 Google Inc.
#
# 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.

"""Test using Fire via `python -m fire`."""

import os
import tempfile

from afire import __main__
from afire import testutils


class MainModuleTest(testutils.BaseTestCase):
    """Tests to verify the behavior of __main__ (python -m fire)."""

    def testNameSetting(self):
        # Confirm one of the usage lines has the gettempdir member.
        with self.assertOutputMatches("gettempdir"):
            __main__.main(["__main__.py", "tempfile"])

    def testArgPassing(self):
        expected = os.path.join("part1", "part2", "part3")
        with self.assertOutputMatches("%s\n" % expected):
            __main__.main(["__main__.py", "os.path", "join", "part1", "part2", "part3"])
        with self.assertOutputMatches("%s\n" % expected):
            __main__.main(["__main__.py", "os", "path", "-", "join", "part1", "part2", "part3"])


class MainModuleFileTest(testutils.BaseTestCase):
    """Tests to verify correct import behavior for file executables."""

    def setUp(self):
        super(MainModuleFileTest, self).setUp()
        self.file = tempfile.NamedTemporaryFile(suffix=".py")  # pylint: disable=consider-using-with
        self.file.write(b"class Foo:\n  def double(self, n):\n    return 2 * n\n")
        self.file.flush()

        self.file2 = tempfile.NamedTemporaryFile()  # pylint: disable=consider-using-with

    def testFileNameFire(self):
        # Confirm that the file is correctly imported and doubles the number.
        with self.assertOutputMatches("4"):
            __main__.main(["__main__.py", self.file.name, "Foo", "double", "--n", "2"])

    def testFileNameFailure(self):
        # Confirm that an existing file without a .py suffix raises a ValueError.
        with self.assertRaises(ValueError):
            __main__.main(["__main__.py", self.file2.name, "Foo", "double", "--n", "2"])

    def testFileNameModuleDuplication(self):
        # Confirm that a file that masks a module still loads the module.
        with self.assertOutputMatches("gettempdir"):
            dirname = os.path.dirname(self.file.name)
            with testutils.ChangeDirectory(dirname):
                with open("tempfile", "w"):
                    __main__.main(
                        [
                            "__main__.py",
                            "tempfile",
                        ]
                    )

                os.remove("tempfile")

    def testFileNameModuleFileFailure(self):
        # Confirm that an invalid file that masks a non-existent module fails.
        with self.assertRaisesRegex(
            ValueError, r"Fire can only be called on \.py files\."
        ):  # pylint: disable=line-too-long,  # pytype: disable=attribute-error
            dirname = os.path.dirname(self.file.name)
            with testutils.ChangeDirectory(dirname):
                with open("foobar", "w"):
                    __main__.main(
                        [
                            "__main__.py",
                            "foobar",
                        ]
                    )

                os.remove("foobar")


if __name__ == "__main__":
    testutils.main()
