Skip to content

Commit 24f9ebc

Browse files
committed
fix: bad_credentials state not starting automatically
1 parent dc0d3d5 commit 24f9ebc

11 files changed

Lines changed: 1169 additions & 63 deletions

pkg/connector/auth_recovery_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,102 @@ func TestRunTokenRecoveryRejectsInvalidatedSessionBeforeRecentRecovery(t *testin
245245
}
246246
}
247247

248+
func TestRunTokenRecoveryRejectsSupersededClient(t *testing.T) {
249+
lc := &LineClient{}
250+
lc.retire()
251+
var calls int
252+
err := lc.runTokenRecovery(context.Background(), func(context.Context) error {
253+
calls++
254+
return nil
255+
})
256+
if !errors.Is(err, errLineClientSuperseded) {
257+
t.Fatalf("err = %v, want errLineClientSuperseded", err)
258+
}
259+
if calls != 0 {
260+
t.Fatalf("recovery calls = %d, want 0", calls)
261+
}
262+
}
263+
264+
func TestRecoverTokenDoesNotReloginAfterForcedLogoutRefresh(t *testing.T) {
265+
lc := &LineClient{}
266+
var reloginCalls int
267+
err := lc.recoverTokenWith(
268+
context.Background(),
269+
func(context.Context) error { return errLoggedOut },
270+
func(context.Context) error {
271+
reloginCalls++
272+
return nil
273+
},
274+
)
275+
if !line.IsLoggedOut(err) {
276+
t.Fatalf("recoverTokenWith error = %v, want logged-out error", err)
277+
}
278+
if reloginCalls != 0 {
279+
t.Fatalf("relogin calls = %d, want 0", reloginCalls)
280+
}
281+
}
282+
283+
func TestRecoverTokenDoesNotReloginAfterCancellation(t *testing.T) {
284+
lc := &LineClient{}
285+
ctx, cancel := context.WithCancel(context.Background())
286+
var reloginCalls int
287+
err := lc.recoverTokenWith(
288+
ctx,
289+
func(context.Context) error {
290+
cancel()
291+
return context.Canceled
292+
},
293+
func(context.Context) error {
294+
reloginCalls++
295+
return nil
296+
},
297+
)
298+
if !errors.Is(err, context.Canceled) {
299+
t.Fatalf("recoverTokenWith error = %v, want context.Canceled", err)
300+
}
301+
if reloginCalls != 0 {
302+
t.Fatalf("relogin calls = %d, want 0", reloginCalls)
303+
}
304+
}
305+
306+
func TestForcedLogoutWinsOverInFlightRecovery(t *testing.T) {
307+
lc := &LineClient{AccessToken: "old-token"}
308+
recoveryStarted := make(chan struct{})
309+
allowRecovery := make(chan struct{})
310+
recoveryDone := make(chan error, 1)
311+
go func() {
312+
recoveryDone <- lc.runTokenRecovery(context.Background(), func(context.Context) error {
313+
close(recoveryStarted)
314+
<-allowRecovery
315+
lc.setTokens("recovered-token", "")
316+
return nil
317+
})
318+
}()
319+
<-recoveryStarted
320+
321+
logoutDone := make(chan struct{})
322+
go func() {
323+
lc.markLoggedOutByOtherClient(context.Background(), errLoggedOut)
324+
close(logoutDone)
325+
}()
326+
close(allowRecovery)
327+
328+
if err := <-recoveryDone; err != nil {
329+
t.Fatalf("recovery returned error: %v", err)
330+
}
331+
select {
332+
case <-logoutDone:
333+
case <-time.After(time.Second):
334+
t.Fatal("forced logout did not complete after recovery")
335+
}
336+
if lc.hasAccessToken() {
337+
t.Fatal("in-flight recovery resurrected the invalidated session")
338+
}
339+
if !lc.isSessionInvalidated() {
340+
t.Fatal("session was not invalidated after in-flight recovery")
341+
}
342+
}
343+
248344
func TestRunTokenRecoverySerializesConcurrentRecovery(t *testing.T) {
249345
var lc LineClient
250346
var calls int32

0 commit comments

Comments
 (0)