Improvements to Equals methods for actor and activity

This commit is contained in:
mariusor 2022-05-24 10:56:26 +02:00
parent 4837641dc8
commit e8c528edf3
No known key found for this signature in database
GPG key ID: DBF5E47F5DBC4D21
6 changed files with 388 additions and 40 deletions

View file

@ -860,9 +860,9 @@ func (a *Activity) GobDecode(data []byte) error {
// Equals verifies if our receiver Object is equals with the "with" Object
func (a Activity) Equals(with Item) bool {
result := true
OnActivity(with, func(w *Activity) error {
OnObject(a, func(o *Object) error {
result = o.Equals(w)
err := OnActivity(with, func(w *Activity) error {
OnObject(a, func(oa *Object) error {
result = oa.Equals(w)
return nil
})
if w.Object != nil {
@ -909,5 +909,8 @@ func (a Activity) Equals(with Item) bool {
}
return nil
})
if err != nil {
result = false
}
return result
}

View file

@ -1459,3 +1459,128 @@ func TestIntransitiveActivity_MarshalJSON(t *testing.T) {
})
}
}
func TestActivity_Equals(t *testing.T) {
type fields struct {
ID ID
Type ActivityVocabularyType
Name NaturalLanguageValues
Attachment Item
AttributedTo Item
Audience ItemCollection
Content NaturalLanguageValues
Context Item
MediaType MimeType
EndTime time.Time
Generator Item
Icon Item
Image Item
InReplyTo Item
Location Item
Preview Item
Published time.Time
Replies Item
StartTime time.Time
Summary NaturalLanguageValues
Tag ItemCollection
Updated time.Time
URL Item
To ItemCollection
Bto ItemCollection
CC ItemCollection
BCC ItemCollection
Duration time.Duration
Likes Item
Shares Item
Source Source
Actor Item
Target Item
Result Item
Origin Item
Instrument Item
Object Item
}
tests := []struct {
name string
fields fields
arg Item
want bool
}{
{
name: "equal-empty-activity",
fields: fields{},
arg: Activity{},
want: true,
},
{
name: "equal-activity-just-id",
fields: fields{ID: "test"},
arg: Activity{ID: "test"},
want: true,
},
{
name: "equal-activity-id",
fields: fields{ID: "test", URL: IRI("example.com")},
arg: Activity{ID: "test"},
want: true,
},
{
name: "equal-false-with-id-and-url",
fields: fields{ID: "test"},
arg: Activity{ID: "test", URL: IRI("example.com")},
want: false,
},
{
name: "not a valid activity",
fields: fields{ID: "http://example.com"},
arg: Link{ID: "http://example.com"},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := Activity{
ID: tt.fields.ID,
Type: tt.fields.Type,
Name: tt.fields.Name,
Attachment: tt.fields.Attachment,
AttributedTo: tt.fields.AttributedTo,
Audience: tt.fields.Audience,
Content: tt.fields.Content,
Context: tt.fields.Context,
MediaType: tt.fields.MediaType,
EndTime: tt.fields.EndTime,
Generator: tt.fields.Generator,
Icon: tt.fields.Icon,
Image: tt.fields.Image,
InReplyTo: tt.fields.InReplyTo,
Location: tt.fields.Location,
Preview: tt.fields.Preview,
Published: tt.fields.Published,
Replies: tt.fields.Replies,
StartTime: tt.fields.StartTime,
Summary: tt.fields.Summary,
Tag: tt.fields.Tag,
Updated: tt.fields.Updated,
URL: tt.fields.URL,
To: tt.fields.To,
Bto: tt.fields.Bto,
CC: tt.fields.CC,
BCC: tt.fields.BCC,
Duration: tt.fields.Duration,
Likes: tt.fields.Likes,
Shares: tt.fields.Shares,
Source: tt.fields.Source,
Actor: tt.fields.Actor,
Target: tt.fields.Target,
Result: tt.fields.Result,
Origin: tt.fields.Origin,
Instrument: tt.fields.Instrument,
Object: tt.fields.Object,
}
if got := a.Equals(tt.arg); got != tt.want {
t.Errorf("Equals() = %v, want %v", got, tt.want)
}
})
}
}

View file

@ -516,16 +516,40 @@ func ToActor(it Item) (*Actor, error) {
// Equals verifies if our receiver Object is equals with the "with" Object
func (a Actor) Equals(with Item) bool {
result := true
OnActor(with, func(w *Actor) error {
OnObject(w, func(wo *Object) error {
if !wo.Equals(a) {
err := OnActor(with, func(w *Actor) error {
OnObject(a, func(oa *Object) error {
result = oa.Equals(w)
return nil
})
if w.Inbox != nil {
if !ItemsEqual(a.Inbox, w.Inbox) {
result = false
return nil
}
}
if w.Outbox != nil {
if !ItemsEqual(a.Outbox, w.Outbox) {
result = false
return nil
}
}
if w.Liked != nil {
if !ItemsEqual(a.Liked, w.Liked) {
result = false
return nil
}
}
if w.PreferredUsername != nil {
if !a.PreferredUsername.Equals(w.PreferredUsername) {
result = false
return nil
}
}
return nil
})
return nil
})
if err != nil {
result = false
}
return result
}

View file

@ -4,6 +4,7 @@ import (
"fmt"
"reflect"
"testing"
"time"
)
func TestActorNew(t *testing.T) {
@ -437,3 +438,134 @@ func TestOnActor(t *testing.T) {
})
}
}
func TestActor_Equals(t *testing.T) {
type fields struct {
ID ID
Type ActivityVocabularyType
Name NaturalLanguageValues
Attachment Item
AttributedTo Item
Audience ItemCollection
Content NaturalLanguageValues
Context Item
MediaType MimeType
EndTime time.Time
Generator Item
Icon Item
Image Item
InReplyTo Item
Location Item
Preview Item
Published time.Time
Replies Item
StartTime time.Time
Summary NaturalLanguageValues
Tag ItemCollection
Updated time.Time
URL Item
To ItemCollection
Bto ItemCollection
CC ItemCollection
BCC ItemCollection
Duration time.Duration
Likes Item
Shares Item
Source Source
Inbox Item
Outbox Item
Following Item
Followers Item
Liked Item
PreferredUsername NaturalLanguageValues
Endpoints *Endpoints
Streams ItemCollection
PublicKey PublicKey
}
tests := []struct {
name string
fields fields
arg Item
want bool
}{
{
name: "equal-empty-actor",
fields: fields{},
arg: Actor{},
want: true,
},
{
name: "equal-actor-just-id",
fields: fields{ID: "test"},
arg: Actor{ID: "test"},
want: true,
},
{
name: "equal-actor-id",
fields: fields{ID: "test", URL: IRI("example.com")},
arg: Actor{ID: "test"},
want: true,
},
{
name: "equal-false-with-id-and-url",
fields: fields{ID: "test"},
arg: Actor{ID: "test", URL: IRI("example.com")},
want: false,
},
{
name: "not a valid actor",
fields: fields{ID: "http://example.com"},
arg: Activity{ID: "http://example.com"},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := Actor{
ID: tt.fields.ID,
Type: tt.fields.Type,
Name: tt.fields.Name,
Attachment: tt.fields.Attachment,
AttributedTo: tt.fields.AttributedTo,
Audience: tt.fields.Audience,
Content: tt.fields.Content,
Context: tt.fields.Context,
MediaType: tt.fields.MediaType,
EndTime: tt.fields.EndTime,
Generator: tt.fields.Generator,
Icon: tt.fields.Icon,
Image: tt.fields.Image,
InReplyTo: tt.fields.InReplyTo,
Location: tt.fields.Location,
Preview: tt.fields.Preview,
Published: tt.fields.Published,
Replies: tt.fields.Replies,
StartTime: tt.fields.StartTime,
Summary: tt.fields.Summary,
Tag: tt.fields.Tag,
Updated: tt.fields.Updated,
URL: tt.fields.URL,
To: tt.fields.To,
Bto: tt.fields.Bto,
CC: tt.fields.CC,
BCC: tt.fields.BCC,
Duration: tt.fields.Duration,
Likes: tt.fields.Likes,
Shares: tt.fields.Shares,
Source: tt.fields.Source,
Inbox: tt.fields.Inbox,
Outbox: tt.fields.Outbox,
Following: tt.fields.Following,
Followers: tt.fields.Followers,
Liked: tt.fields.Liked,
PreferredUsername: tt.fields.PreferredUsername,
Endpoints: tt.fields.Endpoints,
Streams: tt.fields.Streams,
PublicKey: tt.fields.PublicKey,
}
if got := a.Equals(tt.arg); got != tt.want {
t.Errorf("Equals() = %v, want %v", got, tt.want)
}
})
}
}

View file

@ -640,7 +640,7 @@ func (o Object) Equals(with Item) bool {
return false
}
result := true
OnObject(with, func(w *Object) error {
err := OnObject(with, func(w *Object) error {
if len(w.Name) > 0 {
if !w.Name.Equals(o.Name) {
result = false
@ -809,5 +809,8 @@ func (o Object) Equals(with Item) bool {
}
return nil
})
if err != nil {
result = false
}
return result
}

View file

@ -926,51 +926,112 @@ func TestSource_MarshalJSON(t *testing.T) {
}
func TestObject_Equals(t *testing.T) {
type args struct {
with Object
type fields struct {
ID ID
Type ActivityVocabularyType
Name NaturalLanguageValues
Attachment Item
AttributedTo Item
Audience ItemCollection
Content NaturalLanguageValues
Context Item
MediaType MimeType
EndTime time.Time
Generator Item
Icon Item
Image Item
InReplyTo Item
Location Item
Preview Item
Published time.Time
Replies Item
StartTime time.Time
Summary NaturalLanguageValues
Tag ItemCollection
Updated time.Time
URL Item
To ItemCollection
Bto ItemCollection
CC ItemCollection
BCC ItemCollection
Duration time.Duration
Likes Item
Shares Item
Source Source
}
tests := []struct {
name string
o Object
args args
fields fields
arg Item
want bool
}{
{
name: "equal-empty-object",
o: Object{},
args: args{
with: Object{},
},
fields: fields{},
arg: Object{},
want: true,
},
{
name: "equal-object-just-id",
o: Object{ID: "test"},
args: args{
with: Object{ID: "test"},
},
fields: fields{ID: "test"},
arg: Object{ID: "test"},
want: true,
},
{
name: "equal-object-id",
o: Object{ID: "test", URL: IRI("example.com")},
args: args{
with: Object{ID: "test"},
},
fields: fields{ID: "test", URL: IRI("example.com")},
arg: Object{ID: "test"},
want: true,
},
{
name: "equal-false-with-id-and-url",
o: Object{ID: "test"},
args: args{
with: Object{ID: "test", URL: IRI("example.com")},
fields: fields{ID: "test"},
arg: Object{ID: "test", URL: IRI("example.com")},
want: false,
},
{
name: "not a valid object",
fields: fields{ID: "http://example.com"},
arg: Link{ID: "http://example.com"},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.o.Equals(tt.args.with); got != tt.want {
o := Object{
ID: tt.fields.ID,
Type: tt.fields.Type,
Name: tt.fields.Name,
Attachment: tt.fields.Attachment,
AttributedTo: tt.fields.AttributedTo,
Audience: tt.fields.Audience,
Content: tt.fields.Content,
Context: tt.fields.Context,
MediaType: tt.fields.MediaType,
EndTime: tt.fields.EndTime,
Generator: tt.fields.Generator,
Icon: tt.fields.Icon,
Image: tt.fields.Image,
InReplyTo: tt.fields.InReplyTo,
Location: tt.fields.Location,
Preview: tt.fields.Preview,
Published: tt.fields.Published,
Replies: tt.fields.Replies,
StartTime: tt.fields.StartTime,
Summary: tt.fields.Summary,
Tag: tt.fields.Tag,
Updated: tt.fields.Updated,
URL: tt.fields.URL,
To: tt.fields.To,
Bto: tt.fields.Bto,
CC: tt.fields.CC,
BCC: tt.fields.BCC,
Duration: tt.fields.Duration,
Likes: tt.fields.Likes,
Shares: tt.fields.Shares,
Source: tt.fields.Source,
}
if got := o.Equals(tt.arg); got != tt.want {
t.Errorf("Equals() = %v, want %v", got, tt.want)
}
})