make tests fully table driven and increase coverage by a lot

This commit is contained in:
grumbulon 2023-03-10 22:37:25 -05:00
parent 176746cce0
commit e06e8c4e25

View file

@ -88,10 +88,9 @@ func TestAPI(t *testing.T) {
db.Create(&internal.User{Username: tester.username, HashedPassword: string(hashedPassword)})
tester.TestMakeAccount(t)
tester.TestLogin(t)
tester.TestLogout(t)
tester.TestUpload(t)
tester.TestOpenRoutes(t)
tester.TestProtectedRoutes(t)
tester.TestRateLimit(t)
tester.CleanUp(db)
}
@ -115,119 +114,203 @@ func Init(url string) accountTest {
return test
}
func (a *accountTest) TestMakeAccount(t *testing.T) {
var target response
client := http.Client{}
form := url.Values{}
form.Add("username", a.username)
form.Add("password", a.password)
if req, err := http.NewRequest(http.MethodPost, a.url+`api/create`, strings.NewReader(form.Encode())); err == nil {
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
assert.NotNil(t, err)
}
respBody, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(respBody, &target)
if err != nil {
assert.NotNil(t, err)
}
assert.Equal(t, http.StatusCreated, target.Status)
}
}
func (a *accountTest) TestLogin(t *testing.T) {
var target response
client := http.Client{}
form := url.Values{}
form.Add("username", a.username)
form.Add("password", a.password)
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/login`, strings.NewReader(form.Encode())); err == nil {
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
assert.NotNil(t, err)
}
respBody, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(respBody, &target)
if err != nil {
assert.NotNil(t, err)
}
assert.Equal(t, http.StatusOK, resp.StatusCode)
}
}
func (a *accountTest) TestLogout(t *testing.T) {
var target response
client := http.Client{}
form := url.Values{}
form.Add("username", a.username)
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/logout`, strings.NewReader(form.Encode())); err == nil {
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
assert.NotNil(t, err)
}
respBody, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(respBody, &target)
if err != nil {
assert.NotNil(t, err)
}
assert.Equal(t, http.StatusOK, resp.StatusCode)
}
}
type expectedValues struct {
response int
}
func (a *accountTest) TestUpload(t *testing.T) {
func (a *accountTest) TestOpenRoutes(t *testing.T) {
testCases := []struct {
name string
route string
token string
password string
username string
expected expectedValues
}{
{
name: "Should fail to login with bad username",
route: "login",
username: "a.username",
password: a.password,
expected: expectedValues{
response: http.StatusUnauthorized,
},
},
{
name: "Should fail to login with bad password",
route: "login",
username: a.username,
password: "a.password",
expected: expectedValues{
response: http.StatusUnauthorized,
},
},
{
name: "Should fail to login with bad password or username",
route: "login",
username: "apple",
password: "a.password",
expected: expectedValues{
response: http.StatusUnauthorized,
},
},
{
name: "Should fail to login with empty form",
route: "login",
expected: expectedValues{
response: http.StatusInternalServerError,
},
},
{
name: "Should login successfully",
route: "login",
username: a.username,
password: a.password,
expected: expectedValues{
response: http.StatusOK,
},
},
{
name: "Should fail to create account with empty form",
route: "create",
expected: expectedValues{
response: http.StatusInternalServerError,
},
},
{
name: "Should create account with empty username",
route: "create",
password: "asdf",
expected: expectedValues{
response: http.StatusCreated,
},
},
{
name: "Should fail to create account with empty password",
route: "create",
expected: expectedValues{
response: http.StatusInternalServerError,
},
},
{
name: "Should log out successfully",
route: "logout",
username: a.username,
expected: expectedValues{
response: http.StatusOK,
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var target response
client := http.Client{}
form := url.Values{}
form.Add("username", tc.username)
form.Add("password", tc.password)
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/`+tc.route, strings.NewReader(form.Encode())); err == nil {
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
assert.NotNil(t, err)
}
respBody, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(respBody, &target)
if err != nil {
assert.NotNil(t, err)
}
assert.Equal(t, tc.expected.response, resp.StatusCode)
}
})
}
}
func (a *accountTest) TestRateLimit(t *testing.T) {
testCases := []struct {
name string
route string
password string
username string
expected expectedValues
}{
{
name: "Should rate limit open routes",
route: "login",
expected: expectedValues{
response: http.StatusTooManyRequests,
},
},
{
name: "Should rate limit private routes",
route: "upload",
expected: expectedValues{
response: http.StatusTooManyRequests,
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var target response
client := http.Client{}
form := url.Values{}
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/`+tc.route, strings.NewReader(form.Encode())); err == nil {
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
for i := 0; i < 100; i++ {
resp, err := client.Do(req)
if err != nil {
assert.NotNil(t, err)
}
respBody, _ := io.ReadAll(resp.Body)
err = json.Unmarshal(respBody, &target)
if err != nil {
assert.NotNil(t, err)
}
if resp.StatusCode == tc.expected.response {
assert.Equal(t, tc.expected.response, resp.StatusCode)
}
}
}
})
}
}
func (a *accountTest) TestProtectedRoutes(t *testing.T) {
testCases := []struct {
name string
file string
contentType string
route string
fileContents []byte
expected expectedValues
}{
{
name: "Should fail to upload an empty file",
file: "badzonefile",
contentType: "audio/aac",
route: "upload",
expected: expectedValues{
response: http.StatusInternalServerError,
},
},
{
name: "Should upload a valid file",
file: "zonefile",
contentType: "multipart/form-data",
fileContents: []byte{},
route: "upload",
expected: expectedValues{
response: http.StatusCreated,
},
@ -244,18 +327,12 @@ func (a *accountTest) TestUpload(t *testing.T) {
w = multipart.NewWriter(buf)
)
switch tc.name {
case "Should fail to upload an empty file":
f, err = os.CreateTemp(".", tc.file)
if err != nil {
assert.NotNil(t, err)
}
default:
f, err = os.CreateTemp(".", "zonefile")
if err != nil {
assert.NotNil(t, err)
}
f, err = os.CreateTemp(".", "zonefile")
if err != nil {
assert.NotNil(t, err)
}
if tc.name == "Should upload a valid file" {
if err = os.WriteFile(f.Name(), zonebytes, 0o600); err != nil {
assert.NotNil(t, err)
}
@ -263,8 +340,6 @@ func (a *accountTest) TestUpload(t *testing.T) {
defer os.Remove(f.Name()) //nolint: errcheck
client := http.Client{}
part, err := w.CreateFormFile("file", filepath.Base(f.Name()))
if err != nil {
assert.NotNil(t, err)
@ -284,12 +359,11 @@ func (a *accountTest) TestUpload(t *testing.T) {
if err != nil {
assert.NotNil(t, err)
}
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/upload`, buf); err == nil {
switch tc.name {
case "Should fail to upload an empty file":
client := http.Client{}
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/`+tc.route, buf); err == nil {
if tc.name == "Should fail to upload an empty file" {
req.Header.Add("Content-Type", tc.contentType)
default:
} else {
req.Header.Add("Content-Type", w.FormDataContentType())
}
@ -306,7 +380,6 @@ func (a *accountTest) TestUpload(t *testing.T) {
if err != nil {
assert.NotNil(t, err)
}
assert.Equal(t, tc.expected.response, resp.StatusCode)
}
})