# Moovida - Home multimedia server
# Copyright (C) 2006-2009 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Moovida with Fluendo's plugins.
#
# The GPL part of Moovida is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Moovida" in the root directory of this distribution package
# for details on that license.

from twisted.trial.unittest import SkipTest, TestCase
from elisa.core.utils import misc
import os, platform
import random, string

class TestMisc(TestCase):

    def _random_string(self, length=10):
        return ''.join(random.sample(string.ascii_letters, length))

    def test_env_var_explode(self):
        var_name = self._random_string()
        
        os.environ[var_name] = ''
        self.assertEquals(misc.env_var_explode_list(var_name),
                          [])
        
        if platform.system() == 'Windows':
            os.environ[var_name] = 'test;bar'
            self.assertEquals(misc.env_var_explode_list(var_name),
                              ['test', 'bar'])
            os.environ[var_name] = 'test:bar'
            self.assertEquals(misc.env_var_explode_list(var_name),
                              ['test:bar',])
        else:
            os.environ[var_name] = 'test;bar'
            self.assertEquals(misc.env_var_explode_list(var_name),
                              ['test;bar',])
            os.environ[var_name] = 'test:bar'
            self.assertEquals(misc.env_var_explode_list(var_name),
                              ['test','bar'])
            
            
                           
    def test_env_var_expand(self):
        
        if platform.system() == 'Windows':
            raise SkipTest("Does not works under windows, need investigation")
        
        platform_type = platform.system().lower()

        var_name = self._random_string()
        
        os.environ[var_name] = 'test!'
        expanded = misc.env_var_expand('$%s' % var_name)
        self.assertEquals(expanded, 'test!')

        var_name2 = self._random_string()
        os.environ[var_name2] = 'test2'
        os.environ[var_name] = 'test:$%s' % var_name2
        expanded = misc.env_var_expand('$%s' % var_name)
        self.assertEquals(expanded, 'test:test2')

        if platform_type == 'windows':
            # TODO
            pass
        elif platform_type == 'linux':
            expanded = misc.env_var_expand('$HOME/Music')
            home = os.path.expanduser('~')
            self.assertEquals(expanded, os.path.join(home, 'Music'))
        
    def test_uncamelify(self):

        self.assertEquals(misc.un_camelify('F'), 'f')
        self.assertEquals(misc.un_camelify('f'), 'f')

        self.assertEquals(misc.un_camelify('FooBar'), 'foo_bar')
        self.assertEquals(misc.un_camelify('Foo Bar'), 'foo_bar')
        self.assertEquals(misc.un_camelify('fooBar'), 'foo_bar')


    def test_text_from_mappings_valid(self):
        """Test serialising mappings with a valid input"""
        mappings = [("key1", "value1"),
                    ("key2", "value2a"),
                    ("key2", "value2b")]
        serialised = ["key1 = value1", "key2 = value2a", "key2 = value2b", ""]
        serialised = misc.LINESEP.join(serialised)

        result = misc.text_from_mappings(mappings)
        self.assertEquals(result, serialised)

    def test_text_from_mappings_empty(self):
        """Test serialising mappings with an empty input"""
        mappings = []
        result = misc.text_from_mappings(mappings)
        self.assertEquals(result, "")

    def test_text_from_mappings_empty_key(self):
        """Test serialising mappings with an input containing an empty key
        Expected behaviour is to be very fault tolerant and let strange cases
        pass.
        """
        # empty keys are accepted
        mappings = [("key1", "value1"),
                    ("key2", "value2a"),
                    ("key2", "value2b"),
                    ("", "empty")]
        serialised = ["key1 = value1", "key2 = value2a", "key2 = value2b",
                      " = empty", ""]
        serialised = misc.LINESEP.join(serialised)

        result = misc.text_from_mappings(mappings)
        self.assertEquals(result, serialised)

    def test_text_from_mappings_extra_value(self):
        """Test serialising mappings with an input containing a triplet"""
        mappings = [("key1", "value1", "extra_value"),
                    ("key2", "value2a"),
                    ("key2", "value2b")]

        self.failUnlessRaises(ValueError, misc.text_from_mappings, mappings)

    def test_text_from_mappings_none(self):
        """Test serialising None object"""
        result = misc.text_from_mappings(None)
        self.assertEquals(result, "")

    def test_mappings_from_text_valid(self):
        """Test deserialising mappings with a valid input"""
        mappings = [("key1", "value1"),
                    ("key2", "value2a"),
                    ("key2", "value2b")]
        serialised = ["key1 = value1", "key2 = value2a", "key2 = value2b", ""]
        serialised = misc.LINESEP.join(serialised)

        result = misc.mappings_from_text(serialised)
        self.assertEquals(result, mappings)

    def test_mappings_from_text_empty(self):
        """Test deserialising mappings with an empty input"""
        serialised = ""
        result = misc.mappings_from_text(serialised)
        self.assertEquals(result, [])

    def test_mappings_from_text_empty_key(self):
        """Test deserialising mappings with an input containing an empty key
        Expected behaviour is to be very fault tolerant and let strange cases
        pass.
        """
        # empty keys are accepted
        serialised = ["key1 = value1", "key2 = value2a", "key2 = value2b",
                      " = empty", ""]
        serialised = misc.LINESEP.join(serialised)
        mappings = [("key1", "value1"),
                    ("key2", "value2a"),
                    ("key2", "value2b"),
                    ("", "empty")]

        result = misc.mappings_from_text(serialised)
        self.assertEquals(result, mappings)

    def test_mappings_from_text_none(self):
        """Test deserialising None object"""
        result = misc.mappings_from_text(None)
        self.assertEquals(result, [])

    def test_mappings_from_text_multiple(self):
        """Test deserialising a text with multiple assignments"""
        serialised = "key1 = value1 = blabla" + misc.LINESEP

        self.failUnlessRaises(ValueError, misc.mappings_from_text, serialised)

    def test_text_from_mappings_valid_roundtrip(self):
        """Test a complete round trip starting with a mappings"""
        mappings = [("key1", "value1"),
                    ("key2", "value2a"),
                    ("key2", "value2b")]
        text = misc.text_from_mappings(mappings)
        result = misc.mappings_from_text(text)
        self.assertEquals(result, mappings)


class TestRunFunctionalTests(TestCase):

    def setUp(self):
        self._orig_val = os.environ.get(misc.FUNCTIONAL_TESTS_STR, None)

    def tearDown(self):
        if self._orig_val is not None:
            os.environ[misc.FUNCTIONAL_TESTS_STR] = self._orig_val

        self._orig_val = None

    def test_not_set(self):
        if misc.FUNCTIONAL_TESTS_STR in os.environ:
            del os.environ[misc.FUNCTIONAL_TESTS_STR]

        self.assertRaises(SkipTest, misc.run_functional_tests_check)

    def test_set_to_true(self):
        os.environ[misc.FUNCTIONAL_TESTS_STR] = 'True'

        # no raise here
        misc.run_functional_tests_check()

    def test_set_to_false(self):
        os.environ[misc.FUNCTIONAL_TESTS_STR] = 'False'
        self.assertRaises(SkipTest, misc.run_functional_tests_check)

    def test_set_to_random_string(self):
        os.environ[misc.FUNCTIONAL_TESTS_STR] = 'String'
        self.assertRaises(SkipTest, misc.run_functional_tests_check)

