strings.lisp - clic - Clic is an command line interactive client for gopher written in Common LISP
 (HTM) git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
       strings.lisp (6395B)
       ---
            1 ;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
            2 ;;;
            3 ;;; strings.lisp --- Tests for foreign string conversion.
            4 ;;;
            5 ;;; Copyright (C) 2005, James Bielman  <jamesjb@jamesjb.com>
            6 ;;; Copyright (C) 2007, Luis Oliveira  <loliveira@common-lisp.net>
            7 ;;;
            8 ;;; Permission is hereby granted, free of charge, to any person
            9 ;;; obtaining a copy of this software and associated documentation
           10 ;;; files (the "Software"), to deal in the Software without
           11 ;;; restriction, including without limitation the rights to use, copy,
           12 ;;; modify, merge, publish, distribute, sublicense, and/or sell copies
           13 ;;; of the Software, and to permit persons to whom the Software is
           14 ;;; furnished to do so, subject to the following conditions:
           15 ;;;
           16 ;;; The above copyright notice and this permission notice shall be
           17 ;;; included in all copies or substantial portions of the Software.
           18 ;;;
           19 ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
           20 ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
           21 ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
           22 ;;; NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
           23 ;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
           24 ;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
           25 ;;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
           26 ;;; DEALINGS IN THE SOFTWARE.
           27 ;;;
           28 
           29 (in-package #:cffi-tests)
           30 
           31 ;;;# Foreign String Conversion Tests
           32 ;;;
           33 ;;; With the implementation of encoding support, there are a lot of
           34 ;;; things that can go wrong with foreign string conversions.  This is
           35 ;;; a start at defining tests for strings and encoding conversion, but
           36 ;;; there needs to be a lot more.
           37 
           38 (babel:enable-sharp-backslash-syntax)
           39 
           40 ;;; *ASCII-TEST-STRING* contains the characters in the ASCII character
           41 ;;; set that we will convert to a foreign string and check against
           42 ;;; *ASCII-TEST-BYTES*.  We don't bother with control characters.
           43 ;;;
           44 ;;; FIXME: It would probably be good to move these tables into files
           45 ;;; in "tests/", especially if we ever want to get fancier and have
           46 ;;; tests for more encodings.
           47 (eval-when (:compile-toplevel :load-toplevel :execute)
           48   (defparameter *ascii-test-string*
           49     (concatenate 'string " !\"#$%&'()*+,-./0123456789:;"
           50                  "<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]"
           51                  "^_`abcdefghijklmnopqrstuvwxyz{|}~")))
           52 
           53 ;;; *ASCII-TEST-BYTES* contains the expected ASCII encoded values
           54 ;;; for each character in *ASCII-TEST-STRING*.
           55 (eval-when (:compile-toplevel :load-toplevel :execute)
           56   (defparameter *ascii-test-bytes*
           57     (let ((vector (make-array 95 :element-type '(unsigned-byte 8))))
           58       (loop for i from 0
           59             for code from 32 below 127
           60             do (setf (aref vector i) code)
           61             finally (return vector)))))
           62 
           63 ;;; Test basic consistency converting a string to and from Lisp using
           64 ;;; the default encoding.
           65 (deftest string.conversion.basic
           66     (with-foreign-string (s *ascii-test-string*)
           67       (foreign-string-to-lisp s))
           68   #.*ascii-test-string* 95)
           69 
           70 (deftest string.conversion.basic.2
           71     (with-foreign-string ((ptr size) "123" :null-terminated-p nil)
           72       (values (foreign-string-to-lisp ptr :count 3) size))
           73   "123" 3)
           74 
           75 ;;; Ensure that conversion of *ASCII-TEST-STRING* to a foreign buffer
           76 ;;; and back preserves ASCII encoding.
           77 (deftest string.encoding.ascii
           78     (with-foreign-string (s *ascii-test-string* :encoding :ascii)
           79       (let ((vector (make-array 95 :element-type '(unsigned-byte 8))))
           80         (loop for i from 0 below (length vector)
           81               do (setf (aref vector i) (mem-ref s :unsigned-char i)))
           82         vector))
           83   #.*ascii-test-bytes*)
           84 
           85 ;;; FIXME: bogus test. We need support for BOM or UTF-16{BE,LE}.
           86 (pushnew 'string.encoding.utf-16.basic rtest::*expected-failures*)
           87 
           88 ;;; Test UTF-16 conversion of a string back and forth.  Tests proper
           89 ;;; null terminator handling for wide character strings and ensures no
           90 ;;; byte order marks are added.  (Why no BOM? --luis)
           91 ;;;
           92 ;;; FIXME: an identical test using :UTF-16 wouldn't work because on
           93 ;;; little-endian architectures, :UTF-16 defaults to little-endian
           94 ;;; when writing and big-endian on reading because the BOM is
           95 ;;; suppressed.
           96 #-babel::8-bit-chars
           97 (progn
           98   (deftest string.encoding.utf-16le.basic
           99       (with-foreign-string (s *ascii-test-string* :encoding :utf-16le)
          100         (foreign-string-to-lisp s :encoding :utf-16le))
          101     #.*ascii-test-string* 190)
          102 
          103   (deftest string.encoding.utf-16be.basic
          104       (with-foreign-string (s *ascii-test-string* :encoding :utf-16be)
          105         (foreign-string-to-lisp s :encoding :utf-16be))
          106     #.*ascii-test-string* 190))
          107 
          108 ;;; Ensure that writing a long string into a short buffer does not
          109 ;;; attempt to write beyond the edge of the buffer, and that the
          110 ;;; resulting string is still null terminated.
          111 (deftest string.short-write.1
          112     (with-foreign-pointer (buf 6)
          113       (setf (mem-ref buf :unsigned-char 5) 70)
          114       (lisp-string-to-foreign "ABCDE" buf 5 :encoding :ascii)
          115       (values (mem-ref buf :unsigned-char 4)
          116               (mem-ref buf :unsigned-char 5)))
          117   0 70)
          118 
          119 #-babel::8-bit-chars
          120 (deftest string.encoding.utf-8.basic
          121     (with-foreign-pointer (buf 7 size)
          122       (let ((string (concatenate 'babel:unicode-string
          123                                  '(#\u03bb #\u00e3 #\u03bb))))
          124         (lisp-string-to-foreign string buf size :encoding :utf-8)
          125         (loop for i from 0 below size
          126               collect (mem-ref buf :unsigned-char i))))
          127   (206 187 195 163 206 187 0))
          128 
          129 (defparameter *basic-latin-alphabet* "abcdefghijklmnopqrstuvwxyz")
          130 
          131 (deftest string.encodings.all.basic
          132     (let (failed)
          133       ;;; FIXME: UTF-{32,16} and friends fail due to lack of BOM. See
          134       ;;; STRING.ENCODING.UTF-16.BASIC for more details.
          135       (dolist (encoding (remove-if (lambda (x)
          136                                      (member x '(:utf-32 :utf-16 :ucs-2)))
          137                                    (babel:list-character-encodings)))
          138         ;; (format t "Testing ~S~%" encoding)
          139         (with-foreign-string (ptr *basic-latin-alphabet* :encoding encoding)
          140           (let ((string (foreign-string-to-lisp ptr :encoding encoding)))
          141             ;; (format t "  got ~S~%" string)
          142             (unless (string= *basic-latin-alphabet* string)
          143               (push encoding failed)))))
          144       failed)
          145   nil)
          146 
          147 ;;; rt: make sure *default-foreign-enconding* binds to a keyword
          148 (deftest string.encodings.default
          149     (keywordp *default-foreign-encoding*)
          150   t)