Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | #!python |
2 | ||
3 | #---------------------------------------------------------------------- | |
4 | # test largefile support on system where this makes sense | |
5 | # | |
6 | #---------------------------------------------------------------------- | |
7 | ||
8 | from test import test_support | |
9 | import os, struct, stat, sys | |
10 | ||
11 | try: | |
12 | import signal | |
13 | # The default handler for SIGXFSZ is to abort the process. | |
14 | # By ignoring it, system calls exceeding the file size resource | |
15 | # limit will raise IOError instead of crashing the interpreter. | |
16 | oldhandler = signal.signal(signal.SIGXFSZ, signal.SIG_IGN) | |
17 | except (ImportError, AttributeError): | |
18 | pass | |
19 | ||
20 | ||
21 | # create >2GB file (2GB = 2147483648 bytes) | |
22 | size = 2500000000L | |
23 | name = test_support.TESTFN | |
24 | ||
25 | ||
26 | # On Windows and Mac OSX this test comsumes large resources; It takes | |
27 | # a long time to build the >2GB file and takes >2GB of disk space | |
28 | # therefore the resource must be enabled to run this test. If not, | |
29 | # nothing after this line stanza will be executed. | |
30 | if sys.platform[:3] == 'win' or sys.platform == 'darwin': | |
31 | test_support.requires( | |
32 | 'largefile', | |
33 | 'test requires %s bytes and a long time to run' % str(size)) | |
34 | else: | |
35 | # Only run if the current filesystem supports large files. | |
36 | # (Skip this test on Windows, since we now always support large files.) | |
37 | f = open(test_support.TESTFN, 'wb') | |
38 | try: | |
39 | # 2**31 == 2147483648 | |
40 | f.seek(2147483649L) | |
41 | # Seeking is not enough of a test: you must write and flush, too! | |
42 | f.write("x") | |
43 | f.flush() | |
44 | except (IOError, OverflowError): | |
45 | f.close() | |
46 | os.unlink(test_support.TESTFN) | |
47 | raise test_support.TestSkipped, \ | |
48 | "filesystem does not have largefile support" | |
49 | else: | |
50 | f.close() | |
51 | ||
52 | ||
53 | def expect(got_this, expect_this): | |
54 | if test_support.verbose: | |
55 | print '%r =?= %r ...' % (got_this, expect_this), | |
56 | if got_this != expect_this: | |
57 | if test_support.verbose: | |
58 | print 'no' | |
59 | raise test_support.TestFailed, 'got %r, but expected %r' %\ | |
60 | (got_this, expect_this) | |
61 | else: | |
62 | if test_support.verbose: | |
63 | print 'yes' | |
64 | ||
65 | ||
66 | # test that each file function works as expected for a large (i.e. >2GB, do | |
67 | # we have to check >4GB) files | |
68 | ||
69 | if test_support.verbose: | |
70 | print 'create large file via seek (may be sparse file) ...' | |
71 | f = open(name, 'wb') | |
72 | try: | |
73 | f.write('z') | |
74 | f.seek(0) | |
75 | f.seek(size) | |
76 | f.write('a') | |
77 | f.flush() | |
78 | if test_support.verbose: | |
79 | print 'check file size with os.fstat' | |
80 | expect(os.fstat(f.fileno())[stat.ST_SIZE], size+1) | |
81 | finally: | |
82 | f.close() | |
83 | if test_support.verbose: | |
84 | print 'check file size with os.stat' | |
85 | expect(os.stat(name)[stat.ST_SIZE], size+1) | |
86 | ||
87 | if test_support.verbose: | |
88 | print 'play around with seek() and read() with the built largefile' | |
89 | f = open(name, 'rb') | |
90 | try: | |
91 | expect(f.tell(), 0) | |
92 | expect(f.read(1), 'z') | |
93 | expect(f.tell(), 1) | |
94 | f.seek(0) | |
95 | expect(f.tell(), 0) | |
96 | f.seek(0, 0) | |
97 | expect(f.tell(), 0) | |
98 | f.seek(42) | |
99 | expect(f.tell(), 42) | |
100 | f.seek(42, 0) | |
101 | expect(f.tell(), 42) | |
102 | f.seek(42, 1) | |
103 | expect(f.tell(), 84) | |
104 | f.seek(0, 1) | |
105 | expect(f.tell(), 84) | |
106 | f.seek(0, 2) # seek from the end | |
107 | expect(f.tell(), size + 1 + 0) | |
108 | f.seek(-10, 2) | |
109 | expect(f.tell(), size + 1 - 10) | |
110 | f.seek(-size-1, 2) | |
111 | expect(f.tell(), 0) | |
112 | f.seek(size) | |
113 | expect(f.tell(), size) | |
114 | expect(f.read(1), 'a') # the 'a' that was written at the end of file above | |
115 | f.seek(-size-1, 1) | |
116 | expect(f.read(1), 'z') | |
117 | expect(f.tell(), 1) | |
118 | finally: | |
119 | f.close() | |
120 | ||
121 | if test_support.verbose: | |
122 | print 'play around with os.lseek() with the built largefile' | |
123 | f = open(name, 'rb') | |
124 | try: | |
125 | expect(os.lseek(f.fileno(), 0, 0), 0) | |
126 | expect(os.lseek(f.fileno(), 42, 0), 42) | |
127 | expect(os.lseek(f.fileno(), 42, 1), 84) | |
128 | expect(os.lseek(f.fileno(), 0, 1), 84) | |
129 | expect(os.lseek(f.fileno(), 0, 2), size+1+0) | |
130 | expect(os.lseek(f.fileno(), -10, 2), size+1-10) | |
131 | expect(os.lseek(f.fileno(), -size-1, 2), 0) | |
132 | expect(os.lseek(f.fileno(), size, 0), size) | |
133 | expect(f.read(1), 'a') # the 'a' that was written at the end of file above | |
134 | finally: | |
135 | f.close() | |
136 | ||
137 | if hasattr(f, 'truncate'): | |
138 | if test_support.verbose: | |
139 | print 'try truncate' | |
140 | f = open(name, 'r+b') | |
141 | try: | |
142 | f.seek(0, 2) | |
143 | expect(f.tell(), size+1) # else we've lost track of the true size | |
144 | # Cut it back via seek + truncate with no argument. | |
145 | newsize = size - 10 | |
146 | f.seek(newsize) | |
147 | f.truncate() | |
148 | expect(f.tell(), newsize) # else pointer moved | |
149 | f.seek(0, 2) | |
150 | expect(f.tell(), newsize) # else wasn't truncated | |
151 | # Ensure that truncate(smaller than true size) shrinks the file. | |
152 | newsize -= 1 | |
153 | f.seek(42) | |
154 | f.truncate(newsize) | |
155 | expect(f.tell(), 42) # else pointer moved | |
156 | f.seek(0, 2) | |
157 | expect(f.tell(), newsize) # else wasn't truncated | |
158 | ||
159 | # XXX truncate(larger than true size) is ill-defined across platforms | |
160 | ||
161 | # cut it waaaaay back | |
162 | f.seek(0) | |
163 | f.truncate(1) | |
164 | expect(f.tell(), 0) # else pointer moved | |
165 | expect(len(f.read()), 1) # else wasn't truncated | |
166 | ||
167 | finally: | |
168 | f.close() | |
169 | ||
170 | os.unlink(name) |