using System; using Glass.Typesetting; using UnitTestSharp; namespace Glass.UnitTests.Typesetting { public class CodePointsTests : TestFixture { public static readonly string Pair = char.ConvertFromUtf32(0x20BB7); // Combining acute accent, a mark in the Basic Multilingual Plane. public static readonly string Acute = ((char)0x301).ToString(); // Musical symbol combining stem, a mark that needs a surrogate pair. public static readonly string AstralMark = char.ConvertFromUtf32(0x1D165); public static readonly string ZeroWidthJoiner = ((char)0x200D).ToString(); public class NextEndTests : TestFixture { public void Character_AdvancesOne() { CheckEqual(1, CodePoints.NextEnd("abc", 0)); } public void Pair_AdvancesTwo() { CheckEqual(3, CodePoints.NextEnd("a" + Pair + "b", 1)); } public void FromInsideAPair_AdvancesOne() { CheckEqual(3, CodePoints.NextEnd("a" + Pair + "b", 2)); } public void UnpairedHighSurrogate_AdvancesOne() { CheckEqual(2, CodePoints.NextEnd("a" + (char)0xD842, 1)); CheckEqual(2, CodePoints.NextEnd("a" + (char)0xD842 + "b", 1)); } public void AtTheEnd_StaysThere() { CheckEqual(3, CodePoints.NextEnd("abc", 3)); } public void StepsOnlyOverTheCodePointEvenWhenMarksFollow() { CheckEqual(1, CodePoints.NextEnd("e" + Acute, 0)); } public void NullText_Throws() { CheckThrow(typeof(ArgumentNullException)); CodePoints.NextEnd(null, 0); } public void NegativePosition_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); CodePoints.NextEnd("abc", -1); } public void PositionPastTheEnd_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); CodePoints.NextEnd("abc", 4); } } public class PreviousStartTests : TestFixture { public void Character_StepsBackOne() { CheckEqual(2, CodePoints.PreviousStart("abc", 3)); } public void Pair_StepsBackTwo() { CheckEqual(1, CodePoints.PreviousStart("a" + Pair + "b", 3)); } public void FromInsideAPair_StepsBackOne() { CheckEqual(1, CodePoints.PreviousStart("a" + Pair + "b", 2)); } public void UnpairedLowSurrogate_StepsBackOne() { CheckEqual(1, CodePoints.PreviousStart("a" + (char)0xDFB7, 2)); } public void AtTheStart_StaysThere() { CheckEqual(0, CodePoints.PreviousStart("abc", 0)); } public void NullText_Throws() { CheckThrow(typeof(ArgumentNullException)); CodePoints.PreviousStart(null, 0); } public void NegativePosition_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); CodePoints.PreviousStart("abc", -1); } public void PositionPastTheEnd_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); CodePoints.PreviousStart("abc", 4); } } public class JoinsPreviousTests : TestFixture { public void CombiningMark_Joins() { Check(CodePoints.JoinsPrevious("e" + Acute, 1)); } public void MarkThatNeedsAPair_Joins() { Check(CodePoints.JoinsPrevious("a" + AstralMark, 1)); } public void ZeroWidthJoiner_Joins() { Check(CodePoints.JoinsPrevious("a" + ZeroWidthJoiner + "b", 1)); } public void LineFeedAfterACarriageReturn_Joins() { Check(CodePoints.JoinsPrevious("a\r\nb", 2)); } public void LineFeedAfterAnythingElse_DoesNot() { CheckFalse(CodePoints.JoinsPrevious("a\n\nb", 2)); CheckFalse(CodePoints.JoinsPrevious("a\n", 1)); } public void CarriageReturnBeforeALineFeed_DoesNot() { CheckFalse(CodePoints.JoinsPrevious("a\r\nb", 1)); } public void MarkRightAfterAHardBreak_DoesNot() { CheckFalse(CodePoints.JoinsPrevious("a\n" + Acute, 2)); CheckFalse(CodePoints.JoinsPrevious("a\r\n" + Acute, 3)); } public void OrdinaryLetter_DoesNot() { CheckFalse(CodePoints.JoinsPrevious("ab", 1)); } public void LetterThatNeedsAPair_DoesNot() { CheckFalse(CodePoints.JoinsPrevious("a" + Pair, 1)); } public void UnpairedSurrogate_DoesNot() { CheckFalse(CodePoints.JoinsPrevious("a" + (char)0xD842, 1)); } public void AtTheEnd_DoesNot() { CheckFalse(CodePoints.JoinsPrevious("e" + Acute, 2)); } public void MarkAtTheStart_DoesNot() { CheckFalse(CodePoints.JoinsPrevious(Acute + "e", 0)); } public void MarkAfterASpace_Joins() { Check(CodePoints.JoinsPrevious(" " + Acute, 1)); } public void NullText_Throws() { CheckThrow(typeof(ArgumentNullException)); CodePoints.JoinsPrevious(null, 0); } public void PositionPastTheEnd_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); CodePoints.JoinsPrevious("abc", 4); } public void NegativePosition_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); CodePoints.JoinsPrevious("abc", -1); } } public class NextClusterEndTests : TestFixture { public void PlainCharacter_AdvancesOne() { CheckEqual(1, CodePoints.NextClusterEnd("abc", 0)); } public void Pair_AdvancesTwo() { CheckEqual(3, CodePoints.NextClusterEnd("a" + Pair + "b", 1)); } public void IncludesTheMarksThatFollow() { CheckEqual(3, CodePoints.NextClusterEnd("e" + Acute + Acute + "x", 0)); } public void IncludesAMarkThatNeedsAPair() { CheckEqual(3, CodePoints.NextClusterEnd("a" + AstralMark + "b", 0)); } public void IncludesAZeroWidthJoiner() { CheckEqual(2, CodePoints.NextClusterEnd("a" + ZeroWidthJoiner + "b", 0)); } public void StopsBeforeTheNextLetter() { CheckEqual(2, CodePoints.NextClusterEnd("e" + Acute + "x", 0)); } public void AtTheEnd_StaysThere() { CheckEqual(2, CodePoints.NextClusterEnd("e" + Acute, 2)); } public void CarriageReturnLineFeed_IsOneStep() { CheckEqual(3, CodePoints.NextClusterEnd("a\r\nb", 1)); } public void LoneCarriageReturnOrLineFeed_IsOneStep() { CheckEqual(2, CodePoints.NextClusterEnd("a\rb", 1)); CheckEqual(2, CodePoints.NextClusterEnd("a\nb", 1)); } public void MarkAfterAHardBreak_IsNotPartOfIt() { CheckEqual(1, CodePoints.NextClusterEnd("\n" + Acute, 0)); } public void StartingOnAMark_TakesTheMarksAfterItToo() { CheckEqual(2, CodePoints.NextClusterEnd(Acute + Acute + "x", 0)); } } public class PreviousClusterStartTests : TestFixture { public void PlainCharacter_StepsBackOne() { CheckEqual(2, CodePoints.PreviousClusterStart("abc", 3)); } public void Pair_StepsBackTwo() { CheckEqual(1, CodePoints.PreviousClusterStart("a" + Pair + "b", 3)); } public void GoesBackBeforeTheMarks() { CheckEqual(1, CodePoints.PreviousClusterStart("xe" + Acute + Acute, 4)); } public void GoesBackBeforeAMarkThatNeedsAPair() { CheckEqual(1, CodePoints.PreviousClusterStart("xa" + AstralMark, 4)); } public void GoesBackBeforeAZeroWidthJoiner() { CheckEqual(0, CodePoints.PreviousClusterStart("a" + ZeroWidthJoiner, 2)); } public void AtTheStart_StaysThere() { CheckEqual(0, CodePoints.PreviousClusterStart("abc", 0)); } public void CarriageReturnLineFeed_IsOneStep() { CheckEqual(1, CodePoints.PreviousClusterStart("a\r\nb", 3)); } public void MarkAfterAHardBreak_IsNotPartOfIt() { CheckEqual(2, CodePoints.PreviousClusterStart("a\n" + Acute, 3)); } public void MarksAtTheStartOfTheText_AreOneStep() { CheckEqual(0, CodePoints.PreviousClusterStart(Acute + Acute, 2)); } } } }