Skip to content

Commit

Permalink
Merge pull request #1202 from jonjohnsonjr/e2e
Browse files Browse the repository at this point in the history
Make unit tests faster
  • Loading branch information
jonjohnsonjr committed May 11, 2024
2 parents 1b54c78 + 3ef4b39 commit 2fbc085
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 161 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ lint: checkfmt setup-golangci-lint ## Run linters and checks like golangci-lint
test: melange ## Run go test
# build test package
./melange build --generate-index=false pkg/sca/testdata/go-fips-bin/go-fips-bin.yaml --arch=`uname -m` --source-dir=pkg/sca/testdata/go-fips-bin/ --out-dir pkg/sca/testdata/go-fips-bin/packages/ --log-level error
go test ./... -race
go test -tags e2e ./... -race

.PHONY: clean
clean: ## Clean the workspace
Expand Down
18 changes: 5 additions & 13 deletions pkg/convert/gem/gem.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,9 @@ func (c *GemContext) getGemMeta(ctx context.Context, gemURI string) (GemMeta, er
return GemMeta{}, fmt.Errorf("%d when getting %s: %w", resp.StatusCode, gemURI, err)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return GemMeta{}, fmt.Errorf("reading body: %w", err)
}

var g GemMeta
err = json.Unmarshal(body, &g)
if err != nil {
return GemMeta{}, fmt.Errorf("unmarshaling gem metadata: %w", err)
if err := json.NewDecoder(resp.Body).Decode(&g); err != nil {
return GemMeta{}, fmt.Errorf("decoding gem metadata: %w", err)
}

// Try to set the right Uri to the repo, sometimes gems use homepage instead of source code.
Expand Down Expand Up @@ -377,13 +371,11 @@ func (c *GemContext) getGemArtifactSHA(ctx context.Context, artifactURI string)
return "", fmt.Errorf("%d when getting %s", resp.StatusCode, artifactURI)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading body: %w", err)
h256 := sha256.New()
if _, err := io.Copy(h256, resp.Body); err != nil {
return "", fmt.Errorf("hashing %s: %w", artifactURI, err)
}

h256 := sha256.New()
h256.Write(body)
return fmt.Sprintf("%x", h256.Sum(nil)), nil
}

Expand Down
28 changes: 16 additions & 12 deletions pkg/convert/gem/gem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

apkotypes "chainguard.dev/apko/pkg/build/types"
"chainguard.dev/melange/pkg/config"
rlhttp "chainguard.dev/melange/pkg/http"
"github.com/chainguard-dev/clog"
"github.com/chainguard-dev/clog/slogtest"
"github.com/stretchr/testify/assert"
Expand All @@ -23,6 +24,16 @@ const (
archiveDir = testDataDir + "/archive"
)

func testGemContext(base string) *GemContext {
return &GemContext{
Client: &rlhttp.RLHTTPClient{
Client: http.DefaultClient,
},
ToGenerate: make(map[string]GemMeta),
BaseURIFormat: base,
}
}

func TestGetGemMeta(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
Expand All @@ -48,8 +59,7 @@ func TestGetGemMeta(t *testing.T) {
// Iterate through all gem metadata files and ensure the server response is
// the same as the file.
for _, gem := range gems {
gemctx, err := New()
assert.NoError(t, err)
gemctx := testGemContext(server.URL + "/%s.json")

// Read the gem meta into
data, err := os.ReadFile(filepath.Join(gemMetaDir, gem.Name()))
Expand Down Expand Up @@ -93,10 +103,7 @@ func TestFindDependencies(t *testing.T) {
assert.NoError(t, err)
assert.NotEmpty(t, gems)

gemctx, err := New()
assert.NoError(t, err)

gemctx.BaseURIFormat = server.URL + "/%s.json"
gemctx := testGemContext(server.URL + "/%s.json")
gemctx.ToCheck = []string{"async"}

// Build list of dependencies
Expand Down Expand Up @@ -132,8 +139,7 @@ func TestGenerateManifest(t *testing.T) {
}))
defer server.Close()

gemctx, err := New()
assert.NoError(t, err)
gemctx := testGemContext(server.URL + "/%s.json")

gemctx.RubyVersion = DefaultRubyVersion

Expand Down Expand Up @@ -240,8 +246,7 @@ func TestGeneratePackage(t *testing.T) {
},
}

gemctx, err := New()
assert.NoError(t, err)
gemctx := testGemContext("unused")

got := gemctx.generatePackage(g)
assert.Equal(t, expected, got)
Expand All @@ -265,8 +270,7 @@ func TestGenerateEnvironment(t *testing.T) {
},
}

gemctx, err := New()
assert.NoError(t, err)
gemctx := testGemContext("unused")

// Add additionalReposities and additionalKeyrings
gemctx.AdditionalRepositories = []string{"https://packages.wolfi.dev/os", "local /github/workspace/packages"}
Expand Down
96 changes: 96 additions & 0 deletions pkg/convert/python/e2e_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2022 Chainguard, Inc.
//
// 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.

//go:build e2e
// +build e2e

package python

import (
"fmt"
"strings"
"testing"

"github.com/chainguard-dev/clog/slogtest"
"github.com/stretchr/testify/assert"
)

// This test downloads 10MB from files.pythonhosted.org (twice).
// I am not in a position to untangle it, so we're going to gate this behind an e2e build tag that only runs in CI.
func TestGenerateManifest(t *testing.T) {
ctx := slogtest.TestContextWithLogger(t)

for i := range versions {
pythonctxs, err := SetupContext(versions[i])
assert.NoError(t, err)

// botocore ctx
pythonctx := pythonctxs[0]
// Add additionalReposities and additionalKeyrings
pythonctx.AdditionalRepositories = []string{"https://packages.wolfi.dev/os"}
pythonctx.AdditionalKeyrings = []string{"https://packages.wolfi.dev/os/wolfi-signing.rsa.pub"}

got, err := pythonctx.generateManifest(ctx, pythonctx.Package, pythonctx.PackageVersion, nil, nil)
assert.NoError(t, err)

// Check Package
assert.Equal(t, got.Package.Name, "py"+versions[i]+"-botocore")
assert.Equal(t, got.Package.Version, "1.29.78")
assert.EqualValues(t, got.Package.Epoch, 0)
assert.Equal(t, got.Package.Description, "Low-level, data-driven core of boto 3.")
assert.Equal(t, got.Package.Dependencies.Runtime, []string{"py" + versions[i] + "-jmespath", "py" + versions[i] + "-python-dateutil", "py" + versions[i] + "-urllib3", "python-" + versions[i]})

// Check Package.Copyright
assert.Equal(t, len(got.Package.Copyright), 1)
assert.Equal(t, got.Package.Copyright[0].License, "Apache License 2.0")

// Check Environment
assert.Equal(t, got.Environment.Contents.Packages, []string{
"build-base",
"busybox",
"ca-certificates-bundle",
"wolfi-base",
})

// Check Pipeline
assert.Equal(t, len(got.Pipeline), 3)

// Check Pipeline - fetch
assert.Equal(t, got.Pipeline[0].Uses, "fetch")

releases, ok := pythonctx.Package.Releases[pythonctx.PackageVersion]

// If the key exists
assert.True(t, ok)

var release Release
for _, r := range releases {
if r.PackageType == "sdist" {
release = r
}
}
assert.NotEmpty(t, release)
assert.Equal(t, "https://files.pythonhosted.org/packages/8f/34/d4bcefeabfb8e4b46157e84ea55c3ecc7399d5f9a3454728e1d0d5f9cb83/botocore-"+pythonctx.PackageVersion+".tar.gz", release.URL)

tempURI := fmt.Sprintf("https://files.pythonhosted.org/packages/source/%c/%s/%s-%s.tar.gz", pythonctx.PackageName[0], pythonctx.PackageName, pythonctx.PackageName, pythonctx.PackageVersion)
assert.Equal(t, got.Pipeline[0].With, map[string]string{
"expected-sha256": "2bee6ed037590ef1e4884d944486232871513915f12a8590c63e3bb6046479bf",
"uri": strings.ReplaceAll(tempURI, pythonctx.PackageVersion, "${{package.version}}"),
})

// Check Pipeline - runs
assert.Equal(t, got.Pipeline[1].Uses, "python/build-wheel")
assert.Equal(t, got.Pipeline[2].Uses, "strip")
}
}
11 changes: 3 additions & 8 deletions pkg/convert/python/pypi.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
Expand Down Expand Up @@ -155,14 +154,10 @@ func (p *PackageIndex) packageReq(ctx context.Context, endpoint string) (*Packag
err := fmt.Errorf("%d when getting %s: %w", resp.StatusCode, url, cause)
return nil, err
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

err = json.Unmarshal(data, &pkg)
if err != nil {
if err := json.NewDecoder(resp.Body).Decode(&pkg); err != nil {
return nil, err
}
return pkg, err

return pkg, nil
}
71 changes: 4 additions & 67 deletions pkg/convert/python/python_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func TestGetPythonMeta(t *testing.T) {

pythonctx, err := New("botocore")
pythonctx.PackageIndex = NewPackageIndex("https://pypi.org")
pythonctx.PackageIndex.Client.Ratelimiter = nil // don't rate limit our unit tests
assert.NoError(t, err)

var expected Package
Expand Down Expand Up @@ -106,6 +107,7 @@ func TestFindDependencies(t *testing.T) {

for _, pythonctx := range pythonctxs {
pythonctx.PackageIndex.url = server.URL
pythonctx.PackageIndex.Client.Ratelimiter = nil // don't rate limit our unit tests
p, err := pythonctx.PackageIndex.Get(slogtest.TestContextWithLogger(t), pythonctx.PackageName, pythonctx.PackageVersion)
assert.NoError(t, err)
pythonctx.ToCheck = append(pythonctx.ToCheck, p.Info.Name)
Expand Down Expand Up @@ -133,73 +135,6 @@ func TestFindDependencies(t *testing.T) {
}
}

func TestGenerateManifest(t *testing.T) {
ctx := slogtest.TestContextWithLogger(t)

for i := range versions {
pythonctxs, err := SetupContext(versions[i])
assert.NoError(t, err)

// botocore ctx
pythonctx := pythonctxs[0]
// Add additionalReposities and additionalKeyrings
pythonctx.AdditionalRepositories = []string{"https://packages.wolfi.dev/os"}
pythonctx.AdditionalKeyrings = []string{"https://packages.wolfi.dev/os/wolfi-signing.rsa.pub"}

got, err := pythonctx.generateManifest(ctx, pythonctx.Package, pythonctx.PackageVersion, nil, nil)
assert.NoError(t, err)

// Check Package
assert.Equal(t, got.Package.Name, "py"+versions[i]+"-botocore")
assert.Equal(t, got.Package.Version, "1.29.78")
assert.EqualValues(t, got.Package.Epoch, 0)
assert.Equal(t, got.Package.Description, "Low-level, data-driven core of boto 3.")
assert.Equal(t, got.Package.Dependencies.Runtime, []string{"py" + versions[i] + "-jmespath", "py" + versions[i] + "-python-dateutil", "py" + versions[i] + "-urllib3", "python-" + versions[i]})

// Check Package.Copyright
assert.Equal(t, len(got.Package.Copyright), 1)
assert.Equal(t, got.Package.Copyright[0].License, "Apache License 2.0")

// Check Environment
assert.Equal(t, got.Environment.Contents.Packages, []string{
"build-base",
"busybox",
"ca-certificates-bundle",
"wolfi-base",
})

// Check Pipeline
assert.Equal(t, len(got.Pipeline), 3)

// Check Pipeline - fetch
assert.Equal(t, got.Pipeline[0].Uses, "fetch")

releases, ok := pythonctx.Package.Releases[pythonctx.PackageVersion]

// If the key exists
assert.True(t, ok)

var release Release
for _, r := range releases {
if r.PackageType == "sdist" {
release = r
}
}
assert.NotEmpty(t, release)
assert.Equal(t, "https://files.pythonhosted.org/packages/8f/34/d4bcefeabfb8e4b46157e84ea55c3ecc7399d5f9a3454728e1d0d5f9cb83/botocore-"+pythonctx.PackageVersion+".tar.gz", release.URL)

tempURI := fmt.Sprintf("https://files.pythonhosted.org/packages/source/%c/%s/%s-%s.tar.gz", pythonctx.PackageName[0], pythonctx.PackageName, pythonctx.PackageName, pythonctx.PackageVersion)
assert.Equal(t, got.Pipeline[0].With, map[string]string{
"expected-sha256": "2bee6ed037590ef1e4884d944486232871513915f12a8590c63e3bb6046479bf",
"uri": strings.ReplaceAll(tempURI, pythonctx.PackageVersion, "${{package.version}}"),
})

// Check Pipeline - runs
assert.Equal(t, got.Pipeline[1].Uses, "python/build-wheel")
assert.Equal(t, got.Pipeline[2].Uses, "strip")
}
}

// TestGeneratePackage tests when a gem has multiple licenses
func TestGeneratePackage(t *testing.T) {
for i := range versions {
Expand Down Expand Up @@ -236,6 +171,7 @@ func SetupContext(version string) ([]*PythonContext, error) {
}

botocorepythonctx.PackageIndex = NewPackageIndex("https://pypi.org/")
botocorepythonctx.PackageIndex.Client.Ratelimiter = nil // don't rate limit our unit tests
botocorepythonctx.PackageName = "botocore"
botocorepythonctx.PackageVersion = "1.29.78"
botocorepythonctx.PythonVersion = version
Expand All @@ -261,6 +197,7 @@ func SetupContext(version string) ([]*PythonContext, error) {
}

jsonschemapythonctx.PackageIndex = NewPackageIndex("https://pypi.org/")
jsonschemapythonctx.PackageIndex.Client.Ratelimiter = nil // don't rate limit our unit tests
jsonschemapythonctx.PackageName = "jsonschema"
jsonschemapythonctx.PackageVersion = "4.17.3"
jsonschemapythonctx.PythonVersion = version
Expand Down
15 changes: 5 additions & 10 deletions pkg/convert/relmon/release_monitoring.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"time"

Expand Down Expand Up @@ -40,7 +39,7 @@ type MonitorFinder struct {
}

func (mf *MonitorFinder) FindMonitor(ctx context.Context, pkg string) (*Item, error) {
var Items *Items
var items *Items
url := fmt.Sprintf(searchFmt, pkg)
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
Expand All @@ -51,23 +50,19 @@ func (mf *MonitorFinder) FindMonitor(ctx context.Context, pkg string) (*Item, er
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
cause := errors.New("http status return was not 200")
err := fmt.Errorf("%d when getting %s: %w", resp.StatusCode, url, cause)
return nil, err
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}

err = json.Unmarshal(data, &Items)
if err != nil {
if err := json.NewDecoder(resp.Body).Decode(&items); err != nil {
return nil, err
}
if len(Items.Items) == 0 {
if len(items.Items) == 0 {
return nil, errors.New("no items found")
}
return &Items.Items[0], nil
return &items.Items[0], nil
}

0 comments on commit 2fbc085

Please sign in to comment.