Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | # This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | # License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 4 | |
michael@0 | 5 | from unittest import TextTestRunner as _TestRunner, TestResult as _TestResult |
michael@0 | 6 | import unittest |
michael@0 | 7 | import inspect |
michael@0 | 8 | from StringIO import StringIO |
michael@0 | 9 | import os |
michael@0 | 10 | |
michael@0 | 11 | '''Helper to make python unit tests report the way that the Mozilla |
michael@0 | 12 | unit test infrastructure expects tests to report. |
michael@0 | 13 | |
michael@0 | 14 | Usage: |
michael@0 | 15 | |
michael@0 | 16 | import unittest |
michael@0 | 17 | import mozunit |
michael@0 | 18 | |
michael@0 | 19 | if __name__ == '__main__': |
michael@0 | 20 | mozunit.main() |
michael@0 | 21 | ''' |
michael@0 | 22 | |
michael@0 | 23 | class _MozTestResult(_TestResult): |
michael@0 | 24 | def __init__(self, stream, descriptions): |
michael@0 | 25 | _TestResult.__init__(self) |
michael@0 | 26 | self.stream = stream |
michael@0 | 27 | self.descriptions = descriptions |
michael@0 | 28 | |
michael@0 | 29 | def getDescription(self, test): |
michael@0 | 30 | if self.descriptions: |
michael@0 | 31 | return test.shortDescription() or str(test) |
michael@0 | 32 | else: |
michael@0 | 33 | return str(test) |
michael@0 | 34 | |
michael@0 | 35 | def addSuccess(self, test): |
michael@0 | 36 | _TestResult.addSuccess(self, test) |
michael@0 | 37 | filename = inspect.getfile(test.__class__) |
michael@0 | 38 | testname = test._testMethodName |
michael@0 | 39 | self.stream.writeln("TEST-PASS | {0} | {1}".format(filename, testname)) |
michael@0 | 40 | |
michael@0 | 41 | def addError(self, test, err): |
michael@0 | 42 | _TestResult.addError(self, test, err) |
michael@0 | 43 | self.printFail(test, err) |
michael@0 | 44 | |
michael@0 | 45 | def addFailure(self, test, err): |
michael@0 | 46 | _TestResult.addFailure(self, test, err) |
michael@0 | 47 | self.printFail(test,err) |
michael@0 | 48 | |
michael@0 | 49 | def printFail(self, test, err): |
michael@0 | 50 | exctype, value, tb = err |
michael@0 | 51 | # Skip test runner traceback levels |
michael@0 | 52 | while tb and self._is_relevant_tb_level(tb): |
michael@0 | 53 | tb = tb.tb_next |
michael@0 | 54 | if not tb: |
michael@0 | 55 | self.stream.writeln("TEST-UNEXPECTED-FAIL | NO TRACEBACK |") |
michael@0 | 56 | _f, _ln, _t = inspect.getframeinfo(tb)[:3] |
michael@0 | 57 | self.stream.writeln("TEST-UNEXPECTED-FAIL | {0} | line {1}, {2}: {3}" |
michael@0 | 58 | .format(_f, _ln, _t, value.message)) |
michael@0 | 59 | |
michael@0 | 60 | def printErrorList(self): |
michael@0 | 61 | for test, err in self.errors: |
michael@0 | 62 | self.stream.writeln("ERROR: {0}".format(self.getDescription(test))) |
michael@0 | 63 | self.stream.writeln("{0}".format(err)) |
michael@0 | 64 | |
michael@0 | 65 | |
michael@0 | 66 | class MozTestRunner(_TestRunner): |
michael@0 | 67 | def _makeResult(self): |
michael@0 | 68 | return _MozTestResult(self.stream, self.descriptions) |
michael@0 | 69 | def run(self, test): |
michael@0 | 70 | result = self._makeResult() |
michael@0 | 71 | test(result) |
michael@0 | 72 | result.printErrorList() |
michael@0 | 73 | return result |
michael@0 | 74 | |
michael@0 | 75 | class MockedFile(StringIO): |
michael@0 | 76 | def __init__(self, context, filename, content = ''): |
michael@0 | 77 | self.context = context |
michael@0 | 78 | self.name = filename |
michael@0 | 79 | StringIO.__init__(self, content) |
michael@0 | 80 | |
michael@0 | 81 | def close(self): |
michael@0 | 82 | self.context.files[self.name] = self.getvalue() |
michael@0 | 83 | StringIO.close(self) |
michael@0 | 84 | |
michael@0 | 85 | def __enter__(self): |
michael@0 | 86 | return self |
michael@0 | 87 | |
michael@0 | 88 | def __exit__(self, type, value, traceback): |
michael@0 | 89 | self.close() |
michael@0 | 90 | |
michael@0 | 91 | class MockedOpen(object): |
michael@0 | 92 | ''' |
michael@0 | 93 | Context manager diverting the open builtin such that opening files |
michael@0 | 94 | can open "virtual" file instances given when creating a MockedOpen. |
michael@0 | 95 | |
michael@0 | 96 | with MockedOpen({'foo': 'foo', 'bar': 'bar'}): |
michael@0 | 97 | f = open('foo', 'r') |
michael@0 | 98 | |
michael@0 | 99 | will thus open the virtual file instance for the file 'foo' to f. |
michael@0 | 100 | |
michael@0 | 101 | MockedOpen also masks writes, so that creating or replacing files |
michael@0 | 102 | doesn't touch the file system, while subsequently opening the file |
michael@0 | 103 | will return the recorded content. |
michael@0 | 104 | |
michael@0 | 105 | with MockedOpen(): |
michael@0 | 106 | f = open('foo', 'w') |
michael@0 | 107 | f.write('foo') |
michael@0 | 108 | self.assertRaises(Exception,f.open('foo', 'r')) |
michael@0 | 109 | ''' |
michael@0 | 110 | def __init__(self, files = {}): |
michael@0 | 111 | self.files = {} |
michael@0 | 112 | for name, content in files.iteritems(): |
michael@0 | 113 | self.files[os.path.abspath(name)] = content |
michael@0 | 114 | |
michael@0 | 115 | def __call__(self, name, mode = 'r'): |
michael@0 | 116 | absname = os.path.abspath(name) |
michael@0 | 117 | if 'w' in mode: |
michael@0 | 118 | file = MockedFile(self, absname) |
michael@0 | 119 | elif absname in self.files: |
michael@0 | 120 | file = MockedFile(self, absname, self.files[absname]) |
michael@0 | 121 | elif 'a' in mode: |
michael@0 | 122 | file = MockedFile(self, absname, self.open(name, 'r').read()) |
michael@0 | 123 | else: |
michael@0 | 124 | file = self.open(name, mode) |
michael@0 | 125 | if 'a' in mode: |
michael@0 | 126 | file.seek(0, os.SEEK_END) |
michael@0 | 127 | return file |
michael@0 | 128 | |
michael@0 | 129 | def __enter__(self): |
michael@0 | 130 | import __builtin__ |
michael@0 | 131 | self.open = __builtin__.open |
michael@0 | 132 | self._orig_path_exists = os.path.exists |
michael@0 | 133 | __builtin__.open = self |
michael@0 | 134 | os.path.exists = self._wrapped_exists |
michael@0 | 135 | |
michael@0 | 136 | def __exit__(self, type, value, traceback): |
michael@0 | 137 | import __builtin__ |
michael@0 | 138 | __builtin__.open = self.open |
michael@0 | 139 | os.path.exists = self._orig_path_exists |
michael@0 | 140 | |
michael@0 | 141 | def _wrapped_exists(self, p): |
michael@0 | 142 | if p in self.files: |
michael@0 | 143 | return True |
michael@0 | 144 | |
michael@0 | 145 | abspath = os.path.abspath(p) |
michael@0 | 146 | if abspath in self.files: |
michael@0 | 147 | return True |
michael@0 | 148 | |
michael@0 | 149 | return self._orig_path_exists(p) |
michael@0 | 150 | |
michael@0 | 151 | def main(*args): |
michael@0 | 152 | unittest.main(testRunner=MozTestRunner(),*args) |