gps/filesystem_test.go

Summary

Maintainability
A
0 mins
Test Coverage
// Copyright 2017 The Go 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 gps

import (
    "fmt"
    "os"
    "path/filepath"
    "reflect"
    "testing"

    "github.com/golang/dep/internal/test"
)

// This file contains utilities for running tests around file system state.

type fsTestCase struct {
    before, after filesystemState
}

// assert makes sure that the tc.after state matches the state of the actual host
// file system at tc.after.root.
func (tc fsTestCase) assert(t *testing.T) {
    dirMap := make(map[string]bool)
    fileMap := make(map[string]bool)
    linkMap := make(map[string]bool)

    for _, d := range tc.after.dirs {
        dirMap[filepath.Join(tc.after.root, d)] = true
    }
    for _, f := range tc.after.files {
        fileMap[filepath.Join(tc.after.root, f)] = true
    }
    for _, l := range tc.after.links {
        linkMap[filepath.Join(tc.after.root, l.path)] = true
    }

    err := filepath.Walk(tc.after.root, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            t.Errorf("filepath.Walk path=%q  err=%q", path, err)
            return err
        }

        if path == tc.after.root {
            return nil
        }

        // Careful! Have to check whether the path is a symlink first because, on
        // windows, a symlink to a directory will return 'true' for info.IsDir().
        if (info.Mode() & os.ModeSymlink) != 0 {
            if linkMap[path] {
                delete(linkMap, path)
            } else {
                t.Errorf("unexpected symlink exists %q", path)
            }
            return nil
        }

        if info.IsDir() {
            if dirMap[path] {
                delete(dirMap, path)
            } else {
                t.Errorf("unexpected directory exists %q", path)
            }
            return nil
        }

        if fileMap[path] {
            delete(fileMap, path)
        } else {
            t.Errorf("unexpected file exists %q", path)
        }
        return nil
    })

    if err != nil {
        t.Errorf("filesystem.Walk err=%q", err)
    }

    for d := range dirMap {
        t.Errorf("could not find expected directory %q", d)
    }
    for f := range fileMap {
        t.Errorf("could not find expected file %q", f)
    }
    for l := range linkMap {
        t.Errorf("could not find expected symlink %q", l)
    }
}

// setup inflates fs onto the actual host file system at tc.before.root.
// It doesn't delete existing files and should be used on empty roots only.
func (tc fsTestCase) setup(t *testing.T) {
    if err := tc.before.setup(); err != nil {
        t.Fatal(err)
    }
}

func TestDeriveFilesystemState(t *testing.T) {
    testcases := []struct {
        name string
        fs   fsTestCase
    }{
        {
            name: "simple-case",
            fs: fsTestCase{
                before: filesystemState{
                    dirs: []string{
                        "simple-dir",
                    },
                    files: []string{
                        "simple-file",
                    },
                },
                after: filesystemState{
                    dirs: []string{
                        "simple-dir",
                    },
                    files: []string{
                        "simple-file",
                    },
                },
            },
        },
        {
            name: "simple-symlink-case",
            fs: fsTestCase{
                before: filesystemState{
                    dirs: []string{
                        "simple-dir",
                    },
                    files: []string{
                        "simple-file",
                    },
                    links: []fsLink{
                        {
                            path:   "link",
                            to:     "nonexisting",
                            broken: true,
                        },
                    },
                },
                after: filesystemState{
                    dirs: []string{
                        "simple-dir",
                    },
                    files: []string{
                        "simple-file",
                    },
                    links: []fsLink{
                        {
                            path:   "link",
                            to:     "",
                            broken: true,
                        },
                    },
                },
            },
        },
        {
            name: "complex-symlink-case",
            fs: fsTestCase{
                before: filesystemState{
                    links: []fsLink{
                        {
                            path:     "link1",
                            to:       "link2",
                            circular: true,
                        },
                        {
                            path:     "link2",
                            to:       "link1",
                            circular: true,
                        },
                    },
                },
                after: filesystemState{
                    links: []fsLink{
                        {
                            path:     "link1",
                            to:       "",
                            circular: true,
                        },
                        {
                            path:     "link2",
                            to:       "",
                            circular: true,
                        },
                    },
                },
            },
        },
    }

    for _, tc := range testcases {
        h := test.NewHelper(t)

        h.TempDir(tc.name)

        tc.fs.before.root = h.Path(tc.name)
        tc.fs.after.root = h.Path(tc.name)

        tc.fs.setup(t)

        state, err := deriveFilesystemState(h.Path(tc.name))
        if err != nil {
            t.Fatal(err)
        }

        if !reflect.DeepEqual(tc.fs.after, state) {
            fmt.Println(tc.fs.after)
            fmt.Println(state)
            t.Fatal("filesystem state mismatch")
        }

        h.Cleanup()
    }
}