adding server test
This commit is contained in:
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