Watch
1
0
Fork
You've already forked mautrix-whatsapp
0
mirror of https://github.com/mautrix/whatsapp.git synced 2026-08-24 13:04:56 -04:00
mautrix-whatsapp/pkg/connector/voip/group_media_test.go
2026-07-30 05:03:26 +02:00

185 lines
5.9 KiB
Go

package voip
import (
"testing"
"github.com/purpshell/meowcaller"
"go.mau.fi/whatsmeow/types"
)
type recordingGroupVideoSink struct {
frames [][]byte
orientations []int
muted []bool
}
func (s *recordingGroupVideoSink) WriteVideo(frame []byte) error {
s.frames = append(s.frames, append([]byte(nil), frame...))
return nil
}
func (s *recordingGroupVideoSink) SetOrientation(orientation int) {
s.orientations = append(s.orientations, orientation)
}
func (s *recordingGroupVideoSink) setMuted(muted bool) {
s.muted = append(s.muted, muted)
}
func TestWhatsAppVideoRouterKeepsOneStableGroupCamera(t *testing.T) {
camera := &recordingGroupVideoSink{}
screen := &recordingGroupVideoSink{}
router := newWhatsAppVideoRouter(camera, screen, camera.setMuted, screen.setMuted)
alice := types.NewJID("111", types.DefaultUserServer)
bob := types.NewJID("222", types.DefaultUserServer)
router.SetGroupState(meowcaller.GroupCallState{
Participants: []meowcaller.GroupCallParticipant{
{JID: alice, State: "connected"},
{JID: bob, State: "connected"},
},
})
router.WriteParticipantFrame(meowcaller.ParticipantVideoFrame{
ParticipantID: alice.String(),
Sender: alice,
Orientation: 1,
AccessUnit: []byte{0x01},
})
router.WriteParticipantFrame(meowcaller.ParticipantVideoFrame{
ParticipantID: bob.String(),
Sender: bob,
Orientation: 2,
AccessUnit: []byte{0x02},
})
if len(camera.frames) != 1 || camera.frames[0][0] != 0x01 {
t.Fatalf("camera frames = %v, want only the first connected participant", camera.frames)
}
if len(camera.orientations) != 1 || camera.orientations[0] != 1 {
t.Fatalf("camera orientations = %v, want [1]", camera.orientations)
}
}
func TestWhatsAppVideoRouterSelectsCameraByPhoneNumberAlias(t *testing.T) {
camera := &recordingGroupVideoSink{}
screen := &recordingGroupVideoSink{}
router := newWhatsAppVideoRouter(camera, screen, camera.setMuted, screen.setMuted)
aliceLID := types.NewJID("111", types.HiddenUserServer)
alicePN := types.NewJID("15550000001", types.DefaultUserServer)
bobLID := types.NewJID("222", types.HiddenUserServer)
bobPN := types.NewJID("15550000002", types.DefaultUserServer)
router.SetGroupState(meowcaller.GroupCallState{
Participants: []meowcaller.GroupCallParticipant{
{JID: aliceLID, PN: alicePN, State: "connected"},
{JID: bobLID, PN: bobPN, State: "connected"},
},
})
if err := router.SelectCamera(bobPN); err != nil {
t.Fatalf("SelectCamera returned error: %v", err)
}
router.WriteParticipantFrame(meowcaller.ParticipantVideoFrame{
Sender: aliceLID,
AccessUnit: []byte{0x01},
})
router.WriteParticipantFrame(meowcaller.ParticipantVideoFrame{
Sender: bobLID,
AccessUnit: []byte{0x02},
})
if len(camera.frames) != 1 || camera.frames[0][0] != 0x02 {
t.Fatalf("camera frames = %v, want only the selected participant", camera.frames)
}
}
func TestWhatsAppVideoRouterRejectsDisconnectedCameraSelection(t *testing.T) {
router := newWhatsAppVideoRouter(
&recordingGroupVideoSink{},
&recordingGroupVideoSink{},
nil,
nil,
)
router.SetGroupState(meowcaller.GroupCallState{
Participants: []meowcaller.GroupCallParticipant{
{
JID: types.NewJID("111", types.HiddenUserServer),
State: "connected",
},
},
})
if err := router.SelectCamera(types.NewJID("222", types.HiddenUserServer)); err == nil {
t.Fatal("SelectCamera accepted a disconnected participant")
}
}
func TestWhatsAppVideoRouterSeparatesScreenShareFromCamera(t *testing.T) {
camera := &recordingGroupVideoSink{}
screen := &recordingGroupVideoSink{}
router := newWhatsAppVideoRouter(camera, screen, camera.setMuted, screen.setMuted)
alice := types.NewJID("111", types.DefaultUserServer)
router.SetScreenShare(meowcaller.ScreenShareState{Participant: alice, Active: true})
router.WriteParticipantFrame(meowcaller.ParticipantVideoFrame{
ParticipantID: alice.String(),
Sender: alice,
Orientation: 3,
AccessUnit: []byte{0x03},
})
if len(camera.frames) != 0 {
t.Fatalf("camera received screen-share frames: %v", camera.frames)
}
if len(screen.frames) != 1 || screen.frames[0][0] != 0x03 {
t.Fatalf("screen frames = %v, want one screen-share frame", screen.frames)
}
if len(screen.orientations) != 1 || screen.orientations[0] != 3 {
t.Fatalf("screen orientations = %v, want [3]", screen.orientations)
}
if len(screen.muted) == 0 || screen.muted[len(screen.muted)-1] {
t.Fatalf("screen mute transitions = %v, want unmuted", screen.muted)
}
router.SetScreenShare(meowcaller.ScreenShareState{Participant: alice, Active: false})
router.WriteParticipantFrame(meowcaller.ParticipantVideoFrame{
ParticipantID: alice.String(),
Sender: alice,
AccessUnit: []byte{0x04},
})
if len(camera.frames) != 1 || camera.frames[0][0] != 0x04 {
t.Fatalf("camera frames after screen-share stop = %v, want camera frame", camera.frames)
}
if !screen.muted[len(screen.muted)-1] {
t.Fatalf("screen mute transitions = %v, want muted after stop", screen.muted)
}
}
func TestMatrixVideoRouterForwardsOnlyTheActiveSource(t *testing.T) {
var got []byte
router := newMatrixVideoSourceRouter(func(frame LiveKitVideoFrame) error {
got = append(got, frame.AccessUnit...)
return nil
})
if err := router.WriteCamera(LiveKitVideoFrame{AccessUnit: []byte{0x01}}); err != nil {
t.Fatal(err)
}
router.SetScreenSharing(true)
if err := router.WriteCamera(LiveKitVideoFrame{AccessUnit: []byte{0x02}}); err != nil {
t.Fatal(err)
}
if err := router.WriteScreen(LiveKitVideoFrame{AccessUnit: []byte{0x03}}); err != nil {
t.Fatal(err)
}
router.SetScreenSharing(false)
if err := router.WriteScreen(LiveKitVideoFrame{AccessUnit: []byte{0x04}}); err != nil {
t.Fatal(err)
}
if err := router.WriteCamera(LiveKitVideoFrame{AccessUnit: []byte{0x05}}); err != nil {
t.Fatal(err)
}
want := []byte{0x01, 0x03, 0x05}
if string(got) != string(want) {
t.Fatalf("forwarded frames = %v, want %v", got, want)
}
}