67dbb68818
Test / Create distribution (push) Successful in 56s
Test / Sandbox (push) Successful in 2m43s
Test / ShareFS (push) Successful in 3m57s
Test / Hakurei (push) Successful in 4m3s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m36s
Test / Flake checks (push) Successful in 1m5s
This enables changing the behaviour of an artifact implementation without changing its IR structure. Unfortunately this changes the IR header structure resulting in many rebuilds. Signed-off-by: Ophestra <cat@gensokyo.uk>
147 lines
3.0 KiB
Go
147 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"hakurei.app/check"
|
|
"hakurei.app/internal/pkg"
|
|
"hakurei.app/message"
|
|
)
|
|
|
|
func TestNoReply(t *testing.T) {
|
|
t.Parallel()
|
|
if !daemonDeadline().IsZero() {
|
|
t.Fatal("daemonDeadline did not return the zero value")
|
|
}
|
|
|
|
c, err := pkg.Open(
|
|
t.Context(),
|
|
message.New(log.New(os.Stderr, "cir: ", 0)),
|
|
check.MustAbs(t.TempDir()),
|
|
nil,
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("Open: error = %v", err)
|
|
}
|
|
defer c.Close()
|
|
|
|
client, server := net.Pipe()
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
go func() {
|
|
<-t.Context().Done()
|
|
if _err := client.SetDeadline(time.Now()); _err != nil && !errors.Is(_err, io.ErrClosedPipe) {
|
|
panic(_err)
|
|
}
|
|
}()
|
|
|
|
if _err := c.EncodeAll(
|
|
client,
|
|
pkg.NewFile("check", []byte{0}),
|
|
); _err != nil {
|
|
panic(_err)
|
|
} else if _err = client.Close(); _err != nil {
|
|
panic(_err)
|
|
}
|
|
}()
|
|
|
|
a, cureErr := cureFromIR(c, server, remoteNoReply)
|
|
if cureErr != nil {
|
|
t.Fatalf("cureFromIR: error = %v", cureErr)
|
|
}
|
|
|
|
<-done
|
|
wantIdent := pkg.MustDecode("fRn1L_pE6JbizdDOKS9GiZXEIp_yx4YYz_nSuv423hGnxAI2rUAwnR1OG1zjsP0N")
|
|
if gotIdent := c.Ident(a).Value(); gotIdent != wantIdent {
|
|
t.Errorf(
|
|
"cureFromIR: %s, want %s",
|
|
pkg.Encode(gotIdent), pkg.Encode(wantIdent),
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestDaemon(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var buf bytes.Buffer
|
|
logger := log.New(&buf, "daemon: ", 0)
|
|
|
|
addr := net.UnixAddr{
|
|
Name: filepath.Join(t.TempDir(), "daemon"),
|
|
Net: "unix",
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(t.Context())
|
|
defer cancel()
|
|
|
|
cm := cache{
|
|
ctx: ctx,
|
|
msg: message.New(logger),
|
|
base: t.TempDir(),
|
|
}
|
|
defer cm.Close()
|
|
|
|
ul, err := net.ListenUnix("unix", &addr)
|
|
if err != nil {
|
|
t.Fatalf("ListenUnix: error = %v", err)
|
|
}
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
if _err := serve(ctx, logger, &cm, ul); _err != nil {
|
|
panic(_err)
|
|
}
|
|
}()
|
|
|
|
if err = cancelRemote(ctx, &addr, pkg.NewFile("nonexistent", nil), true); err != nil {
|
|
t.Fatalf("cancelRemote: error = %v", err)
|
|
}
|
|
|
|
if err = abortRemote(ctx, &addr, true); err != nil {
|
|
t.Fatalf("abortRemote: error = %v", err)
|
|
}
|
|
|
|
// keep this last for synchronisation
|
|
var p *check.Absolute
|
|
p, err = cureRemote(ctx, &addr, pkg.NewFile("check", []byte{0}), 0)
|
|
if err != nil {
|
|
t.Fatalf("cureRemote: error = %v", err)
|
|
}
|
|
|
|
cancel()
|
|
<-done
|
|
|
|
const want = "fRn1L_pE6JbizdDOKS9GiZXEIp_yx4YYz_nSuv423hGnxAI2rUAwnR1OG1zjsP0N"
|
|
if got := filepath.Base(p.String()); got != want {
|
|
t.Errorf("cureRemote: %s, want %s", got, want)
|
|
}
|
|
|
|
wantLog := []string{
|
|
"",
|
|
"daemon: aborting all pending cures",
|
|
"daemon: attempting to cancel invalid artifact C0YO8fkKg38JGK95j8k1tHywA7nMk9xp2TUa69di7uFvnKioTdOOLaDRiwRcs1Nf",
|
|
"daemon: fulfilled artifact " + want,
|
|
}
|
|
gotLog := strings.Split(buf.String(), "\n")
|
|
slices.Sort(gotLog)
|
|
if !slices.Equal(gotLog, wantLog) {
|
|
t.Errorf(
|
|
"serve: logged\n%s\nwant\n%s",
|
|
strings.Join(gotLog, "\n"), strings.Join(wantLog, "\n"),
|
|
)
|
|
}
|
|
}
|