返回 DeepSeek-Reasonix
installed_fixture_test.go
根目录 / internal / extension / conformance / installed_fixture_test.go
1 package conformance
2
3 import (
4 "context"
5 "os"
6 "path/filepath"
7 "runtime"
8 "testing"
9
10 "reasonix/internal/extension"
11 "reasonix/internal/extension/protocol"
12 "reasonix/internal/extension/sidecar"
13 "reasonix/internal/pluginpkg"
14 )
15
16 func copyFixtureFile(t *testing.T, src, dst string, mode os.FileMode) {
17 t.Helper()
18 data, err := os.ReadFile(src)
19 if err != nil {
20 t.Fatalf("read fixture %s: %v", src, err)
21 }
22 if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
23 t.Fatalf("create fixture directory: %v", err)
24 }
25 if err := os.WriteFile(dst, data, mode); err != nil {
26 t.Fatalf("write fixture %s: %v", dst, err)
27 }
28 }
29
30 // installExamplePackage assembles the built SDK example into the same layout
31 // as an installed plugin, persists enabled state, then reloads it exclusively
32 // through pluginpkg's v2 parser and installed-package inventory.
33 func installExamplePackage(t *testing.T) (string, pluginpkg.InstalledPackage) {
34 t.Helper()
35 home := t.TempDir()
36 root := pluginpkg.InstallRoot(home, testPluginID)
37 copyFixtureFile(t, filepath.Join(exampleRoot, pluginpkg.NativeManifest), filepath.Join(root, pluginpkg.NativeManifest), 0o644)
38 binaryName := "full-sidecar"
39 if runtime.GOOS == "windows" {
40 binaryName += ".exe"
41 }
42 copyFixtureFile(t, examplePath, filepath.Join(root, "bin", binaryName), 0o755)
43
44 pkg, warnings, err := pluginpkg.ParseDir(root)
45 if err != nil {
46 t.Fatalf("ParseDir(installed fullsidecar): %v", err)
47 }
48 if len(warnings) != 0 {
49 t.Fatalf("ParseDir warnings = %v", warnings)
50 }
51 installed := pluginpkg.InstalledPlugin{
52 Name: testPluginID,
53 Root: pluginpkg.RelativeRoot(home, root),
54 Version: pkg.Manifest.Version,
55 ManifestKind: pkg.ManifestKind,
56 Enabled: true,
57 }
58 if err := pluginpkg.Upsert(home, installed); err != nil {
59 t.Fatalf("Upsert installed fullsidecar: %v", err)
60 }
61 loaded, warnings := pluginpkg.LoadInstalled(home)
62 if len(warnings) != 0 {
63 t.Fatalf("LoadInstalled warnings = %v", warnings)
64 }
65 if len(loaded) != 1 {
66 t.Fatalf("LoadInstalled = %d packages, want 1", len(loaded))
67 }
68 return home, loaded[0]
69 }
70
71 func TestInstallableFixtureManifestCoversEveryRuntimeSurface(t *testing.T) {
72 _, item := installExamplePackage(t)
73 pkg := item.Package
74 if pkg.Manifest.APIVersion != pluginpkg.ManifestAPIVersionV2 {
75 t.Fatalf("apiVersion = %q, want %q", pkg.Manifest.APIVersion, pluginpkg.ManifestAPIVersionV2)
76 }
77 if pkg.Manifest.Name != testPluginID || pkg.Manifest.Version != "1.0.0" {
78 t.Fatalf("manifest identity = %q/%q", pkg.Manifest.Name, pkg.Manifest.Version)
79 }
80 rt := pkg.Manifest.Runtime
81 if rt == nil || rt.Command != "${REASONIX_PLUGIN_ROOT}/bin/full-sidecar" {
82 t.Fatalf("runtime = %+v", rt)
83 }
84 wantIntercepts := map[string]bool{"input.receive": true, "tool.before": true, "system_prompt.build": true, "session.start": true}
85 if len(rt.Intercepts) != len(wantIntercepts) {
86 t.Fatalf("runtime.intercepts = %v", rt.Intercepts)
87 }
88 for _, point := range rt.Intercepts {
89 if !wantIntercepts[point] {
90 t.Fatalf("unexpected runtime intercept %q", point)
91 }
92 }
93 wantCapabilities := map[string]bool{"interceptors": true, "strategies": true, "providers": true, "ui": true}
94 if len(rt.Capabilities) != len(wantCapabilities) {
95 t.Fatalf("runtime.capabilities = %v", rt.Capabilities)
96 }
97 for _, capability := range rt.Capabilities {
98 if !wantCapabilities[capability] {
99 t.Fatalf("unexpected runtime capability %q", capability)
100 }
101 }
102 if len(rt.Replaces) != 1 || rt.Replaces[0] != "system_prompt" {
103 t.Fatalf("runtime.replaces = %v", rt.Replaces)
104 }
105 wantProvides := map[string]string{
106 "plugin/full-sidecar/interceptors/default": "",
107 "plugin/full-sidecar/strategies/system_prompt": "",
108 "plugin/full-sidecar/provider/fake/echo": fixtureProviderSchemaHash,
109 "plugin/full-sidecar/uiaction/demo": fixtureUIActionSchemaHash,
110 }
111 if len(pkg.Manifest.Provides) != len(wantProvides) {
112 t.Fatalf("manifest provides = %+v", pkg.Manifest.Provides)
113 }
114 for _, provided := range pkg.Manifest.Provides {
115 key := provided.Namespace + "/" + provided.Kind + "/" + provided.ID
116 wantHash, ok := wantProvides[key]
117 if !ok || provided.SchemaHash != wantHash {
118 t.Fatalf("provided capability %q has schemaHash %q", key, provided.SchemaHash)
119 }
120 }
121 }
122
123 func TestInstallableFixtureEnableDisableRemoveAndKernelContributions(t *testing.T) {
124 home, _ := installExamplePackage(t)
125 if err := pluginpkg.SetEnabled(home, testPluginID, false); err != nil {
126 t.Fatalf("disable fixture: %v", err)
127 }
128 if packages, warnings := sidecar.LoadRuntimePackages(home); len(packages) != 0 || len(warnings) != 0 {
129 t.Fatalf("disabled fixture loaded packages=%d warnings=%v", len(packages), warnings)
130 }
131 if err := pluginpkg.SetEnabled(home, testPluginID, true); err != nil {
132 t.Fatalf("enable fixture: %v", err)
133 }
134 mgr, warnings, err := sidecar.StartPackages(context.Background(), home, protocol.SessionContext{
135 SessionID: "sess-installed", WorkspaceRoot: "/ws", Generation: 1,
136 }, nil)
137 if err != nil {
138 t.Fatalf("StartPackages: %v", err)
139 }
140 t.Cleanup(func() { _ = mgr.Close() })
141 if len(warnings) != 0 {
142 t.Fatalf("StartPackages warnings = %v", warnings)
143 }
144 want := map[string]bool{
145 string(extension.KindInterceptor) + ":input.receive": true,
146 string(extension.KindInterceptor) + ":tool.before": true,
147 string(extension.KindInterceptor) + ":system_prompt.build": true,
148 string(extension.KindInterceptor) + ":session.start": true,
149 string(extension.KindStrategy) + ":system_prompt": true,
150 string(extension.KindProvider) + ":fake/echo": true,
151 string(extension.KindUIAction) + ":demo": true,
152 }
153 contributions := mgr.Contributions()
154 if len(contributions) != len(want) {
155 t.Fatalf("contributions = %+v", contributions)
156 }
157 for _, contribution := range contributions {
158 key := string(contribution.Kind) + ":" + contribution.ID
159 if !want[key] {
160 t.Fatalf("unexpected contribution %q", key)
161 }
162 }
163 if _, ok, err := pluginpkg.Remove(home, testPluginID); err != nil || !ok {
164 t.Fatalf("remove fixture: ok=%v err=%v", ok, err)
165 }
166 if packages, warnings := sidecar.LoadRuntimePackages(home); len(packages) != 0 || len(warnings) != 0 {
167 t.Fatalf("removed fixture loaded packages=%d warnings=%v", len(packages), warnings)
168 }
169 }
170
170 lines GO