adding server test
This commit is contained in:
@@ -195,7 +195,7 @@ func (ints *Server) BuildVideoRoomRequestMessage(users []string, expiry uint64)
|
|||||||
Username: users[idx],
|
Username: users[idx],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg.VideoData.Credentials = videocreds
|
msg.VideoData = &meowlib.VideoData{Credentials: videocreds}
|
||||||
return &msg, nil
|
return &msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
640
client/server_test.go
Normal file
640
client/server_test.go
Normal file
@@ -0,0 +1,640 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"forge.redroom.link/yves/meowlib"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// makeServerPair creates two Server structs with cross-wired keypairs,
|
||||||
|
// simulating a client and a server. clientSrv encrypts for the server;
|
||||||
|
// serverSrv encrypts for the client.
|
||||||
|
func makeServerPair(t *testing.T) (clientSrv *Server, serverSrv *Server) {
|
||||||
|
t.Helper()
|
||||||
|
clientKp, err := meowlib.NewKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
serverKp, err := meowlib.NewKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
clientSrv = &Server{
|
||||||
|
Name: "client-side",
|
||||||
|
Url: "https://server.example.com/meow",
|
||||||
|
PublicKey: serverKp.Public,
|
||||||
|
UserKp: clientKp,
|
||||||
|
}
|
||||||
|
serverSrv = &Server{
|
||||||
|
Name: "server-side",
|
||||||
|
Url: "https://server.example.com/meow",
|
||||||
|
PublicKey: clientKp.Public,
|
||||||
|
UserKp: serverKp,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// CreateServerFromUrl
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestCreateServerFromUrl(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "https://example.com/meow", srv.Name)
|
||||||
|
assert.Equal(t, "https://example.com/meow", srv.Url)
|
||||||
|
assert.NotNil(t, srv.UserKp)
|
||||||
|
assert.NotEmpty(t, srv.UserKp.Public)
|
||||||
|
assert.NotEmpty(t, srv.UserKp.Private)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServerFromUrl_UniqueUserKps(t *testing.T) {
|
||||||
|
srv1, _ := CreateServerFromUrl("https://a.example.com/meow")
|
||||||
|
srv2, _ := CreateServerFromUrl("https://a.example.com/meow")
|
||||||
|
assert.NotEqual(t, srv1.UserKp.Public, srv2.UserKp.Public)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// CreateServerFromUid
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestCreateServerFromUid_WithCredentials(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUid("user:pass@https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "user", srv.Login)
|
||||||
|
assert.Equal(t, "pass", srv.Password)
|
||||||
|
assert.Equal(t, "https://example.com/meow", srv.Url)
|
||||||
|
assert.NotNil(t, srv.UserKp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServerFromUid_WithoutCredentials(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUid("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Empty(t, srv.Login)
|
||||||
|
assert.Empty(t, srv.Password)
|
||||||
|
assert.Equal(t, "https://example.com/meow", srv.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServerFromUid_NameIsFullUid(t *testing.T) {
|
||||||
|
uid := "admin:secret@https://example.com/meow"
|
||||||
|
srv, err := CreateServerFromUid(uid)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, uid, srv.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServerFromUid_PasswordOnly(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUid(":secret@https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Empty(t, srv.Login)
|
||||||
|
assert.Equal(t, "secret", srv.Password)
|
||||||
|
assert.Equal(t, "https://example.com/meow", srv.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// CreateServerFromMeowUrl
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestCreateServerFromMeowUrl_WithCredentials(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromMeowUrl("meow://user:pass@server.example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "user", srv.Login)
|
||||||
|
assert.Equal(t, "pass", srv.Password)
|
||||||
|
assert.Equal(t, "server.example.com/meow", srv.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServerFromMeowUrl_NoCredentials(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromMeowUrl("meow://server.example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Empty(t, srv.Login)
|
||||||
|
assert.Equal(t, "server.example.com/meow", srv.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// CreateServerFromInvitationLink
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestCreateServerFromInvitationLink(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromInvitationLink("meow://user:pass@server.example.com/meow?abc123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "user", srv.Login)
|
||||||
|
assert.Equal(t, "pass", srv.Password)
|
||||||
|
assert.Equal(t, "server.example.com/meow", srv.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServerFromInvitationLink_NoQueryParam(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromInvitationLink("meow://server.example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "server.example.com/meow", srv.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServerFromInvitationLink_MultipleQuestionMarks(t *testing.T) {
|
||||||
|
// Only the first ? splits; everything before it is the server URL
|
||||||
|
srv, err := CreateServerFromInvitationLink("meow://server.example.com/meow?code?extra")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "server.example.com/meow", srv.Url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// CreateServerFromServerCard
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestCreateServerFromServerCard(t *testing.T) {
|
||||||
|
card := &meowlib.ServerCard{
|
||||||
|
Name: "MyServer",
|
||||||
|
PublicKey: "server-pub-key",
|
||||||
|
Description: "A test server",
|
||||||
|
Url: "https://example.com/meow",
|
||||||
|
Login: "admin",
|
||||||
|
Password: "secret",
|
||||||
|
}
|
||||||
|
srv, err := CreateServerFromServerCard(card)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "MyServer", srv.Name)
|
||||||
|
assert.Equal(t, "server-pub-key", srv.PublicKey)
|
||||||
|
assert.Equal(t, "A test server", srv.Description)
|
||||||
|
assert.Equal(t, "https://example.com/meow", srv.Url)
|
||||||
|
assert.Equal(t, "admin", srv.Login)
|
||||||
|
assert.Equal(t, "secret", srv.Password)
|
||||||
|
assert.NotNil(t, srv.UserKp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateServerFromServerCard_MinimalCard(t *testing.T) {
|
||||||
|
card := &meowlib.ServerCard{Url: "https://minimal.example.com"}
|
||||||
|
srv, err := CreateServerFromServerCard(card)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "https://minimal.example.com", srv.Url)
|
||||||
|
assert.NotNil(t, srv.UserKp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// GetServerCard
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestGetServerCard(t *testing.T) {
|
||||||
|
srv := &Server{
|
||||||
|
Name: "MyServer",
|
||||||
|
PublicKey: "pub123",
|
||||||
|
Description: "desc",
|
||||||
|
Url: "https://example.com/meow",
|
||||||
|
Login: "user",
|
||||||
|
Password: "pw",
|
||||||
|
}
|
||||||
|
card := srv.GetServerCard()
|
||||||
|
assert.Equal(t, srv.Name, card.Name)
|
||||||
|
assert.Equal(t, srv.PublicKey, card.PublicKey)
|
||||||
|
assert.Equal(t, srv.Description, card.Description)
|
||||||
|
assert.Equal(t, srv.Url, card.Url)
|
||||||
|
assert.Equal(t, srv.Login, card.Login)
|
||||||
|
assert.Equal(t, srv.Password, card.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetServerCard_RoundTrip(t *testing.T) {
|
||||||
|
card := &meowlib.ServerCard{
|
||||||
|
Name: "RT",
|
||||||
|
PublicKey: "pk",
|
||||||
|
Description: "roundtrip",
|
||||||
|
Url: "https://rt.example.com",
|
||||||
|
Login: "l",
|
||||||
|
Password: "p",
|
||||||
|
}
|
||||||
|
srv, err := CreateServerFromServerCard(card)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
restored := srv.GetServerCard()
|
||||||
|
assert.Equal(t, card.Name, restored.Name)
|
||||||
|
assert.Equal(t, card.PublicKey, restored.PublicKey)
|
||||||
|
assert.Equal(t, card.Description, restored.Description)
|
||||||
|
assert.Equal(t, card.Url, restored.Url)
|
||||||
|
assert.Equal(t, card.Login, restored.Login)
|
||||||
|
assert.Equal(t, card.Password, restored.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// GetUid / GetMeowUrl
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestGetUid_WithCredentials(t *testing.T) {
|
||||||
|
srv := &Server{Login: "user", Password: "pass", Url: "https://example.com/meow"}
|
||||||
|
assert.Equal(t, "user:pass@https://example.com/meow", srv.GetUid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUid_NoCredentials(t *testing.T) {
|
||||||
|
srv := &Server{Url: "https://example.com/meow"}
|
||||||
|
assert.Equal(t, "https://example.com/meow", srv.GetUid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetUid_PasswordOnly(t *testing.T) {
|
||||||
|
srv := &Server{Password: "pass", Url: "https://example.com/meow"}
|
||||||
|
assert.Equal(t, ":pass@https://example.com/meow", srv.GetUid())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetMeowUrl_NoCredentials(t *testing.T) {
|
||||||
|
srv := &Server{Url: "https://example.com/meow"}
|
||||||
|
assert.Equal(t, "meow://https://example.com/meow", srv.GetMeowUrl())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetMeowUrl_WithCredentials(t *testing.T) {
|
||||||
|
srv := &Server{Login: "user", Password: "pass", Url: "https://example.com/meow"}
|
||||||
|
// With credentials the meow:// prefix is not added — matches GetUid behaviour
|
||||||
|
assert.Equal(t, srv.GetUid(), srv.GetMeowUrl())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// AsymEncryptMessage / AsymDecryptMessage
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_AsymEncryptDecrypt_RoundTrip(t *testing.T) {
|
||||||
|
clientSrv, serverSrv := makeServerPair(t)
|
||||||
|
plaintext := []byte("hello from client to server")
|
||||||
|
|
||||||
|
enc, err := clientSrv.AsymEncryptMessage(plaintext)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, enc.Data)
|
||||||
|
assert.NotEmpty(t, enc.Signature)
|
||||||
|
|
||||||
|
decrypted, err := serverSrv.AsymDecryptMessage(enc.Data, enc.Signature)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, plaintext, decrypted)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_AsymEncryptDecrypt_Bidirectional(t *testing.T) {
|
||||||
|
clientSrv, serverSrv := makeServerPair(t)
|
||||||
|
|
||||||
|
// Client → Server
|
||||||
|
enc1, err := clientSrv.AsymEncryptMessage([]byte("client msg"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
dec1, err := serverSrv.AsymDecryptMessage(enc1.Data, enc1.Signature)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, []byte("client msg"), dec1)
|
||||||
|
|
||||||
|
// Server → Client
|
||||||
|
enc2, err := serverSrv.AsymEncryptMessage([]byte("server msg"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
dec2, err := clientSrv.AsymDecryptMessage(enc2.Data, enc2.Signature)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, []byte("server msg"), dec2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_AsymEncryptMessage_InvalidKey(t *testing.T) {
|
||||||
|
srv := &Server{
|
||||||
|
PublicKey: "not-a-valid-key",
|
||||||
|
UserKp: &meowlib.KeyPair{Private: "also-invalid"},
|
||||||
|
}
|
||||||
|
_, err := srv.AsymEncryptMessage([]byte("test"))
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_AsymDecryptMessage_WrongSignatureKey(t *testing.T) {
|
||||||
|
clientSrv, serverSrv := makeServerPair(t)
|
||||||
|
|
||||||
|
enc, err := clientSrv.AsymEncryptMessage([]byte("hello"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Replace expected sender key with a random one
|
||||||
|
eve, err := meowlib.NewKeyPair()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
serverSrv.PublicKey = eve.Public
|
||||||
|
|
||||||
|
_, err = serverSrv.AsymDecryptMessage(enc.Data, enc.Signature)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// PackServerMessage / UnPackServerMessage
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_PackUnPack_RoundTrip(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
payload := []byte("test payload")
|
||||||
|
signature := []byte("test sig")
|
||||||
|
|
||||||
|
packed, err := srv.PackServerMessage(payload, signature)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, packed)
|
||||||
|
|
||||||
|
gotPayload, gotSig, err := srv.UnPackServerMessage(packed)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, payload, gotPayload)
|
||||||
|
assert.Equal(t, signature, gotSig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_PackServerMessage_SetsFrom(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
packed, err := srv.PackServerMessage([]byte("p"), []byte("s"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
msg := &meowlib.PackedServerMessage{}
|
||||||
|
err = proto.Unmarshal(packed, msg)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_UnPackServerMessage_InvalidData(t *testing.T) {
|
||||||
|
srv := &Server{}
|
||||||
|
_, _, err := srv.UnPackServerMessage([]byte{0xff, 0xff, 0xff, 0xff, 0xff})
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// BuildToServerMessageFromUserMessage
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_BuildToServerMessageFromUserMessage(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
pum := &meowlib.PackedUserMessage{
|
||||||
|
Destination: "dest-key",
|
||||||
|
Payload: []byte("encrypted"),
|
||||||
|
Signature: []byte("sig"),
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := srv.BuildToServerMessageFromUserMessage(pum)
|
||||||
|
assert.NotEmpty(t, msg.Uuid)
|
||||||
|
assert.Equal(t, "1", msg.Type)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
assert.Len(t, msg.Messages, 1)
|
||||||
|
assert.Equal(t, pum, msg.Messages[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_BuildToServerMessageFromUserMessage_UniqueUuids(t *testing.T) {
|
||||||
|
srv, _ := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
pum := &meowlib.PackedUserMessage{Destination: "d"}
|
||||||
|
|
||||||
|
msg1 := srv.BuildToServerMessageFromUserMessage(pum)
|
||||||
|
msg2 := srv.BuildToServerMessageFromUserMessage(pum)
|
||||||
|
assert.NotEqual(t, msg1.Uuid, msg2.Uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// BuildMessageSendingMessage
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_BuildMessageSendingMessage(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
pum := &meowlib.PackedUserMessage{
|
||||||
|
Destination: "dest",
|
||||||
|
Payload: []byte("payload"),
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := srv.BuildMessageSendingMessage(pum)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, data)
|
||||||
|
|
||||||
|
var msg meowlib.ToServerMessage
|
||||||
|
err = proto.Unmarshal(data, &msg)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "1", msg.Type)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
assert.Len(t, msg.Messages, 1)
|
||||||
|
assert.Equal(t, []byte("payload"), msg.Messages[0].Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// BuildMessageRequestMessage
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_BuildMessageRequestMessage(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
data, err := srv.BuildMessageRequestMessage([]string{"key1", "key2"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, data)
|
||||||
|
|
||||||
|
var msg meowlib.ToServerMessage
|
||||||
|
err = proto.Unmarshal(data, &msg)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "1", msg.Type)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
assert.NotEmpty(t, msg.Uuid)
|
||||||
|
// Note: lookupKeys parameter is currently unused in the message body
|
||||||
|
assert.Empty(t, msg.PullRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// BuildVideoRoomRequestMessage
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_BuildVideoRoomRequestMessage(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
users := []string{"alice", "bob", "charlie"}
|
||||||
|
msg, err := srv.BuildVideoRoomRequestMessage(users, 3600)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, msg)
|
||||||
|
assert.Equal(t, "1", msg.Type)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
assert.NotNil(t, msg.VideoData)
|
||||||
|
assert.Len(t, msg.VideoData.Credentials, 3)
|
||||||
|
assert.Equal(t, "alice", msg.VideoData.Credentials[0].Username)
|
||||||
|
assert.Equal(t, "bob", msg.VideoData.Credentials[1].Username)
|
||||||
|
assert.Equal(t, "charlie", msg.VideoData.Credentials[2].Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_BuildVideoRoomRequestMessage_SingleUser(t *testing.T) {
|
||||||
|
srv, _ := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
msg, err := srv.BuildVideoRoomRequestMessage([]string{"solo"}, 60)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, msg.VideoData.Credentials, 1)
|
||||||
|
assert.Equal(t, "solo", msg.VideoData.Credentials[0].Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// BuildToServerMessageInvitationCreation
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_BuildToServerMessageInvitationCreation(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
cc := &meowlib.ContactCard{
|
||||||
|
Name: "Alice",
|
||||||
|
ContactPublicKey: "alice-pub",
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := srv.BuildToServerMessageInvitationCreation(cc, "secret", 300, 8)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "1", msg.Type)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
assert.NotNil(t, msg.Invitation)
|
||||||
|
assert.Equal(t, int32(1), msg.Invitation.Step)
|
||||||
|
assert.Equal(t, "secret", msg.Invitation.Password)
|
||||||
|
assert.Equal(t, int32(300), msg.Invitation.Timeout)
|
||||||
|
assert.Equal(t, int32(8), msg.Invitation.ShortcodeLen)
|
||||||
|
assert.NotEmpty(t, msg.Invitation.Payload)
|
||||||
|
|
||||||
|
// Payload is a compressed ContactCard — decompress and verify
|
||||||
|
restored, err := meowlib.NewContactCardFromCompressed(msg.Invitation.Payload)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "Alice", restored.Name)
|
||||||
|
assert.Equal(t, "alice-pub", restored.ContactPublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_BuildToServerMessageInvitationCreation_NoPassword(t *testing.T) {
|
||||||
|
srv, _ := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
cc := &meowlib.ContactCard{Name: "Bob"}
|
||||||
|
|
||||||
|
msg, err := srv.BuildToServerMessageInvitationCreation(cc, "", 60, 6)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Empty(t, msg.Invitation.Password)
|
||||||
|
assert.Equal(t, int32(1), msg.Invitation.Step)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// BuildToServerMessageInvitationRequest
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_BuildToServerMessageInvitationRequest(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
msg, err := srv.BuildToServerMessageInvitationRequest("SC1234", "mypassword")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "1", msg.Type)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
assert.NotNil(t, msg.Invitation)
|
||||||
|
assert.Equal(t, int32(2), msg.Invitation.Step)
|
||||||
|
assert.Equal(t, "SC1234", msg.Invitation.Shortcode)
|
||||||
|
assert.Equal(t, "mypassword", msg.Invitation.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_BuildToServerMessageInvitationRequest_NoPassword(t *testing.T) {
|
||||||
|
srv, _ := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
msg, err := srv.BuildToServerMessageInvitationRequest("CODE", "")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "CODE", msg.Invitation.Shortcode)
|
||||||
|
assert.Empty(t, msg.Invitation.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// BuildToServerMessageInvitationAnswer
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_BuildToServerMessageInvitationAnswer(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
pum := &meowlib.PackedUserMessage{
|
||||||
|
Destination: "dest",
|
||||||
|
Payload: []byte("answer-payload"),
|
||||||
|
Signature: []byte("answer-sig"),
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := srv.BuildToServerMessageInvitationAnswer(pum, "my-pub-key", "inv-uuid-42", 600)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "1", msg.Type)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
assert.NotNil(t, msg.Invitation)
|
||||||
|
assert.Equal(t, int32(3), msg.Invitation.Step)
|
||||||
|
assert.Equal(t, "inv-uuid-42", msg.Invitation.Uuid)
|
||||||
|
assert.Equal(t, "my-pub-key", msg.Invitation.From)
|
||||||
|
assert.NotEmpty(t, msg.Invitation.Payload)
|
||||||
|
|
||||||
|
// Payload is proto-serialized PackedUserMessage
|
||||||
|
var decoded meowlib.PackedUserMessage
|
||||||
|
err = proto.Unmarshal(msg.Invitation.Payload, &decoded)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "dest", decoded.Destination)
|
||||||
|
assert.Equal(t, []byte("answer-payload"), decoded.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// BuildToServerMessageInvitationAnswerRequest
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_BuildToServerMessageInvitationAnswerRequest(t *testing.T) {
|
||||||
|
srv, err := CreateServerFromUrl("https://example.com/meow")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
msg, err := srv.BuildToServerMessageInvitationAnswerRequest("inv-uuid-99")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "1", msg.Type)
|
||||||
|
assert.Equal(t, srv.UserKp.Public, msg.From)
|
||||||
|
assert.NotNil(t, msg.Invitation)
|
||||||
|
assert.Equal(t, int32(4), msg.Invitation.Step)
|
||||||
|
assert.Equal(t, "inv-uuid-99", msg.Invitation.Uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ProcessOutboundMessage / ProcessInboundServerResponse (full pipeline)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func TestServer_ProcessOutboundMessage(t *testing.T) {
|
||||||
|
clientSrv, serverSrv := makeServerPair(t)
|
||||||
|
|
||||||
|
original := &meowlib.ToServerMessage{
|
||||||
|
Uuid: "out-uuid",
|
||||||
|
Type: "1",
|
||||||
|
From: clientSrv.UserKp.Public,
|
||||||
|
}
|
||||||
|
|
||||||
|
packed, err := clientSrv.ProcessOutboundMessage(original)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotEmpty(t, packed)
|
||||||
|
|
||||||
|
// Verify the server side can unpack and decrypt back to the original
|
||||||
|
payload, sig, err := serverSrv.UnPackServerMessage(packed)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
decrypted, err := serverSrv.AsymDecryptMessage(payload, sig)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
var restored meowlib.ToServerMessage
|
||||||
|
err = proto.Unmarshal(decrypted, &restored)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "out-uuid", restored.Uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_ProcessOutboundMessage_InvalidServerKey(t *testing.T) {
|
||||||
|
srv := &Server{
|
||||||
|
PublicKey: "bad-key",
|
||||||
|
UserKp: &meowlib.KeyPair{Public: "pub", Private: "bad-priv"},
|
||||||
|
}
|
||||||
|
msg := &meowlib.ToServerMessage{Type: "1"}
|
||||||
|
_, err := srv.ProcessOutboundMessage(msg)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_ProcessInboundServerResponse(t *testing.T) {
|
||||||
|
clientSrv, serverSrv := makeServerPair(t)
|
||||||
|
|
||||||
|
original := &meowlib.FromServerMessage{
|
||||||
|
Chat: []*meowlib.PackedUserMessage{
|
||||||
|
{Destination: "chat-dest", Payload: []byte("chat-payload")},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
originalBytes, err := proto.Marshal(original)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Simulate server packing: encrypt for the client, then pack
|
||||||
|
enc, err := serverSrv.AsymEncryptMessage(originalBytes)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
packedMsg, err := serverSrv.PackServerMessage(enc.Data, enc.Signature)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Client processes the inbound message
|
||||||
|
received, err := clientSrv.ProcessInboundServerResponse(packedMsg)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, received)
|
||||||
|
assert.Len(t, received.Chat, 1)
|
||||||
|
assert.Equal(t, "chat-dest", received.Chat[0].Destination)
|
||||||
|
assert.Equal(t, []byte("chat-payload"), received.Chat[0].Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServer_ProcessInboundServerResponse_InvalidData(t *testing.T) {
|
||||||
|
srv := &Server{
|
||||||
|
UserKp: &meowlib.KeyPair{Private: "invalid"},
|
||||||
|
}
|
||||||
|
_, err := srv.ProcessInboundServerResponse([]byte{0xff, 0xff})
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user