...

Source file src/github.com/okta/okta-sdk-golang/v2/tests/unit/request_executor_test.go

Documentation: github.com/okta/okta-sdk-golang/v2/tests/unit

     1  package unit
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net/http"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/okta/okta-sdk-golang/v2/okta"
    12  	"github.com/okta/okta-sdk-golang/v2/tests"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  // readerFun makes it easier to implement an inline reader as a closure function.
    17  type readerFun func(p []byte) (n int, err error)
    18  
    19  // Read, part of io.Reader interface.
    20  func (r readerFun) Read(p []byte) (n int, err error) { return r(p) }
    21  
    22  // slowTransport provides a dummy http-like transport serving fixed content, but slowly.
    23  type slowTransport struct{}
    24  
    25  // RoundTrip, part of http.Transport interface. This servers 42 as a JSON response, but slowly.
    26  // In particular, we serve the response immediately, but getting the body takes some milliseconds.
    27  func (t slowTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    28  	realBody := strings.NewReader("42")
    29  	// This body takes 1 millisecond to read. It also needs a valid context for the whole duration.
    30  	slowBody := func(p []byte) (n int, err error) {
    31  		select {
    32  		case <-req.Context().Done():
    33  			return 0, req.Context().Err()
    34  		case <-time.After(1 * time.Millisecond):
    35  			return realBody.Read(p)
    36  		}
    37  	}
    38  
    39  	rsp := &http.Response{
    40  		StatusCode: 200,
    41  		Body:       io.NopCloser(readerFun(slowBody)),
    42  		Header:     http.Header{},
    43  		Request:    req,
    44  	}
    45  	rsp.Header.Set("Content-Type", "application/json")
    46  	return rsp, nil
    47  }
    48  
    49  // TestExecuteRequest tests that the request executor can handle a slow response.
    50  // In particular, we want to make sure that the context is properly passed through
    51  // and not canceled too early.
    52  func TestExecuteRequest(t *testing.T) {
    53  	cfg := []okta.ConfigSetter{
    54  		okta.WithOrgUrl("https://fakeurl"),                               // This is ignored, but required for validator.
    55  		okta.WithToken("foo"),                                            // ditto.
    56  		okta.WithHttpClientPtr(&http.Client{Transport: slowTransport{}}), // Use our more realistic transport.
    57  		okta.WithRequestTimeout(10),                                      // The context issues are gated with actually having a timeout.
    58  	}
    59  	ctx, cl, err := tests.NewClient(context.Background(), cfg...)
    60  	assert.NoError(t, err, "Basic client errors")
    61  	req, err := http.NewRequest("GET", "https://fakeurl", http.NoBody)
    62  	assert.NoError(t, err, "Request building")
    63  	var out int
    64  	rs, err := cl.GetRequestExecutor().Do(ctx, req, &out)
    65  	assert.NoError(t, err, "Request execution")
    66  	if rs.StatusCode != 200 || out != 42 {
    67  		t.Errorf("Got val=%d status=%d, want 42 status=200", out, rs.StatusCode)
    68  	}
    69  }
    70  

View as plain text