aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/tests/polymorphicarray/polymorphicarray_test.cpp
blob: d4ec8f3ed7c0e33dad9d0c4f8dea651e812c20d9 (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
// Copyright Yahoo. 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/util/polymorphicarrays.h>

using namespace vespalib;

class A {
public:
    virtual ~A() = default;
    virtual void assign(const A & rhs) { (void) rhs; assert(false); }  // Required by the primitive array.
    virtual A * clone() const { assert(false); return nullptr; }       // Required for the complex array.

    // For testing
    virtual bool operator == (const A & rhs) const = 0;
    virtual void print(std::ostream & os) const = 0;
};

class Primitive : public A
{
public:
    Primitive(size_t v=11) noexcept : _v(v) { }
    size_t value() const { return _v; }
    bool operator == (const A & rhs) const override {
       return dynamic_cast<const Primitive &>(rhs).value() == value();
    }
    void assign(const A & rhs) override {
        _v = dynamic_cast<const Primitive &>(rhs).value();
    }
    void print(std::ostream & os) const override {
        os << _v;
    }
private:
    size_t _v;
};


class Complex : public A
{
public:
    Complex(size_t v=11) noexcept : _v(v) { }
    size_t value() const { return _v; }
    bool operator == (const A & rhs) const override {
       return dynamic_cast<const Complex &>(rhs).value() == value();
    }
    Complex * clone() const override {
        return new Complex(_v); 
    }
    void print(std::ostream & os) const override {
        os << _v;
    }
private:
    size_t _v;
};

std::ostream & operator << (std::ostream & os, const A & v) {
    v.print(os);
    return os;
}


template <typename T>
void
verifyArray(IArrayT<A> & array)
{
    EXPECT_EQUAL(0u, array.size());
    for (size_t i(0); i < 10; i++) {
        array.push_back(T(i));
    }
    EXPECT_EQUAL(10u, array.size());
    for (size_t i(0); i < 10; i++) {
        EXPECT_EQUAL(T(i), array[i]);
    }
    IArrayT<A>::UP copy(array.clone());
    array.clear();
    EXPECT_EQUAL(0u, array.size());

    for (size_t i(0); i < copy->size(); i++) {
        array.push_back((*copy)[i]);
    }

    array.resize(19);
    EXPECT_EQUAL(19u, array.size());
    for (size_t i(0); i < 10; i++) {
        EXPECT_EQUAL(T(i), array[i]);
    }
    for (size_t i(10); i < array.size(); i++) {
        EXPECT_EQUAL(T(11), array[i]);
    }
    array.resize(13);
    EXPECT_EQUAL(13u, array.size());
    for (size_t i(0); i < 10; i++) {
        EXPECT_EQUAL(T(i), array[i]);
    }
    for (size_t i(10); i < array.size(); i++) {
        EXPECT_EQUAL(T(11), array[i]);
    }
    dynamic_cast<T &>(array[1]) = T(17);
    EXPECT_EQUAL(T(0), array[0]);
    EXPECT_EQUAL(T(17), array[1]);
    EXPECT_EQUAL(T(2), array[2]);
}


TEST("require that primitive arrays conforms") {
    PrimitiveArrayT<Primitive, A> a;
    verifyArray<Primitive>(a); 
    EXPECT_EQUAL(7u, a[7].value());
}

class Factory : public ComplexArrayT<A>::Factory
{
public:
    A * create() override { return new Complex(); }
    Factory * clone() const override { return new Factory(*this); }
};

TEST("require that complex arrays conforms") {
    ComplexArrayT<A> a(Factory::UP(new Factory()));
    verifyArray<Complex>(a); 
}

TEST_MAIN() { TEST_RUN_ALL(); }