1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-11-27 17:23:00 +00:00
arikawa/api/rate/rate_test.go

81 lines
2.2 KiB
Go

package rate
import (
"context"
"fmt"
"net/http"
"testing"
"time"
)
// https://github.com/bwmarrin/discordgo/blob/master/ratelimit_test.go
func mockRequest(t *testing.T, l *Limiter, path string, headers http.Header) {
if err := l.Acquire(context.Background(), path); err != nil {
t.Fatal("Failed to acquire lock:", err)
}
if err := l.Release(path, headers); err != nil {
t.Fatal("Failed to release lock:", err)
}
}
// This test takes ~2 seconds to run
func TestRatelimitReset(t *testing.T) {
l := NewLimiter("")
const msToSec = time.Second / time.Millisecond
until := time.Now().Add(2 * time.Second)
reset := float64(until.UnixNano()/int64(time.Millisecond)) / float64(msToSec)
headers := http.Header{}
headers.Set("X-RateLimit-Remaining", "0")
headers.Set("X-RateLimit-Reset", fmt.Sprintf("%.3f", reset))
headers.Set("Date", time.Now().Format(time.RFC850))
sent := time.Now()
mockRequest(t, l, "/guilds/99/channels", headers)
mockRequest(t, l, "/guilds/55/channels", headers)
mockRequest(t, l, "/guilds/66/channels", headers)
// call it again
mockRequest(t, l, "/guilds/99/channels", headers)
mockRequest(t, l, "/guilds/55/channels", headers)
mockRequest(t, l, "/guilds/66/channels", headers)
// We hit the same endpoint 2 times, so we should only be ratelimited 2
// second and always less than 4 seconds (unless you're on a stoneage
// computer or using swap or something...)
if since := time.Since(sent); since >= time.Second && since < time.Second*4 {
t.Log("OK", since)
} else {
t.Error("did not ratelimit correctly, got:", since)
}
}
// This test takes ~1 seconds to run
func TestRatelimitGlobal(t *testing.T) {
l := NewLimiter("")
headers := http.Header{}
headers.Set("X-RateLimit-Global", "1.002")
// Reset for approx 1 seconds from now
headers.Set("Retry-After", "1")
sent := time.Now()
// This should trigger a global ratelimit
mockRequest(t, l, "/guilds/99/channels", headers)
time.Sleep(time.Millisecond * 100)
// This shouldn't go through in less than 1 second
mockRequest(t, l, "/guilds/55/channels", headers)
if time.Since(sent) >= time.Second && time.Since(sent) < time.Second*2 {
t.Log("OK", time.Since(sent))
} else {
t.Error("did not ratelimit correctly, got:", time.Since(sent))
}
}