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

import mock
import os
import pytz
import shutil
import tempfile
import unittest

from mobly import logger


class LoggerTest(unittest.TestCase):
    """Verifies code in mobly.logger module.
    """
    def setUp(self):
        self.log_dir = tempfile.mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.log_dir)

    def test_epoch_to_log_line_timestamp(self):
        actual_stamp = logger.epoch_to_log_line_timestamp(1469134262116,
                                                          time_zone=pytz.utc)
        self.assertEqual("07-21 20:51:02.116", actual_stamp)

    def test_is_valid_logline_timestamp(self):
        self.assertTrue(
            logger.is_valid_logline_timestamp("06-21 17:44:42.336"))

    def test_is_valid_logline_timestamp_when_wrong_length(self):
        self.assertFalse(
            logger.is_valid_logline_timestamp("  06-21 17:44:42.336"))

    def test_is_valid_logline_timestamp_when_invalid_content(self):
        self.assertFalse(
            logger.is_valid_logline_timestamp("------------------"))

    @mock.patch('mobly.utils.create_alias')
    def test_create_latest_log_alias(self, mock_create_alias):
        logger.create_latest_log_alias('fake_path', alias='latest')
        mock_create_alias.assert_called_once_with('fake_path', 'latest')

    @mock.patch('mobly.logger._setup_test_logger')
    @mock.patch('mobly.logger.create_latest_log_alias')
    def test_setup_test_logger_creates_log_alias(self,
                                                 mock_create_latest_log_alias,
                                                 mock__setup_test_logger):
        logger.setup_test_logger(self.log_dir)
        mock__setup_test_logger.assert_called_once_with(self.log_dir, None)
        mock_create_latest_log_alias.assert_called_once_with(self.log_dir,
                                                             alias='latest')

    @mock.patch('mobly.logger._setup_test_logger')
    @mock.patch('mobly.logger.create_latest_log_alias')
    def test_setup_test_logger_creates_log_alias_with_custom_value(
            self, mock_create_latest_log_alias, mock__setup_test_logger):
        mock_alias = mock.MagicMock()
        logger.setup_test_logger(self.log_dir, alias=mock_alias)

        mock_create_latest_log_alias.assert_called_once_with(self.log_dir,
                                                             alias=mock_alias)

    def test_sanitize_filename_when_valid(self):
        fake_filename = 'logcat.txt'
        expected_filename = 'logcat.txt'
        self.assertEqual(logger.sanitize_filename(fake_filename),
                         expected_filename)

    def test_sanitize_filename_when_valid_with_path(self):
        fake_filename = os.path.join('dir', 'logs', 'logcat.txt')
        expected_filename = os.path.join('dir', 'logs', 'logcat.txt')
        self.assertEqual(logger.sanitize_filename(fake_filename),
                         expected_filename)

    def test_sanitize_filename_when_random_spaces(self):
        fake_filename = 'log cat file.txt'
        expected_filename = 'log_cat_file.txt'
        self.assertEqual(logger.sanitize_filename(fake_filename),
                         expected_filename)

    def test_sanitize_filename_when_over_260_characters(self):
        fake_filename = 'l' * 300
        expected_filename = 'l' * 260
        self.assertEqual(len(logger.sanitize_filename(fake_filename)), 260)
        self.assertEqual(logger.sanitize_filename(fake_filename),
                         expected_filename)

    def test__sanitize_windows_filename_when_path_characters(self):
        fake_filename = '/\\'
        expected_filename = '__'
        self.assertEqual(logger._sanitize_windows_filename(fake_filename),
                         expected_filename)

    def test_sanitize_filename_when_specical_characters(self):
        fake_filename = '<>:"|?*\x00'
        expected_filename = '---_,,,0'
        self.assertEqual(logger.sanitize_filename(fake_filename),
                         expected_filename)

    def test_sanitize_filename_when_con(self):
        for fake_filename, expected_filename in [
            ('con', 'mobly_con'),
            ('CON', 'mobly_CON'),
            ('con.txt', 'mobly_con.txt'),
            ('connections.log', 'connections.log'),
        ]:
            self.assertEqual(logger.sanitize_filename(fake_filename),
                             expected_filename)

    def test_sanitize_filename_when_prn(self):
        for fake_filename, expected_filename in [
            ('prn', 'mobly_prn'),
            ('PRN', 'mobly_PRN'),
            ('prn.txt', 'mobly_prn.txt'),
            ('prnters.log', 'prnters.log'),
        ]:
            self.assertEqual(logger.sanitize_filename(fake_filename),
                             expected_filename)

    def test_sanitize_filename_when_aux(self):
        for fake_filename, expected_filename in [
            ('aux', 'mobly_aux'),
            ('AUX', 'mobly_AUX'),
            ('aux.txt', 'mobly_aux.txt'),
            ('auxiliaries.log', 'auxiliaries.log'),
        ]:
            self.assertEqual(logger.sanitize_filename(fake_filename),
                             expected_filename)

    def test_sanitize_filename_when_nul(self):
        for fake_filename, expected_filename in [
            ('nul', 'mobly_nul'),
            ('NUL', 'mobly_NUL'),
            ('nul.txt', 'mobly_nul.txt'),
            ('nullptrs.log', 'nullptrs.log'),
        ]:
            self.assertEqual(logger.sanitize_filename(fake_filename),
                             expected_filename)

    def test_sanitize_filename_when_com(self):
        for fake_filename, expected_filename in [
            ('com', 'com'),
            ('COM0', 'mobly_COM0'),
            ('com1', 'mobly_com1'),
            ('COM2', 'mobly_COM2'),
            ('com3', 'mobly_com3'),
            ('COM4', 'mobly_COM4'),
            ('com5', 'mobly_com5'),
            ('COM6', 'mobly_COM6'),
            ('com7', 'mobly_com7'),
            ('COM8', 'mobly_COM8'),
            ('com9', 'mobly_com9'),
            ('com0.log', 'mobly_com0.log'),
            ('com0files.log', 'com0files.log'),
        ]:
            self.assertEqual(logger.sanitize_filename(fake_filename),
                             expected_filename)

    def test_sanitize_filename_when_lpt(self):
        for fake_filename, expected_filename in [
            ('lpt', 'lpt'),
            ('LPT0', 'mobly_LPT0'),
            ('lpt1', 'mobly_lpt1'),
            ('LPT2', 'mobly_LPT2'),
            ('lpt3', 'mobly_lpt3'),
            ('LPT4', 'mobly_LPT4'),
            ('lpt5', 'mobly_lpt5'),
            ('LPT6', 'mobly_LPT6'),
            ('lpt7', 'mobly_lpt7'),
            ('LPT8', 'mobly_LPT8'),
            ('lpt9', 'mobly_lpt9'),
            ('lpt3.txt', 'mobly_lpt3.txt'),
            ('lpt3_file.txt', 'lpt3_file.txt'),
        ]:
            self.assertEqual(logger.sanitize_filename(fake_filename),
                             expected_filename)

    def test_sanitize_filename_when_ends_with_space(self):
        fake_filename = 'logcat.txt '
        expected_filename = 'logcat.txt_'
        self.assertEqual(logger.sanitize_filename(fake_filename),
                         expected_filename)

    def test_sanitize_filename_when_ends_with_period(self):
        fake_filename = 'logcat.txt.'
        expected_filename = 'logcat.txt_'
        self.assertEqual(logger.sanitize_filename(fake_filename),
                         expected_filename)


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