1 /* 2 __ 3 / _| 4 __ _ _ _ _ __ ___ _ __ __ _ | |_ ___ ___ ___ 5 / _` | | | | '__/ _ \| '__/ _` | | _/ _ \/ __/ __| 6 | (_| | |_| | | | (_) | | | (_| | | || (_) \__ \__ \ 7 \__,_|\__,_|_| \___/|_| \__,_| |_| \___/|___/___/ 8 9 Copyright (C) 2018-2020 Aurora Free Open Source Software. 10 Copyright (C) 2018-2020 Luís Ferreira <luis@aurorafoss.org> 11 12 This file is part of the Aurora Free Open Source Software. This 13 organization promote free and open source software that you can 14 redistribute and/or modify under the terms of the GNU Lesser General 15 Public License Version 3 as published by the Free Software Foundation or 16 (at your option) any later version approved by the Aurora Free Open Source 17 Software Organization. The license is available in the package root path 18 as 'LICENSE' file. Please review the following information to ensure the 19 GNU Lesser General Public License version 3 requirements will be met: 20 https://www.gnu.org/licenses/lgpl.html . 21 22 Alternatively, this file may be used under the terms of the GNU General 23 Public License version 3 or later as published by the Free Software 24 Foundation. Please review the following information to ensure the GNU 25 General Public License requirements will be met: 26 http://www.gnu.org/licenses/gpl-3.0.html. 27 28 NOTE: All products, services or anything associated to trademarks and 29 service marks used or referenced on this file are the property of their 30 respective companies/owners or its subsidiaries. Other names and brands 31 may be claimed as the property of others. 32 33 For more info about intellectual property visit: aurorafoss.org or 34 directly send an email to: contact (at) aurorafoss.org . 35 */ 36 37 module liblstparse.tests.parser; 38 39 import aurorafw.unit.assertion; 40 41 import core.exception; 42 43 import liblstparse.parser; 44 45 import std.array; 46 import std.exception; 47 import std.file; 48 import std.typecons; 49 import std.ascii; 50 51 @safe @("No coverage") 52 unittest { 53 LSTFile file = LSTFile(DirEntry("tests/res/nocov.lst")); 54 assertEquals("nocov.d", file.filename); 55 assertEquals(0, file.totalCoverage); 56 assertEquals("@safe unittest {", file[3].content); 57 assertTrue(file.linesCovered.empty); 58 // check a non coverable file 59 assertEquals( 60 LSTFile.Line(Nullable!(uint).init, "module tests.res.nocov;"), 61 file.lines[0]); 62 } 63 64 @safe @("Zero coverage") 65 unittest { 66 LSTFile file = LSTFile(DirEntry("tests/res/zerocov.lst")); 67 assertEquals("zerocov.d", file.filename); 68 assertEquals(0, file.totalCoverage); 69 assertFalse(file.linesCovered.empty); 70 assertEquals(0, file.linesCovered[4]); 71 } 72 73 @safe @("Convertion failures") 74 unittest { 75 auto overflow_file = ` 76 |@safe int foo(int t) { 77 81723948712938471923874918273498273941872394| return t * 2; 78 |} 79 covfile.d is 100% covered`[1 .. $]; 80 auto overflow2_file = ` 81 |@safe int foo(int t) { 82 1| return t * 2; 83 |} 84 covfile.d is 819723498712398471293% covered`[1 .. $]; 85 auto failconv_file = ` 86 |@safe int foo(int t) { 87 notaninteger| return t * 2; 88 |} 89 covfile.d is 100% covered`[1 .. $]; 90 auto failconv2_file = ` 91 |@safe int foo(int t) { 92 1| return t * 2; 93 |} 94 covfile.d is ups% covered`[1 .. $]; 95 96 import std.conv : ConvException, ConvOverflowException; 97 expectThrows!ConvOverflowException(LSTFile(overflow_file)); 98 expectThrows!ConvOverflowException(LSTFile(overflow2_file)); 99 expectThrows!ConvException(LSTFile(failconv_file)); 100 expectThrows!ConvException(LSTFile(failconv2_file)); 101 } 102 103 @safe @("Parsing failures") 104 unittest { 105 // minimum valid lst files 106 LSTFile("|\na.d has no code"); 107 LSTFile("1|int main(){return 0;}\nb.d is 100% covered"); 108 109 LSTFileParseException ex; 110 111 // invalid files 112 ex = expectThrows!LSTFileParseException(LSTFile("hey, I like turtles")); 113 assertEquals("Minimum number of lines is 2. Probably not parsing .lst file", ex.msg); 114 ex = expectThrows!LSTFileParseException(LSTFile("hey, I like turtles\n.")); 115 assertEquals("'|' separator not found. Probably not parsing .lst file", ex.msg); 116 ex = expectThrows!LSTFileParseException(LSTFile("|\n 100")); 117 assertEquals("The last line is not well formatted: missing '% covered'", ex.msg); 118 ex = expectThrows!LSTFileParseException( 119 LSTFile("1|int main(){return 0;}\nb.d iss 100% covered")); 120 assertEquals("The last line is not well formatted: missing ' is '", ex.msg); 121 } 122 123 @safe @("Merge coverage files") 124 unittest { 125 // NOTE: This files doesn't represent real coverage 126 // but should be totally valid LST files. 127 auto covfile1 = ` 128 |@safe int foo(int t) { 129 1| return t * 2; 130 |} 131 covfile.d is 100% covered`[1 .. $]; 132 auto covfile2 = ` 133 |@safe int foo(int t) { 134 2| return t * 2; 135 |} 136 covfile.d is 0% covered`[1 .. $]; 137 auto covfile3 = ` 138 |@safe int foo(int t) { 139 | return t * 2; 140 |} 141 covfile.d is 0% covered`[1 .. $]; 142 auto diffcovfile1 = ` 143 |@safe int foo(int t) { 144 0| return t * 2; 145 |} 146 diffcovfile.d is 0% covered`[1 .. $]; 147 auto diffcovfile2 = ` 148 |@safe int foobar(int t) { 149 0| return t * 2; 150 |} 151 diffcovfile.d is 0% covered`[1 .. $]; 152 auto diffcovfile3 = ` 153 |@safe int foobar(int t) { 154 0| return t * 2; 155 | 156 |} 157 diffcovfile.d is 0% covered`[1 .. $]; 158 159 LSTFile file1 = LSTFile(covfile1); 160 LSTFile file2 = LSTFile(covfile2); 161 LSTFile file3 = LSTFile(covfile3); 162 LSTFile diff_file1 = LSTFile(diffcovfile1); 163 LSTFile diff_file2 = LSTFile(diffcovfile2); 164 LSTFile diff_file3 = LSTFile(diffcovfile3); 165 166 // successfully merge a file 167 LSTFile merged = file1.merge(file2); 168 assertEquals("covfile.d", merged.filename); 169 assertEquals(100, merged.totalCoverage); 170 assertFalse(merged.linesCovered.empty); 171 assertEquals(3, merged.linesCovered[1]); 172 173 // merge coverable with non coverable lines 174 merged = file2.merge(file3); 175 assertEquals(2, merged.linesCovered[1]); 176 177 // cover usage of divide by 0 check 178 merged = file3.merge(file3); 179 assertEquals(0, merged.totalCoverage); 180 181 182 LSTFileMergeException ex; 183 184 // different filename 185 ex = expectThrows!LSTFileMergeException(LSTFile.merge(file1, diff_file1)); 186 assertEquals("should merge with the same file", ex.msg); 187 // line length mismatch, not the same content 188 ex = expectThrows!LSTFileMergeException(LSTFile.merge(diff_file1, diff_file3)); 189 assertEquals("lines length mismatch", ex.msg); 190 // file content mismatch, not the same content 191 ex = expectThrows!LSTFileMergeException(LSTFile.merge(diff_file1, diff_file2)); 192 assertEquals("content mismatch at line 1", ex.msg); 193 } 194 195 @system @("Range violation") 196 unittest { 197 LSTFile file = LSTFile.fromFilePath("tests/res/zerocov.lst"); 198 assertNotThrown!RangeError(file.linesCovered[4]); 199 assertThrown!RangeError(file.linesCovered[3]); 200 } 201 202 @safe @("File doesn't exist") 203 unittest { 204 expectThrows!FileException(LSTFile(DirEntry("tests/res/file_not_found.lst"))); 205 } 206 207 @safe @("File with coverage") 208 unittest { 209 import std.file : readText; 210 auto txt = readText("tests/res/tocov.lst"); 211 LSTFile file = LSTFile(txt); 212 assertEquals("tocov.d", file.filename); 213 assertEquals(100, file.totalCoverage); 214 assertFalse(file.linesCovered.empty); 215 assertEquals(1, file.linesCovered[4]); 216 assertEquals(file.linesCovered[4], file[4].coverage); 217 assertEquals(1, file.linesCovered[9]); 218 assertEquals(file.linesCovered[9], file[9].coverage); 219 220 // check a coverable file 221 assertEquals( 222 LSTFile.Line(nullable!uint(1), " return t * 2;"), 223 file.lines[4] 224 ); 225 } 226 227 @safe @("Generate LST") 228 unittest 229 { 230 auto covfile1 = (` 231 |@safe int foo(int t) { 232 1| return t * 2; 233 |} 234 covfile.d is 100% covered` ~ newline)[1 .. $]; 235 auto covfile2 = (` 236 |@safe int foo(int t) { 237 0000000| return t * 2; 238 |} 239 covfile.d is 0% covered` ~ newline)[1 .. $]; 240 auto covfile3 = (` 241 |@safe int foo(int t) { 242 | return t * 2; 243 |} 244 covfile.d has no code` ~ newline)[1 .. $]; 245 246 auto file1 = LSTFile(covfile1); 247 auto file2 = LSTFile(covfile2); 248 auto file3 = LSTFile(covfile3); 249 auto emptyFile = LSTFile(""); 250 251 // should generate the exact same file 252 assertEquals(covfile1, file1.generateLST); 253 assertEquals(covfile2, file2.generateLST); 254 assertEquals(covfile3, file3.generateLST); 255 assertEquals("", emptyFile.generateLST); 256 }