v2 / vlib / io / fs / fs_test.v
216 lines · 188 sloc · 4.09 KB · 24cc5e620241ab06fb63816ec6c3525846d9c687
Raw
1module fs
2
3import io
4import os
5
6struct MockInfo {
7 name_ string
8 size_ u64
9 mode_ os.FileMode
10 mod_time_ i64
11}
12
13fn (info MockInfo) name() string {
14 return info.name_
15}
16
17fn (info MockInfo) size() u64 {
18 return info.size_
19}
20
21fn (info MockInfo) mode() os.FileMode {
22 return info.mode_
23}
24
25fn (info MockInfo) mod_time() i64 {
26 return info.mod_time_
27}
28
29fn (info MockInfo) is_dir() bool {
30 return info.mode_.typ == .directory
31}
32
33struct MockFile {
34 data []u8
35 info_ MockInfo
36mut:
37 offset int
38 entries []DirEntry
39}
40
41fn (mut file MockFile) read(mut buf []u8) !int {
42 if file.offset >= file.data.len {
43 return io.Eof{}
44 }
45 read := copy(mut buf, file.data[file.offset..])
46 file.offset += read
47 return read
48}
49
50fn (file MockFile) stat() !FileInfo {
51 return file.info_
52}
53
54fn (mut file MockFile) close() {}
55
56fn (mut file MockFile) read_dir(n int) ![]DirEntry {
57 if n <= 0 || n >= file.entries.len {
58 return file.entries.clone()
59 }
60 return file.entries[..n].clone()
61}
62
63struct FallbackFS {}
64
65fn (filesystem FallbackFS) open(name string) !File {
66 match name {
67 'notes.txt' {
68 return File(MockFile{
69 data: 'fallback'.bytes()
70 info_: MockInfo{
71 name_: 'notes.txt'
72 size_: u64('fallback'.len)
73 mode_: os.FileMode{
74 typ: .regular
75 }
76 mod_time_: 101
77 }
78 })
79 }
80 'dir' {
81 return File(MockFile{
82 info_: MockInfo{
83 name_: 'dir'
84 mode_: os.FileMode{
85 typ: .directory
86 }
87 }
88 entries: [
89 file_info_to_dir_entry(MockInfo{
90 name_: 'b.txt'
91 mode_: os.FileMode{
92 typ: .regular
93 }
94 }),
95 file_info_to_dir_entry(MockInfo{
96 name_: 'a.txt'
97 mode_: os.FileMode{
98 typ: .regular
99 }
100 }),
101 ]
102 })
103 }
104 else {
105 return error('missing ${name}')
106 }
107 }
108}
109
110struct OptimizedFS {}
111
112fn (filesystem OptimizedFS) open(name string) !File {
113 return error('unexpected open for ${name}')
114}
115
116fn (filesystem OptimizedFS) read_file(name string) ![]u8 {
117 return 'optimized'.bytes()
118}
119
120fn (filesystem OptimizedFS) read_dir(name string) ![]DirEntry {
121 return [
122 file_info_to_dir_entry(MockInfo{
123 name_: 'z.txt'
124 mode_: os.FileMode{
125 typ: .regular
126 }
127 }),
128 file_info_to_dir_entry(MockInfo{
129 name_: 'm.txt'
130 mode_: os.FileMode{
131 typ: .regular
132 }
133 }),
134 ]
135}
136
137fn (filesystem OptimizedFS) stat(name string) !FileInfo {
138 return MockInfo{
139 name_: name
140 size_: 42
141 mode_: os.FileMode{
142 typ: .regular
143 }
144 mod_time_: 202
145 }
146}
147
148fn entry_names(entries []DirEntry) []string {
149 mut names := []string{cap: entries.len}
150 for entry in entries {
151 names << entry.name()
152 }
153 return names
154}
155
156fn test_valid_path() {
157 assert valid_path('.')
158 assert valid_path('alpha')
159 assert valid_path('alpha/beta')
160 assert valid_path(r'alpha\beta')
161 assert !valid_path('')
162 assert !valid_path('/alpha')
163 assert !valid_path('alpha/')
164 assert !valid_path('alpha//beta')
165 assert !valid_path('alpha/./beta')
166 assert !valid_path('alpha/../beta')
167}
168
169fn test_file_info_to_dir_entry() {
170 info := MockInfo{
171 name_: 'subdir'
172 size_: 12
173 mode_: os.FileMode{
174 typ: .directory
175 }
176 mod_time_: 303
177 }
178 entry := file_info_to_dir_entry(info)
179 assert entry.name() == 'subdir'
180 assert entry.is_dir()
181 assert entry.typ() == .directory
182 assert entry.info()!.mod_time() == 303
183}
184
185fn test_read_file_uses_open_fallback() {
186 data := read_file(FallbackFS{}, 'notes.txt')!
187 assert data == 'fallback'.bytes()
188}
189
190fn test_read_file_uses_read_file_fs_when_available() {
191 data := read_file(OptimizedFS{}, 'notes.txt')!
192 assert data == 'optimized'.bytes()
193}
194
195fn test_read_dir_uses_open_fallback_and_sorts() {
196 entries := read_dir(FallbackFS{}, 'dir')!
197 assert entry_names(entries) == ['a.txt', 'b.txt']
198}
199
200fn test_read_dir_uses_read_dir_fs_when_available() {
201 entries := read_dir(OptimizedFS{}, 'dir')!
202 assert entry_names(entries) == ['m.txt', 'z.txt']
203}
204
205fn test_stat_uses_open_fallback() {
206 info := stat(FallbackFS{}, 'notes.txt')!
207 assert info.name() == 'notes.txt'
208 assert info.size() == u64('fallback'.len)
209}
210
211fn test_stat_uses_stat_fs_when_available() {
212 info := stat(OptimizedFS{}, 'notes.txt')!
213 assert info.name() == 'notes.txt'
214 assert info.size() == 42
215 assert info.mod_time() == 202
216}
217