Skip to content

Commit

Permalink
Add tests and fix bugs
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Chacin <[email protected]>
  • Loading branch information
pablochacin committed Jun 17, 2024
1 parent afdc6de commit 5678076
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 48 deletions.
2 changes: 1 addition & 1 deletion catalog.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"k6": {"module": "go.k6.io/k6", "versions": ["v0.50.0", "v0.51.0"]},
"k6/x/kubernetes": {"module": "github.com/grafana/xk6-kubernetes", "versions": ["v0.8.0"]},
"k6/x/kubernetes": {"module": "github.com/grafana/xk6-kubernetes", "versions": ["v0.8.0","v0.9.0"]},
"k6/x/output-kafka": {"module": "github.com/grafana/xk6-output-kafka", "versions": ["v0.7.0"]}
}
17 changes: 8 additions & 9 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

"github.com/grafana/k6catalog"
"github.com/grafana/k6foundry"
"golang.org/x/exp/maps"
)

const (
Expand Down Expand Up @@ -107,6 +106,8 @@ func (b *buildsrv) Build(
return Artifact{}, fmt.Errorf("invalid platform %w", err)
}

// sort dependencies to ensure idempotence of build
sort.Slice(deps, func(i, j int) bool { return deps[i].Name < deps[j].Name })
resolved := map[string]string{}

k6Mod, err := b.catalog.Resolve(ctx, k6catalog.Dependency{Name: k6Dep, Constrains: k6Constrains})
Expand All @@ -125,16 +126,14 @@ func (b *buildsrv) Build(
resolved[d.Name] = m.Version
}

sorted := maps.Keys(resolved)
sort.Strings(sorted)

// generate id form sorted list of dependencies
hash := sha1.New() //nolint:gosec
hash.Sum([]byte(platform))
for _, d := range sorted {
hash.Sum([]byte(fmt.Sprintf("%s:%s", d, resolved[d])))
hashData := bytes.Buffer{}
hashData.WriteString(platform)
hashData.WriteString(fmt.Sprintf(":k6%s", k6Mod.Version))
for _, d := range deps {
hashData.WriteString(fmt.Sprintf(":%s%s", d, resolved[d.Name]))
}
id := fmt.Sprintf("%x", hash.Sum(nil))
id := fmt.Sprintf("%x", sha1.Sum(hashData.Bytes())) //nolint:gosec

artifactObject, err := b.cache.Get(ctx, id)
if err == nil {
Expand Down
230 changes: 192 additions & 38 deletions service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package k6build
import (
"context"
"errors"
"fmt"
"net/http/httptest"
"testing"

Expand All @@ -14,9 +15,9 @@ import (
"github.com/google/go-cmp/cmp/cmpopts"
)

func TestBuild(t *testing.T) {
t.Parallel()
func dependencyComp(a, b Module) bool { return a.Path < b.Path }

func setupBuildService(cacheDir string) (BuildService, error) {
modules := []struct {
path string
version string
Expand Down Expand Up @@ -54,7 +55,7 @@ func TestBuild(t *testing.T) {
for _, m := range modules {
err := proxy.AddModVersion(m.path, m.version, m.source)
if err != nil {
t.Fatalf("setup %v", err)
return nil, fmt.Errorf("setup %w", err)
}
}

Expand All @@ -72,50 +73,63 @@ func TestBuild(t *testing.T) {

builder, err := k6foundry.NewNativeBuilder(context.Background(), opts)
if err != nil {
t.Fatalf("setting up test builder %v", err)
return nil, fmt.Errorf("setting up test builder %w", err)
}

catalog, err := k6catalog.NewCatalogFromJSON("testdata/catalog.json")
if err != nil {
t.Fatalf("setting up test builder %v", err)
return nil, fmt.Errorf("setting up test builder %w", err)
}

cache, err := NewFileCache(cacheDir)
if err != nil {
return nil, fmt.Errorf("creating temp cache %w", err)
}

buildsrv := NewBuildService(catalog, builder, cache)

return buildsrv, nil
}

func TestDependencyResolution(t *testing.T) {
t.Parallel()

testCases := []struct {
title string
k6Constrains string
deps []Dependency
expectErr error
expect Artifact
title string
k6 string
deps []Dependency
expectErr error
expect Artifact
}{
{
title: "build k6 v0.1.0 ",
k6Constrains: "v0.1.0",
deps: []Dependency{},
expectErr: nil,
title: "build k6 v0.1.0 ",
k6: "v0.1.0",
deps: []Dependency{},
expectErr: nil,
expect: Artifact{
Dependencies: map[string]string{"k6": "v0.1.0"},
},
},
{
title: "build k6 >v0.1.0",
k6Constrains: ">v0.1.0",
deps: []Dependency{},
expectErr: nil,
title: "build k6 >v0.1.0",
k6: ">v0.1.0",
deps: []Dependency{},
expectErr: nil,
expect: Artifact{
Dependencies: map[string]string{"k6": "v0.2.0"},
},
},
{
title: "build unsatisfied k6 constrain (>v0.2.0)",
k6Constrains: ">v0.2.0",
deps: []Dependency{},
expectErr: k6catalog.ErrCannotSatisfy,
title: "build unsatisfied k6 constrain (>v0.2.0)",
k6: ">v0.2.0",
deps: []Dependency{},
expectErr: k6catalog.ErrCannotSatisfy,
},
{
title: "build k6 v0.1.0 exact dependency constraint",
k6Constrains: "v0.1.0",
deps: []Dependency{{Name: "k6/x/ext", Constraints: "v0.1.0"}},
expectErr: nil,
title: "build k6 v0.1.0 exact dependency constraint",
k6: "v0.1.0",
deps: []Dependency{{Name: "k6/x/ext", Constraints: "v0.1.0"}},
expectErr: nil,
expect: Artifact{
Dependencies: map[string]string{
"k6": "v0.1.0",
Expand All @@ -124,10 +138,10 @@ func TestBuild(t *testing.T) {
},
},
{
title: "build k6 v0.1.0 unsatisfied dependency constrain",
k6Constrains: "v0.1.0",
deps: []Dependency{{Name: "k6/x/ext", Constraints: ">v0.2.0"}},
expectErr: k6catalog.ErrCannotSatisfy,
title: "build k6 v0.1.0 unsatisfied dependency constrain",
k6: "v0.1.0",
deps: []Dependency{{Name: "k6/x/ext", Constraints: ">v0.2.0"}},
expectErr: k6catalog.ErrCannotSatisfy,
},
}

Expand All @@ -136,17 +150,15 @@ func TestBuild(t *testing.T) {
t.Run(tc.title, func(t *testing.T) {
t.Parallel()

cache, err := NewTempFileCache()
buildsrv, err := setupBuildService(t.TempDir())
if err != nil {
t.Fatalf("creating temp cache %v", err)
t.Fatalf("test setup %v", err)
}

buildsrv := NewBuildService(catalog, builder, cache)

artifact, err := buildsrv.Build(
context.TODO(),
"linux/amd64",
tc.k6Constrains,
tc.k6,
tc.deps,
)

Expand All @@ -159,12 +171,154 @@ func TestBuild(t *testing.T) {
return
}

less := func(a, b Module) bool { return a.Path < b.Path }

diff := cmp.Diff(tc.expect.Dependencies, artifact.Dependencies, cmpopts.SortSlices(less))
diff := cmp.Diff(tc.expect.Dependencies, artifact.Dependencies, cmpopts.SortSlices(dependencyComp))
if diff != "" {
t.Fatalf("dependencies don't match: %s\n", diff)
}
})
}
}

func TestIdempotentBuild(t *testing.T) {
t.Parallel()

buildsrv, err := setupBuildService(t.TempDir())
if err != nil {
t.Fatalf("test setup %v", err)
}

artifact, err := buildsrv.Build(
context.TODO(),
"linux/amd64",
"v0.1.0",
[]Dependency{
{Name: "k6/x/ext", Constraints: "v0.1.0"},
{Name: "k6/x/ext2", Constraints: "v0.1.0"},
},
)
if err != nil {
t.Fatalf("test setup %v", err)
}

t.Run("should rebuild same artifact", func(t *testing.T) {
t.Parallel()

testCases := []struct {
title string
platform string
k6 string
deps []Dependency
}{
{
title: "same dependencies",
platform: "linux/amd64",
k6: "v0.1.0",
deps: []Dependency{
{Name: "k6/x/ext", Constraints: "v0.1.0"},
{Name: "k6/x/ext2", Constraints: "v0.1.0"},
},
},
{
title: "different order of dependencies",
platform: "linux/amd64",
k6: "v0.1.0",
deps: []Dependency{
{Name: "k6/x/ext2", Constraints: "v0.1.0"},
{Name: "k6/x/ext", Constraints: "v0.1.0"},
},
},
}

for _, tc := range testCases {
t.Run(tc.title, func(t *testing.T) {
t.Parallel()

rebuild, err := buildsrv.Build(
context.TODO(),
tc.platform,
tc.k6,
tc.deps,
)
if err != nil {
t.Fatalf("unexpected %v", err)
}

if artifact.ID != rebuild.ID {
t.Fatalf("artifact ID don't match")
}

diff := cmp.Diff(artifact.Dependencies, rebuild.Dependencies, cmpopts.SortSlices(dependencyComp))
if diff != "" {
t.Fatalf("dependencies don't match: %s\n", diff)
}
})
}
})

t.Run("should build a different artifact", func(t *testing.T) {
t.Parallel()

testCases := []struct {
title string
platform string
k6 string
deps []Dependency
}{
{
title: "different k6 versions",
platform: "linux/amd64",
k6: "v0.2.0",
deps: []Dependency{
{Name: "k6/x/ext", Constraints: "v0.1.0"},
{Name: "k6/x/ext2", Constraints: "v0.1.0"},
},
},
{
title: "different dependency versions",
platform: "linux/amd64",
k6: "v0.1.0",
deps: []Dependency{
{Name: "k6/x/ext", Constraints: "v0.2.0"},
{Name: "k6/x/ext2", Constraints: "v0.1.0"},
},
},
{
title: "different dependencies",
platform: "linux/amd64",
k6: "v0.1.0",
deps: []Dependency{
{Name: "k6/x/ext", Constraints: "v0.1.0"},
},
},
{
title: "different platform",
platform: "linux/arm64",
k6: "v0.1.0",
deps: []Dependency{
{Name: "k6/x/ext", Constraints: "v0.1.0"},
{Name: "k6/x/ext2", Constraints: "v0.1.0"},
},
},
}

for _, tc := range testCases {
t.Run(tc.title, func(t *testing.T) {
t.Parallel()

rebuild, err := buildsrv.Build(
context.TODO(),
tc.platform,
tc.k6,
tc.deps,
)
if err != nil {
t.Fatalf("unexpected %v", err)
}

if artifact.ID == rebuild.ID {
t.Fatalf("should had built a different artifact")
}
})
}
})
}

0 comments on commit 5678076

Please sign in to comment.