core/tests/main_test.go

885 lines
28 KiB
Go
Raw Normal View History

package tests
import (
"bytes"
"encoding/json"
"gitea.pena/SQuiz/common/model"
"github.com/stretchr/testify/assert"
"net/http"
"os"
"sync"
"testing"
"time"
)
var baseURL = os.Getenv("API_BASE_URL")
var validToken = os.Getenv("VALID_JWT_TOKEN")
var expiredToken = os.Getenv("EXPIRED_JWT_TOKEN")
2025-05-26 12:09:48 +00:00
var validTokenForDelete = os.Getenv("VALID_JWT_TOKEN_FOR_DELETE")
2025-05-26 13:46:21 +00:00
var validAdminToken = os.Getenv("VALID_ADMIN_JWT_TOKEN")
var existingUserIDToken = os.Getenv("EXISTING_USER_ID_JWT_TOKEN")
var userIDForDelete = os.Getenv("USER_ID_FOR_DELETE")
var existingUserID = os.Getenv("EXISTING_USER_ID")
var testUserID = os.Getenv("TEST_USER_ID")
var sqlInjectionInput = "'; DROP TABLE accounts; --"
var xssInput = "<script>alert('xss')</script>"
func TestGetAccount_Success(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/account/get", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", resp.Header.Get("Content-Type"))
var acc model.Account
2025-05-26 12:09:48 +00:00
err = json.NewDecoder(resp.Body).Decode(&acc)
assert.NoError(t, err)
assert.NotEmpty(t, acc.ID)
assert.NotEmpty(t, acc.UserID)
assert.IsType(t, map[string]interface{}{}, acc.Privileges)
}
func TestGetAccount_Auth(t *testing.T) {
t.Run("AccountNoToken", func(t *testing.T) {
resp, err := http.Get(baseURL + "/account/get")
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("AccountInvalidToken", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/account/get", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer invalid_token")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("AccountExpiredToken", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/account/get", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+expiredToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
}
func TestGetAccount_NotFound(t *testing.T) {
t.Run("DeletedAccount", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/account/get", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+os.Getenv("DELETED_ACCOUNT_TOKEN"))
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
})
}
func TestGetAccount_Privileges(t *testing.T) {
t.Run("NoPrivileges", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/account/get", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+os.Getenv("NO_PRIVILEGES_TOKEN"))
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var acc model.Account
err = json.NewDecoder(resp.Body).Decode(&acc)
assert.NoError(t, err)
assert.Empty(t, acc.Privileges)
})
t.Run("MultiplePrivileges", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/account/get", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+os.Getenv("MULTI_PRIVILEGES_TOKEN"))
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var acc model.Account
err = json.NewDecoder(resp.Body).Decode(&acc)
assert.NoError(t, err)
assert.Greater(t, len(acc.Privileges), 1)
})
}
func TestAccount_Performance(t *testing.T) {
t.Run("AccountResponseTime", func(t *testing.T) {
start := time.Now()
req, err := http.NewRequest("GET", baseURL+"/account/get", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
duration := time.Since(start)
assert.Less(t, duration.Milliseconds(), int64(500))
})
t.Run("AccountLoadTest", func(t *testing.T) {
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
req, err := http.NewRequest("GET", baseURL+"/account/get", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
resp, err := http.DefaultClient.Do(req)
if err == nil {
defer resp.Body.Close()
}
}()
}
wg.Wait()
})
}
// todo 1.3.6 1.3.7 1.3.8. 1.4 пока не знаю как делать надо подумать
func TestCreateAccount(t *testing.T) {
t.Run("Success", func(t *testing.T) {
resp := createAccountRequest(t, validToken, map[string]interface{}{
"user_id": testUserID,
})
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", resp.Header.Get("Content-Type"))
})
t.Run("MissingToken", func(t *testing.T) {
req, err := http.NewRequest("POST", baseURL+"/account/create", nil)
assert.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("InvalidToken", func(t *testing.T) {
resp := createAccountRequest(t, expiredToken, map[string]interface{}{
"user_id": "some-id",
})
defer resp.Body.Close()
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("ExpiredToken", func(t *testing.T) {
resp := createAccountRequest(t, expiredToken, map[string]interface{}{
"user_id": "some-id",
})
defer resp.Body.Close()
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("Conflict_ExistingUserID", func(t *testing.T) {
resp := createAccountRequest(t, validToken, map[string]interface{}{
"user_id": existingUserID,
})
defer resp.Body.Close()
assert.Equal(t, http.StatusConflict, resp.StatusCode)
})
t.Run("EmptyJSON", func(t *testing.T) {
resp := createAccountRequest(t, validToken, map[string]interface{}{})
defer resp.Body.Close()
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("InvalidFormat", func(t *testing.T) {
resp := createAccountRequest(t, validToken, map[string]interface{}{
"user_id": 123,
})
defer resp.Body.Close()
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("SQLInjection", func(t *testing.T) {
resp := createAccountRequest(t, validToken, map[string]interface{}{
"user_id": sqlInjectionInput,
})
defer resp.Body.Close()
assert.NotEqual(t, http.StatusInternalServerError, resp.StatusCode)
})
t.Run("XSSInjection", func(t *testing.T) {
resp := createAccountRequest(t, validToken, map[string]interface{}{
"user_id": xssInput,
})
defer resp.Body.Close()
assert.NotEqual(t, http.StatusInternalServerError, resp.StatusCode)
})
// todo 2.3.6 2.3.7 2.3.8 2.4
}
func createAccountRequest(t *testing.T, token string, payload map[string]interface{}) *http.Response {
body, err := json.Marshal(payload)
assert.NoError(t, err)
req, err := http.NewRequest("POST", baseURL+"/account/create", bytes.NewBuffer(body))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
return resp
}
2025-05-26 12:09:48 +00:00
func TestDeleteAccount_Success(t *testing.T) {
req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validTokenForDelete)
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", resp.Header.Get("Content-Type"))
var result map[string]string
err = json.NewDecoder(resp.Body).Decode(&result)
assert.NoError(t, err)
assert.NotEmpty(t, result["accountId"])
}
func TestDeleteAccount_Auth(t *testing.T) {
t.Run("NoToken", func(t *testing.T) {
req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil)
assert.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("InvalidToken", func(t *testing.T) {
req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer invalid_token")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("ExpiredToken", func(t *testing.T) {
req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+expiredToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
}
func TestDeleteAccount_AlreadyDeleted(t *testing.T) {
req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validTokenForDelete)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
}
func TestDeleteAccount_NonExistent(t *testing.T) {
req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validTokenForDelete)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
}
// todo 3.3.4 3.3.5
func TestDeleteAccount_Performance(t *testing.T) {
t.Run("ResponseTime", func(t *testing.T) {
req, _ := http.NewRequest("DELETE", baseURL+"/account/delete", nil)
req.Header.Set("Authorization", "Bearer "+validToken)
start := time.Now()
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
duration := time.Since(start)
assert.Less(t, duration.Milliseconds(), int64(500))
})
}
func TestDeleteAccount_Load(t *testing.T) {
var wg sync.WaitGroup
for i := 0; i < 50; i++ {
wg.Add(1)
go func() {
defer wg.Done()
req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
if resp != nil {
defer resp.Body.Close()
}
}()
}
wg.Wait()
}
// todo 3.3.7 3.3.8 3.4
2025-05-26 13:46:21 +00:00
func TestGetAccounts_Success(t *testing.T) {
body := map[string]interface{}{
"limit": 10,
"page": 1,
}
b, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validAdminToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", resp.Header.Get("Content-Type"))
var result struct {
Count uint64 `json:"count"`
Items []model.Account `json:"items"`
}
err = json.NewDecoder(resp.Body).Decode(&result)
assert.NoError(t, err)
assert.LessOrEqual(t, len(result.Items), 2)
for _, acc := range result.Items {
assert.NotEmpty(t, acc.ID)
assert.NotEmpty(t, acc.UserID)
assert.NotEmpty(t, acc.CreatedAt)
}
}
func TestGetAccounts_Auth(t *testing.T) {
t.Run("NoToken", func(t *testing.T) {
body := map[string]interface{}{
"limit": 10,
"page": 1,
}
b, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("InvalidToken", func(t *testing.T) {
body := map[string]interface{}{
"limit": 10,
"page": 1,
}
b, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer invalid_token")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("ExpiredToken", func(t *testing.T) {
body := map[string]interface{}{
"limit": 10,
"page": 1,
}
b, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+expiredToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
}
func TestGetAccounts_Pagination(t *testing.T) {
t.Run("ValidPagination", func(t *testing.T) {
body := map[string]interface{}{"limit": 5, "page": 1}
b, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validAdminToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
})
// todo
//t.Run("ZeroPagination", func(t *testing.T) {
// body := map[string]interface{}{"limit": 0, "page": 0}
// b, err := json.Marshal(body)
// assert.NoError(t, err)
// req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
// assert.NoError(t, err)
// req.Header.Set("Authorization", "Bearer "+validAdminToken)
// req.Header.Set("Content-Type", "application/json")
//
// resp, err := http.DefaultClient.Do(req)
// assert.NoError(t, err)
// defer resp.Body.Close()
// assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
//})
// todo
//t.Run("TooHighLimit", func(t *testing.T) {
// body := map[string]interface{}{"limit": 1000}
// b, err := json.Marshal(body)
// assert.NoError(t, err)
// req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
// assert.NoError(t, err)
// req.Header.Set("Authorization", "Bearer "+validAdminToken)
// req.Header.Set("Content-Type", "application/json")
//
// resp, err := http.DefaultClient.Do(req)
// assert.NoError(t, err)
// defer resp.Body.Close()
// assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
//})
}
// todo 4.3.4 4.3.5
func TestGetAccounts_Performance(t *testing.T) {
t.Run("ResponseTimeUnder500ms", func(t *testing.T) {
body := map[string]interface{}{"limit": 10, "page": 1}
b, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validAdminToken)
req.Header.Set("Content-Type", "application/json")
start := time.Now()
resp, err := http.DefaultClient.Do(req)
duration := time.Since(start)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Less(t, duration.Milliseconds(), int64(500))
})
t.Run("LoadTest100Requests", func(t *testing.T) {
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
body := map[string]interface{}{"limit": 10, "page": 1}
b, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validAdminToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err == nil {
resp.Body.Close()
}
}()
}
wg.Wait()
})
}
// todo 4.3.7 4.3.8 4.4
func TestGetPrivilege_Success(t *testing.T) {
body := map[string]string{"userId": existingUserID}
data, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, bytes.NewBuffer(data))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+existingUserIDToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", resp.Header.Get("Content-Type"))
var privileges []model.ShortPrivilege
err = json.NewDecoder(resp.Body).Decode(&privileges)
assert.NoError(t, err)
for _, p := range privileges {
assert.NotEmpty(t, p.ID)
assert.NotEmpty(t, p.PrivilegeID)
assert.NotEmpty(t, p.PrivilegeName)
}
}
func TestGetPrivilege_Auth(t *testing.T) {
t.Run("NoToken", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, nil)
assert.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("InvalidToken", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer invalid_token")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("ExpiredToken", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+expiredToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
}
func TestGetPrivilege_InputValidation(t *testing.T) {
t.Run("MissingUserID", func(t *testing.T) {
req, err := http.NewRequest("GET", baseURL+"/privilege/", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
})
t.Run("InvalidUserID", func(t *testing.T) {
body := map[string]int{"userId": 111}
data, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/privilege/!!!", bytes.NewBuffer(data))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("NonExistentUserID", func(t *testing.T) {
nonExistentID := "non_existent_user_123"
body := map[string]string{"userId": nonExistentID}
data, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/privilege/"+nonExistentID, bytes.NewBuffer(data))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var privileges []model.ShortPrivilege
err = json.NewDecoder(resp.Body).Decode(&privileges)
assert.NoError(t, err)
assert.Empty(t, privileges)
})
}
// todo 5.3.4
func TestGetPrivilege_Security(t *testing.T) {
t.Run("SQLInjection", func(t *testing.T) {
injection := "1' OR '1'='1"
body := map[string]string{"userId": injection}
data, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/privilege/"+injection, bytes.NewBuffer(data))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("XSS", func(t *testing.T) {
body := map[string]string{"userId": xssInput}
data, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/privilege/"+xssInput, bytes.NewBuffer(data))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
}
func TestGetPrivilege_Performance(t *testing.T) {
t.Run("ResponseTime", func(t *testing.T) {
body := map[string]string{"userId": existingUserID}
data, err := json.Marshal(body)
assert.NoError(t, err)
start := time.Now()
req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, bytes.NewBuffer(data))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+existingUserIDToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
defer resp.Body.Close()
assert.Less(t, time.Since(start).Milliseconds(), int64(300))
})
t.Run("LoadTest", func(t *testing.T) {
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
body := map[string]string{"userId": existingUserID}
data, err := json.Marshal(body)
assert.NoError(t, err)
req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, bytes.NewBuffer(data))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+existingUserIDToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
if resp != nil {
defer resp.Body.Close()
}
}()
}
wg.Wait()
})
}
// todo 5.3.7 5.3.8 5.4
func deleteAccountByUserIDRequest(token string, body interface{}) (*http.Response, error) {
payload, err := json.Marshal(body)
if err != nil {
return nil, err
}
req, err := http.NewRequest("DELETE", baseURL+"/account/"+body.(map[string]string)["userId"], bytes.NewReader(payload))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
return http.DefaultClient.Do(req)
}
func TestDeleteAccountByUserID_Success(t *testing.T) {
resp, err := deleteAccountByUserIDRequest(validAdminToken, map[string]string{"userId": userIDForDelete})
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", resp.Header.Get("Content-Type"))
var result map[string]string
err = json.NewDecoder(resp.Body).Decode(&result)
assert.NoError(t, err)
assert.Equal(t, testUserID, result["userId"])
}
func TestDeleteAccountByUserID_Auth(t *testing.T) {
t.Run("NoToken", func(t *testing.T) {
req, err := http.NewRequest("DELETE", baseURL+"/account/"+userIDForDelete, nil)
assert.NoError(t, err)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("InvalidToken", func(t *testing.T) {
resp, err := deleteAccountByUserIDRequest("invalid_token", map[string]string{"userId": userIDForDelete})
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("ExpiredToken", func(t *testing.T) {
resp, err := deleteAccountByUserIDRequest(expiredToken, map[string]string{"userId": userIDForDelete})
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
}
func TestDeleteAccountByUserID_Validation(t *testing.T) {
t.Run("EmptyBody", func(t *testing.T) {
req, err := http.NewRequest("DELETE", baseURL+"/account/", bytes.NewReader([]byte(`{}`)))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validAdminToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("InvalidUserID", func(t *testing.T) {
resp, err := deleteAccountByUserIDRequest(validAdminToken, map[string]string{"userId": "invalid_id"})
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
}
// todo 6.3.4 6.3.5
func TestDeleteAccountByUserID_SQLInjection_XSS(t *testing.T) {
t.Run("SQLInjection", func(t *testing.T) {
resp, err := deleteAccountByUserIDRequest(validAdminToken, map[string]string{"userId": sqlInjectionInput})
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("XSS", func(t *testing.T) {
resp, err := deleteAccountByUserIDRequest(validAdminToken, map[string]string{"userId": xssInput})
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
}
// todo 6.3.7 6.3.8 6.3.9 6.4
func manualDoneRequest(token string, body map[string]string) (*http.Response, error) {
payload, err := json.Marshal(body)
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", baseURL+"/account/manualdone", bytes.NewReader(payload))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
return http.DefaultClient.Do(req)
}
func TestManualDone_Success(t *testing.T) {
resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": testUserID})
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "application/json", resp.Header.Get("Content-Type"))
var result map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&result)
assert.NoError(t, err)
assert.Equal(t, testUserID, result["id"])
}
func TestManualDone_Auth(t *testing.T) {
t.Run("NoToken", func(t *testing.T) {
payload, err := json.Marshal(map[string]string{"id": testUserID})
assert.NoError(t, err)
req, err := http.NewRequest("POST", baseURL+"/account/manualdone", bytes.NewReader(payload))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("InvalidToken", func(t *testing.T) {
resp, err := manualDoneRequest("invalid_token", map[string]string{"id": testUserID})
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
t.Run("ExpiredToken", func(t *testing.T) {
resp, err := manualDoneRequest(expiredToken, map[string]string{"id": testUserID})
assert.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
})
}
func TestManualDone_Validation(t *testing.T) {
t.Run("EmptyBody", func(t *testing.T) {
payload := []byte(`{}`)
req, err := http.NewRequest("POST", baseURL+"/account/manualdone", bytes.NewReader(payload))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+validAdminToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("InvalidID", func(t *testing.T) {
resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": "invalid_id"})
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("NonExistentID", func(t *testing.T) {
resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": "nonexistent_id"})
assert.NoError(t, err)
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
})
}
// todo 7.3.4 7.3.5
func TestManualDone_Security(t *testing.T) {
t.Run("SQLInjection", func(t *testing.T) {
resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": "1' OR '1'='1"})
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("XSSAttack", func(t *testing.T) {
resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": "<script>alert('xss')</script>"})
assert.NoError(t, err)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
}
// todo 7.3.7 7.3.8 7.3.9 7.4