fedd668164bcbf7bab1c91ec09521f828e91f090
[nonrtric/rapp/orufhrecovery.git] / goversion / internal / restclient / client_test.go
1 // -
2 //   ========================LICENSE_START=================================
3 //   O-RAN-SC
4 //   %%
5 //   Copyright (C) 2021: Nordix Foundation
6 //   %%
7 //   Licensed under the Apache License, Version 2.0 (the "License");
8 //   you may not use this file except in compliance with the License.
9 //   You may obtain a copy of the License at
10 //        http://www.apache.org/licenses/LICENSE-2.0
11 //
12 //   Unless required by applicable law or agreed to in writing, software
13 //   distributed under the License is distributed on an "AS IS" BASIS,
14 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 //   See the License for the specific language governing permissions and
16 //   limitations under the License.
17 //   ========================LICENSE_END===================================
18 //
19
20 package restclient
21
22 import (
23         "bytes"
24         "crypto/tls"
25         "fmt"
26         "io/ioutil"
27         "math"
28         "net/http"
29         "reflect"
30         "testing"
31         "time"
32
33         "github.com/hashicorp/go-retryablehttp"
34         "github.com/stretchr/testify/mock"
35         "github.com/stretchr/testify/require"
36         "oransc.org/usecase/oruclosedloop/internal/restclient/mocks"
37 )
38
39 func TestRequestError_Error(t *testing.T) {
40         assertions := require.New(t)
41
42         actualError := RequestError{
43                 StatusCode: http.StatusBadRequest,
44                 Body:       []byte("error"),
45         }
46         assertions.Equal("error response with status: 400 and body: error", actualError.Error())
47 }
48
49 func TestPutWithoutAuth(t *testing.T) {
50         assertions := require.New(t)
51
52         clientMock := mocks.HTTPClient{}
53         clientMock.On("Do", mock.Anything).Return(&http.Response{
54                 StatusCode: http.StatusOK,
55         }, nil)
56
57         error := PutWithoutAuth("url", []byte("body"), &clientMock)
58
59         assertions.Nil(error)
60         var actualRequest *http.Request
61         clientMock.AssertCalled(t, "Do", mock.MatchedBy(func(req *http.Request) bool {
62                 actualRequest = req
63                 return true
64         }))
65         assertions.Equal(http.MethodPut, actualRequest.Method)
66         assertions.Equal("url", actualRequest.URL.Path)
67         assertions.Equal("application/json; charset=utf-8", actualRequest.Header.Get("Content-Type"))
68         assertions.Empty(actualRequest.Header.Get("Authorization"))
69         body, _ := ioutil.ReadAll(actualRequest.Body)
70         expectedBody := []byte("body")
71         assertions.Equal(expectedBody, body)
72         clientMock.AssertNumberOfCalls(t, "Do", 1)
73 }
74
75 func TestPut(t *testing.T) {
76         assertions := require.New(t)
77
78         clientMock := mocks.HTTPClient{}
79         clientMock.On("Do", mock.Anything).Return(&http.Response{
80                 StatusCode: http.StatusOK,
81         }, nil)
82
83         error := Put("url", "body", &clientMock, "admin", "pwd")
84
85         assertions.Nil(error)
86         var actualRequest *http.Request
87         clientMock.AssertCalled(t, "Do", mock.MatchedBy(func(req *http.Request) bool {
88                 actualRequest = req
89                 return true
90         }))
91         assertions.Equal(http.MethodPut, actualRequest.Method)
92         assertions.Equal("url", actualRequest.URL.Path)
93         assertions.Equal("application/json; charset=utf-8", actualRequest.Header.Get("Content-Type"))
94         tempRequest, _ := http.NewRequest("", "", nil)
95         tempRequest.SetBasicAuth("admin", "pwd")
96         assertions.Equal(tempRequest.Header.Get("Authorization"), actualRequest.Header.Get("Authorization"))
97         body, _ := ioutil.ReadAll(actualRequest.Body)
98         expectedBody := []byte("body")
99         assertions.Equal(expectedBody, body)
100         clientMock.AssertNumberOfCalls(t, "Do", 1)
101 }
102
103 func TestDelete(t *testing.T) {
104         assertions := require.New(t)
105
106         clientMock := mocks.HTTPClient{}
107         clientMock.On("Do", mock.Anything).Return(&http.Response{
108                 StatusCode: http.StatusOK,
109         }, nil)
110
111         error := Delete("url", &clientMock)
112
113         assertions.Nil(error)
114         var actualRequest *http.Request
115         clientMock.AssertCalled(t, "Do", mock.MatchedBy(func(req *http.Request) bool {
116                 actualRequest = req
117                 return true
118         }))
119         assertions.Equal(http.MethodDelete, actualRequest.Method)
120         assertions.Equal("url", actualRequest.URL.Path)
121         assertions.Empty(actualRequest.Header.Get("Content-Type"))
122         assertions.Empty(actualRequest.Header.Get("Authorization"))
123         assertions.Equal(http.NoBody, actualRequest.Body)
124         clientMock.AssertNumberOfCalls(t, "Do", 1)
125 }
126
127 func Test_doErrorCases(t *testing.T) {
128         assertions := require.New(t)
129
130         type args struct {
131                 url              string
132                 mockReturnStatus int
133                 mockReturnBody   []byte
134                 mockReturnError  error
135         }
136         tests := []struct {
137                 name    string
138                 args    args
139                 wantErr error
140         }{
141                 {
142                         name: "Bad request should get RequestError",
143                         args: args{
144                                 url:              "badRequest",
145                                 mockReturnStatus: http.StatusBadRequest,
146                                 mockReturnBody:   []byte("bad request"),
147                         },
148                         wantErr: RequestError{
149                                 StatusCode: http.StatusBadRequest,
150                                 Body:       []byte("bad request"),
151                         },
152                 },
153                 {
154                         name: "Server unavailable should get error",
155                         args: args{
156                                 url:             "serverUnavailable",
157                                 mockReturnError: fmt.Errorf("Server unavailable"),
158                         },
159                         wantErr: fmt.Errorf("Server unavailable"),
160                 },
161         }
162         for _, tt := range tests {
163                 t.Run(tt.name, func(t *testing.T) {
164                         clientMock := mocks.HTTPClient{}
165                         clientMock.On("Do", mock.Anything).Return(&http.Response{
166                                 StatusCode: tt.args.mockReturnStatus,
167                                 Body:       ioutil.NopCloser(bytes.NewReader(tt.args.mockReturnBody)),
168                         }, tt.args.mockReturnError)
169
170                         err := do("PUT", tt.args.url, nil, &clientMock)
171                         assertions.Equal(tt.wantErr, err, tt.name)
172                 })
173         }
174 }
175
176 func Test_createClientCertificate(t *testing.T) {
177         assertions := require.New(t)
178         wantedCert, _ := tls.LoadX509KeyPair("../../security/consumer.crt", "../../security/consumer.key")
179         type args struct {
180                 certPath string
181                 keyPath  string
182         }
183         tests := []struct {
184                 name     string
185                 args     args
186                 wantCert tls.Certificate
187                 wantErr  error
188         }{
189                 {
190                         name: "Paths to cert info ok should return cerftificate",
191                         args: args{
192                                 certPath: "../../security/consumer.crt",
193                                 keyPath:  "../../security/consumer.key",
194                         },
195                         wantCert: wantedCert,
196                 },
197                 {
198                         name: "Paths to cert info not ok should return error with info about error",
199                         args: args{
200                                 certPath: "wrong_cert",
201                                 keyPath:  "wrong_key",
202                         },
203                         wantErr: fmt.Errorf("cannot create x509 keypair from cert file wrong_cert and key file wrong_key due to: open wrong_cert: no such file or directory"),
204                 },
205         }
206         for _, tt := range tests {
207                 t.Run(tt.name, func(t *testing.T) {
208                         cert, err := CreateClientCertificate(tt.args.certPath, tt.args.keyPath)
209                         assertions.Equal(tt.wantCert, cert, tt.name)
210                         assertions.Equal(tt.wantErr, err, tt.name)
211                 })
212         }
213 }
214
215 func Test_CreateRetryClient(t *testing.T) {
216         assertions := require.New(t)
217
218         client := CreateRetryClient(tls.Certificate{})
219
220         transport := client.Transport
221         assertions.Equal("*retryablehttp.RoundTripper", reflect.TypeOf(transport).String())
222         retryableTransport := transport.(*retryablehttp.RoundTripper)
223         retryableClient := retryableTransport.Client
224         assertions.Equal(time.Minute, retryableClient.RetryWaitMax)
225         assertions.Equal(math.MaxInt, retryableClient.RetryMax)
226 }
227
228 func TestIsUrlSecured(t *testing.T) {
229         assertions := require.New(t)
230
231         assertions.True(IsUrlSecure("https://url"))
232
233         assertions.False(IsUrlSecure("http://url"))
234 }