Files
ucan/command_test.go
Steve Moyer f37a43ac38 feat(command): adds code/test to parse Command strings
This is probably overkill but most of the code is needed to validate the command
string.  My thought was that this could then be used in the delegation and
invocation structs to provide a stronger type.  The Command struct itself is
a bit more convenient with segments represented by []string but this might
need to be changed to simply string to simplify IPLD encoding/decoding
2024-08-30 08:21:24 -04:00

160 lines
2.8 KiB
Go

package command_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ucan-wg/go-ucan/pkg/command"
)
func TestCommand_String(t *testing.T) {
require.Equal(t, "/", command.Top().String())
}
func TestIsValidCommand(t *testing.T) {
t.Parallel()
t.Run("succeeds when", func(t *testing.T) {
t.Parallel()
for _, testcase := range validTestcases(t) {
testcase := testcase
t.Run(testcase.name, func(t *testing.T) {
t.Parallel()
require.True(t, command.IsValid(testcase.inp))
})
}
})
t.Run("fails when", func(t *testing.T) {
t.Parallel()
for _, testcase := range invalidTestcases(t) {
testcase := testcase
t.Run(testcase.name, func(t *testing.T) {
t.Parallel()
require.False(t, command.IsValid(testcase.inp))
})
}
})
}
func TestParseCommand(t *testing.T) {
t.Parallel()
t.Run("succeeds when", func(t *testing.T) {
t.Parallel()
for _, testcase := range validTestcases(t) {
testcase := testcase
t.Run(testcase.name, func(t *testing.T) {
t.Parallel()
cmd, err := command.Parse("/elem0/elem1/elem2")
require.NoError(t, err)
require.NotNil(t, cmd)
})
}
})
t.Run("fails when", func(t *testing.T) {
t.Parallel()
for _, testcase := range invalidTestcases(t) {
testcase := testcase
t.Run(testcase.name, func(t *testing.T) {
t.Parallel()
cmd, err := command.Parse(testcase.inp)
assert.ErrorIs(t, err, command.ErrParse)
assert.ErrorIs(t, err, testcase.err)
assert.Nil(t, cmd)
})
}
})
}
type testcase struct {
name string
inp string
}
func validTestcases(t *testing.T) []testcase {
t.Helper()
cmds := []string{
"/",
"/crud",
"/crud/create",
"/stack/pop",
"/crypto/sign",
"/foo/bar/baz/qux/quux",
"/ほげ/ふが",
}
testcases := make([]testcase, len(cmds))
for i, inp := range cmds {
testcases[i] = testcase{
name: "Command is " + inp,
inp: inp,
}
}
return testcases
}
type errorTestcase struct {
testcase
err error
}
func invalidTestcases(t *testing.T) []errorTestcase {
t.Helper()
return []errorTestcase{
{
testcase: testcase{
name: "leading slash is missing",
inp: "elem0/elem1/elem2",
},
err: command.ErrRequiresLeadingSlash,
},
{
testcase: testcase{
name: "trailing slash is present",
inp: "/elem0/elem1/elem2/",
},
err: command.ErrDisallowsTrailingSlash,
},
{
testcase: testcase{
name: "only reserved ucan namespace",
inp: "/ucan",
},
err: command.ErrUCANNamespaceReserved,
},
{
testcase: testcase{
name: "reserved ucan namespace prefix",
inp: "/ucan/elem0/elem1/elem2",
},
err: command.ErrUCANNamespaceReserved,
},
{
testcase: testcase{
name: "uppercase character are present",
inp: "/elem0/Elem1/elem2",
},
err: command.ErrRequiresLowercase,
},
}
}