Files
gitea-mcp/internal/tools/validate_test.go
T
mathiasandClaude Opus 4.8 e0bede0547 fix(tools): reject empty repo/name identifier at tool layer (#37)
An empty required repo identifier built a trailing-empty path segment
(`/api/v1/repos/{owner}/`) and leaked gitea's bare 404. parseArgs now
validates, via reflection, that `repo`/`name` string args are non-empty and
returns a typed ErrValidation naming the field. Optional identifiers (e.g.
code_search's owner-wide fan-out `repo`) opt out with `,omitempty`. `owner` is
already enforced by the allowlist check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 22:47:05 +02:00

33 lines
1.2 KiB
Go

package tools_test
import (
"context"
"encoding/json"
"testing"
"gitea.d-ma.be/mathias/gitea-mcp/internal/allowlist"
"gitea.d-ma.be/mathias/gitea-mcp/internal/gitea"
"gitea.d-ma.be/mathias/gitea-mcp/internal/tools"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// #37: an empty required repo identifier must fail fast at the tool layer with a
// typed ErrValidation naming the field, rather than building a trailing-empty
// path segment (`/api/v1/repos/{owner}/`) that leaks gitea's bare 404.
func TestEmptyRepoRejectedAsValidation(t *testing.T) {
c := gitea.NewClient("http://unused", "")
a := allowlist.New([]string{"mathias"})
_, err := tools.NewRepoGet(c, a).Call(context.Background(), json.RawMessage(`{"owner":"mathias","repo":""}`))
require.Error(t, err)
assert.ErrorIs(t, err, gitea.ErrValidation)
assert.Contains(t, err.Error(), "repo")
// same for an empty `name` on a create tool (name = required new-repo name)
_, err = tools.NewRepoCreate(c, a).Call(context.Background(), json.RawMessage(`{"owner":"mathias","name":""}`))
require.Error(t, err)
assert.ErrorIs(t, err, gitea.ErrValidation)
assert.Contains(t, err.Error(), "name")
}