1
0
Fork 0
mirror of https://github.com/KingDuckZ/kamokan.git synced 2025-06-07 00:51:41 +00:00

Add test for SubmitPasteResponse.

This commit is contained in:
King_DuckZ 2017-06-06 00:56:01 +01:00
parent 974424398f
commit f94cc9409b
6 changed files with 305 additions and 1 deletions

View file

@ -34,6 +34,11 @@ namespace tawashi {
const char g_post_key[] = "pastie";
const char g_language_key[] = "lang";
const char g_duration_key[] = "ttl";
#if defined(TAWASHI_WITH_TESTING)
const bool g_connect_to_redis = false;
#else
const bool g_connect_to_redis = true;
#endif
class MissingPostVarError : public TawashiException {
public:
@ -78,7 +83,7 @@ namespace tawashi {
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv
) :
Response(parSettings, parStreamOut, parCgiEnv, true)
Response(parSettings, parStreamOut, parCgiEnv, g_connect_to_redis)
{
}

View file

@ -9,6 +9,8 @@ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_DEBUG} -Wall -Wpedantic -Wconversion
add_executable(${PROJECT_NAME}
check.cpp
test_index_response.cpp
test_submit_pastie.cpp
fake_storage.cpp
)
target_include_directories(${PROJECT_NAME}

View file

@ -0,0 +1,80 @@
/* Copyright 2017, Michele Santullo
* This file is part of "kamokan".
*
* "kamokan" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "kamokan" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "kamokan". If not, see <http://www.gnu.org/licenses/>.
*/
#include "fake_storage.hpp"
#include "num_to_token.hpp"
#include <utility>
#include <algorithm>
namespace tawashi {
FakeStorage::FakeStorage (const Kakoune::SafePtr<SettingsBag>& parSettings, bool parItsConnected) :
Storage(parSettings),
m_submission_num(1),
m_its_connected(parItsConnected)
{
}
FakeStorage::~FakeStorage() = default;
void FakeStorage::connect_async() {
}
bool FakeStorage::is_connected() const {
return m_its_connected;
}
void FakeStorage::finalize_connection() {
}
Storage::SubmissionResult FakeStorage::submit_pastie (
const boost::string_ref& parText,
uint32_t parExpiry,
const boost::string_ref& parLang,
const std::string& parRemoteIP
) const {
SubmittedPastie pastie;
std::string token = num_to_token(m_submission_num++);
pastie.text = std::string(parText.data(), parText.size());
pastie.expiry = parExpiry;
pastie.lang = std::string(parLang.data(), parLang.size());
pastie.remote_ip = parRemoteIP;
pastie.token = token;
m_submitted_pasties.push_back(std::move(pastie));
Storage::SubmissionResult submission_res;
submission_res.token = token;
return submission_res;
}
boost::optional<std::string> FakeStorage::retrieve_pastie (const boost::string_ref& parToken) const {
auto it_found = std::find_if(
m_submitted_pasties.begin(),
m_submitted_pasties.end(),
[&](const SubmittedPastie& pastie) {
return pastie.token == parToken;
}
);
if (m_submitted_pasties.end() == it_found)
return boost::optional<std::string>();
else
return boost::make_optional(it_found->text);
}
const std::vector<FakeStorage::SubmittedPastie>& FakeStorage::submitted_pasties() const {
return m_submitted_pasties;
}
} //namespace tawashi

View file

@ -0,0 +1,62 @@
/* Copyright 2017, Michele Santullo
* This file is part of "kamokan".
*
* "kamokan" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "kamokan" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "kamokan". If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "storage.hpp"
#include <vector>
#include <string>
#include <cstdint>
#if !defined(TAWASHI_WITH_TESTING)
# error "Can't compile this class if test mode is disabled"
#endif
namespace tawashi {
class FakeStorage : public Storage {
public:
struct SubmittedPastie {
std::string text;
std::string lang;
std::string remote_ip;
std::string token;
uint32_t expiry;
};
FakeStorage (const Kakoune::SafePtr<SettingsBag>& parSettings, bool parItsConnected);
tawashi_virtual_testing ~FakeStorage();
tawashi_virtual_testing void connect_async();
tawashi_virtual_testing bool is_connected() const;
tawashi_virtual_testing void finalize_connection();
tawashi_virtual_testing SubmissionResult submit_pastie (
const boost::string_ref& parText,
uint32_t parExpiry,
const boost::string_ref& parLang,
const std::string& parRemoteIP
) const;
tawashi_virtual_testing boost::optional<std::string> retrieve_pastie (const boost::string_ref& parToken) const;
const std::vector<SubmittedPastie>& submitted_pasties() const;
private:
mutable std::vector<SubmittedPastie> m_submitted_pasties;
mutable int64_t m_submission_num;
bool m_its_connected;
};
} //namespace tawashi

View file

@ -18,3 +18,4 @@
#pragma once
#define KAMOKAN_HTML_PATH "@CMAKE_CURRENT_SOURCE_DIR@/html/website"
#cmakedefine TAWASHI_WITH_IP_LOGGING

View file

@ -0,0 +1,154 @@
/* Copyright 2017, Michele Santullo
* This file is part of "kamokan".
*
* "kamokan" is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* "kamokan" is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with "kamokan". If not, see <http://www.gnu.org/licenses/>.
*/
#include "catch.hpp"
#include "submit_paste_response.hpp"
#include "escapist.hpp"
#include "simulation_config.h"
#include "ini_file.hpp"
#include "settings_bag.hpp"
#include "safe_stack_object.hpp"
#include "cgi_env.hpp"
#include "cgi_post.hpp"
#include "fake_storage.hpp"
#include <spdlog/spdlog.h>
#include <sstream>
#include <boost/lexical_cast.hpp>
namespace tawashi {
class SubmitPasteResponseWithFakeStorage : public SubmitPasteResponse {
public:
SubmitPasteResponseWithFakeStorage (
const Kakoune::SafePtr<SettingsBag>& parSettings,
std::ostream* parStreamOut,
const Kakoune::SafePtr<cgi::Env>& parCgiEnv,
std::string&& parPostData
) :
SubmitPasteResponse(parSettings, parStreamOut, parCgiEnv),
m_fake_storage(parSettings, true),
m_post_data(std::move(parPostData))
{
}
virtual cgi::PostMapType cgi_post() const override {
CHECK(not m_post_data.empty());
std::istringstream iss(m_post_data);
return cgi::read_post(iss, this->cgi_env(), this->settings().as<uint32_t>("max_post_size"));
}
virtual const Storage& storage() const override {
return m_fake_storage;
}
const std::vector<FakeStorage::SubmittedPastie>& submitted_pasties() const {
return m_fake_storage.submitted_pasties();
}
private:
FakeStorage m_fake_storage;
std::string m_post_data;
};
} //namespace tawashi
TEST_CASE ("Submit paste response", "[submitpaste][response]") {
using curry::SafeStackObject;
using tawashi::Escapist;
Escapist houdini;
std::string original_pastie = u8"不法投棄(ふほうとうき)とは、廃棄物の処理及び清掃に関する法律(主に、廃棄物処理法、廃掃法と略される)に違反して、同法に定めた処分場以外(主に山中や海、廃墟など人目につかない場所)に廃棄物を投棄することをいう。";
std::string original_lang = u8"colourless";
std::string original_expiry = "2017";
std::string post_data =
"pastie=" + houdini.escape_url(original_pastie) + "&" +
"lang=" + houdini.escape_url(original_lang) + "&" +
"ttl=" + houdini.escape_url(original_expiry)
;
std::string content_length_entry = "CONTENT_LENGTH=" + std::to_string(post_data.size());
const char* const env_raw[] = {
"AUTH_TYPE=",
"CONTENT_TYPE=application/x-www-form-urlencoded; charset=utf-8",
"QUERY_STRING=index.cgi",
"REMOTE_ADDR=127.0.0.1",
"REMOTE_HOST=",
"REMOTE_IDENT=",
"REMOTE_USER=",
"REQUEST_URI=/kamokan/paste.cgi",
"REQUEST_METHOD=POST"
"SCRIPT_NAME=",
"SERVER_NAME=test_server"
"SERVER_SOFTWARE=UnitTest",
content_length_entry.c_str(),
"SERVER_PORT=80",
"HTTPS=",
"REQUEST_METHOD=POST",
nullptr
};
SafeStackObject<tawashi::cgi::Env> fake_env(env_raw, "/");
std::string kamokan_settings(
"[kamokan]\n"
" host_name = 192.168.0.10\n"
" website_root = " KAMOKAN_HTML_PATH "\n"
" logging_level = debug\n"
" langmap_dir = /usr/share/source-highlight\n"
" host_path = /kamokan\n"
" host_port =\n"
" redis_mode = sock\n"
" redis_server = 1.2.3.4\n"
" redis_port = 6379\n"
" redis_sock = /lol/redis.sock\n"
" redis_db = 0\n"
" max_post_size = 1000000\n"
" max_pastie_size = 1500\n"
" min_pastie_size = 1\n"
" truncate_long_pasties = no\n"
);
SafeStackObject<tawashi::IniFile> ini(std::move(kamokan_settings));
SafeStackObject<tawashi::SettingsBag> settings(ini, "kamokan");
std::ostringstream oss;
tawashi::SubmitPasteResponseWithFakeStorage submit_response(
settings,
&oss,
fake_env,
std::move(post_data)
);
submit_response.send();
auto& submitted_pasties = submit_response.submitted_pasties();
REQUIRE(submitted_pasties.size() == 1);
auto& submitted_pastie = submitted_pasties.front();
CHECK(submitted_pastie.text == original_pastie);
CHECK(submitted_pastie.lang == original_lang);
#if defined(TAWASHI_WITH_IP_LOGGING)
CHECK(submitted_pastie.remote_ip == "127.0.0.1");
#endif
CHECK(submitted_pastie.token == "b");
CHECK(submitted_pastie.expiry == boost::lexical_cast<uint32_t>(original_expiry));
{
std::string output = oss.str();
const char expected[] = "Status: 303 See Other\n"
"Location: http://192.168.0.10/kamokan/b?colourless\n\n"
;
CHECK(output == expected);
}
}