chore(testutil): extract testutil.CreateZip and testutil.CreateTar helpers (#15540)

Extracts `testutil.CreateTar` and `testutil.CreateZip` test helpers.
This commit is contained in:
Cian Johnston
2024-11-18 09:17:04 +00:00
committed by GitHub
parent f9d6698384
commit 4719d2406f
6 changed files with 89 additions and 116 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/provisionersdk/proto"
"github.com/coder/coder/v2/testutil"
)
func TestParse(t *testing.T) {
@ -380,7 +381,7 @@ func TestParse(t *testing.T) {
t.Parallel()
session := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, testCase.Files),
TemplateSourceArchive: testutil.CreateTar(t, testCase.Files),
})
err := session.Send(&proto.Request{Type: &proto.Request_Parse{Parse: &proto.ParseRequest{}}})

View File

@ -3,8 +3,6 @@
package terraform_test
import (
"archive/tar"
"bytes"
"context"
"encoding/json"
"errors"
@ -28,6 +26,7 @@ import (
"github.com/coder/coder/v2/provisioner/terraform"
"github.com/coder/coder/v2/provisionersdk"
"github.com/coder/coder/v2/provisionersdk/proto"
"github.com/coder/coder/v2/testutil"
)
type provisionerServeOptions struct {
@ -78,39 +77,6 @@ func setupProvisioner(t *testing.T, opts *provisionerServeOptions) (context.Cont
return ctx, api
}
func makeTar(t *testing.T, files map[string]string) []byte {
t.Helper()
var buffer bytes.Buffer
writer := tar.NewWriter(&buffer)
addedDirs := make(map[string]bool)
for name, content := range files {
// Add parent directories if they don't exist
dir := filepath.Dir(name)
if dir != "." && !addedDirs[dir] {
err := writer.WriteHeader(&tar.Header{
Name: dir + "/", // Directory names must end with /
Mode: 0o755,
Typeflag: tar.TypeDir,
})
require.NoError(t, err)
addedDirs[dir] = true
}
err := writer.WriteHeader(&tar.Header{
Name: name,
Size: int64(len(content)),
Mode: 0o644,
})
require.NoError(t, err)
_, err = writer.Write([]byte(content))
require.NoError(t, err)
}
err := writer.Flush()
require.NoError(t, err)
return buffer.Bytes()
}
func configure(ctx context.Context, t *testing.T, client proto.DRPCProvisionerClient, config *proto.Config) proto.DRPCProvisioner_SessionClient {
t.Helper()
sess, err := client.Session(ctx)
@ -200,7 +166,7 @@ func TestProvision_Cancel(t *testing.T) {
binaryPath: binPath,
})
sess := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, nil),
TemplateSourceArchive: testutil.CreateTar(t, nil),
})
err = sendPlan(sess, proto.WorkspaceTransition_START)
@ -271,7 +237,7 @@ func TestProvision_CancelTimeout(t *testing.T) {
})
sess := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, nil),
TemplateSourceArchive: testutil.CreateTar(t, nil),
})
// provisioner requires plan before apply, so test cancel with plan.
@ -360,7 +326,7 @@ func TestProvision_TextFileBusy(t *testing.T) {
})
sess := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, nil),
TemplateSourceArchive: testutil.CreateTar(t, nil),
})
err = sendPlan(sess, proto.WorkspaceTransition_START)
@ -811,7 +777,7 @@ func TestProvision(t *testing.T) {
ctx, api := setupProvisioner(t, nil)
sess := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, testCase.Files),
TemplateSourceArchive: testutil.CreateTar(t, testCase.Files),
})
planRequest := &proto.Request{Type: &proto.Request_Plan{Plan: &proto.PlanRequest{
@ -925,7 +891,7 @@ func TestProvision_ExtraEnv(t *testing.T) {
ctx, api := setupProvisioner(t, nil)
sess := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, map[string]string{"main.tf": `resource "null_resource" "A" {}`}),
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{"main.tf": `resource "null_resource" "A" {}`}),
})
err := sendPlan(sess, proto.WorkspaceTransition_START)
@ -975,7 +941,7 @@ func TestProvision_SafeEnv(t *testing.T) {
ctx, api := setupProvisioner(t, nil)
sess := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, map[string]string{"main.tf": echoResource}),
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{"main.tf": echoResource}),
})
err := sendPlan(sess, proto.WorkspaceTransition_START)
@ -997,7 +963,7 @@ func TestProvision_MalformedModules(t *testing.T) {
ctx, api := setupProvisioner(t, nil)
sess := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"main.tf": `module "hello" { source = "./module" }`,
"module/module.tf": `resource "null_`,
}),

View File

@ -1,8 +1,6 @@
package tfparse_test
import (
"archive/tar"
"bytes"
"context"
"io"
"log"
@ -11,7 +9,6 @@ import (
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/archive"
"github.com/coder/coder/v2/provisioner/terraform/tfparse"
"github.com/coder/coder/v2/testutil"
@ -363,7 +360,7 @@ func Test_WorkspaceTagDefaultsFromFile(t *testing.T) {
t.Run(tc.name+"/tar", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort)
tar := createTar(t, tc.files)
tar := testutil.CreateTar(t, tc.files)
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
tmpDir := t.TempDir()
tfparse.WriteArchive(tar, "application/x-tar", tmpDir)
@ -381,7 +378,7 @@ func Test_WorkspaceTagDefaultsFromFile(t *testing.T) {
t.Run(tc.name+"/zip", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort)
zip := createZip(t, tc.files)
zip := testutil.CreateZip(t, tc.files)
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
tmpDir := t.TempDir()
tfparse.WriteArchive(zip, "application/zip", tmpDir)
@ -399,36 +396,6 @@ func Test_WorkspaceTagDefaultsFromFile(t *testing.T) {
}
}
func createTar(t testing.TB, files map[string]string) []byte {
var buffer bytes.Buffer
writer := tar.NewWriter(&buffer)
for path, content := range files {
err := writer.WriteHeader(&tar.Header{
Name: path,
Size: int64(len(content)),
Uid: 65534, // nobody
Gid: 65534, // nogroup
Mode: 0o666, // -rw-rw-rw-
})
require.NoError(t, err)
_, err = writer.Write([]byte(content))
require.NoError(t, err)
}
err := writer.Flush()
require.NoError(t, err)
return buffer.Bytes()
}
func createZip(t testing.TB, files map[string]string) []byte {
ta := createTar(t, files)
tr := tar.NewReader(bytes.NewReader(ta))
za, err := archive.CreateZipFromTar(tr, int64(len(ta)))
require.NoError(t, err)
return za
}
// Last run results:
// goos: linux
// goarch: amd64
@ -460,8 +427,8 @@ func BenchmarkWorkspaceTagDefaultsFromFile(b *testing.B) {
}
}`,
}
tarFile := createTar(b, files)
zipFile := createZip(b, files)
tarFile := testutil.CreateTar(b, files)
zipFile := testutil.CreateZip(b, files)
logger := discardLogger(b)
b.ResetTimer()
b.Run("Tar", func(b *testing.B) {

View File

@ -34,7 +34,7 @@ func TestTimingsFromProvision(t *testing.T) {
binaryPath: fakeBin,
})
sess := configure(ctx, t, api, &proto.Config{
TemplateSourceArchive: makeTar(t, nil),
TemplateSourceArchive: testutil.CreateTar(t, nil),
})
ctx, cancel := context.WithTimeout(ctx, testutil.WaitLong)

View File

@ -1,8 +1,6 @@
package provisionerd_test
import (
"archive/tar"
"bytes"
"context"
"fmt"
"io"
@ -97,7 +95,7 @@ func TestProvisionerd(t *testing.T) {
err := stream.Send(&proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_TemplateImport_{
@ -150,7 +148,7 @@ func TestProvisionerd(t *testing.T) {
acq = newAcquireOne(t, &proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"../../../etc/passwd": "content",
}),
Type: &proto.AcquiredJob_TemplateImport_{
@ -194,7 +192,7 @@ func TestProvisionerd(t *testing.T) {
err := stream.Send(&proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_TemplateImport_{
@ -243,7 +241,7 @@ func TestProvisionerd(t *testing.T) {
acq = newAcquireOne(t, &proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
provisionersdk.ReadmeFile: "# A cool template 😎\n",
}),
@ -325,7 +323,7 @@ func TestProvisionerd(t *testing.T) {
acq = newAcquireOne(t, &proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_TemplateDryRun_{
@ -396,7 +394,7 @@ func TestProvisionerd(t *testing.T) {
acq = newAcquireOne(t, &proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_WorkspaceBuild_{
@ -459,7 +457,7 @@ func TestProvisionerd(t *testing.T) {
acq = newAcquireOne(t, &proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_WorkspaceBuild_{
@ -549,7 +547,7 @@ func TestProvisionerd(t *testing.T) {
acq = newAcquireOne(t, &proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_WorkspaceBuild_{
@ -645,7 +643,7 @@ func TestProvisionerd(t *testing.T) {
err := stream.Send(&proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_WorkspaceBuild_{
@ -725,7 +723,7 @@ func TestProvisionerd(t *testing.T) {
err := stream.Send(&proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_WorkspaceBuild_{
@ -819,7 +817,7 @@ func TestProvisionerd(t *testing.T) {
job := &proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_WorkspaceBuild_{
@ -916,7 +914,7 @@ func TestProvisionerd(t *testing.T) {
job := &proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_WorkspaceBuild_{
@ -1010,7 +1008,7 @@ func TestProvisionerd(t *testing.T) {
err := stream.Send(&proto.AcquiredJob{
JobId: "test",
Provisioner: "someprovisioner",
TemplateSourceArchive: createTar(t, map[string]string{
TemplateSourceArchive: testutil.CreateTar(t, map[string]string{
"test.txt": "content",
}),
Type: &proto.AcquiredJob_WorkspaceBuild_{
@ -1078,26 +1076,6 @@ func TestProvisionerd(t *testing.T) {
})
}
// Creates an in-memory tar of the files provided.
func createTar(t *testing.T, files map[string]string) []byte {
var buffer bytes.Buffer
writer := tar.NewWriter(&buffer)
for path, content := range files {
err := writer.WriteHeader(&tar.Header{
Name: path,
Size: int64(len(content)),
})
require.NoError(t, err)
_, err = writer.Write([]byte(content))
require.NoError(t, err)
}
err := writer.Flush()
require.NoError(t, err)
return buffer.Bytes()
}
// Creates a provisionerd implementation with the provided dialer and provisioners.
func createProvisionerd(t *testing.T, dialer provisionerd.Dialer, connector provisionerd.LocalProvisioners) *provisionerd.Server {
server := provisionerd.New(dialer, &provisionerd.Options{

61
testutil/archive.go Normal file
View File

@ -0,0 +1,61 @@
package testutil
import (
"archive/tar"
"bytes"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/archive"
)
// Creates an in-memory tar of the files provided.
// Files in the archive are written with nobody
// owner/group, and -rw-rw-rw- permissions.
func CreateTar(t testing.TB, files map[string]string) []byte {
var buffer bytes.Buffer
writer := tar.NewWriter(&buffer)
// Keep track of directories previously added.
addedDirs := make(map[string]bool)
for path, content := range files {
// Add parent directories if they don't exist
dir := filepath.Dir(path)
if dir != "." && !addedDirs[dir] {
err := writer.WriteHeader(&tar.Header{
Name: dir + "/", // Directory names must end with /
Mode: 0o755,
Typeflag: tar.TypeDir,
})
require.NoError(t, err)
addedDirs[dir] = true
}
err := writer.WriteHeader(&tar.Header{
Name: path,
Size: int64(len(content)),
Uid: 65534, // nobody
Gid: 65534, // nogroup
Mode: 0o666, // -rw-rw-rw-
})
require.NoError(t, err)
_, err = writer.Write([]byte(content))
require.NoError(t, err)
}
err := writer.Flush()
require.NoError(t, err)
return buffer.Bytes()
}
// Creates an in-memory zip of the files provided.
// Uses archive.CreateZipFromTar under the hood.
func CreateZip(t testing.TB, files map[string]string) []byte {
ta := CreateTar(t, files)
tr := tar.NewReader(bytes.NewReader(ta))
za, err := archive.CreateZipFromTar(tr, int64(len(ta)))
require.NoError(t, err)
return za
}