Split off manifest and multi FS tests into separate file.
Change-Id: I02a1325d5fc3a5340f1f4c1d6877ac0f2f8e9101
diff --git a/fs/gitilesfs_test.go b/fs/gitilesfs_test.go
index 797358d..ffb0961 100644
--- a/fs/gitilesfs_test.go
+++ b/fs/gitilesfs_test.go
@@ -24,20 +24,15 @@
"os"
"os/exec"
"path/filepath"
- "reflect"
"regexp"
- "sort"
"strings"
"sync"
"syscall"
"testing"
"time"
- "github.com/google/slothfs/cache"
"github.com/google/slothfs/gitiles"
"github.com/google/slothfs/manifest"
- "github.com/hanwen/go-fuse/fuse"
- "github.com/hanwen/go-fuse/fuse/nodefs"
)
const fuseDebug = false
@@ -373,7 +368,7 @@
}
}
-func TestGitilesFS(t *testing.T) {
+func TestGitilesFSBasic(t *testing.T) {
fix, err := newTestFixture()
if err != nil {
t.Fatal("newTestFixture", err)
@@ -508,360 +503,3 @@
}
}
}
-
-func newManifestTestFixture(mf *manifest.Manifest) (*testFixture, error) {
- fix, err := newTestFixture()
- if err != nil {
- return nil, err
- }
-
- opts := ManifestOptions{
- Manifest: mf,
- }
-
- fs, err := NewManifestFS(fix.service, fix.cache, opts)
- if err != nil {
- return nil, err
- }
- if err := fix.mount(fs); err != nil {
- return nil, err
- }
-
- return fix, nil
-}
-
-func TestManifestFSCloneOption(t *testing.T) {
- mf := *testManifest
- for i := range mf.Project {
- mf.Project[i].CloneDepth = "1"
- }
-
- fix, err := newManifestTestFixture(&mf)
- if err != nil {
- t.Fatalf("newManifestTestFixture: %v", err)
- }
- defer fix.cleanup()
-
- fs := fix.root.(*manifestFSRoot)
- ch := fs.Inode()
- for _, n := range []string{"build", "kati", "AUTHORS"} {
- newCh := ch.GetChild(n)
- if ch == nil {
- t.Fatalf("node for %q not found. Have %s", n, ch.Children())
- }
- ch = newCh
- }
-
- giNode, ok := ch.Node().(*gitilesNode)
- if !ok {
- t.Fatalf("got node type %T, want *gitilesNode", ch.Node())
- }
-
- if giNode.clone {
- t.Errorf("file had clone set.")
- }
-}
-
-func TestManifestFSTimestamps(t *testing.T) {
- fix, err := newManifestTestFixture(testManifest)
- if err != nil {
- t.Fatal("newTestFixture", err)
- }
- defer fix.cleanup()
-
- var zeroFiles []string
- if err := filepath.Walk(fix.mntDir, func(n string, fi os.FileInfo, err error) error {
- if fi != nil && fi.ModTime().UnixNano() == 0 {
- r, _ := filepath.Rel(fix.mntDir, n)
- zeroFiles = append(zeroFiles, r)
- }
- return nil
- }); err != nil {
- t.Fatalf("Walk: %v", err)
- }
- if len(zeroFiles) > 0 {
- sort.Strings(zeroFiles)
- t.Errorf("found files with zero timestamps: %v", zeroFiles)
- }
-}
-
-func TestManifestFSBasic(t *testing.T) {
- fix, err := newManifestTestFixture(testManifest)
- if err != nil {
- t.Fatal("newTestFixture", err)
- }
- defer fix.cleanup()
-
- fn := filepath.Join(fix.mntDir, "build", "kati", "AUTHORS")
- fi, err := os.Lstat(fn)
- if err != nil {
- t.Fatalf("Lstat(%s): %v", fn, err)
- }
- if fi.Size() != 373 {
- t.Errorf("got size %d want %d", fi.Size(), 373)
- }
-
- contents, err := ioutil.ReadFile(fn)
- if err != nil {
- t.Fatalf("ReadFile(%s): %v", fn, err)
- }
-
- want := testGitiles["/platform/build/kati/+show/ce34badf691d36e8048b63f89d1a86ee5fa4325c/AUTHORS?format=TEXT"]
- if string(contents) != want {
- t.Fatalf("got %q, want %q", contents, want)
- }
-
- copyPath := filepath.Join(fix.mntDir, "build", "copydest")
- if copyFI, err := os.Lstat(copyPath); err != nil {
- t.Errorf("Lstat(%s): %v", copyPath, err)
- } else {
- copyStat := copyFI.Sys().(*syscall.Stat_t)
- origStat := fi.Sys().(*syscall.Stat_t)
-
- if !reflect.DeepEqual(copyStat, origStat) {
- t.Errorf("got stat %v, want %v", copyStat, origStat)
- }
- }
-
- linkPath := filepath.Join(fix.mntDir, "build", "linkdest")
- if got, err := os.Readlink(linkPath); err != nil {
- t.Errorf("Readlink(%s): %v", linkPath, err)
- } else if want := "kati/AUTHORS"; got != want {
- t.Errorf("Readlink(%s) = %q, want %q", linkPath, got, want)
- }
-}
-
-func TestManifestFSXMLFile(t *testing.T) {
- fix, err := newManifestTestFixture(testManifest)
- if err != nil {
- t.Fatal("newTestFixture", err)
- }
- defer fix.cleanup()
-
- xmlPath := filepath.Join(fix.mntDir, ".slothfs", "manifest.xml")
- fuseMF, err := manifest.ParseFile(xmlPath)
- if err != nil {
- t.Fatalf("ParseFile(%s): %v", xmlPath, err)
- }
-
- if !reflect.DeepEqual(fuseMF, testManifest) {
- t.Errorf("read back manifest %v, want %v", fuseMF, testManifest)
- }
-}
-
-type testFixture struct {
- dir string
- mntDir string
- server *fuse.Server
- cache *cache.Cache
- testServer *testServer
- service *gitiles.Service
- root nodefs.Node
-}
-
-func (f *testFixture) cleanup() {
- if f.testServer != nil {
- f.testServer.listener.Close()
- }
- if f.server != nil {
- f.server.Unmount()
- }
- os.RemoveAll(f.dir)
-}
-
-func newTestFixture() (*testFixture, error) {
- d, err := ioutil.TempDir("", "multifstest")
- if err != nil {
- return nil, err
- }
-
- fixture := &testFixture{dir: d}
-
- fixture.cache, err = cache.NewCache(filepath.Join(d, "/cache"), cache.Options{})
- if err != nil {
- return nil, err
- }
-
- fixture.testServer, err = newTestServer()
- if err != nil {
- return nil, err
- }
-
- fixture.service, err = gitiles.NewService(gitiles.Options{
- Address: fmt.Sprintf("http://%s", fixture.testServer.addr),
- })
- if err != nil {
- return nil, err
- }
-
- return fixture, nil
-}
-
-func (f *testFixture) mount(root nodefs.Node) error {
- f.mntDir = filepath.Join(f.dir, "mnt")
- if err := os.Mkdir(f.mntDir, 0755); err != nil {
- return err
- }
-
- fuseOpts := &nodefs.Options{
- EntryTimeout: time.Hour,
- NegativeTimeout: time.Hour,
- AttrTimeout: time.Hour,
- }
-
- var err error
- f.server, _, err = nodefs.MountRoot(f.mntDir, root, fuseOpts)
- if err != nil {
- return err
- }
-
- if fuseDebug {
- f.server.SetDebug(true)
- }
- go f.server.Serve()
-
- f.root = root
- return nil
-}
-
-func TestMultiFSBrokenXML(t *testing.T) {
- fix, err := newTestFixture()
- if err != nil {
- t.Fatalf("newTestFixture: %v", err)
- }
- defer fix.cleanup()
-
- brokenXMLFile := filepath.Join(fix.dir, "broken.xml")
- if err := ioutil.WriteFile(brokenXMLFile, []byte("I'm not XML."), 0644); err != nil {
- t.Errorf("WriteFile(%s): %v", brokenXMLFile, err)
- }
-
- opts := MultiFSOptions{}
- fs := NewMultiFS(fix.service, fix.cache, opts)
-
- if err := fix.mount(fs); err != nil {
- t.Fatalf("mount: %v", err)
- }
-
- if err := os.Symlink(brokenXMLFile, filepath.Join(fix.mntDir, "config", "ws")); err == nil {
- t.Fatalf("want error for broken XML file")
- }
-}
-
-func TestMultiFSBasic(t *testing.T) {
- fix, err := newTestFixture()
- if err != nil {
- t.Fatalf("newTestFixture: %v", err)
- }
- defer fix.cleanup()
-
- xmlFile := filepath.Join(fix.dir, "manifest.xml")
- if err := ioutil.WriteFile(xmlFile, []byte(testManifestXML), 0644); err != nil {
- t.Errorf("WriteFile(%s): %v", xmlFile, err)
- }
-
- opts := MultiFSOptions{}
- fs := NewMultiFS(fix.service, fix.cache, opts)
-
- if err := fix.mount(fs); err != nil {
- t.Fatalf("mount: %v", err)
- }
-
- wsDir := filepath.Join(fix.mntDir, "ws")
- if fi, err := os.Lstat(wsDir); err == nil {
- t.Fatalf("got %v, want non-existent workspace dir", fi)
- }
-
- configName := filepath.Join(fix.mntDir, "config", "ws")
- if err := os.Symlink(xmlFile, configName); err != nil {
- t.Fatalf("Symlink(%s): %v", xmlFile, err)
- }
-
- if _, err := os.Lstat(wsDir); err != nil {
- t.Fatalf("Lstat(%s): %v", wsDir, err)
- }
-
- if got, err := os.Readlink(configName); err != nil {
- t.Fatalf("Readlink(%s): %v", configName, err)
- } else if want := "../ws/.slothfs/manifest.xml"; got != want {
- t.Errorf("got link %s, want %s", got, want)
- }
-
- if _, err := manifest.ParseFile(configName); err != nil {
- t.Fatalf("ParseFile(%s): %v", configName, err)
- }
-
- fn := filepath.Join(wsDir, "build", "kati", "AUTHORS")
- if fi, err := os.Lstat(fn); err != nil {
- t.Fatalf("Lstat(%s): %v", fn, err)
- } else if fi.Size() != 373 {
- t.Errorf("got %d, want size 373", fi.Size())
- }
-
- if err := os.Remove(configName); err != nil {
- t.Fatalf("Delete(%s): %v", configName, err)
- }
-
- if fi, err := os.Lstat(wsDir); err == nil {
- t.Errorf("Lstat(%s): got %v, want error", wsDir, fi)
- }
-}
-
-func TestMultiFSManifestDir(t *testing.T) {
- fix, err := newTestFixture()
- if err != nil {
- t.Fatalf("newTestFixture: %v", err)
- }
- defer fix.cleanup()
-
- mfDir := filepath.Join(fix.dir, "manifests")
- if err := os.MkdirAll(mfDir, 0755); err != nil {
- t.Fatalf("MkdirAll: %v", err)
- }
-
- xmlFile := filepath.Join(mfDir, "ws")
- if err := ioutil.WriteFile(xmlFile, []byte(testManifestXML), 0644); err != nil {
- t.Errorf("WriteFile(%s): %v", xmlFile, err)
- }
-
- opts := MultiFSOptions{
- ManifestDir: mfDir,
- }
- fs := NewMultiFS(fix.service, fix.cache, opts)
-
- if err := fix.mount(fs); err != nil {
- t.Fatalf("mount: %v", err)
- }
-
- wsDir := filepath.Join(fix.mntDir, "ws")
- if _, err := os.Lstat(wsDir); err != nil {
- t.Fatalf("Lstat(%s): %v", wsDir, err)
- }
-
- if err := os.Remove(filepath.Join(fix.mntDir, "config", "ws")); err != nil {
- t.Fatalf("Remove(config link): %v", err)
- }
-
- if fi, err := os.Lstat(filepath.Join(mfDir, "ws")); err == nil {
- t.Errorf("'ws' still in manifest dir: %v", fi)
- }
-
- f, err := ioutil.TempFile("", "")
- if err != nil {
- t.Fatalf("TempFile: %v", err)
- }
- if err := ioutil.WriteFile(f.Name(), []byte(testManifestXML), 0644); err != nil {
- t.Errorf("WriteFile(%s): %v", xmlFile, err)
- }
-
- configName := filepath.Join(fix.mntDir, "config", "ws2")
- if err := os.Symlink(f.Name(), configName); err != nil {
- t.Fatalf("Symlink(%s): %v", xmlFile, err)
- }
-
- // XML file appears again.
- xmlFile = filepath.Join(mfDir, "ws2")
- if _, err := os.Stat(xmlFile); err != nil {
- t.Errorf("Stat(%s): %v", xmlFile, err)
- }
-}
diff --git a/fs/manifestfs_test.go b/fs/manifestfs_test.go
new file mode 100644
index 0000000..05c1ca9
--- /dev/null
+++ b/fs/manifestfs_test.go
@@ -0,0 +1,390 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package fs
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "sort"
+ "syscall"
+ "testing"
+ "time"
+
+ "github.com/google/slothfs/cache"
+ "github.com/google/slothfs/gitiles"
+ "github.com/google/slothfs/manifest"
+ "github.com/hanwen/go-fuse/fuse"
+ "github.com/hanwen/go-fuse/fuse/nodefs"
+)
+
+func newManifestTestFixture(mf *manifest.Manifest) (*testFixture, error) {
+ fix, err := newTestFixture()
+ if err != nil {
+ return nil, err
+ }
+
+ opts := ManifestOptions{
+ Manifest: mf,
+ }
+
+ fs, err := NewManifestFS(fix.service, fix.cache, opts)
+ if err != nil {
+ return nil, err
+ }
+ if err := fix.mount(fs); err != nil {
+ return nil, err
+ }
+
+ return fix, nil
+}
+
+func TestManifestFSCloneOption(t *testing.T) {
+ mf := *testManifest
+ for i := range mf.Project {
+ mf.Project[i].CloneDepth = "1"
+ }
+
+ fix, err := newManifestTestFixture(&mf)
+ if err != nil {
+ t.Fatalf("newManifestTestFixture: %v", err)
+ }
+ defer fix.cleanup()
+
+ fs := fix.root.(*manifestFSRoot)
+ ch := fs.Inode()
+ for _, n := range []string{"build", "kati", "AUTHORS"} {
+ newCh := ch.GetChild(n)
+ if ch == nil {
+ t.Fatalf("node for %q not found. Have %s", n, ch.Children())
+ }
+ ch = newCh
+ }
+
+ giNode, ok := ch.Node().(*gitilesNode)
+ if !ok {
+ t.Fatalf("got node type %T, want *gitilesNode", ch.Node())
+ }
+
+ if giNode.clone {
+ t.Errorf("file had clone set.")
+ }
+}
+
+func TestManifestFSTimestamps(t *testing.T) {
+ fix, err := newManifestTestFixture(testManifest)
+ if err != nil {
+ t.Fatal("newTestFixture", err)
+ }
+ defer fix.cleanup()
+
+ var zeroFiles []string
+ if err := filepath.Walk(fix.mntDir, func(n string, fi os.FileInfo, err error) error {
+ if fi != nil && fi.ModTime().UnixNano() == 0 {
+ r, _ := filepath.Rel(fix.mntDir, n)
+ zeroFiles = append(zeroFiles, r)
+ }
+ return nil
+ }); err != nil {
+ t.Fatalf("Walk: %v", err)
+ }
+ if len(zeroFiles) > 0 {
+ sort.Strings(zeroFiles)
+ t.Errorf("found files with zero timestamps: %v", zeroFiles)
+ }
+}
+
+func TestManifestFSBasic(t *testing.T) {
+ fix, err := newManifestTestFixture(testManifest)
+ if err != nil {
+ t.Fatal("newTestFixture", err)
+ }
+ defer fix.cleanup()
+
+ fn := filepath.Join(fix.mntDir, "build", "kati", "AUTHORS")
+ fi, err := os.Lstat(fn)
+ if err != nil {
+ t.Fatalf("Lstat(%s): %v", fn, err)
+ }
+ if fi.Size() != 373 {
+ t.Errorf("got size %d want %d", fi.Size(), 373)
+ }
+
+ contents, err := ioutil.ReadFile(fn)
+ if err != nil {
+ t.Fatalf("ReadFile(%s): %v", fn, err)
+ }
+
+ want := testGitiles["/platform/build/kati/+show/ce34badf691d36e8048b63f89d1a86ee5fa4325c/AUTHORS?format=TEXT"]
+ if string(contents) != want {
+ t.Fatalf("got %q, want %q", contents, want)
+ }
+
+ copyPath := filepath.Join(fix.mntDir, "build", "copydest")
+ if copyFI, err := os.Lstat(copyPath); err != nil {
+ t.Errorf("Lstat(%s): %v", copyPath, err)
+ } else {
+ copyStat := copyFI.Sys().(*syscall.Stat_t)
+ origStat := fi.Sys().(*syscall.Stat_t)
+
+ if !reflect.DeepEqual(copyStat, origStat) {
+ t.Errorf("got stat %v, want %v", copyStat, origStat)
+ }
+ }
+
+ linkPath := filepath.Join(fix.mntDir, "build", "linkdest")
+ if got, err := os.Readlink(linkPath); err != nil {
+ t.Errorf("Readlink(%s): %v", linkPath, err)
+ } else if want := "kati/AUTHORS"; got != want {
+ t.Errorf("Readlink(%s) = %q, want %q", linkPath, got, want)
+ }
+}
+
+func TestManifestFSXMLFile(t *testing.T) {
+ fix, err := newManifestTestFixture(testManifest)
+ if err != nil {
+ t.Fatal("newTestFixture", err)
+ }
+ defer fix.cleanup()
+
+ xmlPath := filepath.Join(fix.mntDir, ".slothfs", "manifest.xml")
+ fuseMF, err := manifest.ParseFile(xmlPath)
+ if err != nil {
+ t.Fatalf("ParseFile(%s): %v", xmlPath, err)
+ }
+
+ if !reflect.DeepEqual(fuseMF, testManifest) {
+ t.Errorf("read back manifest %v, want %v", fuseMF, testManifest)
+ }
+}
+
+type testFixture struct {
+ dir string
+ mntDir string
+ server *fuse.Server
+ cache *cache.Cache
+ testServer *testServer
+ service *gitiles.Service
+ root nodefs.Node
+}
+
+func (f *testFixture) cleanup() {
+ if f.testServer != nil {
+ f.testServer.listener.Close()
+ }
+ if f.server != nil {
+ f.server.Unmount()
+ }
+ os.RemoveAll(f.dir)
+}
+
+func newTestFixture() (*testFixture, error) {
+ d, err := ioutil.TempDir("", "multifstest")
+ if err != nil {
+ return nil, err
+ }
+
+ fixture := &testFixture{dir: d}
+
+ fixture.cache, err = cache.NewCache(filepath.Join(d, "/cache"), cache.Options{})
+ if err != nil {
+ return nil, err
+ }
+
+ fixture.testServer, err = newTestServer()
+ if err != nil {
+ return nil, err
+ }
+
+ fixture.service, err = gitiles.NewService(gitiles.Options{
+ Address: fmt.Sprintf("http://%s", fixture.testServer.addr),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return fixture, nil
+}
+
+func (f *testFixture) mount(root nodefs.Node) error {
+ f.mntDir = filepath.Join(f.dir, "mnt")
+ if err := os.Mkdir(f.mntDir, 0755); err != nil {
+ return err
+ }
+
+ fuseOpts := &nodefs.Options{
+ EntryTimeout: time.Hour,
+ NegativeTimeout: time.Hour,
+ AttrTimeout: time.Hour,
+ }
+
+ var err error
+ f.server, _, err = nodefs.MountRoot(f.mntDir, root, fuseOpts)
+ if err != nil {
+ return err
+ }
+
+ if fuseDebug {
+ f.server.SetDebug(true)
+ }
+ go f.server.Serve()
+
+ f.root = root
+ return nil
+}
+
+func TestMultiFSBrokenXML(t *testing.T) {
+ fix, err := newTestFixture()
+ if err != nil {
+ t.Fatalf("newTestFixture: %v", err)
+ }
+ defer fix.cleanup()
+
+ brokenXMLFile := filepath.Join(fix.dir, "broken.xml")
+ if err := ioutil.WriteFile(brokenXMLFile, []byte("I'm not XML."), 0644); err != nil {
+ t.Errorf("WriteFile(%s): %v", brokenXMLFile, err)
+ }
+
+ opts := MultiFSOptions{}
+ fs := NewMultiFS(fix.service, fix.cache, opts)
+
+ if err := fix.mount(fs); err != nil {
+ t.Fatalf("mount: %v", err)
+ }
+
+ if err := os.Symlink(brokenXMLFile, filepath.Join(fix.mntDir, "config", "ws")); err == nil {
+ t.Fatalf("want error for broken XML file")
+ }
+}
+
+func TestMultiFSBasic(t *testing.T) {
+ fix, err := newTestFixture()
+ if err != nil {
+ t.Fatalf("newTestFixture: %v", err)
+ }
+ defer fix.cleanup()
+
+ xmlFile := filepath.Join(fix.dir, "manifest.xml")
+ if err := ioutil.WriteFile(xmlFile, []byte(testManifestXML), 0644); err != nil {
+ t.Errorf("WriteFile(%s): %v", xmlFile, err)
+ }
+
+ opts := MultiFSOptions{}
+ fs := NewMultiFS(fix.service, fix.cache, opts)
+
+ if err := fix.mount(fs); err != nil {
+ t.Fatalf("mount: %v", err)
+ }
+
+ wsDir := filepath.Join(fix.mntDir, "ws")
+ if fi, err := os.Lstat(wsDir); err == nil {
+ t.Fatalf("got %v, want non-existent workspace dir", fi)
+ }
+
+ configName := filepath.Join(fix.mntDir, "config", "ws")
+ if err := os.Symlink(xmlFile, configName); err != nil {
+ t.Fatalf("Symlink(%s): %v", xmlFile, err)
+ }
+
+ if _, err := os.Lstat(wsDir); err != nil {
+ t.Fatalf("Lstat(%s): %v", wsDir, err)
+ }
+
+ if got, err := os.Readlink(configName); err != nil {
+ t.Fatalf("Readlink(%s): %v", configName, err)
+ } else if want := "../ws/.slothfs/manifest.xml"; got != want {
+ t.Errorf("got link %s, want %s", got, want)
+ }
+
+ if _, err := manifest.ParseFile(configName); err != nil {
+ t.Fatalf("ParseFile(%s): %v", configName, err)
+ }
+
+ fn := filepath.Join(wsDir, "build", "kati", "AUTHORS")
+ if fi, err := os.Lstat(fn); err != nil {
+ t.Fatalf("Lstat(%s): %v", fn, err)
+ } else if fi.Size() != 373 {
+ t.Errorf("got %d, want size 373", fi.Size())
+ }
+
+ if err := os.Remove(configName); err != nil {
+ t.Fatalf("Delete(%s): %v", configName, err)
+ }
+
+ if fi, err := os.Lstat(wsDir); err == nil {
+ t.Errorf("Lstat(%s): got %v, want error", wsDir, fi)
+ }
+}
+
+func TestMultiFSManifestDir(t *testing.T) {
+ fix, err := newTestFixture()
+ if err != nil {
+ t.Fatalf("newTestFixture: %v", err)
+ }
+ defer fix.cleanup()
+
+ mfDir := filepath.Join(fix.dir, "manifests")
+ if err := os.MkdirAll(mfDir, 0755); err != nil {
+ t.Fatalf("MkdirAll: %v", err)
+ }
+
+ xmlFile := filepath.Join(mfDir, "ws")
+ if err := ioutil.WriteFile(xmlFile, []byte(testManifestXML), 0644); err != nil {
+ t.Errorf("WriteFile(%s): %v", xmlFile, err)
+ }
+
+ opts := MultiFSOptions{
+ ManifestDir: mfDir,
+ }
+ fs := NewMultiFS(fix.service, fix.cache, opts)
+
+ if err := fix.mount(fs); err != nil {
+ t.Fatalf("mount: %v", err)
+ }
+
+ wsDir := filepath.Join(fix.mntDir, "ws")
+ if _, err := os.Lstat(wsDir); err != nil {
+ t.Fatalf("Lstat(%s): %v", wsDir, err)
+ }
+
+ if err := os.Remove(filepath.Join(fix.mntDir, "config", "ws")); err != nil {
+ t.Fatalf("Remove(config link): %v", err)
+ }
+
+ if fi, err := os.Lstat(filepath.Join(mfDir, "ws")); err == nil {
+ t.Errorf("'ws' still in manifest dir: %v", fi)
+ }
+
+ f, err := ioutil.TempFile("", "")
+ if err != nil {
+ t.Fatalf("TempFile: %v", err)
+ }
+ if err := ioutil.WriteFile(f.Name(), []byte(testManifestXML), 0644); err != nil {
+ t.Errorf("WriteFile(%s): %v", xmlFile, err)
+ }
+
+ configName := filepath.Join(fix.mntDir, "config", "ws2")
+ if err := os.Symlink(f.Name(), configName); err != nil {
+ t.Fatalf("Symlink(%s): %v", xmlFile, err)
+ }
+
+ // XML file appears again.
+ xmlFile = filepath.Join(mfDir, "ws2")
+ if _, err := os.Stat(xmlFile); err != nil {
+ t.Errorf("Stat(%s): %v", xmlFile, err)
+ }
+}