summaryrefslogtreecommitdiffstats
path: root/searchlib/src/tests/ranksetup/verify_feature/verify_feature_test.cpp
blob: 6d49704e7c19c3c80879c97b8b36a4045318cf5c (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 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/searchlib/fef/fef.h>
#include <vespa/searchlib/fef/test/indexenvironment.h>
#include <vespa/searchlib/fef/test/plugin/setup.h>
#include <vespa/searchlib/features/valuefeature.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <regex>

using namespace search::features;
using namespace search::fef::test;
using namespace search::fef;
using vespalib::make_string_short::fmt;

typedef bool (*cmp)(const vespalib::string & a, const vespalib::string &b);

namespace search::fef {
std::ostream &operator<<(std::ostream &os, Level level) {
    if (level == Level::INFO) {
        return os << "info";
    }
    if (level == Level::WARNING) {
        return os << "warning";
    }
    return os << "error";
}
}

bool equal(const vespalib::string & a, const vespalib::string &b) {
    return a == b;
}

bool regex(const vespalib::string & a, const vespalib::string &b) {
    std::regex exp(b.c_str());
    return std::regex_match(a.c_str(), exp);
}

struct RankFixture {
    BlueprintFactory factory;
    IndexEnvironment indexEnv;

    RankFixture() : factory(), indexEnv() {
        setup_fef_test_plugin(factory);
        factory.addPrototype(std::make_shared<ValueBlueprint>());
    }

    bool verify(const std::string &feature, std::vector<std::pair<cmp, Message>> expected) const {
        std::vector<Message> errors;
        bool ok = verifyFeature(factory, indexEnv, feature, "feature verification test", errors);
        EXPECT_EQUAL(errors.size(), expected.size());
        for (size_t i(0); i < std::min(errors.size(), expected.size()); i++) {
            EXPECT_EQUAL(errors[i].first, expected[i].second.first);
            EXPECT_TRUE(expected[i].first(errors[i].second, expected[i].second.second));
        }
        return ok;
    }
};

TEST_F("verify valid rank feature", RankFixture) {
    EXPECT_TRUE(f1.verify("value(1, 2, 3).0", {}));
    EXPECT_TRUE(f1.verify("value(1, 2, 3).1", {}));
    EXPECT_TRUE(f1.verify("value(1, 2, 3).2", {}));
}

TEST_F("verify unknown feature", RankFixture) {
    EXPECT_FALSE(f1.verify("unknown",
                           {{equal, {Level::WARNING, "invalid rank feature 'unknown': unknown basename: 'unknown'"}},
                            {equal, {Level::ERROR, "verification failed: rank feature 'unknown' (feature verification test)"}}}));
}

TEST_F("verify unknown output", RankFixture) {
    EXPECT_FALSE(f1.verify("value(1, 2, 3).3",
                           {{equal, {Level::WARNING, "invalid rank feature 'value(1,2,3).3': unknown output: '3'"}},
                            {equal, {Level::ERROR, "verification failed: rank feature 'value(1, 2, 3).3' (feature verification test)"}}}));
}

TEST_F("verify illegal input parameters", RankFixture) {
    EXPECT_FALSE(f1.verify("value.0",
                           {{equal, {Level::WARNING, "invalid rank feature 'value.0':"
                                                     " The parameter list used for setting up rank feature value is not valid:"
                                                     " Expected 1+1x parameter(s), but got 0"}},
                            {equal, {Level::ERROR, "verification failed: rank feature 'value.0' (feature verification test)"}}}));
}

TEST_F("verify illegal feature name", RankFixture) {
    EXPECT_FALSE(f1.verify("value(2).",
                           {{equal, {Level::WARNING, "invalid rank feature 'value(2).': malformed name"}},
                            {equal, {Level::ERROR, "verification failed: rank feature 'value(2).' (feature verification test)"}}}));
}

TEST_F("verify too deep dependency graph", RankFixture) {
    EXPECT_TRUE(f1.verify("chain(basic, 255, 4)", {}));
    EXPECT_FALSE(f1.verify("chain(basic, 256, 4)",
                           {{equal,
                             {Level::WARNING,
                              "invalid rank feature 'value(4)': dependency graph too deep\n"
                              "  ... needed by rank feature 'chain(basic,1,4)'\n"
                              "  ... needed by rank feature 'chain(basic,2,4)'\n"
                              "  ... needed by rank feature 'chain(basic,3,4)'\n"
                              "  ... needed by rank feature 'chain(basic,4,4)'\n"
                              "  ... needed by rank feature 'chain(basic,5,4)'\n"
                              "  ... needed by rank feature 'chain(basic,6,4)'\n"
                              "  ... needed by rank feature 'chain(basic,7,4)'\n"
                              "  ... needed by rank feature 'chain(basic,8,4)'\n"
                              "  ... needed by rank feature 'chain(basic,9,4)'\n"
                              "  ... needed by rank feature 'chain(basic,10,4)'\n"
                              "  (skipped 241 entries)\n"
                              "  ... needed by rank feature 'chain(basic,252,4)'\n"
                              "  ... needed by rank feature 'chain(basic,253,4)'\n"
                              "  ... needed by rank feature 'chain(basic,254,4)'\n"
                              "  ... needed by rank feature 'chain(basic,255,4)'\n"
                              "  ... needed by rank feature 'chain(basic,256,4)'\n"}},
                            {regex, {Level::WARNING, "high stack usage: [0-9]+ bytes"}},
                            {equal, {Level::ERROR, "verification failed: rank feature 'chain(basic, 256, 4)' (feature verification test)"}}}));
}

TEST_F("verify dependency cycle", RankFixture) {
    EXPECT_FALSE(f1.verify("chain(cycle, 4, 2)",
                           {{equal,
                             {Level::WARNING,
                              "invalid rank feature 'chain(cycle,2,2)': dependency cycle detected\n"
                              "  ... needed by rank feature 'chain(cycle,1,2)'\n"
                              "  ... needed by rank feature 'chain(cycle,2,2)'\n"
                              "  ... needed by rank feature 'chain(cycle,3,2)'\n"
                              "  ... needed by rank feature 'chain(cycle,4,2)'\n"}},
                            {equal, {Level::ERROR, "verification failed: rank feature 'chain(cycle, 4, 2)' (feature verification test)"}}}));
}

TEST_MAIN() { TEST_RUN_ALL(); }