discord_test.go 6.9 KB

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