679 lines
15 KiB
Go
679 lines
15 KiB
Go
package activitypub
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func assertObjectWithTesting(fn canErrorFunc, expected Item) WithObjectFn {
|
|
return func(p *Object) error {
|
|
if !assertDeepEquals(fn, p, expected) {
|
|
return fmt.Errorf("not equal")
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func TestOnObject(t *testing.T) {
|
|
testObject := Object{
|
|
ID: "https://example.com",
|
|
}
|
|
type args struct {
|
|
it Item
|
|
fn func(canErrorFunc, Item) WithObjectFn
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
expected Item
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "single",
|
|
args: args{testObject, assertObjectWithTesting},
|
|
expected: &testObject,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "single fails",
|
|
args: args{Object{ID: "https://not-equals"}, assertObjectWithTesting},
|
|
expected: &testObject,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "collectionOfObjects",
|
|
args: args{ItemCollection{testObject, testObject}, assertObjectWithTesting},
|
|
expected: &testObject,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "collectionOfObjects fails",
|
|
args: args{ItemCollection{testObject, Object{ID: "https://not-equals"}}, assertObjectWithTesting},
|
|
expected: &testObject,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
var logFn canErrorFunc
|
|
if tt.wantErr {
|
|
logFn = t.Logf
|
|
} else {
|
|
logFn = t.Errorf
|
|
}
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if err := OnObject(tt.args.it, tt.args.fn(logFn, tt.expected)); (err != nil) != tt.wantErr {
|
|
t.Errorf("OnObject() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func assertActivityWithTesting(fn canErrorFunc, expected Item) WithActivityFn {
|
|
return func(p *Activity) error {
|
|
if !assertDeepEquals(fn, p, expected) {
|
|
return fmt.Errorf("not equal")
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func TestOnActivity(t *testing.T) {
|
|
testActivity := Activity{
|
|
ID: "https://example.com",
|
|
}
|
|
type args struct {
|
|
it Item
|
|
fn func(canErrorFunc, Item) WithActivityFn
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
expected Item
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "single",
|
|
args: args{testActivity, assertActivityWithTesting},
|
|
expected: &testActivity,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "single fails",
|
|
args: args{Activity{ID: "https://not-equals"}, assertActivityWithTesting},
|
|
expected: &testActivity,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "collectionOfActivitys",
|
|
args: args{ItemCollection{testActivity, testActivity}, assertActivityWithTesting},
|
|
expected: &testActivity,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "collectionOfActivitys fails",
|
|
args: args{ItemCollection{testActivity, Activity{ID: "https://not-equals"}}, assertActivityWithTesting},
|
|
expected: &testActivity,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
var logFn canErrorFunc
|
|
if tt.wantErr {
|
|
logFn = t.Logf
|
|
} else {
|
|
logFn = t.Errorf
|
|
}
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if err := OnActivity(tt.args.it, tt.args.fn(logFn, tt.expected)); (err != nil) != tt.wantErr {
|
|
t.Errorf("OnActivity() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func assertIntransitiveActivityWithTesting(fn canErrorFunc, expected Item) WithIntransitiveActivityFn {
|
|
return func(p *IntransitiveActivity) error {
|
|
if !assertDeepEquals(fn, p, expected) {
|
|
return fmt.Errorf("not equal")
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func TestOnIntransitiveActivity(t *testing.T) {
|
|
testIntransitiveActivity := IntransitiveActivity{
|
|
ID: "https://example.com",
|
|
}
|
|
type args struct {
|
|
it Item
|
|
fn func(canErrorFunc, Item) WithIntransitiveActivityFn
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
expected Item
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "single",
|
|
args: args{testIntransitiveActivity, assertIntransitiveActivityWithTesting},
|
|
expected: &testIntransitiveActivity,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "single fails",
|
|
args: args{IntransitiveActivity{ID: "https://not-equals"}, assertIntransitiveActivityWithTesting},
|
|
expected: &testIntransitiveActivity,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "collectionOfIntransitiveActivitys",
|
|
args: args{ItemCollection{testIntransitiveActivity, testIntransitiveActivity}, assertIntransitiveActivityWithTesting},
|
|
expected: &testIntransitiveActivity,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "collectionOfIntransitiveActivitys fails",
|
|
args: args{ItemCollection{testIntransitiveActivity, IntransitiveActivity{ID: "https://not-equals"}}, assertIntransitiveActivityWithTesting},
|
|
expected: &testIntransitiveActivity,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
var logFn canErrorFunc
|
|
if tt.wantErr {
|
|
logFn = t.Logf
|
|
} else {
|
|
logFn = t.Errorf
|
|
}
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if err := OnIntransitiveActivity(tt.args.it, tt.args.fn(logFn, tt.expected)); (err != nil) != tt.wantErr {
|
|
t.Errorf("OnIntransitiveActivity() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func assertQuestionWithTesting(fn canErrorFunc, expected Item) WithQuestionFn {
|
|
return func(p *Question) error {
|
|
if !assertDeepEquals(fn, p, expected) {
|
|
return fmt.Errorf("not equal")
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func TestOnQuestion(t *testing.T) {
|
|
testQuestion := Question{
|
|
ID: "https://example.com",
|
|
}
|
|
type args struct {
|
|
it Item
|
|
fn func(canErrorFunc, Item) WithQuestionFn
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
expected Item
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "single",
|
|
args: args{testQuestion, assertQuestionWithTesting},
|
|
expected: &testQuestion,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "single fails",
|
|
args: args{Question{ID: "https://not-equals"}, assertQuestionWithTesting},
|
|
expected: &testQuestion,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "collectionOfQuestions",
|
|
args: args{ItemCollection{testQuestion, testQuestion}, assertQuestionWithTesting},
|
|
expected: &testQuestion,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "collectionOfQuestions fails",
|
|
args: args{ItemCollection{testQuestion, Question{ID: "https://not-equals"}}, assertQuestionWithTesting},
|
|
expected: &testQuestion,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
var logFn canErrorFunc
|
|
if tt.wantErr {
|
|
logFn = t.Logf
|
|
} else {
|
|
logFn = t.Errorf
|
|
}
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if err := OnQuestion(tt.args.it, tt.args.fn(logFn, tt.expected)); (err != nil) != tt.wantErr {
|
|
t.Errorf("OnQuestion() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOnCollection(t *testing.T) {
|
|
t.Skipf("TODO")
|
|
}
|
|
|
|
func TestOnCollectionPage(t *testing.T) {
|
|
t.Skipf("TODO")
|
|
}
|
|
|
|
func TestOnOrderedCollectionPage(t *testing.T) {
|
|
t.Skipf("TODO")
|
|
}
|
|
|
|
type args[T Objects] struct {
|
|
it T
|
|
fn func(fn canErrorFunc, expected T) func(*T) error
|
|
}
|
|
|
|
type testPair[T Objects] struct {
|
|
name string
|
|
args args[T]
|
|
expected T
|
|
wantErr bool
|
|
}
|
|
|
|
func assert[T Objects](fn canErrorFunc, expected T) func(*T) error {
|
|
return func(p *T) error {
|
|
if !assertDeepEquals(fn, *p, expected) {
|
|
return fmt.Errorf("not equal")
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func TestOn(t *testing.T) {
|
|
var tests = []testPair[Object]{
|
|
{
|
|
name: "single object",
|
|
args: args[Object]{Object{ID: "https://example.com"}, assert[Object]},
|
|
expected: Object{ID: "https://example.com"},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "single image",
|
|
args: args[Image]{Image{ID: "http://example.com"}, assert[Image]},
|
|
expected: Image{ID: "http://example.com"},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
var logFn canErrorFunc
|
|
if tt.wantErr {
|
|
logFn = t.Logf
|
|
} else {
|
|
logFn = t.Errorf
|
|
}
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if err := On(tt.args.it, tt.args.fn(logFn, tt.expected)); (err != nil) != tt.wantErr {
|
|
t.Errorf("On[%T]() error = %v, wantErr %v", tt.args.it, err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var (
|
|
emptyPrintFn = func(string, ...any) {}
|
|
|
|
fnPrintObj = func(printFn func(string, ...any)) func(_ *Object) error {
|
|
return func(o *Object) error {
|
|
printFn("%v", o)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
fnObj = func(_ *Object) error { return nil }
|
|
fnAct = func(_ *Actor) error { return nil }
|
|
fnA = func(_ *Activity) error { return nil }
|
|
fnIA = func(_ *IntransitiveActivity) error { return nil }
|
|
|
|
maybeObject Item = new(Object)
|
|
notObject Item = new(Activity)
|
|
maybeActor Item = new(Actor)
|
|
maybeActivity Item = new(Activity)
|
|
notIntransitiveActivity Item = new(Activity)
|
|
maybeIntransitiveActivity Item = new(IntransitiveActivity)
|
|
colOfObjects Item = ItemCollection{Object{ID: "unum"}, Object{ID: "duo"}}
|
|
colOfNotObjects Item = ItemCollection{Activity{ID: "unum"}, Activity{ID: "duo"}}
|
|
)
|
|
|
|
func Benchmark_ToObject(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
ToObject(maybeObject)
|
|
}
|
|
}
|
|
|
|
func Benchmark_To_T_Object(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
To[Object](maybeObject)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ToActor(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
ToActor(maybeActor)
|
|
}
|
|
}
|
|
|
|
func Benchmark_To_T_Actor(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
To[Actor](maybeActor)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ToActivity(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
ToActivity(maybeActivity)
|
|
}
|
|
}
|
|
|
|
func Benchmark_To_T_Activity(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
To[Activity](maybeActivity)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ToIntransitiveActivityHappy(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
ToIntransitiveActivity(maybeIntransitiveActivity)
|
|
}
|
|
}
|
|
|
|
func Benchmark_To_T_IntransitiveActivityHappy(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
To[IntransitiveActivity](maybeIntransitiveActivity)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ToIntransitiveActivityNotHappy(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
ToIntransitiveActivity(notIntransitiveActivity)
|
|
}
|
|
}
|
|
|
|
func Benchmark_To_T_IntransitiveActivityNotHappy(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
To[IntransitiveActivity](notIntransitiveActivity)
|
|
}
|
|
}
|
|
|
|
func Benchmark_OnObject(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
OnObject(maybeObject, fnObj)
|
|
}
|
|
}
|
|
|
|
func Benchmark_On_T_Object(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
On[Object](maybeObject, fnObj)
|
|
}
|
|
}
|
|
func Benchmark_OnActor(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
OnActor(maybeObject, fnAct)
|
|
}
|
|
}
|
|
func Benchmark_On_T_Actor(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
On[Actor](maybeObject, fnAct)
|
|
}
|
|
}
|
|
func Benchmark_OnActivity(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
OnActivity(maybeObject, fnA)
|
|
}
|
|
}
|
|
|
|
func Benchmark_On_T_Activity(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
On[Activity](maybeObject, fnA)
|
|
}
|
|
}
|
|
func Benchmark_OnIntransitiveActivity(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
OnIntransitiveActivity(maybeObject, fnIA)
|
|
}
|
|
}
|
|
|
|
func Benchmark_On_T_IntransitiveActivity(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
On[IntransitiveActivity](maybeObject, fnIA)
|
|
}
|
|
}
|
|
func Benchmark_OnObjectNotHappy(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
OnObject(notObject, fnObj)
|
|
}
|
|
}
|
|
|
|
func Benchmark_On_T_ObjectNotHappy(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
On[Object](notObject, fnObj)
|
|
}
|
|
}
|
|
|
|
func Benchmark_OnObjectHappyCol(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
OnObject(colOfObjects, fnObj)
|
|
}
|
|
}
|
|
|
|
func Benchmark_On_T_ObjectHappyCol(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
On[Object](colOfObjects, fnObj)
|
|
}
|
|
}
|
|
|
|
func Benchmark_OnObjectNotHappyCol(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
OnObject(colOfNotObjects, fnObj)
|
|
}
|
|
}
|
|
|
|
func Benchmark_On_T_ObjectNotHappyCol(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
On[Object](colOfNotObjects, fnObj)
|
|
}
|
|
}
|
|
|
|
func TestDerefItem(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
arg Item
|
|
want ItemCollection
|
|
}{
|
|
{
|
|
name: "empty",
|
|
},
|
|
{
|
|
name: "simple object",
|
|
arg: &Object{ID: "https://example.com"},
|
|
want: ItemCollection{&Object{ID: "https://example.com"}},
|
|
},
|
|
{
|
|
name: "simple IRI",
|
|
arg: IRI("https://example.com"),
|
|
want: ItemCollection{IRI("https://example.com")},
|
|
},
|
|
{
|
|
name: "IRI collection",
|
|
arg: IRIs{IRI("https://example.com"), IRI("https://example.com/~jdoe")},
|
|
want: ItemCollection{IRI("https://example.com"), IRI("https://example.com/~jdoe")},
|
|
},
|
|
{
|
|
name: "Item collection",
|
|
arg: ItemCollection{
|
|
&Object{ID: "https://example.com"},
|
|
&Actor{ID: "https://example.com/~jdoe"},
|
|
},
|
|
want: ItemCollection{
|
|
&Object{ID: "https://example.com"},
|
|
&Actor{ID: "https://example.com/~jdoe"},
|
|
},
|
|
},
|
|
{
|
|
name: "mixed item collection",
|
|
arg: ItemCollection{
|
|
&Object{ID: "https://example.com"},
|
|
IRI("https://example.com/666"),
|
|
&Actor{ID: "https://example.com/~jdoe"},
|
|
},
|
|
want: ItemCollection{
|
|
&Object{ID: "https://example.com"},
|
|
IRI("https://example.com/666"),
|
|
&Actor{ID: "https://example.com/~jdoe"},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := DerefItem(tt.arg); !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("DerefItem() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestItemOrderTimestamp(t *testing.T) {
|
|
early1 := time.Date(2001, 6, 6, 6, 0, 0, 0, time.UTC)
|
|
early2 := time.Date(2001, 6, 6, 6, 0, 1, 0, time.UTC)
|
|
late1 := time.Date(2001, 6, 6, 7, 0, 0, 0, time.UTC)
|
|
late2 := time.Date(2001, 6, 6, 7, 0, 1, 0, time.UTC)
|
|
type args struct {
|
|
i1 Item
|
|
i2 Item
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want bool
|
|
}{
|
|
{
|
|
name: "empty",
|
|
args: args{},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "first empty",
|
|
args: args{
|
|
i1: nil,
|
|
i2: &Object{},
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "second empty",
|
|
args: args{
|
|
i1: &Object{},
|
|
i2: nil,
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "empty published/updated",
|
|
args: args{
|
|
i1: &Object{},
|
|
i2: &Object{},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "first has empty published/updated",
|
|
args: args{
|
|
i1: &Object{},
|
|
i2: &Object{Published: early1},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "check published equals",
|
|
args: args{
|
|
i1: &Object{Published: early1},
|
|
i2: &Object{Published: early1},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "check published/updated equals",
|
|
args: args{
|
|
i1: &Object{Published: early2},
|
|
i2: &Object{Updated: early2},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "check updated/published equals",
|
|
args: args{
|
|
i1: &Object{Updated: late1},
|
|
i2: &Object{Published: late1},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "check first published earlier",
|
|
args: args{
|
|
i1: &Object{Published: early1},
|
|
i2: &Object{Published: late1},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "check second published earlier",
|
|
args: args{
|
|
i1: &Object{Published: late1},
|
|
i2: &Object{Published: early1},
|
|
},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "check first updated earlier",
|
|
args: args{
|
|
i1: &Object{Updated: early1},
|
|
i2: &Object{Updated: late1},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "check second updated earlier",
|
|
args: args{
|
|
i1: &Object{Updated: late1},
|
|
i2: &Object{Updated: early1},
|
|
},
|
|
want: true,
|
|
},
|
|
|
|
{
|
|
name: "check first earlier",
|
|
args: args{
|
|
i1: &Object{Published: early1, Updated: late1},
|
|
i2: &Object{Published: early1, Updated: late2},
|
|
},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "check second earlier",
|
|
args: args{
|
|
i1: &Object{Published: early1, Updated: late2},
|
|
i2: &Object{Published: early1, Updated: late1},
|
|
},
|
|
want: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := ItemOrderTimestamp(tt.args.i1, tt.args.i2); got != tt.want {
|
|
t.Errorf("ItemOrderTimestamp() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|