7a04f298d2
- update to latest telegram layer - remove some references to fields in tg.Entities that don't exist in the schema - originally added here: https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e - referenced here - https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3 - https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
198 lines
4.4 KiB
Go
198 lines
4.4 KiB
Go
package codec
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
"testing/iotest"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.mau.fi/mautrix-telegram/pkg/gotd/bin"
|
|
"go.mau.fi/mautrix-telegram/pkg/gotd/testutil"
|
|
)
|
|
|
|
type codecTest struct {
|
|
name string
|
|
align int
|
|
create func() Codec
|
|
}
|
|
|
|
func codecs() []codecTest {
|
|
return []codecTest{
|
|
{"Abridged", 4, func() Codec {
|
|
return Abridged{}
|
|
}},
|
|
{"Intermediate", 4, func() Codec {
|
|
return Intermediate{}
|
|
}},
|
|
{"PaddedIntermediate", 4, func() Codec {
|
|
return PaddedIntermediate{}
|
|
}},
|
|
{"Full", 0, func() Codec {
|
|
return &Full{}
|
|
}},
|
|
{"NoHeaderIntermediate", 0, func() Codec {
|
|
return NoHeader{Codec: Intermediate{}}
|
|
}},
|
|
}
|
|
}
|
|
|
|
type payload struct {
|
|
name string
|
|
testData string
|
|
mustFail bool
|
|
readTestOnly bool
|
|
}
|
|
|
|
func payloads() []payload {
|
|
var code [4]byte
|
|
binary.LittleEndian.PutUint32(code[:], CodeTransportFlood)
|
|
return []payload{
|
|
{"Empty", "", true, false},
|
|
{"Protocol error", string(code[:]), true, true},
|
|
{"Small 8b", "abcdabcd", false, false},
|
|
{"Medium 1kb", strings.Repeat("a", 1024), false, false},
|
|
}
|
|
}
|
|
|
|
func testGood(c codecTest, p payload) func(t *testing.T) {
|
|
return func(t *testing.T) {
|
|
t.Run("One message", func(t *testing.T) {
|
|
a := require.New(t)
|
|
codec := c.create()
|
|
buf := bytes.NewBuffer(nil)
|
|
payload := &bin.Buffer{Buf: []byte(p.testData)}
|
|
|
|
l := payload.Len()
|
|
// Encode
|
|
a.NoError(codec.Write(buf, payload))
|
|
a.Equal(l, payload.Len(), "Codec must not change buffer length")
|
|
|
|
// Decode
|
|
payload.Reset()
|
|
a.NoError(codec.Read(buf, payload))
|
|
a.Equal(p.testData, string(payload.Buf))
|
|
})
|
|
|
|
t.Run("Two messages", func(t *testing.T) {
|
|
a := require.New(t)
|
|
codec := c.create()
|
|
buf := bytes.NewBuffer(nil)
|
|
payload := &bin.Buffer{Buf: []byte(p.testData)}
|
|
|
|
l := payload.Len()
|
|
// Encode twice
|
|
a.NoError(codec.Write(buf, payload))
|
|
payload.ResetTo([]byte(p.testData))
|
|
a.NoError(codec.Write(buf, payload))
|
|
a.Equal(l, payload.Len(), "Codec must not change buffer length")
|
|
|
|
// Decode twice
|
|
payload.Reset()
|
|
a.NoError(codec.Read(buf, payload))
|
|
a.Equal(p.testData, string(payload.Buf))
|
|
payload.Reset()
|
|
a.NoError(codec.Read(buf, payload))
|
|
a.Equal(p.testData, string(payload.Buf))
|
|
})
|
|
}
|
|
}
|
|
|
|
func testBad(c codecTest, p payload) func(t *testing.T) {
|
|
return func(t *testing.T) {
|
|
if !p.readTestOnly {
|
|
t.Run("Write", func(t *testing.T) {
|
|
payload := &bin.Buffer{Buf: []byte(p.testData)}
|
|
require.Error(t, c.create().Write(io.Discard, payload))
|
|
})
|
|
}
|
|
|
|
t.Run("Read", func(t *testing.T) {
|
|
reader := bytes.NewBufferString(p.testData)
|
|
require.Error(t, c.create().Read(reader, &bin.Buffer{}))
|
|
})
|
|
}
|
|
}
|
|
|
|
func testHeaderTag(c codecTest) func(t *testing.T) {
|
|
e := io.ErrClosedPipe
|
|
return func(t *testing.T) {
|
|
t.Run("GoodTag", func(t *testing.T) {
|
|
a := require.New(t)
|
|
buf := bytes.NewBuffer(nil)
|
|
a.NoError(c.create().WriteHeader(buf))
|
|
a.NoError(c.create().ReadHeader(buf))
|
|
})
|
|
|
|
if tagged, ok := c.create().(TaggedCodec); ok {
|
|
t.Run("ReadError", func(t *testing.T) {
|
|
r := iotest.ErrReader(e)
|
|
require.ErrorIs(t, c.create().ReadHeader(r), e)
|
|
})
|
|
t.Run("WriteError", func(t *testing.T) {
|
|
w := testutil.ErrWriter(e)
|
|
require.ErrorIs(t, c.create().WriteHeader(w), e)
|
|
})
|
|
t.Run("BadTag", func(t *testing.T) {
|
|
tag := tagged.ObfuscatedTag()
|
|
buf := bytes.NewBuffer(tag[:])
|
|
tag[0] = 0
|
|
require.ErrorIs(t, c.create().ReadHeader(buf), ErrProtocolHeaderMismatch)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func testCodec(c codecTest) func(t *testing.T) {
|
|
e := io.ErrClosedPipe
|
|
|
|
return func(t *testing.T) {
|
|
t.Run("ReadError", func(t *testing.T) {
|
|
r := iotest.ErrReader(e)
|
|
require.ErrorIs(t, c.create().Read(r, &bin.Buffer{}), e)
|
|
})
|
|
|
|
t.Run("WriteError", func(t *testing.T) {
|
|
w := testutil.ErrWriter(e)
|
|
require.ErrorIs(t,
|
|
c.create().Write(
|
|
w,
|
|
&bin.Buffer{Buf: make([]byte, 16)},
|
|
),
|
|
e,
|
|
)
|
|
})
|
|
|
|
if c.align != 0 {
|
|
t.Run("AlignError", func(t *testing.T) {
|
|
require.Error(t,
|
|
c.create().Write(
|
|
io.Discard,
|
|
&bin.Buffer{Buf: make([]byte, c.align-1)},
|
|
),
|
|
)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCodecs(t *testing.T) {
|
|
for _, c := range codecs() {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
for _, p := range payloads() {
|
|
if p.mustFail {
|
|
t.Run(p.name, testBad(c, p))
|
|
} else {
|
|
t.Run(p.name, testGood(c, p))
|
|
}
|
|
}
|
|
|
|
t.Run("Header", testHeaderTag(c))
|
|
testCodec(c)(t)
|
|
})
|
|
}
|
|
}
|