mirror of
https://github.com/sliverarmory/reflektor
synced 2026-08-25 09:14:48 +00:00
127 lines
3.6 KiB
Go
127 lines
3.6 KiB
Go
package reflektor_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/sliverarmory/reflektor"
|
|
)
|
|
|
|
const goRuntimeHelperLibraryEnv = "REFLEKTOR_GO_HELPER_LIBRARY"
|
|
|
|
func runGoRuntimeFixtureSubprocess(t *testing.T, libraryPath string) {
|
|
t.Helper()
|
|
|
|
stateDir := t.TempDir()
|
|
markerPath := filepath.Join(stateDir, "complete")
|
|
readyPath := filepath.Join(stateDir, "ready")
|
|
releasePath := filepath.Join(stateDir, "release")
|
|
closedPath := filepath.Join(stateDir, "closed")
|
|
afterClosePath := filepath.Join(stateDir, "after-close")
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
|
|
cmd := exec.CommandContext(ctx, os.Args[0], "-test.run=^TestGoRuntimeFixtureSubprocess$", "-test.count=1")
|
|
cmd.Env = overrideEnv(os.Environ(), map[string]string{
|
|
goRuntimeHelperLibraryEnv: libraryPath,
|
|
"REFLEKTOR_MARKER": markerPath,
|
|
"REFLEKTOR_READY": readyPath,
|
|
"REFLEKTOR_RELEASE": releasePath,
|
|
"REFLEKTOR_CLOSED": closedPath,
|
|
"REFLEKTOR_AFTER_CLOSE": afterClosePath,
|
|
})
|
|
var output bytes.Buffer
|
|
cmd.Stdout = &output
|
|
cmd.Stderr = &output
|
|
if err := cmd.Start(); err != nil {
|
|
t.Fatalf("start Go runtime fixture helper: %v", err)
|
|
}
|
|
|
|
waitCh := make(chan error, 1)
|
|
go func() {
|
|
waitCh <- cmd.Wait()
|
|
}()
|
|
|
|
ticker := time.NewTicker(10 * time.Millisecond)
|
|
defer ticker.Stop()
|
|
for {
|
|
if got, err := os.ReadFile(readyPath); err == nil && bytes.Equal(got, []byte("ready")) {
|
|
break
|
|
}
|
|
select {
|
|
case err := <-waitCh:
|
|
t.Fatalf("Go runtime fixture helper exited before readiness: %v\n%s", err, output.String())
|
|
case <-ctx.Done():
|
|
t.Fatalf("Go runtime fixture helper did not become ready: %v\n%s", ctx.Err(), output.String())
|
|
case <-ticker.C:
|
|
}
|
|
}
|
|
|
|
if err := os.WriteFile(releasePath, []byte("release"), 0o600); err != nil {
|
|
t.Fatalf("release Go runtime fixture helper: %v", err)
|
|
}
|
|
|
|
select {
|
|
case err := <-waitCh:
|
|
if err != nil {
|
|
t.Fatalf("Go runtime fixture helper failed: %v\n%s", err, output.String())
|
|
}
|
|
case <-ctx.Done():
|
|
t.Fatalf("Go runtime fixture helper did not return after release: %v\n%s", ctx.Err(), output.String())
|
|
}
|
|
|
|
got, err := os.ReadFile(markerPath)
|
|
if err != nil {
|
|
t.Fatalf("read Go runtime completion marker: %v\n%s", err, output.String())
|
|
}
|
|
if !bytes.Equal(got, []byte("ok")) {
|
|
t.Fatalf("unexpected Go runtime completion marker: got=%q want=%q", got, []byte("ok"))
|
|
}
|
|
afterClose, err := os.ReadFile(afterClosePath)
|
|
if err != nil {
|
|
t.Fatalf("read Go runtime post-Close marker: %v\n%s", err, output.String())
|
|
}
|
|
if !bytes.Equal(afterClose, []byte("alive")) {
|
|
t.Fatalf("unexpected Go runtime post-Close marker: got=%q want=%q", afterClose, []byte("alive"))
|
|
}
|
|
}
|
|
|
|
func TestGoRuntimeFixtureSubprocess(t *testing.T) {
|
|
libraryPath := os.Getenv(goRuntimeHelperLibraryEnv)
|
|
if libraryPath == "" {
|
|
return
|
|
}
|
|
|
|
library, err := reflektor.LoadLibraryFile(libraryPath)
|
|
if err != nil {
|
|
t.Fatalf("LoadLibraryFile(%s): %v", libraryPath, err)
|
|
}
|
|
if err := library.CallExport("StartW"); err != nil {
|
|
t.Fatalf("CallExport(StartW): %v", err)
|
|
}
|
|
if err := library.Close(); err != nil {
|
|
t.Fatalf("Close(): %v", err)
|
|
}
|
|
closedPath := os.Getenv("REFLEKTOR_CLOSED")
|
|
afterClosePath := os.Getenv("REFLEKTOR_AFTER_CLOSE")
|
|
if err := os.WriteFile(closedPath, []byte("closed"), 0o600); err != nil {
|
|
t.Fatalf("signal Close(): %v", err)
|
|
}
|
|
deadline := time.Now().Add(5 * time.Second)
|
|
for {
|
|
if got, err := os.ReadFile(afterClosePath); err == nil && bytes.Equal(got, []byte("alive")) {
|
|
break
|
|
}
|
|
if time.Now().After(deadline) {
|
|
t.Fatalf("Go runtime did not remain alive after Close")
|
|
}
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
}
|