|
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) |