• R/O
  • SSH
  • HTTPS

perl-fuse-fv: Commit


Commit MetaInfo

Revision71 (tree)
Zeit2011-07-17 20:30:39
Autortofjw

Log Message

add Test::Virtual::Filesystem support (but not run correctly, yet)

Ändern Zusammenfassung

Diff

--- Fuse-Class/trunk/test/test28.pm (revision 70)
+++ Fuse-Class/trunk/test/test28.pm (nonexistent)
@@ -1,275 +0,0 @@
1-#
2-# test filesystem for Fuse 2.8
3-# (file operations are done via file/directory handle.)
4-#
5-
6-use strict;
7-use warnings;
8-
9-use Fcntl;
10-
11-package test::test28;
12-
13-use base qw(Fuse::Class);
14-
15-sub new {
16- my $class = shift;
17-
18- my $t = 12345;
19-
20- my $self = {
21- content => {
22- '/' => {
23- attr => [0, 0,
24- Fcntl::S_IFDIR
25- | Fcntl::S_IRWXU | Fcntl::S_IRWXG | Fcntl::S_IRWXO,
26- 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
27- }
28- },
29-
30- handle => {
31- }
32- };
33-
34- use Data::Dumper;
35- print Dumper($self);
36- return bless $self, $class;
37-}
38-
39-sub issue_handle {
40- my $self = shift;
41- my ($path) = @_;
42-
43- my $i = 0;
44- while ($self->{handle}->{$i}) {
45- $i++;
46- }
47-
48- $self->{handle}->{$i} = [$path, $self->{content}->{$path}];
49-
50- return $i;
51-}
52-
53-sub release_handle {
54- my $self = shift;
55- my ($fh) = @_;
56-
57- delete $self->{handle}->{$fh};
58-}
59-
60-sub getattr {
61- my $self = shift;
62- my ($path) = @_;
63-
64- return -2 unless ($self->{content}->{$path});
65-
66- return @{$self->{content}->{$path}->{attr}};
67-}
68-
69-sub readlink {
70- my $self = shift;
71-
72- return '/readlink/result';
73-}
74-
75-sub getdir {
76- my $self = shift;
77- my ($path) = @_;
78-
79- die "this function must not be called.";
80-}
81-
82-sub mknod {
83- my $self = shift;
84- my ($path, $mode, $devno) = @_;
85-
86- return -1 if ($self->{content}->{$path});
87-
88- my $t = time;
89-
90- $self->{content}->{$path} = {
91- attr => [0, 0, $mode, 1,
92- $>+0, $)+0, $devno, 0, $t, $t, $t,
93- 4096, 0,
94- ],
95- content => '',
96- };
97- return 0;
98-}
99-
100-sub mkdir {
101- my $self = shift;
102- my ($path, $mode) = @_;
103-
104- return -1 if ($self->{content}->{$path});
105-
106- $mode |= Fcntl::S_IFDIR;
107- my $t = time;
108-
109- $self->{content}->{$path} = {
110- attr => [0, 0, $mode, 1,
111- $>+0, $)+0, 0, 0, $t, $t, $t,
112- 1, 0,
113- ],
114- content => '',
115- };
116- return 0;
117-}
118-
119-sub unlink {
120- my $self = shift;
121- my ($path) = @_;
122-
123- delete $self->{content}->{$path};
124-
125- return 0;
126-}
127-
128-sub rmdir {
129- my $self = shift;
130- my ($path) = @_;
131-
132- my $s = '/';
133- my $prefix = $path;
134- $prefix .= $s unless ($prefix =~ /\Q$s\E$/);
135-
136- my @names = grep { m|^\Q$prefix\E| } keys %{$self->{content}};
137- unshift(@names, $path);
138-
139- for my $p (@names) {
140- delete $self->{content}->{$p};
141- }
142-
143- use Data::Dumper;
144- print STDERR Dumper($self);
145-
146- return 0;
147-}
148-
149-sub opendir {
150- my $self = shift;
151- my ($path) = @_;
152-
153- return (-2) unless ($self->{content}->{$path});
154-
155- return (0, $self->issue_handle($path));
156-}
157-
158-sub readdir {
159- my $self = shift;
160- my ($path, $offset, $dh) = @_;
161-
162- return (-2) unless (defined($self->{handle}->{$dh}));
163-
164- my $s = '/';
165- my $prefix = $self->{handle}->{$dh}->[0];
166- $prefix .= $s unless ($prefix =~ /\Q$s\E$/);
167-
168- my @names =
169- map { substr($_, length($prefix)) }
170- sort
171- grep { m|^\Q$prefix\E[^\Q$s\E]+$| } keys %{$self->{content}};
172-
173- unshift(@names, '.');
174-
175- if ($offset < @names) {
176- return (@names[$offset..$#names], 0);
177- }
178-
179- return (0);
180-}
181-
182-sub releasedir {
183- my $self = shift;
184- my ($path, $dh) = @_;
185-
186- if ($self->{handle}->{$dh}) {
187- $self->release_handle($dh);
188- return 0;
189- }
190-
191- return -2;
192-}
193-
194-sub truncate {
195- my $self = shift;
196- my ($path, $offset, $fh) = @_;
197-
198- return -2 unless (defined($self->{content}->{$path}));
199-
200- my $data = $self->{content}->{$path}->{content};
201- return -1 unless (defined($data));
202-
203- $self->{content}->{$path}->{content} = substr($data, 0, $offset);
204-
205- return 0;
206-}
207-
208-sub utime {
209- my $self = shift;
210- my ($path, $atime, $mtime) = @_;
211-
212- die "utimens must be called";
213-}
214-
215-sub open {
216- my $self = shift;
217- my ($path, $flags, $fileinfo) = @_;
218-
219- print STDERR "open: $path, $flags\n";
220- use Data::Dumper;
221- print STDERR Dumper($fileinfo);
222-
223- return (-2) unless ($self->{content}->{$path});
224-
225- return (0, $self->issue_handle($path));
226-}
227-
228-sub write {
229- my $self = shift;
230- my ($path, $buffer, $offset, $fh) = @_;
231-
232- return (-2) unless (defined($self->{handle}->{$fh}));
233-
234- my $file = $self->{handle}->{$fh}->[1];
235- my $data = $file->{content};
236- substr($data, $offset) = $buffer;
237- $file->{content} = $data;
238- $file->{attr}->[7] = length($data);
239-
240- return length($buffer);
241-}
242-
243-sub read {
244- my $self = shift;
245- my ($path, $size, $offset, $fh) = @_;
246-
247- return (-2) unless (defined($self->{handle}->{$fh}));
248-
249- my $file = $self->{handle}->{$fh}->[1];
250- my $data = $file->{content};
251-
252- return substr($data, $offset, $size);
253-}
254-
255-sub statfs {
256- my $self = shift;
257-
258- return (255, 50000, 40000, 30000, 20000, 10000);
259-}
260-
261-sub utimens {
262- my $self = shift;
263- my ($path, $atime, $mtime) = @_;
264-
265- return -2 unless ($self->{content}->{$path});
266-
267- my $attr = $self->{content}->{$path}->{attr};
268-
269- $attr->[8] = $atime;
270- $attr->[9] = $mtime;
271-
272- return 0;
273-}
274-
275-1;
--- Fuse-Class/trunk/test/fuse28.pm (nonexistent)
+++ Fuse-Class/trunk/test/fuse28.pm (revision 71)
@@ -0,0 +1,275 @@
1+#
2+# test filesystem for Fuse 2.8
3+# (file operations are done via file/directory handle.)
4+#
5+
6+use strict;
7+use warnings;
8+
9+use Fcntl;
10+
11+package test::fuse28;
12+
13+use base qw(Fuse::Class);
14+
15+sub new {
16+ my $class = shift;
17+
18+ my $t = 12345;
19+
20+ my $self = {
21+ content => {
22+ '/' => {
23+ attr => [0, 0,
24+ Fcntl::S_IFDIR
25+ | Fcntl::S_IRWXU | Fcntl::S_IRWXG | Fcntl::S_IRWXO,
26+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
27+ }
28+ },
29+
30+ handle => {
31+ }
32+ };
33+
34+ use Data::Dumper;
35+ print Dumper($self);
36+ return bless $self, $class;
37+}
38+
39+sub issue_handle {
40+ my $self = shift;
41+ my ($path) = @_;
42+
43+ my $i = 0;
44+ while ($self->{handle}->{$i}) {
45+ $i++;
46+ }
47+
48+ $self->{handle}->{$i} = [$path, $self->{content}->{$path}];
49+
50+ return $i;
51+}
52+
53+sub release_handle {
54+ my $self = shift;
55+ my ($fh) = @_;
56+
57+ delete $self->{handle}->{$fh};
58+}
59+
60+sub getattr {
61+ my $self = shift;
62+ my ($path) = @_;
63+
64+ return -2 unless ($self->{content}->{$path});
65+
66+ return @{$self->{content}->{$path}->{attr}};
67+}
68+
69+sub readlink {
70+ my $self = shift;
71+
72+ return '/readlink/result';
73+}
74+
75+sub getdir {
76+ my $self = shift;
77+ my ($path) = @_;
78+
79+ die "this function must not be called.";
80+}
81+
82+sub mknod {
83+ my $self = shift;
84+ my ($path, $mode, $devno) = @_;
85+
86+ return -1 if ($self->{content}->{$path});
87+
88+ my $t = time;
89+
90+ $self->{content}->{$path} = {
91+ attr => [0, 0, $mode, 1,
92+ $>+0, $)+0, $devno, 0, $t, $t, $t,
93+ 4096, 0,
94+ ],
95+ content => '',
96+ };
97+ return 0;
98+}
99+
100+sub mkdir {
101+ my $self = shift;
102+ my ($path, $mode) = @_;
103+
104+ return -1 if ($self->{content}->{$path});
105+
106+ $mode |= Fcntl::S_IFDIR;
107+ my $t = time;
108+
109+ $self->{content}->{$path} = {
110+ attr => [0, 0, $mode, 1,
111+ $>+0, $)+0, 0, 0, $t, $t, $t,
112+ 1, 0,
113+ ],
114+ content => '',
115+ };
116+ return 0;
117+}
118+
119+sub unlink {
120+ my $self = shift;
121+ my ($path) = @_;
122+
123+ delete $self->{content}->{$path};
124+
125+ return 0;
126+}
127+
128+sub rmdir {
129+ my $self = shift;
130+ my ($path) = @_;
131+
132+ my $s = '/';
133+ my $prefix = $path;
134+ $prefix .= $s unless ($prefix =~ /\Q$s\E$/);
135+
136+ my @names = grep { m|^\Q$prefix\E| } keys %{$self->{content}};
137+ unshift(@names, $path);
138+
139+ for my $p (@names) {
140+ delete $self->{content}->{$p};
141+ }
142+
143+ # use Data::Dumper;
144+ # print STDERR Dumper($self);
145+
146+ return 0;
147+}
148+
149+sub opendir {
150+ my $self = shift;
151+ my ($path) = @_;
152+
153+ return (-2) unless ($self->{content}->{$path});
154+
155+ return (0, $self->issue_handle($path));
156+}
157+
158+sub readdir {
159+ my $self = shift;
160+ my ($path, $offset, $dh) = @_;
161+
162+ return (-2) unless (defined($self->{handle}->{$dh}));
163+
164+ my $s = '/';
165+ my $prefix = $self->{handle}->{$dh}->[0];
166+ $prefix .= $s unless ($prefix =~ /\Q$s\E$/);
167+
168+ my @names =
169+ map { substr($_, length($prefix)) }
170+ sort
171+ grep { m|^\Q$prefix\E[^\Q$s\E]+$| } keys %{$self->{content}};
172+
173+ unshift(@names, '.');
174+
175+ if ($offset < @names) {
176+ return (@names[$offset..$#names], 0);
177+ }
178+
179+ return (0);
180+}
181+
182+sub releasedir {
183+ my $self = shift;
184+ my ($path, $dh) = @_;
185+
186+ if ($self->{handle}->{$dh}) {
187+ $self->release_handle($dh);
188+ return 0;
189+ }
190+
191+ return -2;
192+}
193+
194+sub truncate {
195+ my $self = shift;
196+ my ($path, $offset, $fh) = @_;
197+
198+ return -2 unless (defined($self->{content}->{$path}));
199+
200+ my $data = $self->{content}->{$path}->{content};
201+ return -1 unless (defined($data));
202+
203+ $self->{content}->{$path}->{content} = substr($data, 0, $offset);
204+
205+ return 0;
206+}
207+
208+sub utime {
209+ my $self = shift;
210+ my ($path, $atime, $mtime) = @_;
211+
212+ die "utimens must be called";
213+}
214+
215+sub open {
216+ my $self = shift;
217+ my ($path, $flags, $fileinfo) = @_;
218+
219+ print STDERR "open: $path, $flags\n";
220+ # use Data::Dumper;
221+ # print STDERR Dumper($fileinfo);
222+
223+ return (-2) unless ($self->{content}->{$path});
224+
225+ return (0, $self->issue_handle($path));
226+}
227+
228+sub write {
229+ my $self = shift;
230+ my ($path, $buffer, $offset, $fh) = @_;
231+
232+ return (-2) unless (defined($self->{handle}->{$fh}));
233+
234+ my $file = $self->{handle}->{$fh}->[1];
235+ my $data = $file->{content};
236+ substr($data, $offset) = $buffer;
237+ $file->{content} = $data;
238+ $file->{attr}->[7] = length($data);
239+
240+ return length($buffer);
241+}
242+
243+sub read {
244+ my $self = shift;
245+ my ($path, $size, $offset, $fh) = @_;
246+
247+ return (-2) unless (defined($self->{handle}->{$fh}));
248+
249+ my $file = $self->{handle}->{$fh}->[1];
250+ my $data = $file->{content};
251+
252+ return substr($data, $offset, $size);
253+}
254+
255+sub statfs {
256+ my $self = shift;
257+
258+ return (255, 50000, 40000, 30000, 20000, 10000);
259+}
260+
261+sub utimens {
262+ my $self = shift;
263+ my ($path, $atime, $mtime) = @_;
264+
265+ return -2 unless ($self->{content}->{$path});
266+
267+ my $attr = $self->{content}->{$path}->{attr};
268+
269+ $attr->[8] = $atime;
270+ $attr->[9] = $mtime;
271+
272+ return 0;
273+}
274+
275+1;
--- Fuse-Class/trunk/t/subclass.t (revision 70)
+++ Fuse-Class/trunk/t/subclass.t (nonexistent)
@@ -1,89 +0,0 @@
1-
2-use strict;
3-
4-use Test::More tests => 14;
5-
6-#################################################
7-package TestClass;
8-
9-use base qw(Fuse::Class);
10-
11-sub getdir {
12- my $self = shift;
13- my ($dir) = @_;
14-
15- return (".", "..", "x$dir", 0);
16-}
17-
18-sub mknod {
19- my $self = shift;
20- my ($fname) = @_;
21-
22- $! = Errno::EINTR;
23- die "error";
24-}
25-
26-sub mkdir {
27- my $self = shift;
28- my ($fname) = @_;
29-
30- $! = 0;
31- die "error";
32-}
33-
34-#################################################
35-
36-package main;
37-
38-my %Fuse_main;
39-
40-#
41-# override Fuse::main for test
42-#
43-{
44- no warnings "redefine";
45- no strict "refs";
46-
47- *Fuse::main = sub {
48- %Fuse_main = @_;
49- for my $k (keys %Fuse_main) {
50- my $subname = $Fuse_main{$k};
51- $Fuse_main{$k} = sub { &$subname(@_); };
52- }
53- };
54-}
55-
56-use Errno;
57-
58-my $fs = TestClass->new();
59-is(ref($fs), "TestClass", "constructor");
60-
61-$fs->main(mountpoint => "/never-found");
62-$Fuse::Class::_Module = $fs; # set in Fuse::Class
63-
64-# overrided method
65-my $getdir = $Fuse_main{getdir};
66-is_deeply([&$getdir("abc")], [".", "..", "xabc", 0]);
67-
68-# error (in $!)
69-my $mknod = $Fuse_main{mknod};
70-is(&$mknod("/never-found"), -Errno::EINTR());
71-
72-# error (not in $!)
73-my $mkdir = $Fuse_main{mkdir};
74-is(&$mkdir("/never-found"), -Errno::EPERM());
75-
76-# not implemented
77-my $getattr = $Fuse_main{getattr};
78-is($fs->can('getattr') ? &$getattr("/") : -Errno::EPERM(), -Errno::EPERM());
79-
80-# default implement
81-is($fs->readlink("/not/found"), -Errno::ENOENT());
82-is($fs->statfs(), -Errno::ENOANO());
83-is($fs->flush("/some/file"), 0);
84-is($fs->release("/some/file"), 0);
85-is($fs->fsync("/some/file"), 0);
86-is($fs->getxattr("/some/file"), 0);
87-is($fs->listxattr("/some/file"), 0);
88-is($fs->removexattr("/some/file"), 0);
89-is($fs->setxattr("/some/file", "name", "value", 0), -Errno::EOPNOTSUPP());
--- Fuse-Class/trunk/t/10subclass.t (nonexistent)
+++ Fuse-Class/trunk/t/10subclass.t (revision 71)
@@ -0,0 +1,89 @@
1+
2+use strict;
3+
4+use Test::More tests => 14;
5+
6+#################################################
7+package TestClass;
8+
9+use base qw(Fuse::Class);
10+
11+sub getdir {
12+ my $self = shift;
13+ my ($dir) = @_;
14+
15+ return (".", "..", "x$dir", 0);
16+}
17+
18+sub mknod {
19+ my $self = shift;
20+ my ($fname) = @_;
21+
22+ $! = Errno::EINTR;
23+ die "error";
24+}
25+
26+sub mkdir {
27+ my $self = shift;
28+ my ($fname) = @_;
29+
30+ $! = 0;
31+ die "error";
32+}
33+
34+#################################################
35+
36+package main;
37+
38+my %Fuse_main;
39+
40+#
41+# override Fuse::main for test
42+#
43+{
44+ no warnings "redefine";
45+ no strict "refs";
46+
47+ *Fuse::main = sub {
48+ %Fuse_main = @_;
49+ for my $k (keys %Fuse_main) {
50+ my $subname = $Fuse_main{$k};
51+ $Fuse_main{$k} = sub { &$subname(@_); };
52+ }
53+ };
54+}
55+
56+use Errno;
57+
58+my $fs = TestClass->new();
59+is(ref($fs), "TestClass", "constructor");
60+
61+$fs->main(mountpoint => "/never-found");
62+$Fuse::Class::_Module = $fs; # set in Fuse::Class
63+
64+# overrided method
65+my $getdir = $Fuse_main{getdir};
66+is_deeply([&$getdir("abc")], [".", "..", "xabc", 0]);
67+
68+# error (in $!)
69+my $mknod = $Fuse_main{mknod};
70+is(&$mknod("/never-found"), -Errno::EINTR());
71+
72+# error (not in $!)
73+my $mkdir = $Fuse_main{mkdir};
74+is(&$mkdir("/never-found"), -Errno::EPERM());
75+
76+# not implemented
77+my $getattr = $Fuse_main{getattr};
78+is($fs->can('getattr') ? &$getattr("/") : -Errno::EPERM(), -Errno::EPERM());
79+
80+# default implement
81+is($fs->readlink("/not/found"), -Errno::ENOENT());
82+is($fs->statfs(), -Errno::ENOANO());
83+is($fs->flush("/some/file"), 0);
84+is($fs->release("/some/file"), 0);
85+is($fs->fsync("/some/file"), 0);
86+is($fs->getxattr("/some/file"), 0);
87+is($fs->listxattr("/some/file"), 0);
88+is($fs->removexattr("/some/file"), 0);
89+is($fs->setxattr("/some/file", "name", "value", 0), -Errno::EOPNOTSUPP());
--- Fuse-Class/trunk/t/80fuse28.t (nonexistent)
+++ Fuse-Class/trunk/t/80fuse28.t (revision 71)
@@ -0,0 +1,114 @@
1+#
2+# test filesystem using test::fuse28.pm test mudule
3+#
4+
5+use strict;
6+use POSIX ":sys_wait_h";
7+use Test::Class;
8+use Test::More;
9+use Fuse;
10+
11+use test::fuse28;
12+
13+my $mount_point = "/tmp/fuse-class-test-$<-$$";
14+
15+my $reason = "no reason (test error?)";
16+
17+sub start_check {
18+ #
19+ # Fuse version must be 2.8 or later for this test.
20+ #
21+ my $version = Fuse::fuse_version;
22+ if ($version < 2.8) {
23+ $reason = "Fuse version is lower than 2.8.";
24+ return 0;
25+ }
26+
27+ #
28+ # fusermount command is available?
29+ #
30+ my $res = `fusermount -V 2>&1`;
31+ unless ($res =~ /version/) {
32+ $reason = "fusermount command is not available.";
33+ return 0;
34+ }
35+
36+ #
37+ # Test::Virtual::Filesystem
38+ #
39+ eval "use Test::Virtual::Filesystem;";
40+ if ($@) {
41+ $reason = "Test::Virtual::Filesystem is not available.";
42+ return 0;
43+ }
44+
45+ return 1;
46+}
47+
48+#
49+# start Fuse main loop in child process
50+#
51+sub child_process {
52+ mkdir $mount_point, 0777;
53+ diag $mount_point;
54+ die "$mount_point: cannot create directoy: $!" unless (-d $mount_point);
55+
56+ my $fs = new test::fuse28;
57+ $fs->main(mountpoint => $mount_point);
58+}
59+
60+sub cleanup {
61+ my $child_pid = shift;
62+
63+ my $kid = 0;
64+ my $n = 0;
65+ do {
66+ system("fusermount", "-u", $mount_point);
67+ sleep(1);
68+ $kid = waitpid $child_pid, WNOHANG;
69+ } while($kid != $child_pid && $n++ < 10);
70+
71+ rmdir $mount_point;
72+}
73+
74+#
75+# test start
76+#
77+unless (start_check) {
78+ plan skip_all => $reason;
79+}
80+else {
81+ eval "use Test::Virtual::Filesystem;";
82+ my $child_pid = -1;
83+
84+ eval {
85+ plan tests => 1;
86+ is(1, 1);
87+ $child_pid = fork();
88+ die $! if ($child_pid < 0);
89+
90+ if ($child_pid == 0) {
91+ child_process;
92+ exit 0;
93+ }
94+
95+ sleep(3);
96+
97+ my $test = Test::Virtual::Filesystem->new({mountdir => $mount_point,
98+ compatible => '0.03'});
99+ $test->enable_test_xattr(1);
100+ # $test->enable_test_chown(1);
101+ # $test->enable_test_atime(1);
102+ $test->runtests;
103+
104+ system("df");
105+ };
106+
107+ my $err = $@;
108+ cleanup($child_pid);
109+
110+ if ($child_pid > 0) {
111+ }
112+
113+ die $err if ($err);
114+}
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
--- Fuse-Class/trunk/lib/Fuse/Class.pm (revision 70)
+++ Fuse-Class/trunk/lib/Fuse/Class.pm (revision 71)
@@ -458,9 +458,9 @@
458458
459459 Returns an errno, and a directory handle (optional)
460460
461-Called when opening a directory for reading. If special handling is
462-required to open a directory, this operation can be implemented to handle
463-that.
461+This method is called to open a directory for reading.
462+If special handling is required to open a directory, this method
463+can be implemented.
464464
465465 Supported by Fuse version 2.3 or later.
466466
Show on old repository browser