1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
package sync
import (
"errors"
"fmt"
stdsync "sync"
"sync/atomic"
"testing"
"codeberg.org/snonux/gitsyncer/internal/config"
)
func TestHandlePushError_DisablesBackupForSession(t *testing.T) {
syncer := &Syncer{}
syncer.SetBackupEnabled(true)
err := syncer.handlePushError("backup", &config.Organization{BackupLocation: true}, errors.New("dial tcp: connection refused"))
if err != nil {
t.Fatalf("expected backup push failure to be downgraded, got %v", err)
}
if syncer.backupActive() {
t.Fatal("expected backup sync to be disabled for the remainder of the session")
}
}
func TestHandlePushError_PropagatesPrimaryRemoteFailure(t *testing.T) {
syncer := &Syncer{}
syncer.SetBackupEnabled(true)
pushErr := errors.New("push rejected")
err := syncer.handlePushError("origin", &config.Organization{}, pushErr)
if !errors.Is(err, pushErr) {
t.Fatalf("expected primary remote error to be returned, got %v", err)
}
}
func TestHandlePushError_BackupDisableIsIsolatedPerSyncer(t *testing.T) {
backupOrg := &config.Organization{BackupLocation: true}
syncerA := &Syncer{}
syncerA.SetBackupEnabled(true)
syncerB := &Syncer{}
syncerB.SetBackupEnabled(true)
err := syncerA.handlePushError("backup-a", backupOrg, errors.New("dial tcp: connection refused"))
if err != nil {
t.Fatalf("expected backup push failure to be downgraded, got %v", err)
}
if syncerA.backupActive() {
t.Fatal("expected syncerA backup sync to be disabled for the remainder of the session")
}
if !syncerB.backupActive() {
t.Fatal("expected syncerB backup session to remain active")
}
}
func TestBackupSessionState_DisableIsThreadSafe(t *testing.T) {
var session backupSessionState
var firstDisableCount atomic.Int32
const workers = 32
var wg stdsync.WaitGroup
wg.Add(workers)
for i := 0; i < workers; i++ {
go func(i int) {
defer wg.Done()
if session.disable(fmt.Sprintf("reason-%d", i)) {
firstDisableCount.Add(1)
}
}(i)
}
wg.Wait()
if got := firstDisableCount.Load(); got != 1 {
t.Fatalf("expected exactly one successful disable transition, got %d", got)
}
disabled, reason := session.status()
if !disabled {
t.Fatal("expected backup session to be disabled")
}
if reason == "" {
t.Fatal("expected disable reason to be recorded")
}
}
func TestParseSSHLocation_SupportsSSHURLWithPort(t *testing.T) {
t.Parallel()
userHost, sshArgs, basePath, err := parseSSHLocation("ssh://git@r0:30022/repos")
if err != nil {
t.Fatalf("parseSSHLocation() error = %v", err)
}
if userHost != "git@r0" {
t.Fatalf("userHost = %q, want %q", userHost, "git@r0")
}
if basePath != "/repos" {
t.Fatalf("basePath = %q, want %q", basePath, "/repos")
}
wantArgs := []string{"-p", "30022", "git@r0"}
if len(sshArgs) != len(wantArgs) {
t.Fatalf("sshArgs = %#v, want %#v", sshArgs, wantArgs)
}
for i := range wantArgs {
if sshArgs[i] != wantArgs[i] {
t.Fatalf("sshArgs = %#v, want %#v", sshArgs, wantArgs)
}
}
}
|