Skip to content

Commit d5025cd

Browse files
authored
Add tests to check that /login creates a device_lists.changed entry (#438)
* Add tests to check that /login creates a device_lists.changed entry * Remove Parallel, use a public instead of private chat
1 parent 41787c7 commit d5025cd

File tree

3 files changed

+112
-8
lines changed

3 files changed

+112
-8
lines changed

tests/csapi/keychanges_test.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package csapi_tests
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/url"
7+
"testing"
8+
9+
"github.com/tidwall/gjson"
10+
11+
"github.com/matrix-org/complement/internal/b"
12+
"github.com/matrix-org/complement/internal/client"
13+
"github.com/matrix-org/complement/internal/match"
14+
"github.com/matrix-org/complement/internal/must"
15+
)
16+
17+
func TestKeyChangesLocal(t *testing.T) {
18+
deployment := Deploy(t, b.BlueprintAlice)
19+
defer deployment.Destroy(t)
20+
21+
alice := deployment.Client(t, "hs1", "@alice:hs1")
22+
password := "$uperSecretPassword"
23+
bob := deployment.RegisterUser(t, "hs1", "bob", password, false)
24+
unauthedClient := deployment.Client(t, "hs1", "")
25+
26+
t.Run("New login should create a device_lists.changed entry", func(t *testing.T) {
27+
mustUploadKeys(t, bob)
28+
29+
roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"})
30+
bob.JoinRoom(t, roomID, []string{})
31+
nextBatch1 := alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID))
32+
33+
reqBody := client.WithJSONBody(t, map[string]interface{}{
34+
"identifier": map[string]interface{}{
35+
"type": "m.id.user",
36+
"user": bob.UserID,
37+
},
38+
"type": "m.login.password",
39+
"password": password,
40+
})
41+
// Create a new device by logging in
42+
res := unauthedClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "r0", "login"}, reqBody)
43+
loginResp := must.ParseJSON(t, res.Body)
44+
unauthedClient.AccessToken = must.GetJSONFieldStr(t, loginResp, "access_token")
45+
unauthedClient.DeviceID = must.GetJSONFieldStr(t, loginResp, "device_id")
46+
unauthedClient.UserID = must.GetJSONFieldStr(t, loginResp, "user_id")
47+
mustUploadKeys(t, unauthedClient)
48+
49+
// Alice should now see a device list changed entry for Bob
50+
nextBatch := alice.MustSyncUntil(t, client.SyncReq{Since: nextBatch1}, func(userID string, syncResp gjson.Result) error {
51+
deviceListsChanged := syncResp.Get("device_lists.changed")
52+
if !deviceListsChanged.IsArray() {
53+
return fmt.Errorf("no device_lists.changed entry found: %+v", syncResp.Raw)
54+
}
55+
for _, userID := range deviceListsChanged.Array() {
56+
if userID.String() == bob.UserID {
57+
return nil
58+
}
59+
}
60+
return fmt.Errorf("no device_lists.changed entry found for %s", bob.UserID)
61+
})
62+
// Verify on /keys/changes that Bob has changes
63+
queryParams := url.Values{}
64+
queryParams.Set("from", nextBatch1)
65+
queryParams.Set("to", nextBatch)
66+
resp := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "keys", "changes"}, client.WithQueries(queryParams))
67+
must.MatchResponse(t, resp, match.HTTPResponse{
68+
StatusCode: http.StatusOK,
69+
JSON: []match.JSON{
70+
match.JSONKeyEqual("changed.0", bob.UserID), // there should only be one change, so access it directly
71+
},
72+
})
73+
74+
// Get Bobs keys, there should be two
75+
queryKeys := client.WithJSONBody(t, map[string]interface{}{
76+
"device_keys": map[string][]string{
77+
bob.UserID: {},
78+
},
79+
})
80+
resp = alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, queryKeys)
81+
keyCount := 0
82+
must.MatchResponse(t, resp, match.HTTPResponse{
83+
StatusCode: http.StatusOK,
84+
JSON: []match.JSON{
85+
match.JSONMapEach("device_keys."+bob.UserID, func(k, v gjson.Result) error {
86+
keyCount++
87+
return nil
88+
}),
89+
},
90+
})
91+
wantKeyCount := 2
92+
if keyCount != wantKeyCount {
93+
t.Fatalf("unexpected key count: got %d, want %d", keyCount, wantKeyCount)
94+
}
95+
})
96+
}
97+
98+
func mustUploadKeys(t *testing.T, user *client.CSAPI) {
99+
t.Helper()
100+
deviceKeys, oneTimeKeys := generateKeys(t, user, 5)
101+
reqBody := client.WithJSONBody(t, map[string]interface{}{
102+
"device_keys": deviceKeys,
103+
"one_time_keys": oneTimeKeys,
104+
})
105+
user.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody)
106+
}

tests/csapi/upload_keys_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,15 +173,15 @@ func TestUploadKey(t *testing.T) {
173173
})
174174
}
175175

176-
func generateKeys(t *testing.T, user *client.CSAPI, otkCount uint) (map[string]interface{}, map[string]interface{}) {
176+
func generateKeys(t *testing.T, user *client.CSAPI, otkCount uint) (deviceKeys map[string]interface{}, oneTimeKeys map[string]interface{}) {
177177
t.Helper()
178178
account := olm.NewAccount()
179179
ed25519Key, curveKey := account.IdentityKeys()
180180

181181
ed25519KeyID := fmt.Sprintf("ed25519:%s", user.DeviceID)
182182
curveKeyID := fmt.Sprintf("curve25519:%s", user.DeviceID)
183183

184-
deviceKeys := map[string]interface{}{
184+
deviceKeys = map[string]interface{}{
185185
"user_id": user.UserID,
186186
"device_id": user.DeviceID,
187187
"algorithms": []interface{}{"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"},
@@ -200,8 +200,7 @@ func generateKeys(t *testing.T, user *client.CSAPI, otkCount uint) (map[string]i
200200
}
201201

202202
account.GenOneTimeKeys(otkCount)
203-
204-
oneTimeKeys := map[string]interface{}{}
203+
oneTimeKeys = map[string]interface{}{}
205204

206205
for kid, key := range account.OneTimeKeys() {
207206
keyID := fmt.Sprintf("signed_curve25519:%s", kid)

tests/federation_upload_keys_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,15 @@ func TestFederationKeyUploadQuery(t *testing.T) {
123123
})
124124
}
125125

126-
func generateKeys(t *testing.T, user *client.CSAPI, otkCount uint) (map[string]interface{}, map[string]interface{}) {
126+
func generateKeys(t *testing.T, user *client.CSAPI, otkCount uint) (deviceKeys map[string]interface{}, oneTimeKeys map[string]interface{}) {
127127
t.Helper()
128128
account := olm.NewAccount()
129129
ed25519Key, curveKey := account.IdentityKeys()
130130

131131
ed25519KeyID := fmt.Sprintf("ed25519:%s", user.DeviceID)
132132
curveKeyID := fmt.Sprintf("curve25519:%s", user.DeviceID)
133133

134-
deviceKeys := map[string]interface{}{
134+
deviceKeys = map[string]interface{}{
135135
"user_id": user.UserID,
136136
"device_id": user.DeviceID,
137137
"algorithms": []interface{}{"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"},
@@ -150,8 +150,7 @@ func generateKeys(t *testing.T, user *client.CSAPI, otkCount uint) (map[string]i
150150
}
151151

152152
account.GenOneTimeKeys(otkCount)
153-
154-
oneTimeKeys := map[string]interface{}{}
153+
oneTimeKeys = map[string]interface{}{}
155154

156155
for kid, key := range account.OneTimeKeys() {
157156
keyID := fmt.Sprintf("signed_curve25519:%s", kid)

0 commit comments

Comments
 (0)