Commit 1eb7e839 authored by Nicolas Carion's avatar Nicolas Carion

fuzzing covers most TimelineModel functions

parent b5452853
......@@ -16,9 +16,16 @@ SET(fuzzing_SRCS
main_fuzzer.cpp
fuzzing.cpp
)
SET(reproduce_SRCS
main_reproducer.cpp
fuzzing.cpp
)
ADD_EXECUTABLE(fuzz ${fuzzing_SRCS})
ADD_EXECUTABLE(fuzz_reproduce ${reproduce_SRCS})
target_link_libraries(fuzz kdenliveLib)
target_link_libraries(fuzz_reproduce kdenliveLib)
target_link_options(fuzz PUBLIC "-fsanitize=fuzzer")
set_property(TARGET fuzz PROPERTY CXX_STANDARD 14)
set_property(TARGET fuzz_reproduce PROPERTY CXX_STANDARD 14)
set_target_properties(fuzz PROPERTIES COMPILE_FLAGS "${FUZZING_CXX_FLAGS}")
This diff is collapsed.
/***************************************************************************
* Copyright (C) 2019 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program 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 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#include "core.h"
#include "fuzzing.hpp"
#include <QApplication>
#include <cstring>
#include <iostream>
#include <sstream>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
qputenv("MLT_TESTS", QByteArray("1"));
Core::build();
std::stringstream ss;
std::string str;
while (getline(std::cin, str)) {
ss << str << std::endl;
}
std::cout << "executing " << ss.str() << std::endl;
fuzz(ss.str());
return 0;
}
......@@ -43,6 +43,7 @@ std::vector<Logger::Invok> Logger::invoks;
std::unordered_map<std::string, std::vector<Logger::Constr>> Logger::constr;
std::unordered_map<std::string, std::string> Logger::translation_table;
std::unordered_map<std::string, std::string> Logger::back_translation_table;
int Logger::dump_count = 0;
thread_local size_t Logger::result_awaiting = INT_MAX;
......@@ -140,6 +141,7 @@ bool isIthParamARef(const rttr::method &method, size_t i)
void Logger::print_trace()
{
dump_count++;
auto process_args = [&](const std::vector<rttr::variant> &args, const std::unordered_set<size_t> &refs = {}) {
std::stringstream ss;
bool deb = true;
......@@ -147,8 +149,10 @@ void Logger::print_trace()
for (const auto &a : args) {
if (deb) {
deb = false;
i = 0;
} else {
ss << ", ";
++i;
}
if (refs.count(i) > 0) {
ss << "dummy_" << i;
......@@ -180,7 +184,6 @@ void Logger::print_trace()
} else {
std::cout << "Error: unhandled arg type " << a.get_type().get_name().to_string() << std::endl;
}
++i;
}
return ss.str();
};
......@@ -191,8 +194,10 @@ void Logger::print_trace()
for (const auto &a : args) {
if (deb) {
deb = false;
i = 0;
} else {
ss << " ";
++i;
}
if (refs.count(i) > 0) {
continue;
......@@ -236,7 +241,6 @@ void Logger::print_trace()
} else {
std::cout << "Error: unhandled arg type " << a.get_type().get_name().to_string() << std::endl;
}
++i;
}
return ss.str();
};
......@@ -273,6 +277,24 @@ void Logger::print_trace()
test_file << a.get_type().get_name().to_string() << " dummy_" << std::to_string(a.get_index()) << ";" << std::endl;
}
}
std::string invok_name = invok.method;
if (translation_table.count(invok_name) > 0) {
auto args = invok.args;
if (rttr::type::get<TimelineModel>().get_method(invok_name).is_valid()) {
args.insert(args.begin(), invok.ptr);
// adding an arg just messed up the references
std::unordered_set<size_t> new_refs;
for (const size_t &r : refs) {
new_refs.insert(r + 1);
}
std::swap(refs, new_refs);
}
fuzz_file << translation_table[invok_name] << " " << process_args_fuzz(args, refs) << std::endl;
} else {
std::cout << "ERROR: unknown method " << invok_name << std::endl;
}
if (m.get_return_type() != rttr::type::get<void>()) {
test_file << m.get_return_type().get_name().to_string() << " res = ";
}
......
......@@ -101,6 +101,7 @@ protected:
static std::vector<rttr::variant> operations;
static std::unordered_map<std::string, std::vector<Constr>> constr;
static std::vector<Invok> invoks;
static int dump_count;
};
/** @brief This class provides a RAII mechanism to log the execution of a function */
......
......@@ -7,6 +7,7 @@ Mlt::Profile profile_model;
TEST_CASE("Basic creation/deletion of a track", "[TrackModel]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
std::shared_ptr<MarkerListModel> guideModel = std::make_shared<MarkerListModel>(undoStack);
......@@ -127,6 +128,7 @@ TEST_CASE("Basic creation/deletion of a track", "[TrackModel]")
TEST_CASE("Basic creation/deletion of a clip", "[ClipModel]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
......@@ -170,10 +172,12 @@ TEST_CASE("Basic creation/deletion of a clip", "[ClipModel]")
REQUIRE(timeline->getClipsCount() == 0);
binModel->clean();
pCore->m_projectManager = nullptr;
Logger::print_trace();
}
TEST_CASE("Clip manipulation", "[ClipModel]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
......@@ -921,10 +925,12 @@ TEST_CASE("Clip manipulation", "[ClipModel]")
}
binModel->clean();
pCore->m_projectManager = nullptr;
Logger::print_trace();
}
TEST_CASE("Check id unicity", "[ClipModel]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
......@@ -976,10 +982,12 @@ TEST_CASE("Check id unicity", "[ClipModel]")
REQUIRE(all_ids.size() != track_ids.size());
binModel->clean();
pCore->m_projectManager = nullptr;
Logger::print_trace();
}
TEST_CASE("Undo and Redo", "[ClipModel]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
......@@ -1557,10 +1565,12 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
}
binModel->clean();
pCore->m_projectManager = nullptr;
Logger::print_trace();
}
TEST_CASE("Snapping", "[Snapping]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
......@@ -1678,10 +1688,12 @@ TEST_CASE("Snapping", "[Snapping]")
}
binModel->clean();
pCore->m_projectManager = nullptr;
Logger::print_trace();
}
TEST_CASE("Advanced trimming operations", "[Trimming]")
{
Logger::clear();
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
......@@ -2126,4 +2138,5 @@ TEST_CASE("Advanced trimming operations", "[Trimming]")
}
binModel->clean();
pCore->m_projectManager = nullptr;
Logger::print_trace();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment