mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 10:45:45 +01:00
Merge pull request #3950 from ywk253100/180105_ut
Add unit test for adding description of repository
This commit is contained in:
commit
093e2bead2
@ -16,6 +16,7 @@ package api
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
@ -28,11 +29,18 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/vmware/harbor/src/common/dao"
|
"github.com/vmware/harbor/src/common/dao"
|
||||||
|
common_http "github.com/vmware/harbor/src/common/http"
|
||||||
"github.com/vmware/harbor/src/common/models"
|
"github.com/vmware/harbor/src/common/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
nonSysAdminID int64
|
nonSysAdminID, projAdminID, projDeveloperID, projGuestID int
|
||||||
|
|
||||||
|
// The following users/credentials are registered and assigned roles at the beginning of
|
||||||
|
// running testing and cleaned up at the end.
|
||||||
|
// Do not try to change the system and project roles that the users have during
|
||||||
|
// the testing. Creating a new one in your own case if needed.
|
||||||
|
// The project roles that the users have are for project library.
|
||||||
sysAdmin = &usrInfo{
|
sysAdmin = &usrInfo{
|
||||||
Name: "admin",
|
Name: "admin",
|
||||||
Passwd: "Harbor12345",
|
Passwd: "Harbor12345",
|
||||||
@ -41,6 +49,18 @@ var (
|
|||||||
Name: "non_admin",
|
Name: "non_admin",
|
||||||
Passwd: "Harbor12345",
|
Passwd: "Harbor12345",
|
||||||
}
|
}
|
||||||
|
projAdmin = &usrInfo{
|
||||||
|
Name: "proj_admin",
|
||||||
|
Passwd: "Harbor12345",
|
||||||
|
}
|
||||||
|
projDeveloper = &usrInfo{
|
||||||
|
Name: "proj_developer",
|
||||||
|
Passwd: "Harbor12345",
|
||||||
|
}
|
||||||
|
projGuest = &usrInfo{
|
||||||
|
Name: "proj_guest",
|
||||||
|
Passwd: "Harbor12345",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
type testingRequest struct {
|
type testingRequest struct {
|
||||||
@ -113,22 +133,25 @@ func handle(r *testingRequest) (*httptest.ResponseRecorder, error) {
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleAndParse(r *testingRequest, v interface{}) (*httptest.ResponseRecorder, error) {
|
func handleAndParse(r *testingRequest, v interface{}) error {
|
||||||
req, err := newRequest(r)
|
resp, err := handle(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := httptest.NewRecorder()
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
beego.BeeApp.Handlers.ServeHTTP(resp, req)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if resp.Code >= 200 && resp.Code <= 299 {
|
if resp.Code >= 200 && resp.Code <= 299 {
|
||||||
if err := json.NewDecoder(resp.Body).Decode(v); err != nil {
|
return json.Unmarshal(data, v)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return &common_http.Error{
|
||||||
|
Code: resp.Code,
|
||||||
|
Message: string(data),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCodeCheckingCases(t *testing.T, cases ...*codeCheckingCase) {
|
func runCodeCheckingCases(t *testing.T, cases ...*codeCheckingCase) {
|
||||||
@ -179,17 +202,73 @@ func TestMain(m *testing.M) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func prepare() error {
|
func prepare() error {
|
||||||
|
// register nonSysAdmin
|
||||||
id, err := dao.Register(models.User{
|
id, err := dao.Register(models.User{
|
||||||
Username: nonSysAdmin.Name,
|
Username: nonSysAdmin.Name,
|
||||||
Password: nonSysAdmin.Passwd,
|
Password: nonSysAdmin.Passwd,
|
||||||
|
Email: nonSysAdmin.Name + "@test.com",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
nonSysAdminID = id
|
nonSysAdminID = int(id)
|
||||||
return nil
|
|
||||||
|
// register projAdmin and assign project admin role
|
||||||
|
id, err = dao.Register(models.User{
|
||||||
|
Username: projAdmin.Name,
|
||||||
|
Password: projAdmin.Passwd,
|
||||||
|
Email: projAdmin.Name + "@test.com",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
projAdminID = int(id)
|
||||||
|
|
||||||
|
if err = dao.AddProjectMember(1, projAdminID, models.PROJECTADMIN); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// register projDeveloper and assign project developer role
|
||||||
|
id, err = dao.Register(models.User{
|
||||||
|
Username: projDeveloper.Name,
|
||||||
|
Password: projDeveloper.Passwd,
|
||||||
|
Email: projDeveloper.Name + "@test.com",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
projDeveloperID = int(id)
|
||||||
|
|
||||||
|
if err = dao.AddProjectMember(1, projDeveloperID, models.DEVELOPER); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// register projGuest and assign project guest role
|
||||||
|
id, err = dao.Register(models.User{
|
||||||
|
Username: projGuest.Name,
|
||||||
|
Password: projGuest.Passwd,
|
||||||
|
Email: projGuest.Name + "@test.com",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
projGuestID = int(id)
|
||||||
|
|
||||||
|
return dao.AddProjectMember(1, projGuestID, models.GUEST)
|
||||||
}
|
}
|
||||||
|
|
||||||
func clean() error {
|
func clean() {
|
||||||
return dao.DeleteUser(int(nonSysAdminID))
|
ids := []int{projAdminID, projDeveloperID, projGuestID}
|
||||||
|
for _, id := range ids {
|
||||||
|
if err := dao.DeleteProjectMember(1, id); err != nil {
|
||||||
|
fmt.Printf("failed to clean up member %d from project library: %v", id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ids = append(ids, nonSysAdminID)
|
||||||
|
for _, id := range ids {
|
||||||
|
if err := dao.DeleteUser(id); err != nil {
|
||||||
|
fmt.Printf("failed to clean up user %d: %v \n", id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,7 @@ func init() {
|
|||||||
beego.Router("/api/statistics", &StatisticAPI{})
|
beego.Router("/api/statistics", &StatisticAPI{})
|
||||||
beego.Router("/api/users/?:id", &UserAPI{})
|
beego.Router("/api/users/?:id", &UserAPI{})
|
||||||
beego.Router("/api/logs", &LogAPI{})
|
beego.Router("/api/logs", &LogAPI{})
|
||||||
|
beego.Router("/api/repositories/*", &RepositoryAPI{}, "put:Put")
|
||||||
beego.Router("/api/repositories/*/tags/:tag", &RepositoryAPI{}, "delete:Delete;get:GetTag")
|
beego.Router("/api/repositories/*/tags/:tag", &RepositoryAPI{}, "delete:Delete;get:GetTag")
|
||||||
beego.Router("/api/repositories/*/tags", &RepositoryAPI{}, "get:GetTags")
|
beego.Router("/api/repositories/*/tags", &RepositoryAPI{}, "get:GetTags")
|
||||||
beego.Router("/api/repositories/*/tags/:tag/manifest", &RepositoryAPI{}, "get:GetManifests")
|
beego.Router("/api/repositories/*/tags/:tag/manifest", &RepositoryAPI{}, "get:GetManifests")
|
||||||
|
@ -291,14 +291,13 @@ func TestRepPolicyAPIGet(t *testing.T) {
|
|||||||
|
|
||||||
// 200
|
// 200
|
||||||
policy := &api_models.ReplicationPolicy{}
|
policy := &api_models.ReplicationPolicy{}
|
||||||
resp, err := handleAndParse(
|
err := handleAndParse(
|
||||||
&testingRequest{
|
&testingRequest{
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
url: fmt.Sprintf("%s/%d", repPolicyAPIBasePath, policyID),
|
url: fmt.Sprintf("%s/%d", repPolicyAPIBasePath, policyID),
|
||||||
credential: sysAdmin,
|
credential: sysAdmin,
|
||||||
}, policy)
|
}, policy)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, http.StatusOK, resp.Code)
|
|
||||||
assert.Equal(t, policyID, policy.ID)
|
assert.Equal(t, policyID, policy.ID)
|
||||||
assert.Equal(t, policyName, policy.Name)
|
assert.Equal(t, policyName, policy.Name)
|
||||||
}
|
}
|
||||||
@ -354,7 +353,7 @@ func TestRepPolicyAPIList(t *testing.T) {
|
|||||||
|
|
||||||
// 200 system admin
|
// 200 system admin
|
||||||
policies := []*api_models.ReplicationPolicy{}
|
policies := []*api_models.ReplicationPolicy{}
|
||||||
resp, err := handleAndParse(
|
err = handleAndParse(
|
||||||
&testingRequest{
|
&testingRequest{
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
url: repPolicyAPIBasePath,
|
url: repPolicyAPIBasePath,
|
||||||
@ -368,14 +367,13 @@ func TestRepPolicyAPIList(t *testing.T) {
|
|||||||
credential: sysAdmin,
|
credential: sysAdmin,
|
||||||
}, &policies)
|
}, &policies)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, http.StatusOK, resp.Code)
|
|
||||||
require.Equal(t, 1, len(policies))
|
require.Equal(t, 1, len(policies))
|
||||||
assert.Equal(t, policyID, policies[0].ID)
|
assert.Equal(t, policyID, policies[0].ID)
|
||||||
assert.Equal(t, policyName, policies[0].Name)
|
assert.Equal(t, policyName, policies[0].Name)
|
||||||
|
|
||||||
// 200 project admin
|
// 200 project admin
|
||||||
policies = []*api_models.ReplicationPolicy{}
|
policies = []*api_models.ReplicationPolicy{}
|
||||||
resp, err = handleAndParse(
|
err = handleAndParse(
|
||||||
&testingRequest{
|
&testingRequest{
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
url: repPolicyAPIBasePath,
|
url: repPolicyAPIBasePath,
|
||||||
@ -392,14 +390,13 @@ func TestRepPolicyAPIList(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, &policies)
|
}, &policies)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, http.StatusOK, resp.Code)
|
|
||||||
require.Equal(t, 1, len(policies))
|
require.Equal(t, 1, len(policies))
|
||||||
assert.Equal(t, policyID, policies[0].ID)
|
assert.Equal(t, policyID, policies[0].ID)
|
||||||
assert.Equal(t, policyName, policies[0].Name)
|
assert.Equal(t, policyName, policies[0].Name)
|
||||||
|
|
||||||
// 200 project developer
|
// 200 project developer
|
||||||
policies = []*api_models.ReplicationPolicy{}
|
policies = []*api_models.ReplicationPolicy{}
|
||||||
resp, err = handleAndParse(
|
err = handleAndParse(
|
||||||
&testingRequest{
|
&testingRequest{
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
url: repPolicyAPIBasePath,
|
url: repPolicyAPIBasePath,
|
||||||
@ -416,12 +413,11 @@ func TestRepPolicyAPIList(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}, &policies)
|
}, &policies)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, http.StatusOK, resp.Code)
|
|
||||||
require.Equal(t, 0, len(policies))
|
require.Equal(t, 0, len(policies))
|
||||||
|
|
||||||
// 200
|
// 200
|
||||||
policies = []*api_models.ReplicationPolicy{}
|
policies = []*api_models.ReplicationPolicy{}
|
||||||
resp, err = handleAndParse(
|
err = handleAndParse(
|
||||||
&testingRequest{
|
&testingRequest{
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
url: repPolicyAPIBasePath,
|
url: repPolicyAPIBasePath,
|
||||||
@ -435,7 +431,6 @@ func TestRepPolicyAPIList(t *testing.T) {
|
|||||||
credential: sysAdmin,
|
credential: sysAdmin,
|
||||||
}, &policies)
|
}, &policies)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, http.StatusOK, resp.Code)
|
|
||||||
require.Equal(t, 0, len(policies))
|
require.Equal(t, 0, len(policies))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetRepos(t *testing.T) {
|
func TestGetRepos(t *testing.T) {
|
||||||
@ -223,3 +224,106 @@ func TestPopulateAuthor(t *testing.T) {
|
|||||||
populateAuthor(detail)
|
populateAuthor(detail)
|
||||||
assert.Equal(t, maintainer, detail.Author)
|
assert.Equal(t, maintainer, detail.Author)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPutOfRepository(t *testing.T) {
|
||||||
|
base := "/api/repositories/"
|
||||||
|
desc := struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
}{
|
||||||
|
Description: "description_for_test",
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []*codeCheckingCase{
|
||||||
|
// 404
|
||||||
|
&codeCheckingCase{
|
||||||
|
request: &testingRequest{
|
||||||
|
method: http.MethodPut,
|
||||||
|
url: base + "non_exist_repository",
|
||||||
|
bodyJSON: desc,
|
||||||
|
},
|
||||||
|
code: http.StatusNotFound,
|
||||||
|
},
|
||||||
|
// 401
|
||||||
|
&codeCheckingCase{
|
||||||
|
request: &testingRequest{
|
||||||
|
method: http.MethodPut,
|
||||||
|
url: base + "library/hello-world",
|
||||||
|
bodyJSON: desc,
|
||||||
|
},
|
||||||
|
code: http.StatusUnauthorized,
|
||||||
|
},
|
||||||
|
// 403 non-member
|
||||||
|
&codeCheckingCase{
|
||||||
|
request: &testingRequest{
|
||||||
|
method: http.MethodPut,
|
||||||
|
url: base + "library/hello-world",
|
||||||
|
bodyJSON: desc,
|
||||||
|
credential: nonSysAdmin,
|
||||||
|
},
|
||||||
|
code: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
// 403 project guest
|
||||||
|
&codeCheckingCase{
|
||||||
|
request: &testingRequest{
|
||||||
|
method: http.MethodPut,
|
||||||
|
url: base + "library/hello-world",
|
||||||
|
bodyJSON: desc,
|
||||||
|
credential: projGuest,
|
||||||
|
},
|
||||||
|
code: http.StatusForbidden,
|
||||||
|
},
|
||||||
|
// 200 project developer
|
||||||
|
&codeCheckingCase{
|
||||||
|
request: &testingRequest{
|
||||||
|
method: http.MethodPut,
|
||||||
|
url: base + "library/hello-world",
|
||||||
|
bodyJSON: desc,
|
||||||
|
credential: projDeveloper,
|
||||||
|
},
|
||||||
|
code: http.StatusOK,
|
||||||
|
},
|
||||||
|
// 200 project admin
|
||||||
|
&codeCheckingCase{
|
||||||
|
request: &testingRequest{
|
||||||
|
method: http.MethodPut,
|
||||||
|
url: base + "library/hello-world",
|
||||||
|
bodyJSON: desc,
|
||||||
|
credential: projAdmin,
|
||||||
|
},
|
||||||
|
code: http.StatusOK,
|
||||||
|
},
|
||||||
|
// 200 system admin
|
||||||
|
&codeCheckingCase{
|
||||||
|
request: &testingRequest{
|
||||||
|
method: http.MethodPut,
|
||||||
|
url: base + "library/hello-world",
|
||||||
|
bodyJSON: desc,
|
||||||
|
credential: sysAdmin,
|
||||||
|
},
|
||||||
|
code: http.StatusOK,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
runCodeCheckingCases(t, cases...)
|
||||||
|
|
||||||
|
// verify that the description is changed
|
||||||
|
repositories := []*repoResp{}
|
||||||
|
err := handleAndParse(&testingRequest{
|
||||||
|
method: http.MethodGet,
|
||||||
|
url: base,
|
||||||
|
queryStruct: struct {
|
||||||
|
ProjectID int64 `url:"project_id"`
|
||||||
|
}{
|
||||||
|
ProjectID: 1,
|
||||||
|
},
|
||||||
|
}, &repositories)
|
||||||
|
require.Nil(t, err)
|
||||||
|
var repository *repoResp
|
||||||
|
for _, repo := range repositories {
|
||||||
|
if repo.Name == "library/hello-world" {
|
||||||
|
repository = repo
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, repository)
|
||||||
|
assert.Equal(t, desc.Description, repository.Description)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user