all: Grand test refactor (fixes #8779, fixes #8799)

This fixes various test issues with Go 1.20.

- Most tests rewritten to use fakefs where possible
- Some tests that were already skipped, or dubious (invasive,
  unmaintainable, unclear what they even tested) have been removed
- Some actual code rewritten to better support testing in fakefs

Co-authored-by: Eric P <eric@kastelo.net>
This commit is contained in:
Jakob Borg
2023-05-09 10:01:57 +00:00
co-authored by Eric P
parent ddce692f72
commit 1103a27337
54 changed files with 1133 additions and 1594 deletions
+48 -30
View File
@@ -775,9 +775,9 @@ func (s *service) getDBBrowse(w http.ResponseWriter, r *http.Request) {
}
func (s *service) getDBCompletion(w http.ResponseWriter, r *http.Request) {
var qs = r.URL.Query()
var folder = qs.Get("folder") // empty means all folders
var deviceStr = qs.Get("device") // empty means local device ID
qs := r.URL.Query()
folder := qs.Get("folder") // empty means all folders
deviceStr := qs.Get("device") // empty means local device ID
// We will check completion status for either the local device, or a
// specific given device ID.
@@ -814,14 +814,14 @@ func (s *service) getDBStatus(w http.ResponseWriter, r *http.Request) {
}
func (s *service) postDBOverride(_ http.ResponseWriter, r *http.Request) {
var qs = r.URL.Query()
var folder = qs.Get("folder")
qs := r.URL.Query()
folder := qs.Get("folder")
go s.model.Override(folder)
}
func (s *service) postDBRevert(_ http.ResponseWriter, r *http.Request) {
var qs = r.URL.Query()
var folder = qs.Get("folder")
qs := r.URL.Query()
folder := qs.Get("folder")
go s.model.Revert(folder)
}
@@ -1015,7 +1015,7 @@ func (s *service) postSystemRestart(w http.ResponseWriter, _ *http.Request) {
}
func (s *service) postSystemReset(w http.ResponseWriter, r *http.Request) {
var qs = r.URL.Query()
qs := r.URL.Query()
folder := qs.Get("folder")
if len(folder) > 0 {
@@ -1210,7 +1210,6 @@ func (s *service) getSupportBundle(w http.ResponseWriter, r *http.Request) {
l.Warnln("Support bundle: failed to serialize usage-reporting.json.txt", err)
} else {
files = append(files, fileEntry{name: "usage-reporting.json.txt", data: usageReportingData})
}
}
@@ -1243,7 +1242,7 @@ func (s *service) getSupportBundle(w http.ResponseWriter, r *http.Request) {
zipFilePath := filepath.Join(locations.GetBaseDir(locations.ConfigBaseDir), zipFileName)
// Write buffer zip to local zip file (back up)
if err := os.WriteFile(zipFilePath, zipFilesBuffer.Bytes(), 0600); err != nil {
if err := os.WriteFile(zipFilePath, zipFilesBuffer.Bytes(), 0o600); err != nil {
l.Warnln("Support bundle: support bundle zip could not be created:", err)
}
@@ -1299,7 +1298,6 @@ func (s *service) getReport(w http.ResponseWriter, r *http.Request) {
} else {
sendJSON(w, r)
}
}
func (*service) getRandomString(w http.ResponseWriter, r *http.Request) {
@@ -1497,8 +1495,8 @@ func (s *service) postSystemUpgrade(w http.ResponseWriter, _ *http.Request) {
func (s *service) makeDevicePauseHandler(paused bool) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var qs = r.URL.Query()
var deviceStr = qs.Get("device")
qs := r.URL.Query()
deviceStr := qs.Get("device")
var msg string
var status int
@@ -1573,8 +1571,8 @@ func (*service) getHealth(w http.ResponseWriter, _ *http.Request) {
}
func (*service) getQR(w http.ResponseWriter, r *http.Request) {
var qs = r.URL.Query()
var text = qs.Get("text")
qs := r.URL.Query()
text := qs.Get("text")
code, err := qr.Encode(text, qr.M)
if err != nil {
http.Error(w, "Invalid", http.StatusInternalServerError)
@@ -1655,7 +1653,6 @@ func (s *service) getFolderErrors(w http.ResponseWriter, r *http.Request) {
page, perpage := getPagingParams(qs)
errors, err := s.model.FolderErrors(folder)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
@@ -1687,7 +1684,21 @@ func (*service) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
var fsType fs.FilesystemType
fsType.UnmarshalText([]byte(qs.Get("filesystem")))
sendJSON(w, browseFiles(current, fsType))
sendJSON(w, browse(fsType, current))
}
func browse(fsType fs.FilesystemType, current string) []string {
if current == "" {
return browseRoots(fsType)
}
parent, base := parentAndBase(current)
ffs := fs.NewFilesystem(fsType, parent)
files := browseFiles(ffs, base)
for i := range files {
files[i] = filepath.Join(parent, files[i])
}
return files
}
const (
@@ -1708,14 +1719,18 @@ func checkPrefixMatch(s, prefix string) int {
return noMatch
}
func browseFiles(current string, fsType fs.FilesystemType) []string {
if current == "" {
filesystem := fs.NewFilesystem(fsType, "")
if roots, err := filesystem.Roots(); err == nil {
return roots
}
return nil
func browseRoots(fsType fs.FilesystemType) []string {
filesystem := fs.NewFilesystem(fsType, "")
if roots, err := filesystem.Roots(); err == nil {
return roots
}
return nil
}
// parentAndBase returns the parent directory and the remaining base of the
// path. The base may be empty if the path ends with a path separator.
func parentAndBase(current string) (string, string) {
search, _ := fs.ExpandTilde(current)
pathSeparator := string(fs.PathSeparator)
@@ -1731,24 +1746,27 @@ func browseFiles(current string, fsType fs.FilesystemType) []string {
searchFile = filepath.Base(search)
}
fs := fs.NewFilesystem(fsType, searchDir)
return searchDir, searchFile
}
subdirectories, _ := fs.DirNames(".")
func browseFiles(ffs fs.Filesystem, search string) []string {
subdirectories, _ := ffs.DirNames(".")
pathSeparator := string(fs.PathSeparator)
exactMatches := make([]string, 0, len(subdirectories))
caseInsMatches := make([]string, 0, len(subdirectories))
for _, subdirectory := range subdirectories {
info, err := fs.Stat(subdirectory)
info, err := ffs.Stat(subdirectory)
if err != nil || !info.IsDir() {
continue
}
switch checkPrefixMatch(subdirectory, searchFile) {
switch checkPrefixMatch(subdirectory, search) {
case matchExact:
exactMatches = append(exactMatches, filepath.Join(searchDir, subdirectory)+pathSeparator)
exactMatches = append(exactMatches, subdirectory+pathSeparator)
case matchCaseIns:
caseInsMatches = append(caseInsMatches, filepath.Join(searchDir, subdirectory)+pathSeparator)
caseInsMatches = append(caseInsMatches, subdirectory+pathSeparator)
}
}
+16 -21
View File
@@ -39,6 +39,7 @@ import (
"github.com/syncthing/syncthing/lib/model"
modelmocks "github.com/syncthing/syncthing/lib/model/mocks"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/svcutil"
"github.com/syncthing/syncthing/lib/sync"
"github.com/syncthing/syncthing/lib/tlsutil"
@@ -1168,45 +1169,39 @@ func TestBrowse(t *testing.T) {
pathSep := string(os.PathSeparator)
tmpDir := t.TempDir()
ffs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32)+"?nostfolder=true")
if err := os.Mkdir(filepath.Join(tmpDir, "dir"), 0755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(tmpDir, "file"), []byte("hello"), 0644); err != nil {
t.Fatal(err)
}
if err := os.Mkdir(filepath.Join(tmpDir, "MiXEDCase"), 0755); err != nil {
t.Fatal(err)
}
_ = ffs.Mkdir("dir", 0o755)
_ = fs.WriteFile(ffs, "file", []byte("hello"), 0o644)
_ = ffs.Mkdir("MiXEDCase", 0o755)
// We expect completion to return the full path to the completed
// directory, with an ending slash.
dirPath := filepath.Join(tmpDir, "dir") + pathSep
mixedCaseDirPath := filepath.Join(tmpDir, "MiXEDCase") + pathSep
dirPath := "dir" + pathSep
mixedCaseDirPath := "MiXEDCase" + pathSep
cases := []struct {
current string
returns []string
}{
// The directory without slash is completed to one with slash.
{tmpDir, []string{tmpDir + pathSep}},
{"dir", []string{"dir" + pathSep}},
// With slash it's completed to its contents.
// Dirs are given pathSeps.
// Files are not returned.
{tmpDir + pathSep, []string{mixedCaseDirPath, dirPath}},
{"", []string{mixedCaseDirPath, dirPath}},
// Globbing is automatic based on prefix.
{tmpDir + pathSep + "d", []string{dirPath}},
{tmpDir + pathSep + "di", []string{dirPath}},
{tmpDir + pathSep + "dir", []string{dirPath}},
{tmpDir + pathSep + "f", nil},
{tmpDir + pathSep + "q", nil},
{"d", []string{dirPath}},
{"di", []string{dirPath}},
{"dir", []string{dirPath}},
{"f", nil},
{"q", nil},
// Globbing is case-insensitive
{tmpDir + pathSep + "mixed", []string{mixedCaseDirPath}},
{"mixed", []string{mixedCaseDirPath}},
}
for _, tc := range cases {
ret := browseFiles(tc.current, fs.FilesystemTypeBasic)
ret := browseFiles(ffs, tc.current)
if !util.EqualStrings(ret, tc.returns) {
t.Errorf("browseFiles(%q) => %q, expected %q", tc.current, ret, tc.returns)
}