aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/simpleTests.py6
-rw-r--r--test/unit/testDocument.cxx97
2 files changed, 103 insertions, 0 deletions
diff --git a/test/simpleTests.py b/test/simpleTests.py
index 0a14a4bdb..4205c7b3a 100644
--- a/test/simpleTests.py
+++ b/test/simpleTests.py
@@ -371,6 +371,12 @@ class TestSimple(unittest.TestCase):
self.assertEqual(self.ed.Contents(), b"x" + lineEnds[lineEndType] + b"y")
self.assertEqual(self.ed.LineLength(0), 1 + len(lineEnds[lineEndType]))
+ def testLineEndConversionLengthening(self):
+ # Bug #2501
+ self.ed.AddText(4, b"x\ny\n")
+ self.ed.ConvertEOLs(self.ed.SC_EOL_CRLF)
+ self.assertEqual(self.ed.Contents(), b"x\r\ny\r\n")
+
# Several tests for unicode line ends U+2028 and U+2029
@unittest.skipUnless(unicodeLineEndsAvailable, "can not test Unicode line ends")
diff --git a/test/unit/testDocument.cxx b/test/unit/testDocument.cxx
index fb8448da4..9811a215c 100644
--- a/test/unit/testDocument.cxx
+++ b/test/unit/testDocument.cxx
@@ -157,8 +157,30 @@ struct DocPlus {
document.GetCharRange(contents.data(), 0, length);
return contents;
}
+
+ [[nodiscard]] std::string Styles() const {
+ const Sci::Position length = document.Length();
+ std::string contents(length, 0);
+ document.GetStyleRange(reinterpret_cast<unsigned char *>(contents.data()), 0, length);
+ return contents;
+ }
+};
+
+namespace {
+
+// Provide an empty watcher to avoid filling in all the virtuals in simple watchers.
+struct EmptyWatcher : public DocWatcher {
+ void NotifyModifyAttempt(Document *, void *) override {};
+ void NotifySavePoint(Document *, void *, bool) override {};
+ void NotifyModified(Document *, DocModification, void *) override {};
+ void NotifyDeleted(Document *, void *) noexcept override {};
+ void NotifyStyleNeeded(Document *, void *, Sci::Position) override {};
+ void NotifyErrorOccurred(Document *, void *, Scintilla::Status) override {};
+ void NotifyGroupCompleted(Document *, void *) noexcept override {};
};
+}
+
void TimeTrace(std::string_view sv, const Catch::Timer &tikka) {
std::cout << sv << std::setw(5) << tikka.getElapsedMilliseconds() << " milliseconds" << std::endl;
}
@@ -185,6 +207,81 @@ TEST_CASE("Document") {
REQUIRE(!doc.document.CanRedo());
}
+ SECTION("Style") {
+ // Check that styling calls SetStyles and SetStyleFor modify the correct bytes and
+ // produce a minimal span in the notification.
+ // Also checks the notification mechanism.
+ struct ModificationWatcher : public EmptyWatcher {
+ Sci::Position modPos = -1;
+ Sci::Position modLength = -1;
+ void NotifyModified(Document *, DocModification mh, void *) noexcept final {
+ modPos = mh.position;
+ modLength = mh.length;
+ }
+ void Clear() noexcept {
+ modPos = -1;
+ modLength = -1;
+ }
+ };
+ DocPlus doc(sText, 0);
+ // Length of sText is 9
+ REQUIRE(doc.Styles() == std::string(9, 0));
+ ModificationWatcher mw;
+ doc.document.AddWatcher(&mw, nullptr);
+ doc.document.StartStyling(1);
+ doc.document.SetStyles(5, "\0abc\0");
+ REQUIRE(doc.Styles() == std::string("\0\0abc\0\0\0\0", 9));
+ // The NULs are not changed so are not included in the modification range
+ REQUIRE(mw.modPos == 2);
+ REQUIRE(mw.modLength == 3);
+
+ // No change so no notification so no update
+ mw.Clear();
+ doc.document.StartStyling(1);
+ doc.document.SetStyles(5, "\0abc\0");
+ REQUIRE(mw.modPos == -1);
+ REQUIRE(mw.modLength == -1);
+
+ // Just change one byte
+ doc.document.StartStyling(1);
+ doc.document.SetStyles(5, "\0bbc\0");
+ REQUIRE(mw.modPos == 2);
+ REQUIRE(mw.modLength == 1);
+ REQUIRE(doc.Styles() == std::string("\0\0bbc\0\0\0\0", 9));
+
+ // Move the gap
+ doc.MoveGap(1);
+ doc.document.StartStyling(1);
+ doc.document.SetStyles(5, "\0cbc\0");
+ REQUIRE(mw.modPos == 2);
+ REQUIRE(mw.modLength == 1);
+ REQUIRE(doc.Styles() == std::string("\0\0cbc\0\0\0\0", 9));
+
+ doc.MoveGap(2);
+ doc.document.StartStyling(1);
+ doc.document.SetStyles(5, "\0dcc\0");
+ REQUIRE(mw.modPos == 2);
+ REQUIRE(mw.modLength == 2);
+ REQUIRE(doc.Styles() == std::string("\0\0dcc\0\0\0\0", 9));
+
+ // Test SetStyleFor
+
+ doc.MoveGap(3);
+ doc.document.StartStyling(3);
+ doc.document.SetStyleFor(1, 0); // After gap
+ REQUIRE(mw.modPos == 3);
+ REQUIRE(mw.modLength == 1);
+ REQUIRE(doc.Styles() == std::string("\0\0d\0c\0\0\0\0", 9));
+
+ doc.document.StartStyling(2);
+ doc.document.SetStyleFor(3, 0); // Over gap
+ REQUIRE(mw.modPos == 2);
+ REQUIRE(mw.modLength == 3);
+ REQUIRE(doc.Styles() == std::string("\0\0\0\0\0\0\0\0\0", 9));
+
+ doc.document.RemoveWatcher(&mw, nullptr);
+ }
+
// Search ranges are from first argument to just before second argument
// Arguments are expected to be at character boundaries and will be tweaked if
// part way through a character.