2021-04-11 09:50:27 +02:00
|
|
|
package send
|
|
|
|
|
|
|
|
import (
|
|
|
|
"brainbaking.com/go-jamming/app/mf"
|
|
|
|
"brainbaking.com/go-jamming/common"
|
2021-04-18 15:39:29 +02:00
|
|
|
"brainbaking.com/go-jamming/db"
|
2021-04-11 09:50:27 +02:00
|
|
|
"brainbaking.com/go-jamming/mocks"
|
2021-04-16 11:55:18 +02:00
|
|
|
"brainbaking.com/go-jamming/rest"
|
|
|
|
"fmt"
|
2021-04-11 09:50:27 +02:00
|
|
|
"github.com/stretchr/testify/assert"
|
2021-04-16 11:55:18 +02:00
|
|
|
"net/http"
|
2021-04-11 09:50:27 +02:00
|
|
|
"net/url"
|
|
|
|
"sync"
|
|
|
|
"testing"
|
2021-04-16 16:17:09 +02:00
|
|
|
"time"
|
2021-04-11 09:50:27 +02:00
|
|
|
)
|
|
|
|
|
2021-04-18 15:39:29 +02:00
|
|
|
var conf = &common.Config{
|
2021-04-18 21:31:31 +02:00
|
|
|
ConString: ":memory:",
|
2021-04-18 15:39:29 +02:00
|
|
|
AllowedWebmentionSources: []string{
|
|
|
|
"domain",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-04-16 16:17:09 +02:00
|
|
|
func TestSinceForDomain(t *testing.T) {
|
|
|
|
cases := []struct {
|
|
|
|
label string
|
|
|
|
sinceInParam string
|
2021-04-18 15:39:29 +02:00
|
|
|
sinceInDb string
|
2021-04-16 16:17:09 +02:00
|
|
|
expected time.Time
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"Is since parameter if provided",
|
|
|
|
"2021-03-09T15:51:43.732Z",
|
|
|
|
"",
|
|
|
|
time.Date(2021, time.March, 9, 15, 51, 43, 732, time.UTC),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Is file contents if since parameter is empty and file is not",
|
|
|
|
"",
|
|
|
|
"2021-03-09T15:51:43.732Z",
|
|
|
|
time.Date(2021, time.March, 9, 15, 51, 43, 732, time.UTC),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"Is empty time if both parameter and file are not present",
|
|
|
|
"",
|
|
|
|
"",
|
|
|
|
time.Time{},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range cases {
|
|
|
|
t.Run(tc.label, func(t *testing.T) {
|
2021-04-18 15:39:29 +02:00
|
|
|
snder := Sender{
|
|
|
|
Conf: conf,
|
|
|
|
Repo: db.NewMentionRepo(conf),
|
|
|
|
}
|
|
|
|
if tc.sinceInDb != "" {
|
|
|
|
snder.Repo.UpdateSince("domain", common.IsoToTime(tc.sinceInDb))
|
2021-04-16 16:17:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
actual := snder.sinceForDomain("domain", tc.sinceInParam)
|
|
|
|
assert.Equal(t, tc.expected.Year(), actual.Year())
|
|
|
|
assert.Equal(t, tc.expected.Month(), actual.Month())
|
|
|
|
assert.Equal(t, tc.expected.Day(), actual.Day())
|
|
|
|
assert.Equal(t, tc.expected.Hour(), actual.Hour())
|
|
|
|
assert.Equal(t, tc.expected.Minute(), actual.Minute())
|
|
|
|
assert.Equal(t, tc.expected.Second(), actual.Second())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-25 12:18:31 +02:00
|
|
|
func TestSendSingleDoesNotSendIfRelPathNotFound(t *testing.T) {
|
|
|
|
var postedSomething bool
|
|
|
|
snder := Sender{
|
|
|
|
Conf: conf,
|
|
|
|
RestClient: &mocks.RestClientMock{
|
|
|
|
GetBodyFunc: mocks.RelPathGetBodyFunc("../../../mocks/"),
|
|
|
|
PostFormFunc: func(endpt string, formValues url.Values) error {
|
|
|
|
postedSomething = true
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
snder.SendSingle("brainbaking.com", "unknown-file")
|
|
|
|
assert.False(t, postedSomething)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSendSingleSendsMentionsBasedOnRelativeDomain(t *testing.T) {
|
|
|
|
passedFormValues := url.Values{}
|
|
|
|
var endpoint string
|
|
|
|
snder := Sender{
|
|
|
|
Conf: conf,
|
|
|
|
RestClient: &mocks.RestClientMock{
|
|
|
|
GetBodyFunc: mocks.RelPathGetBodyFunc("../../../mocks/"),
|
|
|
|
PostFormFunc: func(endpt string, formValues url.Values) error {
|
|
|
|
passedFormValues = formValues
|
|
|
|
endpoint = endpt
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
snder.SendSingle("brainbaking.com", "single-send-test.html")
|
|
|
|
assert.Equal(t, "http://aaronpk.example/webmention-endpoint-body", endpoint)
|
|
|
|
assert.Equal(t, "https://brainbaking.com/single-send-test.html", passedFormValues.Get("source"))
|
|
|
|
assert.Equal(t, "https://brainbaking.com/link-discover-test-single.html", passedFormValues.Get("target"))
|
|
|
|
}
|
|
|
|
|
2021-04-11 09:50:27 +02:00
|
|
|
func TestSendMentionAsWebmention(t *testing.T) {
|
|
|
|
passedFormValues := url.Values{}
|
|
|
|
snder := Sender{
|
|
|
|
RestClient: &mocks.RestClientMock{
|
|
|
|
PostFormFunc: func(endpoint string, formValues url.Values) error {
|
|
|
|
passedFormValues = formValues
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
sendMentionAsWebmention(&snder, mf.Mention{
|
|
|
|
Source: "mysource",
|
|
|
|
Target: "mytarget",
|
|
|
|
}, "someendpoint")
|
|
|
|
|
|
|
|
assert.Equal(t, "mysource", passedFormValues.Get("source"))
|
|
|
|
assert.Equal(t, "mytarget", passedFormValues.Get("target"))
|
|
|
|
}
|
|
|
|
|
2021-04-16 11:55:18 +02:00
|
|
|
// Stress test for opening HTTP connections en masse.
|
|
|
|
// Works great for up to 1000 runs. 10k hits: "http: Accept error: accept tcp [::]:6666: accept: too many open files in system; retrying in 10ms"
|
|
|
|
// Crashed even GoLand and the open Spotify client...
|
|
|
|
// The rate limiter fixes this, and in reality, we never send out 10k links anyway.
|
|
|
|
func TestSendMentionIntegrationStressTest(t *testing.T) {
|
|
|
|
snder := Sender{
|
2021-04-18 15:39:29 +02:00
|
|
|
Conf: conf,
|
2021-04-16 11:55:18 +02:00
|
|
|
RestClient: &rest.HttpClient{},
|
|
|
|
}
|
|
|
|
|
|
|
|
runs := 100
|
|
|
|
responses := make(chan bool, runs)
|
|
|
|
|
2021-04-20 09:53:17 +02:00
|
|
|
mux := http.NewServeMux()
|
|
|
|
mux.HandleFunc("/pingback", func(writer http.ResponseWriter, request *http.Request) {
|
2021-04-16 11:55:18 +02:00
|
|
|
writer.WriteHeader(200)
|
|
|
|
writer.Write([]byte("pingbacked stuff."))
|
|
|
|
responses <- true
|
|
|
|
})
|
2021-04-20 09:53:17 +02:00
|
|
|
mux.HandleFunc("/target", func(writer http.ResponseWriter, request *http.Request) {
|
2021-04-16 11:55:18 +02:00
|
|
|
target := `<html>
|
|
|
|
<head>
|
|
|
|
<link rel="pingback" href="http://localhost:6666/pingback" />
|
|
|
|
</head>
|
|
|
|
<body>sup!</body>
|
|
|
|
</html>
|
|
|
|
`
|
|
|
|
writer.WriteHeader(200)
|
|
|
|
writer.Write([]byte(target))
|
|
|
|
})
|
2021-04-20 09:53:17 +02:00
|
|
|
srv := &http.Server{Addr: ":6666", Handler: mux}
|
|
|
|
defer srv.Close()
|
2021-04-16 11:55:18 +02:00
|
|
|
|
|
|
|
go func() {
|
|
|
|
fmt.Println("Serving stub at 6666...")
|
2021-04-20 09:53:17 +02:00
|
|
|
srv.ListenAndServe()
|
2021-04-16 11:55:18 +02:00
|
|
|
fmt.Println("Stub stopped?")
|
|
|
|
}()
|
|
|
|
|
|
|
|
fmt.Println("Bootstrapping runs...")
|
|
|
|
for i := 0; i < runs; i++ {
|
|
|
|
snder.sendMention(mf.Mention{
|
|
|
|
Source: "http://localhost:6666/source",
|
|
|
|
Target: "http://localhost:6666/target",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
fmt.Println("Asserting...")
|
|
|
|
for i := 0; i < runs; i++ {
|
|
|
|
pingbacked := <-responses
|
|
|
|
assert.True(t, pingbacked)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-11 09:50:27 +02:00
|
|
|
func TestSendIntegrationTestCanSendBothWebmentionsAndPingbacks(t *testing.T) {
|
|
|
|
posted := map[string]interface{}{}
|
2021-04-16 16:17:09 +02:00
|
|
|
var lock = sync.Mutex{}
|
2021-04-11 09:50:27 +02:00
|
|
|
|
|
|
|
snder := Sender{
|
2021-04-18 15:39:29 +02:00
|
|
|
Conf: conf,
|
|
|
|
Repo: db.NewMentionRepo(conf),
|
2021-04-11 09:50:27 +02:00
|
|
|
RestClient: &mocks.RestClientMock{
|
2021-04-23 09:39:49 +02:00
|
|
|
GetBodyFunc: mocks.RelPathGetBodyFunc("./../../../mocks/"),
|
2021-04-11 09:50:27 +02:00
|
|
|
PostFunc: func(url string, contentType string, body string) error {
|
2021-04-16 16:17:09 +02:00
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
2021-04-11 09:50:27 +02:00
|
|
|
posted[url] = body
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
PostFormFunc: func(endpoint string, formValues url.Values) error {
|
2021-04-16 16:17:09 +02:00
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
2021-04-11 09:50:27 +02:00
|
|
|
posted[endpoint] = formValues
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
snder.Send("brainbaking.com", "2021-03-16T16:00:00.000Z")
|
|
|
|
assert.Equal(t, 3, len(posted))
|
|
|
|
|
|
|
|
wmPost1 := posted["http://aaronpk.example/webmention-endpoint-header"].(url.Values)
|
|
|
|
assert.Equal(t, "https://brainbaking.com/notes/2021/03/16h17m07s14/", wmPost1.Get("source"))
|
|
|
|
assert.Equal(t, "https://brainbaking.com/link-discover-test-multiple.html", wmPost1.Get("target"))
|
|
|
|
|
|
|
|
wmPost2 := posted["http://aaronpk.example/pingback-endpoint-body"].(string)
|
|
|
|
expectedPost2 := `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<methodCall>
|
|
|
|
<methodName>pingback.ping</methodName>
|
|
|
|
<params>
|
|
|
|
<param>
|
|
|
|
<value><string>https://brainbaking.com/notes/2021/03/16h17m07s14/</string></value>
|
|
|
|
</param>
|
|
|
|
<param>
|
|
|
|
<value><string>https://brainbaking.com/pingback-discover-test-single.html</string></value>
|
|
|
|
</param>
|
|
|
|
</params>
|
|
|
|
</methodCall>`
|
|
|
|
assert.Equal(t, expectedPost2, wmPost2)
|
|
|
|
|
|
|
|
wmPost3 := posted["http://aaronpk.example/webmention-endpoint-body"].(url.Values)
|
|
|
|
assert.Equal(t, "https://brainbaking.com/notes/2021/03/16h17m07s14/", wmPost3.Get("source"))
|
|
|
|
assert.Equal(t, "https://brainbaking.com/link-discover-test-single.html", wmPost3.Get("target"))
|
|
|
|
}
|