regexp.test 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. ;;;; regexp.test --- test Guile's regular expression functions -*- scheme -*-
  2. ;;;; Jim Blandy <jimb@red-bean.com> --- September 1999
  3. ;;;;
  4. ;;;; Copyright (C) 1999, 2004 Free Software Foundation, Inc.
  5. ;;;;
  6. ;;;; This program is free software; you can redistribute it and/or modify
  7. ;;;; it under the terms of the GNU General Public License as published by
  8. ;;;; the Free Software Foundation; either version 2, or (at your option)
  9. ;;;; any later version.
  10. ;;;;
  11. ;;;; This program is distributed in the hope that it will be useful,
  12. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;;; GNU General Public License for more details.
  15. ;;;;
  16. ;;;; You should have received a copy of the GNU General Public License
  17. ;;;; along with this software; see the file COPYING. If not, write to
  18. ;;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  19. ;;;; Boston, MA 02110-1301 USA
  20. (use-modules (test-suite lib)
  21. (ice-9 regex))
  22. ;;; Run a regexp-substitute or regexp-substitute/global test, once
  23. ;;; providing a real port and once providing #f, requesting direct
  24. ;;; string output.
  25. (define (vary-port func expected . args)
  26. (pass-if "port is string port"
  27. (equal? expected
  28. (call-with-output-string
  29. (lambda (port)
  30. (apply func port args)))))
  31. (pass-if "port is #f"
  32. (equal? expected
  33. (apply func #f args))))
  34. (define (object->string obj)
  35. (call-with-output-string
  36. (lambda (port)
  37. (write obj port))))
  38. ;;;
  39. ;;; make-regexp
  40. ;;;
  41. (with-test-prefix "make-regexp"
  42. (pass-if-exception "no args" exception:wrong-num-args
  43. (make-regexp))
  44. (pass-if-exception "bad pat arg" exception:wrong-type-arg
  45. (make-regexp 'blah))
  46. ;; in guile prior to 1.6.5 make-regex didn't validate its flags args
  47. (pass-if-exception "bad arg 2" exception:wrong-type-arg
  48. (make-regexp "xyz" 'abc))
  49. (pass-if-exception "bad arg 3" exception:wrong-type-arg
  50. (make-regexp "xyz" regexp/icase 'abc)))
  51. ;;;
  52. ;;; regexp-quote
  53. ;;;
  54. (with-test-prefix "regexp-quote"
  55. (pass-if-exception "no args" exception:wrong-num-args
  56. (regexp-quote))
  57. (pass-if-exception "bad string arg" exception:wrong-type-arg
  58. (regexp-quote 'blah))
  59. (let ((lst `((regexp/basic ,regexp/basic)
  60. (regexp/extended ,regexp/extended)))
  61. ;; string of all characters, except #\nul which doesn't work because
  62. ;; it's the usual end-of-string for the underlying C regexec()
  63. (allchars (list->string (map integer->char
  64. (cdr (iota char-code-limit))))))
  65. (for-each
  66. (lambda (elem)
  67. (let ((name (car elem))
  68. (flag (cadr elem)))
  69. (with-test-prefix name
  70. ;; try on each individual character, except #\nul
  71. (do ((i 1 (1+ i)))
  72. ((>= i char-code-limit))
  73. (let* ((c (integer->char i))
  74. (s (string c))
  75. (q (regexp-quote s)))
  76. (pass-if (list "char" i c s q)
  77. (let ((m (regexp-exec (make-regexp q flag) s)))
  78. (and (= 0 (match:start m))
  79. (= 1 (match:end m)))))))
  80. ;; try on pattern "aX" where X is each character, except #\nul
  81. ;; this exposes things like "?" which are special only when they
  82. ;; follow a pattern to repeat or whatever ("a" in this case)
  83. (do ((i 1 (1+ i)))
  84. ((>= i char-code-limit))
  85. (let* ((c (integer->char i))
  86. (s (string #\a c))
  87. (q (regexp-quote s)))
  88. (pass-if (list "string \"aX\"" i c s q)
  89. (let ((m (regexp-exec (make-regexp q flag) s)))
  90. (and (= 0 (match:start m))
  91. (= 2 (match:end m)))))))
  92. (pass-if "string of all chars"
  93. (let ((m (regexp-exec (make-regexp (regexp-quote allchars)
  94. flag) allchars)))
  95. (and (= 0 (match:start m))
  96. (= (string-length allchars) (match:end m))))))))
  97. lst)))
  98. ;;;
  99. ;;; regexp-substitute
  100. ;;;
  101. (with-test-prefix "regexp-substitute"
  102. (let ((match
  103. (string-match "patleft(sub1)patmid(sub2)patright"
  104. "contleftpatleftsub1patmidsub2patrightcontright")))
  105. (define (try expected . args)
  106. (with-test-prefix (object->string args)
  107. (apply vary-port regexp-substitute expected match args)))
  108. (try "")
  109. (try "string1" "string1")
  110. (try "string1string2" "string1" "string2")
  111. (try "patleftsub1patmidsub2patright" 0)
  112. (try "hi-patleftsub1patmidsub2patright-bye" "hi-" 0 "-bye")
  113. (try "sub1" 1)
  114. (try "hi-sub1-bye" "hi-" 1 "-bye")
  115. (try "hi-sub2-bye" "hi-" 2 "-bye")
  116. (try "contleft" 'pre)
  117. (try "contright" 'post)
  118. (try "contrightcontleft" 'post 'pre)
  119. (try "contrightcontleftcontrightcontleft" 'post 'pre 'post 'pre)
  120. (try "contrightsub2sub1contleft" 'post 2 1 'pre)
  121. (try "foosub1sub1sub1sub1bar" "foo" 1 1 1 1 "bar")))
  122. (with-test-prefix "regexp-substitute/global"
  123. (define (try expected . args)
  124. (with-test-prefix (object->string args)
  125. (apply vary-port regexp-substitute/global expected args)))
  126. (try "hi" "a(x*)b" "ab" "hi")
  127. (try "" "a(x*)b" "ab" 1)
  128. (try "xx" "a(x*)b" "axxb" 1)
  129. (try "xx" "a(x*)b" "_axxb_" 1)
  130. (try "pre" "a(x*)b" "preaxxbpost" 'pre)
  131. (try "post" "a(x*)b" "preaxxbpost" 'post)
  132. (try "string" "x" "string" 'pre "y" 'post)
  133. (try "4" "a(x*)b" "_axxb_" (lambda (m)
  134. (number->string (match:end m 1))))
  135. (try "_aybycyd_" "x+" "_axbxxcxxxd_" 'pre "y" 'post)
  136. ;; This should not go into an infinite loop, just because the regexp
  137. ;; can match the empty string. This test also kind of beats on our
  138. ;; definition of where a null string can match.
  139. (try "y_yaybycydy_y" "x*" "_axbxxcxxxd_" 'pre "y" 'post)
  140. ;; These kind of bother me. The extension from regexp-substitute to
  141. ;; regexp-substitute/global is only natural if your item list
  142. ;; includes both pre and post. If those are required, why bother
  143. ;; to include them at all?
  144. (try "4:7:12:_" "a(x*)b" "_axxbaxbaxxxb_"
  145. (lambda (m) (number->string (match:end m 1))) ":"
  146. 'post)
  147. (try "4:10:19:_:19:10:4" "a(x*)b" "_axxbaxxxxbaxxxxxxxb_"
  148. (lambda (m) (number->string (match:end m 1))) ":"
  149. 'post
  150. ":" (lambda (m) (number->string (match:end m 1))))
  151. ;; Jan Nieuwenhuizen's bug, 2 Sep 1999
  152. (try "" "_" (make-string 500 #\_)
  153. 'post))