280 lines
8.7 KiB
Go
280 lines
8.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
|
)
|
|
|
|
func TestVerifySignature_Valid(t *testing.T) {
|
|
secret := "mysecret"
|
|
body := "{\"message\":\"example\"}"
|
|
|
|
// Compute the expected signature for the valid scenario.
|
|
mac := hmac.New(sha256.New, []byte(secret))
|
|
mac.Write([]byte(body))
|
|
expectedSig := hex.EncodeToString(mac.Sum(nil))
|
|
|
|
// Prepare the signature header in the "sha256=<signature>" format.
|
|
signatureHeader := "sha256=" + expectedSig
|
|
|
|
if !verifySignature(secret, body, signatureHeader) {
|
|
t.Errorf("Expected true for valid signature, got false")
|
|
}
|
|
}
|
|
|
|
func TestVerifySignature_InvalidSignature(t *testing.T) {
|
|
secret := "mysecret"
|
|
body := "{\"message\":\"example\"}"
|
|
|
|
// Use an intentionally incorrect signature.
|
|
signatureHeader := "sha256=invalidsignature"
|
|
|
|
if verifySignature(secret, body, signatureHeader) {
|
|
t.Errorf("Expected false for an invalid signature, but got true")
|
|
}
|
|
}
|
|
|
|
func TestVerifySignature_MissingPrefix(t *testing.T) {
|
|
secret := "mysecret"
|
|
body := "{\"message\":\"example\"}"
|
|
|
|
// Provide a header that does not start with "sha256="
|
|
signatureHeader := "invalidprefix"
|
|
|
|
if verifySignature(secret, body, signatureHeader) {
|
|
t.Errorf("Expected false when header is missing the required prefix, got true")
|
|
}
|
|
}
|
|
|
|
func TestVerifySignature_EmptyHeader(t *testing.T) {
|
|
secret := "mysecret"
|
|
body := "{\"message\":\"example\"}"
|
|
signatureHeader := ""
|
|
|
|
if verifySignature(secret, body, signatureHeader) {
|
|
t.Errorf("Expected false when header is empty, got true")
|
|
}
|
|
}
|
|
|
|
func TestLoadConfig_Success(t *testing.T) {
|
|
// Set up environment variables for the test.
|
|
os.Setenv("REPO_URL", "https://example.com/repo.git")
|
|
os.Setenv("REPO_BRANCH", "main")
|
|
os.Setenv("S3_BUCKET", "my-s3-bucket")
|
|
os.Setenv("S3_KEY", "source.zip")
|
|
os.Setenv("AWS_REGION", "ap-northeast-1")
|
|
|
|
// Call the function.
|
|
cfg, err := loadConfig()
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got %v", err)
|
|
}
|
|
|
|
// Validate the configuration values.
|
|
if cfg.RepoURL != "https://example.com/repo.git" {
|
|
t.Errorf("unexpected RepoURL: got %s, want %s", cfg.RepoURL, "https://example.com/repo.git")
|
|
}
|
|
if cfg.RepoBranch != "main" {
|
|
t.Errorf("unexpected RepoBranch: got %s, want %s", cfg.RepoBranch, "main")
|
|
}
|
|
if cfg.S3Bucket != "my-s3-bucket" {
|
|
t.Errorf("unexpected S3Bucket: got %s, want %s", cfg.S3Bucket, "my-s3-bucket")
|
|
}
|
|
if cfg.S3Key != "source.zip" {
|
|
t.Errorf("unexpected S3Key: got %s, want %s", cfg.S3Key, "source.zip")
|
|
}
|
|
if cfg.AWSRegion != "ap-northeast-1" {
|
|
t.Errorf("unexpected AWSRegion: got %s, want %s", cfg.AWSRegion, "ap-northeast-1")
|
|
}
|
|
}
|
|
|
|
func TestLoadConfig_MissingRepoURL(t *testing.T) {
|
|
// Clear the REPO_URL environment variable.
|
|
os.Unsetenv("REPO_URL")
|
|
|
|
// Optionally, set up other required variables.
|
|
os.Setenv("S3_BUCKET", "my-s3-bucket")
|
|
|
|
// Call the function.
|
|
_, err := loadConfig()
|
|
if err == nil {
|
|
t.Fatal("expected an error due to missing REPO_URL, got nil")
|
|
}
|
|
}
|
|
|
|
func TestLoadConfig_MissingS3Bucket(t *testing.T) {
|
|
// Clear the S3_BUCKET environment variable.
|
|
os.Unsetenv("S3_BUCKET")
|
|
|
|
// Optionally, set up other required variables.
|
|
os.Setenv("REPO_URL", "https://example.com/repo.git")
|
|
|
|
// Call the function.
|
|
_, err := loadConfig()
|
|
if err == nil {
|
|
t.Fatal("expected an error due to missing S3_BUCKET, got nil")
|
|
}
|
|
}
|
|
|
|
// TestHelperProcess is not a real test. It is invoked as a helper process
|
|
// when our fake command runner is used.
|
|
func TestHelperProcess(t *testing.T) {
|
|
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
|
// If the variable is not set, this function should do nothing.
|
|
return
|
|
}
|
|
// If GO_EXIT_STATUS is set, convert it to an integer.
|
|
if exitStatus := os.Getenv("GO_EXIT_STATUS"); exitStatus != "" {
|
|
// You can exit with this status if it's nonzero.
|
|
// For example, if it's "1", then this simulates a failing command.
|
|
os.Exit(1)
|
|
}
|
|
// Otherwise, simulate success.
|
|
os.Exit(0)
|
|
}
|
|
|
|
// fakeExecCommand returns a function that simulates exec.Command.
|
|
// The success parameter indicates whether the command should succeed.
|
|
func fakeExecCommand(success bool) func(name string, arg ...string) *exec.Cmd {
|
|
return func(name string, arg ...string) *exec.Cmd {
|
|
// We simulate the command by re-executing the test binary with special flags.
|
|
// The "--" signals the end of flags for our helper.
|
|
cs := []string{"-test.run=TestHelperProcess", "--", name}
|
|
cs = append(cs, arg...)
|
|
cmd := exec.Command(os.Args[0], cs...)
|
|
// Set an env variable that tells our TestHelperProcess to run.
|
|
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
|
if !success {
|
|
// Set a value to indicate failure. Our helper can inspect this if desired,
|
|
// or we can simply exit with a non-zero status.
|
|
cmd.Env = append(cmd.Env, "GO_EXIT_STATUS=1")
|
|
}
|
|
return cmd
|
|
}
|
|
}
|
|
|
|
func TestCloneRepository_Success(t *testing.T) {
|
|
// Override commandRunner to simulate a successful git clone.
|
|
originalCommandRunner := commandRunner
|
|
commandRunner = fakeExecCommand(true)
|
|
defer func() { commandRunner = originalCommandRunner }()
|
|
|
|
// Use a temporary directory for testing.
|
|
tempDir := t.TempDir()
|
|
|
|
// Call cloneRepository.
|
|
err := cloneRepository(context.Background(), "https://example.com/repo.git", "main", tempDir)
|
|
if err != nil {
|
|
t.Fatalf("expected success, got error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestCloneRepository_Failure(t *testing.T) {
|
|
// Override commandRunner to simulate a failing git clone.
|
|
originalCommandRunner := commandRunner
|
|
commandRunner = fakeExecCommand(false)
|
|
defer func() { commandRunner = originalCommandRunner }()
|
|
|
|
tempDir := t.TempDir()
|
|
|
|
// Call cloneRepository expecting an error.
|
|
err := cloneRepository(context.Background(), "https://example.com/repo.git", "main", tempDir)
|
|
if err == nil {
|
|
t.Fatal("expected an error, got nil")
|
|
}
|
|
}
|
|
|
|
// TestCreateZipArchive_Success simulates a successful zip creation.
|
|
func TestCreateZipArchive_Success(t *testing.T) {
|
|
// Override the global commandRunner with our fake that simulates success.
|
|
originalCommandRunner := commandRunner
|
|
commandRunner = fakeExecCommand(true)
|
|
defer func() { commandRunner = originalCommandRunner }()
|
|
|
|
// Use t.TempDir to create a temporary directory simulating the repo directory.
|
|
tempDir := t.TempDir()
|
|
// Define a zip file path within the temp directory.
|
|
zipFilePath := filepath.Join(tempDir, "source.zip")
|
|
|
|
// Call createZipArchive.
|
|
if err := createZipArchive(context.Background(), tempDir, zipFilePath); err != nil {
|
|
t.Fatalf("expected success, got error: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestCreateZipArchive_Failure simulates a failing zip creation.
|
|
func TestCreateZipArchive_Failure(t *testing.T) {
|
|
// Override commandRunner to simulate a command failure.
|
|
originalCommandRunner := commandRunner
|
|
commandRunner = fakeExecCommand(false)
|
|
defer func() { commandRunner = originalCommandRunner }()
|
|
|
|
tempDir := t.TempDir()
|
|
zipFilePath := filepath.Join(tempDir, "source.zip")
|
|
|
|
// Call createZipArchive and expect an error.
|
|
if err := createZipArchive(context.Background(), tempDir, zipFilePath); err == nil {
|
|
t.Fatal("expected an error, got nil")
|
|
}
|
|
}
|
|
|
|
// fakeUploader implements the Uploader interface.
|
|
type fakeUploader struct {
|
|
success bool
|
|
}
|
|
|
|
func (f *fakeUploader) Upload(ctx context.Context, input *s3.PutObjectInput, opts ...func(*manager.Uploader)) (*manager.UploadOutput, error) {
|
|
if f.success {
|
|
// Simulate a successful upload with a fake location.
|
|
return &manager.UploadOutput{Location: "http://fake-s3/uploaded-file"}, nil
|
|
}
|
|
// Simulate a failure.
|
|
return nil, fmt.Errorf("fake upload error")
|
|
}
|
|
|
|
func TestUploadToS3WithUploader_Success(t *testing.T) {
|
|
ctx := context.Background()
|
|
// Create a temporary directory and file to act as the ZIP file.
|
|
tempDir := t.TempDir()
|
|
zipFilePath := filepath.Join(tempDir, "source.zip")
|
|
content := []byte("dummy zip content")
|
|
if err := os.WriteFile(zipFilePath, content, 0644); err != nil {
|
|
t.Fatalf("failed to create temp zip file: %v", err)
|
|
}
|
|
|
|
// Create a fake uploader that simulates success.
|
|
u := &fakeUploader{success: true}
|
|
|
|
err := uploadToS3WithUploader(ctx, zipFilePath, "fake-bucket", "source.zip", u)
|
|
if err != nil {
|
|
t.Fatalf("expected success, got error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestUploadToS3WithUploader_Failure(t *testing.T) {
|
|
ctx := context.Background()
|
|
tempDir := t.TempDir()
|
|
zipFilePath := filepath.Join(tempDir, "source.zip")
|
|
content := []byte("dummy zip content")
|
|
if err := os.WriteFile(zipFilePath, content, 0644); err != nil {
|
|
t.Fatalf("failed to create temp zip file: %v", err)
|
|
}
|
|
|
|
// Create a fake uploader that simulates a failure.
|
|
u := &fakeUploader{success: false}
|
|
|
|
err := uploadToS3WithUploader(ctx, zipFilePath, "fake-bucket", "source.zip", u)
|
|
if err == nil {
|
|
t.Fatal("expected an error, got nil")
|
|
}
|
|
}
|