Skip to content

Commit bb37448

Browse files
committed
tests(sdk): linearize tests and introduce timeouts to avoid blocking tests
1 parent 64d588a commit bb37448

1 file changed

Lines changed: 83 additions & 45 deletions

File tree

pkg/adaptation/plugin_test.go

Lines changed: 83 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package adaptation
22

33
import (
44
"context"
5+
"errors"
56
"net"
67
"os"
78
"path/filepath"
@@ -17,8 +18,9 @@ import (
1718
)
1819

1920
const (
20-
mockSecretValue = "mockSecretValue"
21-
mockSecretID = secrets.ID("mockSecretID")
21+
mockSecretValue = "mockSecretValue"
22+
mockSecretID = secrets.ID("mockSecretID")
23+
mockRuntimeTestTimeout = 10 * time.Second
2224
)
2325

2426
type mockedPlugin struct {
@@ -78,68 +80,70 @@ func Test_newExternalPlugin(t *testing.T) {
7880
{
7981
name: "create external plugin",
8082
test: func(t *testing.T, l net.Listener, conn net.Conn) {
81-
doneRuntime := make(chan struct{})
82-
go func() {
83-
p := mockExternalPluginRuntime(t, l)
84-
e, err := p.GetSecret(t.Context(), secrets.Request{ID: mockSecretID})
85-
assert.NoError(t, err)
86-
assert.Equal(t, mockSecretValue, string(e.Value))
87-
assert.NoError(t, p.close())
88-
close(doneRuntime)
89-
}()
83+
m := &mockExternalRuntime{l: l, done: make(chan struct{})}
84+
go m.run()
9085

9186
s, err := p.New(newMockedPlugin(), p.WithPluginName("my-plugin"), p.WithConnection(conn))
9287
require.NoError(t, err)
93-
assert.NoError(t, s.Run(context.Background()))
94-
<-doneRuntime
88+
runErr, cancel := runAsyncWithTimeout(t.Context(), s.Run)
89+
defer cancel()
90+
91+
runtime, err := m.getRuntime()
92+
assert.NoError(t, err)
93+
e, err := runtime.GetSecret(t.Context(), secrets.Request{ID: mockSecretID})
94+
assert.NoError(t, err)
95+
assert.Equal(t, mockSecretValue, string(e.Value))
96+
assert.NoError(t, runtime.close())
97+
98+
err = <-runErr
99+
assert.NoError(t, err)
95100
},
96101
},
97102
{
98103
name: "plugin returns error on GetSecret",
99104
test: func(t *testing.T, l net.Listener, conn net.Conn) {
100-
doneRuntime := make(chan struct{})
101-
go func() {
102-
p := mockExternalPluginRuntime(t, l)
103-
_, err := p.GetSecret(t.Context(), secrets.Request{ID: mockSecretID})
104-
assert.ErrorContains(t, err, "id mismatch")
105-
assert.NoError(t, p.close())
106-
close(doneRuntime)
107-
}()
105+
m := &mockExternalRuntime{l: l, done: make(chan struct{})}
106+
go m.run()
108107

109108
s, err := p.New(newMockedPlugin(WithID("rewrite-id")), p.WithPluginName("my-plugin"), p.WithConnection(conn))
110109
require.NoError(t, err)
111-
assert.NoError(t, s.Run(context.Background()))
112-
<-doneRuntime
110+
runErr, cancel := runAsyncWithTimeout(t.Context(), s.Run)
111+
defer cancel()
112+
113+
runtime, err := m.getRuntime()
114+
assert.NoError(t, err)
115+
_, err = runtime.GetSecret(t.Context(), secrets.Request{ID: mockSecretID})
116+
assert.ErrorContains(t, err, "id mismatch")
117+
assert.NoError(t, runtime.close())
118+
119+
err = <-runErr
120+
assert.NoError(t, err)
113121
},
114122
},
115123
{
116124
name: "cancelling plugin.run() shuts down the runtime",
117125
test: func(t *testing.T, l net.Listener, conn net.Conn) {
118-
doneRuntime := make(chan struct{})
119-
donePlugin := make(chan struct{})
120-
downRuntime := make(chan struct{})
121-
go func() {
122-
p := mockExternalPluginRuntime(t, l)
123-
e, err := p.GetSecret(t.Context(), secrets.Request{ID: mockSecretID})
124-
assert.NoError(t, err)
125-
assert.Equal(t, mockSecretValue, string(e.Value))
126-
close(doneRuntime)
127-
<-donePlugin
128-
assert.NoError(t, p.close())
129-
close(downRuntime)
130-
}()
126+
m := &mockExternalRuntime{l: l, done: make(chan struct{})}
127+
go m.run()
131128

132129
s, err := p.New(newMockedPlugin(), p.WithPluginName("my-plugin"), p.WithConnection(conn))
133130
require.NoError(t, err)
134131
ctx, cancel := context.WithCancel(t.Context())
135-
132+
done := make(chan struct{})
136133
go func() {
137134
assert.NoError(t, s.Run(ctx))
138-
close(donePlugin)
135+
close(done)
139136
}()
140-
<-doneRuntime
137+
138+
runtime, err := m.getRuntime()
139+
assert.NoError(t, err)
140+
e, err := runtime.GetSecret(t.Context(), secrets.Request{ID: mockSecretID})
141+
assert.NoError(t, err)
142+
assert.Equal(t, mockSecretValue, string(e.Value))
143+
141144
cancel()
142-
<-downRuntime
145+
<-done
146+
assert.NoError(t, runtime.close())
143147
},
144148
},
145149
{
@@ -179,18 +183,52 @@ func Test_newExternalPlugin(t *testing.T) {
179183
conn, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: socketPath, Net: "unix"})
180184
require.NoError(t, err)
181185
tt.test(t, l, conn)
186+
conn.Close()
187+
l.Close()
182188
})
183189
}
184190
}
185191

186-
func mockExternalPluginRuntime(t *testing.T, l net.Listener) *plugin {
187-
conn, err := l.Accept()
188-
require.NoError(t, err)
192+
func runAsyncWithTimeout(ctx context.Context, run func(ctx context.Context) error) (chan error, context.CancelFunc) {
193+
ctxWithTimeout, cancel := context.WithTimeout(ctx, mockRuntimeTestTimeout)
194+
runErr := make(chan error)
195+
go func() {
196+
runErr <- run(ctxWithTimeout)
197+
}()
198+
return runErr, cancel
199+
}
200+
201+
type mockExternalRuntime struct {
202+
l net.Listener
203+
p *plugin
204+
err error
205+
done chan struct{}
206+
}
189207

208+
func (m *mockExternalRuntime) run() {
209+
defer close(m.done)
210+
conn, err := m.l.Accept()
211+
if err != nil {
212+
m.err = err
213+
return
214+
}
190215
p, err := newExternalPlugin(conn, setupValidator{
191216
out: pluginCfgOut{engineName: "test-engine", engineVersion: "1.0.0", requestTimeout: 30 * time.Second},
192217
acceptPattern: func(secrets.Pattern) error { return nil },
193218
})
194-
require.NoError(t, err)
195-
return p
219+
if err != nil {
220+
m.err = err
221+
return
222+
}
223+
m.p = p
224+
}
225+
226+
func (m *mockExternalRuntime) getRuntime() (*plugin, error) {
227+
select {
228+
case <-m.done:
229+
return m.p, m.err
230+
case <-time.After(mockRuntimeTestTimeout):
231+
m.l.Close() // abort runtime
232+
return nil, errors.New("timeout")
233+
}
196234
}

0 commit comments

Comments
 (0)