Skip to content

Commit 9efcd87

Browse files
authored
test(plugin): add comprehensive plugin package tests (#1056)
* test(plugin): add comprehensive plugin package tests Add tests for Load, FindAll and plugin Exec functionality. Includes test coverage for plugin loading, discovery and command execution. Signed-off-by: Ville Vesilehto <ville@vesilehto.fi> * fix: proper file paths for plugin tests CacheDirectory() will resolve to current working directory if pre-defined directory structure is missing. Signed-off-by: Ville Vesilehto <ville@vesilehto.fi> --------- Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
1 parent 5decd18 commit 9efcd87

File tree

2 files changed

+401
-1
lines changed

2 files changed

+401
-1
lines changed

plugin/install_test.go

Lines changed: 194 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
package plugin
22

3-
import "testing"
3+
import (
4+
"archive/tar"
5+
"bytes"
6+
"compress/gzip"
7+
"context"
8+
"fmt"
9+
"net/http"
10+
"net/http/httptest"
11+
"os"
12+
"path/filepath"
13+
"strings"
14+
"testing"
15+
)
416

517
func TestIsDirectory(t *testing.T) {
618
testCases := []struct {
@@ -29,3 +41,184 @@ func TestIsDirectory(t *testing.T) {
2941
}
3042
}
3143
}
44+
45+
func TestInstall(t *testing.T) {
46+
tests := []struct {
47+
name string
48+
setup func(t *testing.T) (source string, wantPluginName string)
49+
wantErr bool
50+
wantErrSubstring string
51+
}{
52+
{
53+
name: "install from directory",
54+
setup: func(t *testing.T) (string, string) {
55+
pluginDir := createInstallTestPlugin(t, "test-plugin")
56+
return pluginDir, "test-plugin"
57+
},
58+
wantErr: false,
59+
},
60+
{
61+
name: "install from valid URL",
62+
setup: func(t *testing.T) (string, string) {
63+
server := createTestArchiveServer(t, "test-plugin")
64+
return fmt.Sprintf("http::%s/plugin.tar.gz?archive=tar.gz", server.URL), "test-plugin"
65+
},
66+
wantErr: false,
67+
},
68+
{
69+
name: "install from invalid directory",
70+
setup: func(_ *testing.T) (string, string) {
71+
return "/nonexistent/directory", ""
72+
},
73+
wantErr: true,
74+
},
75+
{
76+
name: "install from URL with invalid plugin contents",
77+
setup: func(t *testing.T) (string, string) {
78+
server := createInvalidArchiveServer(t)
79+
return fmt.Sprintf("http::%s/invalid.tar.gz?archive=tar.gz", server.URL), ""
80+
},
81+
wantErr: true,
82+
wantErrSubstring: "loading plugin from dir",
83+
},
84+
}
85+
86+
for _, tt := range tests {
87+
t.Run(tt.name, func(t *testing.T) {
88+
tmpDir := t.TempDir()
89+
t.Setenv("XDG_DATA_HOME", tmpDir)
90+
91+
source, wantPluginName := tt.setup(t)
92+
err := Install(context.Background(), source)
93+
94+
assertError(t, tt.wantErr, tt.wantErrSubstring, err)
95+
assertInstallationResult(t, tmpDir, wantPluginName, tt.wantErr)
96+
})
97+
}
98+
}
99+
100+
// Helper functions
101+
func createInstallTestPlugin(t *testing.T, name string) string {
102+
t.Helper()
103+
104+
pluginDir := filepath.Join(t.TempDir(), name)
105+
if err := os.MkdirAll(pluginDir, 0755); err != nil {
106+
t.Fatal(err)
107+
}
108+
109+
configContent := []byte(fmt.Sprintf(`name: %s
110+
version: 1.0.0
111+
command: test-command`, name))
112+
if err := os.WriteFile(filepath.Join(pluginDir, "plugin.yaml"), configContent, 0o600); err != nil {
113+
t.Fatal(err)
114+
}
115+
116+
return pluginDir
117+
}
118+
119+
func createTestArchiveServer(t *testing.T, pluginName string) *httptest.Server {
120+
t.Helper()
121+
122+
var buf bytes.Buffer
123+
gw := gzip.NewWriter(&buf)
124+
tw := tar.NewWriter(gw)
125+
126+
configContent := []byte(fmt.Sprintf(`name: %s
127+
version: 1.0.0
128+
command: test-command`, pluginName))
129+
130+
header := &tar.Header{
131+
Name: "plugin.yaml",
132+
Mode: 0o600,
133+
Size: int64(len(configContent)),
134+
}
135+
if err := tw.WriteHeader(header); err != nil {
136+
t.Fatal(err)
137+
}
138+
if _, err := tw.Write(configContent); err != nil {
139+
t.Fatal(err)
140+
}
141+
142+
if err := tw.Close(); err != nil {
143+
t.Fatal(err)
144+
}
145+
if err := gw.Close(); err != nil {
146+
t.Fatal(err)
147+
}
148+
149+
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
150+
w.Header().Set("Content-Type", "application/x-gzip")
151+
_, _ = w.Write(buf.Bytes())
152+
}))
153+
}
154+
155+
func createInvalidArchiveServer(t *testing.T) *httptest.Server {
156+
t.Helper()
157+
158+
var buf bytes.Buffer
159+
gw := gzip.NewWriter(&buf)
160+
tw := tar.NewWriter(gw)
161+
162+
header := &tar.Header{
163+
Name: "dummy.txt",
164+
Mode: 0o600,
165+
Size: 0,
166+
}
167+
if err := tw.WriteHeader(header); err != nil {
168+
t.Fatal(err)
169+
}
170+
if err := tw.Close(); err != nil {
171+
t.Fatal(err)
172+
}
173+
if err := gw.Close(); err != nil {
174+
t.Fatal(err)
175+
}
176+
177+
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
178+
w.Header().Set("Content-Type", "application/x-gzip")
179+
_, _ = w.Write(buf.Bytes())
180+
}))
181+
}
182+
183+
func assertError(t *testing.T, wantErr bool, wantMsg string, actual error) {
184+
t.Helper()
185+
186+
if wantErr {
187+
if actual == nil {
188+
t.Fatal("expected error but got none")
189+
}
190+
if wantMsg != "" && !strings.Contains(actual.Error(), wantMsg) {
191+
t.Errorf("error %q should contain %q", actual.Error(), wantMsg)
192+
}
193+
} else if actual != nil {
194+
t.Fatalf("unexpected error: %v", actual)
195+
}
196+
}
197+
198+
func assertInstallationResult(t *testing.T, tmpDir, wantPluginName string, wantErr bool) {
199+
t.Helper()
200+
201+
if wantErr {
202+
assertTempFilesCleaned(t, tmpDir)
203+
return
204+
}
205+
206+
pluginDir := filepath.Join(tmpDir, ".conftest", "plugins", wantPluginName)
207+
if _, err := os.Stat(pluginDir); os.IsNotExist(err) {
208+
t.Errorf("plugin directory %q not found", pluginDir)
209+
}
210+
211+
configPath := filepath.Join(pluginDir, "plugin.yaml")
212+
if _, err := os.Stat(configPath); os.IsNotExist(err) {
213+
t.Error("plugin.yaml not found in plugin directory")
214+
}
215+
}
216+
217+
func assertTempFilesCleaned(t *testing.T, tmpDir string) {
218+
t.Helper()
219+
220+
matches, _ := filepath.Glob(filepath.Join(tmpDir, ".conftest", "plugins", "conftest-plugin-*"))
221+
if len(matches) > 0 {
222+
t.Errorf("temporary directories not cleaned up: %v", matches)
223+
}
224+
}

0 commit comments

Comments
 (0)