feat: implement mock service instances for non-WASM builds using testify/mock

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan 2025-12-31 19:34:14 -05:00
parent 6b0ea10f4e
commit e111c5832f
14 changed files with 623 additions and 100 deletions

View File

@ -96,7 +96,7 @@ Generated files are named `nd_host_<servicename>.go` (lowercase) and placed in `
The generator creates:
- `nd_host_<servicename>.go` - Client wrapper code (WASM build)
- `nd_host_<servicename>_stub.go` - Stub code for non-WASM platforms
- `nd_host_<servicename>_stub.go` - Mock implementations for non-WASM platforms (testing)
- `doc.go` - Package documentation listing all available services
- `go.mod` - Go module file with required dependencies
@ -108,6 +108,48 @@ Each service file includes:
- Response struct types and any struct definitions from the service
- Wrapper functions that handle memory allocation and JSON parsing
### Testing Plugins with Mocks
The stub files (`*_stub.go`) contain [testify/mock](https://github.com/stretchr/testify) implementations that allow plugin authors to unit test their code on non-WASM platforms.
Each host service has:
- A private mock struct embedding `mock.Mock`
- An exported auto-instantiated mock instance (e.g., `host.CacheMock`, `host.ArtworkMock`)
- Wrapper functions that delegate to the mock
**Example: Testing a plugin that uses the Cache service**
```go
package myplugin
import (
"testing"
"github.com/navidrome/navidrome/plugins/pdk/go/host"
)
func TestMyPluginFunction(t *testing.T) {
// Set expectations on the mock
host.CacheMock.On("GetString", "my-key").Return("cached-value", true, nil)
host.CacheMock.On("SetString", "new-key", "new-value", int64(3600)).Return(nil)
// Call your plugin code that uses host.CacheGetString and host.CacheSetString
result := myPluginFunction()
// Assert the result
if result != "expected" {
t.Errorf("unexpected result: %s", result)
}
// Verify all expected calls were made
host.CacheMock.AssertExpectations(t)
}
```
**Resetting mocks between tests:**
If you need to reset mock state between tests, testify's mock doesn't have a built-in reset. Either use separate test functions (testify automatically resets between test runs), or create a helper to set up fresh expectations.
### Python Client Library
When using `-python`, Python client files are generated in a `python/` subdirectory.

View File

@ -26,12 +26,56 @@ func hostFuncMap(svc Service) template.FuncMap {
// Uses private (lowercase) type names for request/response structs.
func clientFuncMap(svc Service) template.FuncMap {
return template.FuncMap{
"lower": strings.ToLower,
"title": strings.Title,
"exportName": func(m Method) string { return m.FunctionName(svc.ExportPrefix()) },
"requestType": func(m Method) string { return m.ClientRequestTypeName(svc.Name) },
"responseType": func(m Method) string { return m.ClientResponseTypeName(svc.Name) },
"formatDoc": formatDoc,
"lower": strings.ToLower,
"title": strings.Title,
"exportName": func(m Method) string { return m.FunctionName(svc.ExportPrefix()) },
"requestType": func(m Method) string { return m.ClientRequestTypeName(svc.Name) },
"responseType": func(m Method) string { return m.ClientResponseTypeName(svc.Name) },
"formatDoc": formatDoc,
"mockReturnValues": mockReturnValues,
}
}
// mockReturnValues generates the testify mock return value accessors for a method.
// For example: args.String(0), args.Bool(1), args.Error(2)
func mockReturnValues(m Method) string {
var parts []string
idx := 0
for _, r := range m.Returns {
parts = append(parts, mockAccessor(r.Type, idx))
idx++
}
if m.HasError {
parts = append(parts, fmt.Sprintf("args.Error(%d)", idx))
}
return strings.Join(parts, ", ")
}
// mockAccessor returns the testify mock accessor call for a given type and index.
func mockAccessor(typ string, idx int) string {
switch {
case typ == "string":
return fmt.Sprintf("args.String(%d)", idx)
case typ == "bool":
return fmt.Sprintf("args.Bool(%d)", idx)
case typ == "int":
return fmt.Sprintf("args.Int(%d)", idx)
case typ == "int64":
return fmt.Sprintf("args.Get(%d).(int64)", idx)
case typ == "int32":
return fmt.Sprintf("args.Get(%d).(int32)", idx)
case typ == "float64":
return fmt.Sprintf("args.Get(%d).(float64)", idx)
case typ == "float32":
return fmt.Sprintf("args.Get(%d).(float32)", idx)
case typ == "[]byte":
return fmt.Sprintf("args.Get(%d).([]byte)", idx)
default:
// For slices, maps, pointers, and custom types, use Get with type assertion
return fmt.Sprintf("args.Get(%d).(%s)", idx, typ)
}
}

View File

@ -587,7 +587,7 @@ var _ = Describe("Generator", func() {
})
Describe("GenerateClientGoStub", func() {
It("should generate valid stub code with panic functions", func() {
It("should generate valid mock code with testify/mock", func() {
svc := Service{
Name: "Cache",
Permission: "cache",
@ -623,16 +623,96 @@ var _ = Describe("Generator", func() {
// Check for package declaration
Expect(codeStr).To(ContainSubstring("package ndpdk"))
// Check for stub comment
Expect(codeStr).To(ContainSubstring("stub implementations for non-WASM builds"))
// Check for mock comment
Expect(codeStr).To(ContainSubstring("mock implementations for non-WASM builds"))
// Check for panic in function body
Expect(codeStr).To(ContainSubstring(`panic("ndpdk: CacheGet is only available in WASM plugins")`))
// Check for testify/mock import
Expect(codeStr).To(ContainSubstring(`"github.com/stretchr/testify/mock"`))
// Check for private mock struct
Expect(codeStr).To(ContainSubstring("type mockCacheService struct"))
Expect(codeStr).To(ContainSubstring("mock.Mock"))
// Check for exported mock instance
Expect(codeStr).To(ContainSubstring("var CacheMock = &mockCacheService{}"))
// Check for mock method
Expect(codeStr).To(ContainSubstring("func (m *mockCacheService) Get(key string)"))
Expect(codeStr).To(ContainSubstring("m.Called(key)"))
// Check for wrapper function delegating to mock
Expect(codeStr).To(ContainSubstring("func CacheGet(key string)"))
Expect(codeStr).To(ContainSubstring("return CacheMock.Get(key)"))
// Stub files should NOT have request/response types (they're not needed)
Expect(codeStr).NotTo(ContainSubstring("Request struct"))
Expect(codeStr).NotTo(ContainSubstring("Response struct"))
})
It("should generate correct mock return values for different types", func() {
svc := Service{
Name: "Test",
Permission: "test",
Interface: "TestService",
Methods: []Method{
{
Name: "GetString",
Params: []Param{
{Name: "key", Type: "string"},
},
Returns: []Param{
{Name: "value", Type: "string"},
},
HasError: true,
},
{
Name: "GetInt64",
Params: []Param{
{Name: "key", Type: "string"},
},
Returns: []Param{
{Name: "value", Type: "int64"},
{Name: "exists", Type: "bool"},
},
HasError: true,
},
{
Name: "GetBytes",
Params: []Param{
{Name: "key", Type: "string"},
},
Returns: []Param{
{Name: "value", Type: "[]byte"},
},
HasError: true,
},
},
}
code, err := GenerateClientGoStub(svc, "ndpdk")
Expect(err).NotTo(HaveOccurred())
// Verify it's valid Go code
_, err = format.Source(code)
Expect(err).NotTo(HaveOccurred())
codeStr := string(code)
// Check string return uses args.String(0)
Expect(codeStr).To(ContainSubstring("args.String(0)"))
// Check int64 return uses args.Get(0).(int64)
Expect(codeStr).To(ContainSubstring("args.Get(0).(int64)"))
// Check bool return uses args.Bool(1)
Expect(codeStr).To(ContainSubstring("args.Bool(1)"))
// Check []byte return uses args.Get(0).([]byte)
Expect(codeStr).To(ContainSubstring("args.Get(0).([]byte)"))
// Check error returns use args.Error(N)
Expect(codeStr).To(ContainSubstring("args.Error("))
})
})
Describe("Integration", func() {

View File

@ -1,13 +1,15 @@
// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains stub implementations for non-WASM builds.
// These stubs allow IDE support and compilation on non-WASM platforms.
// They panic at runtime since host functions are only available in WASM plugins.
// This file contains mock implementations for non-WASM builds.
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
// Plugin authors can use the exported mock instances to set expectations in tests.
//
//go:build !wasip1
package {{.Package}}
import "github.com/stretchr/testify/mock"
{{- /* Generate struct definitions (same as main file, needed for type references in function signatures) */ -}}
{{- range .Service.Structs}}
@ -22,14 +24,27 @@ type {{.Name}} struct {
}
{{- end}}
{{- /* Generate stub wrapper functions that panic */ -}}
// mock{{.Service.Name}}Service is the mock implementation for testing.
type mock{{.Service.Name}}Service struct {
mock.Mock
}
// {{.Service.Name}}Mock is the auto-instantiated mock instance for testing.
// Use this to set expectations: host.{{.Service.Name}}Mock.On("MethodName", args...).Return(values...)
var {{.Service.Name}}Mock = &mock{{.Service.Name}}Service{}
{{range .Service.Methods}}
// {{$.Service.Name}}{{.Name}} is a stub that panics on non-WASM platforms.
// {{.Name}} is the mock method for {{$.Service.Name}}{{.Name}}.
func (m *mock{{$.Service.Name}}Service) {{.Name}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.Name}} {{$p.Type}}{{end}}) {{.ReturnSignature}} {
args := m.Called({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.Name}}{{end}})
return {{mockReturnValues .}}
}
// {{$.Service.Name}}{{.Name}} delegates to the mock instance.
{{- if .Doc}}
{{formatDoc .Doc}}
{{- end}}
func {{$.Service.Name}}{{.Name}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.Name}} {{$p.Type}}{{end}}) {{.ReturnSignature}} {
panic("{{$.Package}}: {{$.Service.Name}}{{.Name}} is only available in WASM plugins")
return {{$.Service.Name}}Mock.{{.Name}}({{range $i, $p := .Params}}{{if $i}}, {{end}}{{$p.Name}}{{end}})
}
{{- end}}

View File

@ -249,3 +249,66 @@ Or use the provided Makefile targets in plugin examples:
```bash
make plugin.wasm
```
## Testing Plugins
The PDK includes [testify/mock](https://github.com/stretchr/testify) implementations for all host services,
allowing you to unit test your plugin code on non-WASM platforms (your development machine).
### Mock Instances
Each host service has an auto-instantiated mock instance:
| Service | Mock Instance |
|---------------|--------------------------|
| `Artwork` | `host.ArtworkMock` |
| `Cache` | `host.CacheMock` |
| `Config` | `host.ConfigMock` |
| `KVStore` | `host.KVStoreMock` |
| `Library` | `host.LibraryMock` |
| `Scheduler` | `host.SchedulerMock` |
| `SubsonicAPI` | `host.SubsonicAPIMock` |
| `WebSocket` | `host.WebSocketMock` |
### Example Test
```go
package myplugin
import (
"testing"
"github.com/navidrome/navidrome/plugins/pdk/go/host"
)
func TestMyPluginFunction(t *testing.T) {
// Set expectations on the mock
host.CacheMock.On("GetString", "my-key").Return("cached-value", true, nil)
host.CacheMock.On("SetString", "new-key", "new-value", int64(3600)).Return(nil)
// Call your plugin code that uses host.CacheGetString / host.CacheSetString
result, err := myPluginFunction()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Assert the result
if result != "expected" {
t.Errorf("unexpected result: %s", result)
}
// Verify all expected calls were made
host.CacheMock.AssertExpectations(t)
}
```
### Running Tests
Since tests run on your development machine (not WASM), use standard Go testing:
```bash
go test ./...
```
The stub files with mocks are only compiled for non-WASM builds (`//go:build !wasip1`),
so they won't affect your production WASM binary.

View File

@ -2,4 +2,14 @@ module github.com/navidrome/navidrome/plugins/pdk/go
go 1.25
require github.com/extism/go-pdk v1.1.3
require (
github.com/extism/go-pdk v1.1.3
github.com/stretchr/testify v1.11.1
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@ -1,2 +1,14 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/extism/go-pdk v1.1.3 h1:hfViMPWrqjN6u67cIYRALZTZLk/enSPpNKa+rZ9X2SQ=
github.com/extism/go-pdk v1.1.3/go.mod h1:Gz+LIU/YCKnKXhgge8yo5Yu1F/lbv7KtKFkiCSzW/P4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,14 +1,31 @@
// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains stub implementations for non-WASM builds.
// These stubs allow IDE support and compilation on non-WASM platforms.
// They panic at runtime since host functions are only available in WASM plugins.
// This file contains mock implementations for non-WASM builds.
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
// Plugin authors can use the exported mock instances to set expectations in tests.
//
//go:build !wasip1
package host
// ArtworkGetArtistUrl is a stub that panics on non-WASM platforms.
import "github.com/stretchr/testify/mock"
// mockArtworkService is the mock implementation for testing.
type mockArtworkService struct {
mock.Mock
}
// ArtworkMock is the auto-instantiated mock instance for testing.
// Use this to set expectations: host.ArtworkMock.On("MethodName", args...).Return(values...)
var ArtworkMock = &mockArtworkService{}
// GetArtistUrl is the mock method for ArtworkGetArtistUrl.
func (m *mockArtworkService) GetArtistUrl(id string, size int32) (string, error) {
args := m.Called(id, size)
return args.String(0), args.Error(1)
}
// ArtworkGetArtistUrl delegates to the mock instance.
// GetArtistUrl generates a public URL for an artist's artwork.
//
// Parameters:
@ -17,10 +34,16 @@ package host
//
// Returns the public URL for the artwork, or an error if generation fails.
func ArtworkGetArtistUrl(id string, size int32) (string, error) {
panic("host: ArtworkGetArtistUrl is only available in WASM plugins")
return ArtworkMock.GetArtistUrl(id, size)
}
// ArtworkGetAlbumUrl is a stub that panics on non-WASM platforms.
// GetAlbumUrl is the mock method for ArtworkGetAlbumUrl.
func (m *mockArtworkService) GetAlbumUrl(id string, size int32) (string, error) {
args := m.Called(id, size)
return args.String(0), args.Error(1)
}
// ArtworkGetAlbumUrl delegates to the mock instance.
// GetAlbumUrl generates a public URL for an album's artwork.
//
// Parameters:
@ -29,10 +52,16 @@ func ArtworkGetArtistUrl(id string, size int32) (string, error) {
//
// Returns the public URL for the artwork, or an error if generation fails.
func ArtworkGetAlbumUrl(id string, size int32) (string, error) {
panic("host: ArtworkGetAlbumUrl is only available in WASM plugins")
return ArtworkMock.GetAlbumUrl(id, size)
}
// ArtworkGetTrackUrl is a stub that panics on non-WASM platforms.
// GetTrackUrl is the mock method for ArtworkGetTrackUrl.
func (m *mockArtworkService) GetTrackUrl(id string, size int32) (string, error) {
args := m.Called(id, size)
return args.String(0), args.Error(1)
}
// ArtworkGetTrackUrl delegates to the mock instance.
// GetTrackUrl generates a public URL for a track's artwork.
//
// Parameters:
@ -41,10 +70,16 @@ func ArtworkGetAlbumUrl(id string, size int32) (string, error) {
//
// Returns the public URL for the artwork, or an error if generation fails.
func ArtworkGetTrackUrl(id string, size int32) (string, error) {
panic("host: ArtworkGetTrackUrl is only available in WASM plugins")
return ArtworkMock.GetTrackUrl(id, size)
}
// ArtworkGetPlaylistUrl is a stub that panics on non-WASM platforms.
// GetPlaylistUrl is the mock method for ArtworkGetPlaylistUrl.
func (m *mockArtworkService) GetPlaylistUrl(id string, size int32) (string, error) {
args := m.Called(id, size)
return args.String(0), args.Error(1)
}
// ArtworkGetPlaylistUrl delegates to the mock instance.
// GetPlaylistUrl generates a public URL for a playlist's artwork.
//
// Parameters:
@ -53,5 +88,5 @@ func ArtworkGetTrackUrl(id string, size int32) (string, error) {
//
// Returns the public URL for the artwork, or an error if generation fails.
func ArtworkGetPlaylistUrl(id string, size int32) (string, error) {
panic("host: ArtworkGetPlaylistUrl is only available in WASM plugins")
return ArtworkMock.GetPlaylistUrl(id, size)
}

View File

@ -1,14 +1,31 @@
// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains stub implementations for non-WASM builds.
// These stubs allow IDE support and compilation on non-WASM platforms.
// They panic at runtime since host functions are only available in WASM plugins.
// This file contains mock implementations for non-WASM builds.
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
// Plugin authors can use the exported mock instances to set expectations in tests.
//
//go:build !wasip1
package host
// CacheSetString is a stub that panics on non-WASM platforms.
import "github.com/stretchr/testify/mock"
// mockCacheService is the mock implementation for testing.
type mockCacheService struct {
mock.Mock
}
// CacheMock is the auto-instantiated mock instance for testing.
// Use this to set expectations: host.CacheMock.On("MethodName", args...).Return(values...)
var CacheMock = &mockCacheService{}
// SetString is the mock method for CacheSetString.
func (m *mockCacheService) SetString(key string, value string, ttlSeconds int64) error {
args := m.Called(key, value, ttlSeconds)
return args.Error(0)
}
// CacheSetString delegates to the mock instance.
// SetString stores a string value in the cache.
//
// Parameters:
@ -18,10 +35,16 @@ package host
//
// Returns an error if the operation fails.
func CacheSetString(key string, value string, ttlSeconds int64) error {
panic("host: CacheSetString is only available in WASM plugins")
return CacheMock.SetString(key, value, ttlSeconds)
}
// CacheGetString is a stub that panics on non-WASM platforms.
// GetString is the mock method for CacheGetString.
func (m *mockCacheService) GetString(key string) (string, bool, error) {
args := m.Called(key)
return args.String(0), args.Bool(1), args.Error(2)
}
// CacheGetString delegates to the mock instance.
// GetString retrieves a string value from the cache.
//
// Parameters:
@ -30,10 +53,16 @@ func CacheSetString(key string, value string, ttlSeconds int64) error {
// Returns the value and whether the key exists. If the key doesn't exist
// or the stored value is not a string, exists will be false.
func CacheGetString(key string) (string, bool, error) {
panic("host: CacheGetString is only available in WASM plugins")
return CacheMock.GetString(key)
}
// CacheSetInt is a stub that panics on non-WASM platforms.
// SetInt is the mock method for CacheSetInt.
func (m *mockCacheService) SetInt(key string, value int64, ttlSeconds int64) error {
args := m.Called(key, value, ttlSeconds)
return args.Error(0)
}
// CacheSetInt delegates to the mock instance.
// SetInt stores an integer value in the cache.
//
// Parameters:
@ -43,10 +72,16 @@ func CacheGetString(key string) (string, bool, error) {
//
// Returns an error if the operation fails.
func CacheSetInt(key string, value int64, ttlSeconds int64) error {
panic("host: CacheSetInt is only available in WASM plugins")
return CacheMock.SetInt(key, value, ttlSeconds)
}
// CacheGetInt is a stub that panics on non-WASM platforms.
// GetInt is the mock method for CacheGetInt.
func (m *mockCacheService) GetInt(key string) (int64, bool, error) {
args := m.Called(key)
return args.Get(0).(int64), args.Bool(1), args.Error(2)
}
// CacheGetInt delegates to the mock instance.
// GetInt retrieves an integer value from the cache.
//
// Parameters:
@ -55,10 +90,16 @@ func CacheSetInt(key string, value int64, ttlSeconds int64) error {
// Returns the value and whether the key exists. If the key doesn't exist
// or the stored value is not an integer, exists will be false.
func CacheGetInt(key string) (int64, bool, error) {
panic("host: CacheGetInt is only available in WASM plugins")
return CacheMock.GetInt(key)
}
// CacheSetFloat is a stub that panics on non-WASM platforms.
// SetFloat is the mock method for CacheSetFloat.
func (m *mockCacheService) SetFloat(key string, value float64, ttlSeconds int64) error {
args := m.Called(key, value, ttlSeconds)
return args.Error(0)
}
// CacheSetFloat delegates to the mock instance.
// SetFloat stores a float value in the cache.
//
// Parameters:
@ -68,10 +109,16 @@ func CacheGetInt(key string) (int64, bool, error) {
//
// Returns an error if the operation fails.
func CacheSetFloat(key string, value float64, ttlSeconds int64) error {
panic("host: CacheSetFloat is only available in WASM plugins")
return CacheMock.SetFloat(key, value, ttlSeconds)
}
// CacheGetFloat is a stub that panics on non-WASM platforms.
// GetFloat is the mock method for CacheGetFloat.
func (m *mockCacheService) GetFloat(key string) (float64, bool, error) {
args := m.Called(key)
return args.Get(0).(float64), args.Bool(1), args.Error(2)
}
// CacheGetFloat delegates to the mock instance.
// GetFloat retrieves a float value from the cache.
//
// Parameters:
@ -80,10 +127,16 @@ func CacheSetFloat(key string, value float64, ttlSeconds int64) error {
// Returns the value and whether the key exists. If the key doesn't exist
// or the stored value is not a float, exists will be false.
func CacheGetFloat(key string) (float64, bool, error) {
panic("host: CacheGetFloat is only available in WASM plugins")
return CacheMock.GetFloat(key)
}
// CacheSetBytes is a stub that panics on non-WASM platforms.
// SetBytes is the mock method for CacheSetBytes.
func (m *mockCacheService) SetBytes(key string, value []byte, ttlSeconds int64) error {
args := m.Called(key, value, ttlSeconds)
return args.Error(0)
}
// CacheSetBytes delegates to the mock instance.
// SetBytes stores a byte slice in the cache.
//
// Parameters:
@ -93,10 +146,16 @@ func CacheGetFloat(key string) (float64, bool, error) {
//
// Returns an error if the operation fails.
func CacheSetBytes(key string, value []byte, ttlSeconds int64) error {
panic("host: CacheSetBytes is only available in WASM plugins")
return CacheMock.SetBytes(key, value, ttlSeconds)
}
// CacheGetBytes is a stub that panics on non-WASM platforms.
// GetBytes is the mock method for CacheGetBytes.
func (m *mockCacheService) GetBytes(key string) ([]byte, bool, error) {
args := m.Called(key)
return args.Get(0).([]byte), args.Bool(1), args.Error(2)
}
// CacheGetBytes delegates to the mock instance.
// GetBytes retrieves a byte slice from the cache.
//
// Parameters:
@ -105,10 +164,16 @@ func CacheSetBytes(key string, value []byte, ttlSeconds int64) error {
// Returns the value and whether the key exists. If the key doesn't exist
// or the stored value is not a byte slice, exists will be false.
func CacheGetBytes(key string) ([]byte, bool, error) {
panic("host: CacheGetBytes is only available in WASM plugins")
return CacheMock.GetBytes(key)
}
// CacheHas is a stub that panics on non-WASM platforms.
// Has is the mock method for CacheHas.
func (m *mockCacheService) Has(key string) (bool, error) {
args := m.Called(key)
return args.Bool(0), args.Error(1)
}
// CacheHas delegates to the mock instance.
// Has checks if a key exists in the cache.
//
// Parameters:
@ -116,10 +181,16 @@ func CacheGetBytes(key string) ([]byte, bool, error) {
//
// Returns true if the key exists and has not expired.
func CacheHas(key string) (bool, error) {
panic("host: CacheHas is only available in WASM plugins")
return CacheMock.Has(key)
}
// CacheRemove is a stub that panics on non-WASM platforms.
// Remove is the mock method for CacheRemove.
func (m *mockCacheService) Remove(key string) error {
args := m.Called(key)
return args.Error(0)
}
// CacheRemove delegates to the mock instance.
// Remove deletes a value from the cache.
//
// Parameters:
@ -127,5 +198,5 @@ func CacheHas(key string) (bool, error) {
//
// Returns an error if the operation fails. Does not return an error if the key doesn't exist.
func CacheRemove(key string) error {
panic("host: CacheRemove is only available in WASM plugins")
return CacheMock.Remove(key)
}

View File

@ -1,14 +1,31 @@
// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains stub implementations for non-WASM builds.
// These stubs allow IDE support and compilation on non-WASM platforms.
// They panic at runtime since host functions are only available in WASM plugins.
// This file contains mock implementations for non-WASM builds.
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
// Plugin authors can use the exported mock instances to set expectations in tests.
//
//go:build !wasip1
package host
// KVStoreSet is a stub that panics on non-WASM platforms.
import "github.com/stretchr/testify/mock"
// mockKVStoreService is the mock implementation for testing.
type mockKVStoreService struct {
mock.Mock
}
// KVStoreMock is the auto-instantiated mock instance for testing.
// Use this to set expectations: host.KVStoreMock.On("MethodName", args...).Return(values...)
var KVStoreMock = &mockKVStoreService{}
// Set is the mock method for KVStoreSet.
func (m *mockKVStoreService) Set(key string, value []byte) error {
args := m.Called(key, value)
return args.Error(0)
}
// KVStoreSet delegates to the mock instance.
// Set stores a byte value with the given key.
//
// Parameters:
@ -17,10 +34,16 @@ package host
//
// Returns an error if the storage limit would be exceeded or the operation fails.
func KVStoreSet(key string, value []byte) error {
panic("host: KVStoreSet is only available in WASM plugins")
return KVStoreMock.Set(key, value)
}
// KVStoreGet is a stub that panics on non-WASM platforms.
// Get is the mock method for KVStoreGet.
func (m *mockKVStoreService) Get(key string) ([]byte, bool, error) {
args := m.Called(key)
return args.Get(0).([]byte), args.Bool(1), args.Error(2)
}
// KVStoreGet delegates to the mock instance.
// Get retrieves a byte value from storage.
//
// Parameters:
@ -28,10 +51,16 @@ func KVStoreSet(key string, value []byte) error {
//
// Returns the value and whether the key exists.
func KVStoreGet(key string) ([]byte, bool, error) {
panic("host: KVStoreGet is only available in WASM plugins")
return KVStoreMock.Get(key)
}
// KVStoreDelete is a stub that panics on non-WASM platforms.
// Delete is the mock method for KVStoreDelete.
func (m *mockKVStoreService) Delete(key string) error {
args := m.Called(key)
return args.Error(0)
}
// KVStoreDelete delegates to the mock instance.
// Delete removes a value from storage.
//
// Parameters:
@ -39,10 +68,16 @@ func KVStoreGet(key string) ([]byte, bool, error) {
//
// Returns an error if the operation fails. Does not return an error if the key doesn't exist.
func KVStoreDelete(key string) error {
panic("host: KVStoreDelete is only available in WASM plugins")
return KVStoreMock.Delete(key)
}
// KVStoreHas is a stub that panics on non-WASM platforms.
// Has is the mock method for KVStoreHas.
func (m *mockKVStoreService) Has(key string) (bool, error) {
args := m.Called(key)
return args.Bool(0), args.Error(1)
}
// KVStoreHas delegates to the mock instance.
// Has checks if a key exists in storage.
//
// Parameters:
@ -50,10 +85,16 @@ func KVStoreDelete(key string) error {
//
// Returns true if the key exists.
func KVStoreHas(key string) (bool, error) {
panic("host: KVStoreHas is only available in WASM plugins")
return KVStoreMock.Has(key)
}
// KVStoreList is a stub that panics on non-WASM platforms.
// List is the mock method for KVStoreList.
func (m *mockKVStoreService) List(prefix string) ([]string, error) {
args := m.Called(prefix)
return args.Get(0).([]string), args.Error(1)
}
// KVStoreList delegates to the mock instance.
// List returns all keys matching the given prefix.
//
// Parameters:
@ -61,11 +102,17 @@ func KVStoreHas(key string) (bool, error) {
//
// Returns a slice of matching keys.
func KVStoreList(prefix string) ([]string, error) {
panic("host: KVStoreList is only available in WASM plugins")
return KVStoreMock.List(prefix)
}
// KVStoreGetStorageUsed is a stub that panics on non-WASM platforms.
// GetStorageUsed is the mock method for KVStoreGetStorageUsed.
func (m *mockKVStoreService) GetStorageUsed() (int64, error) {
args := m.Called()
return args.Get(0).(int64), args.Error(1)
}
// KVStoreGetStorageUsed delegates to the mock instance.
// GetStorageUsed returns the total storage used by this plugin in bytes.
func KVStoreGetStorageUsed() (int64, error) {
panic("host: KVStoreGetStorageUsed is only available in WASM plugins")
return KVStoreMock.GetStorageUsed()
}

View File

@ -1,13 +1,15 @@
// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains stub implementations for non-WASM builds.
// These stubs allow IDE support and compilation on non-WASM platforms.
// They panic at runtime since host functions are only available in WASM plugins.
// This file contains mock implementations for non-WASM builds.
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
// Plugin authors can use the exported mock instances to set expectations in tests.
//
//go:build !wasip1
package host
import "github.com/stretchr/testify/mock"
// Library represents the Library data structure.
// Library represents a music library with metadata.
type Library struct {
@ -23,7 +25,22 @@ type Library struct {
TotalDuration float64 `json:"totalDuration"`
}
// LibraryGetLibrary is a stub that panics on non-WASM platforms.
// mockLibraryService is the mock implementation for testing.
type mockLibraryService struct {
mock.Mock
}
// LibraryMock is the auto-instantiated mock instance for testing.
// Use this to set expectations: host.LibraryMock.On("MethodName", args...).Return(values...)
var LibraryMock = &mockLibraryService{}
// GetLibrary is the mock method for LibraryGetLibrary.
func (m *mockLibraryService) GetLibrary(id int32) (*Library, error) {
args := m.Called(id)
return args.Get(0).(*Library), args.Error(1)
}
// LibraryGetLibrary delegates to the mock instance.
// GetLibrary retrieves metadata for a specific library by ID.
//
// Parameters:
@ -31,13 +48,19 @@ type Library struct {
//
// Returns the library metadata, or an error if the library is not found.
func LibraryGetLibrary(id int32) (*Library, error) {
panic("host: LibraryGetLibrary is only available in WASM plugins")
return LibraryMock.GetLibrary(id)
}
// LibraryGetAllLibraries is a stub that panics on non-WASM platforms.
// GetAllLibraries is the mock method for LibraryGetAllLibraries.
func (m *mockLibraryService) GetAllLibraries() ([]Library, error) {
args := m.Called()
return args.Get(0).([]Library), args.Error(1)
}
// LibraryGetAllLibraries delegates to the mock instance.
// GetAllLibraries retrieves metadata for all configured libraries.
//
// Returns a slice of all libraries with their metadata.
func LibraryGetAllLibraries() ([]Library, error) {
panic("host: LibraryGetAllLibraries is only available in WASM plugins")
return LibraryMock.GetAllLibraries()
}

View File

@ -1,14 +1,31 @@
// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains stub implementations for non-WASM builds.
// These stubs allow IDE support and compilation on non-WASM platforms.
// They panic at runtime since host functions are only available in WASM plugins.
// This file contains mock implementations for non-WASM builds.
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
// Plugin authors can use the exported mock instances to set expectations in tests.
//
//go:build !wasip1
package host
// SchedulerScheduleOneTime is a stub that panics on non-WASM platforms.
import "github.com/stretchr/testify/mock"
// mockSchedulerService is the mock implementation for testing.
type mockSchedulerService struct {
mock.Mock
}
// SchedulerMock is the auto-instantiated mock instance for testing.
// Use this to set expectations: host.SchedulerMock.On("MethodName", args...).Return(values...)
var SchedulerMock = &mockSchedulerService{}
// ScheduleOneTime is the mock method for SchedulerScheduleOneTime.
func (m *mockSchedulerService) ScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (string, error) {
args := m.Called(delaySeconds, payload, scheduleID)
return args.String(0), args.Error(1)
}
// SchedulerScheduleOneTime delegates to the mock instance.
// ScheduleOneTime schedules a one-time event to be triggered after the specified delay.
// Plugins that use this function must also implement the SchedulerCallback capability
//
@ -19,10 +36,16 @@ package host
//
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID string) (string, error) {
panic("host: SchedulerScheduleOneTime is only available in WASM plugins")
return SchedulerMock.ScheduleOneTime(delaySeconds, payload, scheduleID)
}
// SchedulerScheduleRecurring is a stub that panics on non-WASM platforms.
// ScheduleRecurring is the mock method for SchedulerScheduleRecurring.
func (m *mockSchedulerService) ScheduleRecurring(cronExpression string, payload string, scheduleID string) (string, error) {
args := m.Called(cronExpression, payload, scheduleID)
return args.String(0), args.Error(1)
}
// SchedulerScheduleRecurring delegates to the mock instance.
// ScheduleRecurring schedules a recurring event using a cron expression.
// Plugins that use this function must also implement the SchedulerCallback capability
//
@ -33,10 +56,16 @@ func SchedulerScheduleOneTime(delaySeconds int32, payload string, scheduleID str
//
// Returns the schedule ID that can be used to cancel the job, or an error if scheduling fails.
func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleID string) (string, error) {
panic("host: SchedulerScheduleRecurring is only available in WASM plugins")
return SchedulerMock.ScheduleRecurring(cronExpression, payload, scheduleID)
}
// SchedulerCancelSchedule is a stub that panics on non-WASM platforms.
// CancelSchedule is the mock method for SchedulerCancelSchedule.
func (m *mockSchedulerService) CancelSchedule(scheduleID string) error {
args := m.Called(scheduleID)
return args.Error(0)
}
// SchedulerCancelSchedule delegates to the mock instance.
// CancelSchedule cancels a scheduled job identified by its schedule ID.
//
// This works for both one-time and recurring schedules. Once cancelled, the job will not trigger
@ -44,5 +73,5 @@ func SchedulerScheduleRecurring(cronExpression string, payload string, scheduleI
//
// Returns an error if the schedule ID is not found or if cancellation fails.
func SchedulerCancelSchedule(scheduleID string) error {
panic("host: SchedulerCancelSchedule is only available in WASM plugins")
return SchedulerMock.CancelSchedule(scheduleID)
}

View File

@ -1,18 +1,35 @@
// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains stub implementations for non-WASM builds.
// These stubs allow IDE support and compilation on non-WASM platforms.
// They panic at runtime since host functions are only available in WASM plugins.
// This file contains mock implementations for non-WASM builds.
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
// Plugin authors can use the exported mock instances to set expectations in tests.
//
//go:build !wasip1
package host
// SubsonicAPICall is a stub that panics on non-WASM platforms.
import "github.com/stretchr/testify/mock"
// mockSubsonicAPIService is the mock implementation for testing.
type mockSubsonicAPIService struct {
mock.Mock
}
// SubsonicAPIMock is the auto-instantiated mock instance for testing.
// Use this to set expectations: host.SubsonicAPIMock.On("MethodName", args...).Return(values...)
var SubsonicAPIMock = &mockSubsonicAPIService{}
// Call is the mock method for SubsonicAPICall.
func (m *mockSubsonicAPIService) Call(uri string) (string, error) {
args := m.Called(uri)
return args.String(0), args.Error(1)
}
// SubsonicAPICall delegates to the mock instance.
// Call executes a Subsonic API request and returns the JSON response.
//
// The uri parameter should be the Subsonic API path without the server prefix,
// e.g., "getAlbumList2?type=random&size=10". The response is returned as raw JSON.
func SubsonicAPICall(uri string) (string, error) {
panic("host: SubsonicAPICall is only available in WASM plugins")
return SubsonicAPIMock.Call(uri)
}

View File

@ -1,14 +1,31 @@
// Code generated by ndpgen. DO NOT EDIT.
//
// This file contains stub implementations for non-WASM builds.
// These stubs allow IDE support and compilation on non-WASM platforms.
// They panic at runtime since host functions are only available in WASM plugins.
// This file contains mock implementations for non-WASM builds.
// These mocks allow IDE support, compilation, and unit testing on non-WASM platforms.
// Plugin authors can use the exported mock instances to set expectations in tests.
//
//go:build !wasip1
package host
// WebSocketConnect is a stub that panics on non-WASM platforms.
import "github.com/stretchr/testify/mock"
// mockWebSocketService is the mock implementation for testing.
type mockWebSocketService struct {
mock.Mock
}
// WebSocketMock is the auto-instantiated mock instance for testing.
// Use this to set expectations: host.WebSocketMock.On("MethodName", args...).Return(values...)
var WebSocketMock = &mockWebSocketService{}
// Connect is the mock method for WebSocketConnect.
func (m *mockWebSocketService) Connect(url string, headers map[string]string, connectionID string) (string, error) {
args := m.Called(url, headers, connectionID)
return args.String(0), args.Error(1)
}
// WebSocketConnect delegates to the mock instance.
// Connect establishes a WebSocket connection to the specified URL.
//
// Plugins that use this function must also implement the WebSocketCallback capability
@ -22,10 +39,16 @@ package host
// Returns the connection ID that can be used to send messages or close the connection,
// or an error if the connection fails.
func WebSocketConnect(url string, headers map[string]string, connectionID string) (string, error) {
panic("host: WebSocketConnect is only available in WASM plugins")
return WebSocketMock.Connect(url, headers, connectionID)
}
// WebSocketSendText is a stub that panics on non-WASM platforms.
// SendText is the mock method for WebSocketSendText.
func (m *mockWebSocketService) SendText(connectionID string, message string) error {
args := m.Called(connectionID, message)
return args.Error(0)
}
// WebSocketSendText delegates to the mock instance.
// SendText sends a text message over an established WebSocket connection.
//
// Parameters:
@ -34,10 +57,16 @@ func WebSocketConnect(url string, headers map[string]string, connectionID string
//
// Returns an error if the connection is not found or if sending fails.
func WebSocketSendText(connectionID string, message string) error {
panic("host: WebSocketSendText is only available in WASM plugins")
return WebSocketMock.SendText(connectionID, message)
}
// WebSocketSendBinary is a stub that panics on non-WASM platforms.
// SendBinary is the mock method for WebSocketSendBinary.
func (m *mockWebSocketService) SendBinary(connectionID string, data []byte) error {
args := m.Called(connectionID, data)
return args.Error(0)
}
// WebSocketSendBinary delegates to the mock instance.
// SendBinary sends binary data over an established WebSocket connection.
//
// Parameters:
@ -46,10 +75,16 @@ func WebSocketSendText(connectionID string, message string) error {
//
// Returns an error if the connection is not found or if sending fails.
func WebSocketSendBinary(connectionID string, data []byte) error {
panic("host: WebSocketSendBinary is only available in WASM plugins")
return WebSocketMock.SendBinary(connectionID, data)
}
// WebSocketCloseConnection is a stub that panics on non-WASM platforms.
// CloseConnection is the mock method for WebSocketCloseConnection.
func (m *mockWebSocketService) CloseConnection(connectionID string, code int32, reason string) error {
args := m.Called(connectionID, code, reason)
return args.Error(0)
}
// WebSocketCloseConnection delegates to the mock instance.
// CloseConnection gracefully closes a WebSocket connection.
//
// Parameters:
@ -59,5 +94,5 @@ func WebSocketSendBinary(connectionID string, data []byte) error {
//
// Returns an error if the connection is not found or if closing fails.
func WebSocketCloseConnection(connectionID string, code int32, reason string) error {
panic("host: WebSocketCloseConnection is only available in WASM plugins")
return WebSocketMock.CloseConnection(connectionID, code, reason)
}