YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/server/webserver-test.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
33
#include <iosfwd>
34
#include <string>
35
36
#include <gtest/gtest.h>
37
38
#include "yb/gutil/stringprintf.h"
39
#include "yb/gutil/strings/util.h"
40
41
#include "yb/server/default-path-handlers.h"
42
#include "yb/server/webserver.h"
43
44
#include "yb/util/curl_util.h"
45
#include "yb/util/net/sockaddr.h"
46
#include "yb/util/status.h"
47
#include "yb/util/status_log.h"
48
#include "yb/util/string_trim.h"
49
#include "yb/util/test_util.h"
50
#include "yb/util/zlib.h"
51
52
using std::string;
53
using strings::Substitute;
54
55
DECLARE_int32(webserver_max_post_length_bytes);
56
DECLARE_uint64(webserver_compression_threshold_kb);
57
58
namespace yb {
59
60
class WebserverTest : public YBTest {
61
 public:
62
6
  WebserverTest() {
63
6
    static_dir_ = GetTestPath("webserver-docroot");
64
6
    CHECK_OK(env_->CreateDir(static_dir_));
65
66
6
    WebserverOptions opts;
67
6
    opts.port = 0;
68
6
    opts.doc_root = static_dir_;
69
6
    server_.reset(new Webserver(opts, "WebserverTest"));
70
6
  }
71
72
6
  void SetUp() override {
73
6
    YBTest::SetUp();
74
75
6
    AddDefaultPathHandlers(server_.get());
76
6
    ASSERT_OK(server_->Start());
77
78
6
    std::vector<Endpoint> addrs;
79
6
    ASSERT_OK(server_->GetBoundAddresses(&addrs));
80
6
    ASSERT_EQ(addrs.size(), 1);
81
6
    addr_ = addrs[0];
82
6
    url_ = Substitute("http://$0", ToString(addr_));
83
6
  }
84
85
 protected:
86
  EasyCurl curl_;
87
  faststring buf_;
88
  std::unique_ptr<Webserver> server_;
89
  Endpoint addr_;
90
  string url_;
91
92
  string static_dir_;
93
};
94
95
1
TEST_F(WebserverTest, TestIndexPage) {
96
1
  ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/", ToString(addr_)),
97
1
                           &buf_));
98
  // Should have expected title.
99
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "Yugabyte");
100
101
  // Should have link to the root path handlers (Home).
102
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "Home");
103
1
}
104
105
1
TEST_F(WebserverTest, TestHttpCompression) {
106
1
  std::ostringstream oss;
107
1
  string decoded_str;
108
1
  FLAGS_webserver_compression_threshold_kb = 0;
109
110
  // Curl with gzip compression enabled.
111
1
  ASSERT_OK(curl_.FetchURL(url_, &buf_, EasyCurl::kDefaultTimeoutSec,
112
1
                           {"Accept-Encoding: deflate, br, gzip"}));
113
114
  // If compressed successfully, we should be able to uncompress.
115
1
  ASSERT_OK(zlib::Uncompress(Slice(buf_.ToString()), &oss));
116
1
  decoded_str = oss.str();
117
118
  // Should have expected title.
119
1
  ASSERT_STR_CONTAINS(decoded_str, "YugabyteDB");
120
121
  // Should have expected header when compressed with headers returned.
122
1
  curl_.set_return_headers(true);
123
1
  ASSERT_OK(curl_.FetchURL(url_, &buf_, EasyCurl::kDefaultTimeoutSec,
124
1
                          {"Accept-Encoding: deflate, megaturbogzip,  gzip , br"}));
125
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "Content-Encoding: gzip");
126
127
128
  // Curl with compression disabled.
129
1
  curl_.set_return_headers(true);
130
1
  ASSERT_OK(curl_.FetchURL(url_, &buf_));
131
  // Check expected header.
132
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "Content-Type:");
133
134
  // Check unexpected header.
135
1
  ASSERT_STR_NOT_CONTAINS(buf_.ToString(), "Content-Encoding: gzip");
136
137
  // Should have expected title.
138
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "YugabyteDB");
139
140
  // Curl with compression enabled but not accepted by YugabyteDB.
141
1
  curl_.set_return_headers(true);
142
1
  ASSERT_OK(curl_.FetchURL(url_, &buf_, EasyCurl::kDefaultTimeoutSec,
143
1
                           {"Accept-Encoding: megaturbogzip, deflate, xz"}));
144
  // Check expected header.
145
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "HTTP/1.1 200 OK");
146
147
  // Check unexpected header.
148
1
  ASSERT_STR_NOT_CONTAINS(buf_.ToString(), "Content-Encoding: gzip");
149
150
  // Should have expected title.
151
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "YugabyteDB");
152
153
1
}
154
155
1
TEST_F(WebserverTest, TestDefaultPaths) {
156
  // Test memz
157
1
  ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/memz?raw=1", ToString(addr_)),
158
1
                           &buf_));
159
#ifdef TCMALLOC_ENABLED
160
  ASSERT_STR_CONTAINS(buf_.ToString(), "Bytes in use by application");
161
#else
162
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "not available unless tcmalloc is enabled");
163
1
#endif
164
165
  // Test varz -- check for one of the built-in gflags flags.
166
1
  ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/varz?raw=1", ToString(addr_)),
167
1
                           &buf_));
168
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "--v=");
169
170
  // Test status.
171
1
  ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/status", ToString(addr_)),
172
1
                           &buf_));
173
1
  ASSERT_STR_EQ_VERBOSE_TRIMMED("{}", buf_.ToString());
174
1
}
175
176
// Used in symbolization test below.
177
0
void SomeMethodForSymbolTest1() {}
178
// Used in symbolization test below.
179
0
void SomeMethodForSymbolTest2() {}
180
181
1
TEST_F(WebserverTest, TestPprofPaths) {
182
  // Test /pprof/cmdline GET
183
1
  ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/pprof/cmdline", ToString(addr_)),
184
1
                           &buf_));
185
1
  ASSERT_STR_CONTAINS(buf_.ToString(), "webserver-test");
186
2
  ASSERT_TRUE(!HasSuffixString(buf_.ToString(), string("\x00", 1)))
187
2
    << "should not have trailing NULL: " << Slice(buf_).ToDebugString();
188
189
  // Test /pprof/symbol GET
190
1
  ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/pprof/symbol", ToString(addr_)),
191
1
                           &buf_));
192
1
  ASSERT_EQ(buf_.ToString(), "num_symbols: 1");
193
194
  // Test /pprof/symbol POST
195
1
  {
196
    // Formulate a request with some valid symbol addresses.
197
1
    string req = StringPrintf("%p+%p",
198
1
                              &SomeMethodForSymbolTest1,
199
1
                              &SomeMethodForSymbolTest2);
200
1
    SCOPED_TRACE(req);
201
1
    ASSERT_OK(curl_.PostToURL(strings::Substitute("http://$0/pprof/symbol", ToString(addr_)),
202
1
                              req, &buf_));
203
1
    ASSERT_EQ(buf_.ToString(),
204
1
              StringPrintf("%p\tyb::SomeMethodForSymbolTest1()\n"
205
1
                           "%p\tyb::SomeMethodForSymbolTest2()\n",
206
1
                           &SomeMethodForSymbolTest1,
207
1
                           &SomeMethodForSymbolTest2));
208
1
  }
209
1
}
210
211
// Send a POST request with too much data. It should reject
212
// the request with the correct HTTP error code.
213
1
TEST_F(WebserverTest, TestPostTooBig) {
214
1
  FLAGS_webserver_max_post_length_bytes = 10;
215
1
  string req(10000, 'c');
216
1
  Status s = curl_.PostToURL(strings::Substitute("http://$0/pprof/symbol", ToString(addr_)),
217
1
                             req, &buf_);
218
1
  ASSERT_EQ("Remote error: HTTP 413", s.ToString(/* no file/line */ false));
219
1
}
220
221
// Test that static files are served and that directory listings are
222
// disabled.
223
1
TEST_F(WebserverTest, TestStaticFiles) {
224
  // Fetch a non-existent static file.
225
1
  Status s = curl_.FetchURL(strings::Substitute("http://$0/foo.txt", ToString(addr_)),
226
1
                            &buf_);
227
1
  ASSERT_EQ("Remote error: HTTP 404", s.ToString(/* no file/line */ false));
228
229
  // Create the file and fetch again. This time it should succeed.
230
1
  ASSERT_OK(WriteStringToFile(env_.get(), "hello world",
231
1
                              strings::Substitute("$0/foo.txt", static_dir_)));
232
1
  ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/foo.txt", ToString(addr_)),
233
1
                           &buf_));
234
1
  ASSERT_EQ("hello world", buf_.ToString());
235
236
  // Create a directory and ensure that subdirectory listing is disabled.
237
1
  ASSERT_OK(env_->CreateDir(strings::Substitute("$0/dir", static_dir_)));
238
1
  s = curl_.FetchURL(strings::Substitute("http://$0/dir/", ToString(addr_)),
239
1
                     &buf_);
240
1
  ASSERT_EQ("Remote error: HTTP 403", s.ToString(/* no file/line */ false));
241
1
}
242
243
} // namespace yb