"net/http"
"net/http/httptest"
"testing"
+ "testing/synctest"
"time"
"github.com/stretchr/testify/require"
require.Equal(t, "getUpdates", call.method)
require.Equal(t, map[string]any{
"offset": float64(7),
- "timeout": float64(telegramPollSeconds),
+ "timeout": float64(telegramUpdateWaitTimeout / time.Second),
"allowed_updates": []any{"message"},
}, call.params)
}
for _, tc := range testCases {
t.Run(tc.method, func(t *testing.T) {
- server := newTelegramFake(t)
- server.stall = func(call TelegramFakeCall) bool {
- return call.method == tc.method
- }
-
- api := newTelegramAPI(server.URL, telegramTestToken)
- api.sendTimeout = 50 * time.Millisecond
- start := time.Now()
- err := tc.send(t.Context(), api)
- require.EqualError(t, err, "no answer in 50ms")
- require.Less(t, time.Since(start), 5*time.Second)
- require.NotContains(t, err.Error(), telegramTestToken)
- require.NotContains(t, err.Error(), server.URL)
+ synctest.Test(t, func(t *testing.T) {
+ server := newTelegramLocalFake(t)
+ server.stall = func(call TelegramFakeCall) bool {
+ return call.method == tc.method
+ }
+
+ api := newTelegramAPI(server.URL, telegramTestToken)
+ api.http.Transport = server
+ start := time.Now()
+ err := tc.send(t.Context(), api)
+ require.EqualError(t, err, "no answer in 30s")
+ require.Equal(t, telegramSendTimeout, time.Since(start))
+ require.NotContains(t, err.Error(), telegramTestToken)
+ require.NotContains(t, err.Error(), server.URL)
+
+ retry, _ := telegramRetryable(err)
+ require.True(t, retry)
+
+ ctx, cancel := context.WithCancel(t.Context())
+ defer cancel()
- retry, _ := telegramRetryable(err)
- require.True(t, retry)
+ time.AfterFunc(time.Second, cancel)
- api.sendTimeout = time.Hour
- ctx, cancel := context.WithCancel(t.Context())
- time.AfterFunc(50*time.Millisecond, cancel)
- start = time.Now()
- err = tc.send(ctx, api)
- require.Error(t, err)
- require.Less(t, time.Since(start), 5*time.Second)
+ start = time.Now()
+ err = tc.send(ctx, api)
+ require.Error(t, err)
+ require.Equal(t, time.Second, time.Since(start))
+ })
})
}
}
name: "rate limit waits as asked",
reply: func(w http.ResponseWriter) {
w.WriteHeader(http.StatusTooManyRequests)
+
_, _ = io.WriteString(w, `{"ok":false,"error_code":429,"description":"Too Many Requests: retry after 3","parameters":{"retry_after":3}}`)
},
retry: true,
name: "server error page is retried",
reply: func(w http.ResponseWriter) {
w.WriteHeader(http.StatusBadGateway)
+
_, _ = io.WriteString(w, "<html>bad gateway</html>")
},
retry: true,
name: "token echoed in a description is hidden",
reply: func(w http.ResponseWriter) {
w.WriteHeader(http.StatusUnauthorized)
+
_, _ = io.WriteString(w, `{"ok":false,"error_code":401,"description":"Unauthorized: bot`+telegramTestToken+`"}`)
},
retry: false,
name: "bad request is a refusal",
reply: func(w http.ResponseWriter) {
w.WriteHeader(http.StatusBadRequest)
+
_, _ = io.WriteString(w, `{"ok":false,"error_code":400,"description":"Bad Request: can't parse"}`)
},
retry: false,
name: "unknown method is a refusal",
reply: func(w http.ResponseWriter) {
w.WriteHeader(http.StatusNotFound)
+
_, _ = io.WriteString(w, `{"ok":false,"error_code":404,"description":"Not Found"}`)
},
retry: false,
name: "not found page of a proxy is not a refusal",
reply: func(w http.ResponseWriter) {
w.WriteHeader(http.StatusNotFound)
+
_, _ = io.WriteString(w, "<html>not found</html>")
},
retry: false,