testing.odin 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package testing
  2. import "core:fmt"
  3. import "core:io"
  4. import "core:time"
  5. import "core:intrinsics"
  6. // IMPORTANT NOTE: Compiler requires this layout
  7. Test_Signature :: proc(^T)
  8. // IMPORTANT NOTE: Compiler requires this layout
  9. Internal_Test :: struct {
  10. pkg: string,
  11. name: string,
  12. p: Test_Signature,
  13. }
  14. Internal_Cleanup :: struct {
  15. procedure: proc(rawptr),
  16. user_data: rawptr,
  17. }
  18. T :: struct {
  19. error_count: int,
  20. w: io.Writer,
  21. cleanups: [dynamic]Internal_Cleanup,
  22. _fail_now: proc() -> !,
  23. }
  24. error :: proc(t: ^T, args: ..any, loc := #caller_location) {
  25. fmt.wprintf(t.w, "%v: ", loc)
  26. fmt.wprintln(t.w, ..args)
  27. t.error_count += 1
  28. }
  29. errorf :: proc(t: ^T, format: string, args: ..any, loc := #caller_location) {
  30. fmt.wprintf(t.w, "%v: ", loc)
  31. fmt.wprintf(t.w, format, ..args)
  32. fmt.wprintln(t.w)
  33. t.error_count += 1
  34. }
  35. fail :: proc(t: ^T, loc := #caller_location) {
  36. error(t=t, args={"FAIL"}, loc=loc)
  37. t.error_count += 1
  38. }
  39. fail_now :: proc(t: ^T, msg := "", loc := #caller_location) {
  40. if msg != "" {
  41. error(t=t, args={"FAIL:", msg}, loc=loc)
  42. } else {
  43. error(t=t, args={"FAIL"}, loc=loc)
  44. }
  45. t.error_count += 1
  46. if t._fail_now != nil {
  47. t._fail_now()
  48. }
  49. }
  50. failed :: proc(t: ^T) -> bool {
  51. return t.error_count != 0
  52. }
  53. log :: proc(t: ^T, args: ..any, loc := #caller_location) {
  54. fmt.wprintln(t.w, ..args)
  55. }
  56. logf :: proc(t: ^T, format: string, args: ..any, loc := #caller_location) {
  57. fmt.wprintf(t.w, format, ..args)
  58. fmt.wprintln(t.w)
  59. }
  60. // cleanup registers a procedure and user_data, which will be called when the test, and all its subtests, complete
  61. // cleanup proceduers will be called in LIFO (last added, first called) order.
  62. cleanup :: proc(t: ^T, procedure: proc(rawptr), user_data: rawptr) {
  63. append(&t.cleanups, Internal_Cleanup{procedure, user_data})
  64. }
  65. expect :: proc(t: ^T, ok: bool, msg: string = "", loc := #caller_location) -> bool {
  66. if !ok {
  67. error(t=t, args={msg}, loc=loc)
  68. }
  69. return ok
  70. }
  71. expect_value :: proc(t: ^T, value, expected: $T, loc := #caller_location) -> bool where intrinsics.type_is_comparable(T) {
  72. ok := value == expected
  73. if !ok {
  74. errorf(t=t, format="expected %v, got %v", args={expected, value}, loc=loc)
  75. }
  76. return ok
  77. }
  78. set_fail_timeout :: proc(t: ^T, duration: time.Duration, loc := #caller_location) {
  79. _fail_timeout(t, duration, loc)
  80. }