Refactoring #3

Merged
itten merged 87 commits from refactoring into main 2026-09-01 23:52:36 +03:00
5 changed files with 128 additions and 9 deletions
Showing only changes of commit 1eaab14793 - Show all commits
+23
View File
@@ -0,0 +1,23 @@
package playback
import "time"
func (p RetryPolicy) canRetry(failedAttempts int) bool {
return p.MaxAttempts == 0 || failedAttempts < p.MaxAttempts
}
func (p RetryPolicy) retryDelay(failedAttempts int) time.Duration {
delay := p.InitialDelay
for attempt := 1; attempt < failedAttempts; attempt++ {
if delay >= p.MaxDelay/2 {
return p.MaxDelay
}
delay *= 2
}
if delay > p.MaxDelay {
return p.MaxDelay
}
return delay
}
+91
View File
@@ -0,0 +1,91 @@
package playback
import (
"testing"
"time"
)
func TestFiniteAttempts(t *testing.T) {
rp := RetryPolicy{
MaxAttempts: 3,
InitialDelay: 500 * time.Millisecond,
MaxDelay: 10 * time.Second,
}
if !rp.canRetry(1) {
t.Fatal("MaxAttempts=3, failed=1, but can't retry")
}
if !rp.canRetry(2) {
t.Fatal("MaxAttempts=3, failed=2, but can't retry")
}
if rp.canRetry(3) {
t.Fatal("MaxAttempts=3, failed=3, but can retry")
}
}
func TestOneAllowedAttempt(t *testing.T) {
rp := RetryPolicy{
MaxAttempts: 1,
InitialDelay: 500 * time.Millisecond,
MaxDelay: 10 * time.Second,
}
if rp.canRetry(1) {
t.Fatal("MaxAttempts=1, failed=1, but can retry")
}
}
func TestUnlimitedAttempts(t *testing.T) {
rp := RetryPolicy{
MaxAttempts: 0,
InitialDelay: 500 * time.Millisecond,
MaxDelay: 10 * time.Second,
}
for failedAttempts := 1; failedAttempts <= 10; failedAttempts++ {
if !rp.canRetry(failedAttempts) {
t.Fatalf(
"canRetry(%d) = false for unlimited policy",
failedAttempts,
)
}
}
}
func TestBackoff(t *testing.T) {
rp := RetryPolicy{
MaxAttempts: 0,
InitialDelay: 500 * time.Millisecond,
MaxDelay: 10 * time.Second,
}
want := []time.Duration{
500 * time.Millisecond,
1 * time.Second,
2 * time.Second,
4 * time.Second,
8 * time.Second,
10 * time.Second,
10 * time.Second,
}
for i, wantDelay := range want {
failedAttempts := i + 1
got := rp.retryDelay(failedAttempts)
if got != wantDelay {
t.Errorf(
"retryDelay(%d) = %s, want %s",
failedAttempts,
got,
wantDelay,
)
}
}
}
func TestRetryDelayLargeFailureCount(t *testing.T) {
policy := RetryPolicy{
MaxAttempts: 0,
InitialDelay: 500 * time.Millisecond,
MaxDelay: 10 * time.Second,
}
if got := policy.retryDelay(1_000_000); got != policy.MaxDelay {
t.Fatalf("retryDelay() = %s, want cap %s", got, policy.MaxDelay)
}
}
+12
View File
@@ -0,0 +1,12 @@
package playback
type State uint8
const (
StateIdle State = iota
StateConnecting
StatePlaying
StateReconnecting
StateFailed
StateStopping
)
+2 -2
View File
@@ -12,7 +12,7 @@ func TestKindOfThroughWrapping(t *testing.T) {
outer := fmt.Errorf("worker failed: %w", wrapped)
if got := KindOf(outer); got != ErrorKindUnavailable {
t.Fatalf("errorKind() = %v, want %v", got, ErrorKindUnavailable)
t.Fatalf("KindOf() = %v, want %v", got, ErrorKindUnavailable)
}
if !errors.Is(outer, base) {
t.Fatal("wrapped error does not preserve its cause")
@@ -24,7 +24,7 @@ func TestKindOfThroughWrapping(t *testing.T) {
func TestKindOfUnknown(t *testing.T) {
if got := KindOf(errors.New("ordinary error")); got != ErrorKindUnknown {
t.Fatalf("errorKind() = %v, want %v", got, ErrorKindUnknown)
t.Fatalf("KindOf() = %v, want %v", got, ErrorKindUnknown)
}
}
-7
View File
@@ -1,7 +0,0 @@
package main
import "mxl-player/internal/imgui"
func main() {
imgui.New()
}