#!/usr/bin/env python
#
# Copyright (C) 2018 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.
#
"""Does test_ldflags_to_sanitizers stuff."""
from __future__ import absolute_import
import unittest

try:
    from StringIO import StringIO  # type: ignore
except ImportError:
    from io import StringIO

from build.ldflags_to_sanitizers import argv_to_module_arg_lists
from build.ldflags_to_sanitizers import main as ldflags_main
from build.ldflags_to_sanitizers import sanitizers_from_args


class LdflagsToSanitizersTest(unittest.TestCase):
    def test_sanitizers_from_args_no_sanitize_args(self) -> None:
        """Tests that we don't identify sanitizers when there are none."""
        self.assertListEqual([], sanitizers_from_args([]))
        self.assertListEqual([], sanitizers_from_args(['foo', 'bar']))

    def test_sanitizers_from_args_enabled_sanitizers(self) -> None:
        """Tests that we find enabled sanitizers."""
        self.assertListEqual(
            ['address'], sanitizers_from_args(['-fsanitize=address']))
        self.assertListEqual(
            ['address'], sanitizers_from_args(['-fsanitize=address', 'foo']))
        self.assertListEqual(
            ['address', 'undefined'],
            sanitizers_from_args(
                ['-fsanitize=address', '-fsanitize=undefined']))
        self.assertListEqual(
            ['address', 'undefined'],
            sanitizers_from_args(['-fsanitize=address,undefined']))
        self.assertListEqual(
            ['address', 'undefined'],
            sanitizers_from_args(['-fsanitize=address,undefined', 'foo']))

    def test_sanitizers_from_args_disabled_sanitizers(self) -> None:
        """Tests that we don't find disabled sanitizers."""
        self.assertListEqual([], sanitizers_from_args(
            ['-fno-sanitize=address']))
        self.assertListEqual([], sanitizers_from_args(
            ['-fno-sanitize=address', 'foo']))
        self.assertListEqual([], sanitizers_from_args(
            ['-fno-sanitize=address', '-fno-sanitize=undefined']))
        self.assertListEqual([], sanitizers_from_args(
            ['-fno-sanitize=address,undefined']))
        self.assertListEqual([], sanitizers_from_args(
            ['-fno-sanitize=address,undefined', 'foo']))

    def test_sanitizers_from_args_enabled_disabled_sanitizers(self) -> None:
        """Tests that we correctly identify only enabled sanitizers."""
        self.assertListEqual([], sanitizers_from_args(
            ['-fsanitize=address', '-fno-sanitize=address']))
        self.assertListEqual(['address'], sanitizers_from_args(
            ['-fsanitize=address', '-fno-sanitize=address',
             '-fsanitize=address']))
        self.assertListEqual([], sanitizers_from_args(
            ['-fsanitize=address', '-fno-sanitize=address',
             '-fsanitize=address', '-fno-sanitize=address']))
        self.assertListEqual(['undefined'], sanitizers_from_args(
            ['-fsanitize=address,undefined', '-fno-sanitize=address']))
        self.assertListEqual(['undefined'], sanitizers_from_args(
            ['-fsanitize=address', '-fsanitize=undefined',
             '-fno-sanitize=address']))

    def test_argv_to_module_arg_lists(self) -> None:
        """Tests that modules' arguments are properly identified."""
        self.assertTupleEqual(([], []), argv_to_module_arg_lists([]))
        self.assertTupleEqual((['foo'], []), argv_to_module_arg_lists(['foo']))

        self.assertTupleEqual(
            ([], [['foo', 'bar'], ['baz']]),
            argv_to_module_arg_lists(
                ['--module', 'foo', 'bar', '--module', 'baz']))

        self.assertTupleEqual(
            (['foo', 'bar'], [['baz']]),
            argv_to_module_arg_lists(['foo', 'bar', '--module', 'baz']))

    def test_main(self) -> None:
        """Test that the program itself works."""
        sio = StringIO()
        ldflags_main(
            ['ldflags_to_sanitizers.py', '-fsanitize=undefined', '--module',
             '-fsanitize=address,thread', '-fno-sanitize=thread',
             '--module', '-fsanitize=undefined'], sio)
        self.assertEqual('address undefined', sio.getvalue().strip())
