ce8026d46e
- serialise publishes per crate with an advisory lock in one transaction - add a unique index on normalised name and version without build metadata - validate versions as strict SemVer 2.0 and reject an empty .crate - renumber the migration to 0005
67 lines
2.6 KiB
Go
67 lines
2.6 KiB
Go
//go:build dockere2e
|
|
|
|
package e2edocker
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestLocalCargoRegistry publishes through the cargo Web API, then reads the
|
|
// sparse index, downloads the crate and yanks it.
|
|
func TestLocalCargoRegistry(t *testing.T) {
|
|
createRepo(t, `{"name":"local-cargo","package_type":"cargo","repo_type":"local"}`)
|
|
defer deleteRepo(t, "local-cargo")
|
|
base := api("/api/v1/local/local-cargo")
|
|
|
|
meta := `{"name":"e2e-crate","vers":"0.1.0","deps":[],"features":{}}`
|
|
crate := []byte("e2e crate bytes")
|
|
publish := func(meta string) *http.Response {
|
|
var body []byte
|
|
body = binary.LittleEndian.AppendUint32(body, uint32(len(meta)))
|
|
body = append(body, meta...)
|
|
body = binary.LittleEndian.AppendUint32(body, uint32(len(crate)))
|
|
body = append(body, crate...)
|
|
resp, _ := doRequest(t, http.MethodPut, base+"/api/v1/crates/new", body, "application/octet-stream")
|
|
return resp
|
|
}
|
|
|
|
if resp := publish(meta); resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("publish: status %d", resp.StatusCode)
|
|
}
|
|
if resp := publish(meta); resp.StatusCode != http.StatusConflict {
|
|
t.Fatalf("republish: status %d, want 409", resp.StatusCode)
|
|
}
|
|
if resp := publish(`{"name":"e2e-crate","vers":"0.1.0+other","deps":[],"features":{}}`); resp.StatusCode != http.StatusConflict {
|
|
t.Fatalf("build-metadata republish: status %d, want 409", resp.StatusCode)
|
|
}
|
|
if resp := publish(`{"name":"E2E_crate","vers":"0.2.0","deps":[],"features":{}}`); resp.StatusCode != http.StatusBadRequest {
|
|
t.Fatalf("name collision publish: status %d, want 400", resp.StatusCode)
|
|
}
|
|
|
|
resp, b := doRequest(t, http.MethodGet, base+"/config.json", nil, "")
|
|
if resp.StatusCode != http.StatusOK || !strings.Contains(string(b), `"api":"`) {
|
|
t.Fatalf("config.json: status %d: %s", resp.StatusCode, b)
|
|
}
|
|
|
|
resp, b = doRequest(t, http.MethodGet, base+"/e2/e-/e2e-crate", nil, "")
|
|
if resp.StatusCode != http.StatusOK || !strings.Contains(string(b), `"cksum":"`) || !strings.Contains(string(b), `"yanked":false`) {
|
|
t.Fatalf("index: status %d: %s", resp.StatusCode, b)
|
|
}
|
|
|
|
resp, b = doRequest(t, http.MethodGet, base+"/crates/e2e-crate/e2e-crate-0.1.0.crate", nil, "")
|
|
if resp.StatusCode != http.StatusOK || !bytes.Equal(b, crate) {
|
|
t.Fatalf("download: status %d", resp.StatusCode)
|
|
}
|
|
|
|
if resp, b := doRequest(t, http.MethodDelete, base+"/api/v1/crates/e2e-crate/0.1.0/yank", nil, ""); resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("yank: status %d: %s", resp.StatusCode, b)
|
|
}
|
|
if _, b := doRequest(t, http.MethodGet, base+"/e2/e-/e2e-crate", nil, ""); !strings.Contains(string(b), `"yanked":true`) {
|
|
t.Fatalf("index after yank: %s", b)
|
|
}
|
|
}
|