all: Add package runtimeos for runtime.GOOS comparisons I grew tired of hand written string comparisons. This adds generated constants for the GOOS values, and predefined Is$OS constants that can be iffed on. In a couple of places I rewrote trivial switch:es to if:s, and added Illumos where we checked for Solaris (because they are effectively the same, and if we're going to target one of them that would be Illumos...).
133 lines
3.8 KiB
Go
133 lines
3.8 KiB
Go
// Copyright (C) 2019 The Syncthing Authors.
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
package fs
|
|
|
|
import (
|
|
"math/rand"
|
|
"testing"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
|
|
"github.com/syncthing/syncthing/lib/build"
|
|
)
|
|
|
|
func TestCommonPrefix(t *testing.T) {
|
|
test := func(first, second, expect string) {
|
|
t.Helper()
|
|
res := CommonPrefix(first, second)
|
|
if res != expect {
|
|
t.Errorf("Expected %s got %s", expect, res)
|
|
}
|
|
}
|
|
|
|
if build.IsWindows {
|
|
test(`c:\Audrius\Downloads`, `c:\Audrius\Docs`, `c:\Audrius`)
|
|
test(`c:\Audrius\Downloads`, `C:\Audrius\Docs`, ``) // Case differences :(
|
|
test(`C:\Audrius-a\Downloads`, `C:\Audrius-b\Docs`, `C:\`)
|
|
test(`\\?\C:\Audrius-a\Downloads`, `\\?\C:\Audrius-b\Docs`, `\\?\C:\`)
|
|
test(`\\?\C:\Audrius\Downloads`, `\\?\C:\Audrius\Docs`, `\\?\C:\Audrius`)
|
|
test(`Audrius-a\Downloads`, `Audrius-b\Docs`, ``)
|
|
test(`Audrius\Downloads`, `Audrius\Docs`, `Audrius`)
|
|
test(`c:\Audrius\Downloads`, `Audrius\Docs`, ``)
|
|
test(`c:\`, `c:\`, `c:\`)
|
|
test(`\\?\c:\`, `\\?\c:\`, `\\?\c:\`)
|
|
} else {
|
|
test(`/Audrius/Downloads`, `/Audrius/Docs`, `/Audrius`)
|
|
test(`/Audrius\Downloads`, `/Audrius\Docs`, `/`)
|
|
test(`/Audrius-a/Downloads`, `/Audrius-b/Docs`, `/`)
|
|
test(`Audrius\Downloads`, `Audrius\Docs`, ``) // Windows separators
|
|
test(`Audrius/Downloads`, `Audrius/Docs`, `Audrius`)
|
|
test(`Audrius-a\Downloads`, `Audrius-b\Docs`, ``)
|
|
test(`/Audrius/Downloads`, `Audrius/Docs`, ``)
|
|
test(`/`, `/`, `/`)
|
|
}
|
|
test(`Audrius`, `Audrius`, `Audrius`)
|
|
test(`.`, `.`, `.`)
|
|
}
|
|
|
|
func TestWindowsInvalidFilename(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
err error
|
|
}{
|
|
{`asdf.txt`, nil},
|
|
{`nul`, errInvalidFilenameWindowsReservedName},
|
|
{`nul.txt`, errInvalidFilenameWindowsReservedName},
|
|
{`nul.jpg.txt`, errInvalidFilenameWindowsReservedName},
|
|
{`some.nul.jpg`, nil},
|
|
{`foo>bar.txt`, errInvalidFilenameWindowsReservedChar},
|
|
{`foo \bar.txt`, errInvalidFilenameWindowsSpacePeriod},
|
|
{`foo.\bar.txt`, errInvalidFilenameWindowsSpacePeriod},
|
|
{`foo.d\bar.txt`, nil},
|
|
{`foo.d\bar .txt`, nil},
|
|
{`foo.d\bar. txt`, nil},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
err := WindowsInvalidFilename(tc.name)
|
|
if err != tc.err {
|
|
t.Errorf("For %q, got %v, expected %v", tc.name, err, tc.err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSanitizePath(t *testing.T) {
|
|
cases := [][2]string{
|
|
{"", ""},
|
|
{"foo", "foo"},
|
|
{`\*/foo\?/bar[{!@$%^&*#()}]`, "foo bar ()"},
|
|
{"Räksmörgås", "Räksmörgås"},
|
|
{`Räk \/ smörgås`, "Räk smörgås"},
|
|
{"هذا هو *\x07?اسم الملف", "هذا هو اسم الملف"},
|
|
{`../foo.txt`, `.. foo.txt`},
|
|
{" \t \n filename in \t space\r", "filename in space"},
|
|
{"你\xff好", `你 好`},
|
|
{"\000 foo", "foo"},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
res := SanitizePath(tc[0])
|
|
if res != tc[1] {
|
|
t.Errorf("SanitizePath(%q) => %q, expected %q", tc[0], res, tc[1])
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fuzz test: SanitizePath must always return strings of printable UTF-8
|
|
// characters when fed random data.
|
|
//
|
|
// Note that space is considered printable, but other whitespace runes are not.
|
|
func TestSanitizePathFuzz(t *testing.T) {
|
|
buf := make([]byte, 128)
|
|
|
|
for i := 0; i < 100; i++ {
|
|
rand.Read(buf)
|
|
path := SanitizePath(string(buf))
|
|
if !utf8.ValidString(path) {
|
|
t.Errorf("SanitizePath(%q) => %q, not valid UTF-8", buf, path)
|
|
continue
|
|
}
|
|
for _, c := range path {
|
|
if !unicode.IsPrint(c) {
|
|
t.Errorf("non-printable rune %q in sanitized path", c)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func benchmarkWindowsInvalidFilename(b *testing.B, name string) {
|
|
for i := 0; i < b.N; i++ {
|
|
WindowsInvalidFilename(name)
|
|
}
|
|
}
|
|
func BenchmarkWindowsInvalidFilenameValid(b *testing.B) {
|
|
benchmarkWindowsInvalidFilename(b, "License.txt.gz")
|
|
}
|
|
func BenchmarkWindowsInvalidFilenameNUL(b *testing.B) {
|
|
benchmarkWindowsInvalidFilename(b, "nul.txt.gz")
|
|
}
|