0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2025-02-17 23:45:36 -05:00

test: add unit test to verify lock changes

This commit is contained in:
Shivam Mishra 2020-10-13 12:03:47 -07:00
parent 386c72d332
commit 14214a5794
4 changed files with 515 additions and 4 deletions

View file

@ -36,7 +36,7 @@ go_library(
go_test(
name = "go_default_test",
timeout = "moderate",
timeout = "long",
srcs = ["controller_test.go"],
data = [
"//:exported_testdata",
@ -49,7 +49,9 @@ go_test(
"@com_github_mitchellh_mapstructure//:go_default_library",
"@com_github_nmcclain_ldap//:go_default_library",
"@com_github_opencontainers_go_digest//:go_default_library",
"@com_github_opencontainers_image_spec//specs-go/v1:go_default_library",
"@com_github_smartystreets_goconvey//convey:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
"@in_gopkg_resty_v1//:go_default_library",
"@org_golang_x_crypto//bcrypt:go_default_library",
],

View file

@ -1,17 +1,20 @@
package api_test
import (
"bufio"
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path"
"regexp"
"strings"
"testing"
@ -23,8 +26,11 @@ import (
"github.com/anuvu/zot/pkg/api"
"github.com/chartmuseum/auth"
"github.com/mitchellh/mapstructure"
vldap "github.com/nmcclain/ldap"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/stretchr/testify/assert"
vldap "github.com/nmcclain/ldap"
. "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1"
)
@ -101,6 +107,7 @@ func getCredString(username, password string) string {
return usernameAndHash
}
func TestNew(t *testing.T) {
Convey("Make a new controller", t, func() {
config := api.NewConfig()
@ -1515,3 +1522,505 @@ func TestHTTPReadOnly(t *testing.T) {
}
})
}
func TestParallelRequests(t *testing.T) {
testCases := []struct {
srcImageName string
srcImageTag string
destImageName string
destImageTag string
testCaseName string
}{
{
srcImageName: "zot-test",
srcImageTag: "0.0.1",
destImageName: "zot-1-test",
destImageTag: "0.0.1",
testCaseName: "Request-1",
},
{
srcImageName: "zot-test",
srcImageTag: "0.0.1",
destImageName: "zot-2-test",
testCaseName: "Request-2",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-3-test",
testCaseName: "Request-3",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-4-test",
testCaseName: "Request-4",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-5-test",
testCaseName: "Request-5",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-1-test",
testCaseName: "Request-6",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-2-test",
testCaseName: "Request-7",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-3-test",
testCaseName: "Request-8",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-4-test",
testCaseName: "Request-9",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-5-test",
testCaseName: "Request-10",
},
{
srcImageName: "zot-test",
srcImageTag: "0.0.1",
destImageName: "zot-1-test",
destImageTag: "0.0.1",
testCaseName: "Request-11",
},
{
srcImageName: "zot-test",
srcImageTag: "0.0.1",
destImageName: "zot-2-test",
testCaseName: "Request-12",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-3-test",
testCaseName: "Request-13",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-4-test",
testCaseName: "Request-14",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-5-test",
testCaseName: "Request-15",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-1-test",
testCaseName: "Request-16",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-2-test",
testCaseName: "Request-17",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-3-test",
testCaseName: "Request-18",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-4-test",
testCaseName: "Request-19",
},
{
srcImageName: "zot-cve-test",
srcImageTag: "0.0.1",
destImageName: "zot-5-test",
testCaseName: "Request-20",
},
}
config := api.NewConfig()
config.HTTP.Port = SecurePort1
htpasswdPath := makeHtpasswdFileFromString(getCredString(username, passphrase))
// defer os.Remove(htpasswdPath)
config.HTTP.Auth = &api.AuthConfig{
HTPasswd: api.AuthHTPasswd{
Path: htpasswdPath,
},
}
c := api.NewController(config)
dir, err := ioutil.TempDir("", "oci-repo-test")
if err != nil {
panic(err)
}
err = copyFiles("../../test/data", dir)
if err != nil {
panic(err)
}
//defer os.RemoveAll(dir)
c.Config.Storage.RootDirectory = dir
go func() {
// this blocks
if err := c.Run(); err != nil {
return
}
}()
// wait till ready
for {
_, err := resty.R().Get(BaseURL1)
if err == nil {
break
}
time.Sleep(100 * time.Millisecond)
}
// without creds, should get access error
for i, testcase := range testCases {
testcase := testcase
j := i
//println(i)
t.Run(testcase.testCaseName, func(t *testing.T) {
t.Parallel()
client := resty.New()
tagResponse, err := client.R().SetBasicAuth(username, passphrase).
Get(BaseURL1 + "/v2/" + testcase.destImageName + "/tags/list")
assert.Equal(t, err, nil, "Error should be nil")
assert.NotEqual(t, tagResponse.StatusCode(), 400, "bad request")
manifestList := getAllManifests(path.Join(c.Config.Storage.RootDirectory, testcase.srcImageName))
for _, manifest := range manifestList {
headResponse, err := client.R().SetBasicAuth(username, passphrase).
Head(BaseURL1 + "/v2/" + testcase.destImageName + "/manifests/" + manifest)
assert.Equal(t, err, nil, "Error should be nil")
assert.Equal(t, headResponse.StatusCode(), 404, "response status code should return 404")
getResponse, err := client.R().SetBasicAuth(username, passphrase).
Get(BaseURL1 + "/v2/" + testcase.destImageName + "/manifests/" + manifest)
assert.Equal(t, err, nil, "Error should be nil")
assert.Equal(t, getResponse.StatusCode(), 404, "response status code should return 404")
}
blobList := getAllBlobs(path.Join(c.Config.Storage.RootDirectory, testcase.srcImageName))
for _, blob := range blobList {
// Get request of blob
headResponse, err := client.R().
SetBasicAuth(username, passphrase).
Head(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob)
assert.Equal(t, err, nil, "Should not be nil")
assert.NotEqual(t, headResponse.StatusCode(), 500, "internal server error should not occurred")
getResponse, err := client.R().
SetBasicAuth(username, passphrase).
Get(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob)
assert.Equal(t, err, nil, "Should not be nil")
assert.NotEqual(t, getResponse.StatusCode(), 500, "internal server error should not occurred")
blobPath := path.Join(c.Config.Storage.RootDirectory, testcase.srcImageName, "blobs/sha256", blob)
buf, err := ioutil.ReadFile(blobPath)
if err != nil {
panic(err)
}
// Post request of blob
postResponse, err := client.R().
SetHeader("Content-type", "application/octet-stream").
SetBasicAuth(username, passphrase).
SetBody(buf).Post(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/uploads/")
assert.Equal(t, err, nil, "Error should be nil")
assert.NotEqual(t, postResponse.StatusCode(), 500, "response status code should not return 500")
// Post request with query parameter
if j%2 == 0 {
postResponse, err = client.R().
SetHeader("Content-type", "application/octet-stream").
SetBasicAuth(username, passphrase).
SetBody(buf).
Post(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/uploads/")
assert.Equal(t, err, nil, "Error should be nil")
assert.NotEqual(t, postResponse.StatusCode(), 500, "response status code should not return 500")
var sessionID string
sessionIDList := postResponse.Header().Values("Blob-Upload-UUID")
if len(sessionIDList) == 0 {
location := postResponse.Header().Values("Location")
firstLocation := location[0]
splitLocation := strings.Split(firstLocation, "/")
sessionID = splitLocation[len(splitLocation)-1]
} else {
sessionID = sessionIDList[0]
}
file, err := os.Open(blobPath)
if err != nil {
panic(err)
}
defer file.Close()
reader := bufio.NewReader(file)
b := make([]byte, 1024*1024)
if j%4 == 0 {
readContent := 0
for {
n, err := reader.Read(b)
if err != nil {
if err == io.EOF {
break
}
panic(err)
}
// Patch request of blob
patchResponse, err := client.R().
SetBody(b[0:n]).
SetHeader("Content-Type", "application/octet-stream").
SetHeader("Content-Length", fmt.Sprintf("%d", n)).
SetHeader("Content-Range", fmt.Sprintf("%d", readContent)+"-"+fmt.Sprintf("%d", readContent+n-1)).
SetBasicAuth(username, passphrase).
Patch(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/uploads/" + sessionID)
if err != nil {
panic(err)
}
assert.Equal(t, err, nil, "Error should be nil")
assert.NotEqual(t, patchResponse.StatusCode(), 500, "response status code should not return 500")
readContent += n
}
} else {
for {
n, err := reader.Read(b)
if err != nil {
if err == io.EOF {
break
}
panic(err)
}
// Patch request of blob
patchResponse, err := client.R().SetBody(b[0:n]).SetHeader("Content-type", "application/octet-stream").
SetBasicAuth(username, passphrase).
Patch(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/uploads/" + sessionID)
if err != nil {
panic(err)
}
assert.Equal(t, err, nil, "Error should be nil")
assert.NotEqual(t, patchResponse.StatusCode(), 500, "response status code should not return 500")
}
}
} else {
postResponse, err = client.R().
SetHeader("Content-type", "application/octet-stream").
SetBasicAuth(username, passphrase).
SetBody(buf).SetQueryParam("digest", "sha256:"+blob).
Post(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/uploads/")
assert.Equal(t, err, nil, "Error should be nil")
assert.NotEqual(t, postResponse.StatusCode(), 500, "response status code should not return 500")
}
headResponse, err = client.R().
SetBasicAuth(username, passphrase).
Head(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob)
assert.Equal(t, err, nil, "Should not be nil")
assert.NotEqual(t, headResponse.StatusCode(), 500, "response should return success code")
getResponse, err = client.R().
SetBasicAuth(username, passphrase).
Get(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob)
assert.Equal(t, err, nil, "Should not be nil")
assert.NotEqual(t, getResponse.StatusCode(), 500, "response should return success code")
if i < 5 { // nolint: scopelint
deleteResponse, err := client.R().
SetBasicAuth(username, passphrase).
Delete(BaseURL1 + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob)
assert.Equal(t, err, nil, "Should not be nil")
assert.Equal(t, deleteResponse.StatusCode(), 202, "response should return success code")
}
}
tagResponse, err = client.R().SetBasicAuth(username, passphrase).
Get(BaseURL1 + "/v2/" + testcase.destImageName + "/tags/list")
assert.Equal(t, err, nil, "Error should be nil")
assert.Equal(t, tagResponse.StatusCode(), 200, "response status code should return success code")
repoResponse, err := client.R().SetBasicAuth(username, passphrase).
Get(BaseURL1 + "/v2/_catalog")
assert.Equal(t, err, nil, "Error should be nil")
assert.Equal(t, repoResponse.StatusCode(), 200, "response status code should return success code")
})
}
}
func getAllBlobs(imagePath string) []string {
blobList := make([]string, 0)
if !dirExists(imagePath) {
return []string{}
}
buf, err := ioutil.ReadFile(path.Join(imagePath, "index.json"))
if err != nil {
panic(err)
}
var index ispec.Index
if err := json.Unmarshal(buf, &index); err != nil {
panic(err)
}
var digest godigest.Digest
for _, m := range index.Manifests {
digest = m.Digest
blobList = append(blobList, digest.Encoded())
p := path.Join(imagePath, "blobs", digest.Algorithm().String(), digest.Encoded())
buf, err = ioutil.ReadFile(p)
if err != nil {
panic(err)
}
var manifest ispec.Manifest
if err := json.Unmarshal(buf, &manifest); err != nil {
panic(err)
}
blobList = append(blobList, manifest.Config.Digest.Encoded())
for _, layer := range manifest.Layers {
blobList = append(blobList, layer.Digest.Encoded())
}
}
return blobList
}
func getAllManifests(imagePath string) []string {
manifestList := make([]string, 0)
if !dirExists(imagePath) {
return []string{}
}
buf, err := ioutil.ReadFile(path.Join(imagePath, "index.json"))
if err != nil {
panic(err)
}
var index ispec.Index
if err := json.Unmarshal(buf, &index); err != nil {
panic(err)
}
var digest godigest.Digest
for _, m := range index.Manifests {
digest = m.Digest
manifestList = append(manifestList, digest.Encoded())
}
return manifestList
}
func dirExists(d string) bool {
fi, err := os.Stat(d)
if err != nil && os.IsNotExist(err) {
return false
}
if !fi.IsDir() {
return false
}
return true
}
func copyFiles(sourceDir string, destDir string) error {
sourceMeta, err := os.Stat(sourceDir)
if err != nil {
return err
}
if err := os.MkdirAll(destDir, sourceMeta.Mode()); err != nil {
return err
}
files, err := ioutil.ReadDir(sourceDir)
if err != nil {
return err
}
for _, file := range files {
sourceFilePath := path.Join(sourceDir, file.Name())
destFilePath := path.Join(destDir, file.Name())
if file.IsDir() {
if err = copyFiles(sourceFilePath, destFilePath); err != nil {
return err
}
} else {
sourceFile, err := os.Open(sourceFilePath)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(destFilePath)
if err != nil {
return err
}
defer destFile.Close()
if _, err = io.Copy(destFile, sourceFile); err != nil {
return err
}
}
}
return nil
}

View file

@ -326,7 +326,7 @@ func TestServerCVEResponse(t *testing.T) {
time.Sleep(100 * time.Millisecond)
}
time.Sleep(25 * time.Second)
time.Sleep(35 * time.Second)
defer func(controller *api.Controller) {
ctx := context.Background()

View file

@ -501,7 +501,7 @@ func TestCVESearch(t *testing.T) {
}
// Wait for trivy db to download
time.Sleep(30 * time.Second)
time.Sleep(35 * time.Second)
defer func() {
ctx := context.Background()