Skip to content

Commit bf86bc9

Browse files
authored
Add Equal method for CrossSigningKey (#444)
Playing around with Copilot, code is mostly generated (but reviewed) Also fixes CI by using the correct repository for Dendrite.
1 parent e86ab16 commit bf86bc9

File tree

3 files changed

+173
-1
lines changed

3 files changed

+173
-1
lines changed

.github/workflows/tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ jobs:
8787
steps:
8888
- uses: actions/checkout@v3
8989
with:
90-
repository: "matrix-org/dendrite"
90+
repository: "element-hq/dendrite"
9191
- name: Install libolm
9292
run: sudo apt-get install libolm-dev libolm3
9393
- name: Setup go

fclient/crosssigning.go

+53
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
package fclient
1616

1717
import (
18+
"bytes"
1819
"encoding/json"
20+
"slices"
1921

2022
"github.com/matrix-org/gomatrixserverlib"
2123
"github.com/matrix-org/gomatrixserverlib/spec"
@@ -46,6 +48,57 @@ type CrossSigningKey struct {
4648

4749
func (s *CrossSigningKey) isCrossSigningBody() {} // implements CrossSigningBody
4850

51+
func (s *CrossSigningKey) Equal(other *CrossSigningKey) bool {
52+
if s == nil || other == nil {
53+
return false
54+
}
55+
if s.UserID != other.UserID {
56+
return false
57+
}
58+
if len(s.Usage) != len(other.Usage) {
59+
return false
60+
}
61+
62+
// Make sure the slices are sorted before we compare them.
63+
if !slices.IsSorted(s.Usage) {
64+
slices.Sort(s.Usage)
65+
}
66+
if !slices.IsSorted(other.Usage) {
67+
slices.Sort(other.Usage)
68+
}
69+
for i := range s.Usage {
70+
if s.Usage[i] != other.Usage[i] {
71+
return false
72+
}
73+
}
74+
if len(s.Keys) != len(other.Keys) {
75+
return false
76+
}
77+
for k, v := range s.Keys {
78+
if !bytes.Equal(other.Keys[k], v) {
79+
return false
80+
}
81+
}
82+
if len(s.Signatures) != len(other.Signatures) {
83+
return false
84+
}
85+
for k, v := range s.Signatures {
86+
otherV, ok := other.Signatures[k]
87+
if !ok {
88+
return false
89+
}
90+
if len(v) != len(otherV) {
91+
return false
92+
}
93+
for k2, v2 := range v {
94+
if !bytes.Equal(otherV[k2], v2) {
95+
return false
96+
}
97+
}
98+
}
99+
return true
100+
}
101+
49102
type CrossSigningBody interface {
50103
isCrossSigningBody()
51104
}

fclient/crosssigning_test.go

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package fclient
2+
3+
import (
4+
"testing"
5+
6+
"github.com/matrix-org/gomatrixserverlib"
7+
"github.com/matrix-org/gomatrixserverlib/spec"
8+
)
9+
10+
var tests = []struct {
11+
name string
12+
s *CrossSigningKey
13+
other *CrossSigningKey
14+
expect bool
15+
}{
16+
{
17+
name: "NilReceiver_ReturnsFalse",
18+
s: nil,
19+
other: &CrossSigningKey{},
20+
expect: false,
21+
},
22+
{
23+
name: "NilOther_ReturnsFalse",
24+
s: &CrossSigningKey{},
25+
other: nil,
26+
expect: false,
27+
},
28+
{
29+
name: "DifferentUserID_ReturnsFalse",
30+
s: &CrossSigningKey{UserID: "user1"},
31+
other: &CrossSigningKey{UserID: "user2"},
32+
expect: false,
33+
},
34+
{
35+
name: "DifferentUsageLength_ReturnsFalse",
36+
s: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster}},
37+
other: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster, CrossSigningKeyPurposeSelfSigning}},
38+
expect: false,
39+
},
40+
{
41+
name: "UnsortedUsages_ReturnsTrue",
42+
s: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeSelfSigning, CrossSigningKeyPurposeMaster}},
43+
other: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster, CrossSigningKeyPurposeSelfSigning}},
44+
expect: true,
45+
},
46+
{
47+
name: "UnsortedUsages_ReturnsTrue",
48+
s: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeSelfSigning, CrossSigningKeyPurposeMaster}},
49+
other: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeSelfSigning, CrossSigningKeyPurposeMaster}},
50+
expect: true,
51+
},
52+
{
53+
name: "DifferentUsageValues_ReturnsFalse",
54+
s: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster}},
55+
other: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeSelfSigning}},
56+
expect: false,
57+
},
58+
{
59+
name: "DifferentKeysLength_ReturnsFalse",
60+
s: &CrossSigningKey{Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}}},
61+
other: &CrossSigningKey{Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}, "key2": {}}},
62+
expect: false,
63+
},
64+
{
65+
name: "DifferentKeysValues_ReturnsFalse",
66+
s: &CrossSigningKey{Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}}},
67+
other: &CrossSigningKey{Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {1}}},
68+
expect: false,
69+
},
70+
{
71+
name: "DifferentSignaturesLength_ReturnsFalse",
72+
s: &CrossSigningKey{Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}}},
73+
other: &CrossSigningKey{Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}, "sig2": {"key2": {}}}},
74+
expect: false,
75+
},
76+
{
77+
name: "DifferentSignaturesValues_ReturnsFalse",
78+
s: &CrossSigningKey{Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}}},
79+
other: &CrossSigningKey{Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {1}}}},
80+
expect: false,
81+
},
82+
{
83+
name: "IdenticalKeys_ReturnsTrue",
84+
s: &CrossSigningKey{
85+
UserID: "user1",
86+
Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster},
87+
Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}},
88+
Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}},
89+
},
90+
other: &CrossSigningKey{
91+
UserID: "user1",
92+
Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster},
93+
Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}},
94+
Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}},
95+
},
96+
expect: true,
97+
},
98+
}
99+
100+
func TestCrossSigningKeyEqual(t *testing.T) {
101+
for _, tt := range tests {
102+
t.Run(tt.name, func(t *testing.T) {
103+
if got := tt.s.Equal(tt.other); got != tt.expect {
104+
t.Errorf("Equal() = %v, want %v", got, tt.expect)
105+
}
106+
})
107+
}
108+
}
109+
110+
func BenchmarkEqual(b *testing.B) {
111+
112+
for i := 0; i < b.N; i++ {
113+
for _, tt := range tests {
114+
if !tt.s.Equal(tt.other) && tt.expect {
115+
b.Fatal(tt.name, tt.s)
116+
}
117+
}
118+
}
119+
}

0 commit comments

Comments
 (0)