Documentation
¶
Index ¶
- Constants
- Variables
- func FixtureName(profile, path string, jsonMode bool) string
- func IdentifierShape(s string) string
- func LoadBearing(path string) bool
- func Redact(body []byte) []byte
- func SaveFixture(dir, name string, r Response) error
- func SaveFixtureTrimmed(dir, name string, r Response) (int, error)
- func TrimBody(body []byte) ([]byte, bool)
- func ValidateBinary(r Response) error
- func WriteSummary(w io.Writer, r Report, values bool)
- func WriteTable(w io.Writer, sums []EndpointSummary)
- func WriteText(w io.Writer, r Report, values bool)
- type Client
- type Difference
- type DiscoveredIDs
- type EndpointSummary
- type PathSummary
- type Protocol
- type ReferenceDefect
- type Report
- type Request
- type RequestComparer
- type Response
- type ResponseObserver
- type Route
- type RouteInventory
Constants ¶
const ( KindMissing = "missing" KindExtra = "extra" KindType = "type" KindValue = "value" KindStatus = "status" KindHeader = "header" KindParse = "parse" KindRequestError = "request_error" )
Difference kinds. Missing, extra, type, status, header, parse and request_error differences are blocking. Value differences stay informational here so Jellyfin/Emby/Silo are not gated on the Plex load-bearing list. plex.Compare promotes those values (and hub #order).
Variables ¶
var KeyShapeFields = []string{"key", "ratingKey"}
KeyShapeFields compare by identifier shape (path template or {id}), not the numeric IDs inside them. A shape mismatch is load-bearing.
var LoadBearingFields = []string{
"viewMode",
"viewGroup",
"leafCount",
"viewedLeafCount",
"childCount",
"size",
"totalSize",
"type",
"nocache",
"allowSync",
"librarySectionID",
"hubIdentifier",
"context",
"style",
"more",
"generalDecisionCode",
"directPlayDecisionCode",
"transcodeDecisionCode",
"mdeDecisionCode",
"generalDecisionText",
"directPlayDecisionText",
"transcodeDecisionText",
"mdeDecisionText",
}
LoadBearingFields are Plex protocol-shape values clients branch on. Shared Compare reports mismatches; plex.Compare makes them blocking so Jellyfin/Emby/Silo gates are not affected. Catalog contents still differ between servers; those names stay listed here because a wrong type, count, or hub identity is a wire bug even when titles differ.
var VolatileFields = []string{}/* 147 elements not displayed */
VolatileFields are per-server values compared by type (and URL shape) only. A leading or trailing * is a wildcard. Load-bearing names win even when a pattern here would also match.
Functions ¶
func FixtureName ¶
FixtureName is the file name (without ".json") of the fixture for a request made with a client profile in XML or JSON.
func IdentifierShape ¶
IdentifierShape reduces a key or ratingKey to the shape clients match on.
func LoadBearing ¶
LoadBearing reports whether a schema path's leaf is a load-bearing field or a key/ratingKey shape. Image/Rating/Setting @type and Part @key are catalog decoration, not protocol branches.
func SaveFixture ¶
SaveFixture stores one redacted response as a JSON fixture.
func SaveFixtureTrimmed ¶
SaveFixtureTrimmed redacts and limits each repeated container child list to 50 items. It returns the number of response bodies whose listings were shortened.
func TrimBody ¶
TrimBody truncates XML repeated sibling elements and JSON arrays to their first 50 entries.
func ValidateBinary ¶
ValidateBinary checks a live response against strict byte-range semantics.
func WriteSummary ¶
WriteSummary prints, per endpoint, the missing and extra attributes or elements and the type mismatches (and, with values, the informational value differences), followed by a count table.
func WriteTable ¶
func WriteTable(w io.Writer, sums []EndpointSummary)
WriteTable prints a Markdown table of per-endpoint difference counts (distinct schema paths across clients).
Types ¶
type Difference ¶
type Difference struct {
// Client, Format and Endpoint identify the request (filled by the
// caller that ran it; Compare leaves them empty).
Client string `json:"client,omitempty"`
Format string `json:"format,omitempty"`
Endpoint string `json:"endpoint,omitempty"`
Path string `json:"path"`
Kind string `json:"kind"`
Reference any `json:"reference,omitempty"`
Target any `json:"target,omitempty"`
// Count is how many times the path occurs on the side that has it (the
// reference for missing/type/value, the target for extra).
Count int `json:"count,omitempty"`
// Nested is how many descendant paths of a missing or extra element
// were folded into this difference.
Nested int `json:"nested,omitempty"`
Blocking bool `json:"blocking"`
Reason string `json:"reason,omitempty"`
}
Difference describes one structural or protocol mismatch at one schema path. Array indices are collapsed, so a path stands for every element of a repeated list ("/MediaContainer/Video/@title", "$/MediaContainer/Metadata[]/title").
type DiscoveredIDs ¶
type DiscoveredIDs struct {
Values map[string]string `json:"values"`
Warnings []string `json:"warnings,omitempty"`
}
DiscoveredIDs holds per-server identifiers used to make templated probes target real items.
type EndpointSummary ¶
type EndpointSummary struct {
Endpoint string `json:"endpoint"`
Missing []PathSummary `json:"missing,omitempty"`
Extra []PathSummary `json:"extra,omitempty"`
Type []PathSummary `json:"type,omitempty"`
Value []PathSummary `json:"value,omitempty"`
// Other holds status, header, parse and request errors.
Other []PathSummary `json:"other,omitempty"`
}
EndpointSummary groups the differences of one endpoint (all clients and formats).
func Summarize ¶
func Summarize(r Report) []EndpointSummary
Summarize groups a report by endpoint, then by (format, kind, path), so a gap that every client shows is listed once.
func (EndpointSummary) Blocking ¶
func (e EndpointSummary) Blocking() int
Blocking counts the endpoint's blocking path differences.
type PathSummary ¶
type PathSummary struct {
Format string `json:"format"`
Path string `json:"path"`
Kind string `json:"kind"`
Reference string `json:"reference,omitempty"`
Target string `json:"target,omitempty"`
Clients []string `json:"clients"`
Count int `json:"count,omitempty"`
Nested int `json:"nested,omitempty"`
Blocking bool `json:"blocking,omitempty"`
}
PathSummary is one schema difference aggregated across the clients that showed it.
type Protocol ¶
type Protocol interface {
Clients() map[string]Client
Corpus(profile string) []Request
Formats() []bool // false is XML, true is JSON
Discover(context.Context, *http.Client, string, string, string, *DiscoveredIDs) DiscoveredIDs
Fetch(context.Context, *http.Client, string, string, Request, string, map[string]string, bool) (Response, error)
FixtureName(profile string, request Request, jsonMode bool) string
// IgnorePaths supplies regular expressions for protocol-specific differences.
IgnorePaths() []string
Redact(response Response) Response
Compare(reference, target Response) Report
}
Protocol supplies the wire-specific parts of a conformance run. Implementations must not retain credentials or use shared mutable state between runs.
type ReferenceDefect ¶
type ReferenceDefect struct {
ID string `json:"id"`
Detail string `json:"detail"`
Observed string `json:"observed"`
}
ReferenceDefect records a known behavior of a reference, never an Ether requirement.
type Report ¶
type Report struct {
Differences []Difference `json:"differences"`
Discovery []string `json:"discovery,omitempty"`
ReferenceDefects []ReferenceDefect `json:"reference_defects,omitempty"`
// Endpoints lists every endpoint compared, so summaries can show
// endpoints without differences too.
Endpoints []string `json:"endpoints,omitempty"`
}
Report is the result of comparing responses.
func Compare ¶
Compare checks status, selected headers and the response schema. Bodies are reduced to schemas (paths with array indices collapsed, the set of value types and distinct values seen at each path, and child element order), so two listings of different titles compare by shape: an attribute that PMS emits on some items but the target never emits is "missing", the reverse is "extra", and a JSON number where PMS sends a string is a "type" mismatch. VolatileFields (titles, timestamps, versions, redacted fields) are compared by type only. LoadBearingFields still emit value diffs (including multi-value sets); plex.Compare promotes those to blocking.
func CompareBinary ¶
CompareBinary compares range semantics, not media bytes or cross-server hashes.
func CompareHeaders ¶
CompareHeaders compares responses using protocol-supplied headers.
func ComparePlaylist ¶
ComparePlaylist compares HLS structure without comparing signed URLs, segment counts, timestamps or media-specific values across servers.
func (Report) WithRequest ¶
WithRequest stamps every difference with the request it came from.
type Request ¶
type Request struct {
Name, Method, Path string
Headers map[string]http.Header
Body []byte
RangeKind string
FixtureOnly bool
ExpectedStatus int
}
Request is one logical request in the PMS probe corpus.
type RequestComparer ¶
RequestComparer permits narrowly scoped protocol rules that depend on the request being compared. Protocols without it retain the ordinary comparer.
type Response ¶
type Response struct {
Status int `json:"status"`
Headers http.Header `json:"headers"`
Body []byte `json:"body"`
Kind string `json:"kind,omitempty"`
RangeKind string `json:"rangeKind,omitempty"`
BodyLength int64 `json:"bodyLength,omitempty"`
SHA256 string `json:"sha256,omitempty"`
Truncated bool `json:"truncated,omitempty"`
ReferenceDefect *ReferenceDefect `json:"reference_defect,omitempty"`
RequestRange string `json:"requestRange,omitempty"`
}
Response is a captured HTTP response.
func LoadFixture ¶
LoadFixture reads a response fixture.
func RedactSecrets ¶
RedactSecrets removes known run-specific credentials and identifiers from a response before it can reach disk or reports, without altering JSON keys.
type ResponseObserver ¶
ResponseObserver is an optional protocol extension for stateful ordered flows. Implementations may update only the caller-owned run variables.
type RouteInventory ¶
RouteInventory distinguishes an unavailable front end from an available one with no routes.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package capture records sanitized HTTP traffic while proxying client requests.
|
Package capture records sanitized HTTP traffic while proxying client requests. |
|
Package mediabrowser implements profile-driven Jellyfin and Emby probes.
|
Package mediabrowser implements profile-driven Jellyfin and Emby probes. |
|
Package openapi validates JSON responses against OpenAPI 3 and Swagger 2 documents.
|
Package openapi validates JSON responses against OpenAPI 3 and Swagger 2 documents. |
|
Package silo provides Silo's native profile-driven conformance protocol.
|
Package silo provides Silo's native profile-driven conformance protocol. |
|
Package specs exposes the pinned conformance manifest to offline tools.
|
Package specs exposes the pinned conformance manifest to offline tools. |