1 ;;;; testcover-ses.el -- Example use of `testcover' to test "SES"
3 ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 ;; Free Software Foundation, Inc.
6 ;; Author: Jonathan Yavner <jyavner@engineer.com>
7 ;; Maintainer: Jonathan Yavner <jyavner@engineer.com>
8 ;; Keywords: spreadsheet lisp utility
11 ;; GNU Emacs is free software: you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation, either version 3 of the License, or
14 ;; (at your option) any later version.
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
26 (defvar ses-initial-global-parameters
)
29 (declare-function ses-set-curcell
"ses")
30 (declare-function ses-update-cells
"ses")
31 (declare-function ses-load
"ses")
32 (declare-function ses-vector-delete
"ses")
33 (declare-function ses-create-header-string
"ses")
34 (declare-function ses-read-cell
"ses")
35 (declare-function ses-read-symbol
"ses")
36 (declare-function ses-command-hook
"ses")
37 (declare-function ses-jump
"ses")
40 ;;;Here are some macros that exercise SES. Set `pause' to t if you want the
41 ;;;macros to pause after each step.
43 (x (if pause
"\18q" ""))
44 (y "\18\ 6ses-test.ses\r\e<"))
45 ;;Fiddle with the existing spreadsheet
46 (fset 'ses-exercise-example
47 (concat "\18\ 6" data-directory
"ses-example.ses\r\e<"
51 x
"\10\10\ 6pses-center\r"
62 x
"(+ \18o\ e\ e\ 6\0\ 6\ 6"
63 x
"\15-1\18o\ 3\12 \ 3\13\r\ 2"
66 ;;Create a new spreadsheet
67 (fset 'ses-exercise-new
85 (fset 'ses-exercise-display
86 (concat y
"\e:(revert-buffer t t)\r"
112 x
"\ 2\ 2\ 2\"1234567-1234567-1234567\r\ 2"
115 x
"\ e\"1234567-1234567-1234567\r\ 2"
118 x
"\ 2\ 2\"1234567\r"
122 (fset 'ses-exercise-formulas
123 (concat y
"\e:(revert-buffer t t)\r"
128 x
"\ e(apply '+ (ses-range B1 B3)\r\ 2"
129 x
"(apply 'ses+ (ses-range B1 B3)\r\ 2"
130 x
"\ e(apply 'ses+ (ses-range A2 A3)\r\ 2"
131 x
"\ e(mapconcat'number-to-string(ses-range B2 B4) \"-\"\r\ 2"
132 x
"\ 2(apply 'concat (reverse (ses-range A3 D3))\r\ 2"
133 x
"\ 2(* (+ A2 A3) (ses+ B2 B3)\r\ 2"
137 x
"\10(apply 'ses+ (ses-range E1 E2)\r\ 2"
138 x
"\10(apply 'ses+ (ses-range A5 B5)\r\ 2"
139 x
"\10(apply 'ses+ (ses-range E1 F1)\r\ 2"
140 x
"\10(apply 'ses+ (ses-range D1 E1)\r\ 2"
142 x
"(ses-average (ses-range A2 A5)\r\ 2"
143 x
"\ e(apply 'ses+ (ses-range A5 A6)\r\ 2"
152 x
"\ 6(ses-average (ses-range B3 E3)\r\ 2"
154 x
"\ e\1012345678\r\ 2"
156 ;;Recalculating and reconstructing
157 (fset 'ses-exercise-recalc
158 (concat y
"\e:(revert-buffer t t)\r"
168 x
"\e>\18nw\ 6\ 6\ 6"
169 x
"\0\e>\exdelete-region\r"
172 x
"\0\e>\exdelete-region\r"
183 x
"\ 2\ 2\"Very long2\r"
187 x
"\ e\r\7f\7f\7fC2\r"
188 x
"\10\0\ e\ 6\ 3\ 3"
190 x
"\ e\ e\r\7f\7f\7fC2\r"
198 (fset 'ses-exercise-header-row
199 (concat y
"\e:(revert-buffer t t)\r"
214 ;;Detecting unsafe formulas and printers
215 (fset 'ses-exercise-unsafe
216 (concat y
"\e:(revert-buffer t t)\r"
217 x
"p(lambda (x) (delete-file x))\rn"
218 x
"p(lambda (x) (delete-file \"ses-nothing\"))\ry"
220 x
"\ e(delete-file \"x\"\rn"
221 x
"(delete-file \"ses-nothing\"\ry\ 2"
223 x
"(open-network-stream \"x\" nil \"localhost\" \"smtp\"\ry\ 2"
226 ;;Inserting and deleting rows
227 (fset 'ses-exercise-rows
228 (concat y
"\e:(revert-buffer t t)\r"
238 x
"\10\10(not B25\r\ 2"
243 x
"\15100\ f" ;Make this approx your CPU speed in MHz
245 ;;Inserting and deleting columns
246 (fset 'ses-exercise-columns
247 (concat y
"\e:(revert-buffer t t)\r"
268 x
"\0\ e\ e\ 6\ 6\ 3\e\13D"
270 (fset 'ses-exercise-editing
271 (concat y
"\e:(revert-buffer t t)\r"
273 x
"\ 6(\ 2'\ 6x\r\ 2"
288 x
"\ 2\"Very long\r\ 2"
301 x
"\"Also very long\r\ 2"
305 x
"\ e\ 2'qwerty\r\ 2"
306 x
"\ 6(concat \18o\e<\0\ e\ e"
307 x
"\15-1\18o\ 3\12\r\ 2"
308 x
"(apply '+ \18o\e<\0\ e\ 6\15-1\18o\ 3\13\r\ 2"
316 x
"\"Another long one\r\ 2"
325 (fset 'ses-exercise-sort-column
326 (concat y
"\e:(revert-buffer t t)\r"
332 x
"\0\10\10\10\ 3\e\13A\r"
333 x
"\ e\0\10\10\10\ 3\e\13B\r"
334 x
"\10\10\ 6\0\ e\ e\ 6\ 6\ 3\e\13C\r"
336 x
"\ 2\0\ e\ e\ e\15\ 3\e\13C\r"
338 ;;Simple cell printers
339 (fset 'ses-exercise-cell-printers
340 (concat y
"\e:(revert-buffer t t)\r"
341 x
"\ 6\"4\11\t76\r\ 2"
355 x
"\ 2\0\ 6\ 6pnil\r"
363 x
"\ 3\10\"%.6g#\"\r"
364 x
"\ 3\10\"%.6g.\"\r"
365 x
"\ 3\10\"%.6g.\"\r"
371 x
"p(lambda\11 (x)\11 '(\"Hi\"))\r"
372 x
"p(lambda\11 (x)\11 '(\"Bye\"))\r"
374 ;;Spanning cell printers
375 (fset 'ses-exercise-spanning-printers
376 (concat y
"\e:(revert-buffer t t)\r"
378 x
"pses-dashfill-span\r"
380 x
"pses-tildefill-span\r"
386 x
"\t\"12345678\r\ 2"
387 x
"pses-dashfill-span\r"
402 ;;Cut/copy/paste - within same buffer
403 (fset 'ses-exercise-paste-1buf
404 (concat y
"\e:(revert-buffer t t)\r"
423 x
"\ 6pses-dashfill\r"
424 x
"\ 2\0\ 6\ 6\ 6\ e\ e\ e"
430 x
"\153\10(+ G2 H1\r"
434 x
"\ 2\158\10(ses-average (ses-range G2 H2)\r\ 2"
438 x
"\10\ 2(ses-average (ses-range E7 E9)\r\ 2"
441 x
"\ 2\ 2\10(ses-average (ses-range E7 F7)\r\ 2"
444 x
"\ 2\ 2\10(ses-average (ses-range D6 E6)\r\ 2"
449 x
"pses-tildefill-span\r"
450 x
"\ e\ 6\"Subline A(1)\r\ 2"
451 x
"pses-dashfill-span\r"
452 x
"\ 2\10\0\ e\ e\ e\ew\ 3\ 3"
453 x
"\ 1\10\10\10\10\10\10"
455 x
"\0\ e\ 6\ 6\ew\ 3\ 3"
458 ;;Cut/copy/paste - between two buffers
459 (fset 'ses-exercise-paste-2buf
460 (concat y
"\e:(revert-buffer t t)\r"
461 x
"\ 6\ e\eo\"middle\r\ 2\0\ 6\ e\ 6"
463 x
"\184bses-test.txt\r"
465 x
"\ 5\"xxx\0\ 2\ 2\ 2\ 2"
469 x
"\18o\ 5\"\0\ 2\ 2\ 2\ 2\ 2"
471 x
"\18o123.45\0\ 2\ 2\ 2\ 2\ 2\ 2"
473 x
"\18o1 \ 2\ 2\0\ 6\ 6\ 6\ 6\ 6\ 6\ 6"
476 x
"\ 6\18o symb\0\ 2\ 2\ 2\ 2"
477 x
"\17\18o\15\19\ey\152\ey"
480 x
"w9\n\ep\"<%s>\"\n"
481 x
"\18o\n2\t\"3\nxxx\t5\n\0\10\10"
484 ;;Export text, import it back
485 (fset 'ses-exercise-import-export
486 (concat y
"\e:(revert-buffer t t)\r"
488 x
"\184bses-test.txt\r"
490 x
"xT\18o\19\15-1\18o"
491 x
"\ 3\ 3\ 6'crunch\r\ 2"
492 x
"\10\10\10pses-center-span\r"
494 x
"\18o\n\19\15-1\18o"
503 (defun ses-exercise-macros ()
504 "Executes all SES coverage-test macros."
505 (dolist (x '(ses-exercise-example
508 ses-exercise-formulas
510 ses-exercise-header-row
515 ses-exercise-sort-column
516 ses-exercise-cell-printers
517 ses-exercise-spanning-printers
518 ses-exercise-paste-1buf
519 ses-exercise-paste-2buf
520 ses-exercise-import-export
))
521 (message "<Testing %s>" x
)
522 (execute-kbd-macro x
)))
524 (defun ses-exercise-signals ()
525 "Exercise code paths that lead to error signals, other than those for
526 spreadsheet files with invalid formatting."
527 (message "<Checking for expected errors>")
528 (switch-to-buffer "ses-test.ses")
532 (dolist (x '((ses-column-widths 14)
533 (ses-column-printers "%s")
534 (ses-column-printers ["%s" "%s" "%s"]) ;Should be two
535 (ses-column-widths [14])
536 (ses-delete-column -99)
537 (ses-delete-column 2)
539 (ses-goto-data 'hogwash)
542 (ses-insert-column -14)
544 (ses-jump 'B8) ;Covered by preceding cell
545 (ses-printer-validate '("%s" t))
546 (ses-printer-validate '([47]))
547 (ses-read-header-row -1)
548 (ses-read-header-row 32767)
549 (ses-relocate-all 0 0 -1 1)
550 (ses-relocate-all 0 0 1 -1)
551 (ses-select (ses-range A1 A2) 'x (ses-range B1 B1))
552 (ses-set-cell 0 0 'hogwash nil)
553 (ses-set-column-width 0 0)
554 (ses-yank-cells #("a\nb"
555 0 1 (ses (A1 nil nil))
556 2 3 (ses (A3 nil nil)))
558 (ses-yank-cells #("ab"
559 0 1 (ses (A1 nil nil))
560 1 2 (ses (A2 nil nil)))
563 (ses-yank-tsf "1\t2\n3" nil)
564 (let ((curcell nil)) (ses-check-curcell))
565 (let ((curcell 'A1)) (ses-check-curcell 'needrange))
566 (let ((curcell '(A1 . A2))) (ses-check-curcell 'end))
567 (let ((curcell '(A1 . A2))) (ses-sort-column "B"))
568 (let ((curcell '(C1 . D2))) (ses-sort-column "B"))
569 (execute-kbd-macro "jB10\n\152\ 4")
570 (execute-kbd-macro [?j ?B ?9 ?\n ?\C-@ ?\C-f ?\C-f cut])
571 (progn (kill-new "x") (execute-kbd-macro "\e>\19n"))
572 (execute-kbd-macro "\ 2\0\ew")))
576 (signal 'singularity-error nil)) ;Shouldn't get here
577 (singularity-error (error "No error from %s?" x))
579 ;;Test quit-handling in ses-update-cells. Cant' use `eval' here.
580 (let ((inhibit-quit t))
584 (ses-update-cells '(A1))
585 (signal 'singularity-error nil))
586 (singularity-error (error "Quit failure in ses-update-cells"))
588 (setq quit-flag nil)))
590 (defun ses-exercise-invalid-spreadsheets ()
591 "Execute code paths that detect invalid spreadsheet files."
592 ;;Detect invalid spreadsheets
593 (let ((p&d "\n\n\f\n(ses-cell A1 nil nil nil nil)\n\n")
594 (cw "(ses-column-widths [7])\n")
595 (cp "(ses-column-printers [ses-center])\n")
596 (dp "(ses-default-printer \"%.7g\")\n")
597 (hr "(ses-header-row 0)\n")
599 (igp ses-initial-global-parameters))
600 (dolist (x (list "(1)"
608 "\n\n\f\n(ses-cell)(2 1 1)"
609 "\n\n\f\n(x)\n(2 1 1)"
610 "\n\n\n\f\n(ses-cell A2)\n(2 2 2)"
611 "\n\n\n\f\n(ses-cell B1)\n(2 2 2)"
612 "\n\n\f\n(ses-cell A1 nil nil nil nil)\n(2 1 1)"
613 (concat p&d "(x)\n(x)\n(x)\n(x)\n" p11)
614 (concat p&d "(ses-column-widths)(x)\n(x)\n(x)\n" p11)
615 (concat p&d cw "(x)\n(x)\n(x)\n(2 1 1)")
616 (concat p&d cw "(ses-column-printers)(x)\n(x)\n" p11)
617 (concat p&d cw cp "(x)\n(x)\n" p11)
618 (concat p&d cw cp "(ses-default-printer)(x)\n" p11)
619 (concat p&d cw cp dp "(x)\n" p11)
620 (concat p&d cw cp dp "(ses-header-row)" p11)
621 (concat p&d cw cp dp hr p11)
622 (concat p&d cw cp dp "\n" hr igp)))
627 (signal 'singularity-error nil)) ;Shouldn't get here
628 (singularity-error (error "%S is an invalid spreadsheet!" x))
631 (defun ses-exercise-startup ()
632 "Prepare for coverage tests"
633 ;;Clean up from any previous runs
634 (condition-case nil (kill-buffer "ses-example.ses") (error nil))
635 (condition-case nil (kill-buffer "ses-test.ses") (error nil))
636 (condition-case nil (delete-file "ses-test.ses") (file-error nil))
637 (delete-other-windows) ;Needed for "\C-xo" in ses-exercise-editing
638 (setq ses-mode-map nil) ;Force rebuild
639 (testcover-unmark-all "ses.el")
641 (let ((testcover-1value-functions
642 ;;forward-line always returns 0, for us.
643 ;;remove-text-properties always returns t for us.
644 ;;ses-recalculate-cell returns the same " " any time curcell is a cons
645 ;;Macros ses-dorange and ses-dotimes-msg generate code that always
647 (append '(forward-line remove-text-properties ses-recalculate-cell
648 ses-dorange ses-dotimes-msg)
649 testcover-1value-functions))
651 ;;These maps get initialized, then never changed again
652 (append '(ses-mode-map ses-mode-print-map ses-mode-edit-map)
653 testcover-constants)))
654 (testcover-start "ses.el" t))
655 (require 'unsafep)) ;In case user has safe-functions = t!
658 ;;;#########################################################################
659 (defun ses-exercise ()
660 "Executes all SES coverage tests and displays the results."
662 (ses-exercise-startup)
663 ;;Run the keyboard-macro tests
664 (let ((safe-functions nil)
665 (ses-initial-size '(1 . 1))
666 (ses-initial-column-width 7)
667 (ses-initial-default-printer "%.7g")
668 (ses-after-entry-functions '(forward-char))
670 (ses-exercise-macros)
671 (ses-exercise-signals)
672 (ses-exercise-invalid-spreadsheets)
673 ;;Upgrade of old-style spreadsheet
675 (insert " \n\n\f\n(ses-cell A1 nil nil nil nil)\n\n(ses-column-widths [7])\n(ses-column-printers [nil])\n(ses-default-printer \"%.7g\")\n\n( ;Global parameters (these are read first)\n 1 ;SES file-format\n 1 ;numrows\n 1 ;numcols\n)\n\n")
677 ;;ses-vector-delete is always called from buffer-undo-list with the same
678 ;;symbol as argument. We'll give it a different one here.
680 (ses-vector-delete 'x 0 0))
681 ;;ses-create-header-string behaves differently in a non-window environment
682 ;;but we always test under windows.
683 (let ((window-system (not window-system)))
685 (ses-create-header-string))
686 ;;Test for nonstandard after-entry functions
687 (let ((ses-after-entry-functions '(forward-line))
689 (ses-read-cell 0 0 1)
690 (ses-read-symbol 0 0 t)))
691 ;;Tests with unsafep disabled
692 (let ((safe-functions t)
694 (message "<Checking safe-functions = t>")
695 (kill-buffer "ses-example.ses")
696 (find-file "ses-example.ses"))
697 ;;Checks for nonstandard default values for new spreadsheets
699 (dolist (x '(("%.6g" 8 (2 . 2))
701 (let ((ses-initial-size (nth 2 x))
702 (ses-initial-column-width (nth 1 x))
703 (ses-initial-default-printer (nth 0 x)))
705 (set-buffer-modified-p t)
707 ;;Test error-handling in command hook, outside a macro.
708 ;;This will ring the bell.
709 (let (curcell-overlay)
711 ;;Due to use of run-with-timer, ses-command-hook sometimes gets called
712 ;;after we switch to another buffer.
713 (switch-to-buffer "*scratch*")
716 (message "<Marking source code>")
717 (testcover-mark-all "ses.el")
718 (testcover-next-mark)
720 (delete-other-windows)
721 (kill-buffer "ses-test.txt")
722 ;;Could do this here: (testcover-end "ses.el")
725 ;; arch-tag: 87052ba4-5cf8-46cf-9375-fe245f3360b8
726 ;; testcover-ses.el ends here.