Skip to content

Commit 2b7a28b

Browse files
committed
Implement tests and usages
1 parent e947f1a commit 2b7a28b

File tree

3 files changed

+486
-0
lines changed

3 files changed

+486
-0
lines changed

cmd/main.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package main
2+
3+
import (
4+
"github.com/pkg/errors"
5+
"go-restclient/restclient"
6+
"log"
7+
"net/http"
8+
"net/url"
9+
"time"
10+
)
11+
12+
type dummyHttpResponse struct {
13+
StatusCode int `json:"status_code"`
14+
Data interface{} `json:"data"`
15+
}
16+
17+
type dummyBasicAuthenticator struct {
18+
Username, Password string
19+
}
20+
21+
func NewTestBasicAuthenticator(username, password string) restclient.Authenticator {
22+
return &dummyBasicAuthenticator{
23+
Username: username,
24+
Password: password,
25+
}
26+
}
27+
28+
func (b dummyBasicAuthenticator) Apply(request *http.Request) error {
29+
request.SetBasicAuth(b.Username, b.Password)
30+
return nil
31+
}
32+
33+
func usage1() error {
34+
var response dummyHttpResponse
35+
headers := http.Header{"Content-Type": []string{"application/json"}, "Cookie": []string{"test-1234"}}
36+
queryParams := url.Values{"tenantId": []string{"d90c3101-53bc-4c54-94db-21582bab8e17"}, "vectorId": []string{"1"}}
37+
ri := restclient.NewRequestInfo("https", "ysyesilyurt.com", []string{"tasks", "1"}, &queryParams, &headers, nil)
38+
req, err := restclient.NewRequest(ri)
39+
if err != nil {
40+
return errors.Wrap(err, "Failed to construct http.Request out of RequestInfo")
41+
}
42+
43+
client := restclient.NewHttpClient(true, 30*time.Second)
44+
cri := restclient.NewDoRequestInfo(req, nil, &response)
45+
err = client.Get(cri)
46+
if err != nil {
47+
return errors.Wrap(err, "Failed to do HTTP GET request")
48+
}
49+
return nil
50+
}
51+
52+
func usage2() error {
53+
var response dummyHttpResponse
54+
headers := http.Header{"Content-Type": []string{"application/json"}, "Cookie": []string{"test-1234"}}
55+
ri, err := restclient.NewRequestInfoFromRawURL("https://ysyesilyurt.com/tasks/1?tenantId=d90c3101-53bc-4c54-94db-21582bab8e17&vectorId=1", &headers, nil)
56+
if err != nil {
57+
return errors.Wrap(err, "Failed to construct RequestInfo out of Raw URL")
58+
}
59+
60+
req, err := restclient.NewRequest(ri)
61+
if err != nil {
62+
return errors.Wrap(err, "Failed to construct http.Request out of RequestInfo")
63+
}
64+
65+
client := restclient.NewHttpClient(true, 0)
66+
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
67+
cri := restclient.NewDoRequestInfoWithTimeout(req, auth, &response, 15*time.Second)
68+
err = client.Get(cri)
69+
if err != nil {
70+
return errors.Wrap(err, "Failed to do HTTP GET request")
71+
}
72+
return nil
73+
}
74+
75+
func usage3() error {
76+
var response dummyHttpResponse
77+
headers := http.Header{"Content-Type": []string{"application/json"}, "Cookie": []string{"test-1234"}}
78+
ri, err := restclient.NewRequestInfoFromRawURL("https://ysyesilyurt.com/tasks/1?tenantId=d90c3101-53bc-4c54-94db-21582bab8e17&vectorId=1", &headers, nil)
79+
if err != nil {
80+
return errors.Wrap(err, "Failed to construct RequestInfo out of Raw URL")
81+
}
82+
83+
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
84+
err = restclient.PerformGetRequest(ri, auth, &response, true, 30*time.Second)
85+
if err != nil {
86+
return errors.Wrap(err, "Failed to perform HTTP GET request")
87+
}
88+
return nil
89+
}
90+
91+
func main() {
92+
// Below usages will fail with `no such host` when run
93+
err := usage1()
94+
if err != nil {
95+
log.Printf("Example usage1 failed, reason: %v", err)
96+
}
97+
err = usage2()
98+
if err != nil {
99+
log.Printf("Example usage2 failed, reason: %v", err)
100+
}
101+
err = usage3()
102+
if err != nil {
103+
log.Printf("Example usage3 failed, reason: %v", err)
104+
}
105+
}

restclient/client_test.go

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
package restclient
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
. "github.com/smartystreets/goconvey/convey"
7+
"log"
8+
"net/http"
9+
"net/http/httptest"
10+
"strings"
11+
"testing"
12+
"time"
13+
)
14+
15+
const (
16+
TestDataFormat = "%s - %s"
17+
TestSuccess = "TestSuccess"
18+
TestFailed = "TestFailed"
19+
)
20+
21+
type testBasicAuthenticator struct {
22+
Username, Password string
23+
}
24+
25+
func NewTestBasicAuthenticator(username, password string) Authenticator {
26+
return &testBasicAuthenticator{
27+
Username: username,
28+
Password: password,
29+
}
30+
}
31+
32+
func (b testBasicAuthenticator) Apply(request *http.Request) error {
33+
request.SetBasicAuth(b.Username, b.Password)
34+
return nil
35+
}
36+
37+
type testRequestBody struct {
38+
TestId int `json:"test_id"`
39+
TestName string `json:"test_name"`
40+
}
41+
42+
type testHttpResponse struct {
43+
StatusCode int `json:"status_code"`
44+
Data interface{} `json:"data"`
45+
}
46+
47+
func TestHttpClientRequests(t *testing.T) {
48+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
49+
var response testHttpResponse
50+
w.Header().Set("Content-Type", "application/json")
51+
52+
handleRequest := func(reqMethod string, statusCode int, resultString string) {
53+
username, password, ok := r.BasicAuth()
54+
if !ok || username != "ysyesilyurt" || password != "0123" {
55+
statusCode = http.StatusUnauthorized
56+
resultString = TestFailed
57+
}
58+
response.StatusCode = statusCode
59+
response.Data = fmt.Sprintf(TestDataFormat, resultString, reqMethod)
60+
w.WriteHeader(statusCode)
61+
}
62+
63+
handleRequestWithBody := func(reqMethod string) {
64+
status := http.StatusOK
65+
resultString := TestSuccess
66+
var body testRequestBody
67+
err := UnmarshalRequestBody(r, &body)
68+
if err != nil || body.TestName != "Testing Request Body" || body.TestId != 123 {
69+
status = http.StatusBadRequest
70+
resultString = TestFailed
71+
}
72+
handleRequest(reqMethod, status, resultString)
73+
}
74+
75+
switch r.Method {
76+
case http.MethodGet:
77+
handleRequest(http.MethodGet, http.StatusOK, TestSuccess)
78+
case http.MethodPost:
79+
handleRequestWithBody(http.MethodPost)
80+
case http.MethodPut:
81+
handleRequestWithBody(http.MethodPut)
82+
case http.MethodPatch:
83+
handleRequestWithBody(http.MethodPatch)
84+
case http.MethodDelete:
85+
handleRequest(http.MethodDelete, http.StatusOK, TestSuccess)
86+
default:
87+
response.StatusCode = http.StatusForbidden
88+
response.Data = fmt.Sprintf(TestDataFormat, TestFailed, r.Method)
89+
}
90+
err := json.NewEncoder(w).Encode(response)
91+
if err != nil {
92+
log.Fatalf("httptest server failed to respond with testHttpResponse %v", err.Error())
93+
}
94+
}))
95+
defer ts.Close()
96+
// e.g. ts URL: http://127.0.0.1:63316
97+
splittedURL := strings.Split(ts.URL, "://")
98+
testServerScheme := splittedURL[0]
99+
testServerHost := splittedURL[1]
100+
101+
Convey("TEST HTTP GET", t, func() {
102+
var testResponse testHttpResponse
103+
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, nil)
104+
testRequest, err := NewRequest(testRequestInfo)
105+
if err != nil {
106+
log.Fatal("failed to construct testRequest")
107+
}
108+
client := NewHttpClient(true, 30*time.Second)
109+
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
110+
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
111+
err = client.Get(cri)
112+
Convey("Response should be fetched without any err and with proper Data", func() {
113+
data, ok := testResponse.Data.(string)
114+
So(err, ShouldBeNil)
115+
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
116+
So(ok, ShouldBeTrue)
117+
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodGet))
118+
})
119+
})
120+
121+
Convey("TEST HTTP GET with failing authentication credentials", t, func() {
122+
var testResponse testHttpResponse
123+
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, nil)
124+
testRequest, err := NewRequest(testRequestInfo)
125+
if err != nil {
126+
log.Fatal("failed to construct testRequest")
127+
}
128+
client := NewHttpClient(true, 30*time.Second)
129+
auth := NewTestBasicAuthenticator("FAILING", "CREDENTIALS")
130+
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
131+
err = client.Get(cri)
132+
Convey("Response should be fetched without any err and with proper Data", func() {
133+
_, ok := testResponse.Data.(string)
134+
So(ok, ShouldBeFalse)
135+
So(testResponse.StatusCode, ShouldEqual, 0)
136+
So(err, ShouldNotBeNil)
137+
So(err.Error(), ShouldEqual, fmt.Sprintf("{\"status_code\":%d,\"data\":\"%s\"}\n: %s", http.StatusUnauthorized, fmt.Sprintf(TestDataFormat, TestFailed, http.MethodGet), unauthorizedErr))
138+
})
139+
})
140+
141+
Convey("TEST HTTP POST with correct body", t, func() {
142+
var testResponse testHttpResponse
143+
testBody := testRequestBody{
144+
TestId: 123,
145+
TestName: "Testing Request Body",
146+
}
147+
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, testBody)
148+
testRequest, err := NewRequest(testRequestInfo)
149+
if err != nil {
150+
log.Fatal("failed to construct testRequest")
151+
}
152+
client := NewHttpClient(true, 30*time.Second)
153+
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
154+
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
155+
err = client.Post(cri)
156+
Convey("Response should be fetched without any err and with proper Data", func() {
157+
data, ok := testResponse.Data.(string)
158+
So(err, ShouldBeNil)
159+
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
160+
So(ok, ShouldBeTrue)
161+
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodPost))
162+
})
163+
})
164+
165+
Convey("TEST HTTP POST with incorrect body", t, func() {
166+
var testResponse testHttpResponse
167+
testBody := "INCORRECT REQUEST BODY"
168+
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, testBody)
169+
testRequest, err := NewRequest(testRequestInfo)
170+
if err != nil {
171+
log.Fatal("failed to construct testRequest")
172+
}
173+
client := NewHttpClient(true, 30*time.Second)
174+
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
175+
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
176+
err = client.Post(cri)
177+
Convey("Response should be fetched without any err and with proper Data", func() {
178+
_, ok := testResponse.Data.(string)
179+
So(ok, ShouldBeFalse)
180+
So(testResponse.StatusCode, ShouldEqual, 0)
181+
So(err, ShouldNotBeNil)
182+
So(err.Error(), ShouldEqual, fmt.Sprintf("{\"status_code\":%d,\"data\":\"%s\"}\n: %s", http.StatusBadRequest, fmt.Sprintf(TestDataFormat, TestFailed, http.MethodPost), badRequestErr))
183+
})
184+
})
185+
186+
Convey("TEST HTTP PUT with correct body", t, func() {
187+
var testResponse testHttpResponse
188+
testBody := testRequestBody{
189+
TestId: 123,
190+
TestName: "Testing Request Body",
191+
}
192+
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, testBody)
193+
testRequest, err := NewRequest(testRequestInfo)
194+
if err != nil {
195+
log.Fatal("failed to construct testRequest")
196+
}
197+
client := NewHttpClient(true, 30*time.Second)
198+
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
199+
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
200+
err = client.Put(cri)
201+
Convey("Response should be fetched without any err and with proper Data", func() {
202+
data, ok := testResponse.Data.(string)
203+
So(err, ShouldBeNil)
204+
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
205+
So(ok, ShouldBeTrue)
206+
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodPut))
207+
})
208+
})
209+
210+
Convey("TEST HTTP PATCH with correct body", t, func() {
211+
var testResponse testHttpResponse
212+
testBody := testRequestBody{
213+
TestId: 123,
214+
TestName: "Testing Request Body",
215+
}
216+
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, testBody)
217+
testRequest, err := NewRequest(testRequestInfo)
218+
if err != nil {
219+
log.Fatal("failed to construct testRequest")
220+
}
221+
client := NewHttpClient(true, 30*time.Second)
222+
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
223+
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
224+
err = client.Patch(cri)
225+
Convey("Response should be fetched without any err and with proper Data", func() {
226+
data, ok := testResponse.Data.(string)
227+
So(err, ShouldBeNil)
228+
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
229+
So(ok, ShouldBeTrue)
230+
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodPatch))
231+
})
232+
})
233+
234+
Convey("TEST HTTP DELETE", t, func() {
235+
var testResponse testHttpResponse
236+
testRequestInfo := NewRequestInfo(testServerScheme, testServerHost, nil, nil, nil, nil)
237+
testRequest, err := NewRequest(testRequestInfo)
238+
if err != nil {
239+
log.Fatal("failed to construct testRequest")
240+
}
241+
client := NewHttpClient(true, 30*time.Second)
242+
auth := NewTestBasicAuthenticator("ysyesilyurt", "0123")
243+
cri := NewDoRequestInfo(testRequest, auth, &testResponse)
244+
err = client.Delete(cri)
245+
Convey("Response should be fetched without any err and with proper Data", func() {
246+
data, ok := testResponse.Data.(string)
247+
So(err, ShouldBeNil)
248+
So(testResponse.StatusCode, ShouldEqual, http.StatusOK)
249+
So(ok, ShouldBeTrue)
250+
So(data, ShouldEqual, fmt.Sprintf(TestDataFormat, TestSuccess, http.MethodDelete))
251+
})
252+
})
253+
}

0 commit comments

Comments
 (0)