548 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Scheme
		
	
	
	
	
	
		
		
			
		
	
	
			548 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Scheme
		
	
	
	
	
	
|  | #!/usr/bin/env pika-script-fu-interpreter-3.0 | ||
|  | 
 | ||
|  | ; Test byte, file/string ports and string handling. | ||
|  | 
 | ||
|  | (define temp-path | ||
|  |   (string-append (car (pika-pikarc-query "temp-path")) "/")) | ||
|  | 
 | ||
|  | (define (plugin-tmp-filepath name) | ||
|  |   (string-append temp-path "script-fu-test9-" name ".txt")) | ||
|  | 
 | ||
|  | ; ---------- Helper functions ---------- | ||
|  | 
 | ||
|  | (define (make-testresult success error-message) | ||
|  |   (list success error-message)) | ||
|  | (define (testresult-success x) (car x)) | ||
|  | (define (testresult-error x) (cadr x)) | ||
|  | 
 | ||
|  | (define (displayln msg) | ||
|  |   (display msg) | ||
|  |   (newline)) | ||
|  | 
 | ||
|  | (define (trim char chars) | ||
|  |   (if (= (char->integer char) (char->integer (car chars))) | ||
|  |       (trim char (cdr chars)) | ||
|  |       chars)) | ||
|  | 
 | ||
|  | (define (rtrim str) | ||
|  |   (list->string (reverse (trim #\space (reverse (string->list str)))))) | ||
|  | 
 | ||
|  | (define (any->string any) | ||
|  |   (let* ((to-string | ||
|  |            (lambda (any) | ||
|  |              (let* ((str (make-string 256))) | ||
|  |                (call-with-output-string str | ||
|  |                  (lambda (port) (write any port))) | ||
|  |                str)))) | ||
|  |     (rtrim (to-string any)))) | ||
|  | 
 | ||
|  | (define (write-all-bytes port bytes) | ||
|  |   (if (null? bytes) | ||
|  |     '() | ||
|  |     (begin | ||
|  |       (write-byte (car bytes) port) | ||
|  |       (write-all-bytes port (cdr bytes))))) | ||
|  | 
 | ||
|  | (define (bytes->string bytes) | ||
|  |   (let* ((str (make-string (length bytes)))) | ||
|  |     (call-with-output-string str | ||
|  |       (lambda (port) (map (lambda (b) (write-byte b port)) bytes))) | ||
|  |     str)) | ||
|  | 
 | ||
|  | (define (with-string open-function str function) | ||
|  |   (let ((port (open-function str))) | ||
|  |     (if (port? port) | ||
|  |       (let ((result '())) | ||
|  |         (set! result (function port)) | ||
|  |         (close-port port) | ||
|  |         result) | ||
|  |       (make-testresult #f "Failed to open string for string port!")))) | ||
|  | 
 | ||
|  | (define (call-with-input-string str function) | ||
|  |   (with-string open-input-string str function)) | ||
|  | 
 | ||
|  | (define (call-with-output-string str function) | ||
|  |   (with-string open-output-string str function)) | ||
|  | 
 | ||
|  | ; Loops from i to n-1. | ||
|  | (define (loop i n function) | ||
|  |   (if (< i n) | ||
|  |     (begin | ||
|  |       (function i) | ||
|  |       (loop (+ i 1) n function)) | ||
|  |     #t)) | ||
|  | 
 | ||
|  | (define (assert code) | ||
|  |   (let* ((old-error-hook *error-hook*) | ||
|  |          (exceptions '()) | ||
|  |          (append-exception | ||
|  |            (lambda (x) | ||
|  |              (if (null? exceptions) | ||
|  |                (set! exceptions "Exception: ") | ||
|  |                '()) | ||
|  |              (set! exceptions (string-append exceptions " " (any->string x))))) | ||
|  |          (assert-error-hook | ||
|  |            (lambda (xs) | ||
|  |              (map append-exception xs) | ||
|  |              (old-error-hook xs))) | ||
|  |          (result #f)) | ||
|  |     (set! *error-hook* assert-error-hook) | ||
|  |     (catch '() (set! result (eval code))) | ||
|  |     (set! *error-hook* old-error-hook) | ||
|  |     (if (and (null? exceptions) | ||
|  |              result) | ||
|  |       (make-testresult result '()) | ||
|  |       (make-testresult #f | ||
|  |         (if (null? exceptions) | ||
|  |           (string-append "Assertion failed: " (any->string code)) | ||
|  |           exceptions))))) | ||
|  | 
 | ||
|  | ; ---------- Test data ---------- | ||
|  | 
 | ||
|  | (define test-data-1byte | ||
|  |   (map integer->byte (list 65))) ; 65 = A | ||
|  | 
 | ||
|  | (define test-data-256bytes | ||
|  |   (let ((result '())) | ||
|  |     (loop 0 256 (lambda (i) (set! result (cons i result)))) | ||
|  |   (reverse (map integer->byte result)))) | ||
|  | 
 | ||
|  | (define test-data-1char | ||
|  |   (map integer->byte (list 228 189 160))) ; 你 (UTF-8) | ||
|  | 
 | ||
|  | (define test-data-2chars | ||
|  |   (map integer->byte | ||
|  |     (list 228 189 160    ; 你 (UTF-8) | ||
|  |           229 165 189))) ; 好 (UTF-8) | ||
|  | 
 | ||
|  | ; ---------- Tests start here --------- | ||
|  | 
 | ||
|  | ; Each test function should be individually executable or | ||
|  | ; have a wrapper function that can be individually executed. | ||
|  | 
 | ||
|  | ; ----- Test byte functions ----- | ||
|  | 
 | ||
|  | ; Ensure all integers with values in the range 0-255 | ||
|  | ; can be converted to a byte and then back successfully. | ||
|  | (define (test-byte-conversion) | ||
|  |   (let* ((errors '()) | ||
|  |          (failed | ||
|  |            (lambda (error) | ||
|  |              (if (null? errors) | ||
|  |                (set! errors "") | ||
|  |                '()) | ||
|  |              (set! errors (string-append errors error)))) | ||
|  |          (test-conversion | ||
|  |            (lambda (i) | ||
|  |              (let ((result (assert `(= (byte->integer (integer->byte ,i)) ,i)))) | ||
|  |                (if (not (testresult-success result)) | ||
|  |                  (failed (testresult-error result)) | ||
|  |                  '()))))) | ||
|  |     (loop 0 256 test-conversion) | ||
|  |     (make-testresult (null? errors) errors))) | ||
|  | 
 | ||
|  | ; Ensure byte? returns true with bytes. | ||
|  | (define (test-byte?-byte) | ||
|  |   (assert '(byte? (integer->byte 10)))) | ||
|  | 
 | ||
|  | ; Ensure byte? returns false with integers. | ||
|  | (define (test-byte?-integer) | ||
|  |   (assert '(not (byte? 10)))) | ||
|  | 
 | ||
|  | ; Ensure byte? returns false with characters. | ||
|  | (define (test-byte?-char) | ||
|  |   (assert '(not (byte? #\A)))) | ||
|  | 
 | ||
|  | ; Ensure atom? works with bytes. | ||
|  | (define (test-byte-atom?) | ||
|  |   (assert '(atom? (integer->byte 128)))) | ||
|  | 
 | ||
|  | ; Ensure atom->string works with bytes. | ||
|  | (define (test-byte-atom->string) | ||
|  |   (assert '(string=? (atom->string (integer->byte 65)) "A"))) | ||
|  | 
 | ||
|  | ; ----- Read tests for ports ----- | ||
|  | 
 | ||
|  | ; The same tests are used for file and string ports, | ||
|  | ; as they must behave identically. These do not have to be | ||
|  | ; individually executable, as they require the port to be set up. | ||
|  | 
 | ||
|  | ; Ensure that we can read a single byte. | ||
|  | ; Test data: test-data-1byte | ||
|  | (define (test-read-byte-single port) | ||
|  |   (assert `(= (byte->integer (read-byte ,port)) 65))) ; 65 = A | ||
|  | 
 | ||
|  | ; Ensure peek-byte returns the correct value and does not remove bytes from the port. | ||
|  | ; Test data: test-data-1byte | ||
|  | (define (test-read-byte-peek port) | ||
|  |   (assert | ||
|  |     `(and (= (byte->integer (peek-byte ,port)) 65) ; 65 = A | ||
|  |           (not (eof-object? (peek-byte ,port)))))) | ||
|  | 
 | ||
|  | ; Ensure every single possible byte value can be read. | ||
|  | ; Test data: test-data-256bytes | ||
|  | (define (test-read-byte-all-values port) | ||
|  |   (let* ((errors '()) | ||
|  |          (failure (lambda () )) | ||
|  |          (try | ||
|  |            (lambda (i) | ||
|  |              (let ((result (assert `(= (byte->integer (read-byte ,port)) ,i)))) | ||
|  |                (if (not (testresult-success result)) | ||
|  |                  (failure (testresult-error result)) | ||
|  |                  '()))))) | ||
|  |     (loop 0 256 try) | ||
|  |     (make-testresult (null? errors) errors))) | ||
|  | 
 | ||
|  | ; Ensure that we can read a single char (not multi-byte). | ||
|  | ; Test data: test-data-1byte | ||
|  | (define (test-read-char-single-ascii port) | ||
|  |   (assert `(= (char->integer (read-char ,port)) 65))) ; 65 = A | ||
|  | 
 | ||
|  | ; Ensure that we can read a single multi-byte char. | ||
|  | ; Note: char->integer returns the integer value of a gunichar, | ||
|  | ; which is a UTF-32 or UCS-4 character code. | ||
|  | ; Test data: test-data-1char | ||
|  | (define (test-read-char-single port) | ||
|  |   (assert `(= (char->integer (read-char ,port)) 20320))) ; 20320 = 你 (UTF-32) | ||
|  | 
 | ||
|  | ; Ensure peek-char returns the correct value and does not | ||
|  | ; remove chars from the port. | ||
|  | ; Test data: test-data-1char | ||
|  | (define (test-read-char-peek port) | ||
|  |   (assert | ||
|  |     `(and (= (char->integer (peek-char ,port)) 20320) ; 20320 = 你 (UTF-32) | ||
|  |           (not (eof-object? (peek-char ,port)))))) | ||
|  | 
 | ||
|  | ; Ensure that we can read multiple multi-byte chars from a file. | ||
|  | ; Test data: test-data-2chars | ||
|  | (define (test-read-char-multiple port) | ||
|  |   (assert | ||
|  |     `(and (= (char->integer (read-char ,port)) 20320)    ; 20320 = 你 (UTF-32) | ||
|  |           (= (char->integer (read-char ,port)) 22909)))) ; 22909 = 好 (UTF-32) | ||
|  | 
 | ||
|  | ; Ensure read-byte can not read past EOF. | ||
|  | ; Test data: test-data-1byte | ||
|  | (define (test-read-byte-overflow port) | ||
|  |   (assert `(begin (read-byte ,port) (eof-object? (read-byte ,port))))) | ||
|  | 
 | ||
|  | ; Ensure read-char can not read past EOF. | ||
|  | ; Test data: test-data-1char | ||
|  | (define (test-read-char-overflow port) | ||
|  |   (assert `(begin (read-char ,port) (eof-object? (read-char ,port))))) | ||
|  | 
 | ||
|  | ; ----- Write tests for ports ----- | ||
|  | 
 | ||
|  | ; These tests come in pairs, we write to a port and then read from it to verify. | ||
|  | 
 | ||
|  | (define (test-write-byte-single port) | ||
|  |   (assert `(begin (write-byte (integer->byte 77) ,port) #t))) ; 77 == M | ||
|  | (define (test-write-byte-single-verify port) | ||
|  |   (assert `(= (byte->integer (read-byte ,port)) 77))) ; 77 == M | ||
|  | 
 | ||
|  | (define (test-write-char-single port) | ||
|  |   (assert `(begin (write-char (car (string->list "你")) ,port) #t))) | ||
|  | (define (test-write-char-single-verify port) | ||
|  |   (assert `(= (char->integer (read-char ,port)) 20320))) ; 20320 = 你 (UTF-32) | ||
|  | 
 | ||
|  | ; ----- String port tests ----- | ||
|  | 
 | ||
|  | ; Wrapper functions for the port read and write tests. | ||
|  | 
 | ||
|  | (define (test-input-string-port test-data test-function) | ||
|  |   (call-with-input-string (bytes->string test-data) test-function)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-byte-single) | ||
|  |   (test-input-string-port test-data-1byte test-read-byte-single)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-byte-peek) | ||
|  |   (test-input-string-port test-data-1byte test-read-byte-peek)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-byte-all-values) | ||
|  |   (test-input-string-port test-data-256bytes test-read-byte-all-values)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-char-single-ascii) | ||
|  |   (test-input-string-port test-data-1byte test-read-char-single-ascii)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-char-single) | ||
|  |   (test-input-string-port test-data-1char test-read-char-single)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-char-peek) | ||
|  |   (test-input-string-port test-data-1char test-read-char-peek)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-char-multiple) | ||
|  |   (test-input-string-port test-data-2chars test-read-char-multiple)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-byte-overflow) | ||
|  |   (test-input-string-port test-data-1byte test-read-byte-overflow)) | ||
|  | 
 | ||
|  | (define (test-string-port-read-char-overflow) | ||
|  |   (test-input-string-port test-data-1char test-read-char-overflow)) | ||
|  | 
 | ||
|  | (define (test-string-port-write test-data write-test verify-write-test) | ||
|  |   (let* ((str (make-string (length test-data))) | ||
|  |          (write-result (call-with-output-string str write-test)) | ||
|  |          (read-result (call-with-input-string str verify-write-test))) | ||
|  |     (if (and (testresult-success write-result) | ||
|  |              (testresult-success read-result)) | ||
|  |       (make-testresult #t '()) | ||
|  |       (make-testresult #f | ||
|  |         (string-append | ||
|  |           "write-error: " (any->string (testresult-error write-result)) ", " | ||
|  |          "read-error: " (any->string (testresult-error read-result))))))) | ||
|  | 
 | ||
|  | (define (test-string-port-write-byte-single) | ||
|  |   (test-string-port-write test-data-1byte test-write-byte-single test-write-byte-single-verify)) | ||
|  | 
 | ||
|  | (define (test-string-port-write-char-single) | ||
|  |   (test-string-port-write test-data-1char test-write-char-single test-write-char-single-verify)) | ||
|  | 
 | ||
|  | ; ----- File port tests ----- | ||
|  | 
 | ||
|  | ; Wrapper functions for the port read and write tests. | ||
|  | 
 | ||
|  | (define (test-input-file-port test-data test-function) | ||
|  |   (let ((filepath (plugin-tmp-filepath "fileport"))) | ||
|  |     (call-with-output-file filepath (lambda (port) (write-all-bytes port test-data))) | ||
|  |     (call-with-input-file filepath test-function))) | ||
|  | 
 | ||
|  | (define (test-file-port-read-byte-single) | ||
|  |   (test-input-file-port test-data-1byte test-read-byte-single)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-byte-single) | ||
|  |   (test-input-file-port test-data-1byte test-read-byte-single)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-byte-peek) | ||
|  |   (test-input-file-port test-data-1byte test-read-byte-peek)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-byte-all-values) | ||
|  |   (test-input-file-port test-data-256bytes test-read-byte-all-values)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-char-single-ascii) | ||
|  |   (test-input-file-port test-data-1byte test-read-char-single-ascii)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-char-single) | ||
|  |   (test-input-file-port test-data-1char test-read-char-single)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-char-peek) | ||
|  |   (test-input-file-port test-data-1char test-read-char-peek)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-char-multiple) | ||
|  |   (test-input-file-port test-data-2chars test-read-char-multiple)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-byte-overflow) | ||
|  |   (test-input-file-port test-data-1byte test-read-byte-overflow)) | ||
|  | 
 | ||
|  | (define (test-file-port-read-char-overflow) | ||
|  |   (test-input-file-port test-data-1char test-read-char-overflow)) | ||
|  | 
 | ||
|  | (define (test-file-port-write test-data write-test verify-write-test) | ||
|  |   (let* ((filepath (plugin-tmp-filepath "fileport")) | ||
|  |          (write-result (call-with-output-file filepath write-test)) | ||
|  |          (read-result (call-with-input-file filepath verify-write-test))) | ||
|  |     (if (and (testresult-success write-result) | ||
|  |              (testresult-success read-result)) | ||
|  |       (make-testresult #t '()) | ||
|  |       (make-testresult #f | ||
|  |         (string-append | ||
|  |           "write-error: " (any->string (testresult-error write-result)) ", " | ||
|  |           "read-error: " (any->string (testresult-error read-result))))))) | ||
|  | 
 | ||
|  | (define (test-file-port-write-byte-single) | ||
|  |   (test-string-port-write | ||
|  |     test-data-1byte test-write-byte-single test-write-byte-single-verify)) | ||
|  | 
 | ||
|  | (define (test-file-port-write-char-single) | ||
|  |   (test-string-port-write | ||
|  |     test-data-1char test-write-char-single test-write-char-single-verify)) | ||
|  | 
 | ||
|  | ; ----- Generic string tests ----- | ||
|  | 
 | ||
|  | ; Ensure basic string functions work. | ||
|  | 
 | ||
|  | (define (test-string-length) | ||
|  |   (assert '(= (string-length "Hello") 5))) | ||
|  | 
 | ||
|  | (define (test-string-length-multibyte) | ||
|  |   (assert '(= (string-length "你好") 2))) | ||
|  | 
 | ||
|  | (define (test-string->list-length) | ||
|  |   (assert '(= (length (string->list "Hello")) 5))) | ||
|  | 
 | ||
|  | (define (test-string->list-length-multibyte) | ||
|  |   (assert '(= (length (string->list "你好")) 2))) | ||
|  | 
 | ||
|  | (define (test-string-first-char) | ||
|  |   (assert '(= (char->integer (car (string->list "Hello"))) 72))) ; 72 = H | ||
|  | 
 | ||
|  | (define (test-string-first-char-multibyte) | ||
|  |   (assert '(= (char->integer (car (string->list "你好"))) 20320))) ; 20320 = 你 (UTF-32) | ||
|  | 
 | ||
|  | (define (test-string-overflow) | ||
|  |   (assert '(null? (cdr (string->list "H"))))) | ||
|  | 
 | ||
|  | (define (test-string-overflow-multibyte) | ||
|  |   (assert '(null? (cdr (string->list "你"))))) | ||
|  | 
 | ||
|  | ; ----- Generic string tests on strings created using string port ----- | ||
|  | 
 | ||
|  | ; Test string functions on strings which are created by writing bytes into | ||
|  | ; a string port. | ||
|  | 
 | ||
|  | ; Write byte sequence of 你 into a string and ensure string-count returns 1. | ||
|  | (define (test-string-port-string-count) | ||
|  |   (let* ((str (make-string 3)) | ||
|  |      (port (open-output-string str))) | ||
|  |   (begin | ||
|  |     ; 你 = E4 BD A0 = 228 189 160 | ||
|  |     (write-byte (integer->byte 228) port) | ||
|  |     (write-byte (integer->byte 189) port) | ||
|  |     (write-byte (integer->byte 160) port) | ||
|  |     (close-port port) | ||
|  |     (assert | ||
|  |       `(and (= (char->integer (car (string->list ,str))) 20320) ; 20320 = 你 (UTF-32) | ||
|  |             (= (string-length ,str) 1)))))) | ||
|  | 
 | ||
|  | ; ---------- Test Execution ---------- | ||
|  | 
 | ||
|  | ; Count test results. | ||
|  | (define tests-succeeded 0) | ||
|  | (define tests-failed 0) | ||
|  | 
 | ||
|  | (define (test-succeeded) | ||
|  |   (set! tests-succeeded (+ tests-succeeded 1)) | ||
|  |   (display "SUCCESS") | ||
|  |   (newline)) | ||
|  | (define (test-failed msg) | ||
|  |   (set! tests-failed (+ tests-failed 1)) | ||
|  |   (display "FAILED") (newline) | ||
|  |   (display msg) (newline)) | ||
|  | 
 | ||
|  | (define (run-test test) | ||
|  |   (display test) (display ": ") | ||
|  |   (let ((result ((eval test)))) | ||
|  |     (if (car result) | ||
|  |       (test-succeeded) | ||
|  |       (test-failed (cdr result))))) | ||
|  | 
 | ||
|  | (define (run-tests . tests) | ||
|  |   (map run-test tests)) | ||
|  | 
 | ||
|  | (define (run-byte-tests) | ||
|  |   (run-tests | ||
|  |     'test-byte-conversion | ||
|  |     'test-byte?-byte | ||
|  |     'test-byte?-integer | ||
|  |     'test-byte?-char | ||
|  |     'test-byte-atom? | ||
|  |     'test-byte-atom->string)) | ||
|  | 
 | ||
|  | (define (run-string-port-tests) | ||
|  |   (run-tests | ||
|  |     'test-string-port-read-byte-single | ||
|  |     'test-string-port-read-byte-peek | ||
|  |     'test-string-port-read-byte-all-values | ||
|  |     'test-string-port-read-char-single-ascii | ||
|  |     'test-string-port-read-char-single | ||
|  |     'test-string-port-read-char-peek | ||
|  |     'test-string-port-read-char-multiple | ||
|  |     'test-string-port-read-byte-overflow | ||
|  |     'test-string-port-read-char-overflow | ||
|  |     'test-string-port-write-byte-single | ||
|  |     'test-string-port-write-char-single)) | ||
|  | 
 | ||
|  | (define (run-file-port-tests) | ||
|  |   (run-tests | ||
|  |     'test-file-port-read-byte-single | ||
|  |     'test-file-port-read-byte-peek | ||
|  |     'test-file-port-read-byte-all-values | ||
|  |     'test-file-port-read-char-single-ascii | ||
|  |     'test-file-port-read-char-single | ||
|  |     'test-file-port-read-char-peek | ||
|  |     'test-file-port-read-char-multiple | ||
|  |     'test-file-port-read-byte-overflow | ||
|  |     'test-file-port-read-char-overflow | ||
|  |     'test-file-port-write-byte-single | ||
|  |     'test-file-port-write-char-single)) | ||
|  | 
 | ||
|  | (define (run-string-tests) | ||
|  |   (run-tests | ||
|  |     'test-string-length | ||
|  |     'test-string-length-multibyte | ||
|  |     'test-string->list-length | ||
|  |     'test-string->list-length-multibyte | ||
|  |     'test-string-first-char | ||
|  |     'test-string-first-char-multibyte | ||
|  |     'test-string-overflow | ||
|  |     'test-string-overflow-multibyte)) | ||
|  | 
 | ||
|  | (define (run-string-tests-string-port) | ||
|  |   (run-tests | ||
|  |     'test-string-port-string-count)) | ||
|  | 
 | ||
|  | (define (run-string-tests-string-port) | ||
|  |   (run-test 'test-string-port-string-count)) | ||
|  | 
 | ||
|  | (define (run-all-tests) | ||
|  |   (displayln "========== Information ==========") | ||
|  |   (displayln "To run a single test individually, specify the name of the test.") | ||
|  |   (displayln (string-append "Temporary files with format 'script-fu-test9-*.txt' can be found in: " temp-path)) | ||
|  |   (newline) | ||
|  |   (displayln "========== Testing byte functions ==========") | ||
|  |   (run-byte-tests) | ||
|  |   (newline) | ||
|  |   (displayln "========== Testing string port ==========") | ||
|  |   (run-string-port-tests) | ||
|  |   (newline) | ||
|  |   (displayln "========== Testing string functions ==========") | ||
|  |   (run-string-tests) | ||
|  |   (newline) | ||
|  |   (displayln "========== Testing string functions on strings created using string ports ==========") | ||
|  |   (run-string-tests-string-port) | ||
|  |   (newline) | ||
|  |   (displayln "========== Testing file port ==========") | ||
|  |   ; All file port tests will fail if writing to a file doesn't work properly, | ||
|  |   ; as test data is written to a temporary file. This was done so that the test | ||
|  |   ; data only exists in one place (in this file as list of bytes). | ||
|  |   (run-file-port-tests) | ||
|  |   (newline) | ||
|  |   (if (= tests-failed 0) | ||
|  |     (displayln "ALL tests passed!") | ||
|  |     (displayln | ||
|  |       (string-append | ||
|  |         "Test 9: " (number->string tests-failed) | ||
|  |         " tests FAILED. Run tests in Script-Fu console for details.")))) | ||
|  | 
 | ||
|  | (define (with-log-to-pika-message function) | ||
|  |   (let ((test-log (make-string 4096))) | ||
|  |     (call-with-output-string test-log | ||
|  |       (lambda (port) | ||
|  |         (set-output-port port) | ||
|  |         (function))) | ||
|  |     (pika-message (rtrim test-log)))) | ||
|  | 
 | ||
|  | (define (name->function name) | ||
|  |   (eval (call-with-input-string (string-append "'" name) read))) | ||
|  | 
 | ||
|  | (define (select-run-function testname) | ||
|  |   (if (> (string-length testname) 0) | ||
|  |     (lambda () (run-test (name->function testname))) | ||
|  |     run-all-tests)) | ||
|  | 
 | ||
|  | (define (script-fu-test9 testname) | ||
|  |   (with-log-to-pika-message (select-run-function testname))) | ||
|  | 
 | ||
|  | ; ---------- Script registration ---------- | ||
|  | 
 | ||
|  | (script-fu-register | ||
|  |   "script-fu-test9" | ||
|  |   "Test SF interpreter 9" | ||
|  |   "Test byte and utf8 char handling. Must print SUCCESS for each test case." | ||
|  |   "Richard Szibele" | ||
|  |   "Copyright (C) 2022, Richard Szibele" | ||
|  |   "2022" | ||
|  |   "" | ||
|  |   SF-STRING "Test (optional)" "" | ||
|  | ) | ||
|  | 
 | ||
|  | (script-fu-menu-register "script-fu-test9" "<Image>/Test") |