discord_test.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. package discordgo
  2. import (
  3. "os"
  4. "runtime"
  5. "sync/atomic"
  6. "testing"
  7. "time"
  8. )
  9. //////////////////////////////////////////////////////////////////////////////
  10. ////////////////////////////////////////////////////// VARS NEEDED FOR TESTING
  11. var (
  12. dg *Session // Stores a global discordgo user session
  13. dgBot *Session // Stores a global discordgo bot session
  14. envToken = os.Getenv("DG_TOKEN") // Token to use when authenticating the user account
  15. envBotToken = os.Getenv("DGB_TOKEN") // Token to use when authenticating the bot account
  16. envEmail = os.Getenv("DG_EMAIL") // Email to use when authenticating
  17. envPassword = os.Getenv("DG_PASSWORD") // Password to use when authenticating
  18. envGuild = os.Getenv("DG_GUILD") // Guild ID to use for tests
  19. envChannel = os.Getenv("DG_CHANNEL") // Channel ID to use for tests
  20. // envUser = os.Getenv("DG_USER") // User ID to use for tests
  21. envAdmin = os.Getenv("DG_ADMIN") // User ID of admin user to use for tests
  22. )
  23. func init() {
  24. if envBotToken != "" {
  25. if d, err := New(envBotToken); err == nil {
  26. dgBot = d
  27. }
  28. }
  29. if envEmail == "" || envPassword == "" || envToken == "" {
  30. return
  31. }
  32. if d, err := New(envEmail, envPassword, envToken); err == nil {
  33. dg = d
  34. }
  35. }
  36. //////////////////////////////////////////////////////////////////////////////
  37. /////////////////////////////////////////////////////////////// START OF TESTS
  38. // TestNew tests the New() function without any arguments. This should return
  39. // a valid Session{} struct and no errors.
  40. func TestNew(t *testing.T) {
  41. _, err := New()
  42. if err != nil {
  43. t.Errorf("New() returned error: %+v", err)
  44. }
  45. }
  46. // TestInvalidToken tests the New() function with an invalid token
  47. func TestInvalidToken(t *testing.T) {
  48. d, err := New("asjkldhflkjasdh")
  49. if err != nil {
  50. t.Fatalf("New(InvalidToken) returned error: %+v", err)
  51. }
  52. // New with just a token does not do any communication, so attempt an api call.
  53. _, err = d.UserSettings()
  54. if err == nil {
  55. t.Errorf("New(InvalidToken), d.UserSettings returned nil error.")
  56. }
  57. }
  58. // TestInvalidUserPass tests the New() function with an invalid Email and Pass
  59. func TestInvalidEmailPass(t *testing.T) {
  60. _, err := New("invalidemail", "invalidpassword")
  61. if err == nil {
  62. t.Errorf("New(InvalidEmail, InvalidPass) returned nil error.")
  63. }
  64. }
  65. // TestInvalidPass tests the New() function with an invalid Password
  66. func TestInvalidPass(t *testing.T) {
  67. if envEmail == "" {
  68. t.Skip("Skipping New(username,InvalidPass), DG_EMAIL not set")
  69. return
  70. }
  71. _, err := New(envEmail, "invalidpassword")
  72. if err == nil {
  73. t.Errorf("New(Email, InvalidPass) returned nil error.")
  74. }
  75. }
  76. // TestNewUserPass tests the New() function with a username and password.
  77. // This should return a valid Session{}, a valid Session.Token.
  78. func TestNewUserPass(t *testing.T) {
  79. if envEmail == "" || envPassword == "" {
  80. t.Skip("Skipping New(username,password), DG_EMAIL or DG_PASSWORD not set")
  81. return
  82. }
  83. d, err := New(envEmail, envPassword)
  84. if err != nil {
  85. t.Fatalf("New(user,pass) returned error: %+v", err)
  86. }
  87. if d == nil {
  88. t.Fatal("New(user,pass), d is nil, should be Session{}")
  89. }
  90. if d.Token == "" {
  91. t.Fatal("New(user,pass), d.Token is empty, should be a valid Token.")
  92. }
  93. }
  94. // TestNewToken tests the New() function with a Token. This should return
  95. // the same as the TestNewUserPass function.
  96. func TestNewToken(t *testing.T) {
  97. if envToken == "" {
  98. t.Skip("Skipping New(token), DG_TOKEN not set")
  99. }
  100. d, err := New(envToken)
  101. if err != nil {
  102. t.Fatalf("New(envToken) returned error: %+v", err)
  103. }
  104. if d == nil {
  105. t.Fatal("New(envToken), d is nil, should be Session{}")
  106. }
  107. if d.Token == "" {
  108. t.Fatal("New(envToken), d.Token is empty, should be a valid Token.")
  109. }
  110. }
  111. // TestNewUserPassToken tests the New() function with a username, password and token.
  112. // This should return the same as the TestNewUserPass function.
  113. func TestNewUserPassToken(t *testing.T) {
  114. if envEmail == "" || envPassword == "" || envToken == "" {
  115. t.Skip("Skipping New(username,password,token), DG_EMAIL, DG_PASSWORD or DG_TOKEN not set")
  116. return
  117. }
  118. d, err := New(envEmail, envPassword, envToken)
  119. if err != nil {
  120. t.Fatalf("New(user,pass,token) returned error: %+v", err)
  121. }
  122. if d == nil {
  123. t.Fatal("New(user,pass,token), d is nil, should be Session{}")
  124. }
  125. if d.Token == "" {
  126. t.Fatal("New(user,pass,token), d.Token is empty, should be a valid Token.")
  127. }
  128. }
  129. func TestOpenClose(t *testing.T) {
  130. if envToken == "" {
  131. t.Skip("Skipping TestClose, DG_TOKEN not set")
  132. }
  133. d, err := New(envToken)
  134. if err != nil {
  135. t.Fatalf("TestClose, New(envToken) returned error: %+v", err)
  136. }
  137. if err = d.Open(); err != nil {
  138. t.Fatalf("TestClose, d.Open failed: %+v", err)
  139. }
  140. // We need a better way to know the session is ready for use,
  141. // this is totally gross.
  142. start := time.Now()
  143. for {
  144. d.RLock()
  145. if d.DataReady {
  146. d.RUnlock()
  147. break
  148. }
  149. d.RUnlock()
  150. if time.Since(start) > 10*time.Second {
  151. t.Fatal("DataReady never became true.yy")
  152. }
  153. runtime.Gosched()
  154. }
  155. // TODO find a better way
  156. // Add a small sleep here to make sure heartbeat and other events
  157. // have enough time to get fired. Need a way to actually check
  158. // those events.
  159. time.Sleep(2 * time.Second)
  160. // UpdateStatus - maybe we move this into wsapi_test.go but the websocket
  161. // created here is needed. This helps tests that the websocket was setup
  162. // and it is working.
  163. if err = d.UpdateStatus(0, time.Now().String()); err != nil {
  164. t.Errorf("UpdateStatus error: %+v", err)
  165. }
  166. if err = d.Close(); err != nil {
  167. t.Fatalf("TestClose, d.Close failed: %+v", err)
  168. }
  169. }
  170. func TestAddHandler(t *testing.T) {
  171. testHandlerCalled := int32(0)
  172. testHandler := func(s *Session, m *MessageCreate) {
  173. atomic.AddInt32(&testHandlerCalled, 1)
  174. }
  175. interfaceHandlerCalled := int32(0)
  176. interfaceHandler := func(s *Session, i interface{}) {
  177. atomic.AddInt32(&interfaceHandlerCalled, 1)
  178. }
  179. bogusHandlerCalled := int32(0)
  180. bogusHandler := func(s *Session, se *Session) {
  181. atomic.AddInt32(&bogusHandlerCalled, 1)
  182. }
  183. d := Session{}
  184. d.AddHandler(testHandler)
  185. d.AddHandler(testHandler)
  186. d.AddHandler(interfaceHandler)
  187. d.AddHandler(bogusHandler)
  188. d.handleEvent(messageCreateEventType, &MessageCreate{})
  189. d.handleEvent(messageDeleteEventType, &MessageDelete{})
  190. <-time.After(500 * time.Millisecond)
  191. // testHandler will be called twice because it was added twice.
  192. if atomic.LoadInt32(&testHandlerCalled) != 2 {
  193. t.Fatalf("testHandler was not called twice.")
  194. }
  195. // interfaceHandler will be called twice, once for each event.
  196. if atomic.LoadInt32(&interfaceHandlerCalled) != 2 {
  197. t.Fatalf("interfaceHandler was not called twice.")
  198. }
  199. if atomic.LoadInt32(&bogusHandlerCalled) != 0 {
  200. t.Fatalf("bogusHandler was called.")
  201. }
  202. }
  203. func TestRemoveHandler(t *testing.T) {
  204. testHandlerCalled := int32(0)
  205. testHandler := func(s *Session, m *MessageCreate) {
  206. atomic.AddInt32(&testHandlerCalled, 1)
  207. }
  208. d := Session{}
  209. r := d.AddHandler(testHandler)
  210. d.handleEvent(messageCreateEventType, &MessageCreate{})
  211. r()
  212. d.handleEvent(messageCreateEventType, &MessageCreate{})
  213. <-time.After(500 * time.Millisecond)
  214. // testHandler will be called once, as it was removed in between calls.
  215. if atomic.LoadInt32(&testHandlerCalled) != 1 {
  216. t.Fatalf("testHandler was not called once.")
  217. }
  218. }