;;; 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 do (loop 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) ;; If we're adding space to the beginning, and our start position ;; is at the very beginning, we want to test within the added space. ;; Otherwise adjust the start and end for the beginning padding. with start-pos = (if (= 1 start-pos) 1 (+ padding-adjust start-pos)) with end-pos = (+ end-pos padding-adjust) do (loop for pos from start-pos to end-pos 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 } " )) (ert-deftest indent-multi-line-expr () (test-indent " fn foo() { x(); let a = b(); } " ))