deviceauthtest

package
v0.1.35 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 3, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package deviceauthtest provides a shared contract test suite for all core.DeviceAuthorizationStore implementations (RFC 8628). Each backend — in-memory, fs, gorm, gae — exercises the same ~10 behavioral scenarios by handing this package a Factory closure and calling RunAll. Mirrors the existing appstoretest / keystoretest precedent.

Why a shared suite: the per-backend test files had started to drift in small ways (wording on error messages, scope-override coverage, LastPolledAt persistence). Pulling the scenarios into one place enforces the contract uniformly and makes adding a fifth backend a one-line RunAll invocation.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RunAll

func RunAll(t *testing.T, factory Factory)

RunAll runs the complete DeviceAuthorizationStore contract suite against the provided factory. Each scenario gets a fresh Backend via factory(t) so state cannot leak between cases.

func TestApproveBindsSubjectAndOverridesScopes

func TestApproveBindsSubjectAndOverridesScopes(t *testing.T, factory Factory)

TestApproveBindsSubjectAndOverridesScopes pins the contract that the approving user's GrantedScopes REPLACE the originally-requested scopes (down-scope at consent, RFC 8628 §3.3-adjacent behavior matching the authorization-code grant's scope semantics).

func TestApproveTwiceRejects

func TestApproveTwiceRejects(t *testing.T, factory Factory)

TestApproveTwiceRejects pins that a second approval looks like not-found, not a noisy state-transition error — once the record is approved the user_code is functionally consumed and any further lookup-by-user_code MUST be indistinguishable from "no such code," otherwise the verification UI leaks pending-state information.

func TestCleanupExpired

func TestCleanupExpired(t *testing.T, factory Factory)

TestCleanupExpired pins that CleanupExpired removes only expired records and reports the count. The non-expired record MUST survive — a naive "delete all" would prematurely cancel pending authorizations.

func TestCollision

func TestCollision(t *testing.T, factory Factory)

TestCollision pins that re-creating a device_code is rejected. The device_code is the AS-issued unique handle the client polls on; a silently-overwritten record would let a second client hijack the first's pending authorization.

func TestCreateAndGet

func TestCreateAndGet(t *testing.T, factory Factory)

TestCreateAndGet pins the happy-path round-trip via both lookup keys and verifies user_code lookup is case- and dash-insensitive.

func TestDeleteRemovesUserCodeIndex

func TestDeleteRemovesUserCodeIndex(t *testing.T, factory Factory)

TestDeleteRemovesUserCodeIndex pins that Delete clears BOTH lookup paths. The user_code index is a denormalized secondary key; backends that forget to clean it leak a record reachable by user_code but not by device_code.

func TestDenyTransitions

func TestDenyTransitions(t *testing.T, factory Factory)

TestDenyTransitions pins that Deny moves the record into the Denied terminal state; the subsequent poll at /api/token will then map this to RFC 8628 §3.5 access_denied.

func TestNotFound

func TestNotFound(t *testing.T, factory Factory)

TestNotFound pins that both lookup keys return ErrDeviceAuthorizationNotFound (not a generic error) when the record does not exist.

func TestRestartPersists

func TestRestartPersists(t *testing.T, factory Factory)

TestRestartPersists pins that a record written via the initial Store handle is visible via a freshly-opened handle over the same backing storage. For persistent backends this is the property the backend exists to provide; for in-memory it degenerates to a same-handle round-trip (Reopen returns the receiver) which is trivially true and kept as a no-op so the scenario set is identical across all backends.

func TestUpdatePollingBumpsInterval

func TestUpdatePollingBumpsInterval(t *testing.T, factory Factory)

TestUpdatePollingBumpsInterval pins RFC 8628 §3.5 slow_down handling: when the AS observes the client polled faster than the advertised interval, the next poll MUST receive an interval bumped by 5 seconds. Also pins that LastPolledAt is persisted so the next poll can do its own interval check.

Types

type Backend

type Backend struct {
	Store  core.DeviceAuthorizationStore
	Reopen func() core.DeviceAuthorizationStore
}

Backend is the per-test fixture handed to every scenario. Store is the initial handle the test exercises; Reopen returns a fresh handle bound to the same backing storage so the RestartPersists scenario can simulate a process restart.

For persistent backends (fs / gorm / gae) Reopen constructs a new store rooted at the same dir / DB connection / namespace. For the in-memory backend Reopen returns the same instance — there is no underlying storage to reconnect to and the property the scenario pins ("data survives a fresh handle") is trivially true.

type Factory

type Factory func(t *testing.T) Backend

Factory creates a Backend per scenario. Persistent backends MUST close over per-test state (a tempdir from t.TempDir(), a *gorm.DB, a datastore namespace) so Store and Reopen both resolve to the same underlying storage within one scenario.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL