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