2025-04-07 00:40:19 +02:00

177 lines
3.9 KiB
Go

package main
import (
"errors"
"testing"
"time"
)
var (
ErrNoResponse = errors.New("no response")
ErrExpected = errors.New("expected error")
)
type response struct {
body string
err error
delay time.Duration
}
type mockClient struct {
responses map[string]chan response
}
func newMockClient(responses map[string][]response) *mockClient {
client := &mockClient{responses: map[string]chan response{}}
for address, responses := range responses {
client.responses[address] = make(chan response, len(responses))
for _, resp := range responses {
client.responses[address] <- resp
}
}
return client
}
func (c *mockClient) Get(address string) (string, error) {
select {
case resp := <-c.responses[address]:
<-time.After(resp.delay)
return resp.body, resp.err
default:
return "", ErrNoResponse
}
}
func TestGet(t *testing.T) {
tests := []struct {
name string
responses map[string][]response
requests []string
results []struct {
body string
err error
}
}{
{
name: "Basic caching",
responses: map[string][]response{
"example.com": {
{body: "response1", err: nil, delay: 100 * time.Millisecond},
},
},
requests: []string{"example.com", "example.com"},
results: []struct {
body string
err error
}{
{body: "response1", err: nil},
{body: "response1", err: nil},
},
},
{
name: "Multiple different URLs",
responses: map[string][]response{
"example.com": {
{body: "response1", err: nil, delay: 50 * time.Millisecond},
},
"example.org": {
{body: "response2", err: nil, delay: 50 * time.Millisecond},
},
},
requests: []string{"example.com", "example.org", "example.com", "example.org"},
results: []struct {
body string
err error
}{
{body: "response1", err: nil},
{body: "response2", err: nil},
{body: "response1", err: nil},
{body: "response2", err: nil},
},
},
{
name: "Error handling",
responses: map[string][]response{
"example.com": {
{body: "", err: ErrExpected, delay: 50 * time.Millisecond},
},
},
requests: []string{"example.com", "example.com"},
results: []struct {
body string
err error
}{
{body: "", err: ErrExpected},
{body: "", err: ErrExpected},
},
},
{
name: "URL not found",
responses: map[string][]response{},
requests: []string{"nonexistent.com"},
results: []struct {
body string
err error
}{
{body: "", err: ErrNoResponse},
},
},
{
name: "Mixed success and errors",
responses: map[string][]response{
"success.com": {
{body: "success", err: nil, delay: 50 * time.Millisecond},
},
"error.com": {
{body: "", err: ErrExpected, delay: 50 * time.Millisecond},
},
},
requests: []string{"success.com", "error.com", "success.com", "error.com"},
results: []struct {
body string
err error
}{
{body: "success", err: nil},
{body: "", err: ErrExpected},
{body: "success", err: nil},
{body: "", err: ErrExpected},
},
},
{
name: "Changing responses",
responses: map[string][]response{
"example.com": {
{body: "first response", err: nil, delay: 50 * time.Millisecond},
{body: "second response", err: nil, delay: 50 * time.Millisecond},
},
},
requests: []string{"example.com", "example.com", "example.com"},
results: []struct {
body string
err error
}{
{body: "first response", err: nil},
{body: "first response", err: nil},
{body: "first response", err: nil},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := newMockClient(tt.responses)
cache := NewCache(client)
for i, req := range tt.requests {
resp, err := cache.Get(req)
if err != tt.results[i].err {
t.Errorf("Unexpected error: %v", err)
}
if resp != tt.results[i].body {
t.Errorf("Wrong response. Expected: %s, got: %s", tt.results[i].body, resp)
}
}
})
}
}