* fix(autoscan): bind sources by plugin id * fix(autoscan): skip overlapping source polls
111 lines
4.0 KiB
Go
111 lines
4.0 KiB
Go
package autoscan
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
pluginv1 "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginproto/silo/plugin/v1"
|
|
)
|
|
|
|
// capturingClient records the last PollChangesRequest it was handed.
|
|
type capturingClient struct {
|
|
last *pluginv1.PollChangesRequest
|
|
}
|
|
|
|
func (c *capturingClient) PollChanges(_ context.Context, req *pluginv1.PollChangesRequest) (*pluginv1.PollChangesResponse, error) {
|
|
c.last = req
|
|
return &pluginv1.PollChangesResponse{SourcePaths: []string{"/mnt/media/x"}, NextMarker: "m2"}, nil
|
|
}
|
|
|
|
// capturingResolver yields a fixed PollChangesClient and records the requested
|
|
// stable scan-source identity.
|
|
type capturingResolver struct {
|
|
client PollChangesClient
|
|
lastPluginID string
|
|
lastCapID string
|
|
}
|
|
|
|
func (r *capturingResolver) ScanSourceClient(_ context.Context, pluginID, capabilityID string) (PollChangesClient, error) {
|
|
r.lastPluginID = pluginID
|
|
r.lastCapID = capabilityID
|
|
return r.client, nil
|
|
}
|
|
|
|
// TestPluginProviderPopulatesConnection asserts the resolved connection is
|
|
// delivered to the plugin on the PollChangesRequest.
|
|
func TestPluginProviderPopulatesConnection(t *testing.T) {
|
|
client := &capturingClient{}
|
|
resolver := &capturingResolver{client: client}
|
|
prov := NewPluginProvider(resolver)
|
|
|
|
conn := ResolvedConnection{BaseURL: "https://arr.example", APIKey: "secret-key"}
|
|
sourceConfig := map[string]string{"exclusions": ".downloads"}
|
|
changes, next, err := prov.PollChanges(context.Background(), "silo.autoscan.arr", "cap", "m1", conn, sourceConfig)
|
|
if err != nil {
|
|
t.Fatalf("PollChanges: %v", err)
|
|
}
|
|
if len(changes) != 1 || changes[0].SourcePath != "/mnt/media/x" || changes[0].Scope != ChangeScopeAuto || next != "m2" {
|
|
t.Fatalf("unexpected provider result: changes=%v next=%q", changes, next)
|
|
}
|
|
if client.last == nil {
|
|
t.Fatal("expected a PollChangesRequest to be sent")
|
|
}
|
|
if client.last.GetCapabilityId() != "cap" || client.last.GetMarker() != "m1" {
|
|
t.Fatalf("unexpected request fields: cap=%q marker=%q", client.last.GetCapabilityId(), client.last.GetMarker())
|
|
}
|
|
if resolver.lastPluginID != "silo.autoscan.arr" || resolver.lastCapID != "cap" {
|
|
t.Fatalf("resolver identity = %q/%q", resolver.lastPluginID, resolver.lastCapID)
|
|
}
|
|
rc := client.last.GetConnection()
|
|
if rc == nil {
|
|
t.Fatal("expected connection to be populated on the request")
|
|
}
|
|
if rc.GetBaseUrl() != conn.BaseURL || rc.GetApiKey() != conn.APIKey {
|
|
t.Fatalf("connection not delivered: base_url=%q api_key=%q", rc.GetBaseUrl(), rc.GetApiKey())
|
|
}
|
|
if client.last.GetSourceConfig()["exclusions"] != ".downloads" {
|
|
t.Fatalf("source_config not delivered: %#v", client.last.GetSourceConfig())
|
|
}
|
|
}
|
|
|
|
func TestPluginProviderPrefersStructuredChanges(t *testing.T) {
|
|
client := &capturingStructuredClient{}
|
|
prov := NewPluginProvider(&capturingResolver{client: client})
|
|
|
|
changes, next, err := prov.PollChanges(context.Background(), "silo.autoscan.arr", "cap", "m1", ResolvedConnection{}, nil)
|
|
if err != nil {
|
|
t.Fatalf("PollChanges: %v", err)
|
|
}
|
|
if next != "m3" || len(changes) != 2 {
|
|
t.Fatalf("unexpected provider result: changes=%v next=%q", changes, next)
|
|
}
|
|
if changes[0] != (Change{SourcePath: "/ceph/movie/Movie", Scope: ChangeScopeSubtree}) {
|
|
t.Fatalf("first change = %#v", changes[0])
|
|
}
|
|
if changes[1] != (Change{SourcePath: "/ceph/show/S01/E01.mkv", Scope: ChangeScopeFile}) {
|
|
t.Fatalf("second change = %#v", changes[1])
|
|
}
|
|
}
|
|
|
|
type capturingStructuredClient struct {
|
|
last *pluginv1.PollChangesRequest
|
|
}
|
|
|
|
func (c *capturingStructuredClient) PollChanges(_ context.Context, req *pluginv1.PollChangesRequest) (*pluginv1.PollChangesResponse, error) {
|
|
c.last = req
|
|
return &pluginv1.PollChangesResponse{
|
|
SourcePaths: []string{"/legacy/ignored.mkv"},
|
|
NextMarker: "m3",
|
|
Changes: []*pluginv1.ScanSourceChange{
|
|
{
|
|
SourcePath: "/ceph/movie/Movie",
|
|
Scope: pluginv1.ScanSourceChangeScope_SCAN_SOURCE_CHANGE_SCOPE_SUBTREE,
|
|
},
|
|
{
|
|
SourcePath: "/ceph/show/S01/E01.mkv",
|
|
Scope: pluginv1.ScanSourceChangeScope_SCAN_SOURCE_CHANGE_SCOPE_FILE,
|
|
},
|
|
},
|
|
}, nil
|
|
}
|