This can be used with both system and member identifiers. Signed-off-by: Yonah <contrib@gensokyo.uk>
208 lines
4.6 KiB
Go
208 lines
4.6 KiB
Go
package ident_test
|
|
|
|
import (
|
|
"encoding"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.gensokyo.uk/cofront/cof-spec/ident"
|
|
)
|
|
|
|
// rTestCases describes multiple representation test cases.
|
|
type rTestCases[V any, S interface {
|
|
encoding.TextMarshaler
|
|
encoding.TextUnmarshaler
|
|
fmt.Stringer
|
|
|
|
*V
|
|
}] []struct {
|
|
name string
|
|
ident V
|
|
want []byte
|
|
err error
|
|
}
|
|
|
|
// checkRepresentation runs tests described by testCases.
|
|
func (testCases rTestCases[V, S]) run(t *testing.T) {
|
|
t.Helper()
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Helper()
|
|
t.Parallel()
|
|
|
|
t.Run("decode", func(t *testing.T) {
|
|
t.Helper()
|
|
t.Parallel()
|
|
|
|
var got V
|
|
if err := S(&got).UnmarshalText(tc.want); !reflect.DeepEqual(err, tc.err) {
|
|
t.Fatalf("UnmarshalText: error = %v, want %v", err, tc.err)
|
|
}
|
|
|
|
if tc.err != nil {
|
|
return
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, tc.ident) {
|
|
t.Errorf("UnmarshalText: %#v, want %#v", got, tc.ident)
|
|
}
|
|
})
|
|
|
|
if tc.err != nil {
|
|
return
|
|
}
|
|
|
|
t.Run("encode", func(t *testing.T) {
|
|
t.Helper()
|
|
t.Parallel()
|
|
|
|
if got, err := S(&tc.ident).MarshalText(); err != nil {
|
|
t.Fatalf("MarshalText: error = %v", err)
|
|
} else if string(got) != string(tc.want) {
|
|
raw, decodeErr := base64.URLEncoding.AppendDecode(nil, got)
|
|
t.Logf("AppendDecode: %#v, error = %v", raw, decodeErr)
|
|
|
|
t.Errorf("MarshalText: %#v, want %#v", got, tc.want)
|
|
}
|
|
|
|
if got := S(&tc.ident).String(); got != string(tc.want) {
|
|
t.Errorf("String: %s, want %s", got, tc.want)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFS(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
rTestCases[ident.F[ident.S, *ident.S], *ident.F[ident.S, *ident.S]]{
|
|
{"separator", ident.F[ident.S, *ident.S]{}, nil, ident.ErrSeparator},
|
|
{"bad ident", ident.F[ident.S, *ident.S]{}, []byte(
|
|
strings.Repeat("=", ident.EncodedSizeSystem) + ":",
|
|
), base64.CorruptInputError(0)},
|
|
|
|
{"valid", ident.F[ident.S, *ident.S]{
|
|
I: &ident.S{
|
|
Site: ident.TrivialSite,
|
|
Host: ident.TrivialHost,
|
|
|
|
Time: uint64(time.Date(
|
|
0xfd, 7, 15,
|
|
23, 59, 59, 0xcafe,
|
|
time.UTC,
|
|
).UnixNano()),
|
|
|
|
ID: 0xfee1dead0badf00d,
|
|
},
|
|
|
|
Remote: mustNewRemote("gensokyo.uk"),
|
|
}, []byte("_srt_r66_sr-AEPO8ZJKEA3wrQut3uH-:gensokyo.uk"), nil},
|
|
}.run(t)
|
|
}
|
|
|
|
func TestFM(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
rTestCases[ident.F[ident.M, *ident.M], *ident.F[ident.M, *ident.M]]{
|
|
{"separator", ident.F[ident.M, *ident.M]{}, nil, ident.ErrSeparator},
|
|
{"bad ident", ident.F[ident.M, *ident.M]{}, []byte(
|
|
strings.Repeat("=", ident.EncodedSizeMember) + ":",
|
|
), base64.CorruptInputError(0)},
|
|
|
|
{"valid", ident.F[ident.M, *ident.M]{
|
|
I: &ident.M{
|
|
Serial: 0xfdfdfdfdfdfdfdfd,
|
|
|
|
Time: uint64(time.Date(
|
|
0xfd, 7, 15,
|
|
23, 59, 59, 0xcab,
|
|
time.UTC,
|
|
).UnixNano()),
|
|
|
|
ID: 0x2e736e64,
|
|
|
|
System: ident.S{
|
|
Site: ident.TrivialSite,
|
|
Host: ident.TrivialHost,
|
|
|
|
Time: uint64(time.Date(
|
|
0xfd, 7, 15,
|
|
23, 59, 59, 0xcafe,
|
|
time.UTC,
|
|
).UnixNano()),
|
|
|
|
ID: 0xfee1dead0badf00d,
|
|
},
|
|
},
|
|
|
|
Remote: mustNewRemote("gensokyo.uk"),
|
|
}, []byte("_f39_f39_f2rQkLO8ZJKEGRucy4AAAAA_srt_r66_sr-AEPO8ZJKEA3wrQut3uH-:gensokyo.uk"), nil},
|
|
}.run(t)
|
|
}
|
|
|
|
func TestErrors(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := []struct {
|
|
name string
|
|
err error
|
|
want string
|
|
}{
|
|
{"UnexpectedSizeError", &ident.UnexpectedSizeError{
|
|
Data: make([]byte, 1<<10),
|
|
Want: ident.EncodedSizeSystem,
|
|
}, "got 1024 bytes for a 32-byte identifier"},
|
|
|
|
{"InvalidLabelLDH start", &ident.InvalidLabelError{
|
|
Data: []byte{'-'},
|
|
Label: 0xbad,
|
|
Index: 0,
|
|
Reason: ident.InvalidLabelLDH,
|
|
}, "label 2989 starts with '-'"},
|
|
|
|
{"InvalidLabelLDH end", &ident.InvalidLabelError{
|
|
Data: []byte{0, '-'},
|
|
Label: 0xbad,
|
|
Index: 1,
|
|
Reason: ident.InvalidLabelLDH,
|
|
}, "label 2989 ends with '-'"},
|
|
|
|
{"InvalidLabelLDH", &ident.InvalidLabelError{
|
|
Data: []byte{0},
|
|
Label: 0xbad,
|
|
Index: 0,
|
|
Reason: ident.InvalidLabelLDH,
|
|
}, `label 2989 contains invalid byte '\x00' at index 0`},
|
|
|
|
{"InvalidLabelShort", &ident.InvalidLabelError{
|
|
Label: 0xf00d,
|
|
Reason: ident.InvalidLabelShort,
|
|
}, "label 61453 is empty"},
|
|
|
|
{"InvalidLabelLong", &ident.InvalidLabelError{
|
|
Label: 0xf00d,
|
|
Reason: ident.InvalidLabelLong,
|
|
}, "label 61453 is longer than 63 bytes"},
|
|
|
|
{"InvalidLabelError", &ident.InvalidLabelError{
|
|
Label: 0xcafe,
|
|
Reason: 0xbadf00d,
|
|
}, "invalid label 51966 at byte 0"},
|
|
}
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if got := tc.err.Error(); got != tc.want {
|
|
t.Errorf("Error: %q, want %q", got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|