|
| 1 | +# Regression test: TextIOWrapper.readline must return one line at a time |
| 2 | +# (including the line ending), honour the size limit, keep lines that span |
| 3 | +# the 8192-byte read chunks intact, and return "" at EOF. Previously a single |
| 4 | +# call concatenated lines, dropped data, or crashed on uneven line lengths. |
| 5 | + |
| 6 | +# Run with cwd == integration/ (as the integration runner does). |
| 7 | +DATA = "tests/file_readline_data.txt" # b"a\nbb\nccc" (no trailing newline) |
| 8 | +DATA_CRLF = "tests/file_readline_data_crlf.txt" # b"one\r\ntwo\r\n" |
| 9 | +DATA_LONG = "tests/file_readline_data_long.txt" # b"x" * 9000 + b"\ntail\n" |
| 10 | +DATA_STRADDLE = "tests/file_readline_data_straddle.txt" # b"x" * 8191 + b"\r\ntail\r\n" |
| 11 | +DATA_CR_TAIL = "tests/file_readline_data_cr_tail.txt" # b"a\nb\r" |
| 12 | +DATA_CHUNK_END = "tests/file_readline_data_chunk_end.txt" # b"x" * 8191 + b"\ntail\n" |
| 13 | + |
| 14 | +# 1. one line per call, trailing newline included, "" at EOF (and stays ""). |
| 15 | +f = open(DATA, "r") |
| 16 | +assert f.readline() == "a\n" |
| 17 | +assert f.readline() == "bb\n" |
| 18 | +assert f.readline() == "ccc" |
| 19 | +assert f.readline() == "" |
| 20 | +assert f.readline() == "" |
| 21 | + |
| 22 | +# 2. size limit: at most `limit` characters, the rest stays buffered. |
| 23 | +g = open(DATA, "r") |
| 24 | +assert g.readline(1) == "a" |
| 25 | +assert g.readline(0) == "" |
| 26 | +assert g.readline(100) == "\n" |
| 27 | +assert g.readline(2) == "bb" |
| 28 | +assert g.readline() == "\n" |
| 29 | +assert g.readline() == "ccc" |
| 30 | + |
| 31 | +# 3. \r\n is consumed as a single line ending (no spurious empty line). |
| 32 | +# TODO: with newline=None CPython translates the terminator to "\n"; the |
| 33 | +# decoder is not implemented yet, so the raw ending is returned for now. |
| 34 | +h = open(DATA_CRLF, "r") |
| 35 | +assert h.readline() == "one\r\n" |
| 36 | +assert h.readline() == "two\r\n" |
| 37 | +assert h.readline() == "" |
| 38 | + |
| 39 | +# 4. a line longer than the 8192-byte read chunk is returned whole. |
| 40 | +i = open(DATA_LONG, "r") |
| 41 | +line = i.readline() |
| 42 | +assert len(line) == 9001, len(line) |
| 43 | +assert i.readline() == "tail\n" |
| 44 | +assert i.readline() == "" |
| 45 | + |
| 46 | +# 5. readlines returns the same split. |
| 47 | +j = open(DATA, "r") |
| 48 | +assert j.readlines() == ["a\n", "bb\n", "ccc"] |
| 49 | + |
| 50 | +# 6. a \r\n split across the 8192-byte chunk boundary stays one line ending |
| 51 | +# (the first chunk ends with the \r, the \n arrives with the next chunk). |
| 52 | +k = open(DATA_STRADDLE, "r") |
| 53 | +line = k.readline() |
| 54 | +assert len(line) == 8193, len(line) |
| 55 | +assert line == "x" * 8191 + "\r\n" |
| 56 | +assert k.readline() == "tail\r\n" |
| 57 | +assert k.readline() == "" |
| 58 | + |
| 59 | +# 7. a \r\n straddling the size limit: the \r fits within the limit, the \n |
| 60 | +# stays buffered and becomes its own line on the next call (CPython clamps |
| 61 | +# the found line to size and pushes the remainder back). |
| 62 | +m = open(DATA_CRLF, "r") |
| 63 | +assert m.readline(4) == "one\r" |
| 64 | +assert m.readline() == "\n" |
| 65 | +assert m.readline() == "two\r\n" |
| 66 | +assert m.readline() == "" |
| 67 | + |
| 68 | +# 8. an unresolved trailing \r must not stop an earlier complete line from |
| 69 | +# being returned (on a blocking stream the read-ahead would stall), and a |
| 70 | +# lone \r at EOF terminates the final line. |
| 71 | +n = open(DATA_CR_TAIL, "r") |
| 72 | +assert n.readline() == "a\n" |
| 73 | +assert n.readline() == "b\r" |
| 74 | +assert n.readline() == "" |
| 75 | + |
| 76 | +# 9. readlines keeps reading past a delimiter that lands exactly on the chunk |
| 77 | +# boundary and drains the buffer mid-stream (the first line fills the whole |
| 78 | +# 8192-byte chunk). |
| 79 | +o = open(DATA_CHUNK_END, "r") |
| 80 | +assert o.readlines() == ["x" * 8191 + "\n", "tail\n"] |
| 81 | +p = open(DATA_CHUNK_END, "r") |
| 82 | +assert p.readline() == "x" * 8191 + "\n" |
| 83 | +assert p.readlines() == ["tail\n"] |
| 84 | + |
| 85 | +print("file_readline: ok") |
0 commit comments