1// Copyright 2012 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 5package runtime 6 7import ( 8 "fmt" 9 "net/http" 10 "net/http/httptest" 11 "testing" 12 "time" 13 14 "github.com/golang/protobuf/proto" 15 "golang.org/x/net/context" 16 17 "google.golang.org/appengine/internal/aetesting" 18 pb "google.golang.org/appengine/internal/system" 19) 20 21func TestRunInBackgroundSendFirst(t *testing.T) { testRunInBackground(t, true) } 22func TestRunInBackgroundRecvFirst(t *testing.T) { testRunInBackground(t, false) } 23 24func testRunInBackground(t *testing.T, sendFirst bool) { 25 srv := httptest.NewServer(nil) 26 defer srv.Close() 27 28 const id = "f00bar" 29 sendWait, recvWait := make(chan bool), make(chan bool) 30 sbr := make(chan bool) // strobed when system.StartBackgroundRequest has started 31 32 calls := 0 33 c := aetesting.FakeSingleContext(t, "system", "StartBackgroundRequest", func(req *pb.StartBackgroundRequestRequest, res *pb.StartBackgroundRequestResponse) error { 34 calls++ 35 if calls > 1 { 36 t.Errorf("Too many calls to system.StartBackgroundRequest") 37 } 38 sbr <- true 39 res.RequestId = proto.String(id) 40 <-sendWait 41 return nil 42 }) 43 44 var c2 context.Context // a fake 45 newContext = func(*http.Request) context.Context { 46 return c2 47 } 48 49 var fRun int 50 f := func(c3 context.Context) { 51 fRun++ 52 if c3 != c2 { 53 t.Errorf("f got a different context than expected") 54 } 55 } 56 57 ribErrc := make(chan error) 58 go func() { 59 ribErrc <- RunInBackground(c, f) 60 }() 61 62 brErrc := make(chan error) 63 go func() { 64 <-sbr 65 req, err := http.NewRequest("GET", srv.URL+"/_ah/background", nil) 66 if err != nil { 67 brErrc <- fmt.Errorf("http.NewRequest: %v", err) 68 return 69 } 70 req.Header.Set("X-AppEngine-BackgroundRequest", id) 71 client := &http.Client{ 72 Transport: &http.Transport{ 73 Proxy: http.ProxyFromEnvironment, 74 }, 75 } 76 77 <-recvWait 78 _, err = client.Do(req) 79 brErrc <- err 80 }() 81 82 // Send and receive are both waiting at this point. 83 waits := [2]chan bool{sendWait, recvWait} 84 if !sendFirst { 85 waits[0], waits[1] = waits[1], waits[0] 86 } 87 waits[0] <- true 88 time.Sleep(100 * time.Millisecond) 89 waits[1] <- true 90 91 if err := <-ribErrc; err != nil { 92 t.Fatalf("RunInBackground: %v", err) 93 } 94 if err := <-brErrc; err != nil { 95 t.Fatalf("background request: %v", err) 96 } 97 98 if fRun != 1 { 99 t.Errorf("Got %d runs of f, want 1", fRun) 100 } 101} 102