Skip to content

Commit

Permalink
#81 Add submit crawler test
Browse files Browse the repository at this point in the history
  • Loading branch information
meian committed Aug 7, 2024
1 parent a2fb5e9 commit 25784a7
Show file tree
Hide file tree
Showing 7 changed files with 2,601 additions and 9 deletions.
33 changes: 26 additions & 7 deletions crawler/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,29 @@ func mockRequestClient() (*http.Client, captureFunc) {
}

type mockHTTPResponse struct {
status int
bodyFile string
timeout bool
lastRequestURL string
status int
bodyFile string
timeout bool
}

func (m *mockHTTPResponse) NewClient(t *testing.T, hm htmlMap) *http.Client {
t.Helper()
rt := &mockResponseRoundTripper{status: m.status, body: hm.Get(m.bodyFile), timeout: m.timeout}
if m.lastRequestURL != "" {
req, err := http.NewRequest(http.MethodGet, m.lastRequestURL, nil)
require.NoError(t, err)
require.NotNil(t, req)
rt.lastRequest = req
}
return &http.Client{Transport: rt}
}

type mockResponseRoundTripper struct {
status int
body string
timeout bool
lastRequest *http.Request
status int
body string
timeout bool
}

func (m *mockResponseRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
Expand All @@ -114,13 +128,18 @@ func (m *mockResponseRoundTripper) RoundTrip(req *http.Request) (*http.Response,
} else {
wait = time.After(0 * time.Second)
}
ctx := req.Context()
if m.lastRequest != nil {
req = m.lastRequest
}
select {
case <-wait:
return &http.Response{
Request: req,
StatusCode: m.status,
Body: io.NopCloser(strings.NewReader(m.body)),
}, nil
case <-req.Context().Done():
case <-ctx.Done():
return nil, errors.New("request canceled for timeout")
}
}
Expand Down
9 changes: 8 additions & 1 deletion crawler/submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ func NewSubmit(client *http.Client) *Submit {
return &Submit{crawler: NewCrawler(url.SubmitPath).WithClient(client)}
}

func (c *Submit) Do(ctx context.Context, req *requests.Submit) (*responses.Submit, error) {
func (c *Submit) Do(ctx context.Context, req requests.Submit) (*responses.Submit, error) {
if err := req.Validate(); err != nil {
return nil, err
}
logger := logs.FromContext(ctx)
crawler := c.crawler.WithPathParam("contestID", req.ContestID)
resp, err := crawler.Post(ctx, nil, req)
Expand All @@ -29,6 +32,10 @@ func (c *Submit) Do(ctx context.Context, req *requests.Submit) (*responses.Submi
return nil, errors.New("failed to post document")
}
defer resp.Body.Close()
if err := c.crawler.validHTML(ctx, resp.Body); err != nil {
logger.Error(err.Error())
return nil, errors.New("response is not a valid HTML")
}
if resp.StatusCode != http.StatusOK {
logger.With("statusCode", resp.StatusCode).Error("unexpected status code")
return nil, errors.New("unexpected status code for submit")
Expand Down
157 changes: 157 additions & 0 deletions crawler/submit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package crawler_test

import (
"context"
"net/http"
gourl "net/url"
"testing"
"time"

"github.com/meian/atgo/constant"
"github.com/meian/atgo/crawler"
"github.com/meian/atgo/crawler/requests"
"github.com/meian/atgo/crawler/responses"
"github.com/meian/atgo/url"
"github.com/stretchr/testify/assert"
)

func TestSubmit_Do_Request(t *testing.T) {
tests := []struct {
name string
req requests.Submit
want requestWant
}{
{
name: "success",
req: requests.Submit{
ContestID: "abc123",
TaskID: "abc123_c",
CSRFToken: "token",
LanguageID: constant.LanguageGo_1_20_6,
SourceCode: "package main\n\nsome code...",
},
want: requestWant{
path: "/contests/abc123/submit",
query: gourl.Values{},
body: gourl.Values{
"csrf_token": []string{"token"},
"data.LanguageId": []string{constant.LanguageGo_1_20_6.StringValue()},
"data.TaskScreenName": []string{"abc123_c"},
"sourceCode": []string{"package main\n\nsome code..."},
},
called: true,
},
},
{
name: "request is invalid",
req: requests.Submit{
ContestID: "abc123",
},
want: requestWant{called: false},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
client, cFunc := mockRequestClient()
_, _ = crawler.NewSubmit(client).Do(context.Background(), tt.req)
method, path, query, body, called := cFunc()
if !tt.want.called {
assert.False(called)
return
}
assert.Equal(http.MethodPost, method)
assert.Equal(tt.want.path, path)
assert.Equal(tt.want.query, query)
assert.Equal(tt.want.body, body)
assert.True(called)
})
}
}

func TestSubmit_Do_Response(t *testing.T) {
m := testHTMLMap(t, "submit")

type want struct {
err bool
res *responses.Submit
}
tests := []struct {
name string
httpRes mockHTTPResponse
want want
}{
{
name: "success",
httpRes: mockHTTPResponse{
lastRequestURL: url.MySubmissionURL("abc123"),
status: http.StatusOK,
bodyFile: "success.html",
},
want: want{
res: &responses.Submit{
Submitted: true,
},
},
},
{
name: "invalid parameters",
httpRes: mockHTTPResponse{
lastRequestURL: url.SubmitURL("abc123"),
status: http.StatusOK,
bodyFile: "invalid-parameters.html",
},
want: want{err: true},
},
{
name: "not found",
httpRes: mockHTTPResponse{
lastRequestURL: url.SubmitURL("abc123"),
status: http.StatusNotFound,
},
want: want{err: true},
},
{
name: "not a html response",
httpRes: mockHTTPResponse{
lastRequestURL: url.SubmitURL("abc123"),
status: http.StatusOK,
bodyFile: "not-a-html",
},
want: want{err: true},
},
{
name: "timeout",
httpRes: mockHTTPResponse{timeout: true},
want: want{err: true},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
client := tt.httpRes.NewClient(t, m)
req := requests.Submit{
ContestID: "abc123",
TaskID: "abc123_c",
CSRFToken: "token",
LanguageID: constant.LanguageGo_1_20_6,
SourceCode: "package main\n\nsome code...",
}
res, err := crawler.NewSubmit(client).Do(ctx, req)
if tt.want.err {
if assert.Error(err) {
t.Logf("error: %v", err)
}
return
}
assert.NoError(err)
if !assert.NotNil(res) {
return
}
assert.Equal(tt.want.res, res)
})
}
}
Loading

0 comments on commit 25784a7

Please sign in to comment.