session_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. package state
  2. import (
  3. "math"
  4. "net/netip"
  5. "sync"
  6. "testing"
  7. "time"
  8. "github.com/mk6i/retro-aim-server/wire"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func TestSession_SetAndGetAwayMessage(t *testing.T) {
  12. s := NewSession()
  13. assert.Empty(t, s.AwayMessage())
  14. msg := "here's my message"
  15. s.SetAwayMessage(msg)
  16. assert.Equal(t, msg, s.AwayMessage())
  17. }
  18. func TestSession_IncrementAndGetWarning(t *testing.T) {
  19. s := NewSession()
  20. assert.Zero(t, s.Warning())
  21. s.IncrementWarning(1)
  22. s.IncrementWarning(2)
  23. assert.Equal(t, uint16(3), s.Warning())
  24. }
  25. func TestSession_SetAndGetInvisible(t *testing.T) {
  26. s := NewSession()
  27. assert.False(t, s.Invisible())
  28. s.SetUserStatusBitmask(wire.OServiceUserStatusInvisible)
  29. assert.True(t, s.Invisible())
  30. }
  31. func TestSession_SetAndGetScreenName(t *testing.T) {
  32. s := NewSession()
  33. assert.Empty(t, s.IdentScreenName())
  34. sn := NewIdentScreenName("user-screen-name")
  35. s.SetIdentScreenName(sn)
  36. assert.Equal(t, sn, s.IdentScreenName())
  37. }
  38. func TestSession_SetAndGetChatRoomCookie(t *testing.T) {
  39. s := NewSession()
  40. assert.Empty(t, s.ChatRoomCookie())
  41. sn := "the-chat-cookie"
  42. s.SetChatRoomCookie(sn)
  43. assert.Equal(t, sn, s.ChatRoomCookie())
  44. }
  45. func TestSession_SetAndGetUIN(t *testing.T) {
  46. s := NewSession()
  47. assert.Empty(t, s.UIN())
  48. uin := uint32(100003)
  49. s.SetUIN(uin)
  50. assert.Equal(t, uin, s.UIN())
  51. }
  52. func TestSession_SetAndGetClientID(t *testing.T) {
  53. s := NewSession()
  54. assert.Empty(t, s.ClientID())
  55. clientID := "AIM Client ID"
  56. s.SetClientID(clientID)
  57. assert.Equal(t, clientID, s.ClientID())
  58. }
  59. func TestSession_SetAndGetRemoteAddr(t *testing.T) {
  60. s := NewSession()
  61. assert.Empty(t, s.RemoteAddr())
  62. remoteAddr, _ := netip.ParseAddrPort("1.2.3.4:1234")
  63. s.SetRemoteAddr(&remoteAddr)
  64. assert.Equal(t, &remoteAddr, s.RemoteAddr())
  65. }
  66. func TestSession_TLVUserInfo(t *testing.T) {
  67. tests := []struct {
  68. name string
  69. givenSessionFn func() *Session
  70. want wire.TLVUserInfo
  71. }{
  72. {
  73. name: "user is active and visible",
  74. givenSessionFn: func() *Session {
  75. s := NewSession()
  76. s.SetSignonTime(time.Unix(1, 0))
  77. s.SetIdentScreenName(NewIdentScreenName("xXAIMUSERXx"))
  78. s.SetDisplayScreenName("xXAIMUSERXx")
  79. s.IncrementWarning(10)
  80. s.SetUserInfoFlag(wire.OServiceUserFlagOSCARFree)
  81. return s
  82. },
  83. want: wire.TLVUserInfo{
  84. ScreenName: "xXAIMUSERXx",
  85. WarningLevel: 10,
  86. TLVBlock: wire.TLVBlock{
  87. TLVList: wire.TLVList{
  88. wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)),
  89. wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)),
  90. wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)),
  91. wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)),
  92. },
  93. },
  94. },
  95. },
  96. {
  97. name: "user is on ICQ",
  98. givenSessionFn: func() *Session {
  99. s := NewSession()
  100. s.SetSignonTime(time.Unix(1, 0))
  101. s.SetIdentScreenName(NewIdentScreenName("1000003"))
  102. s.SetDisplayScreenName("1000003")
  103. s.SetUserInfoFlag(wire.OServiceUserFlagICQ)
  104. return s
  105. },
  106. want: wire.TLVUserInfo{
  107. ScreenName: "1000003",
  108. TLVBlock: wire.TLVBlock{
  109. TLVList: wire.TLVList{
  110. wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)),
  111. wire.NewTLVBE(wire.OServiceUserInfoUserFlags, wire.OServiceUserFlagOSCARFree|wire.OServiceUserFlagICQ),
  112. wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)),
  113. wire.NewTLVBE(wire.OServiceUserInfoICQDC, wire.ICQDCInfo{}),
  114. wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)),
  115. },
  116. },
  117. },
  118. },
  119. {
  120. name: "user has away message set",
  121. givenSessionFn: func() *Session {
  122. s := NewSession()
  123. s.SetSignonTime(time.Unix(1, 0))
  124. s.SetAwayMessage("here's my away message")
  125. return s
  126. },
  127. want: wire.TLVUserInfo{
  128. TLVBlock: wire.TLVBlock{
  129. TLVList: wire.TLVList{
  130. wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)),
  131. wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x30)),
  132. wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)),
  133. wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)),
  134. },
  135. },
  136. },
  137. },
  138. {
  139. name: "user is invisible",
  140. givenSessionFn: func() *Session {
  141. s := NewSession()
  142. s.SetSignonTime(time.Unix(1, 0))
  143. s.SetUserStatusBitmask(wire.OServiceUserStatusInvisible)
  144. return s
  145. },
  146. want: wire.TLVUserInfo{
  147. TLVBlock: wire.TLVBlock{
  148. TLVList: wire.TLVList{
  149. wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)),
  150. wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)),
  151. wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0100)),
  152. wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)),
  153. },
  154. },
  155. },
  156. },
  157. {
  158. name: "user is idle",
  159. givenSessionFn: func() *Session {
  160. s := NewSession()
  161. // sign on at t=0m
  162. timeBegin := time.Unix(0, 0)
  163. s.SetSignonTime(timeBegin)
  164. // set idle for 1m at t=+5m (ergo user idled @ t=+4m)
  165. timeIdle := timeBegin.Add(5 * time.Minute)
  166. s.nowFn = func() time.Time { return timeIdle }
  167. s.SetIdle(1 * time.Minute)
  168. // now it's t=+10m, ergo idle time should be t10-t4=6m
  169. timeNow := timeBegin.Add(10 * time.Minute)
  170. s.nowFn = func() time.Time { return timeNow }
  171. return s
  172. },
  173. want: wire.TLVUserInfo{
  174. TLVBlock: wire.TLVBlock{
  175. TLVList: wire.TLVList{
  176. wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(0)),
  177. wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)),
  178. wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)),
  179. wire.NewTLVBE(wire.OServiceUserInfoIdleTime, uint16(6)),
  180. wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)),
  181. },
  182. },
  183. },
  184. },
  185. {
  186. name: "user goes idle then returns",
  187. givenSessionFn: func() *Session {
  188. s := NewSession()
  189. s.SetSignonTime(time.Unix(1, 0))
  190. s.SetIdle(1 * time.Second)
  191. s.UnsetIdle()
  192. return s
  193. },
  194. want: wire.TLVUserInfo{
  195. TLVBlock: wire.TLVBlock{
  196. TLVList: wire.TLVList{
  197. wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)),
  198. wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)),
  199. wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)),
  200. wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)),
  201. },
  202. },
  203. },
  204. },
  205. {
  206. name: "user has capabilities",
  207. givenSessionFn: func() *Session {
  208. s := NewSession()
  209. s.SetSignonTime(time.Unix(1, 0))
  210. s.SetCaps([][16]byte{
  211. {
  212. // chat: "748F2420-6287-11D1-8222-444553540000"
  213. 0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
  214. 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00,
  215. },
  216. {
  217. // chat2: "748F2420-6287-11D1-8222-444553540000"
  218. 0x75, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
  219. 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x01,
  220. },
  221. })
  222. return s
  223. },
  224. want: wire.TLVUserInfo{
  225. TLVBlock: wire.TLVBlock{
  226. TLVList: wire.TLVList{
  227. wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)),
  228. wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)),
  229. wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)),
  230. wire.NewTLVBE(wire.OServiceUserInfoOscarCaps, []byte{
  231. // chat: "748F2420-6287-11D1-8222-444553540000"
  232. 0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
  233. 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00,
  234. // chat: "748F2420-6287-11D1-8222-444553540000"
  235. 0x75, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
  236. 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x01,
  237. }),
  238. wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)),
  239. },
  240. },
  241. },
  242. },
  243. {
  244. name: "user has buddy icon",
  245. givenSessionFn: func() *Session {
  246. s := NewSession()
  247. s.SetSignonTime(time.Unix(1, 0))
  248. return s
  249. },
  250. want: wire.TLVUserInfo{
  251. WarningLevel: 0,
  252. TLVBlock: wire.TLVBlock{
  253. TLVList: wire.TLVList{
  254. wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)),
  255. wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)),
  256. wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)),
  257. wire.NewTLVBE(wire.OServiceUserInfoMySubscriptions, uint32(0)),
  258. },
  259. },
  260. },
  261. },
  262. }
  263. for _, tt := range tests {
  264. t.Run(tt.name, func(t *testing.T) {
  265. s := tt.givenSessionFn()
  266. assert.Equal(t, tt.want, s.TLVUserInfo())
  267. })
  268. }
  269. }
  270. func TestSession_SendAndRecvMessage_ExpectSessSendOK(t *testing.T) {
  271. s := NewSession()
  272. msg := wire.SNACMessage{
  273. Frame: wire.SNACFrame{
  274. FoodGroup: wire.ICBM,
  275. },
  276. }
  277. var wg sync.WaitGroup
  278. wg.Add(1)
  279. go func() {
  280. defer wg.Done()
  281. defer s.Close()
  282. status := s.RelayMessage(msg)
  283. assert.Equal(t, SessSendOK, status)
  284. }()
  285. loop:
  286. for {
  287. select {
  288. case m := <-s.ReceiveMessage():
  289. assert.Equal(t, msg, m)
  290. case <-s.Closed():
  291. break loop
  292. }
  293. }
  294. wg.Wait()
  295. }
  296. func TestSession_SendMessage_SessSendClosed(t *testing.T) {
  297. s := Session{
  298. msgCh: make(chan wire.SNACMessage, 1),
  299. stopCh: make(chan struct{}),
  300. }
  301. s.Close()
  302. if res := s.RelayMessage(wire.SNACMessage{}); res != SessSendClosed {
  303. t.Fatalf("expected SessSendClosed, got %+v", res)
  304. }
  305. }
  306. func TestSession_SendMessage_SessQueueFull(t *testing.T) {
  307. bufSize := 10
  308. s := Session{
  309. msgCh: make(chan wire.SNACMessage, bufSize),
  310. stopCh: make(chan struct{}),
  311. }
  312. for i := 0; i < bufSize; i++ {
  313. assert.Equal(t, SessSendOK, s.RelayMessage(wire.SNACMessage{}))
  314. }
  315. assert.Equal(t, SessQueueFull, s.RelayMessage(wire.SNACMessage{}))
  316. }
  317. func TestSession_Close_Twice(t *testing.T) {
  318. s := Session{
  319. stopCh: make(chan struct{}),
  320. }
  321. s.Close()
  322. s.Close() // make sure close is idempotent
  323. if !s.closed {
  324. t.Fatal("expected session to be closed")
  325. }
  326. select {
  327. case <-s.Closed():
  328. case <-time.After(1 * time.Second):
  329. t.Fatalf("channel is not closed")
  330. }
  331. }
  332. func TestSession_Close(t *testing.T) {
  333. s := NewSession()
  334. select {
  335. case <-s.Closed():
  336. assert.Fail(t, "channel is closed")
  337. default:
  338. // channel is open by default
  339. }
  340. s.Close()
  341. <-s.Closed()
  342. }
  343. func TestSession_EvaluateRateLimit_ObserveRateChanges(t *testing.T) {
  344. classParams := [5]wire.RateClass{
  345. {
  346. ID: 1,
  347. WindowSize: 80,
  348. ClearLevel: 2500,
  349. AlertLevel: 2000,
  350. LimitLevel: 1500,
  351. DisconnectLevel: 800,
  352. MaxLevel: 6000,
  353. },
  354. {
  355. ID: 2,
  356. WindowSize: 80,
  357. ClearLevel: 3000,
  358. AlertLevel: 2000,
  359. LimitLevel: 1500,
  360. DisconnectLevel: 1000,
  361. MaxLevel: 6000,
  362. },
  363. {
  364. ID: 3,
  365. WindowSize: 20,
  366. ClearLevel: 5100,
  367. AlertLevel: 5000,
  368. LimitLevel: 4000,
  369. DisconnectLevel: 3000,
  370. MaxLevel: 6000,
  371. },
  372. {
  373. ID: 4,
  374. WindowSize: 20,
  375. ClearLevel: 5500,
  376. AlertLevel: 5300,
  377. LimitLevel: 4200,
  378. DisconnectLevel: 3000,
  379. MaxLevel: 8000,
  380. },
  381. {
  382. ID: 5,
  383. WindowSize: 10,
  384. ClearLevel: 5500,
  385. AlertLevel: 5300,
  386. LimitLevel: 4200,
  387. DisconnectLevel: 3000,
  388. MaxLevel: 8000,
  389. },
  390. }
  391. rateClasses := wire.NewRateLimitClasses(classParams)
  392. t.Run("we can action every 5 seconds indefinitely without getting rate limited", func(t *testing.T) {
  393. now := time.Now()
  394. sess := NewSession()
  395. sess.SetRateClasses(now, rateClasses)
  396. rateClass := rateClasses.Get(3)
  397. sess.SubscribeRateLimits([]wire.RateLimitClassID{rateClass.ID})
  398. for i := 0; i < 100; i++ {
  399. now = now.Add(5 * time.Second)
  400. have := sess.EvaluateRateLimit(now, rateClass.ID)
  401. assert.Equal(t, wire.RateLimitStatusClear, have)
  402. }
  403. })
  404. t.Run("reach disconnect threshold", func(t *testing.T) {
  405. now := time.Now()
  406. sess := NewSession()
  407. sess.SetRateClasses(now, rateClasses)
  408. rateClass := rateClasses.Get(3)
  409. sess.SubscribeRateLimits([]wire.RateLimitClassID{rateClass.ID})
  410. // record some event in the rate limiter
  411. want := []wire.RateLimitStatus{
  412. wire.RateLimitStatusClear,
  413. wire.RateLimitStatusClear,
  414. wire.RateLimitStatusClear,
  415. wire.RateLimitStatusClear,
  416. wire.RateLimitStatusAlert,
  417. wire.RateLimitStatusAlert,
  418. wire.RateLimitStatusAlert,
  419. wire.RateLimitStatusAlert,
  420. wire.RateLimitStatusAlert,
  421. wire.RateLimitStatusLimited,
  422. wire.RateLimitStatusLimited,
  423. wire.RateLimitStatusLimited,
  424. wire.RateLimitStatusLimited,
  425. wire.RateLimitStatusLimited,
  426. wire.RateLimitStatusLimited,
  427. wire.RateLimitStatusLimited,
  428. wire.RateLimitStatusLimited,
  429. wire.RateLimitStatusDisconnect,
  430. }
  431. for i := 0; i < len(want); i++ {
  432. now = now.Add(1 * time.Second)
  433. have := sess.EvaluateRateLimit(now, rateClass.ID)
  434. assert.Equal(t, want[i], have)
  435. }
  436. select {
  437. case <-sess.Closed():
  438. default:
  439. t.Error("expected session to be closed")
  440. }
  441. })
  442. t.Run("reach rate limit threshold, wait for clear threshold", func(t *testing.T) {
  443. now := time.Now()
  444. sess := NewSession()
  445. sess.SetRateClasses(now, rateClasses)
  446. rateClass := rateClasses.Get(3)
  447. sess.SubscribeRateLimits([]wire.RateLimitClassID{rateClass.ID})
  448. // first reach the rate limit threshold
  449. want := []wire.RateLimitStatus{
  450. wire.RateLimitStatusClear,
  451. wire.RateLimitStatusClear,
  452. wire.RateLimitStatusClear,
  453. wire.RateLimitStatusClear,
  454. wire.RateLimitStatusAlert,
  455. wire.RateLimitStatusAlert,
  456. wire.RateLimitStatusAlert,
  457. wire.RateLimitStatusAlert,
  458. wire.RateLimitStatusAlert,
  459. wire.RateLimitStatusLimited,
  460. }
  461. for i := 0; i < len(want); i++ {
  462. now = now.Add(1 * time.Second)
  463. have := sess.EvaluateRateLimit(now, rateClass.ID)
  464. assert.Equal(t, want[i], have)
  465. if i > 0 && want[i-1] != want[i] {
  466. classChanges, rateChanges := sess.ObserveRateChanges(now)
  467. assert.Empty(t, classChanges)
  468. if assert.NotEmpty(t, rateChanges) {
  469. rateDelta := rateChanges[0]
  470. assert.Equal(t, rateClass, rateDelta.RateClass)
  471. assert.Equal(t, want[i], rateDelta.CurrentStatus)
  472. assert.True(t, rateDelta.Subscribed)
  473. if want[i] == wire.RateLimitStatusLimited {
  474. assert.True(t, rateDelta.LimitedNow)
  475. }
  476. }
  477. }
  478. }
  479. // this is a rearranged moving average formula that determines how many
  480. // milliseconds it will take to reach the clear threshold
  481. timeToRecover := int(math.Ceil((time.Duration(rateClass.ClearLevel*rateClass.WindowSize-sess.rateByClassID[rateClass.ID-1].CurrentLevel*(rateClass.WindowSize-1)) * time.Millisecond).Seconds()))
  482. assert.True(t, timeToRecover > 0)
  483. // indicate the time rate limiting kicked in
  484. timeLimited := now
  485. for i := 0; i < timeToRecover; i++ {
  486. now = now.Add(1 * time.Second)
  487. classDelta, stateDelta := sess.ObserveRateChanges(now)
  488. assert.Empty(t, classDelta)
  489. if i == timeToRecover-1 {
  490. // assert that the clear threshold has been met.
  491. assert.ElementsMatch(t, stateDelta, []RateClassState{
  492. {
  493. RateClass: rateClass,
  494. CurrentLevel: 5140,
  495. CurrentStatus: wire.RateLimitStatusClear,
  496. LastTime: timeLimited,
  497. Subscribed: true,
  498. LimitedNow: false,
  499. }})
  500. } else {
  501. // assert that no changed have been observed, it's still rate-limited
  502. assert.Nil(t, stateDelta)
  503. }
  504. }
  505. })
  506. t.Run("observe a rate class change", func(t *testing.T) {
  507. now := time.Now()
  508. sess := NewSession()
  509. sess.SetRateClasses(now, rateClasses)
  510. rateClass := rateClasses.Get(3)
  511. sess.SubscribeRateLimits([]wire.RateLimitClassID{rateClass.ID})
  512. now = now.Add(1 * time.Second)
  513. classDelta, stateDelta := sess.ObserveRateChanges(now)
  514. assert.Empty(t, classDelta)
  515. assert.Empty(t, stateDelta)
  516. paramsCopy := classParams
  517. paramsCopy[rateClass.ID-1].LimitLevel++
  518. newRateClasses := wire.NewRateLimitClasses(paramsCopy)
  519. now = now.Add(1 * time.Second)
  520. sess.SetRateClasses(now, newRateClasses)
  521. now = now.Add(1 * time.Second)
  522. classDelta, stateDelta = sess.ObserveRateChanges(now)
  523. assert.Equal(t, classDelta[0].RateClass, newRateClasses.Get(rateClass.ID))
  524. assert.Empty(t, stateDelta)
  525. })
  526. t.Run("as a bot, I can action every second indefinitely without getting rate limited", func(t *testing.T) {
  527. now := time.Now()
  528. sess := NewSession()
  529. sess.SetUserInfoFlag(wire.OServiceUserFlagBot)
  530. sess.SetRateClasses(now, rateClasses)
  531. for i := 0; i < 100; i++ {
  532. now = now.Add(1 * time.Second)
  533. have := sess.EvaluateRateLimit(now, wire.RateLimitClassID(1))
  534. assert.Equal(t, wire.RateLimitStatusClear, have)
  535. }
  536. })
  537. }
  538. func TestSession_SetAndGetFoodGroupVersions(t *testing.T) {
  539. versions := [wire.MDir + 1]uint16{}
  540. versions[wire.Feedbag] = 1
  541. versions[wire.OService] = 2
  542. s := NewSession()
  543. s.SetFoodGroupVersions(versions)
  544. assert.Equal(t, versions, s.FoodGroupVersions())
  545. }
  546. func TestSession_SetAndGetTypingEventsEnabled(t *testing.T) {
  547. s := NewSession()
  548. assert.False(t, s.TypingEventsEnabled())
  549. s.SetTypingEventsEnabled(true)
  550. assert.True(t, s.TypingEventsEnabled())
  551. s.SetTypingEventsEnabled(false)
  552. assert.False(t, s.TypingEventsEnabled())
  553. }
  554. func TestSession_SetAndGetMultiConnFlag(t *testing.T) {
  555. s := NewSession()
  556. assert.Zero(t, s.MultiConnFlag())
  557. s.SetMultiConnFlag(wire.MultiConnFlagsOldClient)
  558. assert.Equal(t, wire.MultiConnFlagsOldClient, s.MultiConnFlag())
  559. s.SetMultiConnFlag(wire.MultiConnFlagsRecentClient)
  560. assert.Equal(t, wire.MultiConnFlagsRecentClient, s.MultiConnFlag())
  561. s.SetMultiConnFlag(wire.MultiConnFlagsSingleClient)
  562. assert.Equal(t, wire.MultiConnFlagsSingleClient, s.MultiConnFlag())
  563. }