1// Copyright 2014 Google Inc. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5// +build !appengine
6
7package internal
8
9import (
10	"sync"
11	"testing"
12	"time"
13
14	netcontext "golang.org/x/net/context"
15
16	basepb "google.golang.org/appengine/internal/base"
17)
18
19func TestDialLimit(t *testing.T) {
20	// Fill up semaphore with false acquisitions to permit only two TCP connections at a time.
21	// We don't replace limitSem because that results in a data race when net/http lazily closes connections.
22	nFake := cap(limitSem) - 2
23	for i := 0; i < nFake; i++ {
24		limitSem <- 1
25	}
26	defer func() {
27		for i := 0; i < nFake; i++ {
28			<-limitSem
29		}
30	}()
31
32	f, c, cleanup := setup() // setup is in api_test.go
33	defer cleanup()
34	f.hang = make(chan int)
35
36	// If we make two RunSlowly RPCs (which will wait for f.hang to be strobed),
37	// then the simple Non200 RPC should hang.
38	var wg sync.WaitGroup
39	wg.Add(2)
40	for i := 0; i < 2; i++ {
41		go func() {
42			defer wg.Done()
43			Call(toContext(c), "errors", "RunSlowly", &basepb.VoidProto{}, &basepb.VoidProto{})
44		}()
45	}
46	time.Sleep(50 * time.Millisecond) // let those two RPCs start
47
48	ctx, _ := netcontext.WithTimeout(toContext(c), 50*time.Millisecond)
49	err := Call(ctx, "errors", "Non200", &basepb.VoidProto{}, &basepb.VoidProto{})
50	if err != errTimeout {
51		t.Errorf("Non200 RPC returned with err %v, want errTimeout", err)
52	}
53
54	// Drain the two RunSlowly calls.
55	f.hang <- 1
56	f.hang <- 1
57	wg.Wait()
58}
59