Ctrl K
ComunidadGuías…

internal/mtprotoedge/help_legacy_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package mtprotoedge

import (
	"testing"
	"time"

	"github.com/iamxvbaba/td/bin"
	"github.com/iamxvbaba/td/mt"
	"github.com/iamxvbaba/td/proto"
	"github.com/iamxvbaba/td/tg"
)

type trailingHelpTestRequest struct{}

func (*trailingHelpTestRequest) Encode(b *bin.Buffer) error {
	b.PutID(helpTestRequestTypeID)
	b.PutID(0xdeadbeef)
	return nil
}

func (*trailingHelpTestRequest) Decode(b *bin.Buffer) error {
	if err := b.ConsumeID(helpTestRequestTypeID); err != nil {
		return err
	}
	_, err := b.ID()
	return err
}

// TestHelpTestLegacyTerminal verifies that the removed help.test#c0e202f7 = Bool
// method is answered with a fixed boolTrue both bare and along the official
// invokeWithLayer/initConnection wrapper path, and that the connection survives.
func TestHelpTestLegacyTerminal(t *testing.T) {
	tests := []struct {
		name    string
		layer   int
		wrapped bool
	}{
		{name: "bare"},
		{name: "layer227_wrapped", layer: 227, wrapped: true},
		{name: "layer228_wrapped", layer: 228, wrapped: true},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			const dc = 2
			addr, pub, _ := startTestServer(t, Options{DC: dc, LayerRPC: newAdmissionOnlyLayerRPC()})
			conn, auth, cipher := dialHandshake(t, addr, dc, pub)

			var request bin.Encoder = &helpTestRequest{}
			if test.wrapped {
				request = &tg.InvokeWithLayerRequest{
					Layer: test.layer,
					Query: &tg.InitConnectionRequest{
						APIID: 1, DeviceModel: "help-test", SystemVersion: "test",
						AppVersion: "test", SystemLangCode: "en", LangCode: "en",
						Query: &helpTestRequest{},
					},
				}
			}
			clientMsgID := proto.NewMessageIDGen(time.Now)
			reqMsgID := clientMsgID.New(proto.MessageFromClient)
			sendEncrypted(t, conn, cipher, auth, reqMsgID, request)

			replies := collectReplies(t, conn, cipher, auth.AuthKey, proto.ResultTypeID)
			assertHelpTestRPCResult(t, mustHave(t, replies, proto.ResultTypeID, "help.test rpc_result"), reqMsgID)

			pingMsgID := clientMsgID.New(proto.MessageFromClient)
			sendEncryptedWithSeq(t, conn, cipher, auth, pingMsgID, 3, &mt.PingRequest{PingID: 97})
			pongReplies := collectReplies(t, conn, cipher, auth.AuthKey, mt.PongTypeID)
			var pong mt.Pong
			if err := pong.Decode(mustHave(t, pongReplies, mt.PongTypeID, "pong after help.test")); err != nil {
				t.Fatalf("decode pong after help.test: %v", err)
			}
			if pong.MsgID != pingMsgID || pong.PingID != 97 {
				t.Fatalf("pong after help.test = %+v", pong)
			}
		})
	}
}

// TestWrappedHelpTestTrailingBytesRejected keeps the compatibility terminal
// exactly one word: trailing bytes stay a correlated INPUT_REQUEST_INVALID.
func TestWrappedHelpTestTrailingBytesRejected(t *testing.T) {
	const dc = 2
	addr, pub, _ := startTestServer(t, Options{DC: dc, LayerRPC: newAdmissionOnlyLayerRPC()})
	conn, auth, cipher := dialHandshake(t, addr, dc, pub)
	reqMsgID := proto.NewMessageIDGen(time.Now).New(proto.MessageFromClient)
	request := &tg.InvokeWithLayerRequest{
		Layer: 228,
		Query: &tg.InitConnectionRequest{
			APIID: 1, DeviceModel: "malformed-help-test", SystemVersion: "test",
			AppVersion: "test", SystemLangCode: "en", LangCode: "en",
			Query: &trailingHelpTestRequest{},
		},
	}
	sendEncrypted(t, conn, cipher, auth, reqMsgID, request)

	replies := collectReplies(t, conn, cipher, auth.AuthKey, proto.ResultTypeID)
	var result proto.Result
	if err := result.Decode(mustHave(t, replies, proto.ResultTypeID, "malformed help.test rpc_result")); err != nil {
		t.Fatalf("decode malformed help.test rpc_result: %v", err)
	}
	if result.RequestMessageID != reqMsgID {
		t.Fatalf("malformed help.test req_msg_id = %d, want %d", result.RequestMessageID, reqMsgID)
	}
	var rpcErr mt.RPCError
	if err := rpcErr.Decode(&bin.Buffer{Buf: result.Result}); err != nil {
		t.Fatalf("decode malformed help.test RPC error: %v", err)
	}
	if rpcErr.ErrorCode != 400 || rpcErr.ErrorMessage != "INPUT_REQUEST_INVALID" {
		t.Fatalf("malformed help.test RPC error = %+v", rpcErr)
	}
}

func assertHelpTestRPCResult(t *testing.T, b *bin.Buffer, reqMsgID int64) {
	t.Helper()
	var result proto.Result
	if err := result.Decode(b); err != nil {
		t.Fatalf("decode help.test rpc_result: %v", err)
	}
	if result.RequestMessageID != reqMsgID {
		t.Fatalf("help.test rpc_result.req_msg_id = %d, want %d", result.RequestMessageID, reqMsgID)
	}
	inner := &bin.Buffer{Buf: result.Result}
	innerID, err := inner.PeekID()
	if err != nil {
		t.Fatalf("peek help.test rpc_result inner: %v", err)
	}
	if innerID != boolTrueTypeID || inner.Len() != bin.Word {
		t.Fatalf("help.test rpc_result inner = %#x/%d bytes, want %#x/%d", innerID, inner.Len(), boolTrueTypeID, bin.Word)
	}
}