package function import ( "bytes" "crypto/md5" "encoding/hex" "fmt" "io/fs" "io/ioutil" "os" "path/filepath" "reflect" "runtime" "sort" "testing" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing/object" ) func TestFileSystems(t *testing.T) { var err error tests := []struct { name string fileSystem Filesystem }{ { name: "embedded", fileSystem: EmbeddedTemplatesFS, }, { name: "os", fileSystem: initOSFS(t), }, { name: "git", fileSystem: initGitFS(t), }, } 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 } var embeddedFiles []string err = fs.WalkDir(templatesFS, ".", func(path string, d fs.DirEntry, err error) error { if err != nil { return err } embeddedFiles = append(embeddedFiles, path) return nil }) if err != nil { t.Fatal(err) } var localFiles []string err = filepath.Walk("templates", func(path string, info fs.FileInfo, err error) error { if err != nil { return err } path, err = filepath.Rel("templates", path) if err != nil { return err } localFiles = append(localFiles, filepath.ToSlash(path)) return nil }) if err != nil { t.Fatal(err) } sort.Strings(embeddedFiles) sort.Strings(localFiles) if !reflect.DeepEqual(embeddedFiles, localFiles) { t.Log("embedded files: ", embeddedFiles) t.Log("local files: ", localFiles) t.Error("content of embedded files doesn't match the filesystem") return } err = fs.WalkDir(templatesFS, ".", func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if path == "." { return nil } localFilePath := filepath.Join("templates", path) localFileStat, err := os.Lstat(localFilePath) if err != nil { return err } embeddedFileStats, err := templatesFS.Stat(path) if err != nil { return err } if localFileStat.IsDir() && embeddedFileStats.IsDir() { return nil } if localFileStat.IsDir() != embeddedFileStats.IsDir() { t.Errorf("directory-file mismatch on %q", path) return nil } if localFileStat.Size() != embeddedFileStats.Size() { t.Errorf("size mismatch on %q (expected: %d, actual:%d)", path, localFileStat.Size(), embeddedFileStats.Size()) return nil } embeddedFile, err := templatesFS.Open(path) if err != nil { return err } localFileContent, err := ioutil.ReadFile(localFilePath) if err != nil { return err } embeddedFileContent, err := ioutil.ReadAll(embeddedFile) if err != nil { return err } if !bytes.Equal(localFileContent, embeddedFileContent) { localSum := md5.Sum(localFileContent) embeddedSum := md5.Sum(embeddedFileContent) t.Errorf("content mismatch on %q (expected hash: %s, actual hash: %s)", path, hex.EncodeToString(localSum[:]), hex.EncodeToString(embeddedSum[:])) return nil } if runtime.GOOS != "windows" && (embeddedFileStats.Mode().Perm()&0100) != (localFileStat.Mode().Perm()&0100) { t.Errorf("mode mismatch on %q (expected: %o, actual: %o)", path, localFileStat.Mode().Perm(), embeddedFileStats.Mode().Perm()) return nil } return nil }) if err != nil { t.Error(err) } }) } } func initOSFS(t *testing.T) Filesystem { wd, err := os.Getwd() if err != nil { t.Fatal(err) } return osFilesystem{root: filepath.Join(wd, "templates")} } func initGitFS(t *testing.T) Filesystem { repoDir := t.TempDir() err := filepath.Walk("templates", func(path string, fi fs.FileInfo, err error) error { if err != nil { return err } rel, err := filepath.Rel("templates", path) if err != nil { return err } if rel == "" || rel == "." { return nil } if fi.IsDir() { err = os.Mkdir(filepath.Join(repoDir, rel), fi.Mode().Perm()) if err != nil { return err } } else { 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 } } 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 := filesystemFromRepo(uri) if err != nil { t.Fatal(t) } return result }