github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/session/request_test.go (about)

     1  package session
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"errors"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"net/url"
    10  	"testing"
    11  
    12  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegrid"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  type testStruct struct {
    18  	A string `json:"a"`
    19  	B int    `json:"b"`
    20  }
    21  
    22  type testInvalid struct {
    23  	Invalid func()
    24  }
    25  
    26  func TestSession_Exec(t *testing.T) {
    27  	tests := map[string]struct {
    28  		request             *http.Request
    29  		out                 testStruct
    30  		in                  []interface{}
    31  		responseBody        string
    32  		responseStatus      int
    33  		expectedContentType string
    34  		expectedAccept      string
    35  		expectedUserAgent   string
    36  		expectedMethod      string
    37  		expectedPath        string
    38  		expected            interface{}
    39  		withError           error
    40  	}{
    41  		"GET request, use default values for request": {
    42  			request: func() *http.Request {
    43  				req, err := http.NewRequest(http.MethodGet, "/test/path", nil)
    44  				require.NoError(t, err)
    45  				return req
    46  			}(),
    47  			out:            testStruct{},
    48  			responseBody:   `{"a":"text","b":1}`,
    49  			responseStatus: http.StatusOK,
    50  			expectedMethod: http.MethodGet,
    51  			expectedPath:   "/test/path",
    52  			expected: testStruct{
    53  				A: "text",
    54  				B: 1,
    55  			},
    56  		},
    57  		"GET request, escape query": {
    58  			request: func() *http.Request {
    59  				req, err := http.NewRequest(http.MethodGet, "/test/path?param1=some param", nil)
    60  				require.NoError(t, err)
    61  				return req
    62  			}(),
    63  			out:            testStruct{},
    64  			responseBody:   `{"a":"text","b":1}`,
    65  			responseStatus: http.StatusOK,
    66  			expectedMethod: http.MethodGet,
    67  			expectedPath:   "/test/path?param1=some+param",
    68  			expected: testStruct{
    69  				A: "text",
    70  				B: 1,
    71  			},
    72  		},
    73  		"GET request, custom content type, accept and user agent": {
    74  			request: func() *http.Request {
    75  				req, err := http.NewRequest(http.MethodGet, "/test/path", nil)
    76  				require.NoError(t, err)
    77  				req.Header.Set("Content-Type", "text/plain")
    78  				req.Header.Set("User-Agent", "other user agent")
    79  				req.Header.Set("Accept", "text/html")
    80  				return req
    81  			}(),
    82  			out:                 testStruct{},
    83  			responseBody:        `{"a":"text","b":1}`,
    84  			responseStatus:      http.StatusOK,
    85  			expectedMethod:      http.MethodGet,
    86  			expectedPath:        "/test/path",
    87  			expectedContentType: "text/plain",
    88  			expectedAccept:      "text/html",
    89  			expectedUserAgent:   "other user agent",
    90  			expected: testStruct{
    91  				A: "text",
    92  				B: 1,
    93  			},
    94  		},
    95  		"POST request, custom content type, accept and user agent": {
    96  			request: func() *http.Request {
    97  				req, err := http.NewRequest(http.MethodPost, "/test/path", nil)
    98  				require.NoError(t, err)
    99  				req.Header.Set("Content-Type", "text/plain")
   100  				req.Header.Set("User-Agent", "other user agent")
   101  				req.Header.Set("Accept", "text/html")
   102  				return req
   103  			}(),
   104  			in: []interface{}{&testStruct{
   105  				A: "text",
   106  				B: 1,
   107  			}},
   108  			out:                 testStruct{},
   109  			responseBody:        `{"a":"text","b":1}`,
   110  			responseStatus:      http.StatusCreated,
   111  			expectedMethod:      http.MethodPost,
   112  			expectedPath:        "/test/path",
   113  			expectedContentType: "text/plain",
   114  			expectedUserAgent:   "other user agent",
   115  			expectedAccept:      "text/html",
   116  			expected: testStruct{
   117  				A: "text",
   118  				B: 1,
   119  			},
   120  		},
   121  		"POST request, invalid body": {
   122  			request: func() *http.Request {
   123  				req, err := http.NewRequest(http.MethodPost, "/test/path", nil)
   124  				require.NoError(t, err)
   125  				req.Header.Set("Content-Type", "text/plain")
   126  				req.Header.Set("User-Agent", "other user agent")
   127  				return req
   128  			}(),
   129  			in:        []interface{}{&testInvalid{func() {}}},
   130  			out:       testStruct{},
   131  			withError: ErrMarshaling,
   132  		},
   133  		"POST request, unmarshaling error": {
   134  			request: func() *http.Request {
   135  				req, err := http.NewRequest(http.MethodPost, "/test/path", nil)
   136  				require.NoError(t, err)
   137  				req.Header.Set("Content-Type", "text/plain")
   138  				req.Header.Set("User-Agent", "other user agent")
   139  				return req
   140  			}(),
   141  			in: []interface{}{&testStruct{
   142  				A: "text",
   143  				B: 1,
   144  			}},
   145  			out:                 testStruct{},
   146  			responseBody:        `{"a":1,"b":1}`,
   147  			responseStatus:      http.StatusCreated,
   148  			expectedMethod:      http.MethodPost,
   149  			expectedPath:        "/test/path",
   150  			expectedContentType: "text/plain",
   151  			expectedUserAgent:   "other user agent",
   152  			withError:           ErrUnmarshaling,
   153  		},
   154  		"invalid number of input parameters": {
   155  			in:        []interface{}{testStruct{}, testStruct{}},
   156  			withError: ErrInvalidArgument,
   157  		},
   158  	}
   159  
   160  	for name, test := range tests {
   161  		t.Run(name, func(t *testing.T) {
   162  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   163  				assert.Equal(t, test.expectedPath, r.URL.String())
   164  				assert.Equal(t, test.expectedMethod, r.Method)
   165  				if test.expectedContentType == "" {
   166  					assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
   167  				} else {
   168  					assert.Equal(t, test.expectedContentType, r.Header.Get("Content-Type"))
   169  				}
   170  				if test.expectedUserAgent == "" {
   171  					assert.Equal(t, "test user agent", r.Header.Get("User-Agent"))
   172  				} else {
   173  					assert.Equal(t, test.expectedUserAgent, r.Header.Get("User-Agent"))
   174  				}
   175  				if test.expectedAccept == "" {
   176  					assert.Equal(t, "application/json", r.Header.Get("Accept"))
   177  				} else {
   178  					assert.Equal(t, test.expectedAccept, r.Header.Get("Accept"))
   179  				}
   180  				w.WriteHeader(test.responseStatus)
   181  				_, err := w.Write([]byte(test.responseBody))
   182  				assert.NoError(t, err)
   183  			}))
   184  
   185  			certPool := x509.NewCertPool()
   186  			certPool.AddCert(mockServer.Certificate())
   187  			httpClient := &http.Client{
   188  				Transport: &http.Transport{
   189  					TLSClientConfig: &tls.Config{
   190  						RootCAs: certPool,
   191  					},
   192  				},
   193  			}
   194  			serverURL, err := url.Parse(mockServer.URL)
   195  			require.NoError(t, err)
   196  			s, err := New(WithSigner(&edgegrid.Config{
   197  				Host:         serverURL.Host,
   198  				RequestLimit: 10,
   199  			}), WithClient(httpClient), WithUserAgent("test user agent"), WithHTTPTracing(true))
   200  			require.NoError(t, err)
   201  
   202  			_, err = s.Exec(test.request, &test.out, test.in...)
   203  			if test.withError != nil {
   204  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   205  				return
   206  			}
   207  			require.NoError(t, err)
   208  			assert.Equal(t, test.expected, test.out)
   209  		})
   210  	}
   211  }