blob: ed89f56153983d5514fcc030afed4104d55b2067 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package naming
import (
"testing"
)
func TestSplitAddressName(t *testing.T) {
cases := []struct {
input, address, name string
}{
{"", "", ""},
{"/", "", ""},
{"//", "", ""},
{"//abc@@host/foo", "abc@@host", "foo"},
{"a", "", "a"},
{"/a", "a", ""},
{"/a/", "a", ""},
{"a/b", "", "a/b"},
{"/a/b", "a", "b"},
{"abc@@/foo", "", "abc@@/foo"},
{"/abc@@host/foo", "abc@@host", "foo"},
{"/abc/foo", "abc", "foo"},
{"/abc/foo//x", "abc", "foo/x"},
{"/abc:20/foo", "abc:20", "foo"},
{"/abc//foo/bar", "abc", "foo/bar"},
{"/0abc:20/foo", "0abc:20", "foo"},
{"/abc1.2:20/foo", "abc1.2:20", "foo"},
{"/abc:xx/foo", "abc:xx", "foo"},
{"/-abc/foo", "-abc", "foo"},
{"/a.-abc/foo", "a.-abc", "foo"},
{"/[01:02::]:444", "[01:02::]:444", ""},
{"/[01:02::]:444/foo", "[01:02::]:444", "foo"},
{"/12.3.4.5:444", "12.3.4.5:444", ""},
{"/12.3.4.5:444/foo", "12.3.4.5:444", "foo"},
{"/12.3.4.5", "12.3.4.5", ""},
{"/12.3.4.5/foo", "12.3.4.5", "foo"},
{"/12.3.4.5//foo", "12.3.4.5", "foo"},
{"/12.3.4.5/foo//bar", "12.3.4.5", "foo/bar"},
{"/user@domain.com@host:1234/foo/bar", "user@domain.com@host:1234", "foo/bar"},
{"/(dev.v.io/services/mounttabled)@host:1234/foo/bar", "(dev.v.io/services/mounttabled)@host:1234", "foo/bar"},
{"/(dev.v.io/services/mounttabled)@host:1234/", "(dev.v.io/services/mounttabled)@host:1234", ""},
{"/(dev.v.io/services/mounttabled)@host:1234", "(dev.v.io/services/mounttabled)@host:1234", ""},
{"/@4@tcp@127.0.0.1:22@@@@s@dev.v.io/", "@4@tcp@127.0.0.1:22@@@@s@dev.v.io", ""}, // malformed endpoint, doesn't end in a @@
{"/@4@tcp@127.0.0.1:22@@@@s@dev.v.io", "@4@tcp@127.0.0.1:22@@@@s@dev.v.io", ""}, // malformed endpoint, doesn't end in a @@
{"/@4@tcp@127.0.0.1:22@@@@s@dev.v.io/services/mounttabled@@/foo/bar", "@4@tcp@127.0.0.1:22@@@@s@dev.v.io/services/mounttabled@@", "foo/bar"},
{"/@4@tcp@127.0.0.1:22@@@@s@dev.v.io/services/mounttabled,staging.v.io/services/nsroot@@/foo/bar", "@4@tcp@127.0.0.1:22@@@@s@dev.v.io/services/mounttabled,staging.v.io/services/nsroot@@", "foo/bar"},
{"/@@@127.0.0.1:22@@@@/foo/bar", "@@@127.0.0.1:22@@@@", "foo/bar"},
{"/@4@tcp@127.0.0.1:22@@@@s@dev.v.io/services/mounttabled,staging.v.io/services/nsroot@@", "@4@tcp@127.0.0.1:22@@@@s@dev.v.io/services/mounttabled,staging.v.io/services/nsroot@@", ""},
}
for _, c := range cases {
addr, name := SplitAddressName(c.input)
if addr != c.address || name != c.name {
t.Errorf("SplitAddressName(%q): got %q,%q want %q,%q", c.input, addr, name, c.address, c.name)
}
}
}
func BenchmarkSplitAddressName(b *testing.B) {
tests := []string{
"/user@domain.com@host:1234/foo/bar",
"/(dev.v.io/services/mounttabled)@host:1234/foo/bar",
"/@4@tcp@127.0.0.1:22@@@@s@dev.v.io/services/mounttabled@@/foo/bar",
"/@4@tcp@127.0.0.1:22@@@@s@dev.v.io/services/mounttabled,staging.v.io/services/nsroot@@/foo/bar",
}
for i := 0; i < b.N; i++ {
SplitAddressName(tests[i%len(tests)])
}
}
func TestJoinAddressName(t *testing.T) {
cases := []struct {
address, name, joined string
}{
{"", "", ""},
{"", "a", "a"},
{"", "/a", "/a"},
{"", "a", "a"},
{"", "///a", "/a"},
{"/", "", ""},
{"//", "", ""},
{"/a", "", "/a"},
{"//a", "", "/a"},
{"aaa", "", "/aaa"},
{"/aaa", "aa", "/aaa/aa"},
{"ab", "/cd", "/ab/cd"},
{"/ab", "/cd", "/ab/cd"},
{"ab", "//cd", "/ab/cd"},
}
for _, c := range cases {
joined := JoinAddressName(c.address, c.name)
if joined != c.joined {
t.Errorf("JoinAddressName(%q %q): got %q want %q", c.address, c.name, joined, c.joined)
}
}
}
func TestJoin(t *testing.T) {
cases := []struct {
elems []string
joined string
}{
{[]string{}, ""},
{[]string{""}, ""},
{[]string{"", ""}, ""},
{[]string{"a"}, "a"},
{[]string{"a", ""}, "a"},
{[]string{"a/"}, "a"},
{[]string{"a/", ""}, "a"},
{[]string{"a", "/"}, "a"},
{[]string{"", "a"}, "a"},
{[]string{"", "/a"}, "/a"},
{[]string{"a", "b"}, "a/b"},
{[]string{"a/", "b/"}, "a/b"},
{[]string{"a/", "/b"}, "a/b"},
{[]string{"/a", "b"}, "/a/b"},
{[]string{"a", "/", "b"}, "a/b"},
{[]string{"a", "/", "/b"}, "a/b"},
{[]string{"a/", "/", "/b"}, "a/b"},
{[]string{"/a/b", "c"}, "/a/b/c"},
{[]string{"/a", "b", "c"}, "/a/b/c"},
{[]string{"/a/", "/b/", "/c/"}, "/a/b/c"},
{[]string{"a", "b", "c"}, "a/b/c"},
{[]string{"a", "", "c"}, "a/c"},
{[]string{"a", "", "", "c"}, "a/c"},
{[]string{"/a/b", "c/d"}, "/a/b/c/d"},
{[]string{"/a/b", "/c/d"}, "/a/b/c/d"},
{[]string{"/a/b", "//c/d"}, "/a/b/c/d"},
{[]string{"/a//", "c"}, "/a/c"},
{[]string{"/a", "//"}, "/a"},
{[]string{"", "//a/b"}, "/a/b"},
{[]string{"a", "b//"}, "a/b"},
{[]string{"a", "//", "b"}, "a/b"},
{[]string{"a", "//", "/b"}, "a/b"},
{[]string{"a", "//", "//b"}, "a/b"},
{[]string{"a/", "//", "b"}, "a/b"},
{[]string{"a//", "//", "b"}, "a/b"},
{[]string{"a//", "//", "//b"}, "a/b"},
{[]string{"a", "/", "/", "b"}, "a/b"},
{[]string{"a/", "/", "/", "/b"}, "a/b"},
{[]string{"a", "//", "//", "b"}, "a/b"},
{[]string{"a//", "//", "//", "//b"}, "a/b"},
{[]string{"a//", "//b//", "//c//"}, "a/b/c"},
{[]string{"a//", "", "//c//"}, "a/c"},
{[]string{"a///", "////b"}, "a/b"},
{[]string{"////a", "b"}, "/a/b"},
{[]string{"a", "b////"}, "a/b"},
{[]string{"/ep//", ""}, "/ep"},
{[]string{"/ep//", "a"}, "/ep/a"},
{[]string{"/ep//", "//a"}, "/ep/a"},
}
for _, c := range cases {
if got, want := Join(c.elems...), c.joined; want != got {
t.Errorf("Join(%q): got %q want %q", c.elems, got, want)
}
}
}
func TestSplitJoin(t *testing.T) {
cases := []struct {
name, address, relative string
}{
{"/a/b", "a", "b"},
{"/a//b", "a", "b"},
{"/a:10//b/c", "a:10", "b/c"},
{"/a:10/b//c", "a:10", "b/c"},
}
for _, c := range cases {
a, r := SplitAddressName(c.name)
if got, want := a, c.address; got != want {
t.Errorf("%q: got %q, want %q", c.name, got, want)
}
if got, want := r, c.relative; got != want {
t.Errorf("%q: got %q, want %q", c.name, got, want)
}
j := JoinAddressName(a, r)
if got, want := j, Clean(c.name); got != want {
t.Errorf("%q: got %q, want %q", c.name, got, want)
}
}
}
func TestTrimSuffix(t *testing.T) {
cases := []struct {
name, suffix, prefix string
}{
{"", "", ""},
{"a", "", "a"},
{"a", "a", ""},
{"/a", "a", "/a"},
{"a/b", "b", "a"},
{"a/b", "/b", "a/b"},
{"a/b/", "b/", "a"},
{"/a/b", "b", "/a"},
{"/a/b/c", "c", "/a/b"},
{"/a/b/c/d", "c/d", "/a/b"},
{"/a/b//c/d", "c/d", "/a/b"},
{"/a/b//c/d", "/c/d", "/a/b/c/d"},
{"/a/b//c/d", "//c/d", "/a/b/c/d"},
{"//a/b", "//a/b", ""},
{"/a/b", "/a/b", ""},
{"//a", "a", "/a"},
}
for _, c := range cases {
if p := TrimSuffix(c.name, c.suffix); p != c.prefix {
t.Errorf("TrimSuffix(%q, %q): got %q, want %q", c.name, c.suffix, p, c.prefix)
}
}
}
func TestRooted(t *testing.T) {
ep := "/" + FormatEndpoint("tcp", "h:0")
// should be rooted.
cases := []string{
"/",
"/a",
"/a/b",
ep + "/",
}
for _, c := range cases {
if !Rooted(c) {
t.Errorf("Rooted(%q) return false, not true", c)
}
}
cases = []string{
"",
"a",
"b//c",
}
for _, c := range cases {
if Rooted(c) {
t.Errorf("Rooted(%q) return true, not false", c)
}
}
}
func TestClean(t *testing.T) {
cases := []struct {
in, want string
}{
{"", ""},
{"//", "/"},
{"/", "/"},
{"/a//b", "/a/b"},
{"/a//b/", "/a/b"},
{"a//b", "a/b"},
{"a//b/", "a/b"},
{"///a//b/", "/a/b"},
{"a////////b/", "a/b"},
}
for _, c := range cases {
if want, got := c.want, Clean(c.in); got != want {
t.Errorf("Clean(%s) got %q, want %q", c.in, got, want)
}
}
}
func TestEncodeDecode(t *testing.T) {
cases := []struct {
unenc, enc string
}{
{"", ""},
{"/", "%2F"},
{"%", "%25"},
{"/The % rain in /% Spain", "%2FThe %25 rain in %2F%25 Spain"},
{"/%/%", "%2F%25%2F%25"},
{"ᚸӲ읔קAل", "ᚸӲ읔קAل"},
{"ᚸ/Ӳ%읔/ק%A+ل", "ᚸ%2FӲ%25읔%2Fק%25A+ل"},
}
for _, c := range cases {
if want, got := c.enc, EncodeAsNameElement(c.unenc); got != want {
t.Errorf("EncodeAsNameElement(%s) got %q, want %q", c.unenc, got, want)
}
}
for _, c := range cases {
want := c.unenc
got, ok := DecodeFromNameElement(c.enc)
if !ok {
t.Errorf("DecodeFromNameElement(%s) not ok", c.enc)
}
if got != want {
t.Errorf("DecodeFromNameElement(%s) got %q, want %q", c.enc, got, want)
}
}
badEncodings := []string{"%2", "%aqq"}
for _, bad := range badEncodings {
want := bad
got, ok := DecodeFromNameElement(bad)
if ok {
t.Errorf("DecodeFromNameElement(%s) should not be ok", bad)
}
if got != want {
t.Errorf("DecodeFromNameElement(%s) got %q, want %q", bad, got, want)
}
}
}