From 608e64573d59e6eff5d24fbf698735df1f95f1fe Mon Sep 17 00:00:00 2001 From: Jesse Simpson Date: Sat, 26 Apr 2025 16:49:14 -0400 Subject: [PATCH] test: create tests for chart uploader Signed-off-by: Jesse Simpson --- pkg/uploader/chart_uploader_test.go | 147 ++++++++++++++++++++++ pkg/uploader/testdata/test-0.1.0.tgz | Bin 0 -> 1262 bytes pkg/uploader/testdata/test-0.1.0.tgz.prov | 6 + 3 files changed, 153 insertions(+) create mode 100644 pkg/uploader/chart_uploader_test.go create mode 100644 pkg/uploader/testdata/test-0.1.0.tgz create mode 100644 pkg/uploader/testdata/test-0.1.0.tgz.prov diff --git a/pkg/uploader/chart_uploader_test.go b/pkg/uploader/chart_uploader_test.go new file mode 100644 index 000000000..88211a28e --- /dev/null +++ b/pkg/uploader/chart_uploader_test.go @@ -0,0 +1,147 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package uploader + +import ( + "crypto/sha256" + "fmt" + "helm.sh/helm/v4/pkg/cli" + "helm.sh/helm/v4/pkg/pusher" + "helm.sh/helm/v4/pkg/registry" + "net/http" + "net/http/httptest" + "net/url" + "strconv" + "strings" + "testing" +) + +func TestChartUploader_UploadTo_Happy(t *testing.T) { + shasum := "" + var content []byte + contentSize := 0 + uploadSessionId := "c6ce3ba4-788f-4e10-93ed-ff77d35c6851" + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == "HEAD" { + w.WriteHeader(http.StatusNotFound) + } else if r.Method == "POST" && r.URL.Path == "/v2/test/blobs/uploads/" { + w.Header().Set("Location", "/v2/test/blobs/uploads/"+uploadSessionId) + w.WriteHeader(http.StatusAccepted) + } else if r.Method == "PUT" && r.URL.Path == "/v2/test/blobs/uploads/"+uploadSessionId { + w.Header().Set("Location", "/v2/test/blobs/sha256:irrelevant") + w.WriteHeader(http.StatusCreated) + } else if r.Method == "PUT" && strings.HasPrefix(r.URL.Path, "/v2/test/manifests/sha256:") { + content = make([]byte, r.ContentLength) + r.Body.Read(content) + h := sha256.New() + h.Write(content) + shasumBuilder := strings.Builder{} + fmt.Fprintf(&shasumBuilder, "%x", h.Sum(nil)) + shasum = shasumBuilder.String() + contentSize = len(content) + w.Header().Set("Location", "/v2/test/manifests/sha256:"+shasum) + w.WriteHeader(http.StatusCreated) + } else if r.Method == "GET" && r.URL.Path == "/v2/test/manifests/sha256:"+shasum { + w.Header().Set("Content-Length", strconv.Itoa(contentSize)) + w.Header().Set("Content-Type", "application/vnd.oci.image.manifest.v1+json") + w.Header().Set("Docker-Content-Digest", "sha256:"+shasum) + _, err := fmt.Fprint(w, string(content)) + if err != nil { + t.Errorf("%s", err) + } + } else if r.Method == "PUT" && r.URL.Path == "/v2/test/manifests/0.1.0" { + w.Header().Set("Docker-Content-Digest", "sha256:"+shasum) + w.Header().Set("Content-Length", strconv.Itoa(contentSize)) + w.Header().Set("Location", "/v2/test/manifests/sha256:"+shasum) + w.WriteHeader(http.StatusCreated) + } + })) + defer srv.Close() + + envSettings := cli.EnvSettings{} + pushers := pusher.All(&envSettings) + + u, _ := url.ParseRequestURI(srv.URL) + ociReplacedUrl := strings.Replace(u.String(), "http", "oci", 1) + + srvClient := srv.Client() + client, _ := registry.NewClient(registry.ClientOptHTTPClient(srvClient)) + uploader := ChartUploader{ + Pushers: pushers, + RegistryClient: client, + Options: []pusher.Option{pusher.WithPlainHTTP(true)}, + } + + err := uploader.UploadTo("testdata/test-0.1.0.tgz", ociReplacedUrl+"") + if err != nil { + fmt.Println(err) + t.Errorf("Expected push to succeed but got error") + } +} + +func TestChartUploader_UploadTo_InvalidChartUrlFormat(t *testing.T) { + envSettings := cli.EnvSettings{} + + pushers := pusher.All(&envSettings) + + uploader := ChartUploader{ + Pushers: pushers, + } + + err := uploader.UploadTo("main", "://invalid.com") + const expectedError = "invalid chart URL format" + fmt.Println(err.Error()) + if !strings.Contains(err.Error(), expectedError) { + t.Errorf("Expected error to contain '" + expectedError + "'") + } +} + +func TestChartUploader_UploadTo_SchemePrefixMissingFromRemote(t *testing.T) { + envSettings := cli.EnvSettings{} + + pushers := pusher.All(&envSettings) + + uploader := ChartUploader{ + Pushers: pushers, + } + + err := uploader.UploadTo("main", "invalid.com") + const expectedError = "scheme prefix missing from remote" + + fmt.Println(err.Error()) + if !strings.Contains(err.Error(), expectedError) { + t.Errorf("Expected error to contain '" + expectedError + "'") + } +} + +func TestChartUploader_UploadTo_SchemeNotRegistered(t *testing.T) { + envSettings := cli.EnvSettings{} + + pushers := pusher.All(&envSettings) + + uploader := ChartUploader{ + Pushers: pushers, + } + + err := uploader.UploadTo("main", "grpc://invalid.com") + const expectedError = "scheme \"grpc\" not supported" + + fmt.Println(err.Error()) + if !strings.Contains(err.Error(), expectedError) { + t.Errorf("Expected error to contain '" + expectedError + "'") + } +} diff --git a/pkg/uploader/testdata/test-0.1.0.tgz b/pkg/uploader/testdata/test-0.1.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..933e2c816a516e4601d0516e91e23282da58e5fb GIT binary patch literal 1262 zcmVDc zVQyr3R8em|NM&qo0PI)WZrer^_O+g3e&tpnDcOkw{xkvCDUcQ^k^-%PT#m?*IL#iI z-C5a&?RPJBsgvCV3EDbAP|ppQvpeVcmO~*g`B{ffvMbc;;323eisJdvQF<0dasOEq z&!z{{qvPXev*W{J`uw1n&Zf_c11KKEn|ln$e^YY zVpEJ(8+MURvtsnE9etz+p@jbxszCn1E`ZPA|L|xwyN~~)+2JGpzXl15q7q(_QWh?( zQ|$#dGa7=ImPRcKm2lcScrk%lF?%**BhHramXsnR+@{b?_mep1^{_l2KsAf;54k#BsxvBxM3Z zy0;EI3!sh+G(s7?w1yg>0E*}2>~=pX-53Q=x+j-GMY=vELumH&YaVO@dC97rbPc~? zaO|O1*pNd3Qp5`~Ehw@X{2DmrXlskS#Na*lOi{B!-B{O?gT6yY;_yz`N#zB5o9;CF!qDfU^F_w^{YUpK2?5w_&uHLXa&tjfFDuw_-9ni-%{ zT)(!C^xEgvsynUFSmUV?l0Xiy<(_@RW|{JkRk`AQMW>2WZ|qW|hiX#*$3FP2M3qMu z;$p6B^ZrAyLUq-Dp(}s&1kQPdI(X2yG?>AeLmv~S8E~B#z~~*NaxDX;jN#Bi9j>^Is)CDv4GuJVk6T=<`*yN{2gW6o$epuz*;jk6HebvLd>b;|Sz~czuNjEs$ zO#$ILX>Qr~3a?5?;r&1HF1VGhgu|lfF9%LXyzHce7i-RKvXRtQc{DLvSS#d8IJ5ng zi-*(K3+C7Yw}h~;E`IqmH1P*$0za81`;QH}Y5t3sl0qS$$Jc*-4*cBz-*It&{yQp; zk00m1uR)z?wH{dh_wvozZ|~mz2$7cn8yBF^EKkN{#sliB2-oceph+;H$CI3lgDjrD z7;iVzY*}AlLv}v=U?c|I-d6drwYx^ldvK&q#$K)z`Ho1&>#t$rWR3Sby}ohW3wYO@ zjE8mhhacBfKD?~`%y*7faV*=4chisi)J?ZX`nsCeKU~4yxnU|!2j}(vMx2flyWfak zUxV0psMYpNv=29N*wb$vE%*|~H)FT~!=@!8a0IuvJKKB8hZ`)a?>Av>VyW_>PT#tN Y9_f)D>3gL=0{{U3|HlH~$^aGs0GR-8$^ZZW literal 0 HcmV?d00001 diff --git a/pkg/uploader/testdata/test-0.1.0.tgz.prov b/pkg/uploader/testdata/test-0.1.0.tgz.prov new file mode 100644 index 000000000..15b57c8bb --- /dev/null +++ b/pkg/uploader/testdata/test-0.1.0.tgz.prov @@ -0,0 +1,6 @@ +apiVersion: v2 +name: test +version: 0.1.0 + +files: + test-0.1.0.tgz: sha256:40ac18ea704177f883dab4a4fe7f8b27de9f79633c64649ddbc3a91011ed7be0