2024-09-21 18:07:09 +00:00
|
|
|
package context
|
|
|
|
|
|
|
|
import (
|
2024-09-21 18:20:15 +00:00
|
|
|
"context"
|
2024-09-21 18:46:07 +00:00
|
|
|
"errors"
|
2024-09-21 18:35:43 +00:00
|
|
|
"log"
|
2024-09-21 18:07:09 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
2024-09-21 18:20:15 +00:00
|
|
|
"time"
|
2024-09-21 18:07:09 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type SpyStore struct {
|
2024-09-21 18:35:43 +00:00
|
|
|
response string
|
|
|
|
t *testing.T
|
2024-09-21 18:07:09 +00:00
|
|
|
}
|
|
|
|
|
2024-09-21 18:35:43 +00:00
|
|
|
func (s *SpyStore) Fetch(ctx context.Context) (string, error) {
|
|
|
|
data := make(chan string, 1)
|
|
|
|
go func() {
|
|
|
|
var result string
|
|
|
|
for _, c := range s.response {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
log.Println("spy store got cancelled")
|
|
|
|
return
|
|
|
|
default:
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
result += string(c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
data <- result
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return "", ctx.Err()
|
|
|
|
case res := <-data:
|
|
|
|
return res, nil
|
2024-09-21 18:26:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-21 18:46:07 +00:00
|
|
|
type SpyResponseWriter struct {
|
|
|
|
written bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SpyResponseWriter) Header() http.Header {
|
|
|
|
s.written = true
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SpyResponseWriter) Write([]byte) (int, error) {
|
|
|
|
s.written = true
|
|
|
|
return 0, errors.New("not implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *SpyResponseWriter) WriteHeader(statusCode int) {
|
|
|
|
s.written = true
|
|
|
|
}
|
|
|
|
|
2024-09-21 18:07:09 +00:00
|
|
|
func TestServer(t *testing.T) {
|
2024-09-21 18:20:15 +00:00
|
|
|
t.Run("basic get store", func(t *testing.T) {
|
|
|
|
data := "hello, world"
|
2024-09-21 18:26:22 +00:00
|
|
|
store := &SpyStore{response: data, t: t}
|
2024-09-21 18:20:15 +00:00
|
|
|
srv := Server(store)
|
|
|
|
|
|
|
|
request := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
|
|
response := httptest.NewRecorder()
|
|
|
|
|
|
|
|
srv.ServeHTTP(response, request)
|
|
|
|
|
|
|
|
if response.Body.String() != data {
|
|
|
|
t.Errorf(`got "%s", want "%s"`, response.Body.String(), data)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2024-09-21 18:46:07 +00:00
|
|
|
t.Run("tells store to cancel work if request is cancelled", func(t *testing.T) {
|
|
|
|
data := "hello, world"
|
|
|
|
store := &SpyStore{response: data, t: t}
|
|
|
|
srv := Server(store)
|
|
|
|
|
|
|
|
request := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
|
|
|
|
|
|
cancellingCtx, cancel := context.WithCancel(request.Context())
|
|
|
|
// Wait 5ms to call cancel
|
|
|
|
time.AfterFunc(5*time.Millisecond, cancel)
|
|
|
|
|
|
|
|
request = request.WithContext(cancellingCtx)
|
|
|
|
|
|
|
|
response := &SpyResponseWriter{}
|
|
|
|
|
|
|
|
srv.ServeHTTP(response, request)
|
|
|
|
|
|
|
|
if response.written {
|
|
|
|
t.Error("a response should not have been written")
|
|
|
|
}
|
|
|
|
})
|
2024-09-21 18:07:09 +00:00
|
|
|
}
|