diff --git a/fuzzer/fuzzing.cpp b/fuzzer/fuzzing.cpp
index 023420789..c3a245e92 100644
--- a/fuzzer/fuzzing.cpp
+++ b/fuzzer/fuzzing.cpp
@@ -1,450 +1,451 @@
/***************************************************************************
* 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 . *
***************************************************************************/
#include "fuzzing.hpp"
#include "bin/model/markerlistmodel.hpp"
#include "doc/docundostack.hpp"
#include "fakeit_standalone.hpp"
#include "logger.hpp"
#include
#include
#include
#include
#include
#define private public
#define protected public
#include "assets/keyframes/model/keyframemodel.hpp"
#include "assets/model/assetparametermodel.hpp"
#include "bin/clipcreator.hpp"
#include "bin/projectclip.h"
#include "bin/projectfolder.h"
#include "bin/projectitemmodel.h"
#include "core.h"
#include "effects/effectsrepository.hpp"
#include "effects/effectstack/model/effectitemmodel.hpp"
#include "effects/effectstack/model/effectstackmodel.hpp"
#include "mltconnection.h"
#include "project/projectmanager.h"
#include "timeline2/model/clipmodel.hpp"
#include "timeline2/model/compositionmodel.hpp"
#include "timeline2/model/groupsmodel.hpp"
#include "timeline2/model/timelinefunctions.hpp"
#include "timeline2/model/timelineitemmodel.hpp"
#include "timeline2/model/timelinemodel.hpp"
#include "timeline2/model/trackmodel.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wpedantic"
#include
#pragma GCC diagnostic pop
using namespace fakeit;
namespace {
QString createProducer(Mlt::Profile &prof, std::string color, std::shared_ptr binModel, int length, bool limited)
{
Logger::log_create_producer("test_producer", {color, binModel, length, limited});
std::shared_ptr producer = std::make_shared(prof, "color", color.c_str());
producer->set("length", length);
producer->set("out", length - 1);
Q_ASSERT(producer->is_valid());
QString binId = QString::number(binModel->getFreeClipId());
auto binClip = ProjectClip::construct(binId, QIcon(), binModel, producer);
if (limited) {
binClip->forceLimitedDuration();
}
Fun undo = []() { return true; };
Fun redo = []() { return true; };
Q_ASSERT(binModel->addItem(binClip, binModel->getRootFolder()->clipId(), undo, redo));
return binId;
}
QString createProducerWithSound(Mlt::Profile &prof, std::shared_ptr binModel)
{
Logger::log_create_producer("test_producer_sound", {binModel});
// std::shared_ptr producer = std::make_shared(prof,
// QFileInfo("../tests/small.mkv").absoluteFilePath().toStdString().c_str());
// In case the test system does not have avformat support, we can switch to the integrated blipflash producer
std::shared_ptr producer = std::make_shared(prof, "blipflash");
producer->set_in_and_out(0, 1);
producer->set("kdenlive:duration", 2);
Q_ASSERT(producer->is_valid());
QString binId = QString::number(binModel->getFreeClipId());
auto binClip = ProjectClip::construct(binId, QIcon(), binModel, producer);
Fun undo = []() { return true; };
Fun redo = []() { return true; };
Q_ASSERT(binModel->addItem(binClip, binModel->getRootFolder()->clipId(), undo, redo));
return binId;
}
inline int modulo(int a, int b)
{
const int result = a % b;
return result >= 0 ? result : result + b;
}
namespace {
bool isIthParamARef(const rttr::method &method, size_t i)
{
QString sig = QString::fromStdString(method.get_signature().to_string());
int deb = sig.indexOf("(");
int end = sig.lastIndexOf(")");
sig = sig.mid(deb + 1, deb - end - 1);
QStringList args = sig.split(QStringLiteral(","));
return args[(int)i].contains("&") && !args[(int)i].contains("const &");
}
} // namespace
} // namespace
void fuzz(const std::string &input)
{
Logger::init();
+ Logger::clear();
std::stringstream ss;
ss << input;
Mlt::Profile profile;
auto binModel = pCore->projectItemModel();
binModel->clean();
std::shared_ptr undoStack = std::make_shared(nullptr);
std::shared_ptr guideModel = std::make_shared(undoStack);
TimelineModel::next_id = 0;
Mock pmMock;
When(Method(pmMock, undoStack)).AlwaysReturn(undoStack);
ProjectManager &mocked = pmMock.get();
pCore->m_projectManager = &mocked;
std::vector> all_timelines;
std::unordered_map, std::vector> all_clips, all_tracks, all_compositions, all_groups;
auto update_elems = [&]() {
all_clips.clear();
all_tracks.clear();
all_compositions.clear();
for (const auto &timeline : all_timelines) {
all_clips[timeline] = {};
all_tracks[timeline] = {};
all_compositions[timeline] = {};
all_groups[timeline] = {};
auto &clips = all_clips[timeline];
clips.clear();
for (const auto &c : timeline->m_allClips) {
clips.push_back(c.first);
}
std::sort(clips.begin(), clips.end());
auto &compositions = all_compositions[timeline];
compositions.clear();
for (const auto &c : timeline->m_allCompositions) {
compositions.push_back(c.first);
}
std::sort(compositions.begin(), compositions.end());
auto &tracks = all_tracks[timeline];
tracks.clear();
for (const auto &c : timeline->m_iteratorTable) {
tracks.push_back(c.first);
}
std::sort(tracks.begin(), tracks.end());
auto &groups = all_groups[timeline];
groups.clear();
for (int c : timeline->m_allGroups) {
groups.push_back(c);
}
std::sort(groups.begin(), groups.end());
}
};
auto get_timeline = [&]() -> std::shared_ptr {
int id = 0;
ss >> id;
if (all_timelines.size() == 0) return nullptr;
id = modulo(id, (int)all_timelines.size());
return all_timelines[size_t(id)];
};
auto get_group = [&](std::shared_ptr timeline) {
int id = 0;
ss >> id;
if (!timeline) return -1;
if (timeline->isGroup(id)) return id;
if (all_timelines.size() == 0) return -1;
if (all_groups.count(timeline) == 0) return -1;
if (all_groups[timeline].size() == 0) return -1;
id = modulo(id, (int)all_groups[timeline].size());
return all_groups[timeline][id];
};
auto get_clip = [&](std::shared_ptr timeline) {
int id = 0;
ss >> id;
if (!timeline) return -1;
if (timeline->isClip(id)) return id;
if (all_timelines.size() == 0) return -1;
if (all_clips.count(timeline) == 0) return -1;
if (all_clips[timeline].size() == 0) return -1;
id = modulo(id, (int)all_clips[timeline].size());
return all_clips[timeline][id];
};
auto get_compo = [&](std::shared_ptr timeline) {
int id = 0;
ss >> id;
if (!timeline) return -1;
if (timeline->isComposition(id)) return id;
if (all_timelines.size() == 0) return -1;
if (all_compositions.count(timeline) == 0) return -1;
if (all_compositions[timeline].size() == 0) return -1;
id = modulo(id, (int)all_compositions[timeline].size());
return all_compositions[timeline][id];
};
auto get_item = [&](std::shared_ptr timeline) {
int id = 0;
ss >> id;
if (!timeline) return -1;
if (timeline->isClip(id)) return id;
if (timeline->isComposition(id)) return id;
if (all_timelines.size() == 0) return -1;
int clip_count = 0;
if (all_clips.count(timeline) > 0) {
clip_count = all_clips[timeline].size();
}
int compo_count = 0;
if (all_compositions.count(timeline) > 0) {
compo_count = all_compositions[timeline].size();
}
if (clip_count + compo_count == 0) return -1;
id = modulo(id, clip_count + compo_count);
if (id < clip_count) {
return all_clips[timeline][id];
}
return all_compositions[timeline][id - clip_count];
};
auto get_track = [&](std::shared_ptr timeline) {
int id = 0;
ss >> id;
if (!timeline) return -1;
if (timeline->isTrack(id)) return id;
if (all_timelines.size() == 0) return -1;
if (all_tracks.count(timeline) == 0) return -1;
if (all_tracks[timeline].size() == 0) return -1;
id = modulo(id, (int)all_tracks[timeline].size());
return all_tracks[timeline][id];
};
std::string c;
while (ss >> c) {
if (Logger::back_translation_table.count(c) > 0) {
// std::cout << "found=" << c;
c = Logger::back_translation_table[c];
// std::cout << " tranlated=" << c << std::endl;
if (c == "constr_TimelineModel") {
all_timelines.emplace_back(TimelineItemModel::construct(&profile, guideModel, undoStack));
} else if (c == "constr_TrackModel") {
auto timeline = get_timeline();
int id, pos = 0;
std::string name;
bool audio = false;
ss >> id >> pos >> name >> audio;
if (name == "$$") {
name = "";
}
if (pos < -1) pos = 0;
pos = std::min((int)all_tracks[timeline].size(), pos);
if (timeline) {
TrackModel::construct(timeline, -1, pos, QString::fromStdString(name), audio);
}
} else if (c == "constr_test_producer") {
std::string color;
int length = 0;
bool limited = false;
ss >> color >> length >> limited;
createProducer(profile, color, binModel, length, limited);
} else if (c == "constr_test_producer_sound") {
createProducerWithSound(profile, binModel);
} else {
// std::cout << "executing " << c << std::endl;
rttr::type target_type = rttr::type::get();
bool found = false;
for (const std::string &t : {"TimelineModel"}) {
rttr::type current_type = rttr::type::get_by_name(t);
// std::cout << "type " << t << " has methods count=" << current_type.get_methods().size() << std::endl;
if (current_type.get_method(c).is_valid()) {
found = true;
target_type = current_type;
break;
}
}
if (found) {
bool valid = true;
rttr::method target_method = target_type.get_method(c);
std::vector arguments;
rttr::variant ptr;
if (target_type == rttr::type::get()) {
if (all_timelines.size() == 0) {
valid = false;
}
ptr = get_timeline();
}
int i = -1;
for (const auto &p : target_method.get_parameter_infos()) {
++i;
std::string arg_name = p.get_name().to_string();
// std::cout << arg_name << std::endl;
if (arg_name == "compoId") {
std::shared_ptr tim =
(ptr.can_convert>() ? ptr.convert>() : nullptr);
int compoId = get_compo(tim);
valid = valid && (compoId >= 0);
// std::cout << "got compo" << compoId << std::endl;
arguments.emplace_back(compoId);
} else if (arg_name == "clipId") {
std::shared_ptr tim =
(ptr.can_convert>() ? ptr.convert>() : nullptr);
int clipId = get_clip(tim);
valid = valid && (clipId >= 0);
arguments.emplace_back(clipId);
// std::cout << "got clipId" << clipId << std::endl;
} else if (arg_name == "trackId") {
std::shared_ptr tim =
(ptr.can_convert>() ? ptr.convert>() : nullptr);
int trackId = get_track(tim);
valid = valid && (trackId >= 0);
arguments.emplace_back(trackId);
// std::cout << "got trackId" << trackId << std::endl;
} else if (arg_name == "itemId") {
std::shared_ptr tim =
(ptr.can_convert>() ? ptr.convert>() : nullptr);
int itemId = get_item(tim);
valid = valid && (itemId >= 0);
arguments.emplace_back(itemId);
// std::cout << "got itemId" << itemId << std::endl;
} else if (arg_name == "groupId") {
std::shared_ptr tim =
(ptr.can_convert>() ? ptr.convert>() : nullptr);
int groupId = get_group(tim);
valid = valid && (groupId >= 0);
arguments.emplace_back(groupId);
// std::cout << "got clipId" << clipId << std::endl;
} else if (arg_name == "itemIds") {
int count = 0;
ss >> count;
// std::cout << "got ids. going to read count=" << count << std::endl;
if (count > 0) {
std::shared_ptr tim =
(ptr.can_convert>() ? ptr.convert>() : nullptr);
std::unordered_set ids;
for (int i = 0; i < count; ++i) {
int itemId = get_item(tim);
// std::cout << "\t read" << itemId << std::endl;
valid = valid && (itemId >= 0);
ids.insert(itemId);
}
arguments.emplace_back(ids);
} else {
valid = false;
}
} else if (!isIthParamARef(target_method, i)) {
rttr::type arg_type = p.get_type();
if (arg_type == rttr::type::get()) {
int a = 0;
ss >> a;
// std::cout << "read int " << a << std::endl;
arguments.emplace_back(a);
} else if (arg_type == rttr::type::get()) {
bool a = false;
ss >> a;
// std::cout << "read bool " << a << std::endl;
arguments.emplace_back(a);
} else if (arg_type == rttr::type::get()) {
std::string str = "";
ss >> str;
// std::cout << "read str " << str << std::endl;
if (str == "$$") {
str = "";
}
arguments.emplace_back(QString::fromStdString(str));
} else if (arg_type.is_enumeration()) {
int a = 0;
ss >> a;
rttr::variant var_a = a;
var_a.convert((const rttr::type &)arg_type);
// std::cout << "read enum " << arg_type.get_enumeration().value_to_name(var_a).to_string() << std::endl;
arguments.push_back(var_a);
} else {
assert(false);
}
} else {
if (p.get_type() == rttr::type::get()) {
arguments.emplace_back(-1);
} else {
assert(false);
}
}
}
if (valid) {
// std::cout << "VALID!!!" << std::endl;
std::vector args;
args.reserve(arguments.size());
for (const auto &a : arguments) {
args.emplace_back(a);
// std::cout<<"argument="<checkConsistency());
}
}
}
all_clips.clear();
all_tracks.clear();
all_compositions.clear();
all_groups.clear();
for (auto &all_timeline : all_timelines) {
all_timeline.reset();
}
pCore->m_projectManager = nullptr;
Core::m_self.reset();
MltConnection::m_self.reset();
std::cout << "---------------------------------------------------------------------------------------------------------------------------------------------"
"---------------"
<< std::endl;
}
diff --git a/src/logger.cpp b/src/logger.cpp
index a6930c62c..b06f84eaa 100644
--- a/src/logger.cpp
+++ b/src/logger.cpp
@@ -1,381 +1,382 @@
/***************************************************************************
* 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 . *
***************************************************************************/
#include "logger.hpp"
#include "bin/projectitemmodel.h"
#include "timeline2/model/timelinemodel.hpp"
#include
#include
#include
#include
#include
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wpedantic"
#include
#pragma GCC diagnostic pop
thread_local bool Logger::is_executing = false;
std::mutex Logger::mut;
std::vector Logger::operations;
std::vector Logger::invoks;
std::unordered_map> Logger::constr;
std::unordered_map Logger::translation_table;
std::unordered_map Logger::back_translation_table;
int Logger::dump_count = 0;
thread_local size_t Logger::result_awaiting = INT_MAX;
void Logger::init()
{
std::string cur_ind = "a";
auto incr_ind = [&](auto &&self, size_t i = 0) {
if (i >= cur_ind.size()) {
cur_ind += "a";
return;
}
if (cur_ind[i] == 'z') {
cur_ind[i] = 'A';
} else if (cur_ind[i] == 'Z') {
cur_ind[i] = 'a';
self(self, i + 1);
} else {
cur_ind[i]++;
}
};
for (const auto &o : {"TimelineModel", "TrackModel", "test_producer", "test_producer_sound"}) {
translation_table[std::string("constr_") + o] = cur_ind;
incr_ind(incr_ind);
}
for (const auto &m : rttr::type::get().get_methods()) {
translation_table[m.get_name().to_string()] = cur_ind;
incr_ind(incr_ind);
}
for (const auto &i : translation_table) {
back_translation_table[i.second] = i.first;
}
}
bool Logger::start_logging()
{
std::unique_lock lk(mut);
if (is_executing) {
return false;
}
is_executing = true;
return true;
}
void Logger::stop_logging()
{
std::unique_lock lk(mut);
is_executing = false;
}
std::string Logger::get_ptr_name(const rttr::variant &ptr)
{
if (ptr.can_convert()) {
return "timeline_" + std::to_string(get_id_from_ptr(ptr.convert()));
} else if (ptr.can_convert()) {
return "binModel";
} else {
std::cout << "Error: unhandled ptr type " << ptr.get_type().get_name().to_string() << std::endl;
}
return "unknown";
}
void Logger::log_res(rttr::variant result)
{
std::unique_lock lk(mut);
Q_ASSERT(result_awaiting < invoks.size());
invoks[result_awaiting].res = std::move(result);
}
void Logger::log_create_producer(const std::string &type, std::vector args)
{
std::unique_lock lk(mut);
for (auto &a : args) {
// this will rewove shared/weak/unique ptrs
if (a.get_type().is_wrapper()) {
a = a.extract_wrapped_value();
}
const std::string class_name = a.get_type().get_name().to_string();
}
constr[type].push_back({type, std::move(args)});
operations.emplace_back(ConstrId{type, constr[type].size() - 1});
}
namespace {
bool isIthParamARef(const rttr::method &method, size_t i)
{
QString sig = QString::fromStdString(method.get_signature().to_string());
int deb = sig.indexOf("(");
int end = sig.lastIndexOf(")");
sig = sig.mid(deb + 1, deb - end - 1);
QStringList args = sig.split(QStringLiteral(","));
return args[(int)i].contains("&") && !args[(int)i].contains("const &");
}
std::string quoted(const std::string &input)
{
#if __cpp_lib_quoted_string_io
std::stringstream ss;
ss << std::quoted(input);
return ss.str();
#else
// very incomplete implem
return "\"" + input + "\"";
#endif
}
} // namespace
void Logger::print_trace()
{
dump_count++;
auto process_args = [&](const std::vector &args, const std::unordered_set &refs = {}) {
std::stringstream ss;
bool deb = true;
size_t i = 0;
for (const auto &a : args) {
if (deb) {
deb = false;
i = 0;
} else {
ss << ", ";
++i;
}
if (refs.count(i) > 0) {
ss << "dummy_" << i;
} else if (a.get_type() == rttr::type::get()) {
ss << a.convert();
} else if (a.get_type() == rttr::type::get()) {
ss << (a.convert() ? "true" : "false");
} else if (a.get_type().is_enumeration()) {
auto e = a.get_type().get_enumeration();
ss << e.get_name().to_string() << "::" << a.convert();
} else if (a.can_convert()) {
ss << quoted(a.convert().toStdString());
} else if (a.can_convert()) {
ss << quoted(a.convert());
} else if (a.can_convert>()) {
auto set = a.convert>();
ss << "{";
bool beg = true;
for (int s : set) {
if (beg)
beg = false;
else
ss << ", ";
ss << s;
}
ss << "}";
} else if (a.get_type().is_pointer()) {
ss << get_ptr_name(a);
} else {
std::cout << "Error: unhandled arg type " << a.get_type().get_name().to_string() << std::endl;
}
}
return ss.str();
};
auto process_args_fuzz = [&](const std::vector &args, const std::unordered_set &refs = {}) {
std::stringstream ss;
bool deb = true;
size_t i = 0;
for (const auto &a : args) {
if (deb) {
deb = false;
i = 0;
} else {
ss << " ";
++i;
}
if (refs.count(i) > 0) {
continue;
} else if (a.get_type() == rttr::type::get()) {
ss << a.convert();
} else if (a.get_type() == rttr::type::get()) {
ss << (a.convert() ? "1" : "0");
} else if (a.get_type().is_enumeration()) {
ss << a.convert();
} else if (a.can_convert()) {
std::string out = a.convert().toStdString();
if (out.empty()) {
out = "$$";
}
ss << out;
} else if (a.can_convert()) {
std::string out = a.convert();
if (out.empty()) {
out = "$$";
}
ss << out;
} else if (a.can_convert>()) {
auto set = a.convert>();
ss << set.size() << " ";
bool beg = true;
for (int s : set) {
if (beg)
beg = false;
else
ss << " ";
ss << s;
}
} else if (a.get_type().is_pointer()) {
if (a.can_convert()) {
ss << get_id_from_ptr(a.convert());
} else if (a.can_convert()) {
// only one binModel, we skip the parameter since it's unambiguous
} else {
std::cout << "Error: unhandled ptr type " << a.get_type().get_name().to_string() << std::endl;
}
} else {
std::cout << "Error: unhandled arg type " << a.get_type().get_name().to_string() << std::endl;
}
}
return ss.str();
};
std::ofstream fuzz_file;
fuzz_file.open("fuzz_case_" + std::to_string(dump_count) + ".txt");
std::ofstream test_file;
test_file.open("test_case_" + std::to_string(dump_count) + ".cpp");
test_file << "TEST_CASE(\"Regression\") {" << std::endl;
test_file << "auto binModel = pCore->projectItemModel();" << std::endl;
test_file << "binModel->clean();" << std::endl;
test_file << "std::shared_ptr undoStack = std::make_shared(nullptr);" << std::endl;
test_file << "std::shared_ptr guideModel = std::make_shared(undoStack);" << std::endl;
test_file << "TimelineModel::next_id = 0;" << std::endl;
test_file << "{" << std::endl;
test_file << "Mock pmMock;" << std::endl;
test_file << "When(Method(pmMock, undoStack)).AlwaysReturn(undoStack);" << std::endl;
test_file << "ProjectManager &mocked = pmMock.get();" << std::endl;
test_file << "pCore->m_projectManager = &mocked;" << std::endl;
auto check_consistancy = [&]() {
if (constr.count("TimelineModel") > 0) {
for (size_t i = 0; i < constr["TimelineModel"].size(); ++i) {
test_file << "REQUIRE(timeline_" << i << "->checkConsistency());" << std::endl;
}
}
};
for (const auto &o : operations) {
if (o.can_convert()) {
InvokId id = o.convert();
Invok &invok = invoks[id.id];
std::unordered_set refs;
rttr::method m = invok.ptr.get_type().get_method(invok.method);
test_file << "{" << std::endl;
for (const auto &a : m.get_parameter_infos()) {
if (isIthParamARef(m, a.get_index())) {
refs.insert(a.get_index());
test_file << a.get_type().get_name().to_string() << " dummy_" << std::to_string(a.get_index()) << ";" << std::endl;
}
}
if (m.get_return_type() != rttr::type::get()) {
test_file << m.get_return_type().get_name().to_string() << " res = ";
}
test_file << get_ptr_name(invok.ptr) << "->" << invok.method << "(" << process_args(invok.args, refs) << ");" << std::endl;
if (m.get_return_type() != rttr::type::get() && invok.res.is_valid()) {
test_file << "REQUIRE( res == " << invok.res.to_string() << ");" << std::endl;
}
test_file << "}" << std::endl;
std::string invok_name = invok.method;
if (translation_table.count(invok_name) > 0) {
auto args = invok.args;
if (rttr::type::get().get_method(invok_name).is_valid()) {
args.insert(args.begin(), invok.ptr);
// adding an arg just messed up the references
std::unordered_set 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;
}
} else if (o.can_convert()) {
ConstrId id = o.convert();
std::string constr_name = std::string("constr_") + id.type;
if (translation_table.count(constr_name) > 0) {
fuzz_file << translation_table[constr_name] << " " << process_args_fuzz(constr[id.type][id.id].second) << std::endl;
} else {
std::cout << "ERROR: unknown constructor " << constr_name << std::endl;
}
if (id.type == "TimelineModel") {
test_file << "TimelineItemModel tim_" << id.id << "(®_profile, undoStack);" << std::endl;
test_file << "Mock timMock_" << id.id << "(tim_" << id.id << ");" << std::endl;
test_file << "auto timeline_" << id.id << " = std::shared_ptr(&timMock_" << id.id << ".get(), [](...) {});" << std::endl;
test_file << "TimelineItemModel::finishConstruct(timeline_" << id.id << ", guideModel);" << std::endl;
test_file << "Fake(Method(timMock_" << id.id << ", adjustAssetRange));" << std::endl;
} else if (id.type == "TrackModel") {
std::string params = process_args(constr[id.type][id.id].second);
test_file << "TrackModel::construct(" << params << ");" << std::endl;
} else if (id.type == "test_producer") {
std::string params = process_args(constr[id.type][id.id].second);
test_file << "createProducer(reg_profile, " << params << ");" << std::endl;
} else if (id.type == "test_producer_sound") {
std::string params = process_args(constr[id.type][id.id].second);
test_file << "createProducerWithSound(reg_profile, " << params << ");" << std::endl;
} else {
std::cout << "Error: unknown constructor " << id.type << std::endl;
}
} else {
std::cout << "Error: unknown operation" << std::endl;
}
check_consistancy();
test_file << "undoStack->undo();" << std::endl;
check_consistancy();
test_file << "undoStack->redo();" << std::endl;
check_consistancy();
}
test_file << "}" << std::endl;
test_file << "pCore->m_projectManager = nullptr;" << std::endl;
test_file << "}" << std::endl;
}
void Logger::clear()
{
is_executing = false;
invoks.clear();
operations.clear();
+ constr.clear();
}
LogGuard::LogGuard()
{
m_hasGuard = Logger::start_logging();
}
LogGuard::~LogGuard()
{
if (m_hasGuard) {
Logger::stop_logging();
}
}
bool LogGuard::hasGuard() const
{
return m_hasGuard;
}