Skip to content

Commit 1f59479

Browse files
author
Joel Wright
committed
Update tests and fix SizeFSAlphaNum generator bug when reading >64*1024 bytes
1 parent 8336f03 commit 1f59479

File tree

5 files changed

+92
-76
lines changed

5 files changed

+92
-76
lines changed

README.md

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -42,91 +42,86 @@ Create Size File objects in memory:
4242

4343
from sizefs import SizeFS
4444
sfs = SizeFS()
45-
sfs.read('/1B', 1, 0, None)
46-
sfs.read('/2B', 2, 0, None)
47-
sfs.read('/2K', 1024, 0, None)
48-
sfs.read('/128K', 1024*128, 0, None)
49-
sfs.read('/4G', 4*1024*1024, 0, None)
45+
sfs.read('/ones/1B', 1, 0, None, create=True)
46+
sfs.read('/ones/2B', 2, 0, None, create=True)
47+
sfs.read('/ones/2K', 1024, 0, None, create=True)
48+
sfs.read('/ones/128K', 1024*128, 0, None, create=True)
49+
sfs.read('/ones/4G', 4*1024*1024, 0, None, create=True)
5050

5151
The folder structure is used to determine the content of the files:
5252

53-
sfs.read('/zeros/5B', 5, 0, None).read(0, 5)
53+
sfs.read('/zeros/5B', 5, 0, None, create=True).read(0, 5)
5454
out> 00000
5555

56-
sfs.read('/ones/5B', 5, 0, None).read(0, 5)
56+
sfs.read('/ones/5B', 5, 0, None, create=True).read(0, 5)
5757
out> 11111
5858

59-
sfs.read('/alpha_num/5B', 5, 0, None).read(0, 5)
59+
sfs.read('/alpha_num/5B', 5, 0, None, create=True).read(0, 5)
6060
out> TMdEv
6161

62-
Folders can be created to manipulate the data:
62+
The folders 'ones', 'zeros' and 'alpha_num' are always present,
63+
but new folders can also be created. When files are created in a
64+
folder, the xattrs of the folder determine that file's content until
65+
the file's xattrs are updated:
6366

6467
sfs.mkdir('/regex1', None)
65-
sfs.setxattr('/regex1', 'filler', '0', None)
66-
print sfs.read('/alpha_num/5B', 5, 0, None).read(0, 5)
68+
sfs.setxattr('/regex1', 'generator', 'regex', None)
69+
sfs.setxattr('/regex1', 'filler', 'regex', None)
70+
print sfs.read('/regex1/5B', 5, 0, None, create=True).read(0, 5)
6771

68-
out> 00000
72+
out> regex
6973

70-
sfs.mkdir('/regex2', None)
71-
sfs.setxattr('/regex2', 'filler', '1', None)
72-
print sfs.read('/regex2/5B', 5, 0, None).read(0, 5)
74+
sfs.setxattr('/regex1/5B', 'filler', 'string', None)
75+
print sfs.read('/regex1/5B', 5, 0, None).read(0, 5)
7376

74-
out> 11111
77+
out> string
7578

76-
sfs.mkdir('/regex3', None)
77-
sfs.setxattr('/regex3', 'filler', '[a-zA-Z0-9]', None)
78-
print sfs.read('/regex3/5B', 5, 0, None).read(0, 5)
79+
sfs.setxattr('/regex1/5B', 'filler', 'a{2}b{2}c', None)
80+
print sfs.read('/regex1/5B', 5, 0, None).read(0, 5)
7981

80-
out> 1JAbd
82+
out> aabbc
8183

82-
Files can be added to SizeFS using sfs.create:
84+
Files can also be added to SizeFS using sfs.create:
8385

84-
sfs.mkdir('/regex3', None)
85-
sfs.setxattr('/regex3', 'filler', '[a-zA-Z0-9]', None)
86-
sfs.create('/regex3/5B', None)
87-
print sfs.read('/regex3/5B', 5, 0, None)
86+
sfs.mkdir('/folder', None)
87+
sfs.create('/folder/5B', None)
88+
print sfs.read('/folder/5B', 5, 0, None)
89+
90+
out> 11111
8891

89-
out> aS8yG
92+
And as discussed above, the name of the file determines its size:
9093

9194
sfs.create('/regex3/128K', None)
92-
print len(sfs.read('/regex3/128K', 128*1024, 0, None))
95+
# Try to read more contents than the files contains
96+
print len(sfs.read('/regex3/128K', 256*1000, 0, None))
9397

94-
out> 131072
98+
out> 128000
9599

96100
sfs.create('/regex3/128K-1B', None)
97-
print len(sfs.read('/regex3/128K-1B', 128*1024, 0, None))
101+
# Try to read more contents than the files contains
102+
print len(sfs.read('/regex3/128K-1B', 256*1000, 0, None))
98103

99-
out> 131071
104+
out> 127999
100105

101106
sfs.create('/regex3/128K+1B', None)
102-
print len(sfs.read('/alphanum/128K+1B', 128*1024+1, 0, None))
103-
104-
out> 131073
105-
106-
File content can be generated that matches a regex pattern by adding a directory
107-
108-
sfs.mkdir('/regex1')
109-
sfs.setxattr('/regex1','filler','a(bcd)*e{4}[a-z03]*')
110-
sfs.create('/regex1','128K')
111-
print len(sfs.open('regex1/128KB').read(0, 128*1024))
107+
# Try to read more contents than the files contains
108+
print len(sfs.read('/alphanum/128K+1B', 256*1000, 0, None))
112109

113-
out> 131072
114-
115-
sfs.create('/regex1','128K-1B')
116-
print len(sfs.open('regex1/128K-1B').read(0, 128*1024-1))
117-
118-
out> 131071
119-
120-
sfs.create('/regex1','128K+1B')
121-
print len(sfs.open('regex1/128KB+1B').read(0, 128*1024+1))
122-
123-
out> 131073
110+
out> 128001
124111

125112

126113
Extended Usage
127114
--------------
128115

129-
We can set up to 5 properties:
116+
The 'generator' xattr property defines the file content and can be set to one
117+
of:
118+
119+
ones - files are filled with ones
120+
zeros - files are filled with zeros
121+
alpha_num - files are filled with alpha numeric characters
122+
regex - files are filled according to a collection of regular expression patterns
123+
124+
We can set up to 5 properties to control the regular expression patterns:
130125

131126
prefix - defined pattern for the start of a file (default = "")
132127
suffix - defined pattern for the end of a file (default = "")

sizefs/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
__all__ = ['SizeFS', 'SizeFile']
1+
__all__ = ['SizeFS']
22

3-
from sizefs import SizeFS, SIZEFSCHARS
3+
from sizefs import SizeFS

sizefs/contents.pyx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,20 @@ class SizeFSAlphaNumGen(object):
5555

5656
def __init__(self):
5757
self.pre_seed = ''.join(random.choice(self.chars)
58-
for _x in range(64*1024))
58+
for _ in range(64*1024))
5959

6060
def read(self, start, end):
6161
if start <= end:
62-
return self.pre_seed[0:end-start+1]
62+
toRead = end - start
63+
pre_seed_count = 0
64+
content = []
65+
pre_seed_len = len(self.pre_seed)
66+
while toRead > pre_seed_len:
67+
content.append(self.pre_seed)
68+
toRead -= pre_seed_len
69+
pre_seed_count += 1
70+
content.append(self.pre_seed[0:toRead+1])
71+
return ''.join(content)
6372
else:
6473
return ''
6574

sizefs/sizefs.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def getattr(self, path, fh=None):
169169
if parent_folder in self.folders:
170170
return self.folders[parent_folder]
171171

172-
raise FuseOSError(ENOENT)
172+
raise FuseOSError(ENOENT)
173173

174174
def getxattr(self, path, name, position=0):
175175
"""
@@ -229,15 +229,24 @@ def open(self, path, flags):
229229
self.fd += 1
230230
return self.fd
231231

232-
def read(self, path, size, offset, fh):
232+
def read(self, path, size, offset, fh, create=False):
233233
"""
234234
Returns content based on the pattern of the containing folder
235235
"""
236236
if path in self.files:
237-
content = self.files[path]['generator'].read(offset, offset+size-1)
238-
return content
237+
size_bytes = self.files[path]['attrs']['st_size']
238+
if offset > (size_bytes - 1):
239+
return ""
240+
else:
241+
end_of_content = min(offset+size-1, size_bytes-1)
242+
content = self.files[path]['generator'].read(offset, end_of_content)
243+
return content
239244
else:
240-
raise FuseOSError(ENOENT)
245+
if not create:
246+
raise FuseOSError(ENOENT)
247+
else:
248+
self.create(path, 0444)
249+
return self.read(path, size, offset, fh, create=create)
241250

242251
def readdir(self, path, fh):
243252
contents = ['.', '..']

tests/test_sfs.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
__author__ = 'jjw'
22

3-
from sizefs import SizeFS, SIZEFSCHARS
3+
from sizefs import SizeFS
4+
from sizefs.contents import SizeFSAlphaNumGen
45
import unittest
56

67

@@ -10,30 +11,32 @@ def test_basic(self):
1011
# Basic Test
1112

1213
sfs = SizeFS()
13-
self.assertEqual(len(sfs.read('/zeros/1B', 1, 0, None)), 1)
14-
self.assertEqual(len(sfs.read('/ones/1B', 1, 0, None)), 1)
15-
self.assertEqual(len(sfs.read('/alpha_num/1B', 1, 0, None)), 1)
14+
self.assertEqual(len(sfs.read('/zeros/1B', 1, 0, None, create=True)), 1)
15+
self.assertEqual(len(sfs.read('/ones/1B', 1, 0, None, create=True)), 1)
16+
self.assertEqual(len(sfs.read('/alpha_num/1B', 1, 0, None, create=True)), 1)
1617

1718
def test_contents(self):
1819
# Contents Test
1920

2021
sfs = SizeFS()
21-
self.assertEqual(sfs.read('/zeros/5B', 5, 0, None), '00000')
22-
self.assertEqual(sfs.read('/ones/5B', 5, 0, None), '11111')
23-
for ch in sfs.read('/alpha_num/5B', 5, 0, None):
24-
self.assertIn(ch, SIZEFSCHARS)
22+
self.assertEqual(sfs.read('/zeros/5B', 5, 0, None, create=True), '00000')
23+
self.assertEqual(sfs.read('/ones/5B', 5, 0, None, create=True), '11111')
24+
for ch in sfs.read('/alpha_num/5B', 5, 0, None, create=True):
25+
self.assertIn(ch, SizeFSAlphaNumGen.chars)
2526

2627
def test_length(self):
2728
# Length Test
2829
k128 = 128*1000
30+
k256 = 256*1000
2931
sfs = SizeFS()
30-
self.assertEqual(len(sfs.read('/128B', 128, 0, None)), 128)
31-
self.assertEqual(len(sfs.read('/128K', k128-1, 0, None)), k128-1)
32-
self.assertEqual(len(sfs.read('/128K', k128, 0, None)), k128)
33-
self.assertEqual(len(sfs.read('/128K+1B', k128+1, 0, None)), k128+1)
34-
self.assertEqual(len(sfs.read('/zeros/5B', 5, 0, None)), 5)
35-
self.assertEqual(len(sfs.read('/ones/5B', 5, 0, None)), 5)
36-
self.assertEqual(len(sfs.read('/alpha_num/5B', 5, 0, None)), 5)
32+
self.assertEqual(len(sfs.read('/zeros/128B', 128, 0, None, create=True)), 128)
33+
self.assertEqual(len(sfs.read('/zeros/128K', k128-1, 0, None, create=True)), k128-1)
34+
self.assertEqual(len(sfs.read('/alpha_num/128K', k128, 0, None, create=True)), k128)
35+
self.assertEqual(len(sfs.read('/zeros/128K+1B', k128+1, 0, None, create=True)), k128+1)
36+
self.assertEqual(len(sfs.read('/zeros/128K', k256, 0, None, create=True)), k128)
37+
self.assertEqual(len(sfs.read('/zeros/5B', 5, 0, None, create=True)), 5)
38+
self.assertEqual(len(sfs.read('/ones/5B', 5, 0, None, create=True)), 5)
39+
self.assertEqual(len(sfs.read('/alpha_num/5B', 5, 0, None, create=True)), 5)
3740

3841

3942
if __name__ == '__main__':

0 commit comments

Comments
 (0)