1# Tests universal newline support for both reading and parsing files.
2
3# NOTE: this file tests the new `io` library backported from Python 3.x.
4# Similar tests for the builtin file object can be found in test_univnewlines2k.py.
5
6from __future__ import print_function
7from __future__ import unicode_literals
8
9import io
10import _pyio as pyio
11import unittest
12import os
13import sys
14from test import test_support as support
15
16if not hasattr(sys.stdin, 'newlines'):
17    raise unittest.SkipTest(
18        "This Python does not have universal newline support")
19
20FATX = 'x' * (2**14)
21
22DATA_TEMPLATE = [
23    "line1=1",
24    "line2='this is a very long line designed to go past any default " +
25        "buffer limits that exist in io.py but we also want to test " +
26        "the uncommon case, naturally.'",
27    "def line3():pass",
28    "line4 = '%s'" % FATX,
29    ]
30
31DATA_LF = "\n".join(DATA_TEMPLATE) + "\n"
32DATA_CR = "\r".join(DATA_TEMPLATE) + "\r"
33DATA_CRLF = "\r\n".join(DATA_TEMPLATE) + "\r\n"
34
35# Note that DATA_MIXED also tests the ability to recognize a lone \r
36# before end-of-file.
37DATA_MIXED = "\n".join(DATA_TEMPLATE) + "\r"
38DATA_SPLIT = [x + "\n" for x in DATA_TEMPLATE]
39
40class TestGenericUnivNewlines(unittest.TestCase):
41    # use a class variable DATA to define the data to write to the file
42    # and a class variable NEWLINE to set the expected newlines value
43    READMODE = 'r'
44    WRITEMODE = 'wb'
45
46    def setUp(self):
47        data = self.DATA
48        if "b" in self.WRITEMODE:
49            data = data.encode("ascii")
50        with self.open(support.TESTFN, self.WRITEMODE) as fp:
51            fp.write(data)
52
53    def tearDown(self):
54        try:
55            os.unlink(support.TESTFN)
56        except:
57            pass
58
59    def test_read(self):
60        with self.open(support.TESTFN, self.READMODE) as fp:
61            data = fp.read()
62        self.assertEqual(data, DATA_LF)
63        self.assertEqual(set(fp.newlines), set(self.NEWLINE))
64
65    def test_readlines(self):
66        with self.open(support.TESTFN, self.READMODE) as fp:
67            data = fp.readlines()
68        self.assertEqual(data, DATA_SPLIT)
69        self.assertEqual(set(fp.newlines), set(self.NEWLINE))
70
71    def test_readline(self):
72        with self.open(support.TESTFN, self.READMODE) as fp:
73            data = []
74            d = fp.readline()
75            while d:
76                data.append(d)
77                d = fp.readline()
78        self.assertEqual(data, DATA_SPLIT)
79        self.assertEqual(set(fp.newlines), set(self.NEWLINE))
80
81    def test_seek(self):
82        with self.open(support.TESTFN, self.READMODE) as fp:
83            fp.readline()
84            pos = fp.tell()
85            data = fp.readlines()
86            self.assertEqual(data, DATA_SPLIT[1:])
87            fp.seek(pos)
88            data = fp.readlines()
89        self.assertEqual(data, DATA_SPLIT[1:])
90
91
92class TestCRNewlines(TestGenericUnivNewlines):
93    NEWLINE = '\r'
94    DATA = DATA_CR
95
96class TestLFNewlines(TestGenericUnivNewlines):
97    NEWLINE = '\n'
98    DATA = DATA_LF
99
100class TestCRLFNewlines(TestGenericUnivNewlines):
101    NEWLINE = '\r\n'
102    DATA = DATA_CRLF
103
104    def test_tell(self):
105        with self.open(support.TESTFN, self.READMODE) as fp:
106            self.assertEqual(repr(fp.newlines), repr(None))
107            data = fp.readline()
108            pos = fp.tell()
109        self.assertEqual(repr(fp.newlines), repr(self.NEWLINE))
110
111class TestMixedNewlines(TestGenericUnivNewlines):
112    NEWLINE = ('\r', '\n')
113    DATA = DATA_MIXED
114
115
116def test_main():
117    base_tests = (TestCRNewlines,
118                  TestLFNewlines,
119                  TestCRLFNewlines,
120                  TestMixedNewlines)
121    tests = []
122    # Test the C and Python implementations.
123    for test in base_tests:
124        class CTest(test):
125            open = io.open
126        CTest.__name__ = str("C" + test.__name__)
127        class PyTest(test):
128            open = staticmethod(pyio.open)
129        PyTest.__name__ = str("Py" + test.__name__)
130        tests.append(CTest)
131        tests.append(PyTest)
132    support.run_unittest(*tests)
133
134if __name__ == '__main__':
135    test_main()
136