aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-10-07 03:37:39 +0900
committerOphestra <cat@gensokyo.uk>2026-10-07 03:37:39 +0900
commit656a4324e896da8a3d0b1c0de6b91a2ffe1e99cd (patch)
tree244c70a39d110310eca08af03247c7db6b7322e1
parent7ff313f463bcc73225e8d62764c06607eda8f36d (diff)
internal/testsuite: handle intermittent EACCES
The test suite is now fast enough that the tester can also suffer from the same vfs race. This change works around such intermittent failures. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--cmd/hakurei/testsuite/sandbox/tester/main.go12
-rw-r--r--internal/testsuite/testsuite.go26
2 files changed, 36 insertions, 2 deletions
diff --git a/cmd/hakurei/testsuite/sandbox/tester/main.go b/cmd/hakurei/testsuite/sandbox/tester/main.go
index 452712d9..6ccad5be 100644
--- a/cmd/hakurei/testsuite/sandbox/tester/main.go
+++ b/cmd/hakurei/testsuite/sandbox/tester/main.go
@@ -15,6 +15,7 @@ import (
"syscall"
"hakurei.app/cmd/hakurei/testsuite/sandbox/testdata"
+ "hakurei.app/internal/testsuite"
"hakurei.app/internal/testsuite/mountinfo"
)
@@ -29,6 +30,13 @@ func mustAbs(s string) string {
return s
}
+// dial is [net.Dial] retrying intermittent EACCES.
+func dial(network, address string) (net.Conn, error) {
+ return testsuite.RetryExp(func() (net.Conn, error) {
+ return net.Dial(network, address)
+ }, syscall.EACCES)
+}
+
func main() {
log.SetFlags(0)
log.SetPrefix("tester: ")
@@ -165,8 +173,8 @@ func main() {
if want.TrySocket != "" {
retry:
- abstractConn, abstractErr := net.Dial("unix", "@"+want.TrySocket)
- pathnameConn, pathnameErr := net.Dial("unix", want.TrySocket)
+ abstractConn, abstractErr := dial("unix", "@"+want.TrySocket)
+ pathnameConn, pathnameErr := dial("unix", want.TrySocket)
ok := true
if abstractErr == nil {
diff --git a/internal/testsuite/testsuite.go b/internal/testsuite/testsuite.go
index 6e48eca1..a1e39720 100644
--- a/internal/testsuite/testsuite.go
+++ b/internal/testsuite/testsuite.go
@@ -28,6 +28,32 @@ func ReceiveSignals() {
log.Fatalf("terminating on signal %s", <-s)
}
+// RetryExp retries f if the resulting error is equivalent to e according to
+// [errors.Is], up to 8 times.
+func RetryExp[T any](f func() (T, error), e error) (v T, err error) {
+ const statRetry = 8 // 64 ms
+ var n int
+ d := 256 * time.Microsecond
+
+retry:
+ v, err = f()
+ if err != nil {
+ if !errors.Is(err, e) {
+ return
+ }
+
+ n++
+ if n == statRetry {
+ return
+ }
+
+ time.Sleep(d)
+ d *= 2
+ goto retry
+ }
+ return
+}
+
var (
// users caches [user.LookupId] calls.
users = make(map[string]*user.User)