blob: 6fc9e940aeb367af8d14a2955345bac83fcaa4d2 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include <gflags/gflags.h>
#include <gtest/gtest.h>
#include <string>
#include "kudu/gutil/strings/substitute.h"
#include "kudu/gutil/strings/util.h"
#include "kudu/gutil/stringprintf.h"
#include "kudu/server/default-path-handlers.h"
#include "kudu/server/webserver.h"
#include "kudu/util/curl_util.h"
#include "kudu/util/net/sockaddr.h"
#include "kudu/util/test_util.h"
using std::string;
DECLARE_int32(webserver_max_post_length_bytes);
namespace kudu {
class WebserverTest : public KuduTest {
public:
WebserverTest() {
static_dir_ = GetTestPath("webserver-docroot");
CHECK_OK(env_->CreateDir(static_dir_));
WebserverOptions opts;
opts.port = 0;
opts.doc_root = static_dir_;
server_.reset(new Webserver(opts));
}
virtual void SetUp() OVERRIDE {
KuduTest::SetUp();
AddDefaultPathHandlers(server_.get());
ASSERT_OK(server_->Start());
vector<Sockaddr> addrs;
ASSERT_OK(server_->GetBoundAddresses(&addrs));
ASSERT_EQ(addrs.size(), 1);
addr_ = addrs[0];
}
protected:
EasyCurl curl_;
faststring buf_;
gscoped_ptr<Webserver> server_;
Sockaddr addr_;
string static_dir_;
};
TEST_F(WebserverTest, TestIndexPage) {
ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/", addr_.ToString()),
&buf_));
// Should have expected title.
ASSERT_STR_CONTAINS(buf_.ToString(), "Kudu");
// Should have link to default path handlers (e.g memz)
ASSERT_STR_CONTAINS(buf_.ToString(), "memz");
}
TEST_F(WebserverTest, TestDefaultPaths) {
// Test memz
ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/memz?raw=1", addr_.ToString()),
&buf_));
#ifdef TCMALLOC_ENABLED
ASSERT_STR_CONTAINS(buf_.ToString(), "Bytes in use by application");
#else
ASSERT_STR_CONTAINS(buf_.ToString(), "not available unless tcmalloc is enabled");
#endif
// Test varz -- check for one of the built-in gflags flags.
ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/varz?raw=1", addr_.ToString()),
&buf_));
ASSERT_STR_CONTAINS(buf_.ToString(), "--v=");
}
// Used in symbolization test below.
void SomeMethodForSymbolTest1() {}
// Used in symbolization test below.
void SomeMethodForSymbolTest2() {}
TEST_F(WebserverTest, TestPprofPaths) {
// Test /pprof/cmdline GET
ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/pprof/cmdline", addr_.ToString()),
&buf_));
ASSERT_STR_CONTAINS(buf_.ToString(), "webserver-test");
ASSERT_TRUE(!HasSuffixString(buf_.ToString(), string("\x00", 1)))
<< "should not have trailing NULL: " << Slice(buf_).ToDebugString();
// Test /pprof/symbol GET
ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/pprof/symbol", addr_.ToString()),
&buf_));
ASSERT_EQ(buf_.ToString(), "num_symbols: 1");
// Test /pprof/symbol POST
{
// Formulate a request with some valid symbol addresses.
string req = StringPrintf("%p+%p",
&SomeMethodForSymbolTest1,
&SomeMethodForSymbolTest2);
SCOPED_TRACE(req);
ASSERT_OK(curl_.PostToURL(strings::Substitute("http://$0/pprof/symbol", addr_.ToString()),
req, &buf_));
ASSERT_EQ(buf_.ToString(),
StringPrintf("%p\tkudu::SomeMethodForSymbolTest1()\n"
"%p\tkudu::SomeMethodForSymbolTest2()\n",
&SomeMethodForSymbolTest1,
&SomeMethodForSymbolTest2));
}
}
// Send a POST request with too much data. It should reject
// the request with the correct HTTP error code.
TEST_F(WebserverTest, TestPostTooBig) {
FLAGS_webserver_max_post_length_bytes = 10;
string req(10000, 'c');
Status s = curl_.PostToURL(strings::Substitute("http://$0/pprof/symbol", addr_.ToString()),
req, &buf_);
ASSERT_EQ("Remote error: HTTP 413", s.ToString());
}
// Test that static files are served and that directory listings are
// disabled.
TEST_F(WebserverTest, TestStaticFiles) {
// Fetch a non-existent static file.
Status s = curl_.FetchURL(strings::Substitute("http://$0/foo.txt", addr_.ToString()),
&buf_);
ASSERT_EQ("Remote error: HTTP 404", s.ToString());
// Create the file and fetch again. This time it should succeed.
ASSERT_OK(WriteStringToFile(env_.get(), "hello world",
strings::Substitute("$0/foo.txt", static_dir_)));
ASSERT_OK(curl_.FetchURL(strings::Substitute("http://$0/foo.txt", addr_.ToString()),
&buf_));
ASSERT_EQ("hello world", buf_.ToString());
// Create a directory and ensure that subdirectory listing is disabled.
ASSERT_OK(env_->CreateDir(strings::Substitute("$0/dir", static_dir_)));
s = curl_.FetchURL(strings::Substitute("http://$0/dir/", addr_.ToString()),
&buf_);
ASSERT_EQ("Remote error: HTTP 403", s.ToString());
}
} // namespace kudu