mirror of
https://mau.dev/mautrix/go.git
synced 2026-03-14 14:25:53 +01:00
158 lines
4.7 KiB
Go
158 lines
4.7 KiB
Go
// Copyright (c) 2026 Tulir Asokan
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package mautrix_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"maunium.net/go/mautrix"
|
|
"maunium.net/go/mautrix/event"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
func TestClient_SendEphemeralEvent_UsesUnstablePathTxnAndTS(t *testing.T) {
|
|
roomID := id.RoomID("!room:example.com")
|
|
evtType := event.Type{Type: "com.example.ephemeral", Class: event.EphemeralEventType}
|
|
txnID := "txn-123"
|
|
|
|
var gotPath string
|
|
var gotQueryTS string
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotPath = r.URL.Path
|
|
gotQueryTS = r.URL.Query().Get("ts")
|
|
assert.Equal(t, http.MethodPut, r.Method)
|
|
_, _ = w.Write([]byte(`{"event_id":"$evt"}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
cli, err := mautrix.NewClient(ts.URL, "", "")
|
|
require.NoError(t, err)
|
|
|
|
_, err = cli.BeeperSendEphemeralEvent(
|
|
context.Background(),
|
|
roomID,
|
|
evtType,
|
|
map[string]any{"foo": "bar"},
|
|
mautrix.ReqSendEvent{TransactionID: txnID, Timestamp: 1234},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, strings.Contains(gotPath, "/_matrix/client/unstable/com.beeper.ephemeral/rooms/"))
|
|
assert.True(t, strings.HasSuffix(gotPath, "/ephemeral/com.example.ephemeral/"+txnID))
|
|
assert.Equal(t, "1234", gotQueryTS)
|
|
}
|
|
|
|
func TestClient_SendEphemeralEvent_UnsupportedReturnsMUnrecognized(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
_, _ = w.Write([]byte(`{"errcode":"M_UNRECOGNIZED","error":"Unrecognized endpoint"}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
cli, err := mautrix.NewClient(ts.URL, "", "")
|
|
require.NoError(t, err)
|
|
|
|
_, err = cli.BeeperSendEphemeralEvent(
|
|
context.Background(),
|
|
id.RoomID("!room:example.com"),
|
|
event.Type{Type: "com.example.ephemeral", Class: event.EphemeralEventType},
|
|
map[string]any{"foo": "bar"},
|
|
)
|
|
require.Error(t, err)
|
|
assert.True(t, errors.Is(err, mautrix.MUnrecognized))
|
|
}
|
|
|
|
func TestClient_SendEphemeralEvent_EncryptsInEncryptedRooms(t *testing.T) {
|
|
roomID := id.RoomID("!room:example.com")
|
|
evtType := event.Type{Type: "com.example.ephemeral", Class: event.EphemeralEventType}
|
|
txnID := "txn-encrypted"
|
|
|
|
stateStore := mautrix.NewMemoryStateStore()
|
|
err := stateStore.SetEncryptionEvent(context.Background(), roomID, &event.EncryptionEventContent{
|
|
Algorithm: id.AlgorithmMegolmV1,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
fakeCrypto := &fakeCryptoHelper{
|
|
encryptedContent: &event.EncryptedEventContent{
|
|
Algorithm: id.AlgorithmMegolmV1,
|
|
MegolmCiphertext: []byte("ciphertext"),
|
|
},
|
|
}
|
|
|
|
var gotPath string
|
|
var gotBody map[string]any
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotPath = r.URL.Path
|
|
assert.Equal(t, http.MethodPut, r.Method)
|
|
err := json.NewDecoder(r.Body).Decode(&gotBody)
|
|
require.NoError(t, err)
|
|
_, _ = w.Write([]byte(`{"event_id":"$evt"}`))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
cli, err := mautrix.NewClient(ts.URL, "", "")
|
|
require.NoError(t, err)
|
|
cli.StateStore = stateStore
|
|
cli.Crypto = fakeCrypto
|
|
|
|
_, err = cli.BeeperSendEphemeralEvent(
|
|
context.Background(),
|
|
roomID,
|
|
evtType,
|
|
map[string]any{"foo": "bar"},
|
|
mautrix.ReqSendEvent{TransactionID: txnID},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, strings.HasSuffix(gotPath, "/ephemeral/m.room.encrypted/"+txnID))
|
|
assert.Equal(t, string(id.AlgorithmMegolmV1), gotBody["algorithm"])
|
|
assert.Equal(t, 1, fakeCrypto.encryptCalls)
|
|
assert.Equal(t, roomID, fakeCrypto.lastRoomID)
|
|
assert.Equal(t, evtType, fakeCrypto.lastEventType)
|
|
}
|
|
|
|
type fakeCryptoHelper struct {
|
|
encryptCalls int
|
|
lastRoomID id.RoomID
|
|
lastEventType event.Type
|
|
lastEncryptInput any
|
|
encryptedContent *event.EncryptedEventContent
|
|
}
|
|
|
|
func (f *fakeCryptoHelper) Encrypt(_ context.Context, roomID id.RoomID, eventType event.Type, content any) (*event.EncryptedEventContent, error) {
|
|
f.encryptCalls++
|
|
f.lastRoomID = roomID
|
|
f.lastEventType = eventType
|
|
f.lastEncryptInput = content
|
|
return f.encryptedContent, nil
|
|
}
|
|
|
|
func (f *fakeCryptoHelper) Decrypt(context.Context, *event.Event) (*event.Event, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (f *fakeCryptoHelper) WaitForSession(context.Context, id.RoomID, id.SenderKey, id.SessionID, time.Duration) bool {
|
|
return false
|
|
}
|
|
|
|
func (f *fakeCryptoHelper) RequestSession(context.Context, id.RoomID, id.SenderKey, id.SessionID, id.UserID, id.DeviceID) {
|
|
}
|
|
|
|
func (f *fakeCryptoHelper) Init(context.Context) error {
|
|
return nil
|
|
}
|