test_core_strings.odin 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package test_core_strings
  2. import "core:strings"
  3. import "core:testing"
  4. import "core:fmt"
  5. import "core:os"
  6. import "base:runtime"
  7. import "core:mem"
  8. TEST_count := 0
  9. TEST_fail := 0
  10. when ODIN_TEST {
  11. expect :: testing.expect
  12. log :: testing.log
  13. } else {
  14. expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
  15. TEST_count += 1
  16. if !condition {
  17. TEST_fail += 1
  18. fmt.printf("[%v] %v\n", loc, message)
  19. return
  20. }
  21. }
  22. log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
  23. fmt.printf("[%v] ", loc)
  24. fmt.printf("log: %v\n", v)
  25. }
  26. }
  27. main :: proc() {
  28. t := testing.T{}
  29. test_index_any_small_string_not_found(&t)
  30. test_index_any_larger_string_not_found(&t)
  31. test_index_any_small_string_found(&t)
  32. test_index_any_larger_string_found(&t)
  33. test_cut(&t)
  34. test_case_conversion(&t)
  35. fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
  36. if TEST_fail > 0 {
  37. os.exit(1)
  38. }
  39. }
  40. @test
  41. test_index_any_small_string_not_found :: proc(t: ^testing.T) {
  42. index := strings.index_any(".", "/:\"")
  43. expect(t, index == -1, "index_any should be negative")
  44. }
  45. @test
  46. test_index_any_larger_string_not_found :: proc(t: ^testing.T) {
  47. index := strings.index_any("aaaaaaaa.aaaaaaaa", "/:\"")
  48. expect(t, index == -1, "index_any should be negative")
  49. }
  50. @test
  51. test_index_any_small_string_found :: proc(t: ^testing.T) {
  52. index := strings.index_any(".", "/:.\"")
  53. expect(t, index == 0, "index_any should be 0")
  54. }
  55. @test
  56. test_index_any_larger_string_found :: proc(t: ^testing.T) {
  57. index := strings.index_any("aaaaaaaa:aaaaaaaa", "/:\"")
  58. expect(t, index == 8, "index_any should be 8")
  59. }
  60. @test
  61. test_last_index_any_small_string_found :: proc(t: ^testing.T) {
  62. index := strings.last_index_any(".", "/:.\"")
  63. expect(t, index == 0, "last_index_any should be 0")
  64. }
  65. @test
  66. test_last_index_any_small_string_not_found :: proc(t: ^testing.T) {
  67. index := strings.last_index_any(".", "/:\"")
  68. expect(t, index == -1, "last_index_any should be -1")
  69. }
  70. Cut_Test :: struct {
  71. input: string,
  72. offset: int,
  73. length: int,
  74. output: string,
  75. }
  76. cut_tests :: []Cut_Test{
  77. {"some example text", 0, 4, "some" },
  78. {"some example text", 2, 2, "me" },
  79. {"some example text", 5, 7, "example" },
  80. {"some example text", 5, 0, "example text"},
  81. {"恥ずべきフクロウ", 4, 0, "フクロウ" },
  82. }
  83. @test
  84. test_cut :: proc(t: ^testing.T) {
  85. for test in cut_tests {
  86. res := strings.cut(test.input, test.offset, test.length)
  87. defer delete(res)
  88. msg := fmt.tprintf("cut(\"%v\", %v, %v) expected to return \"%v\", got \"%v\"",
  89. test.input, test.offset, test.length, test.output, res)
  90. expect(t, res == test.output, msg)
  91. }
  92. }
  93. Case_Kind :: enum {
  94. Lower_Space_Case,
  95. Upper_Space_Case,
  96. Lower_Snake_Case,
  97. Upper_Snake_Case,
  98. Lower_Kebab_Case,
  99. Upper_Kebab_Case,
  100. Camel_Case,
  101. Pascal_Case,
  102. Ada_Case,
  103. }
  104. Case_Proc :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error)
  105. test_cases := [Case_Kind]struct{s: string, p: Case_Proc}{
  106. .Lower_Space_Case = {"hellope world", to_lower_space_case},
  107. .Upper_Space_Case = {"HELLOPE WORLD", to_upper_space_case},
  108. .Lower_Snake_Case = {"hellope_world", to_snake_case},
  109. .Upper_Snake_Case = {"HELLOPE_WORLD", to_upper_snake_case},
  110. .Lower_Kebab_Case = {"hellope-world", to_kebab_case},
  111. .Upper_Kebab_Case = {"HELLOPE-WORLD", to_upper_kebab_case},
  112. .Camel_Case = {"hellopeWorld", to_camel_case},
  113. .Pascal_Case = {"HellopeWorld", to_pascal_case},
  114. .Ada_Case = {"Hellope_World", to_ada_case},
  115. }
  116. to_lower_space_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) {
  117. return strings.to_delimiter_case(r, ' ', false, allocator)
  118. }
  119. to_upper_space_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) {
  120. return strings.to_delimiter_case(r, ' ', true, allocator)
  121. }
  122. // NOTE: we have these wrappers as having #optional_allocator_error changes the type to not be equivalent
  123. to_snake_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) { return strings.to_snake_case(r, allocator) }
  124. to_upper_snake_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) { return strings.to_upper_snake_case(r, allocator) }
  125. to_kebab_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) { return strings.to_kebab_case(r, allocator) }
  126. to_upper_kebab_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) { return strings.to_upper_kebab_case(r, allocator) }
  127. to_camel_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) { return strings.to_camel_case(r, allocator) }
  128. to_pascal_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) { return strings.to_pascal_case(r, allocator) }
  129. to_ada_case :: proc(r: string, allocator: runtime.Allocator) -> (string, mem.Allocator_Error) { return strings.to_ada_case(r, allocator) }
  130. @test
  131. test_case_conversion :: proc(t: ^testing.T) {
  132. for entry in test_cases {
  133. for test_case, case_kind in test_cases {
  134. result, err := entry.p(test_case.s, context.allocator)
  135. msg := fmt.tprintf("ERROR: We got the allocation error '{}'\n", err)
  136. expect(t, err == nil, msg)
  137. defer delete(result)
  138. msg = fmt.tprintf("ERROR: Input `{}` to converter {} does not match `{}`, got `{}`.\n", test_case.s, case_kind, entry.s, result)
  139. expect(t, result == entry.s, msg)
  140. }
  141. }
  142. }