mirror of
https://github.com/samuelncui/acp.git
synced 2026-07-22 23:42:19 +00:00
133 lines
3.5 KiB
Go
133 lines
3.5 KiB
Go
package acp_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/samuelncui/acp"
|
|
)
|
|
|
|
func TestACPLibraryE2E(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping end-to-end test in short mode")
|
|
}
|
|
|
|
tempDir := t.TempDir()
|
|
source := filepath.Join(tempDir, "source")
|
|
targets := []string{
|
|
filepath.Join(tempDir, "target-a"),
|
|
filepath.Join(tempDir, "target-b"),
|
|
}
|
|
for _, target := range targets {
|
|
if err := os.MkdirAll(target, 0o755); err != nil {
|
|
t.Fatalf("create target directory %q: %v", target, err)
|
|
}
|
|
}
|
|
|
|
files := map[string][]byte{
|
|
"plain.txt": []byte("library copy\n"),
|
|
"empty.txt": nil,
|
|
filepath.Join("nested", "data"): {5, 4, 3, 2, 1},
|
|
}
|
|
for relativePath, data := range files {
|
|
path := filepath.Join(source, relativePath)
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
t.Fatalf("create source directory: %v", err)
|
|
}
|
|
if err := os.WriteFile(path, data, 0o644); err != nil {
|
|
t.Fatalf("write source file %q: %v", relativePath, err)
|
|
}
|
|
}
|
|
|
|
handler, getter := acp.NewReportGetter()
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
copyer, err := acp.New(
|
|
ctx,
|
|
acp.WildcardJob(acp.Source(source), acp.Target(targets...)),
|
|
acp.WithHash(true),
|
|
acp.Overwrite(true),
|
|
acp.WithEventHandler(handler),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("create copyer: %v", err)
|
|
}
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
copyer.Wait()
|
|
close(done)
|
|
}()
|
|
select {
|
|
case <-done:
|
|
case <-ctx.Done():
|
|
t.Fatalf("wait for copyer: %v", ctx.Err())
|
|
}
|
|
|
|
for _, target := range targets {
|
|
copyRoot := filepath.Join(target, filepath.Base(source))
|
|
for relativePath, want := range files {
|
|
got, err := os.ReadFile(filepath.Join(copyRoot, relativePath))
|
|
if err != nil {
|
|
t.Fatalf("read copied file %q from %q: %v", relativePath, target, err)
|
|
}
|
|
if !bytes.Equal(got, want) {
|
|
t.Fatalf("copied file %q from %q = %v, want %v", relativePath, target, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
report := getter()
|
|
if len(report.Errors) != 0 {
|
|
t.Fatalf("report errors = %v", report.Errors)
|
|
}
|
|
if len(report.Jobs) != len(files) {
|
|
t.Fatalf("report jobs = %d, want %d", len(report.Jobs), len(files))
|
|
}
|
|
|
|
jobs := make(map[string]*acp.Job, len(report.Jobs))
|
|
for _, job := range report.Jobs {
|
|
jobs[job.FullPath] = job
|
|
}
|
|
for relativePath, data := range files {
|
|
sourcePath := filepath.Join(source, relativePath)
|
|
job, ok := jobs[sourcePath]
|
|
if !ok {
|
|
t.Fatalf("report job not found for %q", sourcePath)
|
|
}
|
|
if job.Status != acp.JobStatusFinished {
|
|
t.Fatalf("job %q status = %q", sourcePath, job.Status)
|
|
}
|
|
if len(job.FailTargets) != 0 {
|
|
t.Fatalf("job %q failures = %v", sourcePath, job.FailTargets)
|
|
}
|
|
if job.Size != int64(len(data)) {
|
|
t.Fatalf("job %q size = %d, want %d", sourcePath, job.Size, len(data))
|
|
}
|
|
|
|
wantTargets := make(map[string]struct{}, len(targets))
|
|
for _, target := range targets {
|
|
wantTargets[filepath.Join(target, filepath.Base(source), relativePath)] = struct{}{}
|
|
}
|
|
if len(job.SuccessTargets) != len(wantTargets) {
|
|
t.Fatalf("job %q success targets = %v", sourcePath, job.SuccessTargets)
|
|
}
|
|
for _, target := range job.SuccessTargets {
|
|
if _, ok := wantTargets[target]; !ok {
|
|
t.Fatalf("job %q unexpected success target %q", sourcePath, target)
|
|
}
|
|
}
|
|
|
|
sum := sha256.Sum256(data)
|
|
if want := hex.EncodeToString(sum[:]); job.SHA256 != want {
|
|
t.Fatalf("job %q SHA256 = %q, want %q", sourcePath, job.SHA256, want)
|
|
}
|
|
}
|
|
}
|