From fcf18786b4c37972d9220bfb8bbe6a4875433faf Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Thu, 5 Sep 2013 23:02:37 -0400 Subject: [PATCH] Add ERT tests --- src/etc/emacs/README.md | 6 + src/etc/emacs/run_rust_emacs_tests.sh | 3 + src/etc/emacs/rust-mode-tests.el | 380 ++++++++++++++++++++++++++ 3 files changed, 389 insertions(+) create mode 100755 src/etc/emacs/run_rust_emacs_tests.sh create mode 100644 src/etc/emacs/rust-mode-tests.el diff --git a/src/etc/emacs/README.md b/src/etc/emacs/README.md index 508ac7f1af27f..63fbe1f681cb2 100644 --- a/src/etc/emacs/README.md +++ b/src/etc/emacs/README.md @@ -68,6 +68,12 @@ marking, press x, and ELPA will install the packages for you (under * or using M-x package-install rust-mode +### Tests via ERT + +The file `rust-mode-tests.el` contains tests that can be run via ERT. You can +use `run_rust_emacs_tests.sh` to run them in batch mode, if emacs is somewhere +in your `$PATH`. + ### Known bugs * Combining `global-whitespace-mode` and `rust-mode` is generally glitchy. diff --git a/src/etc/emacs/run_rust_emacs_tests.sh b/src/etc/emacs/run_rust_emacs_tests.sh new file mode 100755 index 0000000000000..afb98fde7b047 --- /dev/null +++ b/src/etc/emacs/run_rust_emacs_tests.sh @@ -0,0 +1,3 @@ +# This runs the test for emacs rust-mode. +# It must be possible to find emacs via PATH. +emacs -batch -l rust-mode.el -l rust-mode-tests.el -f ert-run-tests-batch-and-exit diff --git a/src/etc/emacs/rust-mode-tests.el b/src/etc/emacs/rust-mode-tests.el new file mode 100644 index 0000000000000..a7cb2613b9aa7 --- /dev/null +++ b/src/etc/emacs/rust-mode-tests.el @@ -0,0 +1,380 @@ +;;; rust-mode-tests.el --- ERT tests for rust-mode.el + +(require 'rust-mode) +(require 'ert) +(require 'cl) + +(setq rust-test-fill-column 32) + +(defun rust-compare-code-after-manip (original point-pos manip-func expected got) + (equal expected got)) + +(defun rust-test-explain-bad-manip (original point-pos manip-func expected got) + (if (equal expected got) + nil + (list + ;; The (goto-char) and (insert) business here is just for + ;; convenience--after an error, you can copy-paste that into emacs eval to + ;; insert the bare strings into a buffer + "Rust code was manipulated wrong after:" + `(insert ,original) + `(goto-char ,point-pos) + 'expected `(insert ,expected) + 'got `(insert ,got) + (loop for i from 0 to (max (length original) (length expected)) + for oi = (if (< i (length got)) (elt got i)) + for ei = (if (< i (length expected)) (elt expected i)) + while (equal oi ei) + finally return `(first-difference-at + (goto-char ,(+ 1 i)) + expected ,(char-to-string ei) + got ,(char-to-string oi)))))) +(put 'rust-compare-code-after-manip 'ert-explainer + 'rust-test-explain-bad-manip) + +(defun rust-test-manip-code (original point-pos manip-func expected) + (with-temp-buffer + (rust-mode) + (insert original) + (goto-char point-pos) + (funcall manip-func) + (should (rust-compare-code-after-manip + original point-pos manip-func expected (buffer-string))))) + +(defun test-fill-paragraph (unfilled expected &optional start-pos end-pos) + "We're going to run through many scenarios here--the point should be able to be anywhere from the start-pos (defaults to 1) through end-pos (defaults to the length of what was passed in) and (fill-paragraph) should return the same result. + +Also, the result should be the same regardless of whether the code is at the beginning or end of the file. (If you're not careful, that can make a difference.) So we test each position given above with the passed code at the beginning, the end, neither and both. So we do this a total of (end-pos - start-pos)*4 times. Oy." + (let* ((start-pos (or start-pos 1)) + (end-pos (or end-pos (length unfilled))) + (padding "\n \n") + (padding-len (length padding))) + (loop + for pad-at-beginning from 0 to 1 + for pad-at-end from 0 to 1 + with padding-beginning = (if (= 0 pad-at-beginning) "" padding) + with padding-end = (if (= 0 pad-at-end) "" padding) + with padding-adjust = (* padding-len pad-at-beginning) + with padding-beginning = (if (= 0 pad-at-beginning) "" padding) + with padding-end = (if (= 0 pad-at-end) "" padding) + for pos from (if (= 1 start-pos) 1 (+ padding-adjust start-pos)) to (+ end-pos padding-adjust) + do (rust-test-manip-code + (concat padding-beginning unfilled padding-end) + pos + (lambda () + (let ((fill-column rust-test-fill-column)) + (fill-paragraph))) + (concat padding-beginning expected padding-end))))) + +(ert-deftest fill-paragraph-top-level-multi-line-style-doc-comment-second-line () + (test-fill-paragraph + "/** + * This is a very very very very very very very long string + */" + "/** + * This is a very very very very + * very very very long string + */")) + + +(ert-deftest fill-paragraph-top-level-multi-line-style-doc-comment-first-line () + (test-fill-paragraph + "/** This is a very very very very very very very long string + */" + "/** This is a very very very + * very very very very long + * string + */")) + +(ert-deftest fill-paragraph-multi-paragraph-multi-line-style-doc-comment () + (let + ((multi-paragraph-unfilled + "/** + * This is the first really really really really really really really long paragraph + * + * This is the second really really really really really really long paragraph + */")) + (test-fill-paragraph + multi-paragraph-unfilled + "/** + * This is the first really + * really really really really + * really really long paragraph + * + * This is the second really really really really really really long paragraph + */" + 1 89) + (test-fill-paragraph + multi-paragraph-unfilled + "/** + * This is the first really really really really really really really long paragraph + * + * This is the second really + * really really really really + * really long paragraph + */" + 90))) + +(ert-deftest fill-paragraph-multi-paragraph-single-line-style-doc-comment () + (let + ((multi-paragraph-unfilled + "/// This is the first really really really really really really really long paragraph +/// +/// This is the second really really really really really really long paragraph")) + (test-fill-paragraph + multi-paragraph-unfilled + "/// This is the first really +/// really really really really +/// really really long paragraph +/// +/// This is the second really really really really really really long paragraph" + 1 86) + (test-fill-paragraph + multi-paragraph-unfilled + "/// This is the first really really really really really really really long paragraph +/// +/// This is the second really +/// really really really really +/// really long paragraph" + 87))) + +(ert-deftest fill-paragraph-multi-paragraph-single-line-style-indented () + (test-fill-paragraph + " // This is the first really really really really really really really long paragraph + // + // This is the second really really really really really really long paragraph" + " // This is the first really + // really really really + // really really really + // long paragraph + // + // This is the second really really really really really really long paragraph" 1 89)) + +(ert-deftest fill-paragraph-multi-line-style-inner-doc-comment () + (test-fill-paragraph + "/*! This is a very very very very very very very long string + */" + "/*! This is a very very very + * very very very very long + * string + */")) + +(ert-deftest fill-paragraph-single-line-style-inner-doc-comment () + (test-fill-paragraph + "//! This is a very very very very very very very long string" + "//! This is a very very very +//! very very very very long +//! string")) + +(ert-deftest fill-paragraph-prefixless-multi-line-doc-comment () + (test-fill-paragraph + "/** +This is my summary. Blah blah blah blah blah. Dilly dally dilly dally dilly dally doo. + +This is some more text. Fee fie fo fum. Humpty dumpty sat on a wall. +*/" + "/** +This is my summary. Blah blah +blah blah blah. Dilly dally +dilly dally dilly dally doo. + +This is some more text. Fee fie fo fum. Humpty dumpty sat on a wall. +*/" 4 90)) + +(ert-deftest fill-paragraph-with-no-space-after-star-prefix () + (test-fill-paragraph + "/** + *This is a very very very very very very very long string + */" + "/** + *This is a very very very very + *very very very long string + */")) + +(defun test-auto-fill (initial position inserted expected) + (rust-test-manip-code + initial + position + (lambda () + (unwind-protect + (progn + (let ((fill-column rust-test-fill-column)) + (auto-fill-mode) + (goto-char position) + (insert inserted) + (syntax-ppss-flush-cache 1) + (funcall auto-fill-function))) + (auto-fill-mode t))) + expected)) + +(ert-deftest auto-fill-multi-line-doc-comment () + (test-auto-fill + "/** + * + */" + 8 + "This is a very very very very very very very long string" + "/** + * This is a very very very very + * very very very long string + */")) + +(ert-deftest auto-fill-single-line-doc-comment () + (test-auto-fill + "/// This is the first really +/// really really really really +/// really really long paragraph +/// +/// " + 103 + "This is the second really really really really really really long paragraph" + "/// This is the first really +/// really really really really +/// really really long paragraph +/// +/// This is the second really +/// really really really really +/// really long paragraph" + )) + +(ert-deftest auto-fill-multi-line-prefixless () + (test-auto-fill + "/* + + */" + 4 + "This is a very very very very very very very long string" + "/* +This is a very very very very +very very very long string + */" + )) + +(defun test-indent (indented) + (let ((deindented (replace-regexp-in-string "^[[:blank:]]*" " " indented))) + (rust-test-manip-code + deindented + 1 + (lambda () (indent-region 1 (buffer-size))) + indented))) + + +(ert-deftest indent-struct-fields-aligned () + (test-indent +" +struct Foo { bar: int, + baz: int } + +struct Blah {x:int, + y:int, + z:~str}")) + +(ert-deftest indent-doc-comments () + (test-indent +" +/** + * This is a doc comment + * + */ + +/// So is this + +fn foo() { + /*! + * this is a nested doc comment + */ + + //! And so is this +}")) + +(ert-deftest indent-inside-braces () + (test-indent + " +// struct fields out one level: +struct foo { + a:int, + // comments too + b:char +} + +fn bar(x:~int) { // comment here should not affect the next indent + bla(); + bla(); +}")) + +(ert-deftest indent-top-level () + (test-indent + " +// Everything here is at the top level and should not be indented +#[attrib] +mod foo; + +pub static bar = Quux{a: b()} + +use foo::bar::baz; + +fn foo() { } +")) + +(ert-deftest indent-params-no-align () + (test-indent + " +// Indent out one level because no params appear on the first line +fn xyzzy( + a:int, + b:char) { } + +fn abcdef( + a:int, + b:char) + -> char +{ }")) + +(ert-deftest indent-params-align () + (test-indent + " +// Align the second line of params to the first +fn foo(a:int, + b:char) { } + +fn bar( a:int, + b:char) + -> int +{ } + +fn baz( a:int, // shoudl work with a comment here + b:char) + -> int +{ } +")) + +(ert-deftest indent-square-bracket-alignment () + (test-indent + " +fn args_on_the_next_line( // with a comment + a:int, + b:~str) { + let aaaaaa = [ + 1, + 2, + 3]; + let bbbbbbb = [1, 2, 3, + 4, 5, 6]; + let ccc = [ 10, 9, 8, + 7, 6, 5]; +} +")) + +(ert-deftest indent-nested-fns () + (test-indent + " +fn nexted_fns(a: fn(b:int, + c:char) + -> int, + d: int) + -> uint +{ + 0 +} +" +))