1 // Unit Tests for Scintilla internal data structures 2 3 #include <cstddef> 4 #include <cstring> 5 #include <stdexcept> 6 #include <string_view> 7 #include <vector> 8 #include <forward_list> 9 #include <algorithm> 10 #include <memory> 11 12 #include "Platform.h" 13 14 #include "Scintilla.h" 15 #include "Position.h" 16 #include "SplitVector.h" 17 #include "Partitioning.h" 18 #include "RunStyles.h" 19 #include "CellBuffer.h" 20 #include "PerLine.h" 21 22 #include "catch.hpp" 23 24 using namespace Scintilla; 25 26 // Test MarkerHandleSet. 27 28 TEST_CASE("MarkerHandleSet") { 29 30 MarkerHandleSet mhs; 31 32 SECTION("Initial") { 33 // Initial State 34 REQUIRE(mhs.Empty()); 35 REQUIRE(0 == mhs.MarkValue()); 36 REQUIRE(!mhs.Contains(1)); 37 } 38 39 SECTION("InsertDelete") { 40 // Test knows that InsertHandle inserts at front (0) 41 // Insert 1 with handle 100 42 REQUIRE(mhs.InsertHandle(100,1)); 43 REQUIRE(!mhs.Empty()); 44 REQUIRE(2 == mhs.MarkValue()); 45 REQUIRE(mhs.Contains(100)); 46 47 // Insert 2 with handle 200 48 REQUIRE(mhs.InsertHandle(200,2)); 49 REQUIRE(!mhs.Empty()); 50 REQUIRE(mhs.Contains(100)); 51 REQUIRE(mhs.Contains(200)); 52 REQUIRE(6 == mhs.MarkValue()); 53 54 const MarkerHandleNumber *mhn0 = mhs.GetMarkerHandleNumber(0); 55 REQUIRE(200 == mhn0->handle); 56 REQUIRE(2 == mhn0->number); 57 const MarkerHandleNumber *mhn1 = mhs.GetMarkerHandleNumber(1); 58 REQUIRE(100 == mhn1->handle); 59 REQUIRE(1 == mhn1->number); 60 const MarkerHandleNumber *mhn2 = mhs.GetMarkerHandleNumber(2); 61 REQUIRE(nullptr == mhn2); 62 63 // Remove first insertion 64 mhs.RemoveHandle(100); 65 REQUIRE(!mhs.Empty()); 66 REQUIRE(mhs.Contains(200)); 67 REQUIRE(4 == mhs.MarkValue()); 68 69 // Remove remaining element 70 REQUIRE(mhs.RemoveNumber(2, true)); 71 REQUIRE(mhs.Empty()); 72 REQUIRE(!mhs.Contains(200)); 73 REQUIRE(0 == mhs.MarkValue()); 74 } 75 76 SECTION("Combine") { 77 mhs.InsertHandle(100, 1); 78 MarkerHandleSet mhsOther; 79 mhsOther.InsertHandle(200, 2); 80 mhs.CombineWith(&mhsOther); 81 REQUIRE(mhsOther.Empty()); 82 mhs.RemoveHandle(100); 83 mhs.RemoveHandle(200); 84 REQUIRE(mhs.Empty()); 85 } 86 } 87 88 TEST_CASE("LineMarkers") { 89 90 LineMarkers lm; 91 92 SECTION("Initial") { 93 // Initial State 94 REQUIRE(0 == lm.MarkValue(0)); 95 } 96 97 SECTION("AddDelete") { 98 // Test knows the way handles are allocated, starting from 1 99 lm.InsertLines(0, 5); 100 const int handle1 = lm.AddMark(0, 1, 5); 101 REQUIRE(1 == handle1); 102 REQUIRE(2 == lm.MarkValue(0)); 103 REQUIRE(1 == lm.HandleFromLine(0, 0)); 104 REQUIRE(1 == lm.NumberFromLine(0, 0)); 105 REQUIRE(-1 == lm.HandleFromLine(0, 1)); 106 REQUIRE(-1 == lm.NumberFromLine(0, 1)); 107 REQUIRE(0 == lm.LineFromHandle(handle1)); 108 109 REQUIRE(lm.DeleteMark(0, 1, true)); 110 REQUIRE(0 == lm.MarkValue(0)); 111 112 const int handle2 = lm.AddMark(0, 2, 5); 113 REQUIRE(2 == handle2); 114 REQUIRE(4 == lm.MarkValue(0)); 115 lm.DeleteMarkFromHandle(handle2); 116 REQUIRE(0 == lm.MarkValue(0)); 117 } 118 119 SECTION("MarkerNext") { 120 lm.AddMark(1, 1, 5); 121 lm.AddMark(2, 2, 5); 122 const Sci::Line line1 = lm.MarkerNext(0, 6); 123 REQUIRE(1 == line1); 124 const Sci::Line line2 = lm.MarkerNext(line1+1, 6); 125 REQUIRE(2 == line2); 126 const Sci::Line line3 = lm.MarkerNext(line2+1, 6); 127 REQUIRE(-1 == line3); 128 } 129 130 SECTION("MergeMarkers") { 131 lm.AddMark(1, 1, 5); 132 lm.AddMark(2, 2, 5); 133 lm.MergeMarkers(1); 134 REQUIRE(6 == lm.MarkValue(1)); 135 REQUIRE(0 == lm.MarkValue(2)); 136 } 137 138 SECTION("InsertRemoveLine") { 139 const int handle1 = lm.AddMark(1, 1, 5); 140 const int handle2 = lm.AddMark(2, 2, 5); 141 lm.InsertLine(2); 142 REQUIRE(0 == lm.MarkValue(0)); 143 REQUIRE(2 == lm.MarkValue(1)); 144 REQUIRE(0 == lm.MarkValue(2)); 145 REQUIRE(4 == lm.MarkValue(3)); 146 REQUIRE(0 == lm.MarkValue(4)); 147 lm.RemoveLine(2); 148 REQUIRE(0 == lm.MarkValue(0)); 149 REQUIRE(2 == lm.MarkValue(1)); 150 REQUIRE(4 == lm.MarkValue(2)); 151 REQUIRE(0 == lm.MarkValue(3)); 152 lm.InsertLines(2, 2); 153 REQUIRE(0 == lm.MarkValue(0)); 154 REQUIRE(2 == lm.MarkValue(1)); 155 REQUIRE(0 == lm.MarkValue(2)); 156 REQUIRE(0 == lm.MarkValue(3)); 157 REQUIRE(4 == lm.MarkValue(4)); 158 REQUIRE(0 == lm.MarkValue(5)); 159 REQUIRE(1 == lm.LineFromHandle(handle1)); 160 REQUIRE(4 == lm.LineFromHandle(handle2)); 161 } 162 } 163 164 TEST_CASE("LineLevels") { 165 166 LineLevels ll; 167 168 SECTION("Initial") { 169 // Initial State 170 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(0)); 171 } 172 173 SECTION("SetLevel") { 174 REQUIRE(SC_FOLDLEVELBASE == ll.SetLevel(1, 200, 5)); 175 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(0)); 176 REQUIRE(200 == ll.GetLevel(1)); 177 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(2)); 178 ll.ClearLevels(); 179 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(1)); 180 ll.ExpandLevels(5); 181 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(7)); 182 } 183 184 SECTION("InsertRemoveLine") { 185 ll.SetLevel(1, 1, 5); 186 ll.SetLevel(2, 2, 5); 187 ll.InsertLine(2); 188 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(0)); 189 REQUIRE(1 == ll.GetLevel(1)); 190 REQUIRE(2 == ll.GetLevel(2)); 191 REQUIRE(2 == ll.GetLevel(3)); 192 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(4)); 193 ll.RemoveLine(2); 194 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(0)); 195 REQUIRE(1 == ll.GetLevel(1)); 196 REQUIRE(2 == ll.GetLevel(2)); 197 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(3)); 198 ll.InsertLines(2, 2); 199 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(0)); 200 REQUIRE(1 == ll.GetLevel(1)); 201 REQUIRE(2 == ll.GetLevel(2)); 202 REQUIRE(2 == ll.GetLevel(3)); 203 REQUIRE(2 == ll.GetLevel(4)); 204 REQUIRE(SC_FOLDLEVELBASE == ll.GetLevel(5)); 205 } 206 } 207 208 TEST_CASE("LineState") { 209 210 LineState ls; 211 212 SECTION("Initial") { 213 // Initial State 214 REQUIRE(0 == ls.GetMaxLineState()); 215 REQUIRE(0 == ls.GetLineState(0)); 216 REQUIRE(1 == ls.GetMaxLineState()); 217 ls.Init(); 218 REQUIRE(0 == ls.GetMaxLineState()); 219 REQUIRE(0 == ls.GetLineState(0)); 220 } 221 222 SECTION("SetLineState") { 223 REQUIRE(0 == ls.SetLineState(1, 200)); 224 REQUIRE(0 == ls.GetLineState(0)); 225 REQUIRE(200 == ls.GetLineState(1)); 226 REQUIRE(0 == ls.GetLineState(2)); 227 REQUIRE(0 == ls.SetLineState(2, 400)); 228 REQUIRE(0 == ls.GetLineState(0)); 229 REQUIRE(200 == ls.GetLineState(1)); 230 REQUIRE(400 == ls.GetLineState(2)); 231 REQUIRE(0 == ls.GetLineState(3)); 232 // GetLineState(3) expands to 4 lines 233 REQUIRE(4 == ls.GetMaxLineState()); 234 ls.Init(); 235 REQUIRE(0 == ls.GetLineState(0)); 236 REQUIRE(1 == ls.GetMaxLineState()); 237 } 238 239 SECTION("InsertRemoveLine") { 240 REQUIRE(0 == ls.GetMaxLineState()); 241 ls.SetLineState(1, 1); 242 ls.SetLineState(2, 2); 243 REQUIRE(3 == ls.GetMaxLineState()); 244 ls.InsertLine(2); 245 REQUIRE(4 == ls.GetMaxLineState()); 246 REQUIRE(0 == ls.GetLineState(0)); 247 REQUIRE(1 == ls.GetLineState(1)); 248 REQUIRE(2 == ls.GetLineState(2)); 249 REQUIRE(2 == ls.GetLineState(3)); 250 REQUIRE(0 == ls.GetLineState(4)); 251 REQUIRE(5 == ls.GetMaxLineState()); 252 ls.RemoveLine(2); 253 REQUIRE(4 == ls.GetMaxLineState()); 254 REQUIRE(0 == ls.GetLineState(0)); 255 REQUIRE(1 == ls.GetLineState(1)); 256 REQUIRE(2 == ls.GetLineState(2)); 257 REQUIRE(0 == ls.GetLineState(3)); 258 ls.InsertLines(2, 2); 259 REQUIRE(6 == ls.GetMaxLineState()); 260 REQUIRE(0 == ls.GetLineState(0)); 261 REQUIRE(1 == ls.GetLineState(1)); 262 REQUIRE(2 == ls.GetLineState(2)); 263 REQUIRE(2 == ls.GetLineState(3)); 264 REQUIRE(2 == ls.GetLineState(4)); 265 REQUIRE(0 == ls.GetLineState(5)); 266 } 267 } 268 269 TEST_CASE("LineAnnotation") { 270 271 LineAnnotation la; 272 273 SECTION("Initial") { 274 // Initial State 275 REQUIRE(0 == la.Length(0)); 276 REQUIRE(0 == la.Lines(0)); 277 REQUIRE(0 == la.Style(0)); 278 REQUIRE(false == la.MultipleStyles(0)); 279 } 280 281 SECTION("SetText") { 282 la.SetText(0, "Text"); 283 REQUIRE(4 == la.Length(0)); 284 REQUIRE(1 == la.Lines(0)); 285 REQUIRE(memcmp(la.Text(0), "Text", 4) == 0); 286 REQUIRE(nullptr == la.Styles(0)); 287 REQUIRE(0 == la.Style(0)); 288 la.SetStyle(0, 9); 289 REQUIRE(9 == la.Style(0)); 290 291 la.SetText(0, "Ant\nBird\nCat"); 292 REQUIRE(3 == la.Lines(0)); 293 294 la.ClearAll(); 295 REQUIRE(nullptr == la.Text(0)); 296 } 297 298 SECTION("SetStyles") { 299 la.SetText(0, "Text"); 300 const unsigned char styles[] { 1,2,3,4 }; 301 la.SetStyles(0, styles); 302 REQUIRE(memcmp(la.Text(0), "Text", 4) == 0); 303 REQUIRE(memcmp(la.Styles(0), styles, 4) == 0); 304 REQUIRE(la.MultipleStyles(0)); 305 } 306 307 SECTION("InsertRemoveLine") { 308 la.SetText(0, "Ant"); 309 la.SetText(1, "Bird"); 310 REQUIRE(3 == la.Length(0)); 311 REQUIRE(4 == la.Length(1)); 312 REQUIRE(1 == la.Lines(0)); 313 la.InsertLine(1); 314 REQUIRE(3 == la.Length(0)); 315 REQUIRE(0 == la.Length(1)); 316 REQUIRE(4 == la.Length(2)); 317 la.RemoveLine(2); 318 REQUIRE(3 == la.Length(0)); 319 REQUIRE(4 == la.Length(1)); 320 la.InsertLines(1, 2); 321 REQUIRE(3 == la.Length(0)); 322 REQUIRE(0 == la.Length(1)); 323 REQUIRE(0 == la.Length(2)); 324 REQUIRE(4 == la.Length(3)); 325 } 326 } 327 328 TEST_CASE("LineTabstops") { 329 330 LineTabstops lt; 331 332 SECTION("Initial") { 333 // Initial State 334 REQUIRE(0 == lt.GetNextTabstop(0, 0)); 335 } 336 337 SECTION("AddClearTabstops") { 338 lt.AddTabstop(0, 100); 339 REQUIRE(100 == lt.GetNextTabstop(0, 0)); 340 REQUIRE(0 == lt.GetNextTabstop(0, 100)); 341 lt.ClearTabstops(0); 342 REQUIRE(0 == lt.GetNextTabstop(0, 0)); 343 } 344 345 SECTION("InsertRemoveLine") { 346 lt.AddTabstop(0, 100); 347 lt.AddTabstop(1, 200); 348 lt.InsertLine(1); 349 REQUIRE(100 == lt.GetNextTabstop(0, 0)); 350 REQUIRE(0 == lt.GetNextTabstop(1, 0)); 351 REQUIRE(200 == lt.GetNextTabstop(2, 0)); 352 lt.RemoveLine(1); 353 REQUIRE(100 == lt.GetNextTabstop(0, 0)); 354 REQUIRE(200 == lt.GetNextTabstop(1, 0)); 355 lt.InsertLines(1, 2); 356 REQUIRE(100 == lt.GetNextTabstop(0, 0)); 357 REQUIRE(0 == lt.GetNextTabstop(1, 0)); 358 REQUIRE(0 == lt.GetNextTabstop(2, 0)); 359 REQUIRE(200 == lt.GetNextTabstop(3, 0)); 360 lt.Init(); 361 REQUIRE(0 == lt.GetNextTabstop(0, 0)); 362 } 363 } 364