Add tests for UpdateRelations (#2999)

This also fixes an issue regarding updates to relations for invalid
events, which could result in us retrying said event over and over
again, if we fail to unmarshal the event to
`gomatrixserverlib.RelationContent`, this was discovered by
`@sleroq:virto.community`
This commit is contained in:
Till 2023-03-06 12:43:59 +01:00 committed by GitHub
parent 7fc839f751
commit 7d83f8b633
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 4 deletions

View file

@ -567,9 +567,14 @@ func (d *Database) ReIndex(ctx context.Context, limit, afterID int64) (map[int64
} }
func (d *Database) UpdateRelations(ctx context.Context, event *gomatrixserverlib.HeaderedEvent) error { func (d *Database) UpdateRelations(ctx context.Context, event *gomatrixserverlib.HeaderedEvent) error {
// No need to unmarshal if the event is a redaction
if event.Type() == gomatrixserverlib.MRoomRedaction {
return nil
}
var content gomatrixserverlib.RelationContent var content gomatrixserverlib.RelationContent
if err := json.Unmarshal(event.Content(), &content); err != nil { if err := json.Unmarshal(event.Content(), &content); err != nil {
return fmt.Errorf("json.Unmarshal: %w", err) logrus.WithError(err).Error("unable to unmarshal relation content")
return nil
} }
switch { switch {
case content.Relations == nil: case content.Relations == nil:
@ -578,8 +583,6 @@ func (d *Database) UpdateRelations(ctx context.Context, event *gomatrixserverlib
return nil return nil
case content.Relations.RelationType == "": case content.Relations.RelationType == "":
return nil return nil
case event.Type() == gomatrixserverlib.MRoomRedaction:
return nil
default: default:
return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error { return d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
return d.Relations.InsertRelation( return d.Relations.InsertRelation(

View file

@ -10,11 +10,13 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/dendrite/syncapi/routing"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/nats-io/nats.go" "github.com/nats-io/nats.go"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"github.com/matrix-org/dendrite/syncapi/routing"
"github.com/matrix-org/dendrite/syncapi/storage"
"github.com/matrix-org/dendrite/clientapi/producers" "github.com/matrix-org/dendrite/clientapi/producers"
"github.com/matrix-org/dendrite/roomserver" "github.com/matrix-org/dendrite/roomserver"
"github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/api"
@ -1074,6 +1076,90 @@ func testContext(t *testing.T, dbType test.DBType) {
} }
} }
func TestUpdateRelations(t *testing.T) {
testCases := []struct {
name string
eventContent map[string]interface{}
eventType string
}{
{
name: "empty event content should not error",
},
{
name: "unable to unmarshal event should not error",
eventContent: map[string]interface{}{
"m.relates_to": map[string]interface{}{
"event_id": map[string]interface{}{}, // this should be a string and not struct
},
},
},
{
name: "empty event ID is ignored",
eventContent: map[string]interface{}{
"m.relates_to": map[string]interface{}{
"event_id": "",
},
},
},
{
name: "empty rel_type is ignored",
eventContent: map[string]interface{}{
"m.relates_to": map[string]interface{}{
"event_id": "$randomEventID",
"rel_type": "",
},
},
},
{
name: "redactions are ignored",
eventType: gomatrixserverlib.MRoomRedaction,
eventContent: map[string]interface{}{
"m.relates_to": map[string]interface{}{
"event_id": "$randomEventID",
"rel_type": "m.replace",
},
},
},
{
name: "valid event is correctly written",
eventContent: map[string]interface{}{
"m.relates_to": map[string]interface{}{
"event_id": "$randomEventID",
"rel_type": "m.replace",
},
},
},
}
ctx := context.Background()
alice := test.NewUser(t)
room := test.NewRoom(t, alice)
test.WithAllDatabases(t, func(t *testing.T, dbType test.DBType) {
base, shutdownBase := testrig.CreateBaseDendrite(t, dbType)
t.Cleanup(shutdownBase)
db, err := storage.NewSyncServerDatasource(base, &base.Cfg.SyncAPI.Database)
if err != nil {
t.Fatal(err)
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
evType := "m.room.message"
if tc.eventType != "" {
evType = tc.eventType
}
ev := room.CreateEvent(t, alice, evType, tc.eventContent)
err = db.UpdateRelations(ctx, ev)
if err != nil {
t.Fatal(err)
}
})
}
})
}
func syncUntil(t *testing.T, func syncUntil(t *testing.T,
base *base.BaseDendrite, accessToken string, base *base.BaseDendrite, accessToken string,
skip bool, skip bool,