私のプログラムで漏れが見つかったら、問題を解決しました。しかし、今私は " test"のGoテストで接続が漏れているのを見つけようとしていますか?これは私の質問です。Goテストでリークする接続をテストするにはどうすればよいですか?
私のテストでリクエストの数を変更しようとしましたが問題ではありませんでした。私が何をしても、私のテストでTCP接続の現在の数は同じままです。
func TestLeakingConnections(t *testing.T) {
getter := myhttp.New()
s := newServer(ok)
defer s.Close()
cur := tcps(t)
for i := 0; i < 1000; i++ {
r, _ := getter.GetWithTimeout(s.URL, time.Millisecond*10)
r.Body.Close()
}
for tries := 10; tries >= 0; tries-- {
growth := tcps(t) - cur
if growth > 5 {
t.Error("leaked")
return
}
}
}
// find tcp connections
func tcps(t *testing.T) (conns int) {
lsof, err := exec.Command("lsof", "-n", "-p", strconv.Itoa(os.Getpid())).Output()
if err != nil {
t.Skip("skipping test; error finding or running lsof")
}
for _, ls := range strings.Split(string(lsof), "\n") {
if strings.Contains(ls, "TCP") {
conns++
}
}
return
}
func newServer(f http.HandlerFunc) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(f))
}
func ok(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/xml")
io.WriteString(w, "<xml></xml>")
}
// myhttp package
// ...other code omitted for clarification
func (g *Getter) GetWithTimeout(
url string,
timeout time.Duration,
) (
*http.Response, error,
) {
// this is the leaking part
// moving this out of here will stop leaks
transport := http.Transport{
DialContext: (&net.Dialer{
Timeout: timeout,
}).DialContext,
TLSHandshakeTimeout: timeout,
ResponseHeaderTimeout: timeout,
ExpectContinueTimeout: timeout,
}
client := http.Client{
Timeout: timeout,
Transport: &transport,
}
return client.Get(url)
}
// fixture worker package
// some outside code injects getter into fixture_worker like this:
getter := myhttp.New()
// NewWithTimeout creates a new fetcher with timeout threshold
func NewWithTimeout(
getter myhttp.HTTPGetter,
fetchURL string,
timeout time.Duration,
) *Fetcher {
return &Fetcher{getter, fetchURL, timeout}
}
// Fetch fetches fixture xml
func (f *Fetcher) Fetch() (*parser.FixtureXML, error) {
res, err := f.getter.GetWithTimeout(f.fetchURL, f.timeout)
if err != nil {
if res != nil && res.Body != nil {
res.Body.Close()
}
return nil, errors.Wrap(err, ErrFetch.Error())
}
defer res.Body.Close()
ioutil.ReadAll(res.Body)
return &parser.FixtureXML{}, nil
}
治具ワーカーlsof
の出力:テストのhttps://pastebin.com/fDUkpYsE
出力:労働者フィクスチャそれが漏れたのに対し、リークしたことがないhttps://pastebin.com/uGpK0czn
テスト。
フィクスチャーワーカーは、テストと同じコードを使用して、myhttpパッケージを使用してhttp取得を要求しています。
あなたは身体をまったく読んでいません.HTMLクライアントは、接続を完全に捨てて節約しています(動作は保証されておらず、信頼できません)。 'GetWithTimeout'は正当な応答があったときにエラー値を追加して、本文を閉じるという文書化されたパターンも破っています。これは、呼び出し側が、 'ErrStatus'を何らかの方法で検査せずに、エラーが発生したときにボディが閉じるかどうかを知る方法がないことを意味します。私は 'dialFunc'の理由を理解していないので、とにかく' DialContext'を使うべきです。 – JimB
良いヒントをいただき、ありがとうございます。しかし、それは私の質問に答えることはできません:どうすれば私のテストで漏れをテストできますか? –