mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 15:16:51 +08:00
headers: merge parsing of key-values
This commit is contained in:
@@ -49,36 +49,6 @@ type Auth struct {
|
|||||||
Algorithm *string
|
Algorithm *string
|
||||||
}
|
}
|
||||||
|
|
||||||
func findValue(v0 string) (string, string, error) {
|
|
||||||
if v0 == "" {
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if v0[0] == '"' {
|
|
||||||
i := 1
|
|
||||||
for {
|
|
||||||
if i >= len(v0) {
|
|
||||||
return "", "", fmt.Errorf("apices not closed (%v)", v0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if v0[i] == '"' {
|
|
||||||
return v0[1:i], v0[i+1:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for {
|
|
||||||
if i >= len(v0) || v0[i] == ',' {
|
|
||||||
return v0[:i], v0[i:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read decodes an Authenticate or a WWW-Authenticate header.
|
// Read decodes an Authenticate or a WWW-Authenticate header.
|
||||||
func (h *Auth) Read(v base.HeaderValue) error {
|
func (h *Auth) Read(v base.HeaderValue) error {
|
||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
@@ -93,10 +63,11 @@ func (h *Auth) Read(v base.HeaderValue) error {
|
|||||||
|
|
||||||
i := strings.IndexByte(v0, ' ')
|
i := strings.IndexByte(v0, ' ')
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return fmt.Errorf("unable to find method (%s)", v0)
|
return fmt.Errorf("unable to split between method and keys (%v)", v)
|
||||||
}
|
}
|
||||||
|
method, v0 := v0[:i], v0[i+1:]
|
||||||
|
|
||||||
switch v0[:i] {
|
switch method {
|
||||||
case "Basic":
|
case "Basic":
|
||||||
h.Method = AuthBasic
|
h.Method = AuthBasic
|
||||||
|
|
||||||
@@ -104,62 +75,45 @@ func (h *Auth) Read(v base.HeaderValue) error {
|
|||||||
h.Method = AuthDigest
|
h.Method = AuthDigest
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid method (%s)", v0[:i])
|
return fmt.Errorf("invalid method (%s)", method)
|
||||||
}
|
}
|
||||||
v0 = v0[i+1:]
|
|
||||||
|
|
||||||
for len(v0) > 0 {
|
kvs, err := keyValParse(v0, ',')
|
||||||
i := strings.IndexByte(v0, '=')
|
if err != nil {
|
||||||
if i < 0 {
|
return err
|
||||||
return fmt.Errorf("unable to find key (%s)", v0)
|
}
|
||||||
}
|
|
||||||
var key string
|
|
||||||
key, v0 = v0[:i], v0[i+1:]
|
|
||||||
|
|
||||||
var val string
|
for k, rv := range kvs {
|
||||||
var err error
|
v := rv
|
||||||
val, v0, err = findValue(v0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch key {
|
switch k {
|
||||||
case "username":
|
case "username":
|
||||||
h.Username = &val
|
h.Username = &v
|
||||||
|
|
||||||
case "realm":
|
case "realm":
|
||||||
h.Realm = &val
|
h.Realm = &v
|
||||||
|
|
||||||
case "nonce":
|
case "nonce":
|
||||||
h.Nonce = &val
|
h.Nonce = &v
|
||||||
|
|
||||||
case "uri":
|
case "uri":
|
||||||
h.URI = &val
|
h.URI = &v
|
||||||
|
|
||||||
case "response":
|
case "response":
|
||||||
h.Response = &val
|
h.Response = &v
|
||||||
|
|
||||||
case "opaque":
|
case "opaque":
|
||||||
h.Opaque = &val
|
h.Opaque = &v
|
||||||
|
|
||||||
case "stale":
|
case "stale":
|
||||||
h.Stale = &val
|
h.Stale = &v
|
||||||
|
|
||||||
case "algorithm":
|
case "algorithm":
|
||||||
h.Algorithm = &val
|
h.Algorithm = &v
|
||||||
|
|
||||||
|
default:
|
||||||
// ignore non-standard keys
|
// ignore non-standard keys
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip comma
|
|
||||||
if len(v0) > 0 && v0[0] == ',' {
|
|
||||||
v0 = v0[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip spaces
|
|
||||||
for len(v0) > 0 && v0[0] == ' ' {
|
|
||||||
v0 = v0[1:]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@@ -173,21 +173,51 @@ var casesAuth = []struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthRead(t *testing.T) {
|
func TestAuthRead(t *testing.T) {
|
||||||
for _, c := range casesAuth {
|
for _, ca := range casesAuth {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
var h Auth
|
var h Auth
|
||||||
err := h.Read(c.vin)
|
err := h.Read(ca.vin)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, c.h, h)
|
require.Equal(t, ca.h, h)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAuthReadError(t *testing.T) {
|
||||||
|
for _, ca := range []struct {
|
||||||
|
name string
|
||||||
|
hv base.HeaderValue
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
base.HeaderValue{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"2 values",
|
||||||
|
base.HeaderValue{"a", "b"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"no keys",
|
||||||
|
base.HeaderValue{"Basic"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid method",
|
||||||
|
base.HeaderValue{"Testing key1=val1"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
var h Auth
|
||||||
|
err := h.Read(ca.hv)
|
||||||
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthWrite(t *testing.T) {
|
func TestAuthWrite(t *testing.T) {
|
||||||
for _, c := range casesAuth {
|
for _, ca := range casesAuth {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
vout := c.h.Write()
|
vout := ca.h.Write()
|
||||||
require.Equal(t, c.vout, vout)
|
require.Equal(t, ca.vout, vout)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
70
pkg/headers/keyval.go
Normal file
70
pkg/headers/keyval.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package headers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func findValue(str string, separator byte) (string, string, error) {
|
||||||
|
if str == "" {
|
||||||
|
return "", "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if str[0] == '"' {
|
||||||
|
i := 1
|
||||||
|
for {
|
||||||
|
if i >= len(str) {
|
||||||
|
return "", "", fmt.Errorf("apices not closed (%v)", str)
|
||||||
|
}
|
||||||
|
|
||||||
|
if str[i] == '"' {
|
||||||
|
return str[1:i], str[i+1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
if i >= len(str) || str[i] == separator {
|
||||||
|
return str[:i], str[i:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyValParse(str string, separator byte) (map[string]string, error) {
|
||||||
|
ret := make(map[string]string)
|
||||||
|
|
||||||
|
for len(str) > 0 {
|
||||||
|
i := strings.IndexByte(str, '=')
|
||||||
|
if i < 0 {
|
||||||
|
return nil, fmt.Errorf("unable to find key")
|
||||||
|
}
|
||||||
|
var k string
|
||||||
|
k, str = str[:i], str[i+1:]
|
||||||
|
|
||||||
|
var v string
|
||||||
|
var err error
|
||||||
|
v, str, err = findValue(str, separator)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret[k] = v
|
||||||
|
|
||||||
|
// skip separator
|
||||||
|
if len(str) > 0 && str[0] == separator {
|
||||||
|
str = str[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip spaces
|
||||||
|
for len(str) > 0 && str[0] == ' ' {
|
||||||
|
str = str[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
64
pkg/headers/keyval_test.go
Normal file
64
pkg/headers/keyval_test.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package headers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
var casesKeyVal = []struct {
|
||||||
|
name string
|
||||||
|
s string
|
||||||
|
kvs map[string]string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"base",
|
||||||
|
`key1=v1,key2=v2`,
|
||||||
|
map[string]string{
|
||||||
|
"key1": "v1",
|
||||||
|
"key2": "v2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with space",
|
||||||
|
`key1=v1, key2=v2`,
|
||||||
|
map[string]string{
|
||||||
|
"key1": "v1",
|
||||||
|
"key2": "v2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with apices",
|
||||||
|
`key1="v1", key2=v2`,
|
||||||
|
map[string]string{
|
||||||
|
"key1": "v1",
|
||||||
|
"key2": "v2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with apices and comma",
|
||||||
|
`key1="v,1", key2="v2"`,
|
||||||
|
map[string]string{
|
||||||
|
"key1": "v,1",
|
||||||
|
"key2": "v2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"with apices and equal",
|
||||||
|
`key1="v=1", key2="v2"`,
|
||||||
|
map[string]string{
|
||||||
|
"key1": "v=1",
|
||||||
|
"key2": "v2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKeyValParse(t *testing.T) {
|
||||||
|
for _, ca := range casesKeyVal {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
kvs, err := keyValParse(ca.s, ',')
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, ca.kvs, kvs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -34,13 +34,12 @@ func (h *RTPInfo) Read(v base.HeaderValue) error {
|
|||||||
// remove leading spaces
|
// remove leading spaces
|
||||||
part = strings.TrimLeft(part, " ")
|
part = strings.TrimLeft(part, " ")
|
||||||
|
|
||||||
for _, kv := range strings.Split(part, ";") {
|
kvs, err := keyValParse(part, ';')
|
||||||
tmp := strings.SplitN(kv, "=", 2)
|
if err != nil {
|
||||||
if len(tmp) != 2 {
|
return err
|
||||||
return fmt.Errorf("unable to parse key-value (%v)", kv)
|
}
|
||||||
}
|
|
||||||
k, v := tmp[0], tmp[1]
|
|
||||||
|
|
||||||
|
for k, v := range kvs {
|
||||||
switch k {
|
switch k {
|
||||||
case "url":
|
case "url":
|
||||||
e.URL = v
|
e.URL = v
|
||||||
|
@@ -168,21 +168,43 @@ var casesRTPInfo = []struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRTPInfoRead(t *testing.T) {
|
func TestRTPInfoRead(t *testing.T) {
|
||||||
for _, c := range casesRTPInfo {
|
for _, ca := range casesRTPInfo {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
var h RTPInfo
|
var h RTPInfo
|
||||||
err := h.Read(c.vin)
|
err := h.Read(ca.vin)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, c.h, h)
|
require.Equal(t, ca.h, h)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRTPInfoReadError(t *testing.T) {
|
||||||
|
for _, ca := range []struct {
|
||||||
|
name string
|
||||||
|
hv base.HeaderValue
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
base.HeaderValue{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"2 values",
|
||||||
|
base.HeaderValue{"a", "b"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
var h RTPInfo
|
||||||
|
err := h.Read(ca.hv)
|
||||||
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRTPInfoWrite(t *testing.T) {
|
func TestRTPInfoWrite(t *testing.T) {
|
||||||
for _, c := range casesRTPInfo {
|
for _, ca := range casesRTPInfo {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
req := c.h.Write()
|
req := ca.h.Write()
|
||||||
require.Equal(t, c.vout, req)
|
require.Equal(t, ca.vout, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,23 +27,25 @@ func (h *Session) Read(v base.HeaderValue) error {
|
|||||||
return fmt.Errorf("value provided multiple times (%v)", v)
|
return fmt.Errorf("value provided multiple times (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.Split(v[0], ";")
|
v0 := v[0]
|
||||||
if len(parts) == 0 {
|
|
||||||
return fmt.Errorf("invalid value (%v)", v)
|
i := strings.IndexByte(v0, ';')
|
||||||
|
if i < 0 {
|
||||||
|
h.Session = v0
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
h.Session = parts[0]
|
h.Session = v0[:i]
|
||||||
|
v0 = v0[i+1:]
|
||||||
|
|
||||||
for _, kv := range parts[1:] {
|
v0 = strings.TrimLeft(v0, " ")
|
||||||
// remove leading spaces
|
|
||||||
kv = strings.TrimLeft(kv, " ")
|
|
||||||
|
|
||||||
tmp := strings.SplitN(kv, "=", 2)
|
kvs, err := keyValParse(v0, ';')
|
||||||
if len(tmp) != 2 {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to parse key-value (%v)", kv)
|
return err
|
||||||
}
|
}
|
||||||
k, v := tmp[0], tmp[1]
|
|
||||||
|
|
||||||
|
for k, v := range kvs {
|
||||||
switch k {
|
switch k {
|
||||||
case "timeout":
|
case "timeout":
|
||||||
iv, err := strconv.ParseUint(v, 10, 64)
|
iv, err := strconv.ParseUint(v, 10, 64)
|
||||||
|
@@ -49,21 +49,43 @@ var casesSession = []struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSessionRead(t *testing.T) {
|
func TestSessionRead(t *testing.T) {
|
||||||
for _, c := range casesSession {
|
for _, ca := range casesSession {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
var h Session
|
var h Session
|
||||||
err := h.Read(c.vin)
|
err := h.Read(ca.vin)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, c.h, h)
|
require.Equal(t, ca.h, h)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSessionReadError(t *testing.T) {
|
||||||
|
for _, ca := range []struct {
|
||||||
|
name string
|
||||||
|
hv base.HeaderValue
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
base.HeaderValue{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"2 values",
|
||||||
|
base.HeaderValue{"a", "b"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
var h Session
|
||||||
|
err := h.Read(ca.hv)
|
||||||
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSessionWrite(t *testing.T) {
|
func TestSessionWrite(t *testing.T) {
|
||||||
for _, c := range casesSession {
|
for _, ca := range casesSession {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
req := c.h.Write()
|
req := ca.h.Write()
|
||||||
require.Equal(t, c.vout, req)
|
require.Equal(t, ca.vout, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -99,12 +99,17 @@ func (h *Transport) Read(v base.HeaderValue) error {
|
|||||||
return fmt.Errorf("value provided multiple times (%v)", v)
|
return fmt.Errorf("value provided multiple times (%v)", v)
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.Split(v[0], ";")
|
v0 := v[0]
|
||||||
if len(parts) == 0 {
|
|
||||||
return fmt.Errorf("invalid value (%v)", v)
|
var part string
|
||||||
|
i := strings.IndexByte(v0, ';')
|
||||||
|
if i >= 0 {
|
||||||
|
part, v0 = v0[:i], v0[i+1:]
|
||||||
|
} else {
|
||||||
|
part, v0 = v0, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
switch parts[0] {
|
switch part {
|
||||||
case "RTP/AVP", "RTP/AVP/UDP":
|
case "RTP/AVP", "RTP/AVP/UDP":
|
||||||
h.Protocol = base.StreamProtocolUDP
|
h.Protocol = base.StreamProtocolUDP
|
||||||
|
|
||||||
@@ -114,28 +119,35 @@ func (h *Transport) Read(v base.HeaderValue) error {
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid protocol (%v)", v)
|
return fmt.Errorf("invalid protocol (%v)", v)
|
||||||
}
|
}
|
||||||
parts = parts[1:]
|
|
||||||
|
|
||||||
switch parts[0] {
|
i = strings.IndexByte(v0, ';')
|
||||||
|
if i >= 0 {
|
||||||
|
part, v0 = v0[:i], v0[i+1:]
|
||||||
|
} else {
|
||||||
|
part, v0 = v0, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
switch part {
|
||||||
case "unicast":
|
case "unicast":
|
||||||
v := base.StreamDeliveryUnicast
|
v := base.StreamDeliveryUnicast
|
||||||
h.Delivery = &v
|
h.Delivery = &v
|
||||||
parts = parts[1:]
|
|
||||||
|
|
||||||
case "multicast":
|
case "multicast":
|
||||||
v := base.StreamDeliveryMulticast
|
v := base.StreamDeliveryMulticast
|
||||||
h.Delivery = &v
|
h.Delivery = &v
|
||||||
parts = parts[1:]
|
|
||||||
|
|
||||||
// cast is optional, do not return any error
|
default:
|
||||||
|
// cast is optional, go back
|
||||||
|
v0 = part + ";" + v0
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, kv := range parts {
|
kvs, err := keyValParse(v0, ';')
|
||||||
tmp := strings.SplitN(kv, "=", 2)
|
if err != nil {
|
||||||
if len(tmp) != 2 {
|
return err
|
||||||
return fmt.Errorf("unable to parse key-value (%v)", kv)
|
}
|
||||||
}
|
|
||||||
k, v := tmp[0], tmp[1]
|
for k, rv := range kvs {
|
||||||
|
v := rv
|
||||||
|
|
||||||
switch k {
|
switch k {
|
||||||
case "destination":
|
case "destination":
|
||||||
|
@@ -114,21 +114,43 @@ var casesTransport = []struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTransportRead(t *testing.T) {
|
func TestTransportRead(t *testing.T) {
|
||||||
for _, c := range casesTransport {
|
for _, ca := range casesTransport {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
var h Transport
|
var h Transport
|
||||||
err := h.Read(c.vin)
|
err := h.Read(ca.vin)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, c.h, h)
|
require.Equal(t, ca.h, h)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTransportReadError(t *testing.T) {
|
||||||
|
for _, ca := range []struct {
|
||||||
|
name string
|
||||||
|
hv base.HeaderValue
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
base.HeaderValue{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"2 values",
|
||||||
|
base.HeaderValue{"a", "b"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
var h Transport
|
||||||
|
err := h.Read(ca.hv)
|
||||||
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransportWrite(t *testing.T) {
|
func TestTransportWrite(t *testing.T) {
|
||||||
for _, c := range casesTransport {
|
for _, ca := range casesTransport {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
req := c.h.Write()
|
req := ca.h.Write()
|
||||||
require.Equal(t, c.vout, req)
|
require.Equal(t, ca.vout, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user