123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- //+build darwin, freebsd, openbsd, netbsd
- 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 !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[:])
- }
- }
- }
|