Commits

seanmcl  committed b0aa55b

working on automated tests

  • Participants
  • Parent commits 650db11

Comments (0)

Files changed (10)

+
+new stuff
+=========
+
+- Robust unit testing.  Jane.test, Jane.test-eq, Jane.test-error, Jane.run-tests.
+  Example
+   (Jane.test-eq List.assoc.1 (List.assoc 5 '((5 . 6) (1 . 3))) 6)
+   (Jane.test-eq List.assoc.2 (List.assoc 5 '((5 6) (1 3))) '(6))
+   (Jane.test-eq List.assoc.3 (List.assoc 5 '((5 6) (1 3))) '(7))
+
+  Result
+     Selector: "Omake\\|Hashtbl\\|String\\|List"
+     Passed: 2 (0 unexpected)
+     Failed: 1 (1 unexpected)
+     Error:  0 (0 unexpected)
+     Total:  3/3
+
+     Started at:   2012-07-23 16:28:08-0400
+     Finished.
+     Finished at:  2012-07-23 16:28:08-0400
+
+     ..F
+
+     F List\.assoc\.3
+         (ert-test-failed
+          ((ert-should
+            (equal
+             (List\.assoc 5 ...)
+             '...))
+           :form
+           (equal
+            (6)
+            (7))
+           :value nil :explanation
+           (list-elt 0
+                     (different-atoms 6 7))))
+
+  From the *ert* buffer you can jump to the errors (typing '.'), fix the code, and
+  rerun the test (typing 'r').
+
+  This will be a major part of the planned omake-mode testing framework.
+
+
+
+
+changes
+=======
+
+- Omake.shutdown kills non-project buffers as well as project buffers.
+
+bug fixes
+=========
+- If a unit test failed, it would stop the rest
+  of the init code from running, thus making Emacs unusable.
+
+--------------------------------------------------------------------------------
+
 new stuff
 =========
 
   Now all relevant logs and buffers are saved to
   /tmp/omake-server/USER/bug-report/N
   The command asks the user for a message, which is also stored in
-  the directory.  An email is sent including the user message and 
+  the directory.  An email is sent including the user message and
   where to find the files.
 
 - omake-mode working on OSX

File bin/check.sh

+#!/bin/bash
+
+#set -x
+# Create a single file with all the elisp files and compile it to make
+# sure there are no errors
+
+tmp_file=/tmp/all.el
+
+bin=$(dirname $(pwd)/$0)
+home=$(dirname $bin)
+contrib_dir=$home/elisp/contrib
+jane_dir=$home/elisp/jane
+omake_dir=$home/elisp/omake
+
+# top_files="
+# jane-common"
+
+jane_files="
+jane-lib"
+
+#jane-micro-features"
+
+omake_files="
+omake-custom
+omake-file
+omake-errors
+omake-version
+omake-face
+omake-id
+omake-path
+omake-progress
+omake-window
+omake-error
+omake-ring
+omake-failure
+omake-result
+omake-status
+omake-buffer
+omake-spinner
+omake-project
+omake-model
+omake-env
+omake-ocaml
+omake-filter
+omake-connection
+omake-server
+omake-ping
+omake-timer
+omake-interface
+omake-setup"
+
+rm -f $tmp_file
+cat > $tmp_file <<EOF
+(eval-when-compile
+  (require 'bytecomp)
+  (require 'autorevert)
+  (setq byte-compile-warnings (remove 'cl-functions byte-compile-warning-types))
+  (require 'cl)
+  (add-to-list 'load-path "$contrib_dir"))
+(declare-function find-if "cl-seq")
+(declare-function remove-if "cl-seq")
+(declare-function remove-if-not "cl-seq")
+(declare-function set-difference "cl-seq")
+(declare-function reduce "cl-seq")
+(declare-function auto-revert-mode "autorevert")
+EOF
+
+function e {
+    echo $1 >> $tmp_file
+}
+
+
+function emit {
+    e ";; -----------------------------------------------------------------------------"
+    e ";; $1"
+    e ";; -----------------------------------------------------------------------------"
+}
+
+# for file in $top_files; do
+#     emit $file
+#     cat $home/$file.el >> $tmp_file
+# done
+
+for file in $jane_files; do
+    emit $file
+    cat $jane_dir/$file.el >> $tmp_file
+done
+
+for file in $omake_files; do
+    emit $file
+    cat $omake_dir/$file.el >> $tmp_file
+done
+
+batch=/tmp/batch.txt
+emacs --batch -f batch-byte-compile $tmp_file &> $batch
+
+if grep "Error\|Warning" $batch &> /dev/null; then
+    echo "check.sh: compilation failed"
+    cat $batch
+    exit 1
+fi
+
+emacs --batch "(require \"ert\") (ert-run-tests-interactively)" $tmp_file &> $batch
+

File elisp/jane/jane-lib.el

 (require 'bytecomp)
 (setq byte-compile-warnings (remove 'cl-functions byte-compile-warning-types))
 (require 'cl)
+(require 'sendmail)
 (require 'ert)
 
 
 ;; (Jane.Test.regexp)
 
 (defun Jane.Test.add-module (sym)
+  "Add Foo from, e.g. Foo.List.map, to the test modules list"
   (let* ((name (symbol-name sym))
          (_ (string-match "\\([A-Za-z]+\\)\..*" name))
          (mod (match-string 1 name)))
     (add-to-list 'Jane.Test.modules mod)))
-               
+
 (defmacro Jane.test (sym e1)
-  (Jane.Test.add-module sym)
-  `(ert-deftest ,sym () (ert-should ,e1)))
+  `(progn
+     (Jane.Test.add-module ',sym)
+     (ert-deftest ,sym () (ert-should ,e1))))
                
 (defmacro Jane.test-eq (sym e1 e2)
-  (Jane.Test.add-module sym)
-  `(ert-deftest ,sym () (ert-should (equal ,e1 ,e2))))
+  `(progn
+     (Jane.Test.add-module ',sym)
+     (ert-deftest ,sym () (ert-should (equal ,e1 ,e2)))))
                
 (defmacro Jane.test-error (sym e)
-;  (Jane.Test.add-module sym)
-  `(ert-deftest ,sym ()
-     (ert-should-error ,e)))
+  `(progn
+     (Jane.Test.add-module ',sym)
+     (ert-deftest ,sym () (ert-should-error ,e))))
 
 (defun Jane.run-tests ()
   (interactive)
     (List.iter (lambda (x)
                  (funcall f ctr x)
                  (setq ctr (+ ctr 1))) l)))
-
 (Jane.test-eq List.iteri.1 
            (let ((ctr 0))
              (List.iteri (lambda (i x) (setq ctr (+ ctr i x))) '(1 1 1 1 1))
   (cond
    ((null l) t)
    (t (and (funcall p (car l)) (List.all p (cdr l))))))
-;; (List.all (lambda (x) (> x 5)) '(6 7 8))
-;; (List.all (lambda (x) (> x 5)) '(6 3 8))
-
-(defunl List.exists (p l)
-  (cond
-   ((null l) nil)
-   (t (or (funcall p (car l)) (List.exists p (cdr l))))))
-;; (List.exists (lambda (x) (> x 5)) '(6 7 8))
-;; (List.exists (lambda (x) (> x 5)) '(1 2 3))
+(Jane.test List.all.1 (List.all (lambda (x) (> x 0)) '(1 2 3 4)))
 
 (defun List.replicate (x n)
   (if (equal n 0) ()
 (defun String.strip (s)
   "Replace space before and after a string.  There should be no newlines in the 
 string."
-  (assert (not (string-match "\n" s)) t "No newlines in String.strip")
-  (let ((s (replace-regexp-in-string "^[ \t]*" "" s)))
-    (replace-regexp-in-string "[ \t]*$" "" s)))
+  (let ((s (replace-regexp-in-string "\\`[ \t]*" "" s)))
+    (replace-regexp-in-string "[ \t]*\\'" "" s)))
 (Jane.test-eq String.strip.1 (String.strip " abc def ") "abc def")
-(Jane.test-error String.strip.2 (progn (error "abc") (String.strip " abc \n def ")))
+(Jane.test-eq String.strip.2 (String.strip " abc \n def ") "abc \n def")
 
 (defun String.eval (s)
   "Eval a string as code"
 ;; Hash tables                                                                ;;
 ;;----------------------------------------------------------------------------;;
 
-(setq tbl (make-hash-table :test 'equal))
-(puthash 'a 5 tbl)
-(puthash 'b 6 tbl)
-(puthash 'c 7 tbl)
-(setq tbll '((a . 5) (b . 6) (c . 7)))
-
 (defun Hashtbl.to-alist (tbl)
   (let ((data nil))
     (maphash (lambda (k v) (setq data (cons (cons k v) data))) tbl)
     (reverse data)))
-(Jane.test-eq Hashtbl.to-alist.1 (Hashtbl.to-alist tbl) tbll)
+(Jane.test Hashtbl.to-alist.1 
+           (let ((tbl (make-hash-table :test 'equal))
+                 (l '((a . 5) (b . 6) (c . 7))))
+             (puthash 'a 5 tbl)
+             (puthash 'b 6 tbl)
+             (puthash 'c 7 tbl)
+             (equal (Hashtbl.to-alist tbl) l)))
 
 (defun Hashtbl.of-alist (l)
   (let ((tbl (make-hash-table :test 'equal)))
     (dolist (x l) (puthash (car x) (cdr x) tbl))
     tbl))
-;; This test isn't great.  The order may get messed up, but it seems
-;; to work.
-(Jane.test-eq Hashtbl.of-alist.1 (Hashtbl.to-alist (Hashtbl.of-alist tbll)) tbll)
+(Jane.test Hashtbl.of-alist.1 
+           (let ((l '((a . 5) (b . 6) (c . 7))))
+             (equal l (Hashtbl.to-alist (Hashtbl.of-alist l)))))
 
 (defun Hashtbl.keys (tbl)
   (List.map 'car (Hashtbl.to-alist tbl)))
-(Jane.test-eq Hashtbl.keys.1 (Hashtbl.keys tbl) '(a b c))
+(Jane.test Hashtbl.keys.1
+           (let ((tbl (Hashtbl.of-alist '((a . 5) (b . 6) (c . 7)))))
+             (equal (Hashtbl.keys tbl) '(a b c))))
 
 (defun Hashtbl.data (tbl)
   (List.map 'cdr (Hashtbl.to-alist tbl)))
-(Jane.test-eq Hashtbl.data.1 (Hashtbl.data tbl) '(5 6 7))
+(Jane.test Hashtbl.data.1
+           (let ((tbl (Hashtbl.of-alist '((a . 5) (b . 6) (c . 7)))))
+             (equal (Hashtbl.data tbl) '(5 6 7))))
 
 (defunl Hashtbl.iter (f tbl)
   (maphash f tbl))
-
-(Jane.test-eq  Hashtbl.iter.1 
-           (let ((ctr 0))
-             (Hashtbl.iter (lambda (_ x) (setq ctr (+ ctr x))) tbl)
-             ctr) 18)
+(Jane.test Hashtbl.iter.1 
+              (let ((tbl (Hashtbl.of-alist '((a . 5) (b . 6) (c . 7))))
+                    (ctr 0))
+                (Hashtbl.iter (lambda (_ x) (setq ctr (+ ctr x))) tbl)
+                (equal ctr 18)))
 
 
 ;;----------------------------------------------------------------------------;;
   (let ((file (read-file-name "File: ")))
     (byte-compile-file file)
     (message "removing compiled file")
-    (remove-file (concat file "c"))))
+    (delete-file (concat file "c"))))
 
 
 ;;----------------------------------------------------------------------------;;

File elisp/jane/jane-micro-features.el

 
 ;; (Jane.compilation)
 (defun Jane.compilation ()
-  (defcustom jane-ask-before-killing-compilations t
-    "If you have compilation buffers, ask about killing them before killing emacs."
-    :group 'js)
+  (eval-and-compile
+    (defcustom jane-ask-before-killing-compilations t
+      "If you have compilation buffers, ask about killing them before killing emacs."
+      :group 'js))
 
   (add-hook 'compilation-mode-hook
             (lambda ()
 
 ;; (Jane.dired)
 (defun Jane.dired ()
-  (require 'dired)
-  (require 'dired-x)
+  (eval-and-compile
+    (require 'dired)
+    (require 'dired-x))
   (add-hook 'dired-mode-hook
          (function (lambda ()
                      (dired-omit-mode 1)
 ;; (Jane.iswitchb)
 (defun Jane.iswitchb ()
   "Buffer management -- C-xb shows matching buffers interactively"
-  (require 'iswitchb)
+  (eval-and-compile (require 'iswitchb))
   (iswitchb-mode 1)
   (custom-set-variables
    '(read-buffer-function 'iswitchb-read-buffer)

File elisp/omake/make.sh

-#!/bin/bash
-
-# Create a single file with all of omake.el and compile it to make
-# sure everything is defined.
-
-file=/tmp/all.el
-
-case $(uname) in
-    Darwin)
-        path=/Users/seanmcl/save/projects/omake-mode/elisp/jane
-        ;;
-    Linux)
-        path=/home/seanmcl/jane-local/elisp/jane
-        ;;
-    *)
-        echo "Unknown system"
-esac
-
-files="
-omake-file.el
-omake-errors.el
-omake-version.el
-omake-custom.el
-omake-face.el
-omake-id.el
-omake-path.el
-omake-progress.el
-omake-window.el
-omake-error.el
-omake-ring.el
-omake-failure.el
-omake-result.el
-omake-status.el
-omake-buffer.el
-omake-spinner.el
-omake-project.el
-omake-model.el
-omake-env.el
-omake-ocaml.el
-omake-filter.el
-omake-connection.el
-omake-server.el
-omake-ping.el
-omake-timer.el
-omake-interface.el
-omake-setup.el
-"
-
-rm -f $file
-cat > $file <<EOF
-(eval-when-compile
-  (require 'bytecomp)
-  (require 'autorevert)
-  (setq byte-compile-warnings (remove 'cl-functions byte-compile-warning-types))
-  (require 'cl)
-  (add-to-list 'load-path "$path")
-  (require 'jane-lib))
-(declare-function remove-if-not "cl-seq")
-(declare-function set-difference "cl-seq")
-(declare-function reduce "cl-seq")
-(declare-function auto-revert-mode "autorevert")
-EOF
-
-cat $files >> $file
-
-emacs --batch -f batch-byte-compile $file

File elisp/omake/omake-buffer.el

       (mode-log "[omake mode log]")
       (projects "[omake projects]"))))
 
+(defun Omake.Buffer.kill-non-project-buffers ()
+  (Omake.Buffer.kill 'server-log)
+  (Omake.Buffer.kill 'mode-log)
+  (Omake.Buffer.kill 'projects))
+
 (defun Omake.Buffer.is-status-buffer (buffer)
   (assert (bufferp buffer))
   (let ((name (buffer-name buffer)))
             (with-current-buffer buf
               (when dir (cd dir))
               (toggle-read-only 1)
-              (case kind 
+              (case kind
                 ;; Don't turn on omake-mode in the projects buffer
                 (projects nil)
                 (t (omake-mode 1))))))

File elisp/omake/omake-connection.el

 (defun Omake.Connection.open ()
   "A TCP connection is made to the server via the user's socket."
   (message "Establishing a connection to the server.")
-  (let* ((user (String.strip (shell-command-to-string "whoami")))
-         (p (make-network-process
+  (let* ((p (make-network-process
              :name "omake-server"
              :filter 'Omake.Filter.fun
              :family 'local
-             :service (concat "/tmp/omake-server/" user "/socket")
+             :service (concat "/tmp/omake-server/" Omake.user "/socket")
              :family 'local)))
     (set-process-query-on-exit-flag p nil)
     (setq Omake.Connection.process p)

File elisp/omake/omake-errors.el

                        (Mail.send :recipients recipients
                                   :subject subject
                                   :body body))))
-         copy)
-      (fset 'copy
-            (lambda (f name) 
-              (Omake.ignore-errors
-                  (copy-file f (expand-file-name name dir)))))
-      (fset 'copy-buf
-            (lambda (b name) 
-              (Omake.ignore-errors
-               (with-current-buffer b (write-file name)))))
+         (copy
+          (lambda (f name) 
+            (Omake.ignore-errors
+              (copy-file f (expand-file-name name dir)))))
+         (copy-buf
+          (lambda (b name) 
+            (Omake.ignore-errors
+              (with-current-buffer b (write-file name))))))
       (message "Collecting bug files")
-      (copy Omake.File.server-log "server-log")
-      (copy Omake.File.server-state "server-state.el")
-      (copy Omake.File.mode-log "mode-log")
-      (copy (Omake.File.raw id) "raw")
-      (copy (Omake.File.elisp id) "elisp")
-      (copy (Omake.File.project-log id) "project-log")
+      (funcall copy Omake.File.server-log "server-log")
+      (funcall copy Omake.File.server-state "server-state.el")
+      (funcall copy Omake.File.mode-log "mode-log")
+      (funcall copy (Omake.File.raw id) "raw")
+      (funcall copy (Omake.File.elisp id) "elisp")
+      (funcall copy (Omake.File.project-log id) "project-log")
       (Omake.ignore-errors
-       (copy-buf (Omake.Buffer.get 'status) "status-buffer"))
+       (funcall copy-buf (Omake.Buffer.get 'status) "status-buffer"))
       (message "Emailing maintainer")
       (Omake.Errors.get-bug-desc callback))))
 

File elisp/omake/omake-interface.el

 
 (defun Omake.shutdown ()
   (interactive)
-  (Omake.Server.stop))
+  (Omake.Server.stop)
+  ;; project buffers should be dead now
+  (Omake.Buffer.kill-non-project-buffers))
 
 (defun Omake.shutdown-and-remove-hooks ()
   (interactive)
   (interactive)
   (Omake.Model.reset-visited (Omake.Id.current)))
 
-;; CR smclaughlin: make this copy the log and omake files?
-;;
-;; 2012-06-05 sweeks: I commented out Omake.notify-maintainer-of-error until we make it
-;; better.
-;;
-;; (defun Omake.notify-maintainer-of-error ()
-;;   "Send an email with the raw buffer"
-;;   (interactive)
-;;   (let* ((id (Omake.Id.current))
-;;          (msg (read-from-minibuffer "Message: "))
-;;          (file (format "%s/%s-%s.txt"
-;;                       Omake.error-file-dir
-;;                       Omake.user
-;;                       (format-time-string "%Y-%m-%d")))
-;;          (body (format "%s: %s" Omake.user msg)))
-;;     (Shell.mail "omake-mode error" Omake.maintainer-email-addr msg)))
-;; (Omake.notify-maintainer-of-error "/mnt/local/sda1/smclaughlin/gord/trunk/")
-
 (provide 'omake-interface)

File elisp/omake/omake-model.el

              (project (Omake.Model.project model))
              (dir (Omake.Project.omakeroot-dir project)))
         ;; Critical section
-        (Omake.Buffer.kill 'status project t)
+        ;(Omake.Buffer.kill 'status project t)
         (Omake.Buffer.kill 'raw project)
         (Omake.Buffer.kill 'elisp project)
         (Omake.Buffer.kill 'project-log project)