135 lines
5.7 KiB
Go
135 lines
5.7 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
agentcommand "agent-command"
|
|
"agent-system-backend/internal/cmdbus"
|
|
"agent-system-backend/internal/store"
|
|
"agent-system-backend/pkg/extension"
|
|
)
|
|
|
|
// compatRegulationsPlugin stands in for the external kbreg repository: it uses
|
|
// only pkg/extension types and registers through the optional Registrar.
|
|
type compatRegulationsPlugin struct{ seen []extension.RegulationsCaller }
|
|
|
|
func (p *compatRegulationsPlugin) Register(reg extension.Registry) error {
|
|
registrar, ok := reg.(extension.RegulationsRegistrar)
|
|
if !ok {
|
|
return errors.New("regulations registrar unavailable")
|
|
}
|
|
return registrar.RegisterRegulationsProvider(p)
|
|
}
|
|
|
|
func (p *compatRegulationsPlugin) SearchRegulations(_ context.Context, c extension.RegulationsCaller, req extension.RegulationsSearchRequest) (extension.RegulationsSearchResult, error) {
|
|
p.seen = append(p.seen, c)
|
|
return extension.RegulationsSearchResult{CorpusRevision: "rev-compat", State: extension.RegulationsStateOK,
|
|
Hits: []extension.RegulationHit{{RegulationID: "r", EditionID: "e", NodeID: "n", Disclosure: extension.RegulationDisclosureExcerpt}}}, nil
|
|
}
|
|
|
|
func (p *compatRegulationsPlugin) ResolveRegulationEvidence(_ context.Context, c extension.RegulationsCaller, req extension.RegulationEvidenceRequest) (extension.RegulationEvidence, error) {
|
|
p.seen = append(p.seen, c)
|
|
return extension.RegulationEvidence{CorpusRevision: req.CorpusRevision, NodeID: req.NodeID, Disclosure: extension.RegulationDisclosureFull, HashVerified: true}, nil
|
|
}
|
|
|
|
func (p *compatRegulationsPlugin) SearchWeb(_ context.Context, c extension.RegulationsCaller, req extension.WebSearchRequest) (extension.WebSearchResult, error) {
|
|
p.seen = append(p.seen, c)
|
|
return extension.WebSearchResult{Provider: "compat", SentQuery: req.Query, State: extension.WebSearchStateEmpty}, nil
|
|
}
|
|
|
|
func (p *compatRegulationsPlugin) CaptureWeb(_ context.Context, c extension.RegulationsCaller, req extension.WebCaptureRequest) (extension.WebCapture, error) {
|
|
p.seen = append(p.seen, c)
|
|
return extension.WebCapture{FinalURL: req.URL, State: extension.WebCaptureStateFailed, Reason: "offline"}, nil
|
|
}
|
|
|
|
// compatRegulationsConsumer is a second compiled plugin that reaches the
|
|
// provider only through the dispatch Host type assertion.
|
|
func compatRegulationsConsumer(reg extension.Registry) error {
|
|
return reg.AddCommandHandler(json.RawMessage(`{"id":"consumer.regs","title":"regs"}`),
|
|
func(ctx context.Context, h extension.Host, req extension.Request) (any, error) {
|
|
regs, ok := h.(extension.RegulationsHost)
|
|
if !ok {
|
|
return nil, errors.New("regulations host capability missing")
|
|
}
|
|
search, err := regs.SearchRegulations(ctx, extension.RegulationsSearchRequest{SchemaVersion: extension.RegulationsSchemaVersion, Query: "注册检验"})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
web, err := regs.SearchWeb(ctx, extension.WebSearchRequest{SchemaVersion: extension.RegulationsSchemaVersion, Query: "注册检验 指导原则"})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return map[string]any{"revision": search.CorpusRevision, "webState": web.State}, nil
|
|
})
|
|
}
|
|
|
|
func newRegulationsCompatApp(t *testing.T, plugins ...extension.InProc) (*cmdbus.Bus, *store.Store, hostcaps) {
|
|
t.Helper()
|
|
extension.ResetCompiled()
|
|
t.Cleanup(extension.ResetCompiled)
|
|
for _, p := range plugins {
|
|
extension.RegisterCompiled(p)
|
|
}
|
|
st, err := store.OpenSQLite(filepath.Join(t.TempDir(), "compat.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { st.Close() })
|
|
if err := st.EnsureUser("alice", ""); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
bus := cmdbus.New(st, nil, func() time.Time { return time.Unix(1700000000, 0).UTC() })
|
|
caps := hostcaps{st: st, regulations: ®ulationsSlot{}}
|
|
applyCompiled("", bus, caps)
|
|
return bus, st, caps
|
|
}
|
|
|
|
func TestRegulationsCompiledPluginCompatibility(t *testing.T) {
|
|
provider := &compatRegulationsPlugin{}
|
|
impostor := &compatRegulationsPlugin{}
|
|
bus, st, caps := newRegulationsCompatApp(t,
|
|
extension.InProc{ID: "impostor", Register: impostor.Register},
|
|
extension.InProc{ID: "kbreg", Register: provider.Register},
|
|
extension.InProc{ID: "consumer", Register: compatRegulationsConsumer},
|
|
)
|
|
if caps.regulations.get() != extension.RegulationsProvider(provider) {
|
|
t.Fatal("compiled kbreg provider was not the registered provider")
|
|
}
|
|
resp := bus.Dispatch(context.Background(), cmdbus.Request{ID: "consumer.regs", Owner: "alice", Actor: "alice", Entrance: "button"})
|
|
if resp.Receipt.State != agentcommand.StateCommitted {
|
|
t.Fatalf("dispatch = %+v", resp.Receipt)
|
|
}
|
|
payload, _ := resp.Payload.(map[string]any)
|
|
if payload["revision"] != "rev-compat" || payload["webState"] != extension.WebSearchStateEmpty {
|
|
t.Fatalf("payload = %+v", resp.Payload)
|
|
}
|
|
want := extension.RegulationsCaller{PluginID: "consumer", Actor: "alice", Owner: "alice"}
|
|
if len(provider.seen) != 2 || provider.seen[0] != want || provider.seen[1] != want || len(impostor.seen) != 0 {
|
|
t.Fatalf("provider callers = %+v impostor = %+v", provider.seen, impostor.seen)
|
|
}
|
|
evs, err := st.ListAuditEvents("alice", 20)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
actions := map[string]bool{}
|
|
for _, ev := range evs {
|
|
actions[ev.Action] = true
|
|
}
|
|
if !actions[auditRegulationsSearch] || !actions[auditWebSearch] {
|
|
t.Fatalf("host audit missing: %+v", evs)
|
|
}
|
|
}
|
|
|
|
func TestRegulationsCompiledConsumerWithoutProvider(t *testing.T) {
|
|
bus, _, _ := newRegulationsCompatApp(t, extension.InProc{ID: "consumer", Register: compatRegulationsConsumer})
|
|
resp := bus.Dispatch(context.Background(), cmdbus.Request{ID: "consumer.regs", Owner: "alice", Actor: "alice", Entrance: "button"})
|
|
if resp.Receipt.State == agentcommand.StateCommitted {
|
|
t.Fatalf("consumer succeeded without a regulations provider: %+v", resp.Payload)
|
|
}
|
|
}
|