mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 02:32:25 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			292 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			292 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // GoToSocial
 | |
| // Copyright (C) GoToSocial Authors admin@gotosocial.org
 | |
| // SPDX-License-Identifier: AGPL-3.0-or-later
 | |
| //
 | |
| // This program is free software: you can redistribute it and/or modify
 | |
| // it under the terms of the GNU Affero General Public License as published by
 | |
| // the Free Software Foundation, either version 3 of the License, or
 | |
| // (at your option) any later version.
 | |
| //
 | |
| // This program is distributed in the hope that it will be useful,
 | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| // GNU Affero General Public License for more details.
 | |
| //
 | |
| // You should have received a copy of the GNU Affero General Public License
 | |
| // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| package messages_test
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/json"
 | |
| 	"net/url"
 | |
| 	"testing"
 | |
| 
 | |
| 	"code.superseriousbusiness.org/gotosocial/internal/ap"
 | |
| 	"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
 | |
| 	"code.superseriousbusiness.org/gotosocial/internal/messages"
 | |
| 	"code.superseriousbusiness.org/gotosocial/testrig"
 | |
| 
 | |
| 	"github.com/google/go-cmp/cmp"
 | |
| )
 | |
| 
 | |
| var testStatus = testrig.NewTestStatuses()["admin_account_status_1"]
 | |
| 
 | |
| var testAccount = testrig.NewTestAccounts()["admin_account"]
 | |
| 
 | |
| var fromClientAPICases = []struct {
 | |
| 	msg  messages.FromClientAPI
 | |
| 	data []byte
 | |
| }{
 | |
| 	{
 | |
| 		msg: messages.FromClientAPI{
 | |
| 			APObjectType:   ap.ObjectNote,
 | |
| 			APActivityType: ap.ActivityCreate,
 | |
| 			GTSModel:       testStatus,
 | |
| 			TargetURI:      "https://gotosocial.org",
 | |
| 			Origin:         >smodel.Account{ID: "654321"},
 | |
| 			Target:         >smodel.Account{ID: "123456"},
 | |
| 		},
 | |
| 		data: toJSON(map[string]any{
 | |
| 			"ap_object_type":   ap.ObjectNote,
 | |
| 			"ap_activity_type": ap.ActivityCreate,
 | |
| 			"gts_model":        json.RawMessage(toJSON(testStatus)),
 | |
| 			"gts_model_type":   "*gtsmodel.Status",
 | |
| 			"target_uri":       "https://gotosocial.org",
 | |
| 			"origin_id":        "654321",
 | |
| 			"target_id":        "123456",
 | |
| 		}),
 | |
| 	},
 | |
| 	{
 | |
| 		msg: messages.FromClientAPI{
 | |
| 			APObjectType:   ap.ObjectProfile,
 | |
| 			APActivityType: ap.ActivityUpdate,
 | |
| 			GTSModel:       testAccount,
 | |
| 			TargetURI:      "https://uk-queen-is-dead.org",
 | |
| 			Origin:         >smodel.Account{ID: "123456"},
 | |
| 			Target:         >smodel.Account{ID: "654321"},
 | |
| 		},
 | |
| 		data: toJSON(map[string]any{
 | |
| 			"ap_object_type":   ap.ObjectProfile,
 | |
| 			"ap_activity_type": ap.ActivityUpdate,
 | |
| 			"gts_model":        json.RawMessage(toJSON(testAccount)),
 | |
| 			"gts_model_type":   "*gtsmodel.Account",
 | |
| 			"target_uri":       "https://uk-queen-is-dead.org",
 | |
| 			"origin_id":        "123456",
 | |
| 			"target_id":        "654321",
 | |
| 		}),
 | |
| 	},
 | |
| }
 | |
| 
 | |
| var fromFediAPICases = []struct {
 | |
| 	msg  messages.FromFediAPI
 | |
| 	data []byte
 | |
| }{
 | |
| 	{
 | |
| 		msg: messages.FromFediAPI{
 | |
| 			APObjectType:   ap.ObjectNote,
 | |
| 			APActivityType: ap.ActivityCreate,
 | |
| 			GTSModel:       testStatus,
 | |
| 			TargetURI:      "https://gotosocial.org",
 | |
| 			Requesting:     >smodel.Account{ID: "654321"},
 | |
| 			Receiving:      >smodel.Account{ID: "123456"},
 | |
| 		},
 | |
| 		data: toJSON(map[string]any{
 | |
| 			"ap_object_type":   ap.ObjectNote,
 | |
| 			"ap_activity_type": ap.ActivityCreate,
 | |
| 			"gts_model":        json.RawMessage(toJSON(testStatus)),
 | |
| 			"gts_model_type":   "*gtsmodel.Status",
 | |
| 			"target_uri":       "https://gotosocial.org",
 | |
| 			"requesting_id":    "654321",
 | |
| 			"receiving_id":     "123456",
 | |
| 		}),
 | |
| 	},
 | |
| 	{
 | |
| 		msg: messages.FromFediAPI{
 | |
| 			APObjectType:   ap.ObjectProfile,
 | |
| 			APActivityType: ap.ActivityUpdate,
 | |
| 			GTSModel:       testAccount,
 | |
| 			TargetURI:      "https://uk-queen-is-dead.org",
 | |
| 			Requesting:     >smodel.Account{ID: "123456"},
 | |
| 			Receiving:      >smodel.Account{ID: "654321"},
 | |
| 		},
 | |
| 		data: toJSON(map[string]any{
 | |
| 			"ap_object_type":   ap.ObjectProfile,
 | |
| 			"ap_activity_type": ap.ActivityUpdate,
 | |
| 			"gts_model":        json.RawMessage(toJSON(testAccount)),
 | |
| 			"gts_model_type":   "*gtsmodel.Account",
 | |
| 			"target_uri":       "https://uk-queen-is-dead.org",
 | |
| 			"requesting_id":    "123456",
 | |
| 			"receiving_id":     "654321",
 | |
| 		}),
 | |
| 	},
 | |
| }
 | |
| 
 | |
| func TestSerializeFromClientAPI(t *testing.T) {
 | |
| 	for _, test := range fromClientAPICases {
 | |
| 		// Serialize test message to blob.
 | |
| 		data, err := test.msg.Serialize()
 | |
| 		if err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		// Check serialized JSON data as expected.
 | |
| 		assertJSONEqual(t, test.data, data)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDeserializeFromClientAPI(t *testing.T) {
 | |
| 	for _, test := range fromClientAPICases {
 | |
| 		var msg messages.FromClientAPI
 | |
| 
 | |
| 		// Deserialize test message blob.
 | |
| 		err := msg.Deserialize(test.data)
 | |
| 		if err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		// Check that msg is as expected.
 | |
| 		assertEqual(t, test.msg.APActivityType, msg.APActivityType)
 | |
| 		assertEqual(t, test.msg.APObjectType, msg.APObjectType)
 | |
| 		assertEqual(t, test.msg.GTSModel, msg.GTSModel)
 | |
| 		assertEqual(t, test.msg.TargetURI, msg.TargetURI)
 | |
| 		assertEqual(t, accountID(test.msg.Origin), accountID(msg.Origin))
 | |
| 		assertEqual(t, accountID(test.msg.Target), accountID(msg.Target))
 | |
| 
 | |
| 		// Perform final check to ensure
 | |
| 		// account model keys deserialized.
 | |
| 		assertEqualRSA(t, test.msg.GTSModel, msg.GTSModel)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestSerializeFromFediAPI(t *testing.T) {
 | |
| 	for _, test := range fromFediAPICases {
 | |
| 		// Serialize test message to blob.
 | |
| 		data, err := test.msg.Serialize()
 | |
| 		if err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		// Check serialized JSON data as expected.
 | |
| 		assertJSONEqual(t, test.data, data)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestDeserializeFromFediAPI(t *testing.T) {
 | |
| 	for _, test := range fromFediAPICases {
 | |
| 		var msg messages.FromFediAPI
 | |
| 
 | |
| 		// Deserialize test message blob.
 | |
| 		err := msg.Deserialize(test.data)
 | |
| 		if err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		// Check that msg is as expected.
 | |
| 		assertEqual(t, test.msg.APActivityType, msg.APActivityType)
 | |
| 		assertEqual(t, test.msg.APObjectType, msg.APObjectType)
 | |
| 		assertEqual(t, urlStr(test.msg.APIRI), urlStr(msg.APIRI))
 | |
| 		assertEqual(t, test.msg.APObject, msg.APObject)
 | |
| 		assertEqual(t, test.msg.GTSModel, msg.GTSModel)
 | |
| 		assertEqual(t, test.msg.TargetURI, msg.TargetURI)
 | |
| 		assertEqual(t, accountID(test.msg.Receiving), accountID(msg.Receiving))
 | |
| 		assertEqual(t, accountID(test.msg.Requesting), accountID(msg.Requesting))
 | |
| 
 | |
| 		// Perform final check to ensure
 | |
| 		// account model keys deserialized.
 | |
| 		assertEqualRSA(t, test.msg.GTSModel, msg.GTSModel)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // assertEqualRSA asserts that test account model RSA keys are equal.
 | |
| func assertEqualRSA(t *testing.T, expect, receive any) bool {
 | |
| 	t.Helper()
 | |
| 
 | |
| 	account1, ok1 := expect.(*gtsmodel.Account)
 | |
| 
 | |
| 	account2, ok2 := receive.(*gtsmodel.Account)
 | |
| 
 | |
| 	if ok1 != ok2 {
 | |
| 		t.Errorf("different model types: expect=%T receive=%T", expect, receive)
 | |
| 		return false
 | |
| 	} else if !ok1 {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	if !account1.PublicKey.Equal(account2.PublicKey) {
 | |
| 		t.Error("public keys do not match")
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("publickey=%v", account1.PublicKey)
 | |
| 
 | |
| 	if !account1.PrivateKey.Equal(account2.PrivateKey) {
 | |
| 		t.Error("private keys do not match")
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("privatekey=%v", account1.PrivateKey)
 | |
| 
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| // assertEqual asserts that two values (of any type!) are equal,
 | |
| // note we use the 'cmp' library here as it's much more useful in
 | |
| // outputting debug information than testify, and handles more complex
 | |
| // types like rsa public / private key comparisons correctly.
 | |
| func assertEqual(t *testing.T, expect, receive any) bool {
 | |
| 	t.Helper()
 | |
| 	if diff := cmp.Diff(expect, receive); diff != "" {
 | |
| 		t.Error(diff)
 | |
| 		return false
 | |
| 	}
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| // assertJSONEqual asserts that two slices of JSON data are equal.
 | |
| func assertJSONEqual(t *testing.T, expect, receive []byte) bool {
 | |
| 	t.Helper()
 | |
| 	return assertEqual(t, fromJSON(expect), fromJSON(receive))
 | |
| }
 | |
| 
 | |
| // urlStr returns url as string, or empty.
 | |
| func urlStr(url *url.URL) string {
 | |
| 	if url == nil {
 | |
| 		return ""
 | |
| 	}
 | |
| 	return url.String()
 | |
| }
 | |
| 
 | |
| // accountID returns account's ID, or empty.
 | |
| func accountID(account *gtsmodel.Account) string {
 | |
| 	if account == nil {
 | |
| 		return ""
 | |
| 	}
 | |
| 	return account.ID
 | |
| }
 | |
| 
 | |
| // fromJSON unmarshals input data as JSON.
 | |
| func fromJSON(b []byte) any {
 | |
| 	r := bytes.NewReader(b)
 | |
| 	d := json.NewDecoder(r)
 | |
| 	d.UseNumber()
 | |
| 	var a any
 | |
| 	err := d.Decode(&a)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	if d.More() {
 | |
| 		panic("multiple json values in b")
 | |
| 	}
 | |
| 	return a
 | |
| }
 | |
| 
 | |
| // toJSON marshals input type as JSON data.
 | |
| func toJSON(a any) []byte {
 | |
| 	b, err := json.Marshal(a)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	return b
 | |
| }
 |