tailscale/types/ipproto/ipproto_test.go

139 lines
3.4 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package ipproto
import (
"encoding"
"encoding/json"
"fmt"
"testing"
"tailscale.com/util/must"
)
// Ensure that the Proto type implements encoding.TextMarshaler and
// encoding.TextUnmarshaler.
var (
_ encoding.TextMarshaler = (*Proto)(nil)
_ encoding.TextUnmarshaler = (*Proto)(nil)
)
func TestHistoricalStringNames(t *testing.T) {
// A subset of supported protocols were described with their lowercase String() representations and must remain supported.
var historical = map[string]Proto{
"icmpv4": ICMPv4,
"igmp": IGMP,
"tcp": TCP,
"udp": UDP,
"dccp": DCCP,
"gre": GRE,
"sctp": SCTP,
}
for name, proto := range historical {
var p Proto
must.Do(p.UnmarshalText([]byte(name)))
if got, want := p, proto; got != want {
t.Errorf("Proto.UnmarshalText(%q) = %v, want %v", name, got, want)
}
}
}
func TestAcceptedNamesContainsPreferredNames(t *testing.T) {
for proto, name := range preferredNames {
if _, ok := acceptedNames[name]; !ok {
t.Errorf("preferredNames[%q] = %v, but acceptedNames does not contain it", name, proto)
}
}
}
func TestProtoTextEncodingRoundTrip(t *testing.T) {
for i := 0; i < 256; i++ {
text := must.Get(Proto(i).MarshalText())
var p Proto
must.Do(p.UnmarshalText(text))
if got, want := p, Proto(i); got != want {
t.Errorf("Proto(%d) round-trip got %v, want %v", i, got, want)
}
}
}
func TestProtoUnmarshalText(t *testing.T) {
var p Proto = 1
err := p.UnmarshalText([]byte(nil))
if err != nil || p != 0 {
t.Fatalf("empty input, got err=%v, p=%v, want nil, 0", err, p)
}
for i := 0; i < 256; i++ {
var p Proto
must.Do(p.UnmarshalText([]byte(fmt.Sprintf("%d", i))))
if got, want := p, Proto(i); got != want {
t.Errorf("Proto(%d) = %v, want %v", i, got, want)
}
}
for name, wantProto := range acceptedNames {
var p Proto
must.Do(p.UnmarshalText([]byte(name)))
if got, want := p, wantProto; got != want {
t.Errorf("Proto(%q) = %v, want %v", name, got, want)
}
}
for wantProto, name := range preferredNames {
var p Proto
must.Do(p.UnmarshalText([]byte(name)))
if got, want := p, wantProto; got != want {
t.Errorf("Proto(%q) = %v, want %v", name, got, want)
}
}
}
func TestProtoMarshalText(t *testing.T) {
for i := 0; i < 256; i++ {
text := must.Get(Proto(i).MarshalText())
if wantName, ok := preferredNames[Proto(i)]; ok {
if got, want := string(text), wantName; got != want {
t.Errorf("Proto(%d).MarshalText() = %q, want preferred name %q", i, got, want)
}
continue
}
if got, want := string(text), fmt.Sprintf("%d", i); got != want {
t.Errorf("Proto(%d).MarshalText() = %q, want %q", i, got, want)
}
}
}
func TestProtoMarshalJSON(t *testing.T) {
for i := 0; i < 256; i++ {
j := must.Get(Proto(i).MarshalJSON())
if got, want := string(j), fmt.Sprintf(`%d`, i); got != want {
t.Errorf("Proto(%d).MarshalJSON() = %q, want %q", i, got, want)
}
}
}
func TestProtoUnmarshalJSON(t *testing.T) {
var p Proto
for i := 0; i < 256; i++ {
j := []byte(fmt.Sprintf(`%d`, i))
must.Do(json.Unmarshal(j, &p))
if got, want := p, Proto(i); got != want {
t.Errorf("Proto(%d) = %v, want %v", i, got, want)
}
}
for name, wantProto := range acceptedNames {
must.Do(json.Unmarshal([]byte(fmt.Sprintf(`"%s"`, name)), &p))
if got, want := p, wantProto; got != want {
t.Errorf("Proto(%q) = %v, want %v", name, got, want)
}
}
}