aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/tests/data/input_reader/input_reader_test.cpp
blob: a93de9fb3988d5077e1845e2c7e276d735d0a5ca (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/data/memory_input.h>
#include <vespa/vespalib/data/input_reader.h>
#include <vespa/vespalib/test/chunked_input.h>

using namespace vespalib;
using vespalib::test::ChunkedInput;

TEST("input reader smoke test") {
    const char *data = "abc\n"
                       "foo bar\n"
                       "2 + 2 = 4\n";
    MemoryInput memory_input(data);
    ChunkedInput input(memory_input, 3);
    {
        InputReader src(input);
        EXPECT_EQUAL(src.get_offset(), 0u);
        EXPECT_EQUAL(src.read(), 'a');
        EXPECT_EQUAL(src.read(), 'b');
        EXPECT_EQUAL(src.read(), 'c');
        EXPECT_EQUAL(src.read(), '\n');
        EXPECT_EQUAL(src.get_offset(), 4u);
        EXPECT_EQUAL(src.obtain(), 2u);
        EXPECT_EQUAL(src.read(8), Memory("foo bar\n"));
        EXPECT_EQUAL(src.get_offset(), 12u);
        EXPECT_EQUAL(src.obtain(), 3u);
        EXPECT_EQUAL(src.get_offset(), 12u);
        EXPECT_EQUAL(src.read(2), Memory("2 "));
        EXPECT_EQUAL(src.get_offset(), 14u);
        EXPECT_EQUAL(src.obtain(), 1u);
        EXPECT_EQUAL(src.read(8), Memory("+ 2 = 4\n"));
        EXPECT_TRUE(!src.failed());
        EXPECT_EQUAL(src.get_offset(), strlen(data));
        EXPECT_EQUAL(src.obtain(), 0u);
        EXPECT_TRUE(!src.failed());
        EXPECT_EQUAL(src.read(5), Memory());
        EXPECT_TRUE(src.failed());
        EXPECT_EQUAL(src.read(), '\0');
        EXPECT_EQUAL(src.obtain(), 0u);
        EXPECT_EQUAL(src.get_offset(), strlen(data));
        EXPECT_EQUAL(src.get_error_message(), vespalib::string("input underflow"));
    }
}

TEST("require that not reading everything leaves the input in appropriate state") {
    const char *data = "1234567890";
    MemoryInput input(data);
    {
        InputReader src(input);
        EXPECT_EQUAL(src.obtain(), 10u);
        EXPECT_EQUAL(src.read(5), Memory("12345"));
        EXPECT_EQUAL(input.obtain(), Memory("1234567890"));
    }
    EXPECT_EQUAL(input.obtain(), Memory("67890"));
}

TEST("require that input can be explicitly failed with custom message") {
    const char *data = "1234567890";
    MemoryInput input(data);
    {
        InputReader src(input);
        EXPECT_EQUAL(src.read(5), Memory("12345"));
        EXPECT_TRUE(!src.failed());
        src.fail("custom");
        EXPECT_TRUE(src.failed());
        EXPECT_EQUAL(src.read(), '\0');
        EXPECT_EQUAL(src.read(5), Memory());
        EXPECT_EQUAL(src.obtain(), 0u);
        src.fail("ignored");
        EXPECT_EQUAL(src.get_error_message(), vespalib::string("custom"));
        EXPECT_EQUAL(src.get_offset(), 5u);
    }
}

TEST("require that reading a byte sequence crossing the end of input fails") {
    const char *data = "1234567890";
    MemoryInput memory_input(data);
    ChunkedInput input(memory_input, 3);
    {
        InputReader src(input);
        EXPECT_EQUAL(src.read(15), Memory());
        EXPECT_TRUE(src.failed());
        EXPECT_EQUAL(src.get_error_message(), vespalib::string("input underflow"));
        EXPECT_EQUAL(src.get_offset(), 10u);        
    }
}

TEST("expect that obtain does not set failure state on input reader") {
    const char *data = "12345";
    for (bool byte_first: {true, false}) {
        MemoryInput input(data);
        InputReader src(input);
        EXPECT_EQUAL(src.obtain(), 5u);
        EXPECT_EQUAL(src.obtain(), 5u);
        EXPECT_EQUAL(src.read(5), Memory("12345"));
        EXPECT_TRUE(!src.failed());
        EXPECT_EQUAL(src.obtain(), 0u);
        EXPECT_EQUAL(src.obtain(), 0u);
        EXPECT_TRUE(!src.failed());
        if (byte_first) {
            EXPECT_EQUAL(src.read(), 0);
            EXPECT_TRUE(src.failed());
            EXPECT_EQUAL(src.read(5), Memory());
        } else {
            EXPECT_EQUAL(src.read(5), Memory());
            EXPECT_TRUE(src.failed());
            EXPECT_EQUAL(src.read(), 0);
        }
        EXPECT_EQUAL(src.get_error_message(), vespalib::string("input underflow"));
        EXPECT_EQUAL(src.obtain(), 0u);
    }
}

TEST("require that bytes can be unread when appropriate") {
    const char *data = "12345";
    MemoryInput memory_input(data);
    ChunkedInput input(memory_input, 3);
    InputReader src(input);
    EXPECT_TRUE(!src.try_unread());
    EXPECT_EQUAL(src.read(), '1');
    EXPECT_EQUAL(src.read(), '2');
    EXPECT_EQUAL(src.read(), '3');
    EXPECT_TRUE(src.try_unread());
    EXPECT_TRUE(src.try_unread());
    EXPECT_TRUE(src.try_unread());
    EXPECT_TRUE(!src.try_unread());
    EXPECT_EQUAL(src.read(), '1');
    EXPECT_EQUAL(src.read(), '2');
    EXPECT_EQUAL(src.read(), '3');
    EXPECT_EQUAL(src.read(), '4');
    EXPECT_TRUE(src.try_unread());
    EXPECT_TRUE(!src.try_unread());
    EXPECT_EQUAL(src.read(), '4');
    EXPECT_EQUAL(src.read(), '5');
    EXPECT_EQUAL(src.obtain(), 0u);
    EXPECT_TRUE(!src.try_unread());
    EXPECT_TRUE(!src.failed());
}

TEST("require that try read finds eof without failing the reader") {
    const char *data = "12345";
    MemoryInput memory_input(data);
    ChunkedInput input(memory_input, 3);
    InputReader src(input);
    EXPECT_EQUAL(src.try_read(), '1');
    EXPECT_EQUAL(src.try_read(), '2');
    EXPECT_EQUAL(src.try_read(), '3');
    EXPECT_EQUAL(src.try_read(), '4');
    EXPECT_EQUAL(src.try_read(), '5');
    EXPECT_TRUE(src.try_unread());
    EXPECT_EQUAL(src.try_read(), '5');
    EXPECT_EQUAL(src.try_read(), '\0');
    EXPECT_TRUE(!src.try_unread());
    EXPECT_TRUE(!src.failed());
}

TEST_MAIN() { TEST_RUN_ALL(); }