diff --git a/examples/write/write.q b/examples/write/write.q new file mode 100644 index 0000000..0f343c1 --- /dev/null +++ b/examples/write/write.q @@ -0,0 +1,13 @@ +main() { + address := 4194304 + 1 + length := (0 + 50 - 20) * 10 / 100 + print(address, length) +} + +print(address, length) { + write(length-2, address, length) +} + +write(fd, address, length) { + syscall(1, fd, address, length) +} \ No newline at end of file diff --git a/examples_test.go b/examples_test.go new file mode 100644 index 0000000..faf1103 --- /dev/null +++ b/examples_test.go @@ -0,0 +1,67 @@ +package main_test + +import ( + "os" + "os/exec" + "testing" + + "git.akyoto.dev/cli/q/src/build" + "git.akyoto.dev/go/assert" +) + +func TestExamples(t *testing.T) { + var examples = []struct { + Name string + ExpectedOutput string + ExpectedExitCode int + }{ + {"hello", "", 25}, + {"write", "ELF", 0}, + } + + for _, example := range examples { + example := example + + t.Run(example.Name, func(t *testing.T) { + runExample(t, example.Name, example.ExpectedOutput, example.ExpectedExitCode) + }) + } +} + +// runExample builds and runs the example to check if the output matches the expected output. +func runExample(t *testing.T, name string, expectedOutput string, expectedExitCode int) { + b := build.New("examples/" + name) + assert.True(t, len(b.Executable()) > 0) + defer os.Remove(b.Executable()) + + t.Run("Compile", func(t *testing.T) { + result, err := b.Run() + assert.Nil(t, err) + + err = result.Write(b.Executable()) + assert.Nil(t, err) + + stat, err := os.Stat(b.Executable()) + assert.Nil(t, err) + assert.True(t, stat.Size() > 0) + }) + + t.Run("Output", func(t *testing.T) { + cmd := exec.Command(b.Executable()) + output, err := cmd.Output() + exitCode := 0 + + if err != nil { + exitError, ok := err.(*exec.ExitError) + + if !ok { + t.Fatal(exitError) + } + + exitCode = exitError.ExitCode() + } + + assert.Equal(t, exitCode, expectedExitCode) + assert.DeepEqual(t, string(output), expectedOutput) + }) +} diff --git a/src/build/Result.go b/src/build/Result.go index d0d3699..6a5e94b 100644 --- a/src/build/Result.go +++ b/src/build/Result.go @@ -63,3 +63,9 @@ func (r *Result) EachFunction(caller *Function, traversed map[*Function]bool, ca r.EachFunction(callee, traversed, call) } } + +// Write write the final executable to disk. +func (r *Result) Write(path string) error { + code, data := r.Finalize() + return Write(path, code, data) +} diff --git a/src/cli/Build.go b/src/cli/Build.go index a8dfee9..99a5118 100644 --- a/src/cli/Build.go +++ b/src/cli/Build.go @@ -53,9 +53,7 @@ func Build(args []string) int { return 0 } - path := b.Executable() - code, data := result.Finalize() - err = build.Write(path, code, data) + err = result.Write(b.Executable()) if err != nil { fmt.Fprintln(os.Stderr, err)