mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-30 01:44:36 +00:00
131 lines
3.3 KiB
Odin
131 lines
3.3 KiB
Odin
#+build linux, darwin, freebsd, openbsd, netbsd, haiku
|
|
package tests_core_posix
|
|
|
|
import "core:log"
|
|
import "core:testing"
|
|
import "core:sys/posix"
|
|
|
|
// This test tests some of the process APIs of posix while also double checking size and alignment
|
|
// of the structs we bound.
|
|
|
|
@(test)
|
|
execute_struct_checks :: proc(t: ^testing.T) {
|
|
log.debug("compiling C project")
|
|
{
|
|
switch pid := posix.fork(); pid {
|
|
case -1:
|
|
log.errorf("fork() failed: %s", posix.strerror())
|
|
case 0:
|
|
c_compiler := posix.getenv("CC")
|
|
if c_compiler == nil {
|
|
c_compiler = "clang"
|
|
}
|
|
|
|
posix.execlp(c_compiler,
|
|
c_compiler, #directory + "/structs/structs.c", "-o", #directory + "/structs/c_structs", nil)
|
|
posix.exit(69)
|
|
case:
|
|
if !wait_for(t, pid) { return }
|
|
log.debug("C code has been compiled!")
|
|
}
|
|
}
|
|
|
|
log.debug("compiling Odin project")
|
|
{
|
|
switch pid := posix.fork(); pid {
|
|
case -1:
|
|
log.errorf("fork() failed: %s", posix.strerror())
|
|
case 0:
|
|
posix.execlp(ODIN_ROOT + "/odin",
|
|
ODIN_ROOT + "/odin", "build", #directory + "/structs/structs.odin", "-out:" + #directory + "/structs/odin_structs", "-file", nil)
|
|
posix.exit(69)
|
|
case:
|
|
if !wait_for(t, pid) { return }
|
|
log.debug("Odin code has been compiled!")
|
|
}
|
|
}
|
|
|
|
c_buf: [dynamic]byte
|
|
defer delete(c_buf)
|
|
c_out := get_output(t, &c_buf, #directory + "/structs/c_structs", nil)
|
|
|
|
odin_buf: [dynamic]byte
|
|
defer delete(odin_buf)
|
|
odin_out := get_output(t, &odin_buf, #directory + "/structs/odin_structs", nil)
|
|
|
|
testing.expectf(t, c_out == odin_out, "The C output and Odin output differ!\nC output:\n%s\n\n\n\nOdin Output:\n%s", c_out, odin_out)
|
|
|
|
/* ----------- HELPERS ----------- */
|
|
|
|
wait_for :: proc(t: ^testing.T, pid: posix.pid_t) -> (ok: bool) {
|
|
log.debugf("waiting on pid %v", pid)
|
|
|
|
waiting: for {
|
|
status: i32
|
|
wpid := posix.waitpid(pid, &status, {})
|
|
if wpid == -1 && posix.errno() == .EINTR {
|
|
continue
|
|
}
|
|
if !testing.expectf(t, wpid != -1, "waitpid() failure: %v", posix.strerror()) {
|
|
return false
|
|
}
|
|
|
|
switch {
|
|
case posix.WIFEXITED(status):
|
|
ok = testing.expect_value(t, posix.WEXITSTATUS(status), 0)
|
|
break waiting
|
|
case posix.WIFSIGNALED(status):
|
|
log.errorf("child process raised: %v", posix.strsignal(posix.WTERMSIG(status)))
|
|
ok = false
|
|
break waiting
|
|
case:
|
|
log.errorf("unexpected status (this should never happen): %v", status)
|
|
ok = false
|
|
break waiting
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
get_output :: proc(t: ^testing.T, output: ^[dynamic]byte, cmd: ..cstring) -> (out_str: string) {
|
|
log.debugf("capturing output of: %v", cmd)
|
|
|
|
pipe: [2]posix.FD
|
|
if !testing.expect_value(t, posix.pipe(&pipe), posix.result.OK) {
|
|
return
|
|
}
|
|
|
|
switch pid := posix.fork(); pid {
|
|
case -1:
|
|
log.errorf("fork() failed: %s", posix.strerror())
|
|
return
|
|
case 0:
|
|
posix.close(pipe[0])
|
|
posix.dup2(pipe[1], 1)
|
|
posix.execv(cmd[0], raw_data(cmd[:]))
|
|
panic(string(posix.strerror()))
|
|
case:
|
|
posix.close(pipe[1])
|
|
log.debugf("waiting on pid %v", pid)
|
|
|
|
reader: for {
|
|
buf: [256]byte
|
|
switch read := posix.read(pipe[0], &buf[0], 256); {
|
|
case read < 0:
|
|
log.errorf("read output failed: %v", posix.strerror())
|
|
return
|
|
case read == 0:
|
|
break reader
|
|
case:
|
|
append(output, ..buf[:read])
|
|
}
|
|
}
|
|
|
|
wait_for(t, pid)
|
|
|
|
return string(output[:])
|
|
}
|
|
}
|
|
}
|