mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 15:16:51 +08:00
improve coverage
This commit is contained in:
@@ -183,15 +183,6 @@ func TestAuthenticateRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthenticateWrite(t *testing.T) {
|
|
||||||
for _, ca := range casesAuthenticate {
|
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
|
||||||
vout := ca.h.Write()
|
|
||||||
require.Equal(t, ca.vout, vout)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAutenticatehReadErrors(t *testing.T) {
|
func TestAutenticatehReadErrors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
@@ -231,3 +222,12 @@ func TestAutenticatehReadErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuthenticateWrite(t *testing.T) {
|
||||||
|
for _, ca := range casesAuthenticate {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
vout := ca.h.Write()
|
||||||
|
require.Equal(t, ca.vout, vout)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -60,15 +60,6 @@ func TestAuthorizationRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAuthorizationWrite(t *testing.T) {
|
|
||||||
for _, ca := range casesAuthorization {
|
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
|
||||||
vout := ca.h.Write()
|
|
||||||
require.Equal(t, ca.vout, vout)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAuthorizationReadErrors(t *testing.T) {
|
func TestAuthorizationReadErrors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
@@ -113,3 +104,12 @@ func TestAuthorizationReadErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuthorizationWrite(t *testing.T) {
|
||||||
|
for _, ca := range casesAuthorization {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
vout := ca.h.Write()
|
||||||
|
require.Equal(t, ca.vout, vout)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -132,15 +132,6 @@ func TestRangeRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRangeWrite(t *testing.T) {
|
|
||||||
for _, ca := range casesRange {
|
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
|
||||||
req := ca.h.Write()
|
|
||||||
require.Equal(t, ca.vout, req)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRangeReadErrors(t *testing.T) {
|
func TestRangeReadErrors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
@@ -270,3 +261,12 @@ func TestRangeReadErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRangeWrite(t *testing.T) {
|
||||||
|
for _, ca := range casesRange {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
req := ca.h.Write()
|
||||||
|
require.Equal(t, ca.vout, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -178,15 +178,6 @@ func TestRTPInfoRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRTPInfoWrite(t *testing.T) {
|
|
||||||
for _, ca := range casesRTPInfo {
|
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
|
||||||
req := ca.h.Write()
|
|
||||||
require.Equal(t, ca.vout, req)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRTPInfoReadErrors(t *testing.T) {
|
func TestRTPInfoReadErrors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
@@ -231,3 +222,12 @@ func TestRTPInfoReadErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRTPInfoWrite(t *testing.T) {
|
||||||
|
for _, ca := range casesRTPInfo {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
req := ca.h.Write()
|
||||||
|
require.Equal(t, ca.vout, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -59,15 +59,6 @@ func TestSessionRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSessionWrite(t *testing.T) {
|
|
||||||
for _, ca := range casesSession {
|
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
|
||||||
req := ca.h.Write()
|
|
||||||
require.Equal(t, ca.vout, req)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSessionReadErrors(t *testing.T) {
|
func TestSessionReadErrors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
@@ -102,3 +93,12 @@ func TestSessionReadErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSessionWrite(t *testing.T) {
|
||||||
|
for _, ca := range casesSession {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
req := ca.h.Write()
|
||||||
|
require.Equal(t, ca.vout, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -168,15 +168,6 @@ func TestTransportRead(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransportWrite(t *testing.T) {
|
|
||||||
for _, ca := range casesTransport {
|
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
|
||||||
req := ca.h.Write()
|
|
||||||
require.Equal(t, ca.vout, req)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTransportReadErrors(t *testing.T) {
|
func TestTransportReadErrors(t *testing.T) {
|
||||||
for _, ca := range []struct {
|
for _, ca := range []struct {
|
||||||
name string
|
name string
|
||||||
@@ -271,3 +262,12 @@ func TestTransportReadErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTransportWrite(t *testing.T) {
|
||||||
|
for _, ca := range casesTransport {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
req := ca.h.Write()
|
||||||
|
require.Equal(t, ca.vout, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -131,7 +131,7 @@ func (e *Encoder) writeFragmented(au []byte, pts time.Duration) ([][]byte, error
|
|||||||
copy(data[4:], au[:le])
|
copy(data[4:], au[:le])
|
||||||
au = au[le:]
|
au = au[le:]
|
||||||
|
|
||||||
rpkt := rtp.Packet{
|
frame, err := (&rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
Version: rtpVersion,
|
Version: rtpVersion,
|
||||||
PayloadType: e.payloadType,
|
PayloadType: e.payloadType,
|
||||||
@@ -141,14 +141,13 @@ func (e *Encoder) writeFragmented(au []byte, pts time.Duration) ([][]byte, error
|
|||||||
Marker: (i == (packetCount - 1)),
|
Marker: (i == (packetCount - 1)),
|
||||||
},
|
},
|
||||||
Payload: data,
|
Payload: data,
|
||||||
}
|
}).Marshal()
|
||||||
e.sequenceNumber++
|
|
||||||
|
|
||||||
frame, err := rpkt.Marshal()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.sequenceNumber++
|
||||||
|
|
||||||
ret[i] = frame
|
ret[i] = frame
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +189,7 @@ func (e *Encoder) writeAggregated(aus [][]byte, firstPTS time.Duration) ([][]byt
|
|||||||
pos += auLen
|
pos += auLen
|
||||||
}
|
}
|
||||||
|
|
||||||
rpkt := rtp.Packet{
|
frame, err := (&rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
Version: rtpVersion,
|
Version: rtpVersion,
|
||||||
PayloadType: e.payloadType,
|
PayloadType: e.payloadType,
|
||||||
@@ -200,13 +199,12 @@ func (e *Encoder) writeAggregated(aus [][]byte, firstPTS time.Duration) ([][]byt
|
|||||||
Marker: true,
|
Marker: true,
|
||||||
},
|
},
|
||||||
Payload: payload,
|
Payload: payload,
|
||||||
}
|
}).Marshal()
|
||||||
e.sequenceNumber++
|
|
||||||
|
|
||||||
frame, err := rpkt.Marshal()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.sequenceNumber++
|
||||||
|
|
||||||
return [][]byte{frame}, nil
|
return [][]byte{frame}, nil
|
||||||
}
|
}
|
||||||
|
@@ -213,20 +213,6 @@ var cases = []struct {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncode(t *testing.T) {
|
|
||||||
for _, ca := range cases {
|
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
|
||||||
sequenceNumber := uint16(0x44ed)
|
|
||||||
ssrc := uint32(0x9dbb7812)
|
|
||||||
initialTs := uint32(0x88776655)
|
|
||||||
e := NewEncoder(96, 48000, &sequenceNumber, &ssrc, &initialTs)
|
|
||||||
enc, err := e.Encode(ca.aus, ca.pts)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, ca.enc, enc)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecode(t *testing.T) {
|
func TestDecode(t *testing.T) {
|
||||||
for _, ca := range cases {
|
for _, ca := range cases {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
@@ -424,3 +410,21 @@ func TestDecodeErrors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEncode(t *testing.T) {
|
||||||
|
for _, ca := range cases {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
sequenceNumber := uint16(0x44ed)
|
||||||
|
ssrc := uint32(0x9dbb7812)
|
||||||
|
initialTs := uint32(0x88776655)
|
||||||
|
e := NewEncoder(96, 48000, &sequenceNumber, &ssrc, &initialTs)
|
||||||
|
enc, err := e.Encode(ca.aus, ca.pts)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, ca.enc, enc)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodeRandomInitialState(t *testing.T) {
|
||||||
|
NewEncoder(96, 48000, nil, nil, nil)
|
||||||
|
}
|
||||||
|
@@ -106,7 +106,7 @@ func (e *Encoder) writeBatch(nalus [][]byte, pts time.Duration, marker bool) ([]
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) writeSingle(nalu []byte, pts time.Duration, marker bool) ([][]byte, error) {
|
func (e *Encoder) writeSingle(nalu []byte, pts time.Duration, marker bool) ([][]byte, error) {
|
||||||
rpkt := rtp.Packet{
|
frame, err := (&rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
Version: rtpVersion,
|
Version: rtpVersion,
|
||||||
PayloadType: e.payloadType,
|
PayloadType: e.payloadType,
|
||||||
@@ -116,14 +116,13 @@ func (e *Encoder) writeSingle(nalu []byte, pts time.Duration, marker bool) ([][]
|
|||||||
Marker: marker,
|
Marker: marker,
|
||||||
},
|
},
|
||||||
Payload: nalu,
|
Payload: nalu,
|
||||||
}
|
}).Marshal()
|
||||||
e.sequenceNumber++
|
|
||||||
|
|
||||||
frame, err := rpkt.Marshal()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.sequenceNumber++
|
||||||
|
|
||||||
return [][]byte{frame}, nil
|
return [][]byte{frame}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +163,7 @@ func (e *Encoder) writeFragmented(nalu []byte, pts time.Duration, marker bool) (
|
|||||||
copy(data[2:], nalu[:le])
|
copy(data[2:], nalu[:le])
|
||||||
nalu = nalu[le:]
|
nalu = nalu[le:]
|
||||||
|
|
||||||
rpkt := rtp.Packet{
|
frame, err := (&rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
Version: rtpVersion,
|
Version: rtpVersion,
|
||||||
PayloadType: e.payloadType,
|
PayloadType: e.payloadType,
|
||||||
@@ -174,14 +173,13 @@ func (e *Encoder) writeFragmented(nalu []byte, pts time.Duration, marker bool) (
|
|||||||
Marker: (i == (packetCount-1) && marker),
|
Marker: (i == (packetCount-1) && marker),
|
||||||
},
|
},
|
||||||
Payload: data,
|
Payload: data,
|
||||||
}
|
}).Marshal()
|
||||||
e.sequenceNumber++
|
|
||||||
|
|
||||||
frame, err := rpkt.Marshal()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.sequenceNumber++
|
||||||
|
|
||||||
ret[i] = frame
|
ret[i] = frame
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +220,7 @@ func (e *Encoder) writeAggregated(nalus [][]byte, pts time.Duration, marker bool
|
|||||||
pos += naluLen
|
pos += naluLen
|
||||||
}
|
}
|
||||||
|
|
||||||
rpkt := rtp.Packet{
|
frame, err := (&rtp.Packet{
|
||||||
Header: rtp.Header{
|
Header: rtp.Header{
|
||||||
Version: rtpVersion,
|
Version: rtpVersion,
|
||||||
PayloadType: e.payloadType,
|
PayloadType: e.payloadType,
|
||||||
@@ -232,13 +230,12 @@ func (e *Encoder) writeAggregated(nalus [][]byte, pts time.Duration, marker bool
|
|||||||
Marker: marker,
|
Marker: marker,
|
||||||
},
|
},
|
||||||
Payload: payload,
|
Payload: payload,
|
||||||
}
|
}).Marshal()
|
||||||
e.sequenceNumber++
|
|
||||||
|
|
||||||
frame, err := rpkt.Marshal()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.sequenceNumber++
|
||||||
|
|
||||||
return [][]byte{frame}, nil
|
return [][]byte{frame}, nil
|
||||||
}
|
}
|
||||||
|
12
pkg/rtph264/nalutype_test.go
Normal file
12
pkg/rtph264/nalutype_test.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package rtph264
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNALUType(t *testing.T) {
|
||||||
|
require.NotEqual(t, "unknown", naluType(10).String())
|
||||||
|
require.Equal(t, "unknown", naluType(50).String())
|
||||||
|
}
|
@@ -2,6 +2,7 @@ package rtph264
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -219,20 +220,6 @@ var cases = []struct {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncode(t *testing.T) {
|
|
||||||
for _, ca := range cases {
|
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
|
||||||
sequenceNumber := uint16(0x44ed)
|
|
||||||
ssrc := uint32(0x9dbb7812)
|
|
||||||
initialTs := uint32(0x88776655)
|
|
||||||
e := NewEncoder(96, &sequenceNumber, &ssrc, &initialTs)
|
|
||||||
enc, err := e.Encode(ca.nalus, ca.pts)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, ca.enc, enc)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecode(t *testing.T) {
|
func TestDecode(t *testing.T) {
|
||||||
for _, ca := range cases {
|
for _, ca := range cases {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
@@ -458,10 +445,36 @@ func TestDecodeErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type funcReader func(p []byte) (int, error)
|
func TestEncode(t *testing.T) {
|
||||||
|
for _, ca := range cases {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
sequenceNumber := uint16(0x44ed)
|
||||||
|
ssrc := uint32(0x9dbb7812)
|
||||||
|
initialTs := uint32(0x88776655)
|
||||||
|
e := NewEncoder(96, &sequenceNumber, &ssrc, &initialTs)
|
||||||
|
enc, err := e.Encode(ca.nalus, ca.pts)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, ca.enc, enc)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (f funcReader) Read(p []byte) (int, error) {
|
func TestEncodeRandomInitialState(t *testing.T) {
|
||||||
return f(p)
|
NewEncoder(96, nil, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
type dummyReader struct {
|
||||||
|
byts [][]byte
|
||||||
|
i int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *dummyReader) Read(p []byte) (int, error) {
|
||||||
|
if f.i >= len(f.byts) {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
n := copy(p, f.byts[f.i])
|
||||||
|
f.i++
|
||||||
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadSPSPPS(t *testing.T) {
|
func TestReadSPSPPS(t *testing.T) {
|
||||||
@@ -491,17 +504,43 @@ func TestReadSPSPPS(t *testing.T) {
|
|||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(ca.name, func(t *testing.T) {
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
i := 0
|
sps, pps, err := NewDecoder().ReadSPSPPS(&dummyReader{byts: ca.byts})
|
||||||
f := funcReader(func(p []byte) (int, error) {
|
|
||||||
n := copy(p, ca.byts[i])
|
|
||||||
i++
|
|
||||||
return n, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
sps, pps, err := NewDecoder().ReadSPSPPS(f)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, ca.sps, sps)
|
require.Equal(t, ca.sps, sps)
|
||||||
require.Equal(t, ca.pps, pps)
|
require.Equal(t, ca.pps, pps)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadSPSPPSErrors(t *testing.T) {
|
||||||
|
for _, ca := range []struct {
|
||||||
|
name string
|
||||||
|
byts [][]byte
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
[][]byte{},
|
||||||
|
"EOF",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"more packets needed, then empty",
|
||||||
|
[][]byte{
|
||||||
|
mergeBytes(
|
||||||
|
[]byte{
|
||||||
|
0x80, 0x60, 0x44, 0xed, 0x88, 0x77, 0x79, 0xab,
|
||||||
|
0x9d, 0xbb, 0x78, 0x12, 0x1c, 0x85,
|
||||||
|
},
|
||||||
|
bytes.Repeat([]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 182),
|
||||||
|
[]byte{0x00, 0x01},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"EOF",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(ca.name, func(t *testing.T) {
|
||||||
|
_, _, err := NewDecoder().ReadSPSPPS(&dummyReader{byts: ca.byts})
|
||||||
|
require.Equal(t, ca.err, err.Error())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user