-
Notifications
You must be signed in to change notification settings - Fork 56
/
checker_test.go
134 lines (116 loc) · 2.52 KB
/
checker_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package tcp
import (
"context"
"fmt"
"net"
"net/http"
"net/http/httptest"
"os"
"runtime"
"sync"
"testing"
"time"
)
const (
AddrDead = "127.0.0.1:1"
)
var timeoutAddrs = []string{
"10.255.255.1:80",
"10.0.0.0:1",
}
var AddrTimeout = timeoutAddrs[0]
func _setAddrTimeout() {
for _, addr := range timeoutAddrs {
conn, err := net.DialTimeout("tcp", addr, time.Millisecond*50)
if err == nil {
conn.Close()
continue
}
if os.IsTimeout(err) {
AddrTimeout = addr
return
}
}
}
func init() {
_setAddrTimeout()
}
// assert calls t.Fatal if the result is false
func assert(t *testing.T, result bool) {
if !result {
_, fileName, line, _ := runtime.Caller(1)
t.Fatalf("Test failed: %s:%d", fileName, line)
}
}
func ExampleChecker() {
c := NewChecker()
ctx, stopChecker := context.WithCancel(context.Background())
defer stopChecker()
go func() {
if err := c.CheckingLoop(ctx); err != nil {
fmt.Println("checking loop stopped due to fatal error: ", err)
}
}()
<-c.WaitReady()
timeout := time.Second * 1
err := c.CheckAddr("google.com:80", timeout)
switch err {
case ErrTimeout:
fmt.Println("Connect to Google timed out")
case nil:
fmt.Println("Connect to Google succeeded")
default:
fmt.Println("Error occurred while connecting: ", err)
}
}
func TestCheckAddr(t *testing.T) {
t.Parallel()
var err error
// Create checker
c := NewChecker()
// Start checker
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go c.CheckingLoop(ctx)
<-c.WaitReady()
timeout := time.Second * 2
// Check dead server
err = c.CheckAddr(AddrDead, timeout)
if runtime.GOOS == "linux" {
_, ok := err.(*ErrConnect)
assert(t, ok)
} else {
assert(t, err != nil)
}
// Launch a server for test
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
// Check alive server
err = c.CheckAddr(ts.Listener.Addr().String(), timeout)
assert(t, err == nil)
ts.Close()
// Check non-routable address, thus timeout
err = c.CheckAddr(AddrTimeout, timeout)
if err != ErrTimeout {
t.Log("expected ErrTimeout, got ", err)
t.FailNow()
}
}
func TestCheckAddrConcurrently(t *testing.T) {
// Create checker
c := NewChecker()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go c.CheckingLoop(ctx)
var wg sync.WaitGroup
check := func() {
if err := c.CheckAddr(AddrTimeout, time.Millisecond*50); err == nil {
t.Fatal("Concurrent testing failed")
}
wg.Done()
}
for i := 0; i < 1000; i++ {
wg.Add(1)
go check()
}
wg.Wait()
}