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
|
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/testapp.h>
#include <lib/configstatus.h>
#include <vespa/fastlib/net/httpserver.h>
#include <vespa/config-model.h>
#include <vespa/config/config.h>
#include <vespa/config/subscription/sourcespec.h>
using namespace config;
class HTTPStatus : private Fast_HTTPServer {
private:
std::string _reply;
bool _fail;
void onGetRequest(const string &, const string &, Fast_HTTPConnection &conn) override {
if (_fail) {
conn.Output(conn.GetHTTPVersion().c_str());
conn.Output(" 500 Error\r\n");
conn.Output("Connection: close\r\n");
conn.Output("\r\n");
} else {
conn.Output(conn.GetHTTPVersion().c_str());
conn.Output(" 200 OK\r\n");
conn.Output("Content-Type: application/json\r\n\r\n");
conn.Output(_reply.c_str());
}
};
public:
HTTPStatus(std::string reply)
: Fast_HTTPServer(0), _reply(reply), _fail(false)
{
Start();
};
HTTPStatus(bool fail)
: Fast_HTTPServer(0), _reply(""), _fail(fail)
{
Start();
};
int getListenPort() { return Fast_HTTPServer::getListenPort(); }
~HTTPStatus() {
Stop();
};
};
class Status {
public:
ConfigStatus::Flags flags;
std::unique_ptr<ConfigStatus> status;
Status(int http_port,
const ConfigStatus::Flags& cfg_flags,
const std::vector<std::string>& model_hosts)
: flags(cfg_flags)
{
flags.verbose = true;
ConfigSet set;
ConfigContext::SP ctx(new ConfigContext(set));
cloud::config::ModelConfigBuilder builder;
cloud::config::ModelConfigBuilder::Hosts::Services::Ports port;
port.number = http_port;
port.tags = "http state";
cloud::config::ModelConfigBuilder::Hosts::Services service;
service.name = "qrserver";
service.type = "qrserver";
service.configid = "qrserver/cluster.default";
service.clustertype = "qrserver";
service.clustername = "default";
service.ports.push_back(port);
for (auto& mhost : model_hosts) {
cloud::config::ModelConfigBuilder::Hosts host;
host.services.push_back(service);
host.name = mhost;
builder.hosts.push_back(host);
}
set.addBuilder("admin/model", &builder);
config::ConfigUri uri("admin/model", ctx);
std::unique_ptr<ConfigStatus> s(new ConfigStatus(flags, uri));
status = std::move(s);
}
Status(int http_port)
: Status(http_port, ConfigStatus::Flags(), {{"localhost"}})
{}
~Status() {
}
};
std::string ok_json_at_gen_1() {
return "{\"config\": { \"all\": { \"generation\": 1 } }}";
}
TEST_FF("all ok", HTTPStatus(ok_json_at_gen_1()), Status(f1.getListenPort())) {
ASSERT_EQUAL(0, f2.status->action());
}
TEST_FF("generation too old", HTTPStatus(std::string("{\"config\": { \"all\": { \"generation\": 0 } }}")), Status(f1.getListenPort())) {
ASSERT_EQUAL(1, f2.status->action());
}
TEST_FF("bad json", HTTPStatus(std::string("{")), Status(f1.getListenPort())) {
ASSERT_EQUAL(1, f2.status->action());
}
TEST_FF("http failure", HTTPStatus(true), Status(f1.getListenPort())) {
ASSERT_EQUAL(1, f2.status->action());
}
TEST_F("queried host set can be constrained", HTTPStatus(ok_json_at_gen_1())) {
HostFilter filter({"localhost"});
std::vector<std::string> hosts(
{"localhost", "no-such-host.foo.yahoo.com"});
Status status(f1.getListenPort(), ConfigStatus::Flags(filter), hosts);
// Non-existing host should never be contacted.
ASSERT_EQUAL(0, status.status->action());
}
TEST_MAIN() { TEST_RUN_ALL(); }
|