discord_test.go 7.0 KB

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