It flaps (see #380), and with this change, it will have more time to get the expected output in the flaky GitHub Actions environment.
162 lines
4.2 KiB
Go
162 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"sync/atomic"
|
|
"syscall"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/goleak"
|
|
)
|
|
|
|
func Test_Main(t *testing.T) {
|
|
|
|
dir, err := ioutil.TempDir(os.TempDir(), "remark42")
|
|
require.NoError(t, err)
|
|
defer os.RemoveAll(dir)
|
|
|
|
port := chooseRandomUnusedPort()
|
|
os.Args = []string{"test", "server", "--secret=123456", "--store.bolt.path=" + dir, "--backup=/tmp",
|
|
"--avatar.fs.path=" + dir, "--port=" + strconv.Itoa(port), "--url=https://demo.remark42.com", "--dbg", "--notify.type=none"}
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
<-done
|
|
e := syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
|
|
require.NoError(t, e)
|
|
}()
|
|
|
|
finished := make(chan struct{})
|
|
go func() {
|
|
main()
|
|
close(finished)
|
|
}()
|
|
|
|
// defer cleanup because require check below can fail
|
|
defer func() {
|
|
close(done)
|
|
<-finished
|
|
}()
|
|
|
|
waitForHTTPServerStart(port)
|
|
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/api/v1/ping", port))
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
assert.Equal(t, 200, resp.StatusCode)
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "pong", string(body))
|
|
}
|
|
|
|
func TestMain_WithWebhook(t *testing.T) {
|
|
dir, err := ioutil.TempDir(os.TempDir(), "remark42")
|
|
require.NoError(t, err)
|
|
defer os.RemoveAll(dir)
|
|
|
|
var webhookSent int32
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
atomic.StoreInt32(&webhookSent, 1)
|
|
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
|
|
|
|
b, e := ioutil.ReadAll(r.Body)
|
|
defer r.Body.Close()
|
|
|
|
assert.Nil(t, e)
|
|
assert.Equal(t, "Comment: env test", string(b))
|
|
}))
|
|
defer ts.Close()
|
|
|
|
port := chooseRandomUnusedPort()
|
|
os.Args = []string{"test", "server", "--secret=123456", "--store.bolt.path=" + dir, "--backup=/tmp",
|
|
"--avatar.fs.path=" + dir, "--port=" + strconv.Itoa(port), "--url=https://demo.remark42.com", "--dbg",
|
|
"--admin-passwd=password", "--site=remark", "--notify.admins=webhook"}
|
|
|
|
err = os.Setenv("NOTIFY_WEBHOOK_URL", ts.URL)
|
|
assert.NoError(t, err)
|
|
err = os.Setenv("NOTIFY_WEBHOOK_TEMPLATE", "Comment: {{.Orig}}")
|
|
assert.NoError(t, err)
|
|
err = os.Setenv("NOTIFY_WEBHOOK_HEADERS", "Content-Type:application/json")
|
|
assert.NoError(t, err)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
<-done
|
|
e := syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
|
|
require.NoError(t, e)
|
|
}()
|
|
|
|
finished := make(chan struct{})
|
|
go func() {
|
|
main()
|
|
assert.Eventually(t, func() bool {
|
|
return atomic.LoadInt32(&webhookSent) == int32(1)
|
|
}, time.Second, 100*time.Millisecond, "webhook was not sent")
|
|
close(finished)
|
|
}()
|
|
|
|
// defer cleanup because require check below can fail
|
|
defer func() {
|
|
close(done)
|
|
<-finished
|
|
}()
|
|
|
|
waitForHTTPServerStart(port)
|
|
|
|
resp, err := http.Post(fmt.Sprintf("http://admin:password@localhost:%d/api/v1/comment", port), "",
|
|
strings.NewReader(`{"text": "env test", "locator":{"url": "https://radio-t.com", "site": "remark"}}`))
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
assert.Equal(t, 201, resp.StatusCode)
|
|
}
|
|
|
|
func TestGetDump(t *testing.T) {
|
|
dump := getDump()
|
|
assert.True(t, strings.Contains(dump, "goroutine"))
|
|
assert.True(t, strings.Contains(dump, "[running]"))
|
|
assert.True(t, strings.Contains(dump, "backend/app/main.go"))
|
|
t.Logf("\n dump: %s", dump)
|
|
}
|
|
|
|
func chooseRandomUnusedPort() (port int) {
|
|
for i := 0; i < 10; i++ {
|
|
port = 40000 + int(rand.Int31n(10000))
|
|
if ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port)); err == nil {
|
|
_ = ln.Close()
|
|
break
|
|
}
|
|
}
|
|
return port
|
|
}
|
|
|
|
func waitForHTTPServerStart(port int) {
|
|
// wait for up to 10 seconds for server to start before returning it
|
|
client := http.Client{Timeout: time.Second}
|
|
for i := 0; i < 100; i++ {
|
|
time.Sleep(time.Millisecond * 100)
|
|
if resp, err := client.Get(fmt.Sprintf("http://localhost:%d", port)); err == nil {
|
|
_ = resp.Body.Close()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
// both ignores are for leaks which are detected locally
|
|
goleak.VerifyTestMain(
|
|
m,
|
|
goleak.IgnoreTopFunction("github.com/umputun/remark42/backend/app.init.0.func1"),
|
|
goleak.IgnoreTopFunction("net/http.(*Server).Shutdown"),
|
|
)
|
|
}
|