// Copyright 2012 Google Inc. All rights reserved. // Use of this source code is governed by the Apache 2.0 // license that can be found in the LICENSE file. package runtime import ( "fmt" "net/http" "net/http/httptest" "testing" "time" "github.com/golang/protobuf/proto" "golang.org/x/net/context" "google.golang.org/appengine/internal/aetesting" pb "google.golang.org/appengine/internal/system" ) func TestRunInBackgroundSendFirst(t *testing.T) { testRunInBackground(t, true) } func TestRunInBackgroundRecvFirst(t *testing.T) { testRunInBackground(t, false) } func testRunInBackground(t *testing.T, sendFirst bool) { srv := httptest.NewServer(nil) defer srv.Close() const id = "f00bar" sendWait, recvWait := make(chan bool), make(chan bool) sbr := make(chan bool) // strobed when system.StartBackgroundRequest has started calls := 0 c := aetesting.FakeSingleContext(t, "system", "StartBackgroundRequest", func(req *pb.StartBackgroundRequestRequest, res *pb.StartBackgroundRequestResponse) error { calls++ if calls > 1 { t.Errorf("Too many calls to system.StartBackgroundRequest") } sbr <- true res.RequestId = proto.String(id) <-sendWait return nil }) var c2 context.Context // a fake newContext = func(*http.Request) context.Context { return c2 } var fRun int f := func(c3 context.Context) { fRun++ if c3 != c2 { t.Errorf("f got a different context than expected") } } ribErrc := make(chan error) go func() { ribErrc <- RunInBackground(c, f) }() brErrc := make(chan error) go func() { <-sbr req, err := http.NewRequest("GET", srv.URL+"/_ah/background", nil) if err != nil { brErrc <- fmt.Errorf("http.NewRequest: %v", err) return } req.Header.Set("X-AppEngine-BackgroundRequest", id) client := &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, }, } <-recvWait _, err = client.Do(req) brErrc <- err }() // Send and receive are both waiting at this point. waits := [2]chan bool{sendWait, recvWait} if !sendFirst { waits[0], waits[1] = waits[1], waits[0] } waits[0] <- true time.Sleep(100 * time.Millisecond) waits[1] <- true if err := <-ribErrc; err != nil { t.Fatalf("RunInBackground: %v", err) } if err := <-brErrc; err != nil { t.Fatalf("background request: %v", err) } if fRun != 1 { t.Errorf("Got %d runs of f, want 1", fRun) } }