move gotd fork into repo. (#111)
- 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
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user