159 lines
6.3 KiB
Go
159 lines
6.3 KiB
Go
package isphere
|
|
|
|
import (
|
|
"context"
|
|
"crypto/cipher"
|
|
"crypto/des"
|
|
"encoding/base64"
|
|
"testing"
|
|
)
|
|
|
|
func TestEncryptedPacketLogSourceReturnsNormalizedMessages(t *testing.T) {
|
|
plaintext := `--------------------------------------------------------------------------------------------------------------------------------------------
|
|
2026/7/7 15:30:07
|
|
<message id="msg-1" from="sender@imopenfire1-lanzhou/imp_pc_4.1.2.6842" to="receiver@imopenfire1-lanzhou" type="chat">
|
|
<body>redacted</body>
|
|
<received xmlns="urn:xmpp:receipts" id="receipt-1" type="1" stamp="" />
|
|
<subject>FILE_TRANSFER_CANCEL</subject>
|
|
<isphere xmlns="isphere.im" type="1001" sendtime="1783423807000" version="1" />
|
|
<readed />
|
|
</message>`
|
|
source := EncryptedPacketLogSource{Lines: []string{encryptPacketLineForTest(t, plaintext)}}
|
|
|
|
got, err := source.ReceiveMessages(context.Background(), ReceiveMessagesQuery{Limit: 10})
|
|
if err != nil {
|
|
t.Fatalf("ReceiveMessages returned error: %v", err)
|
|
}
|
|
if len(got.Messages) != 1 {
|
|
t.Fatalf("message count = %d, want 1", len(got.Messages))
|
|
}
|
|
msg := got.Messages[0]
|
|
if msg.ID != "msg-1" || msg.Text != "redacted" || msg.Subject != "FILE_TRANSFER_CANCEL" {
|
|
t.Fatalf("unexpected message content: %+v", msg)
|
|
}
|
|
if msg.ConversationID != "sender@imopenfire1-lanzhou|receiver@imopenfire1-lanzhou" {
|
|
t.Fatalf("conversation id = %q", msg.ConversationID)
|
|
}
|
|
if msg.SenderID != "sender@imopenfire1-lanzhou" || msg.ReceiverID != "receiver@imopenfire1-lanzhou" {
|
|
t.Fatalf("sender/receiver = %q/%q", msg.SenderID, msg.ReceiverID)
|
|
}
|
|
if msg.Timestamp != "1783423807000" || msg.ReceiptID != "receipt-1" || !msg.Read {
|
|
t.Fatalf("metadata = %+v", msg)
|
|
}
|
|
}
|
|
|
|
func TestEncryptedPacketLogSourceFiltersByConversationAndQuery(t *testing.T) {
|
|
first := `--------------------------------------------------------------------------------------------------------------------------------------------
|
|
2026/7/7 15:30:07
|
|
<message id="msg-alpha" from="sender@imopenfire1-lanzhou/imp_pc_4.1.2.6842" to="receiver@imopenfire1-lanzhou" type="chat">
|
|
<body>alpha status update</body>
|
|
<received xmlns="urn:xmpp:receipts" id="receipt-alpha" type="1" stamp="" />
|
|
<subject>TASK_UPDATE</subject>
|
|
<isphere xmlns="isphere.im" type="1001" sendtime="1783423807000" version="1" />
|
|
<readed />
|
|
</message>`
|
|
second := `--------------------------------------------------------------------------------------------------------------------------------------------
|
|
2026/7/7 15:31:07
|
|
<message id="msg-beta" from="project-room@conference.imopenfire1-lanzhou/imp_pc_4.1.2.6842" to="sender@imopenfire1-lanzhou" type="groupchat">
|
|
<body>beta budget redacted-report.docx</body>
|
|
<received xmlns="urn:xmpp:receipts" id="receipt-beta" type="1" stamp="" />
|
|
<subject>FILE_TRANSFER_CANCEL</subject>
|
|
<isphere xmlns="isphere.im" type="1001" sendtime="1783423867000" version="1" />
|
|
<readed />
|
|
</message>`
|
|
source := EncryptedPacketLogSource{Lines: []string{
|
|
encryptPacketLineForTest(t, first),
|
|
encryptPacketLineForTest(t, second),
|
|
}}
|
|
|
|
got, err := source.ReceiveMessages(context.Background(), ReceiveMessagesQuery{
|
|
ConversationID: "project-room@conference.imopenfire1-lanzhou|sender@imopenfire1-lanzhou",
|
|
Query: "BUDGET",
|
|
Limit: 10,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ReceiveMessages returned error: %v", err)
|
|
}
|
|
if len(got.Messages) != 1 {
|
|
t.Fatalf("message count = %d, want 1: %+v", len(got.Messages), got.Messages)
|
|
}
|
|
if got.Messages[0].ID != "msg-beta" {
|
|
t.Fatalf("message id = %q, want msg-beta", got.Messages[0].ID)
|
|
}
|
|
|
|
empty, err := source.ReceiveMessages(context.Background(), ReceiveMessagesQuery{
|
|
ConversationID: "project-room@conference.imopenfire1-lanzhou|sender@imopenfire1-lanzhou",
|
|
Query: "alpha",
|
|
Limit: 10,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ReceiveMessages returned error for empty query: %v", err)
|
|
}
|
|
if len(empty.Messages) != 0 {
|
|
t.Fatalf("empty query returned %+v, want none", empty.Messages)
|
|
}
|
|
}
|
|
|
|
func TestEncryptedPacketLogSourceFiltersBySince(t *testing.T) {
|
|
first := `--------------------------------------------------------------------------------------------------------------------------------------------
|
|
2026/7/7 15:30:07
|
|
<message id="msg-before" from="sender@imopenfire1-lanzhou/imp_pc_4.1.2.6842" to="receiver@imopenfire1-lanzhou" type="chat">
|
|
<body>before threshold</body>
|
|
<received xmlns="urn:xmpp:receipts" id="receipt-before" type="1" stamp="" />
|
|
<subject>TASK_UPDATE</subject>
|
|
<isphere xmlns="isphere.im" type="1001" sendtime="1783423807000" version="1" />
|
|
<readed />
|
|
</message>`
|
|
second := `--------------------------------------------------------------------------------------------------------------------------------------------
|
|
2026/7/7 15:31:07
|
|
<message id="msg-after" from="sender@imopenfire1-lanzhou/imp_pc_4.1.2.6842" to="receiver@imopenfire1-lanzhou" type="chat">
|
|
<body>after threshold</body>
|
|
<received xmlns="urn:xmpp:receipts" id="receipt-after" type="1" stamp="" />
|
|
<subject>TASK_UPDATE</subject>
|
|
<isphere xmlns="isphere.im" type="1001" sendtime="1783423867000" version="1" />
|
|
<readed />
|
|
</message>`
|
|
source := EncryptedPacketLogSource{Lines: []string{
|
|
encryptPacketLineForTest(t, first),
|
|
encryptPacketLineForTest(t, second),
|
|
}}
|
|
|
|
got, err := source.ReceiveMessages(context.Background(), ReceiveMessagesQuery{
|
|
Since: "2026-07-07T11:31:00Z",
|
|
Limit: 10,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ReceiveMessages returned error: %v", err)
|
|
}
|
|
if len(got.Messages) != 1 || got.Messages[0].ID != "msg-after" {
|
|
t.Fatalf("messages = %+v, want only msg-after", got.Messages)
|
|
}
|
|
|
|
_, err = source.ReceiveMessages(context.Background(), ReceiveMessagesQuery{Since: "not-a-time"})
|
|
if err == nil {
|
|
t.Fatalf("ReceiveMessages accepted invalid since")
|
|
}
|
|
}
|
|
|
|
func encryptPacketLineForTest(t *testing.T, plaintext string) string {
|
|
t.Helper()
|
|
block, err := des.NewCipher([]byte("hyhccdtm"))
|
|
if err != nil {
|
|
t.Fatalf("NewCipher: %v", err)
|
|
}
|
|
plain := padPacketLineForTest([]byte(plaintext), des.BlockSize)
|
|
ciphertext := make([]byte, len(plain))
|
|
iv := []byte{0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}
|
|
cipher.NewCBCEncrypter(block, iv).CryptBlocks(ciphertext, plain)
|
|
return base64.StdEncoding.EncodeToString(ciphertext)
|
|
}
|
|
|
|
func padPacketLineForTest(data []byte, blockSize int) []byte {
|
|
pad := blockSize - len(data)%blockSize
|
|
out := append([]byte(nil), data...)
|
|
for i := 0; i < pad; i++ {
|
|
out = append(out, byte(pad))
|
|
}
|
|
return out
|
|
}
|