返回 DeepSeek-Reasonix
authentication_test.go
根目录 / internal / control / authentication_test.go
1 package control
2
3 import (
4 "context"
5 "errors"
6 "sync"
7 "testing"
8
9 "reasonix/internal/provider"
10 )
11
12 type authenticationTestRunner struct {
13 mu sync.Mutex
14 calls int
15 err error
16 }
17
18 func (r *authenticationTestRunner) Run(context.Context, string) error {
19 r.mu.Lock()
20 defer r.mu.Unlock()
21 r.calls++
22 return r.err
23 }
24
25 func (r *authenticationTestRunner) Calls() int {
26 r.mu.Lock()
27 defer r.mu.Unlock()
28 return r.calls
29 }
30
31 func TestAuthenticationMissingCredentialRejectsBeforeRunner(t *testing.T) {
32 runner := &authenticationTestRunner{}
33 c := newOwnedTestController(t, Options{
34 Runner: runner,
35 Authentication: AuthenticationState{Status: AuthenticationMissingCredential, ProviderName: "deepseek", ModelRef: "deepseek/chat"},
36 })
37 err := c.Run(context.Background(), "must not be submitted")
38 var authErr *AuthenticationError
39 if !errors.As(err, &authErr) || authErr.State.Status != AuthenticationMissingCredential {
40 t.Fatalf("Run error = %v, want missing-credential AuthenticationError", err)
41 }
42 if got := runner.Calls(); got != 0 {
43 t.Fatalf("provider runner calls = %d, want 0", got)
44 }
45 if got := c.Turn(); got != 0 {
46 t.Fatalf("admitted turns = %d, want 0", got)
47 }
48 }
49
50 func TestAuthenticationRejectionLatchesUntilExplicitRetry(t *testing.T) {
51 runner := &authenticationTestRunner{err: &provider.AuthError{Provider: "relay", KeyEnv: "RELAY_API_KEY", Status: 401, HasKey: true}}
52 c := newOwnedTestController(t, Options{Runner: runner, ModelRef: "relay/chat"})
53 if err := c.Run(context.Background(), "first"); err == nil {
54 t.Fatal("first Run unexpectedly succeeded")
55 }
56 if got := c.AuthenticationState(); got.Status != AuthenticationRejected || got.HTTPStatus != 401 {
57 t.Fatalf("authentication state = %+v, want rejected 401", got)
58 }
59 if err := c.Run(context.Background(), "blocked"); err == nil {
60 t.Fatal("blocked Run unexpectedly succeeded")
61 }
62 if got := runner.Calls(); got != 1 {
63 t.Fatalf("provider runner calls after blocked retry = %d, want 1", got)
64 }
65 if !c.RetryAuthentication() {
66 t.Fatal("explicit retry was not accepted")
67 }
68 if err := c.Run(context.Background(), "explicit retry"); err == nil {
69 t.Fatal("explicit retry unexpectedly succeeded")
70 }
71 if got := runner.Calls(); got != 2 {
72 t.Fatalf("provider runner calls after explicit retry = %d, want 2", got)
73 }
74 }
75
75 lines GO