From 6017737861df5f3799ec2538e5fb62fe378a309e Mon Sep 17 00:00:00 2001 From: Neil Date: Fri, 31 Jan 2025 12:36:49 +1100 Subject: Add default basic constructor and operator!= to SelectionPosition to ease use. Use default member initializer, constexpr for constructors and equality operators and <, [[nodiscard]] for comparison operators. Add simple unit tests for Selection. Not trying to be exhaustive here, just start the process of adding tests. --- test/unit/UnitTester.vcxproj | 1 + test/unit/makefile | 1 + test/unit/test.mak | 1 + test/unit/testSelection.cxx | 151 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 test/unit/testSelection.cxx (limited to 'test') diff --git a/test/unit/UnitTester.vcxproj b/test/unit/UnitTester.vcxproj index fdf567cff..87688523b 100644 --- a/test/unit/UnitTester.vcxproj +++ b/test/unit/UnitTester.vcxproj @@ -165,6 +165,7 @@ + diff --git a/test/unit/makefile b/test/unit/makefile index 866727505..695551fc9 100644 --- a/test/unit/makefile +++ b/test/unit/makefile @@ -68,6 +68,7 @@ Geometry.o \ PerLine.o \ RESearch.o \ RunStyles.o \ +Selection.o \ UndoHistory.o \ UniConversion.o \ UniqueString.o diff --git a/test/unit/test.mak b/test/unit/test.mak index e4a448f8c..15d9eba43 100644 --- a/test/unit/test.mak +++ b/test/unit/test.mak @@ -25,6 +25,7 @@ TESTEDSRC=\ ../../src/PerLine.cxx \ ../../src/RESearch.cxx \ ../../src/RunStyles.cxx \ + ../../src/Selection.cxx \ ../../src/UndoHistory.cxx \ ../../src/UniConversion.cxx \ ../../src/UniqueString.cxx diff --git a/test/unit/testSelection.cxx b/test/unit/testSelection.cxx new file mode 100644 index 000000000..8c27b42e8 --- /dev/null +++ b/test/unit/testSelection.cxx @@ -0,0 +1,151 @@ +/** @file testSelection.cxx + ** Unit Tests for Scintilla internal data structures + **/ + +#include + +#include +#include +#include + +#include "Debugging.h" + +#include "Position.h" +#include "Selection.h" + +#include "catch.hpp" + +using namespace Scintilla; +using namespace Scintilla::Internal; + +// Test Selection. + +namespace { + +constexpr SelectionPosition invalid; +constexpr SelectionPosition zero(0); +constexpr SelectionRange rangeInvalid; +constexpr SelectionRange rangeZero(0); + +} + +TEST_CASE("SelectionPosition") { + + SECTION("SelectionPosition") { + SelectionPosition sel; + REQUIRE(sel.Position() == Sci::invalidPosition); + REQUIRE(sel.VirtualSpace() == 0); + REQUIRE(!sel.IsValid()); + REQUIRE(sel.VirtualSpace() == 0); + + REQUIRE(sel == invalid); + REQUIRE(sel != zero); + sel.Reset(); + REQUIRE(sel != invalid); + REQUIRE(sel == zero); + } + + SECTION("Comparison") { + constexpr SelectionPosition sel(2,3); + REQUIRE(sel > invalid); + REQUIRE(sel > zero); + REQUIRE(sel >= zero); + REQUIRE(zero < sel); + REQUIRE(zero <= sel); + + SelectionPosition virtuous(0, 4); + REQUIRE(virtuous > zero); + REQUIRE(virtuous >= zero); + REQUIRE(zero < virtuous); + REQUIRE(zero <= virtuous); + + REQUIRE(virtuous.Position() == 0); + REQUIRE(virtuous.VirtualSpace() == 4); + + virtuous.SetPosition(1); // Also resets virtualSpace + REQUIRE(virtuous.Position() == 1); + REQUIRE(virtuous.VirtualSpace() == 0); + virtuous.SetVirtualSpace(3); // Does not reset position + REQUIRE(virtuous.Position() == 1); + REQUIRE(virtuous.VirtualSpace() == 3); + } + + SECTION("Add") { + SelectionPosition sel(2,3); + sel.Add(1); + REQUIRE(sel.Position() == 3); + REQUIRE(sel.VirtualSpace() == 3); + sel.AddVirtualSpace(2); + REQUIRE(sel.Position() == 3); + REQUIRE(sel.VirtualSpace() == 5); + } + + SECTION("MoveForInsertDelete") { + // There are multiple details implemented in MoveForInsertDelete that are supposed to + // move selections in a way that appears to be natural to a user. + + SelectionPosition sel(2,3); + sel.MoveForInsertDelete(true, 0,1, false); + REQUIRE(sel == SelectionPosition(3,3)); + + // Converts a virtual space to real space + sel.MoveForInsertDelete(true, 3,1, false); + REQUIRE(sel == SelectionPosition(4,2)); + + // Deletion at position clears virtual space + sel.MoveForInsertDelete(false, 4,1, false); + REQUIRE(sel == SelectionPosition(4,0)); + + sel.MoveForInsertDelete(false, 3,1, false); + REQUIRE(sel == SelectionPosition(3,0)); + + // Insert at position with and without move for equal + sel.MoveForInsertDelete(true, 3, 1, false); + REQUIRE(sel == SelectionPosition(3, 0)); + sel.MoveForInsertDelete(true, 3, 1, true); + REQUIRE(sel == SelectionPosition(4, 0)); + + // Deletion over the position moves to start of deletion + sel.MoveForInsertDelete(false, 2, 5, false); + REQUIRE(sel == SelectionPosition(2, 0)); + } + +} + +TEST_CASE("SelectionSegment") { + + SECTION("SelectionSegment") { + SelectionSegment ss; + REQUIRE(ss.start == invalid); + REQUIRE(ss.end == invalid); + } + +} + +TEST_CASE("SelectionRange") { + + SECTION("SelectionRange") { + SelectionRange sr; + REQUIRE(sr.anchor == invalid); + REQUIRE(sr.caret == invalid); + } + +} + +TEST_CASE("Selection") { + + SECTION("Selection") { + Selection sel; + + REQUIRE(sel.selType == Selection::SelTypes::stream); + REQUIRE(!sel.IsRectangular()); + REQUIRE(sel.Count() == 1); + REQUIRE(sel.Main() == 0); + + REQUIRE(sel.Range(0) == rangeZero); + REQUIRE(sel.RangeMain() == rangeZero); + REQUIRE(sel.Rectangular() == rangeInvalid); + REQUIRE(sel.Empty()); + } + +} -- cgit v1.2.3