csharp-mode-tests.el (16123B)
1 ;;; csharp-mode-tests.el --- Tests for csharp-mode.el -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2020-2021 Free Software Foundation, Inc. 4 5 ;; Author: Josten Kjønigsen <jostein@gmail.com> 6 ;; Keywords: tests 7 8 ;; This program is free software; you can redistribute it and/or modify 9 ;; it under the terms of the GNU General Public License as published by 10 ;; the Free Software Foundation, either version 3 of the License, or 11 ;; (at your option) any later version. 12 13 ;; This program is distributed in the hope that it will be useful, 14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ;; GNU General Public License for more details. 17 18 ;; You should have received a copy of the GNU General Public License 19 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 20 21 (require 'ert) 22 (require 'cl-lib) 23 (require 'csharp-mode) 24 (require 'package) 25 26 ;; development only packages, not declared as a package-dependency 27 ;; FIXME: loading a .el file from `load-path' should not change user's settings 28 ;; like that. It can happen without the user explicitly requesting it! 29 (package-initialize) 30 (add-to-list 'package-archives '("melpa" . "https://stable.melpa.org/packages/")) 31 32 ;; required to resolve SEQ (or anything on elpa) on Emacs25. 33 (setq package-check-signature nil) 34 35 ;; assess depends on dash 2.12.1, which is no longer available 36 ;; installing dash, resolves 2.13.0, and fixes this broken dependency. 37 (dolist (p '(dash assess)) 38 (when (not (package-installed-p p)) 39 (package-refresh-contents) 40 (package-install p))) 41 42 ;;; test-helper functions 43 44 (defmacro assess-face-in-text= (testee &rest assessments) 45 (when assessments 46 (let* ((text (car assessments)) 47 (face (cadr assessments)) 48 (rest (cddr assessments))) 49 `(progn 50 (require 'assess) 51 (should (assess-face-at= ,testee 'csharp-mode ,text ,face)) 52 (assess-face-in-text= ,testee ,@rest))))) 53 54 (defmacro assess-face-in-file= (file-name &rest assessments) 55 (let* ((find-file-hook nil) ;; disable vc-mode hooks 56 (buffer (find-file-read-only file-name)) 57 (contents (buffer-substring-no-properties (point-min) (point-max)))) 58 (kill-buffer buffer) 59 `(assess-face-in-text= ,contents ,@assessments))) 60 61 ;;; actual tests 62 63 (ert-deftest activating-mode-doesnt-cause-failure () 64 (with-temp-buffer 65 (csharp-mode) 66 (should 67 (equal 'csharp-mode major-mode)))) 68 69 (defvar debug-res nil) 70 71 (ert-deftest fontification-of-literals-detects-end-of-strings () 72 (assess-face-in-file= "./test-files/fontification-test.cs" 73 "bool1" 'font-lock-type-face 74 "Reference1" 'font-lock-variable-name-face 75 "false" 'font-lock-constant-face 76 "bool2" 'font-lock-type-face 77 "Reference2" 'font-lock-variable-name-face 78 "true" 'font-lock-constant-face 79 )) 80 81 (when (and (>= emacs-major-version 29) 82 (string-lessp "5.35.0" c-version)) 83 (ert-deftest fontification-of-multiline-strings () 84 (assess-face-in-file= "./test-files/multiline-strings.cs" 85 "Literal0" 'font-lock-variable-name-face 86 "Literal1" 'font-lock-variable-name-face 87 "Literal2" 'font-lock-variable-name-face 88 "Literal3" 'font-lock-variable-name-face 89 "Literal4" 'font-lock-variable-name-face 90 "Literal5" 'font-lock-variable-name-face 91 "Literal6" 'font-lock-variable-name-face 92 "Literal7" 'font-lock-variable-name-face))) 93 94 (ert-deftest fontification-of-constants () 95 (require 'assess) 96 (assess-face-in-text= 97 "testBool1 = true;\ntestBool2 = false;\ntestObj = null;\ntestProp = value;" 98 "false" 'font-lock-constant-face 99 "true" 'font-lock-constant-face 100 "null" 'font-lock-constant-face 101 "value" 'font-lock-constant-face 102 )) 103 104 (ert-deftest fontification-of-package () 105 (require 'assess) 106 (assess-face-in-text= 107 "var package = true;" 108 "package" 'font-lock-variable-name-face)) 109 110 (ert-deftest fontification-of-functions () 111 (require 'assess) 112 (assess-face-in-text= "var foo = bar.Baz()" 113 "Baz" 'font-lock-function-name-face) 114 (assess-face-in-text= "var foo = bar.Baz<Quux>()" 115 "Baz" 'font-lock-function-name-face 116 "Quux" 'font-lock-type-face)) 117 118 (ert-deftest fontification-of-import () 119 (require 'assess) 120 (assess-face-in-text= 121 "var import = true;" 122 "import" 'font-lock-variable-name-face)) 123 124 (ert-deftest fontification-of-literals-allows-multi-line-strings () 125 (require 'assess) 126 (should (assess-face-at= 127 "string Literal = \"multi-line\nstring\";" 128 'csharp-mode 129 ;; should be interpreted as error 130 18 'font-lock-warning-face 131 )) 132 (should (assess-face-at= 133 "string Literal = @\"multi-line\nstring\";" 134 'csharp-mode 135 ;; should not be interpreted as error because of @ 136 19 'font-lock-string-face 137 ))) 138 139 ;; (ert-deftest fontification-of-compiler-directives () 140 ;; ;; this replaces the manual test of 141 ;; ;; test-files/fontification-test-compiler-directives.cs, but file 142 ;; ;; has been kept around to assist manual testing/verification. 143 ;; (assess-face-in-file= "test-files/fontification-test-compiler-directives.cs" 144 ;; "strReference" 'font-lock-string-face 145 ;; "strVerification" 'font-lock-string-face 146 ;; "singleQuote" 'font-lock-string-face 147 ;; "doubleQuote" 'font-lock-string-face) 148 149 ;; (assess-face-in-text= 150 ;; "#region test\nbool bar = true;" 151 ;; ;; should not be interpreted as string because of trailing \! 152 ;; "bool" 'font-lock-type-face 153 ;; "bar" 'font-lock-variable-name-face 154 ;; "true" 'font-lock-constant-face 155 ;; ) 156 ;; (should (assess-face-at= 157 ;; "#region test'\nx = true;" 158 ;; 'csharp-mode 159 ;; ;; should not be interpreted as string because of trailing \! 160 ;; "true" 'font-lock-constant-face 161 ;; )) 162 ;; (should (assess-face-at= 163 ;; "#region test\"\nx = true;" 164 ;; 'csharp-mode 165 ;; ;; should not be interpreted as string because of trailing \! 166 ;; "true" 'font-lock-constant-face 167 ;; ))) 168 169 (ert-deftest fontification-of-compiler-directives-after-comments () 170 (assess-face-in-file= "./test-files/fontification-test-compiler-directives-with-comments.cs" 171 "case1" 'font-lock-comment-face 172 "case2" 'font-lock-comment-face)) 173 174 (ert-deftest fontification-of-method-names () 175 (assess-face-in-file= "./test-files/imenu-method-test.cs" 176 "OpenWebServicesAsync" 'font-lock-function-name-face 177 "ToString" 'font-lock-function-name-face 178 "Equals" 'font-lock-function-name-face 179 "AbstractMethod" 'font-lock-function-name-face 180 "UnsafeCopy" 'font-lock-function-name-face 181 ;; "GenericMethod1" 'font-lock-function-name-face 182 ;; "GenericMethod2" 'font-lock-function-name-face 183 )) 184 185 (ert-deftest fontification-of-using-statements () 186 (assess-face-in-file= "./test-files/using-fontification.cs" 187 "using" 'font-lock-keyword-face 188 "Reference" 'font-lock-variable-name-face 189 "Under_scored" 'font-lock-variable-name-face 190 "WithNumbers09" 'font-lock-variable-name-face 191 "Ok" 'font-lock-variable-name-face 192 "WithNumbers09" 'font-lock-variable-name-face 193 "OkV2" 'font-lock-variable-name-face 194 )) 195 196 (ert-deftest fontification-of-namespace-statements () 197 (assess-face-in-file= "./test-files/namespace-fontification.cs" 198 "namespace" 'font-lock-keyword-face 199 "Reference" 'font-lock-variable-name-face 200 "Under_scored" 'font-lock-variable-name-face 201 "WithNumbers09" 'font-lock-variable-name-face 202 "Ok" 'font-lock-variable-name-face 203 "WithNumbers09" 'font-lock-variable-name-face 204 "Ok" 'font-lock-variable-name-face 205 )) 206 207 (defun list-repeat-once (mylist) 208 (append mylist mylist)) 209 210 (ert-deftest build-warnings-and-errors-are-parsed () 211 (dolist (test-case 212 `(("./test-files/msbuild-warning.txt" ,csharp-compilation-re-msbuild-warning 213 ,(list-repeat-once 214 '("Class1.cs" 215 "Folder\\Class1.cs" 216 "Program.cs" 217 "Program.cs"))) 218 ("./test-files/msbuild-error.txt" ,csharp-compilation-re-msbuild-error 219 ,(list-repeat-once 220 '("Folder\\Class1.cs"))) 221 ("./test-files/msbuild-concurrent-warning.txt" ,csharp-compilation-re-msbuild-warning 222 ,(list-repeat-once 223 '("Program.cs"))) 224 ("./test-files/msbuild-concurrent-error.txt" ,csharp-compilation-re-msbuild-error 225 ,(list-repeat-once 226 '("Program.cs"))) 227 ("./test-files/msbuild-square-brackets.txt" ,csharp-compilation-re-msbuild-error 228 ,(list-repeat-once 229 '("Properties\\AssemblyInfo.cs" 230 "Program.cs" 231 "Program.cs"))) 232 ("./test-files/msbuild-square-brackets.txt" ,csharp-compilation-re-msbuild-warning 233 ,(list-repeat-once 234 '("Program.cs"))) 235 ("./test-files/xbuild-warning.txt" ,csharp-compilation-re-xbuild-warning 236 ,(list-repeat-once 237 '("/Users/jesseblack/Dropbox/barfapp/ConsoleApplication1/ClassLibrary1/Class1.cs" 238 "/Users/jesseblack/Dropbox/barfapp/ConsoleApplication1/ClassLibrary1/Folder/Class1.cs" 239 "/Users/jesseblack/Dropbox/barfapp/ConsoleApplication1/ConsoleApplication1/Program.cs" 240 "/Users/jesseblack/Dropbox/barfapp/ConsoleApplication1/ConsoleApplication1/Program.cs" 241 "/Users/jesseblack/Dropbox/barfapp/ConsoleApplication1/ConsoleApplication1/Program.cs"))) 242 ("./test-files/xbuild-error.txt" ,csharp-compilation-re-xbuild-error 243 ,(list-repeat-once 244 '("/Users/jesseblack/Dropbox/barfapp/ConsoleApplication1/ClassLibrary1/Folder/Class1.cs"))) 245 ("./test-files/devenv-error.txt" ,csharp-compilation-re-xbuild-error 246 ("c:\\working_chad\\dev_grep\\build_grep_database\\databaseconnection.cpp" 247 "c:\\working_chad\\dev_grep\\build_grep_database\\databaseconnection.cpp" 248 "c:\\working_chad\\dev_grep\\build_grep_database\\databaseconnection.cpp")) 249 ("./test-files/devenv-error.txt" ,csharp-compilation-re-xbuild-warning 250 ("c:\\working_chad\\dev_grep\\build_grep_database\\databaseconnection.cpp")) 251 ("./test-files/devenv-mixed-error.txt" ,csharp-compilation-re-xbuild-error 252 ("C:\\inservice\\SystemTesting\\OperateDeviceProxy\\OperateDevice_Proxy\\Program.cs" 253 "C:\\inservice\\SystemTesting\\OperateDeviceProxy\\OperateDevice_Proxy\\Program.cs" 254 "C:\\inservice\\SystemTesting\\OperateDeviceProxy\\OperateDevice_Proxy\\Program.cs" 255 "c:\\inservice\\systemtesting\\operationsproxy\\operationsproxy.cpp" 256 "c:\\inservice\\systemtesting\\operationsproxy\\operationsproxy.cpp" 257 "c:\\inservice\\systemtesting\\operationsproxy\\operationsproxy.cpp")) 258 259 ("./test-files/dotnet-nuget-error.txt" ,csharp-compilation-re-dotnet-error 260 ("/home/jostein/build/sample-app/sample-app.csproj")) 261 ("./test-files/dotnet-nuget-warning.txt" ,csharp-compilation-re-dotnet-warning 262 ("/home/jostein/build/sample-app/sample-app.csproj")) 263 ("./test-files/dotnet-test-fail-xunit.txt" ,csharp-compilation-re-dotnet-testfail 264 ("/home/jostein/build/sample-app/Module/Testee.cs")))) 265 266 (let* ((file-name (car test-case)) 267 (regexp (cadr test-case)) 268 (matched-file-names (cl-caddr test-case)) 269 (times (length matched-file-names)) 270 (find-file-hook '()) ;; avoid vc-mode file-hooks when opening! 271 (buffer (find-file-read-only file-name))) 272 ;; (message (concat "Testing compilation-log: " file-name)) 273 (dotimes (number times) 274 (let* ((expected (nth number matched-file-names))) 275 ;; (message (concat "- Expecting match: " expected)) 276 (re-search-forward regexp) 277 (should 278 (equal expected (match-string 1))))) 279 (kill-buffer buffer)))) 280 281 (defvar csharp-hook1 nil) 282 (defvar csharp-hook2 nil) 283 284 (ert-deftest activating-mode-triggers-all-hooks () 285 (add-hook 'csharp-mode-hook (lambda () (setq csharp-hook1 t))) 286 (add-hook 'prog-mode-hook (lambda () (setq csharp-hook2 t))) 287 288 (with-temp-buffer 289 (csharp-mode) 290 (should (equal t (and csharp-hook1 291 csharp-hook2))))) 292 293 (defvar c-mode-hook-run nil) 294 (ert-deftest avoid-runing-c-mode-hook () 295 (add-hook 'c-mode-hook (lambda () (setq c-mode-hook-run t))) 296 297 (with-temp-buffer 298 (csharp-mode) 299 (should-not c-mode-hook-run))) 300 301 (ert-deftest indentation-rules-should-be-as-specified-in-test-doc () 302 (let* ((buffer (find-file "test-files/indentation-tests.cs")) 303 (orig-content) 304 (indented-content)) 305 ;; double-ensure mode is active 306 (csharp-mode) 307 308 (setq orig-content (buffer-substring-no-properties (point-min) (point-max))) 309 (indent-region (point-min) (point-max)) 310 (setq indented-content (buffer-substring-no-properties (point-min) (point-max))) 311 312 (should (equal orig-content indented-content)))) 313 314 (ert-deftest region-directive-comment-movement () 315 (find-file "test-files/region-fontification.cs") 316 (csharp-mode) 317 (goto-char (point-min)) 318 (search-forward "#region ") 319 (forward-word 1) 320 (forward-word -1) 321 (should (looking-at "fontifies"))) 322 323 ;; (ert-deftest fontification-of-regions () 324 ;; (require 'assess) 325 ;; (require 'm-buffer) 326 ;; (find-file "test-files/region-fontification.cs") 327 ;; (csharp-mode) 328 ;; (let ((buf (current-buffer))) 329 ;; ;; look for 'a region comment' - should always be a comment 330 ;; (should (assess-face-at= buf 'csharp-mode (lambda (buf) (m-buffer-match buf "a region comment")) 'font-lock-comment-face)) 331 ;; ;; look for 'string' - should always be a type 332 ;; (should (assess-face-at= buf 'csharp-mode (lambda (buf) (m-buffer-match buf "string")) 'font-lock-type-face)))) 333 334 (ert-deftest activating-mode-doesnt-clobber-global-adaptive-fill-regexp () 335 (let ((before adaptive-fill-regexp)) 336 (with-temp-buffer 337 (csharp-mode)) 338 (should 339 (equal before adaptive-fill-regexp)))) 340 341 (ert-deftest activating-mode-style-defaults-to-csharp () 342 (with-temp-buffer 343 (csharp-mode) 344 (should 345 (equal "csharp" c-indentation-style))) 346 347 (let ((c-default-style "csharp")) 348 (with-temp-buffer 349 (csharp-mode) 350 (should 351 (equal "csharp" c-indentation-style)))) 352 353 (let ((c-default-style '((csharp-mode . "csharp") 354 (java-mode . "java")))) 355 (with-temp-buffer 356 (csharp-mode) 357 (should 358 (equal "csharp" c-indentation-style))))) 359 360 (ert-deftest inside-bracelist-test () 361 (with-temp-buffer 362 (csharp-mode) 363 (insert "public class A { public void F() {") 364 (call-interactively #'newline))) 365 366 ;;(ert-run-tests-interactively t) 367 ;; (local-set-key (kbd "<f6>") '(lambda () 368 ;; (interactive) 369 ;; (ert-run-tests-interactively t)))