Files
summercms/modules/pier/export_test.go
Jakub Zych 0aa48ae6c4 test(19.7-09): gate workspace check and unreleased-pin policy, TestSessionReaper and TestAuthTime
- check-phase19.7.sh: workspace_check (framework to this checkout, the OAuth
  server plugin's user plugin to USER_PLUGIN) in the plugins, consumers and
  docker stages; consumer_with_user_plugin builds fonoteka.go and sm-bm-app
  against USER_PLUGIN through a scratch go.work; demo_pins accepts
  unreleased commits its canonical checkout holds and refuses any drift
  with PHASE197_RELEASED=1; self-test cases for each, one PASS line each
- TestSessionReaper pins A-CR-01, A-IN-01 and A-IN-06 (memory and Redis
  stores, store errors, the GET stream re-check, the ephemeral label)
- TestAuthTime pins auth_time at mint and through every refresh path
- GO_TESTS and GO_TAGGED_TESTS require them with the plan 06/07 smokes
2026-10-23 17:45:51 +02:00

88 lines
2.6 KiB
Go

package pier
import (
"context"
"time"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/bouncer"
"git.golem15.com/golem15/summercms/modules/cabana"
)
// Test seams (package pier, compiled into the test binary only).
// SetBackendTokens replaces the admin personal token resolver, which needs
// a database in production (cabana.ResolveBackendToken).
func (p *Pier) SetBackendTokens(fn func(ctx context.Context, app *backpack.App, raw string) (*bouncer.Principal, *cabana.BackendAPIToken, []string, error)) {
p.identities.backendTokens = fn
}
// Resolve resolves a bearer into an Identity as the endpoint does.
func (p *Pier) Resolve(ctx context.Context, raw string) (Identity, error) {
return p.identities.resolve(ctx, raw)
}
// Ceiling reports whether the read/write ceiling applies to the identity.
func (id Identity) Ceiling() bool { return id.ceiling }
// AdvanceStoreClock moves the memory session store's clock forward by d, so
// a test can expire idle sessions without waiting; a Redis store is moved
// with miniredis.FastForward instead.
func (p *Pier) AdvanceStoreClock(d time.Duration) bool {
ms, ok := p.store.(*memoryStore)
if !ok {
return false
}
ms.mu.Lock()
base := ms.now
ms.now = func() time.Time { return base().Add(d) }
ms.mu.Unlock()
return true
}
// StatelessServers counts the per-identity servers of the stateless path.
func (p *Pier) StatelessServers() int {
p.stateless.mu.Lock()
defer p.stateless.mu.Unlock()
return len(p.stateless.entries)
}
// SetRecheck sets how often a long GET stream re-verifies its bearer.
func (p *Pier) SetRecheck(d time.Duration) { p.recheck = d }
// ReapNow runs one session reaper pass and answers how many local sessions
// it closed.
func (p *Pier) ReapNow(ctx context.Context) int { return p.sessions.reapOnce(ctx) }
// LocalSessions counts the stateful sessions connected on this instance.
func (p *Pier) LocalSessions() int {
p.sessions.mu.Lock()
defer p.sessions.mu.Unlock()
return len(p.sessions.local)
}
// StopReaper ends the session reaper goroutine Mount started.
func (p *Pier) StopReaper() {
if p.stopReap != nil {
p.stopReap()
}
}
// SessionDone answers a channel closed once the local session's SDK server
// session has ended (ss.Wait returned), and false when the session is not
// connected on this instance.
func (p *Pier) SessionDone(sid string) (<-chan struct{}, bool) {
p.sessions.mu.Lock()
ls := p.sessions.local[sid]
p.sessions.mu.Unlock()
if ls == nil || ls.ss == nil {
return nil, false
}
done := make(chan struct{})
go func() {
_ = ls.ss.Wait()
close(done)
}()
return done, true
}