1 Star 0 Fork 0

ap6108/fasthttp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
args_test.go 14.29 KB
一键复制 编辑 原始数据 按行查看 历史
Erik Dubbelboer 提交于 2020-12-26 16:53 . Make argsKV more predictable
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
package fasthttp
import (
"bytes"
"fmt"
"net/url"
"reflect"
"strings"
"testing"
"time"
"github.com/valyala/bytebufferpool"
)
func TestDecodeArgAppend(t *testing.T) {
t.Parallel()
testDecodeArgAppend(t, "", "")
testDecodeArgAppend(t, "foobar", "foobar")
testDecodeArgAppend(t, "тест", "тест")
testDecodeArgAppend(t, "a%", "a%")
testDecodeArgAppend(t, "%a%21", "%a!")
testDecodeArgAppend(t, "ab%test", "ab%test")
testDecodeArgAppend(t, "d%тестF", "d%тестF")
testDecodeArgAppend(t, "a%\xffb%20c", "a%\xffb c")
testDecodeArgAppend(t, "foo%20bar", "foo bar")
testDecodeArgAppend(t, "f.o%2C1%3A2%2F4=%7E%60%21%40%23%24%25%5E%26*%28%29_-%3D%2B%5C%7C%2F%5B%5D%7B%7D%3B%3A%27%22%3C%3E%2C.%2F%3F",
"f.o,1:2/4=~`!@#$%^&*()_-=+\\|/[]{};:'\"<>,./?")
}
func testDecodeArgAppend(t *testing.T, s, expectedResult string) {
result := decodeArgAppend(nil, []byte(s))
if string(result) != expectedResult {
t.Fatalf("unexpected decodeArgAppend(%q)=%q; expecting %q", s, result, expectedResult)
}
}
func TestArgsAdd(t *testing.T) {
t.Parallel()
var a Args
a.Add("foo", "bar")
a.Add("foo", "baz")
a.Add("foo", "1")
a.Add("ba", "23")
a.Add("foo", "")
a.AddNoValue("foo")
if a.Len() != 6 {
t.Fatalf("unexpected number of elements: %d. Expecting 6", a.Len())
}
s := a.String()
expectedS := "foo=bar&foo=baz&foo=1&ba=23&foo=&foo"
if s != expectedS {
t.Fatalf("unexpected result: %q. Expecting %q", s, expectedS)
}
a.Sort(bytes.Compare)
ss := a.String()
expectedSS := "ba=23&foo=&foo&foo=1&foo=bar&foo=baz"
if ss != expectedSS {
t.Fatalf("unexpected result: %q. Expecting %q", ss, expectedSS)
}
var a1 Args
a1.Parse(s)
if a1.Len() != 6 {
t.Fatalf("unexpected number of elements: %d. Expecting 6", a.Len())
}
var barFound, bazFound, oneFound, emptyFound1, emptyFound2, baFound bool
a1.VisitAll(func(k, v []byte) {
switch string(k) {
case "foo":
switch string(v) {
case "bar":
barFound = true
case "baz":
bazFound = true
case "1":
oneFound = true
case "":
if emptyFound1 {
emptyFound2 = true
} else {
emptyFound1 = true
}
default:
t.Fatalf("unexpected value %q", v)
}
case "ba":
if string(v) != "23" {
t.Fatalf("unexpected value: %q. Expecting %q", v, "23")
}
baFound = true
default:
t.Fatalf("unexpected key found %q", k)
}
})
if !barFound || !bazFound || !oneFound || !emptyFound1 || !emptyFound2 || !baFound {
t.Fatalf("something is missing: %v, %v, %v, %v, %v, %v", barFound, bazFound, oneFound, emptyFound1, emptyFound2, baFound)
}
}
func TestArgsAcquireReleaseSequential(t *testing.T) {
testArgsAcquireRelease(t)
}
func TestArgsAcquireReleaseConcurrent(t *testing.T) {
ch := make(chan struct{}, 10)
for i := 0; i < 10; i++ {
go func() {
testArgsAcquireRelease(t)
ch <- struct{}{}
}()
}
for i := 0; i < 10; i++ {
select {
case <-ch:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
}
func testArgsAcquireRelease(t *testing.T) {
a := AcquireArgs()
for i := 0; i < 10; i++ {
k := fmt.Sprintf("key_%d", i)
v := fmt.Sprintf("value_%d", i*3+123)
a.Set(k, v)
}
s := a.String()
a.Reset()
a.Parse(s)
for i := 0; i < 10; i++ {
k := fmt.Sprintf("key_%d", i)
expectedV := fmt.Sprintf("value_%d", i*3+123)
v := a.Peek(k)
if string(v) != expectedV {
t.Fatalf("unexpected value %q for key %q. Expecting %q", v, k, expectedV)
}
}
ReleaseArgs(a)
}
func TestArgsPeekMulti(t *testing.T) {
t.Parallel()
var a Args
a.Parse("foo=123&bar=121&foo=321&foo=&barz=sdf")
vv := a.PeekMulti("foo")
expectedVV := [][]byte{
[]byte("123"),
[]byte("321"),
[]byte(nil),
}
if !reflect.DeepEqual(vv, expectedVV) {
t.Fatalf("unexpected vv\n%#v\nExpecting\n%#v\n", vv, expectedVV)
}
vv = a.PeekMulti("aaaa")
if len(vv) > 0 {
t.Fatalf("expecting empty result for non-existing key. Got %#v", vv)
}
vv = a.PeekMulti("bar")
expectedVV = [][]byte{[]byte("121")}
if !reflect.DeepEqual(vv, expectedVV) {
t.Fatalf("unexpected vv\n%#v\nExpecting\n%#v\n", vv, expectedVV)
}
}
func TestArgsEscape(t *testing.T) {
t.Parallel()
testArgsEscape(t, "foo", "bar", "foo=bar")
// Test all characters
k := "f.o,1:2/4"
var v = make([]byte, 256)
for i := 0; i < 256; i++ {
v[i] = byte(i)
}
u := url.Values{}
u.Add(k, string(v))
testArgsEscape(t, k, string(v), u.Encode())
}
func testArgsEscape(t *testing.T, k, v, expectedS string) {
var a Args
a.Set(k, v)
s := a.String()
if s != expectedS {
t.Fatalf("unexpected args %q. Expecting %q. k=%q, v=%q", s, expectedS, k, v)
}
}
func TestPathEscape(t *testing.T) {
t.Parallel()
testPathEscape(t, "/foo/bar")
testPathEscape(t, "")
testPathEscape(t, "/")
testPathEscape(t, "//")
testPathEscape(t, "*") // See https://github.com/golang/go/issues/11202
// Test all characters
var pathSegment = make([]byte, 256)
for i := 0; i < 256; i++ {
pathSegment[i] = byte(i)
}
testPathEscape(t, "/foo/"+string(pathSegment))
}
func testPathEscape(t *testing.T, s string) {
u := url.URL{Path: s}
expectedS := u.EscapedPath()
res := string(appendQuotedPath(nil, []byte(s)))
if res != expectedS {
t.Fatalf("unexpected args %q. Expecting %q.", res, expectedS)
}
}
func TestArgsWriteTo(t *testing.T) {
t.Parallel()
s := "foo=bar&baz=123&aaa=bbb"
var a Args
a.Parse(s)
var w bytebufferpool.ByteBuffer
n, err := a.WriteTo(&w)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if n != int64(len(s)) {
t.Fatalf("unexpected n: %d. Expecting %d", n, len(s))
}
result := string(w.B)
if result != s {
t.Fatalf("unexpected result %q. Expecting %q", result, s)
}
}
func TestArgsGetBool(t *testing.T) {
t.Parallel()
testArgsGetBool(t, "", false)
testArgsGetBool(t, "0", false)
testArgsGetBool(t, "n", false)
testArgsGetBool(t, "no", false)
testArgsGetBool(t, "1", true)
testArgsGetBool(t, "y", true)
testArgsGetBool(t, "yes", true)
testArgsGetBool(t, "123", false)
testArgsGetBool(t, "foobar", false)
}
func testArgsGetBool(t *testing.T, value string, expectedResult bool) {
var a Args
a.Parse("v=" + value)
result := a.GetBool("v")
if result != expectedResult {
t.Fatalf("unexpected result %v. Expecting %v for value %q", result, expectedResult, value)
}
}
func TestArgsUint(t *testing.T) {
t.Parallel()
var a Args
a.SetUint("foo", 123)
a.SetUint("bar", 0)
a.SetUint("aaaa", 34566)
expectedS := "foo=123&bar=0&aaaa=34566"
s := string(a.QueryString())
if s != expectedS {
t.Fatalf("unexpected args %q. Expecting %q", s, expectedS)
}
if a.GetUintOrZero("foo") != 123 {
t.Fatalf("unexpected arg value %d. Expecting %d", a.GetUintOrZero("foo"), 123)
}
if a.GetUintOrZero("bar") != 0 {
t.Fatalf("unexpected arg value %d. Expecting %d", a.GetUintOrZero("bar"), 0)
}
if a.GetUintOrZero("aaaa") != 34566 {
t.Fatalf("unexpected arg value %d. Expecting %d", a.GetUintOrZero("aaaa"), 34566)
}
if string(a.Peek("foo")) != "123" {
t.Fatalf("unexpected arg value %q. Expecting %q", a.Peek("foo"), "123")
}
if string(a.Peek("bar")) != "0" {
t.Fatalf("unexpected arg value %q. Expecting %q", a.Peek("bar"), "0")
}
if string(a.Peek("aaaa")) != "34566" {
t.Fatalf("unexpected arg value %q. Expecting %q", a.Peek("aaaa"), "34566")
}
}
func TestArgsCopyTo(t *testing.T) {
t.Parallel()
var a Args
// empty args
testCopyTo(t, &a)
a.Set("foo", "bar")
testCopyTo(t, &a)
a.Set("xxx", "yyy")
a.AddNoValue("ba")
testCopyTo(t, &a)
a.Del("foo")
testCopyTo(t, &a)
}
func testCopyTo(t *testing.T, a *Args) {
keys := make(map[string]struct{})
a.VisitAll(func(k, v []byte) {
keys[string(k)] = struct{}{}
})
var b Args
a.CopyTo(&b)
if !reflect.DeepEqual(*a, b) { //nolint
t.Fatalf("ArgsCopyTo fail, a: \n%+v\nb: \n%+v\n", *a, b) //nolint
}
b.VisitAll(func(k, v []byte) {
if _, ok := keys[string(k)]; !ok {
t.Fatalf("unexpected key %q after copying from %q", k, a.String())
}
delete(keys, string(k))
})
if len(keys) > 0 {
t.Fatalf("missing keys %#v after copying from %q", keys, a.String())
}
}
func TestArgsVisitAll(t *testing.T) {
t.Parallel()
var a Args
a.Set("foo", "bar")
i := 0
a.VisitAll(func(k, v []byte) {
if string(k) != "foo" {
t.Fatalf("unexpected key %q. Expected %q", k, "foo")
}
if string(v) != "bar" {
t.Fatalf("unexpected value %q. Expected %q", v, "bar")
}
i++
})
if i != 1 {
t.Fatalf("unexpected number of VisitAll calls: %d. Expected %d", i, 1)
}
}
func TestArgsStringCompose(t *testing.T) {
t.Parallel()
var a Args
a.Set("foo", "bar")
a.Set("aa", "bbb")
a.Set("привет", "мир")
a.SetNoValue("bb")
a.Set("", "xxxx")
a.Set("cvx", "")
a.SetNoValue("novalue")
expectedS := "foo=bar&aa=bbb&%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82=%D0%BC%D0%B8%D1%80&bb&=xxxx&cvx=&novalue"
s := a.String()
if s != expectedS {
t.Fatalf("Unexpected string %q. Exected %q", s, expectedS)
}
}
func TestArgsString(t *testing.T) {
t.Parallel()
var a Args
testArgsString(t, &a, "")
testArgsString(t, &a, "foobar")
testArgsString(t, &a, "foo=bar")
testArgsString(t, &a, "foo=bar&baz=sss")
testArgsString(t, &a, "")
testArgsString(t, &a, "f+o=x.x%2A-_8x%D0%BF%D1%80%D0%B8%D0%B2%D0%B5aaa&sdf=ss")
testArgsString(t, &a, "=asdfsdf")
}
func testArgsString(t *testing.T, a *Args, s string) {
a.Parse(s)
s1 := a.String()
if s != s1 {
t.Fatalf("Unexpected args %q. Expected %q", s1, s)
}
}
func TestArgsSetGetDel(t *testing.T) {
t.Parallel()
var a Args
if len(a.Peek("foo")) > 0 {
t.Fatalf("Unexpected value: %q", a.Peek("foo"))
}
if len(a.Peek("")) > 0 {
t.Fatalf("Unexpected value: %q", a.Peek(""))
}
a.Del("xxx")
for j := 0; j < 3; j++ {
for i := 0; i < 10; i++ {
k := fmt.Sprintf("foo%d", i)
v := fmt.Sprintf("bar_%d", i)
a.Set(k, v)
if string(a.Peek(k)) != v {
t.Fatalf("Unexpected value: %q. Expected %q", a.Peek(k), v)
}
}
}
for i := 0; i < 10; i++ {
k := fmt.Sprintf("foo%d", i)
v := fmt.Sprintf("bar_%d", i)
if string(a.Peek(k)) != v {
t.Fatalf("Unexpected value: %q. Expected %q", a.Peek(k), v)
}
a.Del(k)
if string(a.Peek(k)) != "" {
t.Fatalf("Unexpected value: %q. Expected %q", a.Peek(k), "")
}
}
a.Parse("aaa=xxx&bb=aa")
if string(a.Peek("foo0")) != "" {
t.Fatalf("Unexpected value %q", a.Peek("foo0"))
}
if string(a.Peek("aaa")) != "xxx" {
t.Fatalf("Unexpected value %q. Expected %q", a.Peek("aaa"), "xxx")
}
if string(a.Peek("bb")) != "aa" {
t.Fatalf("Unexpected value %q. Expected %q", a.Peek("bb"), "aa")
}
for i := 0; i < 10; i++ {
k := fmt.Sprintf("xx%d", i)
v := fmt.Sprintf("yy%d", i)
a.Set(k, v)
if string(a.Peek(k)) != v {
t.Fatalf("Unexpected value: %q. Expected %q", a.Peek(k), v)
}
}
for i := 5; i < 10; i++ {
k := fmt.Sprintf("xx%d", i)
v := fmt.Sprintf("yy%d", i)
if string(a.Peek(k)) != v {
t.Fatalf("Unexpected value: %q. Expected %q", a.Peek(k), v)
}
a.Del(k)
if string(a.Peek(k)) != "" {
t.Fatalf("Unexpected value: %q. Expected %q", a.Peek(k), "")
}
}
}
func TestArgsParse(t *testing.T) {
t.Parallel()
var a Args
// empty args
testArgsParse(t, &a, "", 0, "foo=", "bar=", "=")
// arg without value
testArgsParse(t, &a, "foo1", 1, "foo=", "bar=", "=")
// arg without value, but with equal sign
testArgsParse(t, &a, "foo2=", 1, "foo=", "bar=", "=")
// arg with value
testArgsParse(t, &a, "foo3=bar1", 1, "foo3=bar1", "bar=", "=")
// empty key
testArgsParse(t, &a, "=bar2", 1, "foo=", "=bar2", "bar2=")
// missing kv
testArgsParse(t, &a, "&&&&", 0, "foo=", "bar=", "=")
// multiple values with the same key
testArgsParse(t, &a, "x=1&x=2&x=3", 3, "x=1")
// multiple args
testArgsParse(t, &a, "&&&qw=er&tyx=124&&&zxc_ss=2234&&", 3, "qw=er", "tyx=124", "zxc_ss=2234")
// multiple args without values
testArgsParse(t, &a, "&&a&&b&&bar&baz", 4, "a=", "b=", "bar=", "baz=")
// values with '='
testArgsParse(t, &a, "zz=1&k=v=v=a=a=s", 2, "k=v=v=a=a=s", "zz=1")
// mixed '=' and '&'
testArgsParse(t, &a, "sss&z=dsf=&df", 3, "sss=", "z=dsf=", "df=")
// encoded args
testArgsParse(t, &a, "f+o%20o=%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82+test", 1, "f o o=привет test")
// invalid percent encoding
testArgsParse(t, &a, "f%=x&qw%z=d%0k%20p&%%20=%%%20x", 3, "f%=x", "qw%z=d%0k p", "% =%% x")
// special chars
testArgsParse(t, &a, "a.b,c:d/e=f.g,h:i/q", 1, "a.b,c:d/e=f.g,h:i/q")
}
func TestArgsHas(t *testing.T) {
t.Parallel()
var a Args
// single arg
testArgsHas(t, &a, "foo", "foo")
testArgsHasNot(t, &a, "foo", "bar", "baz", "")
// multi args without values
testArgsHas(t, &a, "foo&bar", "foo", "bar")
testArgsHasNot(t, &a, "foo&bar", "", "aaaa")
// multi args
testArgsHas(t, &a, "b=xx&=aaa&c=", "b", "", "c")
testArgsHasNot(t, &a, "b=xx&=aaa&c=", "xx", "aaa", "foo")
// encoded args
testArgsHas(t, &a, "a+b=c+d%20%20e", "a b")
testArgsHasNot(t, &a, "a+b=c+d", "a+b", "c+d")
}
func testArgsHas(t *testing.T, a *Args, s string, expectedKeys ...string) {
a.Parse(s)
for _, key := range expectedKeys {
if !a.Has(key) {
t.Fatalf("Missing key %q in %q", key, s)
}
}
}
func testArgsHasNot(t *testing.T, a *Args, s string, unexpectedKeys ...string) {
a.Parse(s)
for _, key := range unexpectedKeys {
if a.Has(key) {
t.Fatalf("Unexpected key %q in %q", key, s)
}
}
}
func testArgsParse(t *testing.T, a *Args, s string, expectedLen int, expectedArgs ...string) {
a.Parse(s)
if a.Len() != expectedLen {
t.Fatalf("Unexpected args len %d. Expected %d. s=%q", a.Len(), expectedLen, s)
}
for _, xx := range expectedArgs {
tmp := strings.SplitN(xx, "=", 2)
k := tmp[0]
v := tmp[1]
buf := a.Peek(k)
if string(buf) != v {
t.Fatalf("Unexpected value for key=%q: %q. Expected %q. s=%q", k, buf, v, s)
}
}
}
func TestArgsDeleteAll(t *testing.T) {
t.Parallel()
var a Args
a.Add("q1", "foo")
a.Add("q1", "bar")
a.Add("q1", "baz")
a.Add("q1", "quux")
a.Add("q2", "1234")
a.Del("q1")
if a.Len() != 1 || a.Has("q1") {
t.Fatalf("Expected q1 arg to be completely deleted. Current Args: %s", a.String())
}
}
func TestIssue932(t *testing.T) {
t.Parallel()
var a []argsKV
a = setArg(a, "t1", "ok", argsHasValue)
a = setArg(a, "t2", "", argsHasValue)
a = setArg(a, "t1", "", argsHasValue)
a = setArgBytes(a, s2b("t3"), []byte{}, argsHasValue)
a = setArgBytes(a, s2b("t4"), nil, argsHasValue)
if peekArgStr(a, "t1") == nil {
t.Error("nil not expected for t1")
}
if peekArgStr(a, "t2") == nil {
t.Error("nil not expected for t2")
}
if peekArgStr(a, "t3") == nil {
t.Error("nil not expected for t3")
}
if peekArgStr(a, "t4") != nil {
t.Error("nil expected for t4")
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/ap6108/fasthttp.git
git@gitee.com:ap6108/fasthttp.git
ap6108
fasthttp
fasthttp
master

搜索帮助

D67c1975 1850385 1daf7b77 1850385