Merged PR 316411: enable unit tests in npm

enable unit tests in npm
This commit is contained in:
Asi Bross 2017-07-06 21:14:44 +00:00 коммит произвёл Asi Bross
Родитель ac94741fe2
Коммит a665942332
8 изменённых файлов: 262 добавлений и 4 удалений

Просмотреть файл

@ -5,6 +5,8 @@
#include <stdarg.h>
#define UNUSED(var) (void)(var)
/// <summary> The maximum string length of a single log call. Anything over will be truncated. </summary>
const size_t LOG_MAX_SIZE = 512;
@ -38,7 +40,12 @@ inline void LogFormattedMessage(
#else
#define LOG(section, level, traceId, format, ...)
#define LOG(section, level, traceId, format, ...) \
UNUSED(section); \
UNUSED(level); \
UNUSED(traceId); \
UNUSED(format); \
UNUSED(__VA_ARGS__);
#endif

Просмотреть файл

@ -14,6 +14,7 @@
"install": "cmake-js compile",
"prepublish": "tsc -p lib",
"pretest": "tsc -p test",
"test": "mocha test --recursive"
"test": "mocha test --recursive",
"unittest": "cmake-js compile -d unittest && node unittest/run.js"
}
}

Просмотреть файл

@ -38,7 +38,7 @@ namespace string {
if (len != 0 || !compress) {
list.push_back(str.substr(start, len));
}
start = i;
start = i + 1;
break;
}
}
@ -69,7 +69,7 @@ namespace string {
/// <summary> Return a trimmed copy of the string. </summary>
inline std::string TrimCopy(const std::string &str) {
std::string copy;
std::string copy = str;
Trim(copy);
return copy;
}

38
unittest/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,38 @@
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
project("napa-unittest")
set(NAPA_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..)
# Test Files
file(GLOB_RECURSE TEST_FILES
main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/settings/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/zone/*.cpp)
# Source files under test
file(GLOB_RECURSE SOURCE_FILES
${NAPA_ROOT}/src/settings/settings-parser.cpp
${NAPA_ROOT}/src/zone/simple-thread-pool.cpp)
# The target name
set(TARGET_NAME ${PROJECT_NAME})
# The generated test executable
add_executable(${TARGET_NAME} ${TEST_FILES} ${SOURCE_FILES})
# Compiler definitions
target_compile_definitions(${TARGET_NAME} PRIVATE NAPA_LOG_DISABLED)
# Include directories
target_include_directories(${TARGET_NAME}
PRIVATE
${NAPA_ROOT}/inc
${NAPA_ROOT}/src
${NAPA_ROOT}/third-party)
# Set output directory for dll/libs
set_target_properties(${TARGET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/bin
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/bin
)

2
unittest/main.cpp Normal file
Просмотреть файл

@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include <catch/catch.hpp>

4
unittest/run.js Normal file
Просмотреть файл

@ -0,0 +1,4 @@
var path = require('path');
var childProcess = require('child_process');
childProcess.execFileSync(path.join(__dirname, 'bin/napa-unittest.exe'), [], { stdio: 'inherit' });

Просмотреть файл

@ -0,0 +1,66 @@
#include <catch/catch.hpp>
#include <settings/settings-parser.h>
#include <string>
using namespace napa;
TEST_CASE("Parsing nothing doesn't fail", "[settings-parser]") {
settings::PlatformSettings settings;
REQUIRE(settings::ParseFromString("", settings));
REQUIRE(settings::ParseFromConsole(0, nullptr, settings));
}
TEST_CASE("Parsing from string", "[settings-parser]") {
settings::PlatformSettings settings;
settings.loggingProvider = "";
REQUIRE(settings::ParseFromString("--loggingProvider myProvider", settings));
REQUIRE(settings.loggingProvider == "myProvider");
}
TEST_CASE("Parsing from console", "[settings-parser]") {
settings::PlatformSettings settings;
settings.loggingProvider = "";
std::vector<char*> args = { "--loggingProvider", "myProvider" };
REQUIRE(settings::ParseFromConsole(static_cast<int>(args.size()), args.data(), settings));
REQUIRE(settings.loggingProvider == "myProvider");
}
TEST_CASE("Parsing non existing setting fails", "[settings-parser]") {
settings::PlatformSettings settings;
REQUIRE(settings::ParseFromString("--thisSettingDoesNotExist noValue", settings) == false);
}
TEST_CASE("Parsing does not change defaults if setting is not provided", "[settings-parser]") {
settings::PlatformSettings settings;
settings.metricProvider = "myMetricProvider";
REQUIRE(settings::ParseFromString("--loggingProvider myProvider", settings));
REQUIRE(settings.metricProvider == "myMetricProvider");
}
TEST_CASE("Parsing with extra white spaces succeeds", "[settings-parser]") {
settings::PlatformSettings settings;
settings.loggingProvider = "";
REQUIRE(settings::ParseFromString(" --loggingProvider \t myProvider \t\t ", settings));
REQUIRE(settings.loggingProvider == "myProvider");
}
TEST_CASE("Parsing with empty string succeeds", "[settings-parser]") {
settings::PlatformSettings settings;
REQUIRE(settings::ParseFromString("", settings) == true);
}
TEST_CASE("Parsing with different value type fails", "[settings-parser]") {
settings::ZoneSettings settings;
REQUIRE(settings::ParseFromString("--workers five", settings) == false);
}

Просмотреть файл

@ -0,0 +1,140 @@
#include <catch/catch.hpp>
#include <zone/scheduler.h>
#include <atomic>
#include <future>
using namespace napa;
using namespace napa::zone;
using namespace napa::settings;
class TestTask : public Task {
public:
TestTask(std::function<void()> callback = []() {}) :
numberOfExecutions(0),
lastExecutedWorkerId(99),
_callback(std::move(callback)) {}
void SetCurrentWorkerId(WorkerId id) {
lastExecutedWorkerId = id;
}
virtual void Execute() override
{
numberOfExecutions++;
_callback();
}
std::atomic<uint32_t> numberOfExecutions;
std::atomic<WorkerId> lastExecutedWorkerId;
private:
std::function<void()> _callback;
};
template <uint32_t I>
class TestWorker {
public:
TestWorker(WorkerId id,
const ZoneSettings &settings,
std::function<void(WorkerId)> idleCallback) : _id(id) {
numberOfWorkers++;
_idleNotificationCallback = idleCallback;
}
~TestWorker() {
for (auto& fut : _futures) {
fut.get();
}
}
void Schedule(std::shared_ptr<Task> task) {
auto testTask = std::dynamic_pointer_cast<TestTask>(task);
testTask->SetCurrentWorkerId(_id);
_futures.emplace_back(std::async(std::launch::async, [this, task]() {
task->Execute();
_idleNotificationCallback(_id);
}));
}
static uint32_t numberOfWorkers;
private:
WorkerId _id;
std::vector<std::shared_future<void>> _futures;
std::function<void(WorkerId)> _idleNotificationCallback;
};
template <uint32_t I>
uint32_t TestWorker<I>::numberOfWorkers = 0;
TEST_CASE("scheduler creates correct number of worker", "[scheduler]") {
ZoneSettings settings;
settings.workers = 3;
auto scheduler = std::make_unique<SchedulerImpl<TestWorker<1>>>(settings);
REQUIRE(TestWorker<1>::numberOfWorkers == settings.workers);
}
TEST_CASE("scheduler assigns tasks correctly", "[scheduler]") {
ZoneSettings settings;
settings.workers = 3;
auto scheduler = std::make_unique<SchedulerImpl<TestWorker<2>>>(settings);
auto task = std::make_shared<TestTask>();
SECTION("schedules on exactly one worker") {
scheduler->Schedule(task);
scheduler = nullptr; // force draining all scheduled tasks
REQUIRE(task->numberOfExecutions == 1);
}
SECTION("schedule on a specific worker") {
scheduler->ScheduleOnWorker(2, task);
scheduler = nullptr; // force draining all scheduled tasks
REQUIRE(task->numberOfExecutions == 1);
REQUIRE(task->lastExecutedWorkerId == 2);
}
SECTION("schedule on all workers") {
scheduler->ScheduleOnAllWorkers(task);
scheduler = nullptr; // force draining all scheduled tasks
REQUIRE(task->numberOfExecutions == settings.workers);
}
}
TEST_CASE("scheduler distributes and schedules all tasks", "[scheduler]") {
ZoneSettings settings;
settings.workers = 4;
auto scheduler = std::make_unique<SchedulerImpl<TestWorker<3>>>(settings);
std::vector<std::shared_ptr<TestTask>> tasks;
for (size_t i = 0; i < 1000; i++) {
auto task = std::make_shared<TestTask>();
tasks.push_back(task);
scheduler->Schedule(task);
}
scheduler = nullptr; // force draining all scheduled tasks
std::vector<bool> scheduledWorkersFlags = { false, false, false, false };
for (size_t i = 0; i < 1000; i++) {
// Make sure that each task was executed once
REQUIRE(tasks[i]->numberOfExecutions == 1);
scheduledWorkersFlags[tasks[i]->lastExecutedWorkerId] = true;
}
// Make sure that all workers were participating
for (auto flag: scheduledWorkersFlags) {
REQUIRE(flag);
}
}