aboutsummaryrefslogtreecommitdiffstats
path: root/modules/util
diff options
context:
space:
mode:
Diffstat (limited to 'modules/util')
-rw-r--r--modules/util/error.go68
-rw-r--r--modules/util/filebuffer/file_backed_buffer.go35
-rw-r--r--modules/util/filebuffer/file_backed_buffer_test.go3
-rw-r--r--modules/util/legacy_test.go2
-rw-r--r--modules/util/map.go13
-rw-r--r--modules/util/map_test.go26
-rw-r--r--modules/util/paginate_test.go14
-rw-r--r--modules/util/path.go5
-rw-r--r--modules/util/remove.go6
-rw-r--r--modules/util/rotatingfilewriter/writer_test.go2
-rw-r--r--modules/util/runtime_test.go4
-rw-r--r--modules/util/sec_to_time.go10
-rw-r--r--modules/util/sec_to_time_test.go3
-rw-r--r--modules/util/slice.go7
-rw-r--r--modules/util/string.go23
-rw-r--r--modules/util/truncate_test.go11
-rw-r--r--modules/util/util.go18
-rw-r--r--modules/util/util_test.go17
18 files changed, 167 insertions, 100 deletions
diff --git a/modules/util/error.go b/modules/util/error.go
index 0f3597147c..6b2721618e 100644
--- a/modules/util/error.go
+++ b/modules/util/error.go
@@ -10,56 +10,88 @@ import (
// Common Errors forming the base of our error system
//
-// Many Errors returned by Gitea can be tested against these errors
-// using errors.Is.
+// Many Errors returned by Gitea can be tested against these errors using "errors.Is".
var (
- ErrInvalidArgument = errors.New("invalid argument")
- ErrPermissionDenied = errors.New("permission denied")
- ErrAlreadyExist = errors.New("resource already exists")
- ErrNotExist = errors.New("resource does not exist")
+ ErrInvalidArgument = errors.New("invalid argument") // also implies HTTP 400
+ ErrPermissionDenied = errors.New("permission denied") // also implies HTTP 403
+ ErrNotExist = errors.New("resource does not exist") // also implies HTTP 404
+ ErrAlreadyExist = errors.New("resource already exists") // also implies HTTP 409
+
+ // ErrUnprocessableContent implies HTTP 422, the syntax of the request content is correct,
+ // but the server is unable to process the contained instructions
+ ErrUnprocessableContent = errors.New("unprocessable content")
)
-// SilentWrap provides a simple wrapper for a wrapped error where the wrapped error message plays no part in the error message
+// errorWrapper provides a simple wrapper for a wrapped error where the wrapped error message plays no part in the error message
// Especially useful for "untyped" errors created with "errors.New(…)" that can be classified as 'invalid argument', 'permission denied', 'exists already', or 'does not exist'
-type SilentWrap struct {
+type errorWrapper struct {
Message string
Err error
}
// Error returns the message
-func (w SilentWrap) Error() string {
+func (w errorWrapper) Error() string {
return w.Message
}
// Unwrap returns the underlying error
-func (w SilentWrap) Unwrap() error {
+func (w errorWrapper) Unwrap() error {
return w.Err
}
-// NewSilentWrapErrorf returns an error that formats as the given text but unwraps as the provided error
-func NewSilentWrapErrorf(unwrap error, message string, args ...any) error {
+type LocaleWrapper struct {
+ err error
+ TrKey string
+ TrArgs []any
+}
+
+// Error returns the message
+func (w LocaleWrapper) Error() string {
+ return w.err.Error()
+}
+
+// Unwrap returns the underlying error
+func (w LocaleWrapper) Unwrap() error {
+ return w.err
+}
+
+// ErrorWrap returns an error that formats as the given text but unwraps as the provided error
+func ErrorWrap(unwrap error, message string, args ...any) error {
if len(args) == 0 {
- return SilentWrap{Message: message, Err: unwrap}
+ return errorWrapper{Message: message, Err: unwrap}
}
- return SilentWrap{Message: fmt.Sprintf(message, args...), Err: unwrap}
+ return errorWrapper{Message: fmt.Sprintf(message, args...), Err: unwrap}
}
// NewInvalidArgumentErrorf returns an error that formats as the given text but unwraps as an ErrInvalidArgument
func NewInvalidArgumentErrorf(message string, args ...any) error {
- return NewSilentWrapErrorf(ErrInvalidArgument, message, args...)
+ return ErrorWrap(ErrInvalidArgument, message, args...)
}
// NewPermissionDeniedErrorf returns an error that formats as the given text but unwraps as an ErrPermissionDenied
func NewPermissionDeniedErrorf(message string, args ...any) error {
- return NewSilentWrapErrorf(ErrPermissionDenied, message, args...)
+ return ErrorWrap(ErrPermissionDenied, message, args...)
}
// NewAlreadyExistErrorf returns an error that formats as the given text but unwraps as an ErrAlreadyExist
func NewAlreadyExistErrorf(message string, args ...any) error {
- return NewSilentWrapErrorf(ErrAlreadyExist, message, args...)
+ return ErrorWrap(ErrAlreadyExist, message, args...)
}
// NewNotExistErrorf returns an error that formats as the given text but unwraps as an ErrNotExist
func NewNotExistErrorf(message string, args ...any) error {
- return NewSilentWrapErrorf(ErrNotExist, message, args...)
+ return ErrorWrap(ErrNotExist, message, args...)
+}
+
+// ErrorWrapLocale wraps an err with a translation key and arguments
+func ErrorWrapLocale(err error, trKey string, trArgs ...any) error {
+ return LocaleWrapper{err: err, TrKey: trKey, TrArgs: trArgs}
+}
+
+func ErrorAsLocale(err error) *LocaleWrapper {
+ var e LocaleWrapper
+ if errors.As(err, &e) {
+ return &e
+ }
+ return nil
}
diff --git a/modules/util/filebuffer/file_backed_buffer.go b/modules/util/filebuffer/file_backed_buffer.go
index 739543e297..0731ba30c8 100644
--- a/modules/util/filebuffer/file_backed_buffer.go
+++ b/modules/util/filebuffer/file_backed_buffer.go
@@ -7,16 +7,10 @@ import (
"bytes"
"errors"
"io"
- "math"
"os"
)
-var (
- // ErrInvalidMemorySize occurs if the memory size is not in a valid range
- ErrInvalidMemorySize = errors.New("Memory size must be greater 0 and lower math.MaxInt32")
- // ErrWriteAfterRead occurs if Write is called after a read operation
- ErrWriteAfterRead = errors.New("Write is unsupported after a read operation")
-)
+var ErrWriteAfterRead = errors.New("write is unsupported after a read operation") // occurs if Write is called after a read operation
type readAtSeeker interface {
io.ReadSeeker
@@ -30,34 +24,17 @@ type FileBackedBuffer struct {
maxMemorySize int64
size int64
buffer bytes.Buffer
+ tempDir string
file *os.File
reader readAtSeeker
}
// New creates a file backed buffer with a specific maximum memory size
-func New(maxMemorySize int) (*FileBackedBuffer, error) {
- if maxMemorySize < 0 || maxMemorySize > math.MaxInt32 {
- return nil, ErrInvalidMemorySize
- }
-
+func New(maxMemorySize int, tempDir string) *FileBackedBuffer {
return &FileBackedBuffer{
maxMemorySize: int64(maxMemorySize),
- }, nil
-}
-
-// CreateFromReader creates a file backed buffer and copies the provided reader data into it.
-func CreateFromReader(r io.Reader, maxMemorySize int) (*FileBackedBuffer, error) {
- b, err := New(maxMemorySize)
- if err != nil {
- return nil, err
+ tempDir: tempDir,
}
-
- _, err = io.Copy(b, r)
- if err != nil {
- return nil, err
- }
-
- return b, nil
}
// Write implements io.Writer
@@ -73,7 +50,7 @@ func (b *FileBackedBuffer) Write(p []byte) (int, error) {
n, err = b.file.Write(p)
} else {
if b.size+int64(len(p)) > b.maxMemorySize {
- b.file, err = os.CreateTemp("", "gitea-buffer-")
+ b.file, err = os.CreateTemp(b.tempDir, "gitea-buffer-")
if err != nil {
return 0, err
}
@@ -148,7 +125,7 @@ func (b *FileBackedBuffer) Seek(offset int64, whence int) (int64, error) {
func (b *FileBackedBuffer) Close() error {
if b.file != nil {
err := b.file.Close()
- os.Remove(b.file.Name())
+ _ = os.Remove(b.file.Name())
b.file = nil
return err
}
diff --git a/modules/util/filebuffer/file_backed_buffer_test.go b/modules/util/filebuffer/file_backed_buffer_test.go
index 16d5a1965f..3f13c6ac7b 100644
--- a/modules/util/filebuffer/file_backed_buffer_test.go
+++ b/modules/util/filebuffer/file_backed_buffer_test.go
@@ -21,7 +21,8 @@ func TestFileBackedBuffer(t *testing.T) {
}
for _, c := range cases {
- buf, err := CreateFromReader(strings.NewReader(c.Data), c.MaxMemorySize)
+ buf := New(c.MaxMemorySize, t.TempDir())
+ _, err := io.Copy(buf, strings.NewReader(c.Data))
assert.NoError(t, err)
assert.EqualValues(t, len(c.Data), buf.Size())
diff --git a/modules/util/legacy_test.go b/modules/util/legacy_test.go
index e732094c29..565fb7f284 100644
--- a/modules/util/legacy_test.go
+++ b/modules/util/legacy_test.go
@@ -17,7 +17,7 @@ import (
func TestCopyFile(t *testing.T) {
testContent := []byte("hello")
- tmpDir := os.TempDir()
+ tmpDir := t.TempDir()
now := time.Now()
srcFile := fmt.Sprintf("%s/copy-test-%d-src.txt", tmpDir, now.UnixMicro())
dstFile := fmt.Sprintf("%s/copy-test-%d-dst.txt", tmpDir, now.UnixMicro())
diff --git a/modules/util/map.go b/modules/util/map.go
new file mode 100644
index 0000000000..f307faad1f
--- /dev/null
+++ b/modules/util/map.go
@@ -0,0 +1,13 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package util
+
+func GetMapValueOrDefault[T any](m map[string]any, key string, defaultValue T) T {
+ if value, ok := m[key]; ok {
+ if v, ok := value.(T); ok {
+ return v
+ }
+ }
+ return defaultValue
+}
diff --git a/modules/util/map_test.go b/modules/util/map_test.go
new file mode 100644
index 0000000000..1a141cec88
--- /dev/null
+++ b/modules/util/map_test.go
@@ -0,0 +1,26 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package util
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetMapValueOrDefault(t *testing.T) {
+ testMap := map[string]any{
+ "key1": "value1",
+ "key2": 42,
+ "key3": nil,
+ }
+
+ assert.Equal(t, "value1", GetMapValueOrDefault(testMap, "key1", "default"))
+ assert.Equal(t, 42, GetMapValueOrDefault(testMap, "key2", 0))
+
+ assert.Equal(t, "default", GetMapValueOrDefault(testMap, "key4", "default"))
+ assert.Equal(t, 100, GetMapValueOrDefault(testMap, "key5", 100))
+
+ assert.Equal(t, "default", GetMapValueOrDefault(testMap, "key3", "default"))
+}
diff --git a/modules/util/paginate_test.go b/modules/util/paginate_test.go
index 6e69dd19cc..3dc5095071 100644
--- a/modules/util/paginate_test.go
+++ b/modules/util/paginate_test.go
@@ -13,23 +13,23 @@ func TestPaginateSlice(t *testing.T) {
stringSlice := []string{"a", "b", "c", "d", "e"}
result, ok := PaginateSlice(stringSlice, 1, 2).([]string)
assert.True(t, ok)
- assert.EqualValues(t, []string{"a", "b"}, result)
+ assert.Equal(t, []string{"a", "b"}, result)
result, ok = PaginateSlice(stringSlice, 100, 2).([]string)
assert.True(t, ok)
- assert.EqualValues(t, []string{}, result)
+ assert.Equal(t, []string{}, result)
result, ok = PaginateSlice(stringSlice, 3, 2).([]string)
assert.True(t, ok)
- assert.EqualValues(t, []string{"e"}, result)
+ assert.Equal(t, []string{"e"}, result)
result, ok = PaginateSlice(stringSlice, 1, 0).([]string)
assert.True(t, ok)
- assert.EqualValues(t, []string{"a", "b", "c", "d", "e"}, result)
+ assert.Equal(t, []string{"a", "b", "c", "d", "e"}, result)
result, ok = PaginateSlice(stringSlice, 1, -1).([]string)
assert.True(t, ok)
- assert.EqualValues(t, []string{"a", "b", "c", "d", "e"}, result)
+ assert.Equal(t, []string{"a", "b", "c", "d", "e"}, result)
type Test struct {
Val int
@@ -38,9 +38,9 @@ func TestPaginateSlice(t *testing.T) {
testVar := []*Test{{Val: 2}, {Val: 3}, {Val: 4}}
testVar, ok = PaginateSlice(testVar, 1, 50).([]*Test)
assert.True(t, ok)
- assert.EqualValues(t, []*Test{{Val: 2}, {Val: 3}, {Val: 4}}, testVar)
+ assert.Equal(t, []*Test{{Val: 2}, {Val: 3}, {Val: 4}}, testVar)
testVar, ok = PaginateSlice(testVar, 2, 2).([]*Test)
assert.True(t, ok)
- assert.EqualValues(t, []*Test{{Val: 4}}, testVar)
+ assert.Equal(t, []*Test{{Val: 4}}, testVar)
}
diff --git a/modules/util/path.go b/modules/util/path.go
index d9f17bd124..0e56348978 100644
--- a/modules/util/path.go
+++ b/modules/util/path.go
@@ -36,9 +36,10 @@ func PathJoinRel(elem ...string) string {
elems[i] = path.Clean("/" + e)
}
p := path.Join(elems...)
- if p == "" {
+ switch p {
+ case "":
return ""
- } else if p == "/" {
+ case "/":
return "."
}
return p[1:]
diff --git a/modules/util/remove.go b/modules/util/remove.go
index d1e38faf5f..3db0b5a796 100644
--- a/modules/util/remove.go
+++ b/modules/util/remove.go
@@ -15,7 +15,7 @@ const windowsSharingViolationError syscall.Errno = 32
// Remove removes the named file or (empty) directory with at most 5 attempts.
func Remove(name string) error {
var err error
- for i := 0; i < 5; i++ {
+ for range 5 {
err = os.Remove(name)
if err == nil {
break
@@ -44,7 +44,7 @@ func Remove(name string) error {
// RemoveAll removes the named file or (empty) directory with at most 5 attempts.
func RemoveAll(name string) error {
var err error
- for i := 0; i < 5; i++ {
+ for range 5 {
err = os.RemoveAll(name)
if err == nil {
break
@@ -73,7 +73,7 @@ func RemoveAll(name string) error {
// Rename renames (moves) oldpath to newpath with at most 5 attempts.
func Rename(oldpath, newpath string) error {
var err error
- for i := 0; i < 5; i++ {
+ for i := range 5 {
err = os.Rename(oldpath, newpath)
if err == nil {
break
diff --git a/modules/util/rotatingfilewriter/writer_test.go b/modules/util/rotatingfilewriter/writer_test.go
index 88392797b3..f6ea1d50ae 100644
--- a/modules/util/rotatingfilewriter/writer_test.go
+++ b/modules/util/rotatingfilewriter/writer_test.go
@@ -23,7 +23,7 @@ func TestCompressOldFile(t *testing.T) {
ng, err := os.OpenFile(nonGzip, os.O_CREATE|os.O_WRONLY, 0o660)
assert.NoError(t, err)
- for i := 0; i < 999; i++ {
+ for range 999 {
f.WriteString("This is a test file\n")
ng.WriteString("This is a test file\n")
}
diff --git a/modules/util/runtime_test.go b/modules/util/runtime_test.go
index 20f9063b0b..01dd034cea 100644
--- a/modules/util/runtime_test.go
+++ b/modules/util/runtime_test.go
@@ -18,14 +18,14 @@ func TestCallerFuncName(t *testing.T) {
func BenchmarkCallerFuncName(b *testing.B) {
// BenchmarkCaller/sprintf-12 12744829 95.49 ns/op
b.Run("sprintf", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
_ = fmt.Sprintf("aaaaaaaaaaaaaaaa %s %s %s", "bbbbbbbbbbbbbbbbbbb", b.Name(), "ccccccccccccccccccccc")
}
})
// BenchmarkCaller/caller-12 10625133 113.6 ns/op
// It is almost as fast as fmt.Sprintf
b.Run("caller", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
CallerFuncName(1)
}
})
diff --git a/modules/util/sec_to_time.go b/modules/util/sec_to_time.go
index 73667d723e..646f33c82a 100644
--- a/modules/util/sec_to_time.go
+++ b/modules/util/sec_to_time.go
@@ -11,16 +11,20 @@ import (
// SecToHours converts an amount of seconds to a human-readable hours string.
// This is stable for planning and managing timesheets.
// Here it only supports hours and minutes, because a work day could contain 6 or 7 or 8 hours.
+// If the duration is less than 1 minute, it will be shown as seconds.
func SecToHours(durationVal any) string {
- duration, _ := ToInt64(durationVal)
- hours := duration / 3600
- minutes := (duration / 60) % 60
+ seconds, _ := ToInt64(durationVal)
+ hours := seconds / 3600
+ minutes := (seconds / 60) % 60
formattedTime := ""
formattedTime = formatTime(hours, "hour", formattedTime)
formattedTime = formatTime(minutes, "minute", formattedTime)
// The formatTime() function always appends a space at the end. This will be trimmed
+ if formattedTime == "" && seconds > 0 {
+ formattedTime = formatTime(seconds, "second", "")
+ }
return strings.TrimRight(formattedTime, " ")
}
diff --git a/modules/util/sec_to_time_test.go b/modules/util/sec_to_time_test.go
index 71a8801d4f..84e767c6e0 100644
--- a/modules/util/sec_to_time_test.go
+++ b/modules/util/sec_to_time_test.go
@@ -22,4 +22,7 @@ func TestSecToHours(t *testing.T) {
assert.Equal(t, "156 hours 30 minutes", SecToHours(6*day+12*hour+30*minute+18*second))
assert.Equal(t, "98 hours 16 minutes", SecToHours(4*day+2*hour+16*minute+58*second))
assert.Equal(t, "672 hours", SecToHours(4*7*day))
+ assert.Equal(t, "1 second", SecToHours(1))
+ assert.Equal(t, "2 seconds", SecToHours(2))
+ assert.Empty(t, SecToHours(nil)) // old behavior, empty means no output
}
diff --git a/modules/util/slice.go b/modules/util/slice.go
index 9c878c24be..da6886491e 100644
--- a/modules/util/slice.go
+++ b/modules/util/slice.go
@@ -71,3 +71,10 @@ func KeysOfMap[K comparable, V any](m map[K]V) []K {
}
return keys
}
+
+func SliceNilAsEmpty[T any](a []T) []T {
+ if a == nil {
+ return []T{}
+ }
+ return a
+}
diff --git a/modules/util/string.go b/modules/util/string.go
index 19cf75b8b3..b9b59df3ef 100644
--- a/modules/util/string.go
+++ b/modules/util/string.go
@@ -103,10 +103,31 @@ func UnsafeStringToBytes(s string) []byte {
func SplitTrimSpace(input, sep string) []string {
input = strings.TrimSpace(input)
var stringList []string
- for _, s := range strings.Split(input, sep) {
+ for s := range strings.SplitSeq(input, sep) {
if s = strings.TrimSpace(s); s != "" {
stringList = append(stringList, s)
}
}
return stringList
}
+
+func asciiLower(b byte) byte {
+ if 'A' <= b && b <= 'Z' {
+ return b + ('a' - 'A')
+ }
+ return b
+}
+
+// AsciiEqualFold is from Golang https://cs.opensource.google/go/go/+/refs/tags/go1.24.4:src/net/http/internal/ascii/print.go
+// ASCII only. In most cases for protocols, we should only use this but not [strings.EqualFold]
+func AsciiEqualFold(s, t string) bool { //nolint:revive // PascalCase
+ if len(s) != len(t) {
+ return false
+ }
+ for i := 0; i < len(s); i++ {
+ if asciiLower(s[i]) != asciiLower(t[i]) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/modules/util/truncate_test.go b/modules/util/truncate_test.go
index 8789c824f5..9f4ad7dc20 100644
--- a/modules/util/truncate_test.go
+++ b/modules/util/truncate_test.go
@@ -5,6 +5,7 @@ package util
import (
"fmt"
+ "strconv"
"strings"
"testing"
@@ -100,7 +101,7 @@ func TestEllipsisString(t *testing.T) {
{limit: 7, left: "\xef\x03\xfe\xef\x03\xfe", right: ""},
}
for _, c := range invalidCases {
- t.Run(fmt.Sprintf("%d", c.limit), func(t *testing.T) {
+ t.Run(strconv.Itoa(c.limit), func(t *testing.T) {
left, right := EllipsisDisplayStringX("\xef\x03\xfe\xef\x03\xfe", c.limit)
assert.Equal(t, c.left, left, "left")
assert.Equal(t, c.right, right, "right")
@@ -115,15 +116,15 @@ func TestEllipsisString(t *testing.T) {
}
func TestTruncateRunes(t *testing.T) {
- assert.Equal(t, "", TruncateRunes("", 0))
- assert.Equal(t, "", TruncateRunes("", 1))
+ assert.Empty(t, TruncateRunes("", 0))
+ assert.Empty(t, TruncateRunes("", 1))
- assert.Equal(t, "", TruncateRunes("ab", 0))
+ assert.Empty(t, TruncateRunes("ab", 0))
assert.Equal(t, "a", TruncateRunes("ab", 1))
assert.Equal(t, "ab", TruncateRunes("ab", 2))
assert.Equal(t, "ab", TruncateRunes("ab", 3))
- assert.Equal(t, "", TruncateRunes("测试", 0))
+ assert.Empty(t, TruncateRunes("测试", 0))
assert.Equal(t, "测", TruncateRunes("测试", 1))
assert.Equal(t, "测试", TruncateRunes("测试", 2))
assert.Equal(t, "测试", TruncateRunes("测试", 3))
diff --git a/modules/util/util.go b/modules/util/util.go
index 1fb4cb21cb..dd8e073888 100644
--- a/modules/util/util.go
+++ b/modules/util/util.go
@@ -11,21 +11,10 @@ import (
"strconv"
"strings"
- "code.gitea.io/gitea/modules/optional"
-
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
-// OptionalBoolParse get the corresponding optional.Option[bool] of a string using strconv.ParseBool
-func OptionalBoolParse(s string) optional.Option[bool] {
- v, e := strconv.ParseBool(s)
- if e != nil {
- return optional.None[bool]()
- }
- return optional.Some(v)
-}
-
// IsEmptyString checks if the provided string is empty
func IsEmptyString(s string) bool {
return len(strings.TrimSpace(s)) == 0
@@ -230,6 +219,13 @@ func IfZero[T comparable](v, def T) T {
return v
}
+func IfEmpty[T any](v, def []T) []T {
+ if len(v) == 0 {
+ return def
+ }
+ return v
+}
+
// OptionalArg helps the "optional argument" in Golang:
//
// func foo(optArg ...int) { return OptionalArg(optArg) }
diff --git a/modules/util/util_test.go b/modules/util/util_test.go
index 52b05acc5b..fe4125cdb5 100644
--- a/modules/util/util_test.go
+++ b/modules/util/util_test.go
@@ -8,8 +8,6 @@ import (
"strings"
"testing"
- "code.gitea.io/gitea/modules/optional"
-
"github.com/stretchr/testify/assert"
)
@@ -175,19 +173,6 @@ func Test_RandomBytes(t *testing.T) {
assert.NotEqual(t, bytes3, bytes4)
}
-func TestOptionalBoolParse(t *testing.T) {
- assert.Equal(t, optional.None[bool](), OptionalBoolParse(""))
- assert.Equal(t, optional.None[bool](), OptionalBoolParse("x"))
-
- assert.Equal(t, optional.Some(false), OptionalBoolParse("0"))
- assert.Equal(t, optional.Some(false), OptionalBoolParse("f"))
- assert.Equal(t, optional.Some(false), OptionalBoolParse("False"))
-
- assert.Equal(t, optional.Some(true), OptionalBoolParse("1"))
- assert.Equal(t, optional.Some(true), OptionalBoolParse("t"))
- assert.Equal(t, optional.Some(true), OptionalBoolParse("True"))
-}
-
// Test case for any function which accepts and returns a single string.
type StringTest struct {
in, out string
@@ -215,7 +200,7 @@ func TestToUpperASCII(t *testing.T) {
func BenchmarkToUpper(b *testing.B) {
for _, tc := range upperTests {
b.Run(tc.in, func(b *testing.B) {
- for i := 0; i < b.N; i++ {
+ for b.Loop() {
ToUpperASCII(tc.in)
}
})