summaryrefslogtreecommitdiff
path: root/internal/transport/delivery/delivery_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/transport/delivery/delivery_test.go')
-rw-r--r--internal/transport/delivery/delivery_test.go265
1 files changed, 98 insertions, 167 deletions
diff --git a/internal/transport/delivery/delivery_test.go b/internal/transport/delivery/delivery_test.go
index 48831f098..e9eaf8fd1 100644
--- a/internal/transport/delivery/delivery_test.go
+++ b/internal/transport/delivery/delivery_test.go
@@ -1,203 +1,134 @@
+// 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 delivery_test
import (
- "fmt"
+ "bytes"
+ "encoding/json"
"io"
- "math/rand"
- "net"
"net/http"
- "strconv"
- "strings"
"testing"
- "codeberg.org/gruf/go-byteutil"
- "github.com/superseriousbusiness/gotosocial/internal/config"
+ "github.com/stretchr/testify/assert"
"github.com/superseriousbusiness/gotosocial/internal/httpclient"
- "github.com/superseriousbusiness/gotosocial/internal/queue"
"github.com/superseriousbusiness/gotosocial/internal/transport/delivery"
)
-func TestDeliveryWorkerPool(t *testing.T) {
- for _, i := range []int{1, 2, 4, 8, 16, 32} {
- t.Run("size="+strconv.Itoa(i), func(t *testing.T) {
- testDeliveryWorkerPool(t, i, generateInput(100*i))
- })
- }
-}
-
-func testDeliveryWorkerPool(t *testing.T, sz int, input []*testrequest) {
- wp := new(delivery.WorkerPool)
- wp.Init(httpclient.New(httpclient.Config{
- AllowRanges: config.MustParseIPPrefixes([]string{
- "127.0.0.0/8",
+var deliveryCases = []struct {
+ msg delivery.Delivery
+ data []byte
+}{
+ {
+ msg: delivery.Delivery{
+ PubKeyID: "https://google.com/users/bigboy#pubkey",
+ ActorID: "https://google.com/users/bigboy",
+ ObjectID: "https://google.com/users/bigboy/follow/1",
+ TargetID: "https://askjeeves.com/users/smallboy",
+ Request: toRequest("POST", "https://askjeeves.com/users/smallboy/inbox", []byte("data!")),
+ },
+ data: toJSON(map[string]any{
+ "pub_key_id": "https://google.com/users/bigboy#pubkey",
+ "actor_id": "https://google.com/users/bigboy",
+ "object_id": "https://google.com/users/bigboy/follow/1",
+ "target_id": "https://askjeeves.com/users/smallboy",
+ "method": "POST",
+ "url": "https://askjeeves.com/users/smallboy/inbox",
+ "body": []byte("data!"),
+ // "header": map[string][]string{},
+ }),
+ },
+ {
+ msg: delivery.Delivery{
+ Request: toRequest("GET", "https://google.com", []byte("uwu im just a wittle seawch engwin")),
+ },
+ data: toJSON(map[string]any{
+ "method": "GET",
+ "url": "https://google.com",
+ "body": []byte("uwu im just a wittle seawch engwin"),
+ // "header": map[string][]string{},
}),
- }))
- wp.Start(sz)
- defer wp.Stop()
- test(t, &wp.Queue, input)
+ },
}
-func test(
- t *testing.T,
- queue *queue.StructQueue[*delivery.Delivery],
- input []*testrequest,
-) {
- expect := make(chan *testrequest)
- errors := make(chan error)
-
- // Prepare an HTTP test handler that ensures expected delivery is received.
- handler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- errors <- (<-expect).Equal(r)
- })
-
- // Start new HTTP test server listener.
- l, err := net.Listen("tcp", "127.0.0.1:0")
- if err != nil {
- t.Fatal(err)
- }
- defer l.Close()
-
- // Start the HTTP server.
- //
- // specifically not using httptest.Server{} here as httptest
- // links that server with its own http.Client{}, whereas we're
- // using an httpclient.Client{} (well, delivery routine is).
- srv := new(http.Server)
- srv.Addr = "http://" + l.Addr().String()
- srv.Handler = handler
- go srv.Serve(l)
- defer srv.Close()
-
- // Range over test input.
- for _, test := range input {
-
- // Generate req for input.
- req := test.Generate(srv.Addr)
- r := httpclient.WrapRequest(req)
-
- // Wrap the request in delivery.
- dlv := new(delivery.Delivery)
- dlv.Request = r
-
- // Enqueue delivery!
- queue.Push(dlv)
- expect <- test
-
- // Wait for errors from handler.
- if err := <-errors; err != nil {
- t.Error(err)
+func TestSerializeDelivery(t *testing.T) {
+ for _, test := range deliveryCases {
+ // Serialize test message to blob.
+ data, err := test.msg.Serialize()
+ if err != nil {
+ t.Fatal(err)
}
- }
-}
-
-type testrequest struct {
- method string
- uri string
- body []byte
-}
-// generateInput generates 'n' many testrequest cases.
-func generateInput(n int) []*testrequest {
- tests := make([]*testrequest, n)
- for i := range tests {
- tests[i] = new(testrequest)
- tests[i].method = randomMethod()
- tests[i].uri = randomURI()
- tests[i].body = randomBody(tests[i].method)
+ // Check that serialized JSON data is as expected.
+ assert.JSONEq(t, string(test.data), string(data))
}
- return tests
}
-var methods = []string{
- http.MethodConnect,
- http.MethodDelete,
- http.MethodGet,
- http.MethodHead,
- http.MethodOptions,
- http.MethodPatch,
- http.MethodPost,
- http.MethodPut,
- http.MethodTrace,
-}
+func TestDeserializeDelivery(t *testing.T) {
+ for _, test := range deliveryCases {
+ var msg delivery.Delivery
-// randomMethod generates a random http method.
-func randomMethod() string {
- return methods[rand.Intn(len(methods))]
-}
+ // Deserialize test message blob.
+ err := msg.Deserialize(test.data)
+ if err != nil {
+ t.Fatal(err)
+ }
-// randomURI generates a random http uri.
-func randomURI() string {
- n := rand.Intn(5)
- p := make([]string, n)
- for i := range p {
- p[i] = strconv.Itoa(rand.Int())
+ // Check that delivery fields are as expected.
+ assert.Equal(t, test.msg.PubKeyID, msg.PubKeyID)
+ assert.Equal(t, test.msg.ActorID, msg.ActorID)
+ assert.Equal(t, test.msg.ObjectID, msg.ObjectID)
+ assert.Equal(t, test.msg.TargetID, msg.TargetID)
+ assert.Equal(t, test.msg.Request.Method, msg.Request.Method)
+ assert.Equal(t, test.msg.Request.URL, msg.Request.URL)
+ assert.Equal(t, readBody(test.msg.Request.Body), readBody(msg.Request.Body))
}
- return "/" + strings.Join(p, "/")
}
-// randomBody generates a random http body DEPENDING on method.
-func randomBody(method string) []byte {
- if requiresBody(method) {
- return []byte(method + " " + randomURI())
+// toRequest creates httpclient.Request from HTTP method, URL and body data.
+func toRequest(method string, url string, body []byte) httpclient.Request {
+ var rbody io.Reader
+ if body != nil {
+ rbody = bytes.NewReader(body)
}
- return nil
-}
-
-// requiresBody returns whether method requires body.
-func requiresBody(method string) bool {
- switch method {
- case http.MethodPatch,
- http.MethodPost,
- http.MethodPut:
- return true
- default:
- return false
+ req, err := http.NewRequest(method, url, rbody)
+ if err != nil {
+ panic(err)
}
+ return httpclient.WrapRequest(req)
}
-// Generate will generate a real http.Request{} from test data.
-func (t *testrequest) Generate(addr string) *http.Request {
- var body io.ReadCloser
- if t.body != nil {
- var b byteutil.ReadNopCloser
- b.Reset(t.body)
- body = &b
+// readBody reads the content of body io.ReadCloser into memory as byte slice.
+func readBody(r io.ReadCloser) []byte {
+ if r == nil {
+ return nil
}
- req, err := http.NewRequest(t.method, addr+t.uri, body)
+ b, err := io.ReadAll(r)
if err != nil {
panic(err)
}
- return req
+ return b
}
-// Equal checks if request matches receiving test request.
-func (t *testrequest) Equal(r *http.Request) error {
- // Ensure methods match.
- if t.method != r.Method {
- return fmt.Errorf("differing request methods: t=%q r=%q", t.method, r.Method)
- }
-
- // Ensure request URIs match.
- if t.uri != r.URL.RequestURI() {
- return fmt.Errorf("differing request urls: t=%q r=%q", t.uri, r.URL.RequestURI())
- }
-
- // Ensure body cases match.
- if requiresBody(t.method) {
-
- // Read request into memory.
- b, err := io.ReadAll(r.Body)
- if err != nil {
- return fmt.Errorf("error reading request body: %v", err)
- }
-
- // Compare the request bodies.
- st := strings.TrimSpace(string(t.body))
- sr := strings.TrimSpace(string(b))
- if st != sr {
- return fmt.Errorf("differing request bodies: t=%q r=%q", st, sr)
- }
+// toJSON marshals input type as JSON data.
+func toJSON(a any) []byte {
+ b, err := json.Marshal(a)
+ if err != nil {
+ panic(err)
}
-
- return nil
+ return b
}