Merge pull request #344 from kiwix/server_unittests

Server unittests
This commit is contained in:
Kelson 2020-04-29 14:02:57 +02:00 committed by GitHub
commit 80fcbceeb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 5339 additions and 2 deletions

View File

@ -1,3 +1,8 @@
resource_files = run_command(find_program('python'),
'-c',
'import sys; f=open(sys.argv[1]); print(f.read())',
files('resources_list.txt')
).stdout().strip().split('\n')
lib_resources = custom_target('resources',
input: 'resources_list.txt',
@ -7,5 +12,5 @@ lib_resources = custom_target('resources',
'--hfile', '@OUTPUT1@',
'--source_dir', '@OUTDIR@',
'@INPUT@'],
build_always_stale: true
depend_files: resource_files
)

Binary file not shown.

5101
test/httplib.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,8 @@ tests = [
'pathTools',
'kiwixserve',
'book',
'manager'
'manager',
'server'
]
@ -21,8 +22,15 @@ gtest_dep = dependency('gtest',
required:false)
if gtest_dep.found() and not meson.is_cross_build()
configure_file(input : 'data/wikipedia_en_ray_charles_mini_2020-03.zim',
output : 'zimfile.zim',
copy: true )
foreach test_name : tests
# XXX: implicit_include_directories must be set to false, otherwise
# XXX: '#include <regex>' includes the regex unit test binary
test_exe = executable(test_name, [test_name+'.cpp'],
implicit_include_directories: false,
link_with : kiwixlib,
link_args: extra_link_args,
dependencies : all_deps + [gtest_dep],

223
test/server.cpp Normal file
View File

@ -0,0 +1,223 @@
#include "gtest/gtest.h"
#include "../include/manager.h"
#include "../include/server.h"
#include "../include/name_mapper.h"
#include "./httplib.h"
class ZimFileServer
{
public: // types
typedef httplib::Headers Headers;
typedef std::shared_ptr<httplib::Response> Response;
public: // functions
ZimFileServer(int serverPort, std::string zimpath);
~ZimFileServer();
Response GET(const char* path, const Headers& headers = Headers())
{
return client->Get(path, headers);
}
Response HEAD(const char* path, const Headers& headers = Headers())
{
return client->Head(path, headers);
}
private: // data
kiwix::Library library;
kiwix::Manager manager;
std::unique_ptr<kiwix::HumanReadableNameMapper> nameMapper;
std::unique_ptr<kiwix::Server> server;
std::unique_ptr<httplib::Client> client;
};
ZimFileServer::ZimFileServer(int serverPort, std::string zimpath)
: manager(&this->library)
{
if (!manager.addBookFromPath(zimpath, zimpath, "", false))
throw std::runtime_error("Unable to add the ZIM file '" + zimpath + "'");
const std::string address = "127.0.0.1";
nameMapper.reset(new kiwix::HumanReadableNameMapper(library, false));
server.reset(new kiwix::Server(&library, nameMapper.get()));
server->setAddress(address);
server->setPort(serverPort);
server->setNbThreads(2);
server->setVerbose(false);
if ( !server->start() )
throw std::runtime_error("ZimFileServer failed to start");
client.reset(new httplib::Client(address, serverPort));
}
ZimFileServer::~ZimFileServer()
{
server->stop();
}
class ServerTest : public ::testing::Test
{
protected:
std::unique_ptr<ZimFileServer> zfs1_;
const int PORT = 8001;
const std::string ZIMFILE = "./test/zimfile.zim";
protected:
void SetUp() override {
zfs1_.reset(new ZimFileServer(PORT, ZIMFILE));
}
void TearDown() override {
zfs1_.reset();
}
};
struct Resource
{
const char* url;
};
std::ostream& operator<<(std::ostream& out, const Resource& r)
{
out << "url: " << r.url;
return out;
}
Resource resources200Compressible[] = {
{ "/" },
{ "/skin/jquery-ui/jquery-ui.structure.min.css" },
{ "/skin/jquery-ui/jquery-ui.min.js" },
{ "/skin/jquery-ui/external/jquery/jquery.js" },
{ "/skin/jquery-ui/jquery-ui.theme.min.css" },
{ "/skin/jquery-ui/jquery-ui.min.css" },
{ "/skin/taskbar.js" },
{ "/skin/taskbar.css" },
{ "/skin/block_external.js" },
{ "/search?content=zimfile&pattern=abcd" },
{ "/suggest?content=zimfile&term=ray" },
{ "/catch/external?source=www.example.com" },
{ "/zimfile/A/index" },
{ "/zimfile/A/Ray_Charles" },
};
Resource resources200Uncompressible[] = {
{ "/skin/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png" },
{ "/skin/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png" },
{ "/skin/jquery-ui/images/ui-icons_222222_256x240.png" },
{ "/skin/jquery-ui/images/ui-bg_glass_55_fbf9ee_1x400.png" },
{ "/skin/jquery-ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png" },
{ "/skin/jquery-ui/images/ui-bg_glass_65_ffffff_1x400.png" },
{ "/skin/jquery-ui/images/ui-icons_2e83ff_256x240.png" },
{ "/skin/jquery-ui/images/ui-icons_cd0a0a_256x240.png" },
{ "/skin/jquery-ui/images/ui-icons_888888_256x240.png" },
{ "/skin/jquery-ui/images/ui-bg_glass_75_e6e6e6_1x400.png" },
{ "/skin/jquery-ui/images/animated-overlay.gif" },
{ "/skin/jquery-ui/images/ui-bg_glass_75_dadada_1x400.png" },
{ "/skin/jquery-ui/images/ui-icons_454545_256x240.png" },
{ "/skin/jquery-ui/images/ui-bg_glass_95_fef1ec_1x400.png" },
{ "/skin/caret.png" },
{ "/catalog/root.xml" },
{ "/catalog/searchdescription.xml" },
{ "/catalog/search" },
{ "/meta?content=zimfile&name=title" },
{ "/meta?content=zimfile&name=description" },
{ "/meta?content=zimfile&name=language" },
{ "/meta?content=zimfile&name=name" },
{ "/meta?content=zimfile&name=tags" },
{ "/meta?content=zimfile&name=date" },
{ "/meta?content=zimfile&name=creator" },
{ "/meta?content=zimfile&name=publisher" },
{ "/meta?content=zimfile&name=favicon" },
{ "/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg" },
};
TEST_F(ServerTest, 200)
{
for ( const Resource& res : resources200Compressible )
EXPECT_EQ(200, zfs1_->GET(res.url)->status) << "res.url: " << res.url;
for ( const Resource& res : resources200Uncompressible )
EXPECT_EQ(200, zfs1_->GET(res.url)->status) << "res.url: " << res.url;
}
TEST_F(ServerTest, CompressibleContentIsCompressedIfAcceptable)
{
for ( const Resource& res : resources200Compressible ) {
const auto x = zfs1_->GET(res.url, { {"Accept-Encoding", "deflate"} });
EXPECT_EQ(200, x->status) << res;
EXPECT_EQ("deflate", x->get_header_value("Content-Encoding")) << res;
EXPECT_EQ("Accept-Encoding", x->get_header_value("Vary")) << res;
}
}
TEST_F(ServerTest, UncompressibleContentIsNotCompressed)
{
for ( const Resource& res : resources200Uncompressible ) {
const auto x = zfs1_->GET(res.url, { {"Accept-Encoding", "deflate"} });
EXPECT_EQ(200, x->status) << res;
EXPECT_EQ("", x->get_header_value("Content-Encoding")) << res;
}
}
const char* urls404[] = {
"/non-existent-item",
"/skin/non-existent-skin-resource",
"/catalog",
"/catalog/non-existent-item",
"/meta",
"/meta?content=zimfile",
"/meta?content=zimfile&name=non-existent-item",
"/meta?content=non-existent-book&name=title",
"/random",
"/random?content=non-existent-book",
"/search",
"/suggest",
"/suggest?content=zimfile",
"/suggest?content=non-existent-book&term=abcd",
"/catch/external",
"/zimfile/A/non-existent-article",
};
TEST_F(ServerTest, 404)
{
for ( const char* url : urls404 )
EXPECT_EQ(404, zfs1_->GET(url)->status) << "url: " << url;
}
TEST_F(ServerTest, SuccessfulSearchForAnArticleTitleRedirectsToTheArticle)
{
auto g = zfs1_->GET("/search?content=zimfile&pattern=ray%20charles" );
ASSERT_EQ(302, g->status);
ASSERT_TRUE(g->has_header("Location"));
ASSERT_EQ("/zimfile/A/Ray_Charles", g->get_header_value("Location"));
}
TEST_F(ServerTest, RandomPageRedirectsToAnExistingArticle)
{
auto g = zfs1_->GET("/random?content=zimfile");
ASSERT_EQ(302, g->status);
ASSERT_TRUE(g->has_header("Location"));
ASSERT_TRUE(g->get_header_value("Location").find("/zimfile/A/") != std::string::npos);
}
TEST_F(ServerTest, BookMainPageIsRedirectedToArticleIndex)
{
auto g = zfs1_->GET("/zimfile");
ASSERT_EQ(302, g->status);
ASSERT_TRUE(g->has_header("Location"));
ASSERT_EQ("/zimfile/A/index", g->get_header_value("Location"));
}