Skip to content

Commit 9d45729

Browse files
committed
✨ (concurrency-and-select): add basic test
1 parent 31c1593 commit 9d45729

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

select/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# select
2+
3+
當遇到多個 goroutine 需要溝通時,可以透過 channel 來傳遞資料
4+
而當遇到多個資料需要傳遞給一個 goroutine 時
5+
6+
這時可以透過 select 語法來最有效的等候多個 channel 的傳遞資訊
7+

select/select.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package select_sample
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"time"
7+
)
8+
9+
var tenSecondTimeout = 10 * time.Second
10+
11+
func ConfigurableRacer(a, b string, timeout time.Duration) (winner string, error error) {
12+
select {
13+
case <-ping(a):
14+
return a, nil
15+
case <-ping(b):
16+
return b, nil
17+
case <-time.After(timeout):
18+
return "", fmt.Errorf("timed out waiting for %s and %s", a, b)
19+
}
20+
}
21+
func Racer(a, b string) (string, error) {
22+
return ConfigurableRacer(a, b, tenSecondTimeout)
23+
}
24+
25+
func measureResponseTime(url string) time.Duration {
26+
start := time.Now()
27+
http.Get(url)
28+
return time.Since(start)
29+
}
30+
31+
func ping(url string) chan struct{} {
32+
ch := make(chan struct{})
33+
go func() {
34+
// close after http Get
35+
http.Get(url)
36+
close(ch)
37+
}()
38+
return ch
39+
}

select/select_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package select_sample
2+
3+
import (
4+
"net/http"
5+
"net/http/httptest"
6+
"testing"
7+
"time"
8+
)
9+
10+
func TestRacer(t *testing.T) {
11+
t.Run("compares speeds of servers, returning the url of the fastest one", func(t *testing.T) {
12+
slowServer := makeDelayServer(5 * time.Millisecond)
13+
fastServer := makeDelayServer(0 * time.Millisecond)
14+
defer slowServer.Close()
15+
defer fastServer.Close()
16+
slowURL := slowServer.URL
17+
fastURL := fastServer.URL
18+
want := fastURL
19+
got, err := Racer(slowURL, fastURL)
20+
if err != nil {
21+
t.Errorf("error should be nit")
22+
}
23+
if got != want {
24+
t.Errorf("got %q, want %q", got, want)
25+
}
26+
})
27+
t.Run("returns an error if a server doesn't respond within the specified time", func(t *testing.T) {
28+
server := makeDelayServer(25 * time.Millisecond)
29+
30+
defer server.Close()
31+
32+
_, err := ConfigurableRacer(server.URL, server.URL, 20*time.Millisecond)
33+
34+
if err == nil {
35+
t.Error("expected an error but didn't get one")
36+
}
37+
})
38+
}
39+
40+
func makeDelayServer(timeout time.Duration) *httptest.Server {
41+
return httptest.NewServer(http.HandlerFunc(
42+
func(w http.ResponseWriter, r *http.Request) {
43+
time.Sleep(timeout)
44+
w.WriteHeader(http.StatusOK)
45+
},
46+
))
47+
}

0 commit comments

Comments
 (0)