mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-08-31 13:17:09 +00:00
100 lines
3.6 KiB
Go
100 lines
3.6 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"atcr.io/pkg/atproto"
|
|
"atcr.io/pkg/auth"
|
|
)
|
|
|
|
func TestEnsureCrewMembership_EmptyHoldDID(t *testing.T) {
|
|
// Test that empty hold DID returns early without error (best-effort function)
|
|
EnsureCrewMembership(context.Background(), "did:plc:user123", "", nil, nil)
|
|
// If we get here without panic, test passes
|
|
}
|
|
|
|
// fakeAuthorizer records cache calls for use in EnsureCrewMembership tests.
|
|
type fakeAuthorizer struct {
|
|
cachedReturn bool
|
|
isCachedCalls atomic.Int32
|
|
recordApprovalCalls atomic.Int32
|
|
clearDenialCalls atomic.Int32
|
|
}
|
|
|
|
func (f *fakeAuthorizer) GetCaptainRecord(ctx context.Context, holdDID string) (*atproto.CaptainRecord, error) {
|
|
return nil, nil
|
|
}
|
|
func (f *fakeAuthorizer) CheckReadAccess(ctx context.Context, holdDID, userDID string) (bool, error) {
|
|
return false, nil
|
|
}
|
|
func (f *fakeAuthorizer) CheckWriteAccess(ctx context.Context, holdDID, userDID string) (bool, error) {
|
|
return false, nil
|
|
}
|
|
func (f *fakeAuthorizer) IsCrewMember(ctx context.Context, holdDID, userDID string) (bool, error) {
|
|
return false, nil
|
|
}
|
|
func (f *fakeAuthorizer) ClearCrewDenial(ctx context.Context, holdDID, userDID string) error {
|
|
f.clearDenialCalls.Add(1)
|
|
return nil
|
|
}
|
|
func (f *fakeAuthorizer) IsCachedCrewMember(ctx context.Context, holdDID, userDID string) (bool, error) {
|
|
f.isCachedCalls.Add(1)
|
|
return f.cachedReturn, nil
|
|
}
|
|
func (f *fakeAuthorizer) RecordCrewApproval(ctx context.Context, holdDID, userDID string) error {
|
|
f.recordApprovalCalls.Add(1)
|
|
return nil
|
|
}
|
|
|
|
var _ auth.HoldAuthorizer = (*fakeAuthorizer)(nil)
|
|
|
|
// TestEnsureCrewMembership_SkipsRequestCrewWhenCached verifies the cache short-circuit:
|
|
// when IsCachedCrewMember returns true, the function returns before invoking the
|
|
// service-token fetcher (and thus before any requestCrew POST).
|
|
func TestEnsureCrewMembership_SkipsRequestCrewWhenCached(t *testing.T) {
|
|
authz := &fakeAuthorizer{cachedReturn: true}
|
|
holdDID := "did:web:hold01.atcr.io"
|
|
|
|
fetcherCalls := atomic.Int32{}
|
|
fetcher := func(ctx context.Context, _ string) (string, error) {
|
|
fetcherCalls.Add(1)
|
|
return "", nil
|
|
}
|
|
|
|
EnsureCrewMembership(context.Background(), "did:plc:user123", holdDID, authz, fetcher)
|
|
|
|
if authz.isCachedCalls.Load() != 1 {
|
|
t.Errorf("Expected IsCachedCrewMember to be called once, got %d", authz.isCachedCalls.Load())
|
|
}
|
|
if fetcherCalls.Load() != 0 {
|
|
t.Errorf("Expected service token fetcher not to be called on cache hit, got %d", fetcherCalls.Load())
|
|
}
|
|
if authz.recordApprovalCalls.Load() != 0 {
|
|
t.Errorf("Expected RecordCrewApproval not to be called on cache hit, got %d", authz.recordApprovalCalls.Load())
|
|
}
|
|
if authz.clearDenialCalls.Load() != 0 {
|
|
t.Errorf("Expected ClearCrewDenial not to be called on cache hit, got %d", authz.clearDenialCalls.Load())
|
|
}
|
|
}
|
|
|
|
// TestEnsureCrewMembership_NilFetcherSkipsAfterCacheCheck verifies that a cache miss
|
|
// with a nil fetcher returns silently and does not call RecordCrewApproval.
|
|
func TestEnsureCrewMembership_NilFetcherSkipsAfterCacheCheck(t *testing.T) {
|
|
authz := &fakeAuthorizer{cachedReturn: false}
|
|
holdDID := "did:web:hold01.atcr.io"
|
|
|
|
EnsureCrewMembership(context.Background(), "did:plc:user123", holdDID, authz, nil)
|
|
|
|
if authz.isCachedCalls.Load() != 1 {
|
|
t.Errorf("Expected IsCachedCrewMember to be called once, got %d", authz.isCachedCalls.Load())
|
|
}
|
|
if authz.recordApprovalCalls.Load() != 0 {
|
|
t.Errorf("Expected RecordCrewApproval not to be called when requestCrew did not run, got %d", authz.recordApprovalCalls.Load())
|
|
}
|
|
}
|
|
|
|
// TODO: Add comprehensive tests with HTTP client mocking for the requestCrew success
|
|
// path (requires a working oauth.Refresher to obtain a service token).
|