summaryrefslogtreecommitdiffstats
path: root/vespalib/src/tests/data/input_reader/input_reader_test.cpp
blob: 54c0613b6dae082c5374c016a1d4ad892d4961a6 (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
// Copyright 2017 Yahoo Inc. 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 <algorithm>

using namespace vespalib;

// make sure input is split into chunks
struct ChunkedInput : Input {
    Input &input;
    ChunkedInput(Input &input_in) : input(input_in) {}
    Memory obtain() override {
        Memory memory = input.obtain();
        memory.size = std::min(memory.size, size_t(3));
        return memory;
    }
    Input &evict(size_t bytes) override {
        EXPECT_LESS_EQUAL(bytes, 3u);
        input.evict(bytes);
        return *this;
    }
};

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);
    {
        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);
    {
        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(), 5);
        EXPECT_EQUAL(src.obtain(), 5);
        EXPECT_EQUAL(src.read(5), Memory("12345"));
        EXPECT_TRUE(!src.failed());
        EXPECT_EQUAL(src.obtain(), 0);
        EXPECT_EQUAL(src.obtain(), 0);
        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(), 0);
    }
}

TEST_MAIN() { TEST_RUN_ALL(); }