# Copyright (c) 2013-2020, SIB - Swiss Institute of Bioinformatics and
#                          Biozentrum - University of Basel
# 
# 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 unittest
import ost
from promod3.core import helper

# setting up an OST LogSink to capture error messages
class _FetchLog(ost.LogSink):
    def __init__(self):
        ost.LogSink.__init__(self)
        self.messages = dict()

    def LogMessage(self, message, severity):
        levels = ['ERROR', 'WARNING', 'SCRIPT', 'INFO', 'VERBOSE', 'DEBUG',
                  'TRACE']
        level = levels[severity]
        if not level in list(self.messages.keys()):
            self.messages[level] = list()
        self.messages[level].append(message.strip())

class HelperTests(unittest.TestCase):
    def testFileExistsTrue(self):
        # test that checking for existing files works like a charm
        helper.FileExists('Helper test', 1, 'test_helper.py')
        self.assertTrue(True)

    def testFileExistsFalse(self):
        # test that missing file leads to abortion
        log = _FetchLog()
        ost.PushLogSink(log)
        with self.assertRaises(SystemExit) as ecd:
            helper.FileExists('Helper test', 28, '')
        self.assertEqual(ecd.exception.code, 28)
        self.assertEqual(log.messages['ERROR'][0],
                         'Helper test file does not exist:')

    def testFileExtensionTrueNgz(self):
        # most basic test: extension supported, no gzip mode
        # this also checks, that the 'gzip' param is 'False' by default by not
        # providing it
        name, ext = helper.FileExtension('Helper test', 1,
                                         'test_helper.py', ['py'])
        self.assertEqual('test_helper', name)
        self.assertEqual('py', ext)

    def testFileExtensionTrueIgz(self):
        # extension supported, in gzip mode but without gzip extension
        name, ext, is_gz = helper.FileExtension('Helper test', 1,
                                                'test_helper.py', ['py'],
                                                gzip=True)
        self.assertEqual('test_helper', name)
        self.assertEqual('py', ext)
        self.assertFalse(is_gz)

    def testFileExtensionTrueIIgz(self):
        # extension supported, in gz mode
        name, ext, is_gz = helper.FileExtension('Helper test', 1,
                                                'data/filewgzext.pdb.gz',
                                                ['pdb'], gzip=True)
        self.assertEqual('filewgzext', name)
        self.assertEqual('pdb', ext)
        self.assertTrue(is_gz)

    def testFileExtensionFalseNoExt(self):
        # make sure we fail on missing extension
        log = _FetchLog()
        ost.PushLogSink(log)
        with self.assertRaises(SystemExit) as ecd:
            _, _ = helper.FileExtension('Helper test', 27, 'noextension',
                                        ['py'])
        self.assertEqual(ecd.exception.code, 27)
        self.assertEqual(log.messages['ERROR'][0],
                         'Helper test file extension not supported: '+
                         'noextension. Allowed extensions are: py')

    def testFileExtensionFalseGZ(self):
        # make sure we fail outside gz mode if a gz extension is provided
        log = _FetchLog()
        ost.PushLogSink(log)
        with self.assertRaises(SystemExit) as ecd:
            _, _ = helper.FileExtension('Helper test', 26,
                                        'wrongname.gz', ['py'])
        self.assertEqual(ecd.exception.code, 26)
        self.assertEqual(log.messages['ERROR'][0],
                         'Helper test file extension not supported: '+
                         'wrongname.gz. Allowed extensions are: py')

    def testFileExtensionFalse(self):
        # check file name with unknown extension
        log = _FetchLog()
        ost.PushLogSink(log)
        with self.assertRaises(SystemExit) as ecd:
            _, _ = helper.FileExtension('Helper test', 25, 'unknown.ext',
                                        ['py'])
        self.assertEqual(ecd.exception.code, 25)
        self.assertEqual(log.messages['ERROR'][0],
                         'Helper test file extension not supported: '+
                         'unknown.ext. Allowed extensions are: py')

    def testMsgErrorAndExit(self):
        # check that we print a message and exit
        log = _FetchLog()
        ost.PushLogSink(log)
        with self.assertRaises(SystemExit) as ecd:
            helper.MsgErrorAndExit("FooBar", 42)
        self.assertEqual(ecd.exception.code, 42)
        self.assertEqual(log.messages['ERROR'][0], "FooBar")

    def testFileGzipFound(self):
        # check that we recognise gz extensions
        gzip = helper.FileGzip("GzipFound", 42, "gzipped_file.txt.gz")
        self.assertEqual(gzip, True)

    def testFileGzipNotFound(self):
        # check that we recognise non-gz extensions
        gzip = helper.FileGzip("GzipNotFound", 42, "gzipped_file.txt")
        self.assertEqual(gzip, False)

    def testFileGzipNotAllowed(self):
        # refuse Gzip
        log = _FetchLog()
        ost.PushLogSink(log)
        with self.assertRaises(SystemExit) as ecd:
            helper.FileGzip("GzipFound", 42, "gzipped_file.txt.gz",
                            allowed=False)
        self.assertEqual(ecd.exception.code, 42)
        self.assertEqual(log.messages['ERROR'][0], "GzipFound file in Gzip "+
                         "not supported: gzipped_file.txt.gz.")

if __name__ == "__main__":
    from ost import testutils
    testutils.RunTests()
