<commit_before>#
# Copyright 2012-2013 Ghent University
#
# This file is part of vsc-base,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://vscentrum.be/nl/en),
# the Hercules foundation (http://www.herculesstichting.be/in_English)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# http://github.com/hpcugent/vsc-base
#
# vsc-base is free software: you can redistribute it and/or modify
# it under the terms of the GNU Library General Public License as
# published by the Free Software Foundation, either version 2 of
# the License, or (at your option) any later version.
#
# vsc-base is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with vsc-base. If not, see <http://www.gnu.org/licenses/>.
#
"""
Unit tests for generaloption

@author: <NAME> (Ghent University)
"""
import datetime
import logging
import os
import re
import tempfile
from tempfile import NamedTemporaryFile
from unittest import TestCase, TestLoader, main

from vsc.utils import fancylogger
from vsc.utils.generaloption import GeneralOption, HELP_OUTPUT_FORMATS
from vsc.utils.missing import shell_quote, shell_unquote
from vsc.utils.optcomplete import gen_cmdline
from vsc.utils.run import run_simple
from vsc.utils.testing import EnhancedTestCase

_init_configfiles = ['/not/a/real/configfile']

class TestOption1(GeneralOption):
    """Create simple test class"""
    DEFAULT_LOGLEVEL = 'INFO'
    DEFAULT_CONFIGFILES = _init_configfiles[:]
    def base_options(self):
        """Make base options"""
        self._opts_base = {
            "base":("Long and short base option", None, "store_true", False, 'b'),
            "longbase":("Long-only base option", None, "store_true", True),
            "justatest":("Another long based option", None, "store_true", True),
            "store":("Store option", None, "store", None),
            "store-with-dash":("Store option with dash in name", None, "store", None),
            "aregexopt":("A regex option", None, "regex", None),
            }
        descr = ["Base", "Base level of options"]

        prefix = None  # base, no prefixes
        self.add_group_parser(self._opts_base, descr, prefix=prefix)

    def level1_options(self):
        """Make the level1 related options"""
        self._opts_level1 = {
            "level":("Long and short option", None, "store_true", False, 'l'),
            "longlevel"  :("Long-only level option", None, "store_true", True),
            "prefix-and-dash":("Test combination of prefix and dash", None, "store", True),
            }
        descr = ["Level1", "1 higher level of options"]

        prefix = 'level'
        self.add_group_parser(self._opts_level1, descr, prefix=prefix)

    def ext_options(self):
        """Make ExtOption options"""
        self._opts_ext = {
            "extend":("Test action extend", None, 'extend', None),
            "extenddefault":("Test action extend with default set", None, 'extend', ['zero', 'one']),
            # add / add_first
            "add":("Test action add", None, 'add', None),
            "add-default":("Test action add", None, 'add', 'now'),
            "add-list":("Test action add", 'strlist', 'add', None),
            "add-list-default":("Test action add", 'strlist', 'add', ['now']),
            "add-list-first":("Test action add", 'strlist', 'add_first', ['now']),
            "add-list-flex":('Test strlist type with add_flex', 'strlist', 'add_flex', ['x', 'y']),
            "add-pathlist-flex":('Test strlist type with add_flex', 'pathlist', 'add_flex', ['p2', 'p3']),

            # date
            "date":('Test action datetime.date', None, 'date', None),
            "datetime":('Test action datetime.datetime', None, 'datetime', None),
            "optional":('Test action optional', None, 'store_or_None', 'DEFAULT', 'o'),
            # default value is not part of choice!
            "optionalchoice":('Test action optional', 'choice', 'store_or_None', 'CHOICE0', ['CHOICE1', 'CHOICE2']),
            # list type
            "strlist":('Test strlist type', 'strlist', 'store', ['x']),
            "strtuple":('Test strtuple type', 'strtuple', 'store', ('x',)),
            "pathlist":('Test pathlist type', 'pathlist', 'store', ['x']),
            "pathtuple":('Test pathtuple type', 'pathtuple', 'store', ('x',)),

            "pathliststorenone":('Test pathlist type with store_or_None', 'pathlist', 'store_or_None', ['x']),
            "pathliststorenone2":('Test pathlist type with store_or_None (2nd attempt)', 'pathlist', 'store_or_None', ['x2']),

            }
        descr = ["ExtOption", "action from ExtOption"]

        prefix = 'ext'
        self.add_group_parser(self._opts_ext, descr, prefix=prefix)


class GeneralOptionTest(EnhancedTestCase):
    """Tests for general option"""

    def test_help_short(self):
        """Generate short help message"""
        topt = TestOption1(go_args=['-h'],
                           go_nosystemexit=True,  # when printing help, optparse ends with sys.exit
                           go_columns=100,  # fix col size for reproducible unittest output
                           help_to_string=True,  # don't print to stdout, but to StingIO fh,
                           prog='optiontest1',  # generate as if called from generaloption.py
                           )
        self.assertEqual(topt.parser.help_to_file.getvalue().find("--level-longlevel"), -1,
                         "Long documentation not expanded in short help")

    def test_help(self):
        """Generate (long) help message"""
        topt = TestOption1(go_args=['--help'],
                           go_nosystemexit=True,
                           go_columns=100,
                           help_to_string=True,
                           prog='optiontest1',
                           )
        helptxt = topt.parser.help_to_file.getvalue()
        self.assertTrue(helptxt.find("--level-longlevel") > -1, "Long documentation expanded in long help")
        # default format should be textual output
        self.assertTrue(helptxt.startswith('Usage'))


    def test_help_long(self):
        """Generate long help message"""
        topt = TestOption1(go_args=['-H'],
                           go_nosystemexit=True,
                           go_columns=100,
                           help_to_string=True,
                           prog='optiontest1',
                           )

        self.assertTrue(topt.parser.help_to_file.getvalue().find("--level-longlevel") > -1)

    def test_help_outputformats(self):
        """Generate (long) rst help message"""
        for choice in HELP_OUTPUT_FORMATS:
            topt = TestOption1(go_args=['--help=%s' % choice],
                               go_nosystemexit=True,
                               go_columns=100,
                               help_to_string=True,
                               prog='optiontest1',
                              )

    def test_help_confighelp(self):
        """Generate long help message"""
        topt = TestOption1(go_args=['--confighelp'],
                           go_nosystemexit=True,
                           go_columns=100,<commit_msg>enhance tests for help options<commit_after>#
# Copyright 2012-2013 Ghent University
#
# This file is part of vsc-base,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://vscentrum.be/nl/en),
# the Hercules foundation (http://www.herculesstichting.be/in_English)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# http://github.com/hpcugent/vsc-base
#
# vsc-base is free software: you can redistribute it and/or modify
# it under the terms of the GNU Library General Public License as
# published by the Free Software Foundation, either version 2 of
# the License, or (at your option) any later version.
#
# vsc-base is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with vsc-base. If not, see <http://www.gnu.org/licenses/>.
#
"""
Unit tests for generaloption

@author: <NAME> (Ghent University)
"""
import datetime
import logging
import os
import re
import tempfile
from tempfile import NamedTemporaryFile
from unittest import TestCase, TestLoader, main

from vsc.utils import fancylogger
from vsc.utils.generaloption import GeneralOption, HELP_OUTPUT_FORMATS
from vsc.utils.missing import shell_quote, shell_unquote
from vsc.utils.optcomplete import gen_cmdline
from vsc.utils.run import run_simple
from vsc.utils.testing import EnhancedTestCase

_init_configfiles = ['/not/a/real/configfile']

class TestOption1(GeneralOption):
    """Create simple test class"""
    DEFAULT_LOGLEVEL = 'INFO'
    DEFAULT_CONFIGFILES = _init_configfiles[:]
    def base_options(self):
        """Make base options"""
        self._opts_base = {
            "base":("Long and short base option", None, "store_true", False, 'b'),
            "longbase":("Long-only base option", None, "store_true", True),
            "justatest":("Another long based option", None, "store_true", True),
            "store":("Store option", None, "store", None),
            "store-with-dash":("Store option with dash in name", None, "store", None),
            "aregexopt":("A regex option", None, "regex", None),
            }
        descr = ["Base", "Base level of options"]

        prefix = None  # base, no prefixes
        self.add_group_parser(self._opts_base, descr, prefix=prefix)

    def level1_options(self):
        """Make the level1 related options"""
        self._opts_level1 = {
            "level":("Long and short option", None, "store_true", False, 'l'),
            "longlevel"  :("Long-only level option", None, "store_true", True),
            "prefix-and-dash":("Test combination of prefix and dash", None, "store", True),
            }
        descr = ["Level1", "1 higher level of options"]

        prefix = 'level'
        self.add_group_parser(self._opts_level1, descr, prefix=prefix)

    def ext_options(self):
        """Make ExtOption options"""
        self._opts_ext = {
            "extend":("Test action extend", None, 'extend', None),
            "extenddefault":("Test action extend with default set", None, 'extend', ['zero', 'one']),
            # add / add_first
            "add":("Test action add", None, 'add', None),
            "add-default":("Test action add", None, 'add', 'now'),
            "add-list":("Test action add", 'strlist', 'add', None),
            "add-list-default":("Test action add", 'strlist', 'add', ['now']),
            "add-list-first":("Test action add", 'strlist', 'add_first', ['now']),
            "add-list-flex":('Test strlist type with add_flex', 'strlist', 'add_flex', ['x', 'y']),
            "add-pathlist-flex":('Test strlist type with add_flex', 'pathlist', 'add_flex', ['p2', 'p3']),

            # date
            "date":('Test action datetime.date', None, 'date', None),
            "datetime":('Test action datetime.datetime', None, 'datetime', None),
            "optional":('Test action optional', None, 'store_or_None', 'DEFAULT', 'o'),
            # default value is not part of choice!
            "optionalchoice":('Test action optional', 'choice', 'store_or_None', 'CHOICE0', ['CHOICE1', 'CHOICE2']),
            # list type
            "strlist":('Test strlist type', 'strlist', 'store', ['x']),
            "strtuple":('Test strtuple type', 'strtuple', 'store', ('x',)),
            "pathlist":('Test pathlist type', 'pathlist', 'store', ['x']),
            "pathtuple":('Test pathtuple type', 'pathtuple', 'store', ('x',)),

            "pathliststorenone":('Test pathlist type with store_or_None', 'pathlist', 'store_or_None', ['x']),
            "pathliststorenone2":('Test pathlist type with store_or_None (2nd attempt)', 'pathlist', 'store_or_None', ['x2']),

            }
        descr = ["ExtOption", "action from ExtOption"]

        prefix = 'ext'
        self.add_group_parser(self._opts_ext, descr, prefix=prefix)


class GeneralOptionTest(EnhancedTestCase):
    """Tests for general option"""

    def test_help_short(self):
        """Generate short help message"""
        topt = TestOption1(go_args=['-h'],
                           go_nosystemexit=True,  # when printing help, optparse ends with sys.exit
                           go_columns=100,  # fix col size for reproducible unittest output
                           help_to_string=True,  # don't print to stdout, but to StingIO fh,
                           prog='optiontest1',  # generate as if called from generaloption.py
                           )
        helptxt = topt.parser.help_to_file.getvalue()
        self.assertEqual(helptxt.find("--level-longlevel"), -1, "Long documentation not expanded in short help")

    def test_help(self):
        """Generate (long) help message"""
        topt = TestOption1(go_args=['--help'],
                           go_nosystemexit=True,
                           go_columns=100,
                           help_to_string=True,
                           prog='optiontest1',
                           )
        helptxt = topt.parser.help_to_file.getvalue()

        # default format should be textual output
        self.assertTrue(helptxt.startswith('Usage'))

        self.assertTrue(helptxt.find("--level-longlevel") > -1, "Long documentation expanded in long help")

    def test_help_long(self):
        """Generate long help message"""
        topt = TestOption1(go_args=['-H'],
                           go_nosystemexit=True,
                           go_columns=100,
                           help_to_string=True,
                           prog='optiontest1',
                           )

        helptxt = topt.parser.help_to_file.getvalue()
        self.assertTrue(helptxt.find("--level-longlevel") > -1, "Long documentation expanded in long help")

    def test_help_outputformats(self):
        """Generate (long) rst help message"""
        for output_format in HELP_OUTPUT_FORMATS:
            topt = TestOption1(go_args=['--help=%s' % output_format],
                               go_nosystemexit=True,
                               go_columns=100,
                               help_to_string=True,
                               prog='optiontest1',
                              )
            helptxt = topt.parser.help_to_file.getvalue()
            if output_format == 'short':
                self.assertEqual(helptxt.find("--level-longlevel"), -1, "Long documentation not expanded in short help")
            elif output_format == 'config':
                self.assertTrue(helptxt.find("#level-longlevel") > -1, "Configuration option in config help")
            else:
                self.assertTrue(helptxt.find("--level-longlevel") > -1, "Long documentation expanded in long help (format: %s)" % output_format)

    def test_help_confighelp(self):
        """Generate long help message"""
        topt = TestOption1(go_args=['--confighelp'],
                           go_nosystemexit=True,
                           go_columns=100,
{'fraction_non_alphanumeric': 0.1297632611723003, 'fraction_numerical': 0.0066464109380934295, 'mean_word_length': 2.4646929824561403, 'pattern_counts': {'":': 54, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '731699', 'n_tokens_mistral': 4535, 'n_tokens_neox': 4433, 'n_words': 1261}