-
Notifications
You must be signed in to change notification settings - Fork 56
Add Equal method for CrossSigningKey #444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ | |
| package fclient | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "encoding/json" | ||
|
|
||
| "github.com/matrix-org/gomatrixserverlib" | ||
|
|
@@ -46,6 +47,49 @@ type CrossSigningKey struct { | |
|
|
||
| func (s *CrossSigningKey) isCrossSigningBody() {} // implements CrossSigningBody | ||
|
|
||
| func (s *CrossSigningKey) Equal(other *CrossSigningKey) bool { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to document what the comparison is taking into account, i.e. there can be different equality implementations depending on the use-case. I presume here we care about the fact that a new object needs to be stored in the DB and we test for equality of all fields.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly. The |
||
| if s == nil || other == nil { | ||
| return false | ||
| } | ||
| if s.UserID != other.UserID { | ||
| return false | ||
| } | ||
| if len(s.Usage) != len(other.Usage) { | ||
| return false | ||
| } | ||
| for i := range s.Usage { | ||
| if s.Usage[i] != other.Usage[i] { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this slice guaranteed to be ordered? If not you might get some false negatives.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair point, but does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per spec no, but you want to be forwards compatible, otherwise you might need to prevent such cross signing keys from being uploaded.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 30cbdb4 |
||
| return false | ||
| } | ||
| } | ||
| if len(s.Keys) != len(other.Keys) { | ||
| return false | ||
| } | ||
| for k, v := range s.Keys { | ||
| if !bytes.Equal(other.Keys[k], v) { | ||
| return false | ||
| } | ||
| } | ||
| if len(s.Signatures) != len(other.Signatures) { | ||
| return false | ||
| } | ||
| for k, v := range s.Signatures { | ||
| otherV, ok := other.Signatures[k] | ||
| if !ok { | ||
| return false | ||
| } | ||
| if len(v) != len(otherV) { | ||
| return false | ||
| } | ||
| for k2, v2 := range v { | ||
| if !bytes.Equal(otherV[k2], v2) { | ||
| return false | ||
| } | ||
| } | ||
| } | ||
| return true | ||
| } | ||
|
|
||
| type CrossSigningBody interface { | ||
| isCrossSigningBody() | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| package fclient | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/matrix-org/gomatrixserverlib" | ||
| "github.com/matrix-org/gomatrixserverlib/spec" | ||
| ) | ||
|
|
||
| func TestCrossSigningKeyEqual(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| s *CrossSigningKey | ||
| other *CrossSigningKey | ||
| expect bool | ||
| }{ | ||
| { | ||
| name: "NilReceiver_ReturnsFalse", | ||
| s: nil, | ||
| other: &CrossSigningKey{}, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "NilOther_ReturnsFalse", | ||
| s: &CrossSigningKey{}, | ||
| other: nil, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "DifferentUserID_ReturnsFalse", | ||
| s: &CrossSigningKey{UserID: "user1"}, | ||
| other: &CrossSigningKey{UserID: "user2"}, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "DifferentUsageLength_ReturnsFalse", | ||
| s: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster}}, | ||
| other: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster, CrossSigningKeyPurposeSelfSigning}}, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "DifferentUsageValues_ReturnsFalse", | ||
| s: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster}}, | ||
| other: &CrossSigningKey{Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeSelfSigning}}, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "DifferentKeysLength_ReturnsFalse", | ||
| s: &CrossSigningKey{Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}}}, | ||
| other: &CrossSigningKey{Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}, "key2": {}}}, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "DifferentKeysValues_ReturnsFalse", | ||
| s: &CrossSigningKey{Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}}}, | ||
| other: &CrossSigningKey{Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {1}}}, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "DifferentSignaturesLength_ReturnsFalse", | ||
| s: &CrossSigningKey{Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}}}, | ||
| other: &CrossSigningKey{Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}, "sig2": {"key2": {}}}}, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "DifferentSignaturesValues_ReturnsFalse", | ||
| s: &CrossSigningKey{Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}}}, | ||
| other: &CrossSigningKey{Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {1}}}}, | ||
| expect: false, | ||
| }, | ||
| { | ||
| name: "IdenticalKeys_ReturnsTrue", | ||
| s: &CrossSigningKey{ | ||
| UserID: "user1", | ||
| Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster}, | ||
| Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}}, | ||
| Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}}, | ||
| }, | ||
| other: &CrossSigningKey{ | ||
| UserID: "user1", | ||
| Usage: []CrossSigningKeyPurpose{CrossSigningKeyPurposeMaster}, | ||
| Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{"key1": {}}, | ||
| Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{"sig1": {"key1": {}}}, | ||
| }, | ||
| expect: true, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| if got := tt.s.Equal(tt.other); got != tt.expect { | ||
| t.Errorf("Equal() = %v, want %v", got, tt.expect) | ||
| } | ||
| }) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we just use
reflect.DeepEqualhere?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is does not allocate at all, while
reflect.DeepEqualdoes. (not that it matters much on that endpoint)