1 ;;;; testcover-ses.el -- Example use of `testcover' to test "SES"
3 ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 ;; Author: Jonathan Yavner <jyavner@engineer.com>
6 ;; Maintainer: Jonathan Yavner <jyavner@engineer.com>
7 ;; Keywords: spreadsheet lisp utility
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING. If not, write to the
21 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 ;; Boston, MA 02110-1301, USA.
26 (defvar ses-initial-global-parameters
)
29 ;;;Here are some macros that exercise SES. Set `pause' to t if you want the
30 ;;;macros to pause after each step.
32 (x (if pause
"\x18q" ""))
33 (y "\x18\x06ses-test.ses\r\e<"))
34 ;;Fiddle with the existing spreadsheet
35 (fset 'ses-exercise-example
36 (concat "\x18\x06" data-directory
"ses-example.ses\r\e<"
40 x
"\x10\x10\x06pses-center\r"
44 x
"\x15\x0e\x02\x02\x02"
51 x
"(+ \x18o\x0e\x0e\x06\0\x06\x06"
52 x
"\x15-1\x18o\x03\x12 \x03\x13\r\x02"
55 ;;Create a new spreadsheet
56 (fset 'ses-exercise-new
58 x
"\x03\x10\"%.8g\"\r"
70 x
"\r\x7f\x7f\x7fB3\r"
74 (fset 'ses-exercise-display
75 (concat y
"\e:(revert-buffer t t)\r"
101 x
"\x02\x02\x02\"1234567-1234567-1234567\r\x02"
104 x
"\x0e\"1234567-1234567-1234567\r\x02"
107 x
"\x02\x02\"1234567\r"
111 (fset 'ses-exercise-formulas
112 (concat y
"\e:(revert-buffer t t)\r"
115 x
"(* B1 B2 D1\r\x02"
117 x
"\x0e(apply '+ (ses-range B1 B3)\r\x02"
118 x
"(apply 'ses+ (ses-range B1 B3)\r\x02"
119 x
"\x0e(apply 'ses+ (ses-range A2 A3)\r\x02"
120 x
"\x0e(mapconcat'number-to-string(ses-range B2 B4) \"-\"\r\x02"
121 x
"\x02(apply 'concat (reverse (ses-range A3 D3))\r\x02"
122 x
"\x02(* (+ A2 A3) (ses+ B2 B3)\r\x02"
126 x
"\x10(apply 'ses+ (ses-range E1 E2)\r\x02"
127 x
"\x10(apply 'ses+ (ses-range A5 B5)\r\x02"
128 x
"\x10(apply 'ses+ (ses-range E1 F1)\r\x02"
129 x
"\x10(apply 'ses+ (ses-range D1 E1)\r\x02"
131 x
"(ses-average (ses-range A2 A5)\r\x02"
132 x
"\x0e(apply 'ses+ (ses-range A5 A6)\r\x02"
141 x
"\x06(ses-average (ses-range B3 E3)\r\x02"
143 x
"\x0e\x1012345678\r\x02"
145 ;;Recalculating and reconstructing
146 (fset 'ses-exercise-recalc
147 (concat y
"\e:(revert-buffer t t)\r"
155 x
"\x03\x10\"%.6g\"\r"
157 x
"\e>\x18nw\x06\x06\x06"
158 x
"\0\e>\exdelete-region\r"
161 x
"\0\e>\exdelete-region\r"
166 x
"\x02\"Very long\r"
172 x
"\x02\x02\"Very long2\r"
175 x
"\r\x7f\x7f\x7fC3\r"
176 x
"\x0e\r\x7f\x7f\x7fC2\r"
177 x
"\x10\0\x0e\x06\x03\x03"
179 x
"\x0e\x0e\r\x7f\x7f\x7fC2\r"
180 x
"\x06\0\x02\x10\x10"
187 (fset 'ses-exercise-header-row
188 (concat y
"\e:(revert-buffer t t)\r"
203 ;;Detecting unsafe formulas and printers
204 (fset 'ses-exercise-unsafe
205 (concat y
"\e:(revert-buffer t t)\r"
206 x
"p(lambda (x) (delete-file x))\rn"
207 x
"p(lambda (x) (delete-file \"ses-nothing\"))\ry"
209 x
"\x0e(delete-file \"x\"\rn"
210 x
"(delete-file \"ses-nothing\"\ry\x02"
212 x
"(open-network-stream \"x\" nil \"localhost\" \"smtp\"\ry\x02"
215 ;;Inserting and deleting rows
216 (fset 'ses-exercise-rows
217 (concat y
"\e:(revert-buffer t t)\r"
219 x
"\x03\x10\"%s=\"\r"
227 x
"\x10\x10(not B25\r\x02"
232 x
"\x15100\x0f" ;Make this approx your CPU speed in MHz
234 ;;Inserting and deleting columns
235 (fset 'ses-exercise-columns
236 (concat y
"\e:(revert-buffer t t)\r"
237 x
"\x03\x10\"%s@\"\r"
249 x
"\x03\x10\"%.6g\"\r"
257 x
"\0\x0e\x0e\x06\x06\x03\e\x13D"
259 (fset 'ses-exercise-editing
260 (concat y
"\e:(revert-buffer t t)\r"
261 x
"\x0e\x0e\x0e1\r\x02"
262 x
"\x06(\x02'\x06x\r\x02"
263 x
"\x02\x10\x10\x10\x0f"
268 x
"\x0e\x06\r\x02 10\r"
277 x
"\x02\"Very long\r\x02"
285 x
"\x06\x06\x152\x7f"
290 x
"\"Also very long\r\x02"
294 x
"\x0e\x02'qwerty\r\x02"
295 x
"\x06(concat \x18o\e<\0\x0e\x0e"
296 x
"\x15-1\x18o\x03\x12\r\x02"
297 x
"(apply '+ \x18o\e<\0\x0e\x06\x15-1\x18o\x03\x13\r\x02"
305 x
"\"Another long one\r\x02"
314 (fset 'ses-exercise-sort-column
315 (concat y
"\e:(revert-buffer t t)\r"
321 x
"\0\x10\x10\x10\x03\e\x13A\r"
322 x
"\x0e\0\x10\x10\x10\x03\e\x13B\r"
323 x
"\x10\x10\x06\0\x0e\x0e\x06\x06\x03\e\x13C\r"
325 x
"\x02\0\x0e\x0e\x0e\x15\x03\e\x13C\r"
327 ;;Simple cell printers
328 (fset 'ses-exercise-cell-printers
329 (concat y
"\e:(revert-buffer t t)\r"
330 x
"\x06\"4\x11\t76\r\x02"
344 x
"\x02\0\x06\x06pnil\r"
352 x
"\x03\x10\"%.6g#\"\r"
353 x
"\x03\x10\"%.6g.\"\r"
354 x
"\x03\x10\"%.6g.\"\r"
357 x
"\x0e\"UPCASE\r\x02"
360 x
"p(lambda\x11 (x)\x11 '(\"Hi\"))\r"
361 x
"p(lambda\x11 (x)\x11 '(\"Bye\"))\r"
363 ;;Spanning cell printers
364 (fset 'ses-exercise-spanning-printers
365 (concat y
"\e:(revert-buffer t t)\r"
367 x
"pses-dashfill-span\r"
369 x
"pses-tildefill-span\r"
375 x
"\t\"12345678\r\x02"
376 x
"pses-dashfill-span\r"
391 ;;Cut/copy/paste - within same buffer
392 (fset 'ses-exercise-paste-1buf
393 (concat y
"\e:(revert-buffer t t)\r"
395 x
"\x03\x03\x10\x06\x19"
406 x
"\x10\x10\x06\x15\x19y"
412 x
"\x06pses-dashfill\r"
413 x
"\x02\0\x06\x06\x06\x0e\x0e\x0e"
417 x
"\r\0\x02\x02\x02\ew"
419 x
"\x153\x10(+ G2 H1\r"
423 x
"\x02\x158\x10(ses-average (ses-range G2 H2)\r\x02"
427 x
"\x10\x02(ses-average (ses-range E7 E9)\r\x02"
430 x
"\x02\x02\x10(ses-average (ses-range E7 F7)\r\x02"
433 x
"\x02\x02\x10(ses-average (ses-range D6 E6)\r\x02"
438 x
"pses-tildefill-span\r"
439 x
"\x0e\x06\"Subline A(1)\r\x02"
440 x
"pses-dashfill-span\r"
441 x
"\x02\x10\0\x0e\x0e\x0e\ew\x03\x03"
442 x
"\x01\x10\x10\x10\x10\x10\x10"
444 x
"\0\x0e\x06\x06\ew\x03\x03"
447 ;;Cut/copy/paste - between two buffers
448 (fset 'ses-exercise-paste-2buf
449 (concat y
"\e:(revert-buffer t t)\r"
450 x
"\x06\x0e\eo\"middle\r\x02\0\x06\x0e\x06"
452 x
"\x184bses-test.txt\r"
454 x
"\x05\"xxx\0\x02\x02\x02\x02"
458 x
"\x18o\x05\"\0\x02\x02\x02\x02\x02"
460 x
"\x18o123.45\0\x02\x02\x02\x02\x02\x02"
462 x
"\x18o1 \x02\x02\0\x06\x06\x06\x06\x06\x06\x06"
465 x
"\x06\x18o symb\0\x02\x02\x02\x02"
466 x
"\x17\x18o\x15\x19\ey\x152\ey"
467 x
"\x18o1\t\0\x02\x02"
468 x
"\x17\x18o\x02\x19"
469 x
"w9\n\ep\"<%s>\"\n"
470 x
"\x18o\n2\t\"3\nxxx\t5\n\0\x10\x10"
473 ;;Export text, import it back
474 (fset 'ses-exercise-import-export
475 (concat y
"\e:(revert-buffer t t)\r"
476 x
"\x0e\x0e\x06\0\x06xt"
477 x
"\x184bses-test.txt\r"
478 x
"\n\x19\x15-1\x18o"
479 x
"xT\x18o\x19\x15-1\x18o"
480 x
"\x03\x03\x06'crunch\r\x02"
481 x
"\x10\x10\x10pses-center-span\r"
482 x
"\0\x0e\x0e\x0e\x0exT"
483 x
"\x18o\n\x19\x15-1\x18o"
485 x
"\x06\0\x02\x10\x10xt"
486 x
"\x0e\x0e\0\x15\x19y"
492 (defun ses-exercise-macros ()
493 "Executes all SES coverage-test macros."
494 (dolist (x '(ses-exercise-example
497 ses-exercise-formulas
499 ses-exercise-header-row
504 ses-exercise-sort-column
505 ses-exercise-cell-printers
506 ses-exercise-spanning-printers
507 ses-exercise-paste-1buf
508 ses-exercise-paste-2buf
509 ses-exercise-import-export
))
510 (message "<Testing %s>" x
)
511 (execute-kbd-macro x
)))
513 (defun ses-exercise-signals ()
514 "Exercise code paths that lead to error signals, other than those for
515 spreadsheet files with invalid formatting."
516 (message "<Checking for expected errors>")
517 (switch-to-buffer "ses-test.ses")
521 (dolist (x '((ses-column-widths 14)
522 (ses-column-printers "%s")
523 (ses-column-printers ["%s" "%s" "%s"]) ;Should be two
524 (ses-column-widths [14])
525 (ses-delete-column -99)
526 (ses-delete-column 2)
528 (ses-goto-data 'hogwash)
531 (ses-insert-column -14)
533 (ses-jump 'B8) ;Covered by preceding cell
534 (ses-printer-validate '("%s" t))
535 (ses-printer-validate '([47]))
536 (ses-read-header-row -1)
537 (ses-read-header-row 32767)
538 (ses-relocate-all 0 0 -1 1)
539 (ses-relocate-all 0 0 1 -1)
540 (ses-select (ses-range A1 A2) 'x (ses-range B1 B1))
541 (ses-set-cell 0 0 'hogwash nil)
542 (ses-set-column-width 0 0)
543 (ses-yank-cells #("a\nb"
544 0 1 (ses (A1 nil nil))
545 2 3 (ses (A3 nil nil)))
547 (ses-yank-cells #("ab"
548 0 1 (ses (A1 nil nil))
549 1 2 (ses (A2 nil nil)))
552 (ses-yank-tsf "1\t2\n3" nil)
553 (let ((curcell nil)) (ses-check-curcell))
554 (let ((curcell 'A1)) (ses-check-curcell 'needrange))
555 (let ((curcell '(A1 . A2))) (ses-check-curcell 'end))
556 (let ((curcell '(A1 . A2))) (ses-sort-column "B"))
557 (let ((curcell '(C1 . D2))) (ses-sort-column "B"))
558 (execute-kbd-macro "jB10\n\x152\x04")
559 (execute-kbd-macro [?j ?B ?9 ?\n ?\C-@ ?\C-f ?\C-f cut])
560 (progn (kill-new "x") (execute-kbd-macro "\e>\x19n"))
561 (execute-kbd-macro "\x02\0\ew")))
565 (signal 'singularity-error nil)) ;Shouldn't get here
566 (singularity-error (error "No error from %s?" x))
568 ;;Test quit-handling in ses-update-cells. Cant' use `eval' here.
569 (let ((inhibit-quit t))
573 (ses-update-cells '(A1))
574 (signal 'singularity-error nil))
575 (singularity-error (error "Quit failure in ses-update-cells"))
577 (setq quit-flag nil)))
579 (defun ses-exercise-invalid-spreadsheets ()
580 "Execute code paths that detect invalid spreadsheet files."
581 ;;Detect invalid spreadsheets
582 (let ((p&d "\n\n\f\n(ses-cell A1 nil nil nil nil)\n\n")
583 (cw "(ses-column-widths [7])\n")
584 (cp "(ses-column-printers [ses-center])\n")
585 (dp "(ses-default-printer \"%.7g\")\n")
586 (hr "(ses-header-row 0)\n")
588 (igp ses-initial-global-parameters))
589 (dolist (x (list "(1)"
597 "\n\n\f\n(ses-cell)(2 1 1)"
598 "\n\n\f\n(x)\n(2 1 1)"
599 "\n\n\n\f\n(ses-cell A2)\n(2 2 2)"
600 "\n\n\n\f\n(ses-cell B1)\n(2 2 2)"
601 "\n\n\f\n(ses-cell A1 nil nil nil nil)\n(2 1 1)"
602 (concat p&d "(x)\n(x)\n(x)\n(x)\n" p11)
603 (concat p&d "(ses-column-widths)(x)\n(x)\n(x)\n" p11)
604 (concat p&d cw "(x)\n(x)\n(x)\n(2 1 1)")
605 (concat p&d cw "(ses-column-printers)(x)\n(x)\n" p11)
606 (concat p&d cw cp "(x)\n(x)\n" p11)
607 (concat p&d cw cp "(ses-default-printer)(x)\n" p11)
608 (concat p&d cw cp dp "(x)\n" p11)
609 (concat p&d cw cp dp "(ses-header-row)" p11)
610 (concat p&d cw cp dp hr p11)
611 (concat p&d cw cp dp "\n" hr igp)))
616 (signal 'singularity-error nil)) ;Shouldn't get here
617 (singularity-error (error "%S is an invalid spreadsheet!" x))
620 (defun ses-exercise-startup ()
621 "Prepare for coverage tests"
622 ;;Clean up from any previous runs
623 (condition-case nil (kill-buffer "ses-example.ses") (error nil))
624 (condition-case nil (kill-buffer "ses-test.ses") (error nil))
625 (condition-case nil (delete-file "ses-test.ses") (file-error nil))
626 (delete-other-windows) ;Needed for "\C-xo" in ses-exercise-editing
627 (setq ses-mode-map nil) ;Force rebuild
628 (testcover-unmark-all "ses.el")
630 (let ((testcover-1value-functions
631 ;;forward-line always returns 0, for us.
632 ;;remove-text-properties always returns t for us.
633 ;;ses-recalculate-cell returns the same " " any time curcell is a cons
634 ;;Macros ses-dorange and ses-dotimes-msg generate code that always
636 (append '(forward-line remove-text-properties ses-recalculate-cell
637 ses-dorange ses-dotimes-msg)
638 testcover-1value-functions))
640 ;;These maps get initialized, then never changed again
641 (append '(ses-mode-map ses-mode-print-map ses-mode-edit-map)
642 testcover-constants)))
643 (testcover-start "ses.el" t))
644 (require 'unsafep)) ;In case user has safe-functions = t!
647 ;;;#########################################################################
648 (defun ses-exercise ()
649 "Executes all SES coverage tests and displays the results."
651 (ses-exercise-startup)
652 ;;Run the keyboard-macro tests
653 (let ((safe-functions nil)
654 (ses-initial-size '(1 . 1))
655 (ses-initial-column-width 7)
656 (ses-initial-default-printer "%.7g")
657 (ses-after-entry-functions '(forward-char))
659 (ses-exercise-macros)
660 (ses-exercise-signals)
661 (ses-exercise-invalid-spreadsheets)
662 ;;Upgrade of old-style spreadsheet
664 (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")
666 ;;ses-vector-delete is always called from buffer-undo-list with the same
667 ;;symbol as argument. We'll give it a different one here.
669 (ses-vector-delete 'x 0 0))
670 ;;ses-create-header-string behaves differently in a non-window environment
671 ;;but we always test under windows.
672 (let ((window-system (not window-system)))
674 (ses-create-header-string))
675 ;;Test for nonstandard after-entry functions
676 (let ((ses-after-entry-functions '(forward-line))
678 (ses-read-cell 0 0 1)
679 (ses-read-symbol 0 0 t)))
680 ;;Tests with unsafep disabled
681 (let ((safe-functions t)
683 (message "<Checking safe-functions = t>")
684 (kill-buffer "ses-example.ses")
685 (find-file "ses-example.ses"))
686 ;;Checks for nonstandard default values for new spreadsheets
688 (dolist (x '(("%.6g" 8 (2 . 2))
690 (let ((ses-initial-size (nth 2 x))
691 (ses-initial-column-width (nth 1 x))
692 (ses-initial-default-printer (nth 0 x)))
694 (set-buffer-modified-p t)
696 ;;Test error-handling in command hook, outside a macro.
697 ;;This will ring the bell.
698 (let (curcell-overlay)
700 ;;Due to use of run-with-timer, ses-command-hook sometimes gets called
701 ;;after we switch to another buffer.
702 (switch-to-buffer "*scratch*")
705 (message "<Marking source code>")
706 (testcover-mark-all "ses.el")
707 (testcover-next-mark)
709 (delete-other-windows)
710 (kill-buffer "ses-test.txt")
711 ;;Could do this here: (testcover-end "ses.el")
714 ;;; arch-tag: 87052ba4-5cf8-46cf-9375-fe245f3360b8
715 ;; testcover-ses.el ends here.