mirror of https://github.com/knative/func.git
240 lines
4.9 KiB
Go
240 lines
4.9 KiB
Go
package filesystem_test
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/go-git/go-git/v5"
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
"knative.dev/func/pkg/filesystem"
|
|
fn "knative.dev/func/pkg/functions"
|
|
)
|
|
|
|
const templatesPath = "../../templates"
|
|
|
|
func TestFileSystems(t *testing.T) {
|
|
var err error
|
|
|
|
tests := []struct {
|
|
name string
|
|
fileSystem filesystem.Filesystem
|
|
}{
|
|
{
|
|
name: "embedded",
|
|
fileSystem: fn.EmbeddedTemplatesFS,
|
|
},
|
|
{
|
|
name: "os",
|
|
fileSystem: initOSFS(t),
|
|
},
|
|
{
|
|
name: "git",
|
|
fileSystem: initGitFS(t),
|
|
},
|
|
}
|
|
|
|
type FileInfo struct {
|
|
Path string
|
|
Type fs.FileMode
|
|
Executable bool
|
|
Content []byte
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
templatesFS := tt.fileSystem
|
|
|
|
if templatesFS == nil && runtime.GOOS == "windows" {
|
|
t.Skip("FS == nil")
|
|
// TODO I have no idea why it returns nil on Windows
|
|
}
|
|
|
|
permMask := fs.FileMode(0111)
|
|
if runtime.GOOS == "windows" {
|
|
permMask = 0
|
|
}
|
|
|
|
var embeddedFiles []FileInfo
|
|
err = fs.WalkDir(templatesFS, ".", func(path string, d fs.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fi, err := templatesFS.Stat(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var bs []byte
|
|
switch fi.Mode() & fs.ModeType {
|
|
case 0:
|
|
f, err := templatesFS.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
bs, err = io.ReadAll(f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case fs.ModeSymlink:
|
|
t, _ := templatesFS.Readlink(path)
|
|
bs = []byte(t)
|
|
}
|
|
embeddedFiles = append(embeddedFiles, FileInfo{
|
|
Path: path,
|
|
Type: fi.Mode().Type(),
|
|
Executable: fi.Mode()&permMask == permMask && !fi.IsDir(),
|
|
Content: bs,
|
|
})
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var localFiles []FileInfo
|
|
err = filepath.Walk(templatesPath, func(path string, info fs.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fi, err := os.Lstat(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var bs []byte
|
|
switch fi.Mode() & fs.ModeType {
|
|
case 0:
|
|
bs, err = os.ReadFile(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case fs.ModeSymlink:
|
|
t, _ := os.Readlink(path)
|
|
bs = []byte(t)
|
|
}
|
|
path, err = filepath.Rel(templatesPath, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
localFiles = append(localFiles, FileInfo{
|
|
Path: filepath.ToSlash(path),
|
|
Type: fi.Mode().Type(),
|
|
Executable: fi.Mode()&permMask == permMask && !fi.IsDir(),
|
|
Content: bs,
|
|
})
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
compare := func(fis []FileInfo) func(i, j int) bool {
|
|
return func(i, j int) bool {
|
|
return fis[i].Path < fis[j].Path
|
|
}
|
|
}
|
|
sort.Slice(embeddedFiles, compare(embeddedFiles))
|
|
sort.Slice(localFiles, compare(localFiles))
|
|
|
|
if diff := cmp.Diff(localFiles, embeddedFiles); diff != "" {
|
|
t.Error("filesystem content missmatch (-want, +got):", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func initOSFS(t *testing.T) filesystem.Filesystem {
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return filesystem.NewOsFilesystem(filepath.Join(wd, templatesPath))
|
|
}
|
|
|
|
func initGitFS(t *testing.T) filesystem.Filesystem {
|
|
repoDir := t.TempDir()
|
|
|
|
err := filepath.Walk(templatesPath, func(path string, fi fs.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rel, err := filepath.Rel(templatesPath, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rel == "" || rel == "." {
|
|
return nil
|
|
}
|
|
|
|
switch {
|
|
case fi.IsDir():
|
|
err = os.Mkdir(filepath.Join(repoDir, rel), fi.Mode().Perm())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case fi.Mode()&fs.ModeSymlink != 0:
|
|
symlinkTarget, err := os.Readlink(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = os.Symlink(symlinkTarget, filepath.Join(repoDir, rel))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
case fi.Mode()&fs.ModeType == 0: // regular file
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = os.WriteFile(filepath.Join(repoDir, rel), data, fi.Mode().Perm())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
return fmt.Errorf("unsupported file type: %s", fi.Mode().String())
|
|
}
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
r, err := git.PlainInit(repoDir, false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
w, err := r.Worktree()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = w.AddGlob(".")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
author := &object.Signature{Name: "johndoe"}
|
|
_, err = w.Commit("init", &git.CommitOptions{
|
|
Author: author,
|
|
Committer: author,
|
|
All: true,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
uri := fmt.Sprintf(`file://%s`, filepath.ToSlash(repoDir))
|
|
|
|
result, err := fn.FilesystemFromRepo(uri)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return result
|
|
}
|