Make errors a little nicer
This commit is contained in:
parent
2bd8d9a5de
commit
9fbb3ab637
109
ph7.go
109
ph7.go
@ -16,98 +16,125 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ResultCode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ResultCodeOK = ResultCode(C.PH7_OK)
|
||||||
|
ResultCodeNoMem = ResultCode(C.PH7_NOMEM)
|
||||||
|
ResultCodeAbort = ResultCode(C.PH7_ABORT)
|
||||||
|
ResultCodeIOErr = ResultCode(C.PH7_IO_ERR)
|
||||||
|
ResultCodeLooked = ResultCode(C.PH7_LOOKED)
|
||||||
|
ResultCodeCorrupt = ResultCode(C.PH7_CORRUPT)
|
||||||
|
ResultCodeCompileErr = ResultCode(C.PH7_COMPILE_ERR)
|
||||||
|
ResultCodeVMErr = ResultCode(C.PH7_VM_ERR)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r ResultCode) String() string {
|
||||||
|
switch r {
|
||||||
|
case ResultCodeOK:
|
||||||
|
return "PH7_OK"
|
||||||
|
case ResultCodeNoMem:
|
||||||
|
return "PH7_NOMEM"
|
||||||
|
case ResultCodeAbort:
|
||||||
|
return "PH7_ABORT"
|
||||||
|
case ResultCodeIOErr:
|
||||||
|
return "PH7_IO_ERR"
|
||||||
|
case ResultCodeLooked:
|
||||||
|
return "PH7_LOOKED"
|
||||||
|
case ResultCodeCorrupt:
|
||||||
|
return "PH7_CORRUPT"
|
||||||
|
case ResultCodeCompileErr:
|
||||||
|
return "PH7_COMPILE_ERR"
|
||||||
|
case ResultCodeVMErr:
|
||||||
|
return "PH7_VM_ERR"
|
||||||
|
default:
|
||||||
|
return "UNKNOWN"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
Value int
|
Code ResultCode
|
||||||
|
}
|
||||||
|
|
||||||
|
func newError(code C.int) error {
|
||||||
|
if code != C.PH7_OK {
|
||||||
|
return Error{
|
||||||
|
Code: ResultCode(code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Error) Error() string {
|
func (e Error) Error() string {
|
||||||
return fmt.Sprintf("ph7 error: %d", e.Value)
|
return fmt.Sprintf("ph7: %s", e.Code)
|
||||||
}
|
|
||||||
|
|
||||||
func newError(value C.int) Error {
|
|
||||||
return Error{
|
|
||||||
Value: int(value),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Engine struct {
|
type Engine struct {
|
||||||
ptr *C.ph7
|
ptr *C.ph7
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEngine() (*Engine, error) {
|
func NewEngine() (Engine, error) {
|
||||||
engine := new(Engine)
|
var engine Engine
|
||||||
result := C.ph7_init(&engine.ptr)
|
result := C.ph7_init(&engine.ptr)
|
||||||
if result != C.PH7_OK {
|
if result != C.PH7_OK {
|
||||||
return nil, newError(result)
|
return Engine{}, newError(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
return engine, nil
|
return engine, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) ExtractErrLog() (string, error) {
|
func (e Engine) ErrLog() (string, error) {
|
||||||
var s *C.char
|
var s *C.char
|
||||||
var n C.int
|
var n C.int
|
||||||
|
|
||||||
result := C.engine_config_err_log(e.ptr, &s, &n)
|
err := newError(C.engine_config_err_log(e.ptr, &s, &n))
|
||||||
if result != C.PH7_OK {
|
if err != nil {
|
||||||
return "", newError(result)
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return C.GoStringN(s, n), nil
|
return C.GoStringN(s, n), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) Compile(source []byte, phpOnly bool) (*VM, error) {
|
func (e Engine) Compile(source []byte, phpOnly bool) (*VM, error) {
|
||||||
csource := C.CBytes(source)
|
csource := C.CBytes(source)
|
||||||
vm := new(VM)
|
vm := new(VM)
|
||||||
var flags C.int
|
var flags C.int
|
||||||
if phpOnly {
|
if phpOnly {
|
||||||
flags |= C.PH7_PHP_ONLY
|
flags |= C.PH7_PHP_ONLY
|
||||||
}
|
}
|
||||||
result := C.ph7_compile_v2(e.ptr, (*C.char)(csource), C.int(len(source)), &vm.ptr, flags)
|
err := newError(C.ph7_compile_v2(e.ptr, (*C.char)(csource), C.int(len(source)), &vm.ptr, flags))
|
||||||
if result != C.PH7_OK {
|
if err != nil {
|
||||||
return nil, newError(result)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO free csource
|
// TODO free csource
|
||||||
return vm, nil
|
return vm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) Close() error {
|
func (e Engine) Close() error {
|
||||||
result := C.ph7_release(e.ptr)
|
return newError(C.ph7_release(e.ptr))
|
||||||
if result != C.PH7_OK {
|
|
||||||
return newError(result)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type VM struct {
|
type VM struct {
|
||||||
ptr *C.ph7_vm
|
ptr *C.ph7_vm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VM) ExtractOutput() (string, error) {
|
func (vm VM) ExtractOutput() (string, error) {
|
||||||
var s *C.char
|
var s *C.char
|
||||||
var n C.int
|
var n C.int
|
||||||
|
|
||||||
result := C.vm_extract_output(vm.ptr, &s, &n)
|
err := newError(C.vm_extract_output(vm.ptr, &s, &n))
|
||||||
if result != C.PH7_OK {
|
if err != nil {
|
||||||
return "", newError(result)
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return C.GoStringN(s, n), nil
|
return C.GoStringN(s, n), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VM) Exec() error {
|
func (v VM) Exec() error {
|
||||||
result := C.ph7_vm_exec(v.ptr, (*C.int)(nil))
|
return newError(C.ph7_vm_exec(v.ptr, (*C.int)(nil)))
|
||||||
if result != C.PH7_OK {
|
|
||||||
return newError(result)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VM) Close() error {
|
func (v VM) Close() error {
|
||||||
result := C.ph7_vm_release(v.ptr)
|
return newError(C.ph7_vm_release(v.ptr))
|
||||||
if result != C.PH7_OK {
|
|
||||||
return newError(result)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
25
ph7_test.go
25
ph7_test.go
@ -7,19 +7,28 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func mustSucceed(t *testing.T, err error) {
|
func mustSucceed(t *testing.T, err error) {
|
||||||
|
t.Helper()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustFail(t *testing.T, err error) {
|
||||||
|
t.Helper()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func mustSucceedF(t *testing.T, f func() error) {
|
func mustSucceedF(t *testing.T, f func() error) {
|
||||||
|
t.Helper()
|
||||||
err := f()
|
err := f()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoStuff(t *testing.T) {
|
func TestHelloWorld(t *testing.T) {
|
||||||
engine, err := ph7.NewEngine()
|
engine, err := ph7.NewEngine()
|
||||||
mustSucceed(t, err)
|
mustSucceed(t, err)
|
||||||
defer mustSucceedF(t, engine.Close)
|
defer mustSucceedF(t, engine.Close)
|
||||||
@ -36,3 +45,17 @@ func TestDoStuff(t *testing.T) {
|
|||||||
t.Fatalf("unexpected output: %s", output)
|
t.Fatalf("unexpected output: %s", output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCompileError(t *testing.T) {
|
||||||
|
engine, err := ph7.NewEngine()
|
||||||
|
mustSucceed(t, err)
|
||||||
|
defer mustSucceedF(t, engine.Close)
|
||||||
|
|
||||||
|
_, err = engine.Compile([]byte("<?php 1234 echo 'Hello world!'; ?>"), false)
|
||||||
|
mustFail(t, err)
|
||||||
|
msg, err := engine.ErrLog()
|
||||||
|
mustSucceed(t, err)
|
||||||
|
if msg == "" {
|
||||||
|
t.Fatalf("expected error message, got nothing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user