Documentation
¶
Overview ¶
Package testplugin runs a real filex storage plugin — the HTTP/JSON protocol of internal/plugin, served over httptest — so any package that consumes a storage.Driver can be exercised against a PLUGIN-backed storage without spawning a second process.
Why this package exists ¶
The plugin adapter was proven through the HTTP file manager only. Every other surface (sync, WebDAV, S3, SFTP, FTP, NFS, quota, thumbnails) reaches storage through the same storage.Driver interface, but each one leans on a different corner of it: sync stats and lists, WebDAV wants a directory at the root, SFTP writes with an unknown size, NFS asks for the same path twice. A plugin driver is NOT a local driver with a longer code path — it answers over a wire, its errors arrive as JSON codes, its instance can vanish under a restart. Those differences only show up when a surface is driven end to end, and a shell script that proves it once on a laptop proves nothing on the next release. Hence: a helper the tests share.
The fake here is deliberately written the way a third-party plugin author would write one — flat map, no filex internals — because if the protocol is awkward to implement it shows up here first.
Index ¶
- Variables
- func FullCaps() plugin.Capabilities
- type Option
- type Plugin
- func (p *Plugin) Counts() (lists, reads, ranges, writes int)
- func (p *Plugin) Data(pth string) ([]byte, bool)
- func (p *Plugin) Delete(pth string)
- func (p *Plugin) Down()
- func (p *Plugin) Driver(t *testing.T) storage.Driver
- func (p *Plugin) DriverName() string
- func (p *Plugin) DriverWithConfig(t *testing.T, cfg map[string]any) storage.Driver
- func (p *Plugin) Emit(ev plugin.Event)
- func (p *Plugin) Exists(pth string) bool
- func (p *Plugin) NoInstanceCount() int
- func (p *Plugin) Paths() []string
- func (p *Plugin) Register(t *testing.T) string
- func (p *Plugin) Restart()
- func (p *Plugin) Seed(pth, data string)
- func (p *Plugin) SeedBytes(pth string, data []byte)
- func (p *Plugin) SeedDir(pth string)
- func (p *Plugin) URL() string
- func (p *Plugin) Up()
Constants ¶
This section is empty.
Variables ¶
var SeedTime = time.Date(2023, 11, 14, 22, 13, 20, 0, time.UTC)
SeedTime is the mtime every seeded file carries. Fixed, because a sync test that compares "changed since last pass" against time.Now() passes for the wrong reason on a fast machine.
Functions ¶
func FullCaps ¶
func FullCaps() plugin.Capabilities
FullCaps is everything the protocol offers. Tests that care about a specific capability being ABSENT should start here and switch one off, so the difference under test is the only difference.
Types ¶
type Option ¶
type Option func(*Plugin)
Option tunes a plugin before it starts.
func WithCaps ¶
func WithCaps(c plugin.Capabilities) Option
WithCaps replaces the declared capabilities.
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin is a running fake plugin: an httptest server speaking the protocol over an in-memory tree.
func (*Plugin) Counts ¶
Counts reports how many list/read/range/write calls reached the plugin. A surface that "works" by never touching the backend is a surface that is serving something else.
func (*Plugin) Data ¶
Data returns what the plugin actually holds at pth. Assertions go through this rather than through the driver, so a surface that silently swallowed a write cannot pass by reading back its own cache.
func (*Plugin) Delete ¶
Delete removes a path from the plugin's tree directly, bypassing the driver — the other half of "somebody else changed the bucket", and the only way to test that a sync notices a disappearance.
func (*Plugin) Down ¶
func (p *Plugin) Down()
Down makes every instance call answer no_instance for good, which is what a plugin whose process is gone looks like from the host: the adapter can keep re-creating instances and keep being told they do not exist. Surfaces must report that as a failure — a "gone" plugin that renders as an empty folder or a 404 tells the user their files were deleted.
func (*Plugin) Driver ¶
Driver returns a storage.Driver already Init'ed against the plugin — the exact value the manager hands the rest of filex.
func (*Plugin) DriverName ¶
DriverName is what the storage registry knows this plugin as.
func (*Plugin) DriverWithConfig ¶
DriverWithConfig is Driver with the config the admin would have saved.
func (*Plugin) NoInstanceCount ¶
NoInstanceCount is how many times the plugin has answered no_instance. A restart test that never reaches a non-zero count proved nothing: the retry path it means to exercise was never entered.
func (*Plugin) Paths ¶
Paths lists everything the plugin holds, sorted — useful in a failure message, where "not found" is far less informative than the actual tree.
func (*Plugin) Register ¶
Register puts the plugin's factory in the global storage registry under "plugin:<name>" and removes it again after the test, so surfaces that look a driver up by name (storage.Get) meet a plugin exactly as they would in production. Returns the driver name to put in the storage row.
func (*Plugin) Restart ¶
func (p *Plugin) Restart()
Restart makes the plugin forget its instance ids exactly once, which is what a crashed-and-respawned plugin looks like from the host. The files survive, as they would on a real backend.
func (*Plugin) Seed ¶
Seed writes a file directly into the plugin's tree, bypassing the driver — the "somebody else put this in the bucket" case every sync exists for.