# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
# Copyright 2012-2014 Canonical, Ltd.
# Author: Thomi Richards
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.


import os
import tempfile

from io import StringIO

try:
    from unittest.mock import patch
except ImportError:
    from mock import patch

from testtools import TestCase
from testtools.matchers import raises

import windowmocker


class TestFilePathLoading(TestCase):

    """Tests the ability to create apps from a file path."""

    def test_create_application_from_path_raises_IOError_on_missing_file(self):
        """create_application_from_path function must raise IOError when asked
        to open a file that does not exist.
        """
        self.assertThat(lambda: windowmocker.create_application_from_path("_does_not_exist"), raises(IOError))

    def test_create_application_from_path_raises_PermError_on_bad_perms(self):
        """create_application_from_path function must raise PermissionError
        when the file's permissions do not allow it to be read.
        """
        fd, temp_filename = tempfile.mkstemp()
        self.addCleanup(os.remove, temp_filename)
        os.close(fd)
        with open(temp_filename, 'w'):
            pass
        os.chmod(temp_filename, 0)

        self.assertThat(
            lambda: windowmocker.create_application_from_path(temp_filename),
            raises(IOError))


class TestFileObjectLoading(TestCase):

    """Tests the ability to create apps from a file-like object."""

    def test_raises_attributeerror_on_bad_parameter_type(self):
        """create_application_from_file must raise a AttributeError if we give it
        something other than a file-like object.

        """
        self.assertThat(lambda: windowmocker.create_application_from_file("string"),
            raises(AttributeError))
        self.assertThat(lambda: windowmocker.create_application_from_file(123),
            raises(AttributeError))
        self.assertThat(lambda: windowmocker.create_application_from_file(123.456),
            raises(AttributeError))
        self.assertThat(lambda: windowmocker.create_application_from_file(True),
            raises(AttributeError))

    @patch('windowmocker.create_application_from_data')
    def test_can_load_ascii_json(self, load_mock):
        windowmocker.create_application_from_file(StringIO(u'["Hello", "World"]'))
        load_mock.assert_called_once_with(["Hello", "World"], None)

    @patch('windowmocker.create_application_from_data')
    def test_can_load_unicode_json(self, load_mock):
        windowmocker.create_application_from_file(
            StringIO(u'["ɥǝןןo", "ʍoɹןp"]'))
        load_mock.assert_called_once_with(
            [u'\u0265\u01dd\u05df\u05dfo', u'\u028do\u0279\u05dfp'], None)

    def test_raises_runtime_on_empty_file(self):
        # BAW 2014-01-31: We cannot assert on the exact error message
        # returned, because it's different between Python 3.3 and 3.4.
        # http://bugs.python.org/issue20453
        self.assertThat(
            lambda: windowmocker.create_application_from_file(StringIO()),
            raises(RuntimeError))
