2017-04-12 08:27:57 -04:00
|
|
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
2019-11-29 06:59:40 -05:00
|
|
|
// See LICENSE.txt for license information.
|
2016-07-12 09:36:27 -04:00
|
|
|
|
|
|
|
|
package model
|
|
|
|
|
|
|
|
|
|
import (
|
2021-07-26 04:11:20 -04:00
|
|
|
"bytes"
|
2023-03-13 13:02:12 -04:00
|
|
|
"encoding/json"
|
|
|
|
|
"io"
|
2016-07-12 09:36:27 -04:00
|
|
|
"testing"
|
2018-02-20 13:50:10 -05:00
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2019-10-03 04:48:37 -04:00
|
|
|
"github.com/stretchr/testify/require"
|
2016-07-12 09:36:27 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestWebSocketEvent(t *testing.T) {
|
2020-01-16 03:18:08 -05:00
|
|
|
userId := NewId()
|
2022-09-02 06:17:22 -04:00
|
|
|
m := NewWebSocketEvent("some_event", NewId(), NewId(), userId, nil, "")
|
2016-07-12 09:36:27 -04:00
|
|
|
m.Add("RootId", NewId())
|
2020-01-16 03:18:08 -05:00
|
|
|
user := &User{
|
|
|
|
|
Id: userId,
|
|
|
|
|
}
|
|
|
|
|
m.Add("user", user)
|
2021-09-01 08:43:12 -04:00
|
|
|
json, err := m.ToJSON()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
result, err := WebSocketEventFromJSON(bytes.NewReader(json))
|
|
|
|
|
require.NoError(t, err)
|
2016-07-12 09:36:27 -04:00
|
|
|
|
2019-10-03 04:48:37 -04:00
|
|
|
require.True(t, m.IsValid(), "should be valid")
|
2020-01-16 03:18:08 -05:00
|
|
|
require.Equal(t, m.GetBroadcast().TeamId, result.GetBroadcast().TeamId, "Team ids do not match")
|
|
|
|
|
require.Equal(t, m.GetData()["RootId"], result.GetData()["RootId"], "Root ids do not match")
|
|
|
|
|
require.Equal(t, m.GetData()["user"].(*User).Id, result.GetData()["user"].(*User).Id, "User ids do not match")
|
2019-12-24 03:32:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestWebSocketEventImmutable(t *testing.T) {
|
2023-11-22 05:09:48 -05:00
|
|
|
m := NewWebSocketEvent(WebsocketEventPostEdited, NewId(), NewId(), NewId(), nil, "")
|
2016-07-12 09:36:27 -04:00
|
|
|
|
2023-11-22 05:09:48 -05:00
|
|
|
newM := m.SetEvent(WebsocketEventPostDeleted)
|
2023-06-13 04:38:36 -04:00
|
|
|
if newM == m {
|
2019-12-24 03:32:11 -05:00
|
|
|
require.Fail(t, "pointers should not be the same")
|
|
|
|
|
}
|
2023-06-13 04:38:36 -04:00
|
|
|
require.NotEqual(t, m.EventType(), newM.EventType())
|
2023-11-22 05:09:48 -05:00
|
|
|
require.Equal(t, newM.EventType(), WebsocketEventPostDeleted)
|
2016-07-12 09:36:27 -04:00
|
|
|
|
2023-06-13 04:38:36 -04:00
|
|
|
newM = m.SetSequence(45)
|
|
|
|
|
if newM == m {
|
2019-12-24 03:32:11 -05:00
|
|
|
require.Fail(t, "pointers should not be the same")
|
|
|
|
|
}
|
2023-06-13 04:38:36 -04:00
|
|
|
require.NotEqual(t, m.GetSequence(), newM.GetSequence())
|
|
|
|
|
require.Equal(t, newM.GetSequence(), int64(45))
|
2019-12-24 03:32:11 -05:00
|
|
|
|
|
|
|
|
broadcast := &WebsocketBroadcast{}
|
2023-06-13 04:38:36 -04:00
|
|
|
newM = m.SetBroadcast(broadcast)
|
|
|
|
|
if newM == m {
|
2019-12-24 03:32:11 -05:00
|
|
|
require.Fail(t, "pointers should not be the same")
|
|
|
|
|
}
|
2023-06-13 04:38:36 -04:00
|
|
|
require.NotEqual(t, m.GetBroadcast(), newM.GetBroadcast())
|
|
|
|
|
require.Equal(t, newM.GetBroadcast(), broadcast)
|
2019-12-24 03:32:11 -05:00
|
|
|
|
2022-07-05 02:46:50 -04:00
|
|
|
data := map[string]any{
|
2019-12-24 03:32:11 -05:00
|
|
|
"key": "val",
|
|
|
|
|
"key2": "val2",
|
|
|
|
|
}
|
2023-06-13 04:38:36 -04:00
|
|
|
newM = m.SetData(data)
|
|
|
|
|
if newM == m {
|
2019-12-24 03:32:11 -05:00
|
|
|
require.Fail(t, "pointers should not be the same")
|
|
|
|
|
}
|
2023-06-13 04:38:36 -04:00
|
|
|
require.NotEqual(t, m, newM)
|
|
|
|
|
require.Equal(t, newM.data, data)
|
|
|
|
|
require.Equal(t, newM.data, newM.GetData())
|
2019-12-24 03:32:11 -05:00
|
|
|
|
2023-06-30 10:42:56 -04:00
|
|
|
mCopy := m.Copy()
|
|
|
|
|
if mCopy == m {
|
2019-12-24 03:32:11 -05:00
|
|
|
require.Fail(t, "pointers should not be the same")
|
|
|
|
|
}
|
2023-06-30 10:42:56 -04:00
|
|
|
require.Equal(t, m, mCopy)
|
2019-12-24 03:32:11 -05:00
|
|
|
}
|
|
|
|
|
|
2021-09-01 08:43:12 -04:00
|
|
|
func TestWebSocketEventFromJSON(t *testing.T) {
|
|
|
|
|
ev, err := WebSocketEventFromJSON(bytes.NewReader([]byte("junk")))
|
|
|
|
|
require.Error(t, err)
|
2019-12-24 03:32:11 -05:00
|
|
|
require.Nil(t, ev, "should not have parsed")
|
2023-11-22 05:09:48 -05:00
|
|
|
data := []byte(`{"event": "typing", "data": {"key": "val"}, "seq": 45, "broadcast": {"user_id": "userid"}}`)
|
2021-09-01 08:43:12 -04:00
|
|
|
ev, err = WebSocketEventFromJSON(bytes.NewReader(data))
|
|
|
|
|
require.NoError(t, err)
|
2019-12-24 03:32:11 -05:00
|
|
|
require.NotNil(t, ev, "should have parsed")
|
2023-11-22 05:09:48 -05:00
|
|
|
require.Equal(t, ev.EventType(), WebsocketEventTyping)
|
2021-07-13 10:35:02 -04:00
|
|
|
require.Equal(t, ev.GetSequence(), int64(45))
|
2022-07-05 02:46:50 -04:00
|
|
|
require.Equal(t, ev.data, map[string]any{"key": "val"})
|
2021-07-13 10:35:02 -04:00
|
|
|
require.Equal(t, ev.GetBroadcast(), &WebsocketBroadcast{UserId: "userid"})
|
2016-07-12 09:36:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestWebSocketResponse(t *testing.T) {
|
2022-07-05 02:46:50 -04:00
|
|
|
m := NewWebSocketResponse("OK", 1, map[string]any{})
|
2016-07-12 09:36:27 -04:00
|
|
|
e := NewWebSocketError(1, &AppError{})
|
|
|
|
|
m.Add("RootId", NewId())
|
2021-09-01 08:43:12 -04:00
|
|
|
json, err := m.ToJSON()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
result, err := WebSocketResponseFromJSON(bytes.NewReader(json))
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
json2, err := e.ToJSON()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
WebSocketResponseFromJSON(bytes.NewReader(json2))
|
|
|
|
|
|
|
|
|
|
badresult, err := WebSocketResponseFromJSON(bytes.NewReader([]byte("junk")))
|
|
|
|
|
require.Error(t, err)
|
2019-10-03 04:48:37 -04:00
|
|
|
require.Nil(t, badresult, "should not have parsed")
|
2016-07-12 09:36:27 -04:00
|
|
|
|
2019-10-03 04:48:37 -04:00
|
|
|
require.True(t, m.IsValid(), "should be valid")
|
2016-07-12 09:36:27 -04:00
|
|
|
|
2019-10-03 04:48:37 -04:00
|
|
|
require.Equal(t, m.Data["RootId"], result.Data["RootId"], "Ids do not match")
|
2016-07-12 09:36:27 -04:00
|
|
|
}
|
2018-02-20 13:50:10 -05:00
|
|
|
|
|
|
|
|
func TestWebSocketEvent_PrecomputeJSON(t *testing.T) {
|
2022-09-02 06:17:22 -04:00
|
|
|
event := NewWebSocketEvent(WebsocketEventPosted, "foo", "bar", "baz", nil, "")
|
2019-12-24 03:32:11 -05:00
|
|
|
event = event.SetSequence(7)
|
2018-02-20 13:50:10 -05:00
|
|
|
|
2021-09-01 08:43:12 -04:00
|
|
|
before, err := event.ToJSON()
|
|
|
|
|
require.NoError(t, err)
|
2018-02-20 13:50:10 -05:00
|
|
|
event.PrecomputeJSON()
|
2021-09-01 08:43:12 -04:00
|
|
|
after, err := event.ToJSON()
|
|
|
|
|
require.NoError(t, err)
|
2018-02-20 13:50:10 -05:00
|
|
|
|
2021-07-26 04:11:20 -04:00
|
|
|
assert.Equal(t, before, after)
|
2018-02-20 13:50:10 -05:00
|
|
|
}
|
|
|
|
|
|
2021-07-26 04:11:20 -04:00
|
|
|
var stringSink []byte
|
2018-02-20 13:50:10 -05:00
|
|
|
|
2021-09-01 08:43:12 -04:00
|
|
|
func BenchmarkWebSocketEvent_ToJSON(b *testing.B) {
|
2022-09-02 06:17:22 -04:00
|
|
|
event := NewWebSocketEvent(WebsocketEventPosted, "foo", "bar", "baz", nil, "")
|
2025-07-18 06:54:51 -04:00
|
|
|
for range 100 {
|
2019-12-24 03:32:11 -05:00
|
|
|
event.GetData()[NewId()] = NewId()
|
2018-02-20 13:50:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b.Run("SerializedNTimes", func(b *testing.B) {
|
2025-07-18 06:54:51 -04:00
|
|
|
for b.Loop() {
|
2021-09-01 08:43:12 -04:00
|
|
|
stringSink, _ = event.ToJSON()
|
2018-02-20 13:50:10 -05:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
b.Run("PrecomputedNTimes", func(b *testing.B) {
|
2025-07-18 06:54:51 -04:00
|
|
|
for b.Loop() {
|
2018-02-20 13:50:10 -05:00
|
|
|
event.PrecomputeJSON()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
b.Run("PrecomputedAndSerializedNTimes", func(b *testing.B) {
|
2025-07-18 06:54:51 -04:00
|
|
|
for b.Loop() {
|
2018-02-20 13:50:10 -05:00
|
|
|
event.PrecomputeJSON()
|
2021-09-01 08:43:12 -04:00
|
|
|
stringSink, _ = event.ToJSON()
|
2018-02-20 13:50:10 -05:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
event.PrecomputeJSON()
|
|
|
|
|
b.Run("PrecomputedOnceAndSerializedNTimes", func(b *testing.B) {
|
2025-07-18 06:54:51 -04:00
|
|
|
for b.Loop() {
|
2021-09-01 08:43:12 -04:00
|
|
|
stringSink, _ = event.ToJSON()
|
2018-02-20 13:50:10 -05:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2021-11-22 03:54:19 -05:00
|
|
|
|
|
|
|
|
func TestWebsocketBroadcastCopy(t *testing.T) {
|
|
|
|
|
w := &WebsocketBroadcast{}
|
|
|
|
|
require.Equal(t, w, w.copy())
|
|
|
|
|
|
|
|
|
|
w = nil
|
|
|
|
|
require.Equal(t, w, w.copy())
|
|
|
|
|
|
|
|
|
|
w = &WebsocketBroadcast{
|
|
|
|
|
OmitUsers: map[string]bool{
|
|
|
|
|
"aaa": true,
|
|
|
|
|
"bbb": true,
|
|
|
|
|
"ccc": false,
|
|
|
|
|
},
|
|
|
|
|
UserId: "aaa",
|
|
|
|
|
ChannelId: "bbb",
|
|
|
|
|
TeamId: "ccc",
|
|
|
|
|
ContainsSanitizedData: true,
|
|
|
|
|
ContainsSensitiveData: true,
|
|
|
|
|
}
|
|
|
|
|
require.Equal(t, w, w.copy())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPrecomputedWebSocketEventJSONCopy(t *testing.T) {
|
|
|
|
|
p := &precomputedWebSocketEventJSON{}
|
|
|
|
|
require.Equal(t, p, p.copy())
|
|
|
|
|
|
|
|
|
|
p = nil
|
|
|
|
|
require.Equal(t, p, p.copy())
|
|
|
|
|
|
|
|
|
|
p = &precomputedWebSocketEventJSON{
|
|
|
|
|
Event: []byte{},
|
|
|
|
|
Data: []byte{},
|
|
|
|
|
Broadcast: []byte{},
|
|
|
|
|
}
|
|
|
|
|
require.Equal(t, p, p.copy())
|
|
|
|
|
|
|
|
|
|
p = &precomputedWebSocketEventJSON{
|
|
|
|
|
Event: []byte{'a', 'b', 'c'},
|
|
|
|
|
Data: []byte{'d', 'e', 'f'},
|
|
|
|
|
Broadcast: []byte{'g', 'h', 'i'},
|
|
|
|
|
}
|
|
|
|
|
require.Equal(t, p, p.copy())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestWebSocketEventDeepCopy(t *testing.T) {
|
|
|
|
|
omitUsers := map[string]bool{
|
|
|
|
|
"user1": true,
|
|
|
|
|
"user2": false,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
broadcast := &WebsocketBroadcast{
|
|
|
|
|
OmitUsers: omitUsers,
|
|
|
|
|
UserId: "aaa",
|
|
|
|
|
ChannelId: "bbb",
|
|
|
|
|
TeamId: "ccc",
|
|
|
|
|
ContainsSanitizedData: true,
|
|
|
|
|
ContainsSensitiveData: true,
|
2022-11-29 16:36:47 -05:00
|
|
|
OmitConnectionId: "ddd",
|
2021-11-22 03:54:19 -05:00
|
|
|
}
|
|
|
|
|
|
2022-11-29 16:36:47 -05:00
|
|
|
ev := NewWebSocketEvent("test", "team", "channel", "user", omitUsers, "ddd")
|
2021-11-22 03:54:19 -05:00
|
|
|
|
|
|
|
|
ev.Add("post", &Post{})
|
|
|
|
|
ev.SetBroadcast(broadcast)
|
|
|
|
|
ev = ev.PrecomputeJSON()
|
|
|
|
|
|
|
|
|
|
evCopy := ev.DeepCopy()
|
|
|
|
|
require.Equal(t, ev, evCopy)
|
Introduce model.AssertNotSameMap (#34058)
When we last bumped dependencies in https://github.com/mattermost/mattermost/pull/30005, `assert.NotSame` for maps started failing because of the change in https://github.com/stretchr/testify/issues/1661. The reality was that the previous assertion was silently skipped, and just now reporting as much.
Here's an illustrative example:
```go
package main
import (
"maps"
"testing"
"github.com/stretchr/testify/assert"
)
func TestClonedMapsAreNotSame(t *testing.T) {
original := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
cloned := maps.Clone(original)
assert.NotSame(t, original, cloned)
}
func TestSameMaps(t *testing.T) {
original := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
cloned := original
assert.Same(t, original, cloned)
cloned["d"] = 4
assert.Same(t, original, cloned)
}
```
which fails with the following after the original dependency update:
```
--- FAIL: TestClonedMapsAreNotSame (0.00s)
main_test.go:19:
Error Trace: /Users/jesse/tmp/testify/main_test.go:19
Error: Both arguments must be pointers
Test: TestClonedMapsAreNotSame
--- FAIL: TestSameMaps (0.00s)
main_test.go:30:
Error Trace: /Users/jesse/tmp/testify/main_test.go:30
Error: Both arguments must be pointers
Test: TestSameMaps
main_test.go:33:
Error Trace: /Users/jesse/tmp/testify/main_test.go:33
Error: Both arguments must be pointers
Test: TestSameMaps
FAIL
FAIL testassertequal 0.149s
FAIL
```
However, instead of fixing the underlying issue, we took the address of those variables and kept using `assert.Same`. This isn't meaningful, since it doesn't directly compare the underlying pointers of the map objects in question, just the address of the pointers to those maps. Here's the output after taking the address (e.g. `&original` and `&cloned`):
```
--- FAIL: TestSameMaps (0.00s)
main_test.go:30:
Error Trace: /Users/jesse/tmp/testify/main_test.go:30
Error: Not same:
expected: 0x14000070170 &map[string]int{"a":1, "b":2, "c":3}
actual : 0x14000070178 &map[string]int{"a":1, "b":2, "c":3}
Test: TestSameMaps
main_test.go:33:
Error Trace: /Users/jesse/tmp/testify/main_test.go:33
Error: Not same:
expected: 0x14000070170 &map[string]int{"a":1, "b":2, "c":3, "d":4}
actual : 0x14000070178 &map[string]int{"a":1, "b":2, "c":3, "d":4}
Test: TestSameMaps
FAIL
FAIL testassertequal 0.157s
FAIL
```
They are obviously the same map, since modifying `cloned` modified the
original, yet `assert.Same` thinks they are different (because the
pointe values are indeed different). (`assert.NotSame` "passes", but for
the wrong reasons.)
To fix this, introduce `model.AssertNotSameMap` to check this correctly.
2025-10-27 12:16:59 -04:00
|
|
|
AssertNotSameMap(t, ev.data, evCopy.data)
|
2021-11-22 03:54:19 -05:00
|
|
|
require.NotSame(t, ev.broadcast, evCopy.broadcast)
|
|
|
|
|
require.NotSame(t, ev.precomputedJSON, evCopy.precomputedJSON)
|
|
|
|
|
|
|
|
|
|
ev.Add("post", &Post{
|
|
|
|
|
Id: "test",
|
|
|
|
|
})
|
|
|
|
|
require.NotEqual(t, ev.data, evCopy.data)
|
|
|
|
|
}
|
2023-03-13 13:02:12 -04:00
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
|
|
func BenchmarkEncodeJSON(b *testing.B) {
|
|
|
|
|
message := NewWebSocketEvent(WebsocketEventUserAdded, "", "channelID", "", nil, "")
|
|
|
|
|
message.Add("user_id", "userID")
|
|
|
|
|
message.Add("team_id", "teamID")
|
|
|
|
|
|
|
|
|
|
ev := message.PrecomputeJSON()
|
|
|
|
|
|
2023-11-08 01:45:24 -05:00
|
|
|
var seq int64
|
2023-03-13 13:02:12 -04:00
|
|
|
enc := json.NewEncoder(io.Discard)
|
2025-07-18 06:54:51 -04:00
|
|
|
for b.Loop() {
|
2023-11-08 01:45:24 -05:00
|
|
|
ev = ev.SetSequence(seq)
|
|
|
|
|
err = ev.Encode(enc, io.Discard)
|
|
|
|
|
seq++
|
2023-03-13 13:02:12 -04:00
|
|
|
}
|
|
|
|
|
}
|