mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-11-27 09:12:53 +00:00
CI: Add perseverance test for Gateway
This commit is contained in:
parent
7b67a98405
commit
c6d8c741e8
112
.gitlab-ci.yml
112
.gitlab-ci.yml
|
@ -1,55 +1,67 @@
|
|||
{
|
||||
"image": "golang:alpine",
|
||||
"variables": {
|
||||
"GO111MODULE": "on",
|
||||
"CGO_ENABLED": "1", # for the race detector
|
||||
"COV": "/tmp/cov_results",
|
||||
"dismock": "github.com/mavolin/dismock/v2/pkg/dismock",
|
||||
"dismock_v": "259685b84e4b6ab364b0fd858aac2aa2dfa42502",
|
||||
# used only in integration_test
|
||||
"tested": "./api,./gateway,./bot,./discord"
|
||||
"image": "golang:alpine",
|
||||
"variables": {
|
||||
"GO111MODULE": "on",
|
||||
"CGO_ENABLED": "1", # for the race detector
|
||||
"COV": "/tmp/cov_results",
|
||||
"dismock": "github.com/mavolin/dismock/v2/pkg/dismock",
|
||||
"dismock_v": "259685b84e4b6ab364b0fd858aac2aa2dfa42502",
|
||||
# used only in integration_test
|
||||
"tested": "./api,./gateway,./bot,./discord"
|
||||
},
|
||||
"before_script": [
|
||||
"apk add git build-base"
|
||||
],
|
||||
"stages": [
|
||||
"build",
|
||||
"test"
|
||||
],
|
||||
"build_test": {
|
||||
"stage": "build",
|
||||
"script": [
|
||||
"go build ./..."
|
||||
]
|
||||
},
|
||||
"unit_test": {
|
||||
"stage": "test",
|
||||
"timeout": "2m", # 2 minutes
|
||||
# Don't run the test if we have a $BOT_TOKEN, because
|
||||
# integration_test will run instead.
|
||||
"except": {
|
||||
"variables": [ "$BOT_TOKEN" ]
|
||||
},
|
||||
"before_script": [
|
||||
"apk add git build-base"
|
||||
],
|
||||
"stages": [
|
||||
"build",
|
||||
"test"
|
||||
],
|
||||
"build_test": {
|
||||
"stage": "build",
|
||||
"script": [
|
||||
"go build ./..."
|
||||
]
|
||||
"script": [
|
||||
"go test -coverprofile $COV -tags unitonly -race ./...",
|
||||
"go tool cover -func $COV"
|
||||
]
|
||||
},
|
||||
"integration_test": {
|
||||
"stage": "test",
|
||||
"timeout": "5m", # 5 minutes
|
||||
# Run the test only if we have $BOT_TOKEN, else fallback to unit
|
||||
# tests.
|
||||
"only": {
|
||||
"variables": [ "$BOT_TOKEN", "$CHANNEL_ID", "$VOICE_ID" ]
|
||||
},
|
||||
"unit_test": {
|
||||
"stage": "test",
|
||||
"timeout": "2m", # 2 minutes
|
||||
# Don't run the test if we have a $BOT_TOKEN, because
|
||||
# integration_test will run instead.
|
||||
"except": {
|
||||
"variables": [ "$BOT_TOKEN" ]
|
||||
},
|
||||
"script": [
|
||||
"go test -coverprofile $COV -tags unitonly -race ./...",
|
||||
"go tool cover -func $COV"
|
||||
]
|
||||
"script": [
|
||||
"go get ./...",
|
||||
# Test this package along with dismock.
|
||||
"go get $dismock@$dismock_v",
|
||||
"go test -coverpkg $tested -coverprofile $COV -race ./... $dismock",
|
||||
"go mod tidy",
|
||||
"go tool cover -func $COV"
|
||||
]
|
||||
},
|
||||
"perseverance_test": {
|
||||
"stage": "test",
|
||||
"timeout": "55m", # 55 minuets; check testenv
|
||||
"interruptible": true, # Stop if newer jobs are available.
|
||||
"only": {
|
||||
"variables": [ "$BOT_TOKEN", "$CHANNEL_ID", "$VOICE_ID" ]
|
||||
},
|
||||
"integration_test": {
|
||||
"stage": "test",
|
||||
"timeout": "5m", # 5 minutes
|
||||
# Run the test only if we have $BOT_TOKEN, else fallback to unit
|
||||
# tests.
|
||||
"only": {
|
||||
"variables": [ "$BOT_TOKEN" ]
|
||||
},
|
||||
"script": [
|
||||
"go get ./...",
|
||||
# Test this package along with dismock.
|
||||
"go get $dismock@$dismock_v",
|
||||
"go test -coverpkg $tested -coverprofile $COV -race ./... $dismock",
|
||||
"go mod tidy",
|
||||
"go tool cover -func $COV"
|
||||
]
|
||||
}
|
||||
"script": [
|
||||
"go get ./...",
|
||||
"go test -race -tags perseverance -run Perseverance -parallel 9 ./..."
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// +build !unitonly
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
|
|
|
@ -203,6 +203,11 @@ func (g *Gateway) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Explicitly signal the pacemaker loop to stop. We should do this in case
|
||||
// the Start function exited before it could bind the event channel into the
|
||||
// loop.
|
||||
g.PacerLoop.Stop()
|
||||
|
||||
wsutil.WSDebug("Websocket closed; error:", err)
|
||||
|
||||
wsutil.WSDebug("Waiting for the Pacemaker loop to exit.")
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// +build !unitonly
|
||||
|
||||
package gateway
|
||||
|
||||
import (
|
||||
|
@ -29,17 +27,14 @@ func TestInvalidToken(t *testing.T) {
|
|||
t.Fatal("Failed to make a Gateway:", err)
|
||||
}
|
||||
|
||||
err = g.Open()
|
||||
if err == nil {
|
||||
if err = g.Open(); err == nil {
|
||||
t.Fatal("Unexpected success while opening with a bad token.")
|
||||
}
|
||||
|
||||
// 4004 Authentication Failed.
|
||||
if strings.Contains(err.Error(), "4004") {
|
||||
return
|
||||
if !strings.Contains(err.Error(), "4004") {
|
||||
t.Fatal("Unexpected error:", err)
|
||||
}
|
||||
|
||||
t.Fatal("Unexpected error:", err)
|
||||
}
|
||||
|
||||
func TestIntegration(t *testing.T) {
|
||||
|
@ -58,7 +53,7 @@ func TestIntegration(t *testing.T) {
|
|||
}
|
||||
g.AddIntents(IntentGuilds)
|
||||
g.AfterClose = func(err error) {
|
||||
log.Println("Closed.")
|
||||
t.Log("Closed.")
|
||||
}
|
||||
gateway = g
|
||||
|
||||
|
|
56
gateway/perseverance_test.go
Normal file
56
gateway/perseverance_test.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
// +build perseverance
|
||||
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v2/internal/testenv"
|
||||
)
|
||||
|
||||
func TestPerseverance(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := testenv.Must(t)
|
||||
|
||||
g, err := NewGateway("Bot " + config.BotToken)
|
||||
if err != nil {
|
||||
t.Fatal("failed to make the gateway:", err)
|
||||
}
|
||||
g.AddIntents(IntentGuilds)
|
||||
|
||||
if err := g.Open(); err != nil {
|
||||
t.Fatal("failed to open the gateway:", err)
|
||||
}
|
||||
|
||||
timeout := make(chan struct{}, 1)
|
||||
|
||||
// Automatically close the gateway after set duration.
|
||||
time.AfterFunc(testenv.PerseveranceTime, func() {
|
||||
t.Log("Perserverence test finshed. Closing gateway.")
|
||||
timeout <- struct{}{}
|
||||
|
||||
if err := g.Close(); err != nil {
|
||||
t.Error("failed to close gateway:", err)
|
||||
}
|
||||
})
|
||||
|
||||
// Spin on events.
|
||||
for ev := range g.Events {
|
||||
t.Logf("Received event %T.", ev)
|
||||
}
|
||||
|
||||
// Exit gracefully if we have not.
|
||||
select {
|
||||
case <-timeout:
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
if err := g.Close(); err != nil {
|
||||
t.Fatal("failed to clean up gateway after fail:", err)
|
||||
}
|
||||
|
||||
t.Fatal("Test failed before timeout.")
|
||||
}
|
|
@ -6,11 +6,14 @@ import (
|
|||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v2/discord"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const PerseveranceTime = 50 * time.Minute
|
||||
|
||||
type Env struct {
|
||||
BotToken string
|
||||
ChannelID discord.ChannelID
|
||||
|
@ -26,7 +29,7 @@ var (
|
|||
func Must(t *testing.T) Env {
|
||||
e, err := GetEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
t.Skip("integration test variables missing")
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
|
|
@ -81,6 +81,12 @@ func (p *PacemakerLoop) StartBeating(pace time.Duration, evl EventLoopHandler, e
|
|||
go func() { exit(p.startLoop()) }()
|
||||
}
|
||||
|
||||
// Stop signals the pacemaker to stop. It does not wait for the pacer to stop.
|
||||
// The pacer will call the given callback with a nil error.
|
||||
func (p *PacemakerLoop) Stop() {
|
||||
close(p.control)
|
||||
}
|
||||
|
||||
// SetEventChannel sets the event channel inside the event loop. There is no
|
||||
// guarantee that the channel is set when the function returns. This function is
|
||||
// concurrently safe.
|
||||
|
@ -106,7 +112,12 @@ func (p *PacemakerLoop) startLoop() error {
|
|||
return errors.Wrap(err, "pace failed, reconnecting")
|
||||
}
|
||||
|
||||
case fn := <-p.control:
|
||||
case fn, ok := <-p.control:
|
||||
if !ok { // Intentional stop at p.Close().
|
||||
WSDebug("Pacemaker intentionally stopped using p.control.")
|
||||
return nil
|
||||
}
|
||||
|
||||
fn()
|
||||
|
||||
case ev, ok := <-p.events:
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// +build !unitonly
|
||||
|
||||
package voice_test
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// +build !unitonly
|
||||
|
||||
package voice
|
||||
|
||||
import (
|
||||
|
|
Loading…
Reference in a new issue