fup/fuphttp/fngen: expose UniqueName function, add tests for it

This commit is contained in:
Luke Granger-Brown 2021-03-21 17:02:56 +00:00
parent 691babc0f7
commit 7b969570a9
2 changed files with 49 additions and 1 deletions

View file

@ -63,7 +63,8 @@ func BoringGenerator(filenamePrefix string, filenameExt string, attempt int) str
return string(out)
}
func uniqueName(ctx context.Context, existsFn func(ctx context.Context, name string) (bool, error), filenamePrefix, extension string, generator FilenameGenerator) (string, error) {
// UniqueName repeatedly attempts to generate a name until existsFn returns false.
func UniqueName(ctx context.Context, existsFn func(ctx context.Context, name string) (bool, error), filenamePrefix, extension string, generator FilenameGenerator) (string, error) {
// There's a race condition here, because we might generate a currently-not-taken filename and collide with someone uploading with the same name.
// However, given the usecase of this software, I've decided not to care. I'm unlikely to be uploading enough things concurrently that this is a real issue.
attempt := 0

View file

@ -5,6 +5,7 @@
package fngen_test
import (
"context"
"fmt"
"strings"
"testing"
@ -47,3 +48,49 @@ func TestBoringGenerator(t *testing.T) {
t.Errorf("BoringGenerator(%q, %q, 0) = %q; want something ending in %v", "prefix", ".ext", got, ".ext")
}
}
func TestUniqueName(t *testing.T) {
gen := func(filenamePrefix string, filenameExt string, attempt int) string {
return fmt.Sprintf("%s.%d%s", filenamePrefix, attempt, filenameExt)
}
exists := func(ctx context.Context, name string) (bool, error) {
switch name {
case "firstTry.0.txt":
return false, nil
case "secondTry.0.txt":
return true, nil
case "secondTry.1.txt":
return false, nil
default:
return false, fmt.Errorf("no existence recorded for %q for testing", name)
}
}
ctx := context.Background()
tcs := []struct {
prefix string
want string
wantErr bool
}{{
prefix: "firstTry",
want: "firstTry.0.txt",
}, {
prefix: "secondTry",
want: "secondTry.1.txt",
}, {
prefix: "error",
wantErr: true,
}}
for _, tc := range tcs {
got, err := fngen.UniqueName(ctx, exists, tc.prefix, ".txt", gen)
switch {
case err != nil && !tc.wantErr:
t.Errorf("UniqueName(%q): %v", tc.prefix, err)
case err == nil && tc.wantErr:
t.Errorf("UniqueName(%q) didn't return error; expected one", tc.prefix)
}
if got != tc.want {
t.Errorf("UniqueName(%q) = %q; want %q", tc.prefix, got, tc.want)
}
}
}