# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult
import unittest
import inspect
from StringIO import StringIO
import os

'''Helper to make python unit tests report the way that the Mozilla
unit test infrastructure expects tests to report.

Usage:

import unittest
import mozunit

if __name__ == '__main__':
    mozunit.main()
'''

class _MozTestResult(_TestResult):
    def __init__(self, stream, descriptions):
        _TestResult.__init__(self)
        self.stream = stream
        self.descriptions = descriptions

    def getDescription(self, test):
        if self.descriptions:
            return test.shortDescription() or str(test)
        else:
            return str(test)

    def addSuccess(self, test):
        _TestResult.addSuccess(self, test)
        filename = inspect.getfile(test.__class__)
        testname = test._testMethodName
        self.stream.writeln("TEST-PASS | {0} | {1}".format(filename, testname))

    def addError(self, test, err):
        _TestResult.addError(self, test, err)
        self.printFail(test, err)

    def addFailure(self, test, err):
        _TestResult.addFailure(self, test, err)
        self.printFail(test,err)

    def printFail(self, test, err):
        exctype, value, tb = err
        # Skip test runner traceback levels
        while tb and self._is_relevant_tb_level(tb):
            tb = tb.tb_next
        if not tb:
            self.stream.writeln("TEST-UNEXPECTED-FAIL | NO TRACEBACK |")
        _f, _ln, _t = inspect.getframeinfo(tb)[:3]
        self.stream.writeln("TEST-UNEXPECTED-FAIL | {0} | line {1}, {2}: {3}" 
                            .format(_f, _ln, _t, value.message))

    def printErrorList(self):
        for test, err in self.errors:
            self.stream.writeln("ERROR: {0}".format(self.getDescription(test)))
            self.stream.writeln("{0}".format(err))


class MozTestRunner(_TestRunner):
    def _makeResult(self):
        return _MozTestResult(self.stream, self.descriptions)
    def run(self, test):
        result = self._makeResult()
        test(result)
        result.printErrorList()
        return result

class MockedFile(StringIO):
    def __init__(self, context, filename, content = ''):
        self.context = context
        self.name = filename
        StringIO.__init__(self, content)

    def close(self):
        self.context.files[self.name] = self.getvalue()
        StringIO.close(self)

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.close()

class MockedOpen(object):
    '''
    Context manager diverting the open builtin such that opening files
    can open "virtual" file instances given when creating a MockedOpen.

    with MockedOpen({'foo': 'foo', 'bar': 'bar'}):
        f = open('foo', 'r')

    will thus open the virtual file instance for the file 'foo' to f.

    MockedOpen also masks writes, so that creating or replacing files
    doesn't touch the file system, while subsequently opening the file
    will return the recorded content.

    with MockedOpen():
        f = open('foo', 'w')
        f.write('foo')
    self.assertRaises(Exception,f.open('foo', 'r'))
    '''
    def __init__(self, files = {}):
        self.files = {}
        for name, content in files.iteritems():
            self.files[os.path.abspath(name)] = content

    def __call__(self, name, mode = 'r'):
        absname = os.path.abspath(name)
        if 'w' in mode:
            file = MockedFile(self, absname)
        elif absname in self.files:
            file = MockedFile(self, absname, self.files[absname])
        elif 'a' in mode:
            file = MockedFile(self, absname, self.open(name, 'r').read())
        else:
            file = self.open(name, mode)
        if 'a' in mode:
            file.seek(0, os.SEEK_END)
        return file

    def __enter__(self):
        import __builtin__
        self.open = __builtin__.open
        self._orig_path_exists = os.path.exists
        __builtin__.open = self
        os.path.exists = self._wrapped_exists

    def __exit__(self, type, value, traceback):
        import __builtin__
        __builtin__.open = self.open
        os.path.exists = self._orig_path_exists

    def _wrapped_exists(self, p):
        if p in self.files:
            return True

        abspath = os.path.abspath(p)
        if abspath in self.files:
            return True

        return self._orig_path_exists(p)

def main(*args):
    unittest.main(testRunner=MozTestRunner(),*args)
