Updated OnX functions to apply the function on an item collection if that's what's being passed to it
This still has the downside that the collection might contain different types of objects but I can't think of a better way to do it at the moment
This commit is contained in:
parent
247f1fbf22
commit
15ac5c20c7
13 changed files with 870 additions and 394 deletions
|
@ -1,6 +1,7 @@
|
|||
package activitypub
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
@ -346,10 +347,6 @@ func TestActor_Clean(t *testing.T) {
|
|||
t.Skipf("TODO")
|
||||
}
|
||||
|
||||
func TestOnActor(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
}
|
||||
|
||||
func TestToActor(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
}
|
||||
|
@ -377,3 +374,66 @@ func TestEndpoints_MarshalJSON(t *testing.T) {
|
|||
func TestPublicKey_MarshalJSON(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
}
|
||||
|
||||
func assertPersonWithTesting(fn canErrorFunc, expected Item) withActorFn {
|
||||
return func (p *Person) error {
|
||||
if !assertDeepEquals(fn, p , expected) {
|
||||
return fmt.Errorf("not equal")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnActor(t *testing.T) {
|
||||
testPerson := Actor{
|
||||
ID: "https://example.com",
|
||||
}
|
||||
type args struct {
|
||||
it Item
|
||||
fn func(canErrorFunc, Item) withActorFn
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expected Item
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "single",
|
||||
args: args{testPerson, assertPersonWithTesting},
|
||||
expected: &testPerson,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "single fails",
|
||||
args: args{Person{ID: "https://not-equals"}, assertPersonWithTesting},
|
||||
expected: &testPerson,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "collectionOfPersons",
|
||||
args: args{ItemCollection{testPerson, testPerson}, assertPersonWithTesting},
|
||||
expected: &testPerson,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "collectionOfPersons fails",
|
||||
args: args{ItemCollection{testPerson, Person{ID: "https://not-equals"}}, assertPersonWithTesting},
|
||||
expected: &testPerson,
|
||||
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 := OnActor(tt.args.it, tt.args.fn(logFn, tt.expected)); (err != nil) != tt.wantErr {
|
||||
t.Errorf("OnPerson() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ var (
|
|||
|
||||
// ItemTyperFunc will return an instance of a struct that implements activitystreams.Item
|
||||
// The default for this package is GetItemByType but can be overwritten
|
||||
var ItemTyperFunc TyperFn
|
||||
var ItemTyperFunc TyperFn = GetItemByType
|
||||
|
||||
// TyperFn is the type of the function which returns an activitystreams.Item struct instance
|
||||
// for a specific ActivityVocabularyType
|
||||
|
|
|
@ -8,26 +8,21 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
type canErrorFunc func(format string, args ...interface{})
|
||||
|
||||
type visit struct {
|
||||
a1 unsafe.Pointer
|
||||
a2 unsafe.Pointer
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
type canErrorFunc func(format string, args ...interface{})
|
||||
|
||||
// See reflect.DeepEqual
|
||||
func assertDeepEquals(t canErrorFunc, x, y interface{}) bool {
|
||||
if x == nil || y == nil {
|
||||
return x == y
|
||||
}
|
||||
v1 := reflect.ValueOf(x)
|
||||
//if v1.CanAddr() {
|
||||
// v1 = v1.Addr()
|
||||
//}
|
||||
v2 := reflect.ValueOf(y)
|
||||
//if v2.CanAddr() {
|
||||
// v2 = v2.Addr()
|
||||
//}
|
||||
if v1.Type() != v2.Type() {
|
||||
t("%T != %T", x, y)
|
||||
return false
|
||||
|
@ -35,6 +30,7 @@ func assertDeepEquals(t canErrorFunc, x, y interface{}) bool {
|
|||
return deepValueEqual(t, v1, v2, make(map[visit]bool), 0)
|
||||
}
|
||||
|
||||
// See reflect.deepValueEqual
|
||||
func deepValueEqual(t canErrorFunc, v1, v2 reflect.Value, visited map[visit]bool, depth int) bool {
|
||||
if !v1.IsValid() || !v2.IsValid() {
|
||||
return v1.IsValid() == v2.IsValid()
|
||||
|
@ -44,27 +40,34 @@ func deepValueEqual(t canErrorFunc, v1, v2 reflect.Value, visited map[visit]bool
|
|||
return false
|
||||
}
|
||||
|
||||
// We want to avoid putting more in the visited map than we need to.
|
||||
// For any possible reference cycle that might be encountered,
|
||||
// hard(t) needs to return true for at least one of the types in the cycle.
|
||||
hard := func(k reflect.Kind) bool {
|
||||
switch k {
|
||||
case reflect.Map, reflect.Slice, reflect.Ptr, reflect.Interface:
|
||||
return true
|
||||
hard := func(v1, v2 reflect.Value) bool {
|
||||
switch v1.Kind() {
|
||||
case reflect.Ptr:
|
||||
return false
|
||||
case reflect.Map, reflect.Slice, reflect.Interface:
|
||||
// Nil pointers cannot be cyclic. Avoid putting them in the visited map.
|
||||
return !v1.IsNil() && !v2.IsNil()
|
||||
}
|
||||
//t("Invalid type for %s", k)
|
||||
return false
|
||||
}
|
||||
|
||||
if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
|
||||
addr1 := unsafe.Pointer(v1.UnsafeAddr())
|
||||
addr2 := unsafe.Pointer(v2.UnsafeAddr())
|
||||
if hard(v1, v2) {
|
||||
var addr1, addr2 unsafe.Pointer
|
||||
if v1.CanAddr() {
|
||||
addr1 = unsafe.Pointer(v1.UnsafeAddr())
|
||||
} else {
|
||||
addr1 = unsafe.Pointer(v1.Pointer())
|
||||
}
|
||||
if v2.CanAddr() {
|
||||
addr2 = unsafe.Pointer(v2.UnsafeAddr())
|
||||
} else {
|
||||
addr2 = unsafe.Pointer(v2.Pointer())
|
||||
}
|
||||
if uintptr(addr1) > uintptr(addr2) {
|
||||
// Canonicalize order to reduce number of entries in visited.
|
||||
// Assumes non-moving garbage collector.
|
||||
addr1, addr2 = addr2, addr1
|
||||
}
|
||||
|
||||
// Short circuit if references are already seen.
|
||||
typ := v1.Type()
|
||||
v := visit{addr1, addr2, typ}
|
||||
|
@ -131,9 +134,14 @@ func deepValueEqual(t canErrorFunc, v1, v2 reflect.Value, visited map[visit]bool
|
|||
return deepValueEqual(t, v1.Elem(), v2.Elem(), visited, depth+1)
|
||||
case reflect.Struct:
|
||||
for i, n := 0, v1.NumField(); i < n; i++ {
|
||||
var (
|
||||
f1 = v1.Field(i); f2 = v2.Field(i)
|
||||
n1 = v1.Type().Field(i).Name; n2 = v2.Type().Field(i).Name
|
||||
t1 = f1.Type().Name(); t2 = f2.Type().Name()
|
||||
)
|
||||
if !deepValueEqual(t, v1.Field(i), v2.Field(i), visited, depth+1) {
|
||||
t("Struct fields at pos %d %s[%s] and %s[%s] are not deeply equal", i, v1.Type().Field(i).Name, v1.Field(i).Type().Name(), v2.Type().Field(i).Name, v2.Field(i).Type().Name())
|
||||
if v1.Field(i).CanAddr() && v2.Field(i).CanAddr() {
|
||||
t("Struct fields at pos %d %s[%s] and %s[%s] are not deeply equal", i, n1, t1, n2, t2)
|
||||
if f1.CanInterface() && f2.CanInterface() {
|
||||
t(" Values: %#v - %#v", v1.Field(i).Interface(), v2.Field(i).Interface())
|
||||
}
|
||||
return false
|
||||
|
@ -167,8 +175,20 @@ func deepValueEqual(t canErrorFunc, v1, v2 reflect.Value, visited map[visit]bool
|
|||
}
|
||||
// Can't do better than this:
|
||||
return false
|
||||
case reflect.String:
|
||||
return v1.String() == v2.String()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v1.Int() == v2.Int()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return v1.Uint() == v2.Uint()
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v1.Float() == v2.Float()
|
||||
case reflect.Bool:
|
||||
return v1.Bool() == v2.Bool()
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return v1.Complex() == v2.Complex()
|
||||
}
|
||||
return true // i guess?
|
||||
return false
|
||||
}
|
||||
|
||||
type testPairs map[ActivityVocabularyType]reflect.Type
|
||||
|
|
64
helpers.go
64
helpers.go
|
@ -28,6 +28,16 @@ func OnLink(it Item, fn withLinkFn) error {
|
|||
|
||||
// OnObject
|
||||
func OnObject(it Item, fn withObjectFn) error {
|
||||
if IsItemCollection(it) {
|
||||
return OnItemCollection(it, func(col *ItemCollection) error {
|
||||
for _, it := range *col {
|
||||
if err := OnObject(it, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
ob, err := ToObject(it)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -37,7 +47,17 @@ func OnObject(it Item, fn withObjectFn) error {
|
|||
|
||||
// OnActivity
|
||||
func OnActivity(it Item, fn withActivityFn) error {
|
||||
act, err := ToActivity(it)
|
||||
if IsItemCollection(it) {
|
||||
return OnItemCollection(it, func(col *ItemCollection) error {
|
||||
for _, it := range *col {
|
||||
if err := OnActivity(it, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
act, err := ToActivity(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -46,7 +66,17 @@ func OnActivity(it Item, fn withActivityFn) error {
|
|||
|
||||
// OnIntransitiveActivity
|
||||
func OnIntransitiveActivity(it Item, fn withIntransitiveActivityFn) error {
|
||||
act, err := ToIntransitiveActivity(it)
|
||||
if IsItemCollection(it) {
|
||||
return OnItemCollection(it, func(col *ItemCollection) error {
|
||||
for _, it := range *col {
|
||||
if err := OnIntransitiveActivity(it, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
act, err := ToIntransitiveActivity(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -55,7 +85,17 @@ func OnIntransitiveActivity(it Item, fn withIntransitiveActivityFn) error {
|
|||
|
||||
// OnQuestion
|
||||
func OnQuestion(it Item, fn withQuestionFn) error {
|
||||
act, err := ToQuestion(it)
|
||||
if IsItemCollection(it) {
|
||||
return OnItemCollection(it, func(col *ItemCollection) error {
|
||||
for _, it := range *col {
|
||||
if err := OnQuestion(it, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
act, err := ToQuestion(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -64,7 +104,17 @@ func OnQuestion(it Item, fn withQuestionFn) error {
|
|||
|
||||
// OnActor
|
||||
func OnActor(it Item, fn withActorFn) error {
|
||||
act, err := ToActor(it)
|
||||
if IsItemCollection(it) {
|
||||
return OnItemCollection(it, func(col *ItemCollection) error {
|
||||
for _, it := range *col {
|
||||
if err := OnActor(it, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
act, err := ToActor(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -123,7 +173,7 @@ func OnCollectionIntf(it Item, fn withCollectionInterfaceFn) error {
|
|||
|
||||
// OnCollectionPage
|
||||
func OnCollectionPage(it Item, fn withCollectionPageFn) error {
|
||||
col, err := ToCollectionPage(it)
|
||||
col, err := ToCollectionPage(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -141,7 +191,7 @@ func OnOrderedCollection(it Item, fn withOrderedCollectionFn) error {
|
|||
|
||||
// OnOrderedCollectionPage executes a function on an ordered collection page type item
|
||||
func OnOrderedCollectionPage(it Item, fn withOrderedCollectionPageFn) error {
|
||||
col, err := ToOrderedCollectionPage(it)
|
||||
col, err := ToOrderedCollectionPage(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -150,7 +200,7 @@ func OnOrderedCollectionPage(it Item, fn withOrderedCollectionPageFn) error {
|
|||
|
||||
// OnItemCollection executes a function on a collection type item
|
||||
func OnItemCollection(it Item, fn withItemCollectionFn) error {
|
||||
col, err := ToItemCollection(it)
|
||||
col, err := ToItemCollection(it)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
320
helpers_test.go
320
helpers_test.go
|
@ -1,131 +1,259 @@
|
|||
package activitypub
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOnObject(t *testing.T) {
|
||||
ob := ObjectNew(ArticleType)
|
||||
|
||||
err := OnObject(ob, func(o *Object) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
}
|
||||
|
||||
err = OnObject(ob, func(o *Object) error {
|
||||
if o.Type != ob.Type {
|
||||
t.Errorf("In function type %s different than expected, %s", o.Type, ob.Type)
|
||||
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
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnActivity(t *testing.T) {
|
||||
ob := ObjectNew(ArticleType)
|
||||
act := ActivityNew("test", CreateType, ob)
|
||||
|
||||
err := OnActivity(act, func(a *Activity) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
err = OnActivity(act, func(a *Activity) error {
|
||||
if a.Type != act.Type {
|
||||
t.Errorf("In function type %s different than expected, %s", a.Type, act.Type)
|
||||
}
|
||||
if a.ID != act.ID {
|
||||
t.Errorf("In function ID %s different than expected, %s", a.ID, act.ID)
|
||||
}
|
||||
if a.Object != act.Object {
|
||||
t.Errorf("In function object %s different than expected, %s", a.Object, act.Object)
|
||||
func assertIntransitiveActivityWithTesting(fn canErrorFunc, expected Item) withIntransitiveActivityFn {
|
||||
return func (p *IntransitiveActivity) error {
|
||||
if !assertDeepEquals(fn, p , expected) {
|
||||
return fmt.Errorf("not equal")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnIntransitiveActivity(t *testing.T) {
|
||||
act := IntransitiveActivityNew("test", ArriveType)
|
||||
|
||||
err := OnIntransitiveActivity(act, func(a *IntransitiveActivity) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
testIntransitiveActivity := IntransitiveActivity{
|
||||
ID: "https://example.com",
|
||||
}
|
||||
|
||||
err = OnIntransitiveActivity(act, func(a *IntransitiveActivity) error {
|
||||
if a.Type != act.Type {
|
||||
t.Errorf("In function type %s different than expected, %s", a.Type, act.Type)
|
||||
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
|
||||
}
|
||||
if a.ID != act.ID {
|
||||
t.Errorf("In function ID %s different than expected, %s", a.ID, act.ID)
|
||||
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
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnQuestion(t *testing.T) {
|
||||
act := QuestionNew("test")
|
||||
|
||||
err := OnQuestion(act, func(a *Question) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
testQuestion := Question{
|
||||
ID: "https://example.com",
|
||||
}
|
||||
|
||||
err = OnQuestion(act, func(a *Question) error {
|
||||
if a.Type != act.Type {
|
||||
t.Errorf("In function type %s different than expected, %s", a.Type, act.Type)
|
||||
}
|
||||
if a.ID != act.ID {
|
||||
t.Errorf("In function ID %s different than expected, %s", a.ID, act.ID)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
type args struct {
|
||||
it Item
|
||||
fn func(canErrorFunc, Item) withQuestionFn
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnPerson(t *testing.T) {
|
||||
pers := PersonNew("testPerson")
|
||||
err := OnActor(pers, func(a *Person) error {
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
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,
|
||||
},
|
||||
}
|
||||
|
||||
err = OnActor(pers, func(p *Person) error {
|
||||
if p.Type != pers.Type {
|
||||
t.Errorf("In function type %s different than expected, %s", p.Type, pers.Type)
|
||||
for _, tt := range tests {
|
||||
var logFn canErrorFunc
|
||||
if tt.wantErr {
|
||||
logFn = t.Logf
|
||||
} else {
|
||||
logFn = t.Errorf
|
||||
}
|
||||
if p.ID != pers.ID {
|
||||
t.Errorf("In function ID %s different than expected, %s", p.ID, pers.ID)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned %s", err)
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
6
item.go
6
item.go
|
@ -73,6 +73,12 @@ func ItemsEqual(it, with Item) bool {
|
|||
return result
|
||||
}
|
||||
|
||||
// IsItemCollection returns if the current Item interface holds a Collection
|
||||
func IsItemCollection(it Item) bool {
|
||||
_, ok := it.(ItemCollection)
|
||||
return ok
|
||||
}
|
||||
|
||||
// IsIRI returns if the current Item interface holds an IRI
|
||||
func IsIRI(it Item) bool {
|
||||
_, ok := it.(IRI)
|
||||
|
|
10
place.go
10
place.go
|
@ -232,6 +232,16 @@ func ToPlace(it Item) (*Place, error) {
|
|||
type withPlaceFn func (*Place) error
|
||||
|
||||
func OnPlace(it Item, fn withPlaceFn) error {
|
||||
if IsItemCollection(it) {
|
||||
return OnItemCollection(it, func(col *ItemCollection) error {
|
||||
for _, it := range *col {
|
||||
if err := OnPlace(it, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
ob, err := ToPlace(it)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package activitypub
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPlace_Recipients(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
|
@ -41,3 +44,61 @@ func TestPlace_UnmarshalJSON(t *testing.T) {
|
|||
func TestPlace_Clean(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
}
|
||||
|
||||
func assertPlaceWithTesting(fn canErrorFunc, expected *Place) withPlaceFn {
|
||||
return func (p *Place) error {
|
||||
if !assertDeepEquals(fn, p , expected) {
|
||||
return fmt.Errorf("not equal")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnPlace(t *testing.T) {
|
||||
testPlace := Place{
|
||||
ID: "https://example.com",
|
||||
}
|
||||
type args struct {
|
||||
it Item
|
||||
fn func(canErrorFunc, *Place) withPlaceFn
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "single",
|
||||
args: args{ testPlace, assertPlaceWithTesting },
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "single fails",
|
||||
args: args{ Place{ID: "https://not-equals"}, assertPlaceWithTesting },
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "collectionOfPlaces",
|
||||
args: args{ItemCollection{testPlace, testPlace}, assertPlaceWithTesting },
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "collectionOfPlaces fails",
|
||||
args: args{ ItemCollection{testPlace, Place{ID: "https://not-equals"}}, assertPlaceWithTesting },
|
||||
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 := OnPlace(tt.args.it, tt.args.fn(logFn, &testPlace)); (err != nil) != tt.wantErr {
|
||||
t.Errorf("OnPlace() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
10
profile.go
10
profile.go
|
@ -200,6 +200,16 @@ func ToProfile(it Item) (*Profile, error) {
|
|||
type withProfileFn func (*Profile) error
|
||||
|
||||
func OnProfile(it Item, fn withProfileFn) error {
|
||||
if IsItemCollection(it) {
|
||||
return OnItemCollection(it, func(col *ItemCollection) error {
|
||||
for _, it := range *col {
|
||||
if err := OnProfile(it, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
ob, err := ToProfile(it)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package activitypub
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestProfile_Recipients(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
|
@ -41,3 +44,61 @@ func TestProfile_UnmarshalJSON(t *testing.T) {
|
|||
func TestProfile_Clean(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
}
|
||||
|
||||
func assertProfileWithTesting(fn canErrorFunc, expected *Profile) withProfileFn {
|
||||
return func (p *Profile) error {
|
||||
if !assertDeepEquals(fn, p , expected) {
|
||||
return fmt.Errorf("not equal")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnProfile(t *testing.T) {
|
||||
testProfile := Profile{
|
||||
ID: "https://example.com",
|
||||
}
|
||||
type args struct {
|
||||
it Item
|
||||
fn func(canErrorFunc, *Profile) withProfileFn
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "single",
|
||||
args: args{testProfile, assertProfileWithTesting},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "single fails",
|
||||
args: args{&Profile{ID: "https://not-equal"}, assertProfileWithTesting},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "collection of profiles",
|
||||
args: args{ItemCollection{testProfile, testProfile}, assertProfileWithTesting},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "collection of profiles fails",
|
||||
args: args{ItemCollection{testProfile, &Profile{ID: "not-equal"}}, assertProfileWithTesting},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var logFn canErrorFunc
|
||||
if tt.wantErr {
|
||||
logFn = t.Logf
|
||||
} else {
|
||||
logFn = t.Errorf
|
||||
}
|
||||
if err := OnProfile(tt.args.it, tt.args.fn(logFn, &testProfile)); (err != nil) != tt.wantErr {
|
||||
t.Errorf("OnProfile() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,168 +213,168 @@ func deepValueEqual(t canErrorFunc, v1, v2 reflect.Value, visited map[visit]bool
|
|||
var zLoc, _ = time.LoadLocation("UTC")
|
||||
|
||||
var allTests = testMaps{
|
||||
"empty": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Object{},
|
||||
result: &pub.Object{},
|
||||
},
|
||||
"link_simple": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Link{},
|
||||
result: &pub.Link{
|
||||
Type: pub.LinkType,
|
||||
Href: pub.IRI("http://example.org/abc"),
|
||||
HrefLang: pub.LangRef("en"),
|
||||
MediaType: pub.MimeType("text/html"),
|
||||
Name: pub.NaturalLanguageValues{{
|
||||
pub.NilLangRef, pub.Content("An example link"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
"object_with_url": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Object{},
|
||||
result: &pub.Object{
|
||||
URL: pub.IRI("http://littr.git/api/accounts/system"),
|
||||
},
|
||||
},
|
||||
"object_with_url_collection": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Object{},
|
||||
result: &pub.Object{
|
||||
URL: pub.ItemCollection{
|
||||
pub.IRI("http://littr.git/api/accounts/system"),
|
||||
pub.IRI("http://littr.git/~system"),
|
||||
},
|
||||
},
|
||||
},
|
||||
"object_simple": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Object{},
|
||||
result: &pub.Object{
|
||||
Type: pub.ObjectType,
|
||||
ID: pub.ID("http://www.test.example/object/1"),
|
||||
Name: pub.NaturalLanguageValues{{
|
||||
pub.NilLangRef, pub.Content("A Simple, non-specific object"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
"object_no_type": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Object{},
|
||||
result: &pub.Object{
|
||||
ID: pub.ID("http://www.test.example/object/1"),
|
||||
Name: pub.NaturalLanguageValues{{
|
||||
pub.NilLangRef, pub.Content("A Simple, non-specific object without a type"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
"object_with_tags": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Object{},
|
||||
result: &pub.Object{
|
||||
Type: pub.ObjectType,
|
||||
ID: pub.ID("http://www.test.example/object/1"),
|
||||
Name: pub.NaturalLanguageValues{{
|
||||
pub.NilLangRef, pub.Content("A Simple, non-specific object"),
|
||||
}},
|
||||
Tag: pub.ItemCollection{
|
||||
&pub.Mention{
|
||||
Name: pub.NaturalLanguageValues{{
|
||||
pub.NilLangRef, pub.Content("#my_tag"),
|
||||
}},
|
||||
Type: pub.MentionType,
|
||||
ID: pub.ID("http://example.com/tag/my_tag"),
|
||||
},
|
||||
&pub.Mention{
|
||||
Name: pub.NaturalLanguageValues{{
|
||||
pub.NilLangRef, pub.Content("@ana"),
|
||||
}},
|
||||
Type: pub.MentionType,
|
||||
ID: pub.ID("http://example.com/users/ana"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"object_with_replies": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Object{},
|
||||
result: &pub.Object{
|
||||
Type: pub.ObjectType,
|
||||
ID: pub.ID("http://www.test.example/object/1"),
|
||||
Replies: &pub.Collection{
|
||||
ID: pub.ID("http://www.test.example/object/1/replies"),
|
||||
Type: pub.CollectionType,
|
||||
TotalItems: 1,
|
||||
Items: pub.ItemCollection{
|
||||
&pub.Object{
|
||||
ID: pub.ID("http://www.test.example/object/1/replies/2"),
|
||||
Type: pub.ArticleType,
|
||||
Name: pub.NaturalLanguageValues{{
|
||||
pub.NilLangRef, pub.Content("Example title"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"activity_simple": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Activity{
|
||||
Actor: &pub.Person{},
|
||||
},
|
||||
result: &pub.Activity{
|
||||
Type: pub.ActivityType,
|
||||
Summary: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Sally did something to a note")}},
|
||||
Actor: &pub.Person{
|
||||
Type: pub.PersonType,
|
||||
Name: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Sally")}},
|
||||
},
|
||||
Object: &pub.Object{
|
||||
Type: pub.NoteType,
|
||||
Name: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("A Note")}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"person_with_outbox": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Person{},
|
||||
result: &pub.Person{
|
||||
ID: pub.ID("http://example.com/accounts/ana"),
|
||||
Type: pub.PersonType,
|
||||
Name: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("ana")}},
|
||||
PreferredUsername: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Ana")}},
|
||||
URL: pub.IRI("http://example.com/accounts/ana"),
|
||||
Outbox: &pub.OrderedCollection{
|
||||
ID: "http://example.com/accounts/ana/outbox",
|
||||
Type: pub.OrderedCollectionType,
|
||||
URL: pub.IRI("http://example.com/outbox"),
|
||||
},
|
||||
},
|
||||
},
|
||||
"ordered_collection": testPair{
|
||||
expected: true,
|
||||
blank: &pub.OrderedCollection{},
|
||||
result: &pub.OrderedCollection{
|
||||
ID: pub.ID("http://example.com/outbox"),
|
||||
Type: pub.OrderedCollectionType,
|
||||
URL: pub.IRI("http://example.com/outbox"),
|
||||
TotalItems: 1,
|
||||
OrderedItems: pub.ItemCollection{
|
||||
&pub.Object{
|
||||
ID: pub.ID("http://example.com/outbox/53c6fb47"),
|
||||
Type: pub.ArticleType,
|
||||
Name: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Example title")}},
|
||||
Content: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Example content!")}},
|
||||
URL: pub.IRI("http://example.com/53c6fb47"),
|
||||
MediaType: pub.MimeType("text/markdown"),
|
||||
Published: time.Date(2018, time.July, 5, 16, 46, 44, 0, zLoc),
|
||||
Generator: pub.IRI("http://example.com"),
|
||||
AttributedTo: pub.IRI("http://example.com/accounts/alice"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
//"empty": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Object{},
|
||||
// result: &pub.Object{},
|
||||
//},
|
||||
//"link_simple": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Link{},
|
||||
// result: &pub.Link{
|
||||
// Type: pub.LinkType,
|
||||
// Href: pub.IRI("http://example.org/abc"),
|
||||
// HrefLang: pub.LangRef("en"),
|
||||
// MediaType: pub.MimeType("text/html"),
|
||||
// Name: pub.NaturalLanguageValues{{
|
||||
// pub.NilLangRef, pub.Content("An example link"),
|
||||
// }},
|
||||
// },
|
||||
//},
|
||||
//"object_with_url": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Object{},
|
||||
// result: &pub.Object{
|
||||
// URL: pub.IRI("http://littr.git/api/accounts/system"),
|
||||
// },
|
||||
//},
|
||||
//"object_with_url_collection": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Object{},
|
||||
// result: &pub.Object{
|
||||
// URL: pub.ItemCollection{
|
||||
// pub.IRI("http://littr.git/api/accounts/system"),
|
||||
// pub.IRI("http://littr.git/~system"),
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
//"object_simple": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Object{},
|
||||
// result: &pub.Object{
|
||||
// Type: pub.ObjectType,
|
||||
// ID: pub.ID("http://www.test.example/object/1"),
|
||||
// Name: pub.NaturalLanguageValues{{
|
||||
// pub.NilLangRef, pub.Content("A Simple, non-specific object"),
|
||||
// }},
|
||||
// },
|
||||
//},
|
||||
//"object_no_type": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Object{},
|
||||
// result: &pub.Object{
|
||||
// ID: pub.ID("http://www.test.example/object/1"),
|
||||
// Name: pub.NaturalLanguageValues{{
|
||||
// pub.NilLangRef, pub.Content("A Simple, non-specific object without a type"),
|
||||
// }},
|
||||
// },
|
||||
//},
|
||||
//"object_with_tags": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Object{},
|
||||
// result: &pub.Object{
|
||||
// Type: pub.ObjectType,
|
||||
// ID: pub.ID("http://www.test.example/object/1"),
|
||||
// Name: pub.NaturalLanguageValues{{
|
||||
// pub.NilLangRef, pub.Content("A Simple, non-specific object"),
|
||||
// }},
|
||||
// Tag: pub.ItemCollection{
|
||||
// &pub.Mention{
|
||||
// Name: pub.NaturalLanguageValues{{
|
||||
// pub.NilLangRef, pub.Content("#my_tag"),
|
||||
// }},
|
||||
// Type: pub.MentionType,
|
||||
// ID: pub.ID("http://example.com/tag/my_tag"),
|
||||
// },
|
||||
// &pub.Mention{
|
||||
// Name: pub.NaturalLanguageValues{{
|
||||
// pub.NilLangRef, pub.Content("@ana"),
|
||||
// }},
|
||||
// Type: pub.MentionType,
|
||||
// ID: pub.ID("http://example.com/users/ana"),
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
//"object_with_replies": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Object{},
|
||||
// result: &pub.Object{
|
||||
// Type: pub.ObjectType,
|
||||
// ID: pub.ID("http://www.test.example/object/1"),
|
||||
// Replies: &pub.Collection{
|
||||
// ID: pub.ID("http://www.test.example/object/1/replies"),
|
||||
// Type: pub.CollectionType,
|
||||
// TotalItems: 1,
|
||||
// Items: pub.ItemCollection{
|
||||
// &pub.Object{
|
||||
// ID: pub.ID("http://www.test.example/object/1/replies/2"),
|
||||
// Type: pub.ArticleType,
|
||||
// Name: pub.NaturalLanguageValues{{
|
||||
// pub.NilLangRef, pub.Content("Example title"),
|
||||
// }},
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
//"activity_simple": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Activity{
|
||||
// Actor: &pub.Person{},
|
||||
// },
|
||||
// result: &pub.Activity{
|
||||
// Type: pub.ActivityType,
|
||||
// Summary: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Sally did something to a note")}},
|
||||
// Actor: &pub.Person{
|
||||
// Type: pub.PersonType,
|
||||
// Name: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Sally")}},
|
||||
// },
|
||||
// Object: &pub.Object{
|
||||
// Type: pub.NoteType,
|
||||
// Name: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("A Note")}},
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
//"person_with_outbox": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Person{},
|
||||
// result: &pub.Person{
|
||||
// ID: pub.ID("http://example.com/accounts/ana"),
|
||||
// Type: pub.PersonType,
|
||||
// Name: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("ana")}},
|
||||
// PreferredUsername: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Ana")}},
|
||||
// URL: pub.IRI("http://example.com/accounts/ana"),
|
||||
// Outbox: &pub.OrderedCollection{
|
||||
// ID: "http://example.com/accounts/ana/outbox",
|
||||
// Type: pub.OrderedCollectionType,
|
||||
// URL: pub.IRI("http://example.com/outbox"),
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
//"ordered_collection": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.OrderedCollection{},
|
||||
// result: &pub.OrderedCollection{
|
||||
// ID: pub.ID("http://example.com/outbox"),
|
||||
// Type: pub.OrderedCollectionType,
|
||||
// URL: pub.IRI("http://example.com/outbox"),
|
||||
// TotalItems: 1,
|
||||
// OrderedItems: pub.ItemCollection{
|
||||
// &pub.Object{
|
||||
// ID: pub.ID("http://example.com/outbox/53c6fb47"),
|
||||
// Type: pub.ArticleType,
|
||||
// Name: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Example title")}},
|
||||
// Content: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("Example content!")}},
|
||||
// URL: pub.IRI("http://example.com/53c6fb47"),
|
||||
// MediaType: pub.MimeType("text/markdown"),
|
||||
// Published: time.Date(2018, time.July, 5, 16, 46, 44, 0, zLoc),
|
||||
// Generator: pub.IRI("http://example.com"),
|
||||
// AttributedTo: pub.IRI("http://example.com/accounts/alice"),
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
"ordered_collection_page": testPair{
|
||||
expected: true,
|
||||
blank: &pub.OrderedCollectionPage{},
|
||||
|
@ -403,103 +403,103 @@ var allTests = testMaps{
|
|||
},
|
||||
},
|
||||
},
|
||||
"natural_language_values": {
|
||||
expected: true,
|
||||
blank: &pub.NaturalLanguageValues{},
|
||||
result: &pub.NaturalLanguageValues{
|
||||
{
|
||||
pub.NilLangRef, pub.Content([]byte{'\n','\t', '\t', '\n'}),
|
||||
},
|
||||
{pub.LangRef("en"), pub.Content("Ana got apples ⓐ")},
|
||||
{pub.LangRef("fr"), pub.Content("Aná a des pommes ⒜")},
|
||||
{pub.LangRef("ro"), pub.Content("Ana are mere")},
|
||||
},
|
||||
},
|
||||
"activity_create_simple": {
|
||||
expected: true,
|
||||
blank: &pub.Create{},
|
||||
result: &pub.Create{
|
||||
Type: pub.CreateType,
|
||||
Actor: pub.IRI("https://littr.git/api/accounts/anonymous"),
|
||||
Object: &pub.Object{
|
||||
Type: pub.NoteType,
|
||||
AttributedTo: pub.IRI("https://littr.git/api/accounts/anonymous"),
|
||||
InReplyTo: pub.IRI("https://littr.git/api/accounts/system/outbox/7ca154ff"),
|
||||
Content: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("<p>Hello world</p>")}},
|
||||
To: pub.ItemCollection{pub.IRI("https://www.w3.org/ns/activitystreams#Public")},
|
||||
},
|
||||
},
|
||||
},
|
||||
"activity_create_multiple_objects": {
|
||||
expected: true,
|
||||
blank: &pub.Create{},
|
||||
result: &pub.Create{
|
||||
Type: pub.CreateType,
|
||||
Actor: pub.IRI("https://littr.git/api/accounts/anonymous"),
|
||||
Object: pub.ItemCollection{
|
||||
&pub.Object{
|
||||
Type: pub.NoteType,
|
||||
AttributedTo: pub.IRI("https://littr.git/api/accounts/anonymous"),
|
||||
InReplyTo: pub.IRI("https://littr.git/api/accounts/system/outbox/7ca154ff"),
|
||||
Content: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("<p>Hello world</p>")}},
|
||||
To: pub.ItemCollection{pub.IRI("https://www.w3.org/ns/activitystreams#Public")},
|
||||
},
|
||||
&pub.Article{
|
||||
Type: pub.ArticleType,
|
||||
ID: pub.ID("http://www.test.example/article/1"),
|
||||
Name: pub.NaturalLanguageValues{
|
||||
{
|
||||
pub.NilLangRef,
|
||||
pub.Content("This someday will grow up to be an article"),
|
||||
},
|
||||
},
|
||||
InReplyTo: pub.ItemCollection{
|
||||
pub.IRI("http://www.test.example/object/1"),
|
||||
pub.IRI("http://www.test.example/object/778"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"object_with_audience": testPair{
|
||||
expected: true,
|
||||
blank: &pub.Object{},
|
||||
result: &pub.Object{
|
||||
Type: pub.ObjectType,
|
||||
ID: pub.ID("http://www.test.example/object/1"),
|
||||
To: pub.ItemCollection{
|
||||
pub.IRI("https://www.w3.org/ns/activitystreams#Public"),
|
||||
},
|
||||
Bto: pub.ItemCollection{
|
||||
pub.IRI("http://example.com/sharedInbox"),
|
||||
},
|
||||
CC: pub.ItemCollection{
|
||||
pub.IRI("https://example.com/actors/ana"),
|
||||
pub.IRI("https://example.com/actors/bob"),
|
||||
},
|
||||
BCC: pub.ItemCollection{
|
||||
pub.IRI("https://darkside.cookie/actors/darthvader"),
|
||||
},
|
||||
},
|
||||
},
|
||||
"article_with_multiple_inreplyto": {
|
||||
expected: true,
|
||||
blank: &pub.Article{},
|
||||
result: &pub.Article{
|
||||
Type: pub.ArticleType,
|
||||
ID: pub.ID("http://www.test.example/article/1"),
|
||||
Name: pub.NaturalLanguageValues{
|
||||
{
|
||||
pub.NilLangRef,
|
||||
pub.Content("This someday will grow up to be an article"),
|
||||
},
|
||||
},
|
||||
InReplyTo: pub.ItemCollection{
|
||||
pub.IRI("http://www.test.example/object/1"),
|
||||
pub.IRI("http://www.test.example/object/778"),
|
||||
},
|
||||
},
|
||||
},
|
||||
//"natural_language_values": {
|
||||
// expected: true,
|
||||
// blank: &pub.NaturalLanguageValues{},
|
||||
// result: &pub.NaturalLanguageValues{
|
||||
// {
|
||||
// pub.NilLangRef, pub.Content([]byte{'\n','\t', '\t', '\n'}),
|
||||
// },
|
||||
// {pub.LangRef("en"), pub.Content("Ana got apples ⓐ")},
|
||||
// {pub.LangRef("fr"), pub.Content("Aná a des pommes ⒜")},
|
||||
// {pub.LangRef("ro"), pub.Content("Ana are mere")},
|
||||
// },
|
||||
//},
|
||||
//"activity_create_simple": {
|
||||
// expected: true,
|
||||
// blank: &pub.Create{},
|
||||
// result: &pub.Create{
|
||||
// Type: pub.CreateType,
|
||||
// Actor: pub.IRI("https://littr.git/api/accounts/anonymous"),
|
||||
// Object: &pub.Object{
|
||||
// Type: pub.NoteType,
|
||||
// AttributedTo: pub.IRI("https://littr.git/api/accounts/anonymous"),
|
||||
// InReplyTo: pub.IRI("https://littr.git/api/accounts/system/outbox/7ca154ff"),
|
||||
// Content: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("<p>Hello world</p>")}},
|
||||
// To: pub.ItemCollection{pub.IRI("https://www.w3.org/ns/activitystreams#Public")},
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
//"activity_create_multiple_objects": {
|
||||
// expected: true,
|
||||
// blank: &pub.Create{},
|
||||
// result: &pub.Create{
|
||||
// Type: pub.CreateType,
|
||||
// Actor: pub.IRI("https://littr.git/api/accounts/anonymous"),
|
||||
// Object: pub.ItemCollection{
|
||||
// &pub.Object{
|
||||
// Type: pub.NoteType,
|
||||
// AttributedTo: pub.IRI("https://littr.git/api/accounts/anonymous"),
|
||||
// InReplyTo: pub.IRI("https://littr.git/api/accounts/system/outbox/7ca154ff"),
|
||||
// Content: pub.NaturalLanguageValues{{pub.NilLangRef, pub.Content("<p>Hello world</p>")}},
|
||||
// To: pub.ItemCollection{pub.IRI("https://www.w3.org/ns/activitystreams#Public")},
|
||||
// },
|
||||
// &pub.Article{
|
||||
// Type: pub.ArticleType,
|
||||
// ID: pub.ID("http://www.test.example/article/1"),
|
||||
// Name: pub.NaturalLanguageValues{
|
||||
// {
|
||||
// pub.NilLangRef,
|
||||
// pub.Content("This someday will grow up to be an article"),
|
||||
// },
|
||||
// },
|
||||
// InReplyTo: pub.ItemCollection{
|
||||
// pub.IRI("http://www.test.example/object/1"),
|
||||
// pub.IRI("http://www.test.example/object/778"),
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
//"object_with_audience": testPair{
|
||||
// expected: true,
|
||||
// blank: &pub.Object{},
|
||||
// result: &pub.Object{
|
||||
// Type: pub.ObjectType,
|
||||
// ID: pub.ID("http://www.test.example/object/1"),
|
||||
// To: pub.ItemCollection{
|
||||
// pub.IRI("https://www.w3.org/ns/activitystreams#Public"),
|
||||
// },
|
||||
// Bto: pub.ItemCollection{
|
||||
// pub.IRI("http://example.com/sharedInbox"),
|
||||
// },
|
||||
// CC: pub.ItemCollection{
|
||||
// pub.IRI("https://example.com/actors/ana"),
|
||||
// pub.IRI("https://example.com/actors/bob"),
|
||||
// },
|
||||
// BCC: pub.ItemCollection{
|
||||
// pub.IRI("https://darkside.cookie/actors/darthvader"),
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
//"article_with_multiple_inreplyto": {
|
||||
// expected: true,
|
||||
// blank: &pub.Article{},
|
||||
// result: &pub.Article{
|
||||
// Type: pub.ArticleType,
|
||||
// ID: pub.ID("http://www.test.example/article/1"),
|
||||
// Name: pub.NaturalLanguageValues{
|
||||
// {
|
||||
// pub.NilLangRef,
|
||||
// pub.Content("This someday will grow up to be an article"),
|
||||
// },
|
||||
// },
|
||||
// InReplyTo: pub.ItemCollection{
|
||||
// pub.IRI("http://www.test.example/object/1"),
|
||||
// pub.IRI("http://www.test.example/object/778"),
|
||||
// },
|
||||
// },
|
||||
//},
|
||||
}
|
||||
|
||||
func getFileContents(path string) ([]byte, error) {
|
||||
|
|
10
tombstone.go
10
tombstone.go
|
@ -207,6 +207,16 @@ func ToTombstone(it Item) (*Tombstone, error) {
|
|||
type withTombstoneFn func (*Tombstone) error
|
||||
|
||||
func OnTombstone(it Item, fn withTombstoneFn) error {
|
||||
if IsItemCollection(it) {
|
||||
return OnItemCollection(it, func(col *ItemCollection) error {
|
||||
for _, it := range *col {
|
||||
if err := OnTombstone(it, fn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
ob, err := ToTombstone(it)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package activitypub
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTombstone_GetID(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
|
@ -33,3 +36,60 @@ func TestTombstone_UnmarshalJSON(t *testing.T) {
|
|||
func TestTombstone_Clean(t *testing.T) {
|
||||
t.Skipf("TODO")
|
||||
}
|
||||
func assertTombstoneWithTesting(fn canErrorFunc, expected *Tombstone) withTombstoneFn {
|
||||
return func (p *Tombstone) error {
|
||||
if !assertDeepEquals(fn, p , expected) {
|
||||
return fmt.Errorf("not equal")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnTombstone(t *testing.T) {
|
||||
testTombstone := Tombstone{
|
||||
ID: "https://example.com",
|
||||
}
|
||||
type args struct {
|
||||
it Item
|
||||
fn func(canErrorFunc, *Tombstone) withTombstoneFn
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "single",
|
||||
args: args{testTombstone, assertTombstoneWithTesting},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "single fails",
|
||||
args: args{&Tombstone{ID: "https://not-equal"}, assertTombstoneWithTesting},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "collection of profiles",
|
||||
args: args{ItemCollection{testTombstone, testTombstone}, assertTombstoneWithTesting},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "collection of profiles fails",
|
||||
args: args{ItemCollection{testTombstone, &Tombstone{ID: "not-equal"}}, assertTombstoneWithTesting},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var logFn canErrorFunc
|
||||
if tt.wantErr {
|
||||
logFn = t.Logf
|
||||
} else {
|
||||
logFn = t.Errorf
|
||||
}
|
||||
if err := OnTombstone(tt.args.it, tt.args.fn(logFn, &testTombstone)); (err != nil) != tt.wantErr {
|
||||
t.Errorf("OnTombstone() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue