boundary.text.tests.cpp

1
2
3
4
5
6
7
8
#include <planet/text/boundary.hpp>

#include <felspar/test.hpp>

#include <string>


namespace {

The multibyte cases, spelled out so the expected offsets below are checkable by eye: é is two bytes, three and 🚀 four.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    constexpr std::string_view e_acute{"é"};
    constexpr std::string_view arrow{"→"};
    constexpr std::string_view rocket{"🚀"};


    auto const suite = felspar::testsuite("text.boundary");


    auto const ascii = suite.test("ascii", [](auto check) {
        constexpr std::string_view text{"abc"};

        check(planet::text::previous_boundary(text, 3)) == 2u;
        check(planet::text::previous_boundary(text, 2)) == 1u;
        check(planet::text::previous_boundary(text, 1)) == 0u;

        check(planet::text::next_boundary(text, 0)) == 1u;
        check(planet::text::next_boundary(text, 1)) == 2u;
        check(planet::text::next_boundary(text, 2)) == 3u;
    });


    auto const multibyte = suite.test(
            "multibyte",
            [](auto check) {
                check(e_acute.size()) == 2u;

                check(planet::text::previous_boundary(e_acute, e_acute.size()))
                        == 0u;
                check(planet::text::next_boundary(e_acute, 0))
                        == e_acute.size();
            },
            [](auto check) {
                check(arrow.size()) == 3u;

                check(planet::text::previous_boundary(arrow, arrow.size()))
                        == 0u;
                check(planet::text::next_boundary(arrow, 0)) == arrow.size();
            },
            [](auto check) {
                check(rocket.size()) == 4u;

                check(planet::text::previous_boundary(rocket, rocket.size()))
                        == 0u;
                check(planet::text::next_boundary(rocket, 0)) == rocket.size();
            },
            [](auto check) {

Mixed with ASCII either side, so a step lands on the character boundary rather than on the end of the string.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
                std::string const text = "a" + std::string{arrow} + "b";

                check(planet::text::previous_boundary(text, text.size())) == 4u;
                check(planet::text::previous_boundary(text, 4)) == 1u;
                check(planet::text::previous_boundary(text, 1)) == 0u;

                check(planet::text::next_boundary(text, 0)) == 1u;
                check(planet::text::next_boundary(text, 1)) == 4u;
                check(planet::text::next_boundary(text, 4)) == 5u;
            });


    auto const ends = suite.test("ends", [](auto check) {
        constexpr std::string_view text{"abc"};

Neither function runs off the end of the string it was given

81
82
        check(planet::text::previous_boundary(text, 0)) == 0u;
        check(planet::text::next_boundary(text, text.size())) == text.size();

Nor past it, for an offset that was never legal in the first place

85
86
87
88
89
90
        check(planet::text::previous_boundary(text, 99)) == 2u;
        check(planet::text::next_boundary(text, 99)) == text.size();
    });


    auto const mid_character = suite.test("mid character", [](auto check) {

An offset that splits a character still comes back as a boundary, which is what lets a cursor set from a measurement be snapped onto one.

 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
        std::string const text = "a" + std::string{rocket};

        check(planet::text::previous_boundary(text, 3)) == 1u;
        check(planet::text::next_boundary(text, 3)) == text.size();

        check(planet::text::previous_boundary(text, 2)) == 1u;
        check(planet::text::next_boundary(text, 2)) == text.size();
    });


    auto const empty = suite.test("empty", [](auto check) {
        constexpr std::string_view text{};

        check(planet::text::previous_boundary(text, 0)) == 0u;
        check(planet::text::previous_boundary(text, 7)) == 0u;
        check(planet::text::next_boundary(text, 0)) == 0u;
        check(planet::text::next_boundary(text, 7)) == 0u;
    });


}