302 lines
8.1 KiB
Go
302 lines
8.1 KiB
Go
package discordgo
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////// VARS NEEDED FOR TESTING
|
|
var (
|
|
dg *Session // Stores a global discordgo user session
|
|
dgBot *Session // Stores a global discordgo bot session
|
|
|
|
envOAuth2Token = os.Getenv("DG_OAUTH2_TOKEN") // Token to use when authenticating using OAuth2 token
|
|
envBotToken = os.Getenv("DGB_TOKEN") // Token to use when authenticating the bot account
|
|
envGuild = os.Getenv("DG_GUILD") // Guild ID to use for tests
|
|
envChannel = os.Getenv("DG_CHANNEL") // Channel ID to use for tests
|
|
envVoiceChannel = os.Getenv("DG_VOICE_CHANNEL") // Channel ID to use for tests
|
|
envAdmin = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
fmt.Println("Init is being called.")
|
|
if envBotToken != "" {
|
|
if d, err := New(envBotToken); err == nil {
|
|
dgBot = d
|
|
}
|
|
}
|
|
|
|
if envOAuth2Token == "" {
|
|
envOAuth2Token = os.Getenv("DGU_TOKEN")
|
|
}
|
|
|
|
if envOAuth2Token != "" {
|
|
if d, err := New(envOAuth2Token); err == nil {
|
|
dg = d
|
|
}
|
|
}
|
|
|
|
os.Exit(m.Run())
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////// START OF TESTS
|
|
|
|
// TestNewToken tests the New() function with a Token.
|
|
func TestNewToken(t *testing.T) {
|
|
|
|
if envOAuth2Token == "" {
|
|
t.Skip("Skipping New(token), DGU_TOKEN not set")
|
|
}
|
|
|
|
d, err := New(envOAuth2Token)
|
|
if err != nil {
|
|
t.Fatalf("New(envToken) returned error: %+v", err)
|
|
}
|
|
|
|
if d == nil {
|
|
t.Fatal("New(envToken), d is nil, should be Session{}")
|
|
}
|
|
|
|
if d.Token == "" {
|
|
t.Fatal("New(envToken), d.Token is empty, should be a valid Token.")
|
|
}
|
|
}
|
|
|
|
func TestOpenClose(t *testing.T) {
|
|
if envOAuth2Token == "" {
|
|
t.Skip("Skipping TestClose, DGU_TOKEN not set")
|
|
}
|
|
|
|
d, err := New(envOAuth2Token)
|
|
if err != nil {
|
|
t.Fatalf("TestClose, New(envToken) returned error: %+v", err)
|
|
}
|
|
|
|
if err = d.Open(); err != nil {
|
|
t.Fatalf("TestClose, d.Open failed: %+v", err)
|
|
}
|
|
|
|
// We need a better way to know the session is ready for use,
|
|
// this is totally gross.
|
|
start := time.Now()
|
|
for {
|
|
d.RLock()
|
|
if d.DataReady {
|
|
d.RUnlock()
|
|
break
|
|
}
|
|
d.RUnlock()
|
|
|
|
if time.Since(start) > 10*time.Second {
|
|
t.Fatal("DataReady never became true.yy")
|
|
}
|
|
runtime.Gosched()
|
|
}
|
|
|
|
// TODO find a better way
|
|
// Add a small sleep here to make sure heartbeat and other events
|
|
// have enough time to get fired. Need a way to actually check
|
|
// those events.
|
|
time.Sleep(2 * time.Second)
|
|
|
|
// UpdateStatus - maybe we move this into wsapi_test.go but the websocket
|
|
// created here is needed. This helps tests that the websocket was setup
|
|
// and it is working.
|
|
if err = d.UpdateGameStatus(0, time.Now().String()); err != nil {
|
|
t.Errorf("UpdateStatus error: %+v", err)
|
|
}
|
|
|
|
if err = d.Close(); err != nil {
|
|
t.Fatalf("TestClose, d.Close failed: %+v", err)
|
|
}
|
|
}
|
|
|
|
func TestAddHandler(t *testing.T) {
|
|
|
|
testHandlerCalled := int32(0)
|
|
testHandler := func(s *Session, m *MessageCreate) {
|
|
atomic.AddInt32(&testHandlerCalled, 1)
|
|
}
|
|
|
|
interfaceHandlerCalled := int32(0)
|
|
interfaceHandler := func(s *Session, i interface{}) {
|
|
atomic.AddInt32(&interfaceHandlerCalled, 1)
|
|
}
|
|
|
|
bogusHandlerCalled := int32(0)
|
|
bogusHandler := func(s *Session, se *Session) {
|
|
atomic.AddInt32(&bogusHandlerCalled, 1)
|
|
}
|
|
|
|
d := Session{}
|
|
d.AddHandler(testHandler)
|
|
d.AddHandler(testHandler)
|
|
|
|
d.AddHandler(interfaceHandler)
|
|
d.AddHandler(bogusHandler)
|
|
|
|
d.handleEvent(messageCreateEventType, &MessageCreate{})
|
|
d.handleEvent(messageDeleteEventType, &MessageDelete{})
|
|
|
|
<-time.After(500 * time.Millisecond)
|
|
|
|
// testHandler will be called twice because it was added twice.
|
|
if atomic.LoadInt32(&testHandlerCalled) != 2 {
|
|
t.Fatalf("testHandler was not called twice.")
|
|
}
|
|
|
|
// interfaceHandler will be called twice, once for each event.
|
|
if atomic.LoadInt32(&interfaceHandlerCalled) != 2 {
|
|
t.Fatalf("interfaceHandler was not called twice.")
|
|
}
|
|
|
|
if atomic.LoadInt32(&bogusHandlerCalled) != 0 {
|
|
t.Fatalf("bogusHandler was called.")
|
|
}
|
|
}
|
|
|
|
func TestRemoveHandler(t *testing.T) {
|
|
|
|
testHandlerCalled := int32(0)
|
|
testHandler := func(s *Session, m *MessageCreate) {
|
|
atomic.AddInt32(&testHandlerCalled, 1)
|
|
}
|
|
|
|
d := Session{}
|
|
r := d.AddHandler(testHandler)
|
|
|
|
d.handleEvent(messageCreateEventType, &MessageCreate{})
|
|
|
|
r()
|
|
|
|
d.handleEvent(messageCreateEventType, &MessageCreate{})
|
|
|
|
<-time.After(500 * time.Millisecond)
|
|
|
|
// testHandler will be called once, as it was removed in between calls.
|
|
if atomic.LoadInt32(&testHandlerCalled) != 1 {
|
|
t.Fatalf("testHandler was not called once.")
|
|
}
|
|
}
|
|
|
|
func TestScheduledEvents(t *testing.T) {
|
|
if dgBot == nil {
|
|
t.Skip("Skipping, dgBot not set.")
|
|
}
|
|
|
|
beginAt := time.Now().Add(1 * time.Hour)
|
|
endAt := time.Now().Add(2 * time.Hour)
|
|
event, err := dgBot.GuildScheduledEventCreate(envGuild, &GuildScheduledEventParams{
|
|
Name: "Test Event",
|
|
PrivacyLevel: GuildScheduledEventPrivacyLevelGuildOnly,
|
|
ScheduledStartTime: &beginAt,
|
|
ScheduledEndTime: &endAt,
|
|
Description: "Awesome Test Event created on livestream",
|
|
EntityType: GuildScheduledEventEntityTypeExternal,
|
|
EntityMetadata: &GuildScheduledEventEntityMetadata{
|
|
Location: "https://discord.com",
|
|
},
|
|
})
|
|
defer dgBot.GuildScheduledEventDelete(envGuild, event.ID)
|
|
|
|
if err != nil || event.Name != "Test Event" {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
events, err := dgBot.GuildScheduledEvents(envGuild, true)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var foundEvent *GuildScheduledEvent
|
|
for _, e := range events {
|
|
if e.ID == event.ID {
|
|
foundEvent = e
|
|
break
|
|
}
|
|
}
|
|
if foundEvent.Name != event.Name {
|
|
t.Fatal("err on GuildScheduledEvents endpoint. Missing Scheduled Event")
|
|
}
|
|
|
|
getEvent, err := dgBot.GuildScheduledEvent(envGuild, event.ID, true)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if getEvent.Name != event.Name {
|
|
t.Fatal("err on GuildScheduledEvent endpoint. Mismatched Scheduled Event")
|
|
}
|
|
|
|
eventUpdated, err := dgBot.GuildScheduledEventEdit(envGuild, event.ID, &GuildScheduledEventParams{Name: "Test Event Updated"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if eventUpdated.Name != "Test Event Updated" {
|
|
t.Fatal("err on GuildScheduledEventUpdate endpoint. Scheduled Event Name mismatch")
|
|
}
|
|
|
|
// Usage of 1 and 1 is just the pseudo data with the purpose to run all branches in the function without crashes.
|
|
// see https://github.com/bwmarrin/discordgo/pull/1032#discussion_r815438303 for more details.
|
|
users, err := dgBot.GuildScheduledEventUsers(envGuild, event.ID, 1, true, "1", "1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(users) != 0 {
|
|
t.Fatal("err on GuildScheduledEventUsers. Mismatch of event maybe occurred")
|
|
}
|
|
|
|
err = dgBot.GuildScheduledEventDelete(envGuild, event.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestComplexScheduledEvents(t *testing.T) {
|
|
if dgBot == nil {
|
|
t.Skip("Skipping, dgBot not set.")
|
|
}
|
|
|
|
beginAt := time.Now().Add(1 * time.Hour)
|
|
endAt := time.Now().Add(2 * time.Hour)
|
|
event, err := dgBot.GuildScheduledEventCreate(envGuild, &GuildScheduledEventParams{
|
|
Name: "Test Voice Event",
|
|
PrivacyLevel: GuildScheduledEventPrivacyLevelGuildOnly,
|
|
ScheduledStartTime: &beginAt,
|
|
ScheduledEndTime: &endAt,
|
|
Description: "Test event on voice channel",
|
|
EntityType: GuildScheduledEventEntityTypeVoice,
|
|
ChannelID: envVoiceChannel,
|
|
})
|
|
if err != nil || event.Name != "Test Voice Event" {
|
|
t.Fatal(err)
|
|
}
|
|
defer dgBot.GuildScheduledEventDelete(envGuild, event.ID)
|
|
|
|
_, err = dgBot.GuildScheduledEventEdit(envGuild, event.ID, &GuildScheduledEventParams{
|
|
EntityType: GuildScheduledEventEntityTypeExternal,
|
|
EntityMetadata: &GuildScheduledEventEntityMetadata{
|
|
Location: "https://discord.com",
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatal("err on GuildScheduledEventEdit. Change of entity type to external failed")
|
|
}
|
|
|
|
_, err = dgBot.GuildScheduledEventEdit(envGuild, event.ID, &GuildScheduledEventParams{
|
|
ChannelID: envVoiceChannel,
|
|
EntityType: GuildScheduledEventEntityTypeVoice,
|
|
EntityMetadata: nil,
|
|
})
|
|
|
|
if err != nil {
|
|
t.Fatal("err on GuildScheduledEventEdit. Change of entity type to voice failed")
|
|
}
|
|
}
|