testsupport

package
v0.1.21 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: GPL-2.0, GPL-3.0 Imports: 5 Imported by: 0

Documentation

Overview

Package testsupport provides shared test helpers used across multiple packages. It avoids duplicating mock implementations in each test file.

Package testsupport — scanner-alignment helpers.

The store package consolidates SQL column lists and Scan-argument lists in tableScanner-like structs (each scanner pairs a `columns` string with a `scan` or `scanInto` function). This file provides reusable helpers that detect drift between those two halves at test time.

The bug class targeted: a column added to the SELECT list without a matching pointer in the Scan call (or vice versa) panics at runtime when the query is executed. The helpers below catch this in `go test` instead.

Borrows sqlc's safety property (compile-time scan-order validation) without taking the codegen tool. Coverage is partial: the test catches add/remove drift definitively and reorder drift when the test author supplies an expected-field list.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FieldNameAt

func FieldNameAt(sample, ptr any) string

FieldNameAt reports the name of the struct field within `sample` that holds the address `ptr`. Returns "" if `ptr` is outside the memory range of `sample` (a local variable passed to Scan instead of a struct field, e.g. `var manual int; row.Scan(..., &manual, ...)`).

Both arguments must be pointers; sample must be a pointer to a struct. The check is offset-based: each pointer is compared against the addresses of every exported and unexported field. Embedded struct fields are not unwrapped; pass the embedded type directly if needed.

func SplitColumns

func SplitColumns(s string) []string

SplitColumns parses a `tableScanner.columns` string into a slice of trimmed column names. Handles multi-line column lists with tabs, newlines, and surrounding whitespace.

Example:

SplitColumns("id, user_id,\n\ttoken_hash, created_at")
-> ["id", "user_id", "token_hash", "created_at"]

Types

type AlignmentResult

type AlignmentResult struct {
	// Columns is the parsed column list from the scanner's columns string.
	Columns []string
	// ScanArgs is the slice of pointer args captured by ScanRecorder.
	ScanArgs []any
	// Fields contains the resolved field name for each ScanArg, or ""
	// for args that point outside the sample struct (local variables).
	Fields []string
}

AlignmentResult captures the outcome of an Aligned check. The test author decides which assertions to run against it: count match alone catches add/remove drift; comparing Fields against an expected slice catches reorder drift.

type NopConfig

type NopConfig struct {
	ProviderCfgs map[api.ProviderID]api.ProviderCfg
	SearchConfig api.SearchConfig
	AdaptiveCfg  api.AdaptiveConfig
	Sync         api.SyncConfig
	PostProcess  api.PostProcessConfig
	MinScore     int
	ProviderPrio int
}

NopConfig is a zero-value implementation of search.SearchCfg for tests. Embed it in test-specific mocks and override only the methods you need. Note: the compile-time assertion against search.SearchCfg lives in search/nopconfig_assert_test.go to avoid testsupport→search→testsupport import cycles (search test code imports testsupport).

func (*NopConfig) Adaptive

func (n *NopConfig) Adaptive() api.AdaptiveConfig

func (*NopConfig) MinScoreForTarget

func (n *NopConfig) MinScoreForTarget(_ *api.SubtitleTarget, _ api.MediaType) int

func (*NopConfig) PostProcessConfig

func (n *NopConfig) PostProcessConfig() api.PostProcessConfig

func (*NopConfig) ProviderConfigs

func (n *NopConfig) ProviderConfigs() map[api.ProviderID]api.ProviderCfg

func (*NopConfig) ProviderPriority

func (n *NopConfig) ProviderPriority(_ api.ProviderID) int

func (*NopConfig) ProvidersForTarget

func (n *NopConfig) ProvidersForTarget(_ *api.SubtitleTarget, all []api.ProviderID) []api.ProviderID

func (*NopConfig) Scores

func (n *NopConfig) Scores() api.Scores

func (*NopConfig) Search

func (n *NopConfig) Search() api.SearchConfig

func (*NopConfig) SyncConfig

func (n *NopConfig) SyncConfig() api.SyncConfig

type NopStore

type NopStore struct {
	// contains filtered or unexported fields

} //nolint:unused // embedded for compile-time interface safety

NopStore implements api.Store with all methods returning zero/nil values. Embed it in test-specific mock structs and override only the methods relevant to each test case.

NopStore embeds panicStore (which panics on every method) and overrides all methods with no-op returns. When a new method is added to api.Store, only panicStore needs updating (the compiler tells you); NopStore then inherits the panic until the no-op override is added here.

func (*NopStore) BackedOffProviders

func (*NopStore) BackedOffProviders(context.Context, api.MediaType, string, string, int) ([]api.ProviderID, error)

func (*NopStore) CleanupDrift

func (*NopStore) CleanupDrift(context.Context, api.ConfigDrift) error

func (*NopStore) ClearManualLock

func (*NopStore) ClearManualLock(context.Context, api.MediaType, string, string) error

func (*NopStore) Close

func (*NopStore) Close(context.Context) error

func (*NopStore) CurrentScore

func (*NopStore) CurrentScore(context.Context, api.MediaType, string, string) (score int, at time.Time, found bool, _ error)

func (*NopStore) DeleteStateByPaths

func (*NopStore) DeleteStateByPaths(context.Context, []string) (api.CleanupResult, error)

func (*NopStore) DownloadedRefs

func (*NopStore) GetBackoffByPrefix

func (*NopStore) GetBackoffByPrefix(context.Context, api.MediaType, string) ([]api.BackoffEntry, error)

func (*NopStore) GetBackoffItems

func (*NopStore) GetBackoffItems(context.Context) ([]api.BackoffEntry, error)

func (*NopStore) GetManualLocks

func (*NopStore) GetManualLocks(context.Context) ([]api.ManualLockEntry, error)

func (*NopStore) GetPollTimestamp

func (*NopStore) GetPollTimestamp(context.Context, api.PollKey) (time.Time, error)

func (*NopStore) GetScanStates

func (*NopStore) GetScanStates(context.Context, api.MediaType, string) ([]api.ScanStateRow, error)

func (*NopStore) GetState

func (*NopStore) GetSubtitleFiles

func (*NopStore) GetSubtitleFiles(context.Context, api.MediaType, string) ([]api.SubtitleFileRow, error)

func (*NopStore) GetSyncOffset

func (*NopStore) GetSyncOffset(context.Context, string) (int64, error)

func (*NopStore) HistoryMediaIDs

func (*NopStore) HistoryMediaIDs(context.Context, api.MediaType, string) ([]string, error)

func (*NopStore) IsManuallyLocked

func (*NopStore) IsManuallyLocked(context.Context, api.MediaType, string, string) (bool, error)

func (*NopStore) LastScanTime

func (*NopStore) LastScanTime(context.Context) (string, error)

func (*NopStore) ManualDownloadCount

func (*NopStore) ManualDownloadCount(context.Context, api.MediaType, string, string) (int, error)

func (*NopStore) ManualSubtitlePaths

func (*NopStore) ManualSubtitlePaths(context.Context, api.MediaType, string, string) ([]string, error)

func (*NopStore) NextManualNumber

func (*NopStore) NextManualNumber(context.Context, api.MediaType, string, string) int

func (*NopStore) RecentlyScanned

func (*NopStore) RecentlyScanned(context.Context, time.Time) (map[string]bool, error)

func (*NopStore) ReconcileState

func (*NopStore) ReconcileState(context.Context) (api.ReconcileResult, error)

func (*NopStore) RecordScanState

func (*NopStore) RecordScanState(context.Context, *api.ScanRecord) error

func (*NopStore) RecordSubtitleFiles

func (*NopStore) RecordSubtitleFiles(context.Context, api.MediaType, string, []api.SubtitleFile) (bool, error)

func (*NopStore) SaveDownload

func (*NopStore) SaveDownload(context.Context, *api.DownloadRecord) error

func (*NopStore) SetPollTimestamp

func (*NopStore) SetPollTimestamp(context.Context, api.PollKey, time.Time) error

func (*NopStore) SetSyncOffset

func (*NopStore) SetSyncOffset(context.Context, string, int64) error

func (*NopStore) Stats

func (*NopStore) Stats(context.Context) (downloads, backoffs int, _ error)

func (*NopStore) TotalSubtitleFiles

func (*NopStore) TotalSubtitleFiles(context.Context) (int, error)

func (*NopStore) UpsertSubtitleFile

func (*NopStore) UpsertSubtitleFile(context.Context, api.MediaType, string, *api.SubtitleFile) error

type ScanRecorder

type ScanRecorder struct {
	Args []any
}

ScanRecorder satisfies the `interface{ Scan(...any) error }` shape used by row scanners and captures the pointer arguments passed to Scan in the order they were passed.

func (*ScanRecorder) Scan

func (r *ScanRecorder) Scan(args ...any) error

Scan records args and returns nil. Pass &ScanRecorder{} as the row to any scanInto / scan function to capture its argument order.

Jump to

Keyboard shortcuts

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