#
# Copyright (C) 2017 The Android Open Source Project
#
# 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 textwrap
import unittest

import build.gen_cygpath


class GetMountsTest(unittest.TestCase):
    def testSingleMount(self) -> None:
        mount_output = "C:/cygwin on / type ntfs (binary,auto)"
        self.assertEqual(
            [("/", "C:/cygwin")], build.gen_cygpath.get_mounts(mount_output)
        )

    def testCaseInsensitiveMount(self) -> None:
        mount_output = "C: on /cygdrive/c type ntfs"
        expected_output = [
            ("/cygdrive/c", "C:"),
            ("/cygdrive/C", "C:"),
        ]

        self.assertEqual(expected_output, build.gen_cygpath.get_mounts(mount_output))

    def testManyMounts(self) -> None:
        mount_output = textwrap.dedent(
            """\
            C:/cygwin/bin on /usr/bin type ntfs (binary,auto)
            C:/cygwin/lib on /usr/lib type ntfs (binary,auto)
            C:/cygwin on / type ntfs (binary,auto)
            C: on /cygdrive/c type ntfs (binary,posix=0,user,noumount,auto)
            D: on /cygdrive/d type udf (binary,posix=0,user,noumount,auto)
            """
        )

        expected_output = [
            ("/", "C:/cygwin"),
            ("/usr/bin", "C:/cygwin/bin"),
            ("/usr/lib", "C:/cygwin/lib"),
            ("/cygdrive/c", "C:"),
            ("/cygdrive/C", "C:"),
            ("/cygdrive/d", "D:"),
            ("/cygdrive/D", "D:"),
        ]

        self.assertEqual(expected_output, build.gen_cygpath.get_mounts(mount_output))


class MakeCygpathFunctionTest(unittest.TestCase):
    def testSingleMount(self) -> None:
        mounts = [("/", "C:/cygwin")]
        expected_output = "$(patsubst /%,C:/cygwin/%,\n$1)"

        self.assertEqual(
            expected_output, build.gen_cygpath.make_cygpath_function(mounts)
        )

    def testManyMounts(self) -> None:
        mounts = [
            ("/", "C:/cygwin"),
            ("/usr/bin", "C:/cygwin/bin"),
            ("/usr/lib", "C:/cygwin/lib"),
            ("/cygdrive/c", "C:"),
            ("/cygdrive/C", "C:"),
            ("/cygdrive/d", "D:"),
            ("/cygdrive/D", "D:"),
        ]

        expected_output = textwrap.dedent(
            """\
            $(patsubst /%,C:/cygwin/%,
            $(patsubst /usr/bin/%,C:/cygwin/bin/%,
            $(patsubst /usr/lib/%,C:/cygwin/lib/%,
            $(patsubst /cygdrive/c/%,C:/%,
            $(patsubst /cygdrive/C/%,C:/%,
            $(patsubst /cygdrive/d/%,D:/%,
            $(patsubst /cygdrive/D/%,D:/%,
            $1)))))))"""
        )

        self.assertEqual(
            expected_output, build.gen_cygpath.make_cygpath_function(mounts)
        )
