owpengram-server/internal/rpc/send_media_geo_test.go

234 lines
7.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package rpc
import (
"bytes"
"context"
"testing"
"github.com/gotd/td/tg"
"github.com/gotd/td/tgerr"
)
func TestSendMediaPrivateGeoPoint(t *testing.T) {
ctx := context.Background()
r, owner, friend := newMediaTestRouter(t)
point := &tg.InputGeoPoint{Lat: 39.9042, Long: 116.4074}
point.SetAccuracyRadius(30) // gotd flag 字段必须 Set*() 置 flag 位,直接赋字段 getter 读不到
updates, err := r.onMessagesSendMedia(WithUserID(ctx, owner.ID), &tg.MessagesSendMediaRequest{
Peer: &tg.InputPeerUser{UserID: friend.ID, AccessHash: friend.AccessHash},
Media: &tg.InputMediaGeoPoint{GeoPoint: point},
RandomID: 2001,
})
if err != nil {
t.Fatalf("sendMedia geo: %v", err)
}
msg := newMessageFromUpdates(t, updates)
media, ok := msg.Media.(*tg.MessageMediaGeo)
if !ok {
t.Fatalf("expected MessageMediaGeo, got %T", msg.Media)
}
geo, ok := media.Geo.(*tg.GeoPoint)
if !ok {
t.Fatalf("expected tg.GeoPoint, got %T", media.Geo)
}
if geo.Lat != 39.9042 || geo.Long != 116.4074 {
t.Errorf("geo = (%v, %v), want (39.9042, 116.4074)", geo.Lat, geo.Long)
}
if geo.AccessHash == 0 {
t.Error("geo access_hash should be non-zero (clients echo it to upload.getWebFile)")
}
if radius, ok := geo.GetAccuracyRadius(); !ok || radius != 30 {
t.Errorf("accuracy_radius = %d (%v), want 30", radius, ok)
}
}
func TestSendMediaGeoPointOutOfRange(t *testing.T) {
ctx := context.Background()
r, owner, friend := newMediaTestRouter(t)
for _, point := range []*tg.InputGeoPoint{
{Lat: 90.5, Long: 0},
{Lat: -91, Long: 0},
{Lat: 0, Long: 180.01},
{Lat: 0, Long: -181},
} {
_, err := r.onMessagesSendMedia(WithUserID(ctx, owner.ID), &tg.MessagesSendMediaRequest{
Peer: &tg.InputPeerUser{UserID: friend.ID, AccessHash: friend.AccessHash},
Media: &tg.InputMediaGeoPoint{GeoPoint: point},
RandomID: 2002,
})
if err == nil || !tgerr.Is(err, "MEDIA_INVALID") {
t.Errorf("geo (%v,%v): err = %v, want MEDIA_INVALID", point.Lat, point.Long, err)
}
}
}
func TestSendMediaGeoPointEmpty(t *testing.T) {
ctx := context.Background()
r, owner, friend := newMediaTestRouter(t)
_, err := r.onMessagesSendMedia(WithUserID(ctx, owner.ID), &tg.MessagesSendMediaRequest{
Peer: &tg.InputPeerUser{UserID: friend.ID, AccessHash: friend.AccessHash},
Media: &tg.InputMediaGeoPoint{GeoPoint: &tg.InputGeoPointEmpty{}},
RandomID: 2003,
})
if err == nil || !tgerr.Is(err, "MEDIA_EMPTY") {
t.Fatalf("err = %v, want MEDIA_EMPTY", err)
}
}
func TestSendMediaPrivateVenue(t *testing.T) {
ctx := context.Background()
r, owner, friend := newMediaTestRouter(t)
updates, err := r.onMessagesSendMedia(WithUserID(ctx, owner.ID), &tg.MessagesSendMediaRequest{
Peer: &tg.InputPeerUser{UserID: friend.ID, AccessHash: friend.AccessHash},
Media: &tg.InputMediaVenue{
GeoPoint: &tg.InputGeoPoint{Lat: 31.2304, Long: 121.4737},
Title: "People's Square",
Address: "Huangpu, Shanghai",
Provider: "foursquare",
VenueID: "4b5b3c4ff964a520fd0029e3",
VenueType: "arts_entertainment/default",
},
RandomID: 2004,
})
if err != nil {
t.Fatalf("sendMedia venue: %v", err)
}
msg := newMessageFromUpdates(t, updates)
media, ok := msg.Media.(*tg.MessageMediaVenue)
if !ok {
t.Fatalf("expected MessageMediaVenue, got %T", msg.Media)
}
if media.Title != "People's Square" || media.Address != "Huangpu, Shanghai" ||
media.Provider != "foursquare" || media.VenueID != "4b5b3c4ff964a520fd0029e3" ||
media.VenueType != "arts_entertainment/default" {
t.Fatalf("venue media = %+v, want preserved venue payload", media)
}
geo, ok := media.Geo.(*tg.GeoPoint)
if !ok || geo.Lat != 31.2304 || geo.Long != 121.4737 {
t.Fatalf("venue geo = %#v, want (31.2304, 121.4737)", media.Geo)
}
}
func TestSendMediaVenueWithoutTitle(t *testing.T) {
ctx := context.Background()
r, owner, friend := newMediaTestRouter(t)
_, err := r.onMessagesSendMedia(WithUserID(ctx, owner.ID), &tg.MessagesSendMediaRequest{
Peer: &tg.InputPeerUser{UserID: friend.ID, AccessHash: friend.AccessHash},
Media: &tg.InputMediaVenue{
GeoPoint: &tg.InputGeoPoint{Lat: 1, Long: 1},
Title: " ",
},
RandomID: 2005,
})
if err == nil || !tgerr.Is(err, "MEDIA_EMPTY") {
t.Fatalf("err = %v, want MEDIA_EMPTY", err)
}
}
func TestSendMediaPrivateDiceValueRanges(t *testing.T) {
ctx := context.Background()
r, owner, friend := newMediaTestRouter(t)
cases := []struct {
emoticon string
want string
max int
}{
{"\U0001F3B2", "\U0001F3B2", 6}, // 🎲
{"\U0001F3AF", "\U0001F3AF", 6}, // 🎯
{"\U0001F3B3", "\U0001F3B3", 6}, // 🎳
{"\U0001F3C0", "\U0001F3C0", 5}, // 🏀
{"⚽", "⚽", 5}, // 裸足球
{"⚽️", "⚽", 5}, // 带 U+FE0F 变体,须归一
{"\U0001F3B0", "\U0001F3B0", 64}, // 🎰
}
randomID := int64(3000)
for _, tc := range cases {
// 多抽几次覆盖取值边界value 必须始终落在 [1, max]。
for i := 0; i < 8; i++ {
randomID++
updates, err := r.onMessagesSendMedia(WithUserID(ctx, owner.ID), &tg.MessagesSendMediaRequest{
Peer: &tg.InputPeerUser{UserID: friend.ID, AccessHash: friend.AccessHash},
Media: &tg.InputMediaDice{Emoticon: tc.emoticon},
RandomID: randomID,
})
if err != nil {
t.Fatalf("sendMedia dice %q: %v", tc.emoticon, err)
}
msg := newMessageFromUpdates(t, updates)
media, ok := msg.Media.(*tg.MessageMediaDice)
if !ok {
t.Fatalf("expected MessageMediaDice, got %T", msg.Media)
}
if media.Emoticon != tc.want {
t.Fatalf("dice emoticon = %q, want %q", media.Emoticon, tc.want)
}
if media.Value < 1 || media.Value > tc.max {
t.Fatalf("dice %q value = %d, want in [1, %d]", tc.emoticon, media.Value, tc.max)
}
}
}
}
func TestSendMediaDiceUnknownEmoticon(t *testing.T) {
ctx := context.Background()
r, owner, friend := newMediaTestRouter(t)
_, err := r.onMessagesSendMedia(WithUserID(ctx, owner.ID), &tg.MessagesSendMediaRequest{
Peer: &tg.InputPeerUser{UserID: friend.ID, AccessHash: friend.AccessHash},
Media: &tg.InputMediaDice{Emoticon: "\U0001F600"},
RandomID: 3100,
})
if err == nil || !tgerr.Is(err, "EMOTICON_INVALID") {
t.Fatalf("err = %v, want EMOTICON_INVALID", err)
}
}
func TestUploadGetWebFileGeoTile(t *testing.T) {
ctx := context.Background()
r, owner, _ := newMediaTestRouter(t)
req := &tg.UploadGetWebFileRequest{
Location: &tg.InputWebFileGeoPointLocation{
GeoPoint: &tg.InputGeoPoint{Lat: 39.9, Long: 116.4},
AccessHash: 12345,
W: 100, H: 100, Zoom: 15, Scale: 1,
},
Offset: 0,
Limit: 1 << 17,
}
file, err := r.onUploadGetWebFile(WithUserID(ctx, owner.ID), req)
if err != nil {
t.Fatalf("getWebFile: %v", err)
}
if file.Size != 12 || len(file.Bytes) != 12 {
t.Fatalf("size = %d bytes = %d, want 12/12 (fake tile)", file.Size, len(file.Bytes))
}
if file.MimeType != "image/png" {
t.Errorf("mime = %q, want image/png", file.MimeType)
}
// offset 续传按字节切片size 始终是全量大小。
req.Offset = 4
req.Limit = 4
chunk, err := r.onUploadGetWebFile(WithUserID(ctx, owner.ID), req)
if err != nil {
t.Fatalf("getWebFile offset: %v", err)
}
if chunk.Size != 12 || !bytes.Equal(chunk.Bytes, []byte{0x0D, 0x0A, 0x1A, 0x0A}) {
t.Fatalf("offset chunk = %v (size %d), want bytes 4..8 of tile", chunk.Bytes, chunk.Size)
}
// URL 形态当前无来源,必须显式拒绝而非静默。
if _, err := r.onUploadGetWebFile(WithUserID(ctx, owner.ID), &tg.UploadGetWebFileRequest{
Location: &tg.InputWebFileLocation{URL: "https://example.com/a.png", AccessHash: 1},
Limit: 4096,
}); err == nil || !tgerr.Is(err, "LOCATION_INVALID") {
t.Fatalf("url webfile err = %v, want LOCATION_INVALID", err)
}
}