test: local upload store-failure branches (kill minio mid-test)
This commit is contained in:
@@ -0,0 +1,88 @@
|
|||||||
|
package v2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
|
||||||
|
"git.unkin.net/unkin/artifactapi/internal/database"
|
||||||
|
"git.unkin.net/unkin/artifactapi/internal/storage"
|
||||||
|
"git.unkin.net/unkin/artifactapi/internal/testsupport"
|
||||||
|
"git.unkin.net/unkin/artifactapi/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestLocalUploadStoreFailure covers the upload handlers' store-error branches
|
||||||
|
// by killing the object store after a successful upload.
|
||||||
|
func TestLocalUploadStoreFailure(t *testing.T) {
|
||||||
|
if testDSN == "" {
|
||||||
|
t.Skip("Docker unavailable")
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
db, err := database.New(testDSN)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
conn, termMinio, err := testsupport.StartMinio(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Skip("minio unavailable")
|
||||||
|
}
|
||||||
|
var store *storage.S3
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
if store, err = storage.NewS3(conn.Endpoint, conn.AccessKey, conn.SecretKey, "fault", false, ""); err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
termMinio()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pt := range []models.PackageType{models.PackageGeneric, models.PackagePyPI} {
|
||||||
|
if err := db.CreateRemote(ctx, &models.Remote{Name: "fault-" + string(pt), PackageType: pt, RepoType: models.RepoTypeLocal}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h := NewLocalHandler(db, store)
|
||||||
|
router := chi.NewRouter()
|
||||||
|
router.Route("/remotes/{name}/files", func(r chi.Router) {
|
||||||
|
r.Put("/*", h.Routes().ServeHTTP)
|
||||||
|
})
|
||||||
|
srv := httptest.NewServer(router)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
put := func(name, path, body string) int {
|
||||||
|
rq, _ := http.NewRequest("PUT", srv.URL+"/remotes/"+name+"/files/"+path, strings.NewReader(body))
|
||||||
|
resp, err := http.DefaultClient.Do(rq)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("put: %v", err)
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
return resp.StatusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity: uploads succeed while the store is up.
|
||||||
|
if c := put("fault-generic", "ok.bin", "data"); c != 201 {
|
||||||
|
t.Fatalf("generic upload while up = %d", c)
|
||||||
|
}
|
||||||
|
if c := put("fault-pypi", "foo-1.0-py3-none-any.whl", "wheel"); c != 201 {
|
||||||
|
t.Fatalf("pypi upload while up = %d", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill the store; subsequent CAS.Store calls fail -> 500.
|
||||||
|
termMinio()
|
||||||
|
if c := put("fault-generic", "after.bin", "data"); c != 500 {
|
||||||
|
t.Errorf("generic upload after store down = %d, want 500", c)
|
||||||
|
}
|
||||||
|
if c := put("fault-pypi", "bar-1.0-py3-none-any.whl", "wheel"); c != 500 {
|
||||||
|
t.Errorf("pypi upload after store down = %d, want 500", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user