mirror of
https://github.com/blindlobstar/go-interview-problems
synced 2025-04-28 12:45:19 +00:00
177 lines
3.9 KiB
Go
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)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|