Skip to content
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
b24db69
fix: Copy the bundle to the VM
yejseo01 Nov 27, 2025
eebf9ec
fix: cleanup properly on bundle path
yejseo01 Nov 27, 2025
fd02300
fix: fix CI by migrating the simulator to the VM
yejseo01 Nov 19, 2025
45b8105
fix: stabilize CI
yejseo01 Nov 20, 2025
20afe34
fix: isolate the remoteproc names
yejseo01 Nov 24, 2025
ca87c58
fix: fix log skipping
yejseo01 Nov 24, 2025
fddc63a
fix: setup simulator in non-mounted area
yejseo01 Nov 26, 2025
02f713c
fix: Assert checks filesystem inside VM
yejseo01 Nov 27, 2025
d382711
fix: setup simulator and binaries in unmounted VM area
yejseo01 Nov 27, 2025
f13be98
lint: remove unnecessary print
yejseo01 Nov 27, 2025
2a7835c
fix: don't mount the area!
yejseo01 Nov 27, 2025
1b7f752
fix: improve remoteproc device indexing
yejseo01 Nov 27, 2025
92212d0
fix: remove mount dependency
yejseo01 Nov 27, 2025
b4b1919
fix: remove unused mount directory
yejseo01 Nov 27, 2025
28dde4a
fix: add test helper file
yejseo01 Nov 27, 2025
0f4065e
fix: Make sure that destination folders exist before building binaries
yejseo01 Dec 4, 2025
8168bd2
lint: receive error
yejseo01 Dec 5, 2025
a24fc01
lint: tie same types together in functions
yejseo01 Dec 5, 2025
d2445b5
refactor: Refactor the git process
yejseo01 Dec 5, 2025
c10291d
lint: verbosify function name
yejseo01 Dec 5, 2025
4db0ace
lint: rename function
yejseo01 Dec 5, 2025
880e601
lint: remove unnecessary comment
yejseo01 Dec 5, 2025
8a12116
fix: preserve Stop()'s error if there is any
yejseo01 Dec 5, 2025
efc268c
fix: remove potential lockup
yejseo01 Dec 5, 2025
87abf3e
fix: remove unncessary bits
yejseo01 Dec 5, 2025
1bb529b
fix: Pin the remoteproc-simulator when building
yejseo01 Dec 8, 2025
8f2ee8a
fix: Add assertion
yejseo01 Dec 8, 2025
3db3984
fix: make the detection target message const
yejseo01 Dec 8, 2025
e6451c8
fix: make rootpathPrefix more identifiable
yejseo01 Dec 8, 2025
12e7641
fix: don't use rootpathPrefix as binary dumping area
yejseo01 Dec 8, 2025
ef68f98
fix: retrieve correct number of files in VM dir
yejseo01 Dec 8, 2025
9c585fb
fix: remove simulator installation
yejseo01 Dec 8, 2025
4bc2193
fix: remove simulator installation properly
yejseo01 Dec 8, 2025
3aa6fa0
fix: download artifacts rather than building in CI
yejseo01 Dec 8, 2025
74f98ec
debug: check the architecture
yejseo01 Dec 8, 2025
37ed6b1
lint: remove unnecessary messages
yejseo01 Dec 8, 2025
79d1acc
lint: rename variable
yejseo01 Dec 8, 2025
778ed2c
fix: cleanup properly after the simulator inside the VM
yejseo01 Dec 8, 2025
93ad8cf
fix: remove usage of WithIndex()
yejseo01 Dec 8, 2025
55a26f9
fix: take if statement out of the loop
yejseo01 Dec 8, 2025
6569a68
refactor: cleanup parameter intake of Start()
yejseo01 Dec 8, 2025
1073bfd
lint: remove unused public function
yejseo01 Dec 8, 2025
84a6d9c
lint: pass limavm.Debian not limavm.VM
yejseo01 Dec 8, 2025
46bbba1
feat: implement vm.ReadDir() and use it
yejseo01 Dec 8, 2025
995da7c
fix: remove unnecessary modules
yejseo01 Dec 8, 2025
2cc4bd3
lint: rename variable to match consistency
yejseo01 Dec 9, 2025
684e8ce
fix: remove unnecessary parameters
yejseo01 Dec 9, 2025
3d19d40
fix: rename variable properly
yejseo01 Dec 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions e2e/limavm/debian.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ type Debian struct {
VM
}

func NewDebian(mountDir string) (Debian, error) {
vm, err := newVM("debian", mountDir)
func NewDebian() (Debian, error) {
vm, err := newVM("debian")
if err != nil {
return Debian{}, err
}
Expand Down
4 changes: 2 additions & 2 deletions e2e/limavm/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ type Docker struct {
VM
}

func NewDocker(mountDir string) (Docker, error) {
vm, err := newVM("docker", mountDir)
func NewDocker() (Docker, error) {
vm, err := newVM("docker")
if err != nil {
return Docker{}, err
}
Expand Down
20 changes: 18 additions & 2 deletions e2e/limavm/limavm.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ var BinBuildEnv = map[string]string{
"GOOS": "linux",
}

func newVM(template string, mountDir string) (VM, error) {
vmName, err := scripts.PrepareLimaVM(template, mountDir)
func newVM(template string) (VM, error) {
vmName, err := scripts.PrepareLimaVM(template)
return VM{name: vmName}, err
}

func (vm VM) Name() string {
return vm.name
}

func (vm VM) InstallBin(binToInstall string) (InstalledBin, error) {
installPath, err := scripts.InstallBin(vm.name, binToInstall)
if err != nil {
Expand Down Expand Up @@ -84,6 +88,14 @@ func (vm VM) RunCommand(name string, args ...string) (stdout, stderr string, err
return stdout, stderr, nil
}

func (vm VM) ReadFile(path string) (string, error) {
stdout, stderr, err := vm.RunCommand("cat", path)
if err != nil {
return "", fmt.Errorf("failed to read file %s: %w\nstderr:\n%s", path, err, stderr)
}
return stdout, nil
}

type Runnable interface {
Run(args ...string) (stdout, stderr string, err error)
}
Expand All @@ -97,6 +109,10 @@ func (b InstalledBin) Run(args ...string) (stdout, stderr string, err error) {
return b.vm.RunCommand(b.pathToBin, args...)
}

func (b InstalledBin) Command(args ...string) *exec.Cmd {
return b.vm.cmd(b.pathToBin, args...)
}

func (b InstalledBin) Path() string {
return b.pathToBin
}
Expand Down
4 changes: 2 additions & 2 deletions e2e/limavm/podman.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ type Podman struct {
VM
}

func NewPodman(mountDir string) (Podman, error) {
vm, err := newVM("podman", mountDir)
func NewPodman() (Podman, error) {
vm, err := newVM("podman")
if err != nil {
return Podman{}, err
}
Expand Down
6 changes: 2 additions & 4 deletions e2e/limavm/scripts/prepare-lima-vm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ MOUNT_DIR=""
usage() {
echo "Usage: $0 <template> <mount-dir>" >&2
echo " template: Lima template to use (docker or podman)" >&2
echo " mount-dir: Directory attached in the vm" >&2
exit 1
}

Expand All @@ -22,7 +21,7 @@ cleanup_on_failure() {

create_vm() {
echo "Creating Lima VM..." >&2
if ! limactl create --tty=false --name "$VM_NAME" --set ".mounts += [{\"location\":\"$MOUNT_DIR\",\"writable\":true}]" "template://$TEMPLATE"; then
if ! limactl create --tty=false --name "$VM_NAME" "template://$TEMPLATE"; then
echo "Error: Failed to create VM" >&2
exit 1
fi
Expand All @@ -38,12 +37,11 @@ start_vm() {
}

main() {
if [ $# -ne 2 ]; then
if [ $# -ne 1 ]; then
usage
fi

TEMPLATE="$1"
MOUNT_DIR="$2"

VM_NAME="remoteproc-test-vm-$(date +%s)"
echo "Creating VM: $VM_NAME" >&2
Expand Down
10 changes: 5 additions & 5 deletions e2e/limavm/scripts/scripts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ var (
teardownLimaVMScript = filepath.Join(scriptsDir, "teardown-lima-vm.sh")
)

func PrepareLimaVM(template string, mountDir string) (string, error) {
prepareCmd := exec.Command(prepareLimaVMScript, template, mountDir)
func PrepareLimaVM(template string) (string, error) {
prepareCmd := exec.Command(prepareLimaVMScript, template)
prepareStreamer := runner.NewStreamingCmd(prepareCmd).WithPrefix("prepare-vm")

if err := prepareStreamer.Start(); err != nil {
if err := prepareStreamer.Start(nil); err != nil {
return "", fmt.Errorf("failed to start prepare-lima script: %w", err)
}

Expand All @@ -42,7 +42,7 @@ func InstallBin(vmName string, binToInstall string) (string, error) {
installCmd := exec.Command(installBinScript, vmName, binToInstall)
installStreamer := runner.NewStreamingCmd(installCmd).WithPrefix("install-bin")

if err := installStreamer.Start(); err != nil {
if err := installStreamer.Start(nil); err != nil {
return "", fmt.Errorf("failed to start install-bin script: %w", err)
}

Expand All @@ -67,7 +67,7 @@ func BuildImage(vmName string, template string, buildContext string, imageName s
buildCmd := exec.Command(buildImageScript, vmName, template, buildContext, imageName)
buildStreamer := runner.NewStreamingCmd(buildCmd).WithPrefix("build-image")

if err := buildStreamer.Start(); err != nil {
if err := buildStreamer.Start(nil); err != nil {
return fmt.Errorf("failed to start build-image script: %w", err)
}

Expand Down
14 changes: 7 additions & 7 deletions e2e/remoteproc/assert.go
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
package remoteproc

import (
"os"
"path/filepath"
"testing"
"time"

"github.com/arm/remoteproc-runtime/e2e/limavm"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func AssertState(t testing.TB, deviceDir string, wantState string) {
func AssertState(t testing.TB, deviceDir string, vm limavm.VM, wantState string) {
t.Helper()
const waitFor = 500 * time.Millisecond
const tickEvery = 100 * time.Millisecond
stateFilePath := filepath.Join(deviceDir, "state")
assert.EventuallyWithT(t, func(c *assert.CollectT) {
assertFileContent(c, stateFilePath, wantState)
assertFileContent(c, stateFilePath, vm, wantState)
}, waitFor, tickEvery)
}

func RequireState(t testing.TB, deviceDir string, wantState string) {
func RequireState(t testing.TB, deviceDir string, vm limavm.VM, wantState string) {
t.Helper()
const waitFor = 500 * time.Millisecond
const tickEvery = 100 * time.Millisecond
stateFilePath := filepath.Join(deviceDir, "state")
require.EventuallyWithT(t, func(c *assert.CollectT) {
assertFileContent(c, stateFilePath, wantState)
assertFileContent(c, stateFilePath, vm, wantState)
}, waitFor, tickEvery)
}

func assertFileContent(t assert.TestingT, path string, wantContent string) {
gotContent, err := os.ReadFile(path)
func assertFileContent(t assert.TestingT, path string, vm limavm.VM, wantContent string) {
gotContent, err := vm.ReadFile(path)
if assert.NoError(t, err) {
assert.Equal(t, wantContent, string(gotContent))
}
Expand Down
62 changes: 49 additions & 13 deletions e2e/remoteproc/simulator.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
package remoteproc

import (
"bufio"
"fmt"
"os/exec"
"io"
"path/filepath"
"strings"
"time"

"github.com/arm/remoteproc-runtime/e2e/limavm"
"github.com/arm/remoteproc-runtime/e2e/runner"
)

type Simulator struct {
cmd *runner.StreamingCmd
name string
index uint
rootDir string
installedVM limavm.InstalledBin
cmd *runner.StreamingCmd
name string
index uint
rootDir string
}

func NewSimulator(rootDir string) *Simulator {
func NewSimulator(installedVM limavm.InstalledBin, rootDir string) *Simulator {
return &Simulator{
rootDir: rootDir,
index: 0,
name: "some-cpu",
installedVM: installedVM,
rootDir: rootDir,
index: 0,
name: "some-cpu",
}
}

Expand All @@ -28,21 +34,51 @@ func (r *Simulator) WithName(name string) *Simulator {
return r
}

func (r *Simulator) WithIndex(index uint) *Simulator {
r.index = index
return r
}

func (r *Simulator) Start() error {
cmd := exec.Command(
"remoteproc-simulator",
cmd := r.installedVM.Command(
"--root-dir", r.rootDir,
"--index", fmt.Sprintf("%d", r.index),
"--name", r.name,
)
streamer := runner.NewStreamingCmd(cmd).WithPrefix("remoteproc-simulator")
if err := streamer.Start(); err != nil {
streamer := runner.NewStreamingCmd(cmd).WithPrefix("simulator: " + r.name + ": ")
reader, writer := io.Pipe()
if err := streamer.Start(writer); err != nil {
return fmt.Errorf("failed to start simulator: %w", err)
}
r.cmd = streamer

if err := r.waitForBoot(15*time.Second, reader); err != nil {
_ = r.Stop()
return fmt.Errorf("simulator failed to create remoteproc device: %w", err)
}

return nil
}

func (r *Simulator) waitForBoot(waitingTime time.Duration, outputBuf *io.PipeReader) error {
deadline := time.Now().Add(waitingTime)
scanner := bufio.NewScanner(outputBuf)
for scanner.Scan() {
if time.Now().After(deadline) {
return fmt.Errorf("timeout waiting for simulator to create remoteproc device")
}
line := scanner.Text()
if strings.Contains(line, "Remoteproc initialized at") {
err := outputBuf.Close()
if err != nil {
return fmt.Errorf("failed to close output buffer: %w", err)
}
return nil
}
}
panic("unreachable")
}

func (r *Simulator) Stop() error {
if r.cmd != nil {
return r.cmd.Stop()
Expand Down
91 changes: 91 additions & 0 deletions e2e/repo/bin.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package repo

import (
"bufio"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)

func BuildRuntimeBin(binOutDir string, rootPathPrefix string, env map[string]string) (string, error) {
Expand Down Expand Up @@ -72,3 +74,92 @@ func BuildBothBins(binOutDir string, rootPathPrefix string, env map[string]strin

return []string{runtime, shim}, nil
}

func BuildRemoteprocSimulator(binOutDir string, env map[string]string) (string, error) {
const repoURL = "https://github.com/arm/remoteproc-simulator.git"
const repoDirName = "remoteproc-simulator"
binOut := filepath.Join(binOutDir, "remoteproc-simulator")

tempDir, err := os.MkdirTemp("", "remoteproc-simulator-*")
if err != nil {
return "", fmt.Errorf("failed to create temp directory: %w", err)
}
defer func() { _ = os.RemoveAll(tempDir) }()

repoDir := filepath.Join(tempDir, repoDirName)

clone := exec.Command("git", "clone", "--quiet", repoURL, repoDir)
clone.Env = os.Environ()
for k, v := range env {
clone.Env = append(clone.Env, fmt.Sprintf("%s=%s", k, v))
}
if out, err := clone.CombinedOutput(); err != nil {
return "", fmt.Errorf("failed to clone remoteproc simulator repository: %w\n%s", err, out)
}

tagCmd := exec.Command("git", "tag", "--list", "--sort=-version:refname")
tagCmd.Dir = repoDir
tagCmd.Env = os.Environ()
for k, v := range env {
tagCmd.Env = append(tagCmd.Env, fmt.Sprintf("%s=%s", k, v))
}

tagOutput, err := tagCmd.StdoutPipe()
if err != nil {
return "", fmt.Errorf("failed to create stdout pipe for tag listing: %w", err)
}

if err := tagCmd.Start(); err != nil {
return "", fmt.Errorf("failed to list tags for remoteproc simulator: %w", err)
}

var latestTag string
scanner := bufio.NewScanner(tagOutput)
for scanner.Scan() {
tag := strings.TrimSpace(scanner.Text())
if tag == "" {
continue
}
if !strings.HasPrefix(tag, "v") {
continue
}
latestTag = tag
break
}
if err := scanner.Err(); err != nil {
return "", fmt.Errorf("failed to read tags for remoteproc simulator: %w", err)
}
if err := tagCmd.Wait(); err != nil {
return "", fmt.Errorf("failed to list tags for remoteproc simulator: %w", err)
}

if latestTag == "" {
return "", fmt.Errorf("no semantic version tag found in remoteproc simulator repository")
}

checkout := exec.Command("git", "checkout", "--quiet", latestTag)
checkout.Dir = repoDir
checkout.Env = os.Environ()
for k, v := range env {
checkout.Env = append(checkout.Env, fmt.Sprintf("%s=%s", k, v))
}
if out, err := checkout.CombinedOutput(); err != nil {
return "", fmt.Errorf("failed to checkout latest tag %s: %w\n%s", latestTag, err, out)
}

build := exec.Command(
"go", "build",
"-o", binOut,
"./cmd/remoteproc-simulator",
)
build.Dir = repoDir
build.Env = os.Environ()
for k, v := range env {
build.Env = append(build.Env, fmt.Sprintf("%s=%s", k, v))
}

if out, err := build.CombinedOutput(); err != nil {
return "", fmt.Errorf("failed to build remoteproc simulator: %s\n%s", err, out)
}
return binOut, nil
}
Loading