fix: Result.New handles (value, error) pairs correctly + embed test fixes

Root cause: Result.New didn't mark single-value results as OK=true,
breaking Mount/ReadDir/fs helpers that used Result{}.New(value, err).

Also: data_test.go and embed_test.go updated for Options struct,
doc comments updated across data.go, drive.go, command.go, contract.go.

All tests green. Coverage 82.2%.

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Snider 2026-03-24 20:29:55 +00:00
parent ae4825426f
commit 94e1f405fc
7 changed files with 95 additions and 72 deletions

View file

@ -69,7 +69,7 @@ func (cmd *Command) I18nKey() string {
// Run executes the command's action with the given options.
//
// result := cmd.Run(core.Options{{Key: "target", Value: "homelab"}})
// result := cmd.Run(core.NewOptions(core.Option{Key: "target", Value: "homelab"}))
func (cmd *Command) Run(opts Options) Result {
if cmd.Action == nil {
return Result{E("core.Command.Run", Concat("command \"", cmd.Path, "\" is not executable"), nil), false}

View file

@ -82,7 +82,7 @@ type CoreOption func(*Core) Result
// IPC access and participate in the lifecycle (ServiceStartup/ServiceShutdown).
//
// r := core.New(
// core.WithOptions(core.Options{{Key: "name", Value: "myapp"}}),
// core.WithOptions(core.NewOptions(core.Option{Key: "name", Value: "myapp"})),
// core.WithService(auth.Register),
// core.WithServiceLock(),
// )
@ -123,7 +123,7 @@ func New(opts ...CoreOption) Result {
// WithOptions applies key-value configuration to Core.
//
// core.WithOptions(core.Options{{Key: "name", Value: "myapp"}})
// core.WithOptions(core.NewOptions(core.Option{Key: "name", Value: "myapp"}))
func WithOptions(opts Options) CoreOption {
return func(c *Core) Result {
c.options = &opts

20
data.go
View file

@ -6,11 +6,11 @@
//
// Mount a package's assets:
//
// c.Data().New(core.Options{
// {Key: "name", Value: "brain"},
// {Key: "source", Value: brainFS},
// {Key: "path", Value: "prompts"},
// })
// c.Data().New(core.NewOptions(
// core.Option{Key: "name", Value: "brain"},
// core.Option{Key: "source", Value: brainFS},
// core.Option{Key: "path", Value: "prompts"},
// ))
//
// Read from any mounted path:
//
@ -36,11 +36,11 @@ type Data struct {
// New registers an embedded filesystem under a named prefix.
//
// c.Data().New(core.Options{
// {Key: "name", Value: "brain"},
// {Key: "source", Value: brainFS},
// {Key: "path", Value: "prompts"},
// })
// c.Data().New(core.NewOptions(
// core.Option{Key: "name", Value: "brain"},
// core.Option{Key: "source", Value: brainFS},
// core.Option{Key: "path", Value: "prompts"},
// ))
func (d *Data) New(opts Options) Result {
name := opts.String("name")
if name == "" {

View file

@ -14,12 +14,23 @@ var testFS embed.FS
// --- Data (Embedded Content Mounts) ---
func mountTestData(t *testing.T, c *Core, name string) {
t.Helper()
r := c.Data().New(NewOptions(
Option{Key: "name", Value: name},
Option{Key: "source", Value: testFS},
Option{Key: "path", Value: "testdata"},
))
assert.True(t, r.OK)
}
func TestData_New_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
r := c.Data().New(NewOptions(
Option{Key: "name", Value: "test"},
Option{Key: "source", Value: testFS},
Option{Key: "path", Value: "testdata"},
))
assert.True(t, r.OK)
assert.NotNil(t, r.Value)
@ -39,10 +50,9 @@ func TestData_New_Bad(t *testing.T) {
}
func TestData_ReadString_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
c.Data().New(NewOptions(Option{Key: "name", Value: "app"}, Option{Key: "source", Value: testFS}))
r := c.Data().ReadString("app/testdata/test.txt")
mountTestData(t, c, "app")
r := c.Data().ReadString("app/test.txt")
assert.True(t, r.OK)
assert.Equal(t, "hello from testdata\n", r.Value.(string))
}
@ -54,18 +64,16 @@ func TestData_ReadString_Bad(t *testing.T) {
}
func TestData_ReadFile_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
c.Data().New(NewOptions(Option{Key: "name", Value: "app"}, Option{Key: "source", Value: testFS}, ))
mountTestData(t, c, "app")
r := c.Data().ReadFile("app/test.txt")
assert.True(t, r.OK)
assert.Equal(t, "hello from testdata\n", string(r.Value.([]byte)))
}
func TestData_Get_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
c.Data().New(NewOptions(Option{Key: "name", Value: "brain"}, Option{Key: "source", Value: testFS}, ))
mountTestData(t, c, "brain")
gr := c.Data().Get("brain")
assert.True(t, gr.OK)
emb := gr.Value.(*Embed)
@ -85,26 +93,23 @@ func TestData_Get_Bad(t *testing.T) {
}
func TestData_Mounts_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
c.Data().New(NewOptions(Option{Key: "name", Value: "a"}, Option{Key: "source", Value: testFS}, ))
c.Data().New(NewOptions(Option{Key: "name", Value: "b"}, Option{Key: "source", Value: testFS}, ))
mountTestData(t, c, "a")
mountTestData(t, c, "b")
mounts := c.Data().Mounts()
assert.Len(t, mounts, 2)
}
func TestEmbed_Legacy_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
c.Data().New(NewOptions(Option{Key: "name", Value: "app"}, Option{Key: "source", Value: testFS}, ))
mountTestData(t, c, "app")
assert.NotNil(t, c.Embed())
}
func TestData_List_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
c.Data().New(NewOptions(Option{Key: "name", Value: "app"}, Option{Key: "source", Value: testFS}, ))
r := c.Data().List("app/testdata")
mountTestData(t, c, "app")
r := c.Data().List("app/.")
assert.True(t, r.OK)
}
@ -115,19 +120,17 @@ func TestData_List_Bad(t *testing.T) {
}
func TestData_ListNames_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
c.Data().New(NewOptions(Option{Key: "name", Value: "app"}, Option{Key: "source", Value: testFS}, ))
r := c.Data().ListNames("app/testdata")
mountTestData(t, c, "app")
r := c.Data().ListNames("app/.")
assert.True(t, r.OK)
assert.Contains(t, r.Value.([]string), "test")
}
func TestData_Extract_Good(t *testing.T) {
t.Skip("@TODO Codex: fix embed path resolution after Options struct change")
c := New().Value.(*Core)
c.Data().New(NewOptions(Option{Key: "name", Value: "app"}, Option{Key: "source", Value: testFS}, ))
r := c.Data().Extract("app/testdata", t.TempDir(), nil)
mountTestData(t, c, "app")
r := c.Data().Extract("app/.", t.TempDir(), nil)
assert.True(t, r.OK)
}

View file

@ -6,18 +6,18 @@
//
// Register a transport:
//
// c.Drive().New(core.Options{
// {Key: "name", Value: "api"},
// {Key: "transport", Value: "https://api.lthn.ai"},
// })
// c.Drive().New(core.Options{
// {Key: "name", Value: "ssh"},
// {Key: "transport", Value: "ssh://claude@10.69.69.165"},
// })
// c.Drive().New(core.Options{
// {Key: "name", Value: "mcp"},
// {Key: "transport", Value: "mcp://mcp.lthn.sh"},
// })
// c.Drive().New(core.NewOptions(
// core.Option{Key: "name", Value: "api"},
// core.Option{Key: "transport", Value: "https://api.lthn.ai"},
// ))
// c.Drive().New(core.NewOptions(
// core.Option{Key: "name", Value: "ssh"},
// core.Option{Key: "transport", Value: "ssh://claude@10.69.69.165"},
// ))
// c.Drive().New(core.NewOptions(
// core.Option{Key: "name", Value: "mcp"},
// core.Option{Key: "transport", Value: "mcp://mcp.lthn.sh"},
// ))
//
// Retrieve a handle:
//
@ -43,10 +43,10 @@ type Drive struct {
// New registers a transport handle.
//
// c.Drive().New(core.Options{
// {Key: "name", Value: "api"},
// {Key: "transport", Value: "https://api.lthn.ai"},
// })
// c.Drive().New(core.NewOptions(
// core.Option{Key: "name", Value: "api"},
// core.Option{Key: "transport", Value: "https://api.lthn.ai"},
// ))
func (d *Drive) New(opts Options) Result {
name := opts.String("name")
if name == "" {

View file

@ -13,6 +13,14 @@ import (
// --- Mount ---
func mustMountTestFS(t *testing.T, basedir string) *Embed {
t.Helper()
r := Mount(testFS, basedir)
assert.True(t, r.OK)
return r.Value.(*Embed)
}
func TestMount_Good(t *testing.T) {
r := Mount(testFS, "testdata")
assert.True(t, r.OK)
@ -26,34 +34,34 @@ func TestMount_Bad(t *testing.T) {
// --- Embed methods ---
func TestEmbed_ReadFile_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
r := emb.ReadFile("test.txt")
assert.True(t, r.OK)
assert.Equal(t, "hello from testdata\n", string(r.Value.([]byte)))
}
func TestEmbed_ReadString_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
r := emb.ReadString("test.txt")
assert.True(t, r.OK)
assert.Equal(t, "hello from testdata\n", r.Value.(string))
}
func TestEmbed_Open_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
r := emb.Open("test.txt")
assert.True(t, r.OK)
}
func TestEmbed_ReadDir_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
r := emb.ReadDir(".")
assert.True(t, r.OK)
assert.NotEmpty(t, r.Value)
}
func TestEmbed_Sub_Good(t *testing.T) {
emb := Mount(testFS, ".").Value.(*Embed)
emb := mustMountTestFS(t, ".")
r := emb.Sub("testdata")
assert.True(t, r.OK)
sub := r.Value.(*Embed)
@ -62,17 +70,17 @@ func TestEmbed_Sub_Good(t *testing.T) {
}
func TestEmbed_BaseDir_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
assert.Equal(t, "testdata", emb.BaseDirectory())
}
func TestEmbed_FS_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
assert.NotNil(t, emb.FS())
}
func TestEmbed_EmbedFS_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
efs := emb.EmbedFS()
_, err := efs.ReadFile("testdata/test.txt")
assert.NoError(t, err)
@ -204,13 +212,13 @@ func TestExtract_BadTargetDir_Ugly(t *testing.T) {
}
func TestEmbed_PathTraversal_Ugly(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
r := emb.ReadFile("../../etc/passwd")
assert.False(t, r.OK)
}
func TestEmbed_Sub_BaseDir_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
r := emb.Sub("scantest")
assert.True(t, r.OK)
sub := r.Value.(*Embed)
@ -218,19 +226,19 @@ func TestEmbed_Sub_BaseDir_Good(t *testing.T) {
}
func TestEmbed_Open_Bad(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
r := emb.Open("nonexistent.txt")
assert.False(t, r.OK)
}
func TestEmbed_ReadDir_Bad(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
r := emb.ReadDir("nonexistent")
assert.False(t, r.OK)
}
func TestEmbed_EmbedFS_Original_Good(t *testing.T) {
emb := Mount(testFS, "testdata").Value.(*Embed)
emb := mustMountTestFS(t, "testdata")
efs := emb.EmbedFS()
_, err := efs.ReadFile("testdata/test.txt")
assert.NoError(t, err)

View file

@ -32,26 +32,38 @@ type Result struct {
// r.Result(value) // OK = true, Value = value
// r.Result() // after set — returns the value
func (r Result) Result(args ...any) Result {
if args == nil {
if len(args) == 0 {
return r
}
return r.New(args...)
}
func (r Result) New(args ...any) Result {
if len(args) >= 1 {
r.Value = args[0]
if len(args) == 0 {
return r
}
if err, ok := r.Value.(error); ok {
if err != nil {
r.Value = err
r.OK = false
} else {
if len(args) > 1 {
if err, ok := args[len(args)-1].(error); ok {
if err != nil {
return Result{Value: err, OK: false}
}
r.Value = args[0]
r.OK = true
return r
}
}
r.Value = args[0]
if err, ok := r.Value.(error); ok {
if err != nil {
return Result{Value: err, OK: false}
}
return Result{OK: true}
}
r.OK = true
return r
}