github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/controller/http_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package controller_test
     5  
     6  import (
     7  	"net"
     8  	"net/http"
     9  	"net/url"
    10  
    11  	"github.com/juju/httprequest"
    12  	"github.com/juju/testing"
    13  	jc "github.com/juju/testing/checkers"
    14  	gc "gopkg.in/check.v1"
    15  	names "gopkg.in/juju/names.v2"
    16  
    17  	"github.com/juju/juju/api/base"
    18  	coretesting "github.com/juju/juju/testing"
    19  )
    20  
    21  // newHTTPFixture creates and returns an HTTP fixture to be used in order to
    22  // mock controller HTTP requests to the given controller address.
    23  // Use it like in the following example:
    24  //   fix := newHTTPFixture("/my/controller/path", func(w http.ResponseWriter, req *http.Request) {
    25  //       // Simulate what's returned by the server.
    26  //   })
    27  //   stub := fix.run(c, func(ac base.APICallCloser) {
    28  //       // Do something with the API caller.
    29  //   })
    30  // At this point the stub, if the handler has been called, includes one call
    31  // with the HTTP method requested while running the test function.
    32  func newHTTPFixture(address string, handle func(http.ResponseWriter, *http.Request)) *httpFixture {
    33  	return &httpFixture{
    34  		address: address,
    35  		handle:  handle,
    36  	}
    37  }
    38  
    39  // httpFixture is used to mock controller HTTP API calls.
    40  type httpFixture struct {
    41  	address string
    42  	handle  func(http.ResponseWriter, *http.Request)
    43  }
    44  
    45  // run sets up the fixture and run the given test. See newHTTPFixture for an
    46  // example of how to use this.
    47  func (f *httpFixture) run(c *gc.C, test func(base.APICallCloser)) *testing.Stub {
    48  	stub := &testing.Stub{}
    49  	lis, err := net.Listen("tcp", "127.0.0.1:0")
    50  	c.Assert(err, jc.ErrorIsNil)
    51  	defer lis.Close()
    52  	mux := http.NewServeMux()
    53  	mux.HandleFunc(f.address, func(w http.ResponseWriter, r *http.Request) {
    54  		stub.AddCall(r.Method)
    55  		f.handle(w, r)
    56  	})
    57  	go func() {
    58  		http.Serve(lis, mux)
    59  	}()
    60  	test(&httpAPICallCloser{
    61  		url: &url.URL{
    62  			Scheme: "http",
    63  			Host:   lis.Addr().String(),
    64  		},
    65  	})
    66  	return stub
    67  }
    68  
    69  var _ base.APICallCloser = (*httpAPICallCloser)(nil)
    70  
    71  // httpAPICallCloser implements base.APICallCloser.
    72  type httpAPICallCloser struct {
    73  	base.APICallCloser
    74  	url *url.URL
    75  }
    76  
    77  // ModelTag implements base.APICallCloser.
    78  func (*httpAPICallCloser) ModelTag() (names.ModelTag, bool) {
    79  	return coretesting.ModelTag, true
    80  }
    81  
    82  // BestFacadeVersion implements base.APICallCloser.
    83  func (*httpAPICallCloser) BestFacadeVersion(facade string) int {
    84  	return 42
    85  }
    86  
    87  // HTTPClient implements base.APICallCloser. The returned HTTP client can be
    88  // used to send requests to the testing server set up in httpFixture.run().
    89  func (ac *httpAPICallCloser) HTTPClient() (*httprequest.Client, error) {
    90  	return &httprequest.Client{
    91  		BaseURL: ac.url.String(),
    92  	}, nil
    93  }