Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go-fuse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Levin Zimmermann
go-fuse
Commits
71c48e77
Commit
71c48e77
authored
Apr 06, 2019
by
Han-Wen Nienhuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
posixtest: new package for generic file system tests
parent
194f6362
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
341 additions
and
283 deletions
+341
-283
nodefs/simple_test.go
nodefs/simple_test.go
+12
-260
posixtest/test.go
posixtest/test.go
+326
-0
unionfs/unionfs_test.go
unionfs/unionfs_test.go
+3
-23
No files found.
nodefs/simple_test.go
View file @
71c48e77
...
@@ -5,13 +5,11 @@
...
@@ -5,13 +5,11 @@
package
nodefs
package
nodefs
import
(
import
(
"bytes"
"fmt"
"fmt"
"io/ioutil"
"io/ioutil"
"os"
"os"
"path/filepath"
"path/filepath"
"reflect"
"reflect"
"runtime"
"sync"
"sync"
"syscall"
"syscall"
"testing"
"testing"
...
@@ -19,6 +17,7 @@ import (
...
@@ -19,6 +17,7 @@ import (
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/internal/testutil"
"github.com/hanwen/go-fuse/internal/testutil"
"github.com/hanwen/go-fuse/posixtest"
)
)
type
testCase
struct
{
type
testCase
struct
{
...
@@ -132,72 +131,14 @@ func TestFileBasic(t *testing.T) {
...
@@ -132,72 +131,14 @@ func TestFileBasic(t *testing.T) {
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
content
:=
[]
byte
(
"hello world"
)
posixtest
.
FileBasic
(
t
,
tc
.
mntDir
)
fn
:=
tc
.
mntDir
+
"/file"
if
err
:=
ioutil
.
WriteFile
(
fn
,
content
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
if
got
,
err
:=
ioutil
.
ReadFile
(
fn
);
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
else
if
bytes
.
Compare
(
got
,
content
)
!=
0
{
t
.
Errorf
(
"ReadFile: got %q, want %q"
,
got
,
content
)
}
f
,
err
:=
os
.
Open
(
fn
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open: %v"
,
err
)
}
defer
f
.
Close
()
fi
,
err
:=
f
.
Stat
()
if
err
!=
nil
{
t
.
Fatalf
(
"Fstat: %v"
,
err
)
}
else
if
int
(
fi
.
Size
())
!=
len
(
content
)
{
t
.
Errorf
(
"got size %d want 5"
,
fi
.
Size
())
}
stat
:=
fuse
.
ToStatT
(
fi
)
if
got
,
want
:=
uint32
(
stat
.
Mode
),
uint32
(
fuse
.
S_IFREG
|
0755
);
got
!=
want
{
t
.
Errorf
(
"Fstat: got mode %o, want %o"
,
got
,
want
)
}
if
err
:=
f
.
Close
();
err
!=
nil
{
t
.
Errorf
(
"Close: %v"
,
err
)
}
}
}
func
TestFileTruncate
(
t
*
testing
.
T
)
{
func
TestFileTruncate
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
content
:=
[]
byte
(
"hello world"
)
posixtest
.
TruncateFile
(
t
,
tc
.
mntDir
)
tc
.
writeOrig
(
"file"
,
string
(
content
),
0755
)
f
,
err
:=
os
.
OpenFile
(
tc
.
mntDir
+
"/file"
,
os
.
O_RDWR
,
0644
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open: %v"
,
err
)
}
defer
f
.
Close
()
const
trunc
=
5
if
err
:=
f
.
Truncate
(
5
);
err
!=
nil
{
t
.
Errorf
(
"Truncate: %v"
,
err
)
}
if
err
:=
f
.
Close
();
err
!=
nil
{
t
.
Errorf
(
"Close: %v"
,
err
)
}
if
got
,
err
:=
ioutil
.
ReadFile
(
tc
.
origDir
+
"/file"
);
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
else
if
want
:=
content
[
:
trunc
];
bytes
.
Compare
(
got
,
want
)
!=
0
{
t
.
Errorf
(
"got %q, want %q"
,
got
,
want
)
}
}
}
func
TestFileFdLeak
(
t
*
testing
.
T
)
{
func
TestFileFdLeak
(
t
*
testing
.
T
)
{
...
@@ -208,24 +149,7 @@ func TestFileFdLeak(t *testing.T) {
...
@@ -208,24 +149,7 @@ func TestFileFdLeak(t *testing.T) {
}
}
}()
}()
tc
.
writeOrig
(
"file"
,
"hello world"
,
0755
)
posixtest
.
FdLeak
(
t
,
tc
.
mntDir
)
for
i
:=
0
;
i
<
100
;
i
++
{
if
_
,
err
:=
ioutil
.
ReadFile
(
tc
.
mntDir
+
"/file"
);
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
}
if
runtime
.
GOOS
==
"linux"
{
infos
,
err
:=
ioutil
.
ReadDir
(
"/proc/self/fd"
)
if
err
!=
nil
{
t
.
Errorf
(
"ReadDir %v"
,
err
)
}
if
len
(
infos
)
>
15
{
t
.
Errorf
(
"found %d open file descriptors for 100x ReadFile"
,
len
(
infos
))
}
}
tc
.
Clean
()
tc
.
Clean
()
bridge
:=
tc
.
rawFS
.
(
*
rawBridge
)
bridge
:=
tc
.
rawFS
.
(
*
rawBridge
)
...
@@ -240,54 +164,13 @@ func TestMkdir(t *testing.T) {
...
@@ -240,54 +164,13 @@ func TestMkdir(t *testing.T) {
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
if
err
:=
os
.
Mkdir
(
tc
.
mntDir
+
"/dir"
,
0755
);
err
!=
nil
{
posixtest
.
MkdirRmdir
(
t
,
tc
.
mntDir
)
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
if
fi
,
err
:=
os
.
Lstat
(
tc
.
mntDir
+
"/dir"
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat %v"
,
err
)
}
else
if
!
fi
.
IsDir
()
{
t
.
Fatalf
(
"is not a directory"
)
}
if
err
:=
os
.
Remove
(
tc
.
mntDir
+
"/dir"
);
err
!=
nil
{
t
.
Fatalf
(
"Remove: %v"
,
err
)
}
}
}
func
testRenameOverwrite
(
t
*
testing
.
T
,
destExists
bool
)
{
func
testRenameOverwrite
(
t
*
testing
.
T
,
destExists
bool
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
posixtest
.
RenameOverwrite
(
t
,
tc
.
mntDir
,
destExists
)
if
err
:=
os
.
Mkdir
(
tc
.
origDir
+
"/dir"
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
tc
.
writeOrig
(
"file"
,
"hello"
,
0644
)
if
destExists
{
tc
.
writeOrig
(
"/dir/renamed"
,
"xx"
,
0644
)
}
st
:=
syscall
.
Stat_t
{}
if
err
:=
syscall
.
Lstat
(
tc
.
mntDir
+
"/file"
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat before: %v"
,
err
)
}
beforeIno
:=
st
.
Ino
if
err
:=
os
.
Rename
(
tc
.
mntDir
+
"/file"
,
tc
.
mntDir
+
"/dir/renamed"
);
err
!=
nil
{
t
.
Errorf
(
"Rename: %v"
,
err
)
}
if
fi
,
err
:=
os
.
Lstat
(
tc
.
mntDir
+
"/file"
);
err
==
nil
{
t
.
Fatalf
(
"Lstat old: %v"
,
fi
)
}
if
err
:=
syscall
.
Lstat
(
tc
.
mntDir
+
"/dir/renamed"
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat after: %v"
,
err
)
}
if
got
:=
st
.
Ino
;
got
!=
beforeIno
{
t
.
Errorf
(
"got ino %d, want %d"
,
got
,
beforeIno
)
}
}
}
func
TestRenameDestExist
(
t
*
testing
.
T
)
{
func
TestRenameDestExist
(
t
*
testing
.
T
)
{
...
@@ -303,114 +186,28 @@ func TestNlinkZero(t *testing.T) {
...
@@ -303,114 +186,28 @@ func TestNlinkZero(t *testing.T) {
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
src
:=
tc
.
mntDir
+
"/src"
posixtest
.
NlinkZero
(
t
,
tc
.
mntDir
)
dst
:=
tc
.
mntDir
+
"/dst"
if
err
:=
ioutil
.
WriteFile
(
src
,
[]
byte
(
"source"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
if
err
:=
ioutil
.
WriteFile
(
dst
,
[]
byte
(
"dst"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
f
,
err
:=
syscall
.
Open
(
dst
,
0
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open: %v"
,
err
)
}
defer
syscall
.
Close
(
f
)
var
st
syscall
.
Stat_t
if
err
:=
syscall
.
Fstat
(
f
,
&
st
);
err
!=
nil
{
t
.
Errorf
(
"Fstat before: %v"
,
err
)
}
else
if
st
.
Nlink
!=
1
{
t
.
Errorf
(
"Nlink of file: got %d, want 1"
,
st
.
Nlink
)
}
if
err
:=
os
.
Rename
(
src
,
dst
);
err
!=
nil
{
t
.
Fatalf
(
"Rename: %v"
,
err
)
}
if
err
:=
syscall
.
Fstat
(
f
,
&
st
);
err
!=
nil
{
t
.
Errorf
(
"Fstat after: %v"
,
err
)
}
else
if
st
.
Nlink
!=
0
{
t
.
Errorf
(
"Nlink of overwritten file: got %d, want 0"
,
st
.
Nlink
)
}
}
}
func
TestParallelFileOpen
(
t
*
testing
.
T
)
{
func
TestParallelFileOpen
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
fn
:=
tc
.
mntDir
+
"/file"
posixtest
.
ParallelFileOpen
(
t
,
tc
.
mntDir
)
if
err
:=
ioutil
.
WriteFile
(
fn
,
[]
byte
(
"content"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
var
wg
sync
.
WaitGroup
one
:=
func
(
b
byte
)
{
f
,
err
:=
os
.
OpenFile
(
fn
,
os
.
O_RDWR
,
0644
)
if
err
!=
nil
{
t
.
Fatalf
(
"OpenFile: %v"
,
err
)
}
var
buf
[
10
]
byte
f
.
Read
(
buf
[
:
])
buf
[
0
]
=
b
f
.
WriteAt
(
buf
[
0
:
1
],
2
)
f
.
Close
()
wg
.
Done
()
}
for
i
:=
0
;
i
<
10
;
i
++
{
wg
.
Add
(
1
)
go
one
(
byte
(
i
))
}
wg
.
Wait
()
}
}
func
TestSymlink
(
t
*
testing
.
T
)
{
func
TestSymlink
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
fn
:=
tc
.
mntDir
+
"/link"
posixtest
.
SymlinkReadlink
(
t
,
tc
.
mntDir
)
target
:=
"target"
if
err
:=
os
.
Symlink
(
target
,
fn
);
err
!=
nil
{
t
.
Fatalf
(
"Symlink: %v"
,
err
)
}
if
got
,
err
:=
os
.
Readlink
(
fn
);
err
!=
nil
{
t
.
Fatalf
(
"Readlink: %v"
,
err
)
}
else
if
got
!=
target
{
t
.
Errorf
(
"Readlink: got %q, want %q"
,
got
,
target
)
}
}
}
func
TestLink
(
t
*
testing
.
T
)
{
func
TestLink
(
t
*
testing
.
T
)
{
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
link
:=
tc
.
mntDir
+
"/link"
posixtest
.
Link
(
t
,
tc
.
mntDir
)
target
:=
tc
.
mntDir
+
"/target"
if
err
:=
ioutil
.
WriteFile
(
target
,
[]
byte
(
"hello"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
st
:=
syscall
.
Stat_t
{}
if
err
:=
syscall
.
Lstat
(
target
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat before: %v"
,
err
)
}
beforeIno
:=
st
.
Ino
if
err
:=
os
.
Link
(
target
,
link
);
err
!=
nil
{
t
.
Errorf
(
"Link: %v"
,
err
)
}
if
err
:=
syscall
.
Lstat
(
link
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat after: %v"
,
err
)
}
if
st
.
Ino
!=
beforeIno
{
t
.
Errorf
(
"Lstat after: got %d, want %d"
,
st
.
Ino
,
beforeIno
)
}
}
}
func
TestNotifyEntry
(
t
*
testing
.
T
)
{
func
TestNotifyEntry
(
t
*
testing
.
T
)
{
...
@@ -450,38 +247,7 @@ func TestReadDir(t *testing.T) {
...
@@ -450,38 +247,7 @@ func TestReadDir(t *testing.T) {
tc
:=
newTestCase
(
t
,
true
,
true
)
tc
:=
newTestCase
(
t
,
true
,
true
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
f
,
err
:=
os
.
Open
(
tc
.
mntDir
)
posixtest
.
ReadDir
(
t
,
tc
.
mntDir
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open: %v"
,
err
)
}
defer
f
.
Close
()
// add entries after opening the directory
want
:=
map
[
string
]
bool
{}
for
i
:=
0
;
i
<
110
;
i
++
{
// 40 bytes of filename, so 110 entries overflows a
// 4096 page.
nm
:=
fmt
.
Sprintf
(
"file%036x"
,
i
)
want
[
nm
]
=
true
tc
.
writeOrig
(
nm
,
"hello"
,
0644
)
}
names
,
err
:=
f
.
Readdirnames
(
-
1
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadDir: %v"
,
err
)
}
got
:=
map
[
string
]
bool
{}
for
_
,
e
:=
range
names
{
got
[
e
]
=
true
}
if
len
(
got
)
!=
len
(
want
)
{
t
.
Errorf
(
"got %d entries, want %d"
,
len
(
got
),
len
(
want
))
}
for
k
:=
range
got
{
if
!
want
[
k
]
{
t
.
Errorf
(
"got unknown name %q"
,
k
)
}
}
}
}
// This test is racy. If an external process consumes space while this
// This test is racy. If an external process consumes space while this
...
@@ -594,19 +360,5 @@ func TestTruncate(t *testing.T) {
...
@@ -594,19 +360,5 @@ func TestTruncate(t *testing.T) {
tc
:=
newTestCase
(
t
,
false
,
false
)
tc
:=
newTestCase
(
t
,
false
,
false
)
defer
tc
.
Clean
()
defer
tc
.
Clean
()
if
err
:=
ioutil
.
WriteFile
(
tc
.
origDir
+
"/file"
,
[]
byte
(
"hello"
),
0644
);
err
!=
nil
{
posixtest
.
TruncateNoFile
(
t
,
tc
.
mntDir
)
t
.
Errorf
(
"WriteFile: %v"
,
err
)
}
if
err
:=
syscall
.
Truncate
(
tc
.
mntDir
+
"/file"
,
1
);
err
!=
nil
{
t
.
Fatalf
(
"Truncate: %v"
,
err
)
}
var
st
syscall
.
Stat_t
if
err
:=
syscall
.
Lstat
(
tc
.
mntDir
+
"/file"
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat: %v"
,
err
)
}
if
st
.
Size
!=
1
{
t
.
Errorf
(
"got size %d, want 1"
,
st
.
Size
)
}
}
}
posixtest/test.go
0 → 100644
View file @
71c48e77
// Copyright 2019 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package posixtest file systems for generic posix conformance.
package
posixtest
import
(
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"sync"
"syscall"
"testing"
"github.com/hanwen/go-fuse/fuse"
)
// SymlinkReadlink tests basic symlink functionality
func
SymlinkReadlink
(
t
*
testing
.
T
,
mnt
string
)
{
err
:=
os
.
Symlink
(
"/foobar"
,
mnt
+
"/link"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Symlink: %v"
,
err
)
}
val
,
err
:=
os
.
Readlink
(
mnt
+
"/link"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Readlink: %v"
,
err
)
}
if
val
!=
"/foobar"
{
t
.
Errorf
(
"symlink mismatch: %v"
,
val
)
}
}
func
FileBasic
(
t
*
testing
.
T
,
mnt
string
)
{
content
:=
[]
byte
(
"hello world"
)
fn
:=
mnt
+
"/file"
if
err
:=
ioutil
.
WriteFile
(
fn
,
content
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
if
got
,
err
:=
ioutil
.
ReadFile
(
fn
);
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
else
if
bytes
.
Compare
(
got
,
content
)
!=
0
{
t
.
Errorf
(
"ReadFile: got %q, want %q"
,
got
,
content
)
}
f
,
err
:=
os
.
Open
(
fn
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open: %v"
,
err
)
}
defer
f
.
Close
()
fi
,
err
:=
f
.
Stat
()
if
err
!=
nil
{
t
.
Fatalf
(
"Fstat: %v"
,
err
)
}
else
if
int
(
fi
.
Size
())
!=
len
(
content
)
{
t
.
Errorf
(
"got size %d want 5"
,
fi
.
Size
())
}
stat
:=
fuse
.
ToStatT
(
fi
)
if
got
,
want
:=
uint32
(
stat
.
Mode
),
uint32
(
fuse
.
S_IFREG
|
0755
);
got
!=
want
{
t
.
Errorf
(
"Fstat: got mode %o, want %o"
,
got
,
want
)
}
if
err
:=
f
.
Close
();
err
!=
nil
{
t
.
Errorf
(
"Close: %v"
,
err
)
}
}
func
TruncateFile
(
t
*
testing
.
T
,
mnt
string
)
{
content
:=
[]
byte
(
"hello world"
)
fn
:=
mnt
+
"/file"
if
err
:=
ioutil
.
WriteFile
(
fn
,
content
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
f
,
err
:=
os
.
OpenFile
(
fn
,
os
.
O_RDWR
,
0644
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open: %v"
,
err
)
}
defer
f
.
Close
()
const
trunc
=
5
if
err
:=
f
.
Truncate
(
5
);
err
!=
nil
{
t
.
Errorf
(
"Truncate: %v"
,
err
)
}
if
err
:=
f
.
Close
();
err
!=
nil
{
t
.
Errorf
(
"Close: %v"
,
err
)
}
if
got
,
err
:=
ioutil
.
ReadFile
(
fn
);
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
else
if
want
:=
content
[
:
trunc
];
bytes
.
Compare
(
got
,
want
)
!=
0
{
t
.
Errorf
(
"got %q, want %q"
,
got
,
want
)
}
}
func
TruncateNoFile
(
t
*
testing
.
T
,
mnt
string
)
{
fn
:=
mnt
+
"/file"
if
err
:=
ioutil
.
WriteFile
(
fn
,
[]
byte
(
"hello"
),
0644
);
err
!=
nil
{
t
.
Errorf
(
"WriteFile: %v"
,
err
)
}
if
err
:=
syscall
.
Truncate
(
fn
,
1
);
err
!=
nil
{
t
.
Fatalf
(
"Truncate: %v"
,
err
)
}
var
st
syscall
.
Stat_t
if
err
:=
syscall
.
Lstat
(
fn
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat: %v"
,
err
)
}
if
st
.
Size
!=
1
{
t
.
Errorf
(
"got size %d, want 1"
,
st
.
Size
)
}
}
func
FdLeak
(
t
*
testing
.
T
,
mnt
string
)
{
fn
:=
mnt
+
"/file"
if
err
:=
ioutil
.
WriteFile
(
fn
,
[]
byte
(
"hello world"
),
0755
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
for
i
:=
0
;
i
<
100
;
i
++
{
if
_
,
err
:=
ioutil
.
ReadFile
(
fn
);
err
!=
nil
{
t
.
Fatalf
(
"ReadFile: %v"
,
err
)
}
}
if
runtime
.
GOOS
==
"linux"
{
infos
,
err
:=
ioutil
.
ReadDir
(
"/proc/self/fd"
)
if
err
!=
nil
{
t
.
Errorf
(
"ReadDir %v"
,
err
)
}
if
len
(
infos
)
>
15
{
t
.
Errorf
(
"found %d open file descriptors for 100x ReadFile"
,
len
(
infos
))
}
}
}
func
MkdirRmdir
(
t
*
testing
.
T
,
mnt
string
)
{
fn
:=
mnt
+
"/dir"
if
err
:=
os
.
Mkdir
(
fn
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
if
fi
,
err
:=
os
.
Lstat
(
fn
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat %v"
,
err
)
}
else
if
!
fi
.
IsDir
()
{
t
.
Fatalf
(
"is not a directory"
)
}
if
err
:=
os
.
Remove
(
fn
);
err
!=
nil
{
t
.
Fatalf
(
"Remove: %v"
,
err
)
}
}
func
NlinkZero
(
t
*
testing
.
T
,
mnt
string
)
{
src
:=
mnt
+
"/src"
dst
:=
mnt
+
"/dst"
if
err
:=
ioutil
.
WriteFile
(
src
,
[]
byte
(
"source"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
if
err
:=
ioutil
.
WriteFile
(
dst
,
[]
byte
(
"dst"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
f
,
err
:=
syscall
.
Open
(
dst
,
0
,
0
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open: %v"
,
err
)
}
defer
syscall
.
Close
(
f
)
var
st
syscall
.
Stat_t
if
err
:=
syscall
.
Fstat
(
f
,
&
st
);
err
!=
nil
{
t
.
Errorf
(
"Fstat before: %v"
,
err
)
}
else
if
st
.
Nlink
!=
1
{
t
.
Errorf
(
"Nlink of file: got %d, want 1"
,
st
.
Nlink
)
}
if
err
:=
os
.
Rename
(
src
,
dst
);
err
!=
nil
{
t
.
Fatalf
(
"Rename: %v"
,
err
)
}
if
err
:=
syscall
.
Fstat
(
f
,
&
st
);
err
!=
nil
{
t
.
Errorf
(
"Fstat after: %v"
,
err
)
}
else
if
st
.
Nlink
!=
0
{
t
.
Errorf
(
"Nlink of overwritten file: got %d, want 0"
,
st
.
Nlink
)
}
}
func
ParallelFileOpen
(
t
*
testing
.
T
,
mnt
string
)
{
fn
:=
mnt
+
"/file"
if
err
:=
ioutil
.
WriteFile
(
fn
,
[]
byte
(
"content"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
var
wg
sync
.
WaitGroup
one
:=
func
(
b
byte
)
{
f
,
err
:=
os
.
OpenFile
(
fn
,
os
.
O_RDWR
,
0644
)
if
err
!=
nil
{
t
.
Fatalf
(
"OpenFile: %v"
,
err
)
}
var
buf
[
10
]
byte
f
.
Read
(
buf
[
:
])
buf
[
0
]
=
b
f
.
WriteAt
(
buf
[
0
:
1
],
2
)
f
.
Close
()
wg
.
Done
()
}
for
i
:=
0
;
i
<
10
;
i
++
{
wg
.
Add
(
1
)
go
one
(
byte
(
i
))
}
wg
.
Wait
()
}
func
Link
(
t
*
testing
.
T
,
mnt
string
)
{
link
:=
mnt
+
"/link"
target
:=
mnt
+
"/target"
if
err
:=
ioutil
.
WriteFile
(
target
,
[]
byte
(
"hello"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
st
:=
syscall
.
Stat_t
{}
if
err
:=
syscall
.
Lstat
(
target
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat before: %v"
,
err
)
}
beforeIno
:=
st
.
Ino
if
err
:=
os
.
Link
(
target
,
link
);
err
!=
nil
{
t
.
Errorf
(
"Link: %v"
,
err
)
}
if
err
:=
syscall
.
Lstat
(
link
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat after: %v"
,
err
)
}
if
st
.
Ino
!=
beforeIno
{
t
.
Errorf
(
"Lstat after: got %d, want %d"
,
st
.
Ino
,
beforeIno
)
}
}
func
RenameOverwrite
(
t
*
testing
.
T
,
mnt
string
,
destExists
bool
)
{
if
err
:=
os
.
Mkdir
(
mnt
+
"/dir"
,
0755
);
err
!=
nil
{
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
if
err
:=
ioutil
.
WriteFile
(
mnt
+
"/file"
,
[]
byte
(
"hello"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile: %v"
,
err
)
}
if
destExists
{
if
err
:=
ioutil
.
WriteFile
(
mnt
+
"/dir/renamed"
,
[]
byte
(
"xx"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile dest: %v"
,
err
)
}
}
st
:=
syscall
.
Stat_t
{}
if
err
:=
syscall
.
Lstat
(
mnt
+
"/file"
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat before: %v"
,
err
)
}
beforeIno
:=
st
.
Ino
if
err
:=
os
.
Rename
(
mnt
+
"/file"
,
mnt
+
"/dir/renamed"
);
err
!=
nil
{
t
.
Errorf
(
"Rename: %v"
,
err
)
}
if
fi
,
err
:=
os
.
Lstat
(
mnt
+
"/file"
);
err
==
nil
{
t
.
Fatalf
(
"Lstat old: %v"
,
fi
)
}
if
err
:=
syscall
.
Lstat
(
mnt
+
"/dir/renamed"
,
&
st
);
err
!=
nil
{
t
.
Fatalf
(
"Lstat after: %v"
,
err
)
}
if
got
:=
st
.
Ino
;
got
!=
beforeIno
{
t
.
Errorf
(
"got ino %d, want %d"
,
got
,
beforeIno
)
}
}
func
ReadDir
(
t
*
testing
.
T
,
mnt
string
)
{
f
,
err
:=
os
.
Open
(
mnt
)
if
err
!=
nil
{
t
.
Fatalf
(
"Open: %v"
,
err
)
}
defer
f
.
Close
()
// add entries after opening the directory
want
:=
map
[
string
]
bool
{}
for
i
:=
0
;
i
<
110
;
i
++
{
// 40 bytes of filename, so 110 entries overflows a
// 4096 page.
nm
:=
fmt
.
Sprintf
(
"file%036x"
,
i
)
want
[
nm
]
=
true
if
err
:=
ioutil
.
WriteFile
(
filepath
.
Join
(
mnt
,
nm
),
[]
byte
(
"hello"
),
0644
);
err
!=
nil
{
t
.
Fatalf
(
"WriteFile %q: %v"
,
nm
,
err
)
}
}
names
,
err
:=
f
.
Readdirnames
(
-
1
)
if
err
!=
nil
{
t
.
Fatalf
(
"ReadDir: %v"
,
err
)
}
got
:=
map
[
string
]
bool
{}
for
_
,
e
:=
range
names
{
got
[
e
]
=
true
}
if
len
(
got
)
!=
len
(
want
)
{
t
.
Errorf
(
"got %d entries, want %d"
,
len
(
got
),
len
(
want
))
}
for
k
:=
range
got
{
if
!
want
[
k
]
{
t
.
Errorf
(
"got unknown name %q"
,
k
)
}
}
}
unionfs/unionfs_test.go
View file @
71c48e77
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/internal/testutil"
"github.com/hanwen/go-fuse/internal/testutil"
"github.com/hanwen/go-fuse/posixtest"
)
)
func
TestFilePathHash
(
t
*
testing
.
T
)
{
func
TestFilePathHash
(
t
*
testing
.
T
)
{
...
@@ -203,19 +204,7 @@ func TestUnionFsSymlink(t *testing.T) {
...
@@ -203,19 +204,7 @@ func TestUnionFsSymlink(t *testing.T) {
wd
,
clean
:=
setupUfs
(
t
)
wd
,
clean
:=
setupUfs
(
t
)
defer
clean
()
defer
clean
()
err
:=
os
.
Symlink
(
"/foobar"
,
wd
+
"/mnt/link"
)
posixtest
.
SymlinkReadlink
(
t
,
wd
+
"/mnt"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Symlink: %v"
,
err
)
}
val
,
err
:=
os
.
Readlink
(
wd
+
"/mnt/link"
)
if
err
!=
nil
{
t
.
Fatalf
(
"Readlink: %v"
,
err
)
}
if
val
!=
"/foobar"
{
t
.
Errorf
(
"symlink mismatch: %v"
,
val
)
}
}
}
func
TestUnionFsSymlinkPromote
(
t
*
testing
.
T
)
{
func
TestUnionFsSymlinkPromote
(
t
*
testing
.
T
)
{
...
@@ -447,16 +436,7 @@ func TestUnionFsMkdir(t *testing.T) {
...
@@ -447,16 +436,7 @@ func TestUnionFsMkdir(t *testing.T) {
wd
,
clean
:=
setupUfs
(
t
)
wd
,
clean
:=
setupUfs
(
t
)
defer
clean
()
defer
clean
()
dirname
:=
wd
+
"/mnt/subdir"
posixtest
.
MkdirRmdir
(
t
,
wd
+
"/mnt"
)
err
:=
os
.
Mkdir
(
dirname
,
0755
)
if
err
!=
nil
{
t
.
Fatalf
(
"Mkdir: %v"
,
err
)
}
err
=
os
.
Remove
(
dirname
)
if
err
!=
nil
{
t
.
Fatalf
(
"Remove: %v"
,
err
)
}
}
}
func
TestUnionFsMkdirPromote
(
t
*
testing
.
T
)
{
func
TestUnionFsMkdirPromote
(
t
*
testing
.
T
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment