mirror of
https://github.com/status-im/realm-js.git
synced 2025-02-25 12:45:32 +00:00
Refactor the fuzzer a bit
This commit is contained in:
parent
edc0d1fc4a
commit
47cee90d32
@ -1,2 +1,5 @@
|
|||||||
add_executable(fuzzer fuzzer.cpp)
|
add_executable(fuzzer
|
||||||
|
command_file.hpp
|
||||||
|
command_file.cpp
|
||||||
|
fuzzer.cpp)
|
||||||
target_link_libraries(fuzzer realm-object-store)
|
target_link_libraries(fuzzer realm-object-store)
|
||||||
|
222
fuzzer/command_file.cpp
Normal file
222
fuzzer/command_file.cpp
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
#include "command_file.hpp"
|
||||||
|
|
||||||
|
#include "impl/realm_coordinator.hpp"
|
||||||
|
#include "shared_realm.hpp"
|
||||||
|
|
||||||
|
#include <realm/link_view.hpp>
|
||||||
|
#include <realm/table.hpp>
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
|
||||||
|
using namespace fuzzer;
|
||||||
|
using namespace realm;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define log(...) fprintf(stderr, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define log(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static T read_value(std::istream& input)
|
||||||
|
{
|
||||||
|
T ret;
|
||||||
|
input >> ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
static auto make_reader(void (*fn)(RealmState&, Args...)) {
|
||||||
|
return [=](std::istream& input) {
|
||||||
|
return std::bind(fn, std::placeholders::_1, read_value<Args>(input)...);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_add(RealmState& state, int64_t value)
|
||||||
|
{
|
||||||
|
log("add %lld\n", value);
|
||||||
|
size_t ndx = state.table.add_empty_row();
|
||||||
|
state.table.set_int(0, ndx, state.uid++);
|
||||||
|
state.table.set_int(1, ndx, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_modify(RealmState& state, size_t index, int64_t value)
|
||||||
|
{
|
||||||
|
if (index < state.table.size()) {
|
||||||
|
log("modify %zu %lld\n", index, value);
|
||||||
|
state.table.set_int(1, index, value);
|
||||||
|
state.modified.push_back(state.table.get_int(0, index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_delete(RealmState& state, size_t index)
|
||||||
|
{
|
||||||
|
if (index < state.table.size()) {
|
||||||
|
log("delete %zu\n", index);
|
||||||
|
state.table.move_last_over(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_commit(RealmState& state)
|
||||||
|
{
|
||||||
|
log("commit\n");
|
||||||
|
state.realm.commit_transaction();
|
||||||
|
state.coordinator.on_change();
|
||||||
|
state.realm.begin_transaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_lv_insert(RealmState& state, size_t pos, size_t target)
|
||||||
|
{
|
||||||
|
if (target < state.table.size() && pos <= state.lv->size()) {
|
||||||
|
log("lv insert %zu %zu\n", pos, target);
|
||||||
|
state.lv->insert(pos, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_lv_set(RealmState& state, size_t pos, size_t target)
|
||||||
|
{
|
||||||
|
if (target < state.table.size() && pos < state.lv->size()) {
|
||||||
|
log("lv set %zu %zu\n", pos, target);
|
||||||
|
// We can't reliably detect self-assignment for verification, so don't do it
|
||||||
|
if (state.lv->get(pos).get_index() != target)
|
||||||
|
state.lv->set(pos, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_lv_move(RealmState& state, size_t from, size_t to)
|
||||||
|
{
|
||||||
|
if (from < state.lv->size() && to < state.lv->size()) {
|
||||||
|
log("lv move %zu %zu\n", from, to);
|
||||||
|
// FIXME: only do the move if it has an effect to avoid getting a
|
||||||
|
// notification which we weren't expecting. This is really urgh.
|
||||||
|
for (size_t i = std::min(from, to); i < std::max(from, to); ++i) {
|
||||||
|
if (state.lv->get(i).get_index() != state.lv->get(i + 1).get_index()) {
|
||||||
|
state.lv->move(from, to);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_lv_swap(RealmState& state, size_t ndx1, size_t ndx2)
|
||||||
|
{
|
||||||
|
if (ndx1 < state.lv->size() && ndx2 < state.lv->size()) {
|
||||||
|
log("lv swap %zu %zu\n", ndx1, ndx2);
|
||||||
|
if (state.lv->get(ndx1).get_index() != state.lv->get(ndx2).get_index()) {
|
||||||
|
state.lv->swap(ndx1, ndx2);
|
||||||
|
// FIXME: swap() needs to produce moves so that a pair of swaps can
|
||||||
|
// be collapsed away. Currently it just marks the rows as modified.
|
||||||
|
state.modified.push_back(state.lv->get(ndx1).get_int(0));
|
||||||
|
state.modified.push_back(state.lv->get(ndx2).get_int(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_lv_remove(RealmState& state, size_t pos)
|
||||||
|
{
|
||||||
|
if (pos < state.lv->size()) {
|
||||||
|
log("lv remove %zu\n", pos);
|
||||||
|
state.lv->remove(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_lv_remove_target(RealmState& state, size_t pos)
|
||||||
|
{
|
||||||
|
if (pos < state.lv->size()) {
|
||||||
|
log("lv target remove %zu\n", pos);
|
||||||
|
state.lv->remove_target_row(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::map<char, std::function<std::function<void (RealmState&)>(std::istream&)>> readers = {
|
||||||
|
// Row functions
|
||||||
|
{'a', make_reader(run_add)},
|
||||||
|
{'c', make_reader(run_commit)},
|
||||||
|
{'d', make_reader(run_delete)},
|
||||||
|
{'m', make_reader(run_modify)},
|
||||||
|
|
||||||
|
// LinkView functions
|
||||||
|
{'i', make_reader(run_lv_insert)},
|
||||||
|
{'s', make_reader(run_lv_set)},
|
||||||
|
{'o', make_reader(run_lv_move)},
|
||||||
|
{'w', make_reader(run_lv_swap)},
|
||||||
|
{'r', make_reader(run_lv_remove)},
|
||||||
|
{'t', make_reader(run_lv_remove_target)},
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static std::vector<T> read_int_list(std::istream& input_stream)
|
||||||
|
{
|
||||||
|
std::vector<T> ret;
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(input_stream, line) && !line.empty()) {
|
||||||
|
try {
|
||||||
|
ret.push_back(std::stoll(line));
|
||||||
|
log("%lld\n", (long long)ret.back());
|
||||||
|
}
|
||||||
|
catch (std::invalid_argument) {
|
||||||
|
// not an error
|
||||||
|
}
|
||||||
|
catch (std::out_of_range) {
|
||||||
|
// not an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandFile::CommandFile(std::istream& input)
|
||||||
|
: initial_values(read_int_list<int64_t>(input))
|
||||||
|
, initial_list_indices(read_int_list<size_t>(input))
|
||||||
|
{
|
||||||
|
if (!input.good())
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (input.good()) {
|
||||||
|
char op = '\0';
|
||||||
|
input >> op;
|
||||||
|
if (!input.good())
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto it = readers.find(op);
|
||||||
|
if (it == readers.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto fn = it->second(input);
|
||||||
|
if (!input.good())
|
||||||
|
return;
|
||||||
|
commands.push_back(std::move(fn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandFile::import(RealmState& state)
|
||||||
|
{
|
||||||
|
auto& table = state.table;
|
||||||
|
|
||||||
|
state.realm.begin_transaction();
|
||||||
|
|
||||||
|
table.clear();
|
||||||
|
size_t ndx = table.add_empty_row(initial_values.size());
|
||||||
|
for (auto value : initial_values) {
|
||||||
|
table.set_int(0, ndx, state.uid++);
|
||||||
|
table.set_int(1, ndx++, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.lv->clear();
|
||||||
|
for (auto value : initial_list_indices) {
|
||||||
|
if (value < table.size())
|
||||||
|
state.lv->add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.realm.commit_transaction();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandFile::run(RealmState& state)
|
||||||
|
{
|
||||||
|
state.realm.begin_transaction();
|
||||||
|
for (auto& command : commands) {
|
||||||
|
command(state);
|
||||||
|
}
|
||||||
|
state.realm.commit_transaction();
|
||||||
|
}
|
38
fuzzer/command_file.hpp
Normal file
38
fuzzer/command_file.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include <realm/link_view_fwd.hpp>
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace realm {
|
||||||
|
class Table;
|
||||||
|
class LinkView;
|
||||||
|
class Realm;
|
||||||
|
namespace _impl {
|
||||||
|
class RealmCoordinator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace fuzzer {
|
||||||
|
struct RealmState {
|
||||||
|
realm::Realm& realm;
|
||||||
|
realm::_impl::RealmCoordinator& coordinator;
|
||||||
|
|
||||||
|
realm::Table& table;
|
||||||
|
realm::LinkViewRef lv;
|
||||||
|
int64_t uid = 0;
|
||||||
|
std::vector<int64_t> modified;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommandFile {
|
||||||
|
std::vector<int64_t> initial_values;
|
||||||
|
std::vector<size_t> initial_list_indices;
|
||||||
|
std::vector<std::function<void (RealmState&)>> commands;
|
||||||
|
|
||||||
|
CommandFile(std::istream& input);
|
||||||
|
|
||||||
|
void import(RealmState& state);
|
||||||
|
void run(RealmState& state);
|
||||||
|
};
|
||||||
|
}
|
@ -1,3 +1,6 @@
|
|||||||
|
#include "command_file.hpp"
|
||||||
|
|
||||||
|
#include "list.hpp"
|
||||||
#include "object_schema.hpp"
|
#include "object_schema.hpp"
|
||||||
#include "property.hpp"
|
#include "property.hpp"
|
||||||
#include "results.hpp"
|
#include "results.hpp"
|
||||||
@ -10,22 +13,15 @@
|
|||||||
#include <realm/link_view.hpp>
|
#include <realm/link_view.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <set>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <strstream>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
using namespace realm;
|
using namespace realm;
|
||||||
|
|
||||||
#define FUZZ_SORTED 1
|
#define FUZZ_SORTED 0
|
||||||
|
#define FUZZ_LINKVIEW 1
|
||||||
#if 0
|
|
||||||
#define log(...) fprintf(stderr, __VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define log(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Read from a fd until eof into a string
|
// Read from a fd until eof into a string
|
||||||
// Needs to use unbuffered i/o to work properly with afl
|
// Needs to use unbuffered i/o to work properly with afl
|
||||||
@ -44,160 +40,32 @@ static void read_all(std::string& buffer, int fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<int64_t> read_initial_values(std::istream& input_stream)
|
static Query query(fuzzer::RealmState& state)
|
||||||
{
|
{
|
||||||
std::vector<int64_t> initial_values;
|
#if FUZZ_LINKVIEW
|
||||||
std::string line;
|
return state.table.where(state.lv);
|
||||||
input_stream.seekg(0);
|
#else
|
||||||
while (std::getline(input_stream, line) && !line.empty()) {
|
return state.table.where().greater(1, 100).less(1, 50000);
|
||||||
try {
|
#endif
|
||||||
initial_values.push_back(std::stoll(line));
|
|
||||||
}
|
|
||||||
catch (std::invalid_argument) {
|
|
||||||
// not an error
|
|
||||||
}
|
|
||||||
catch (std::out_of_range) {
|
|
||||||
// not an error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return initial_values;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Change {
|
static TableView tableview(fuzzer::RealmState& state)
|
||||||
enum class Action {
|
|
||||||
Commit,
|
|
||||||
Add,
|
|
||||||
Modify,
|
|
||||||
Delete
|
|
||||||
} action;
|
|
||||||
|
|
||||||
size_t index = npos;
|
|
||||||
int64_t value = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::vector<Change> read_changes(std::istream& input_stream)
|
|
||||||
{
|
{
|
||||||
std::vector<Change> ret;
|
auto tv = query(state).find_all();
|
||||||
|
|
||||||
while (!input_stream.eof()) {
|
|
||||||
char op = '\0';
|
|
||||||
input_stream >> op;
|
|
||||||
if (!input_stream.good())
|
|
||||||
break;
|
|
||||||
switch (op) {
|
|
||||||
case 'a': {
|
|
||||||
int64_t value = 0;
|
|
||||||
input_stream >> value;
|
|
||||||
if (input_stream.good())
|
|
||||||
ret.push_back({Change::Action::Add, npos, value});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'm': {
|
|
||||||
int64_t value;
|
|
||||||
size_t ndx;
|
|
||||||
input_stream >> ndx >> value;
|
|
||||||
if (input_stream.good())
|
|
||||||
ret.push_back({Change::Action::Modify, ndx, value});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'd': {
|
|
||||||
size_t ndx;
|
|
||||||
input_stream >> ndx;
|
|
||||||
if (input_stream.good())
|
|
||||||
ret.push_back({Change::Action::Delete, ndx, 0});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'c': {
|
|
||||||
ret.push_back({Change::Action::Commit, npos, 0});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Query query(Table& table)
|
|
||||||
{
|
|
||||||
return table.where().greater(1, 100).less(1, 50000);
|
|
||||||
}
|
|
||||||
|
|
||||||
static TableView tableview(Table& table)
|
|
||||||
{
|
|
||||||
auto tv = table.where().greater(1, 100).less(1, 50000).find_all();
|
|
||||||
#if FUZZ_SORTED
|
#if FUZZ_SORTED
|
||||||
tv.sort({1, 0}, {true, true});
|
tv.sort({1, 0}, {true, true});
|
||||||
#endif
|
#endif
|
||||||
return tv;
|
return tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t id = 0;
|
|
||||||
|
|
||||||
static void import_initial_values(SharedRealm& r, std::vector<int64_t>& initial_values)
|
|
||||||
{
|
|
||||||
auto& table = *r->read_group()->get_table("class_object");
|
|
||||||
|
|
||||||
r->begin_transaction();
|
|
||||||
table.clear();
|
|
||||||
size_t ndx = table.add_empty_row(initial_values.size());
|
|
||||||
for (auto value : initial_values) {
|
|
||||||
table.set_int(0, ndx, id++);
|
|
||||||
table.set_int(1, ndx++, value);
|
|
||||||
log("%lld\n", value);
|
|
||||||
}
|
|
||||||
r->commit_transaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the changes from the command file and then return whether a change
|
// Apply the changes from the command file and then return whether a change
|
||||||
// notification should occur
|
// notification should occur
|
||||||
static bool apply_changes(Realm& r, std::istream& input_stream)
|
static bool apply_changes(fuzzer::CommandFile& commands, fuzzer::RealmState& state)
|
||||||
{
|
{
|
||||||
auto& table = *r.read_group()->get_table("class_object");
|
auto tv = tableview(state);
|
||||||
auto tv = tableview(table);
|
commands.run(state);
|
||||||
|
|
||||||
std::vector<int64_t> modified;
|
auto tv2 = tableview(state);
|
||||||
|
|
||||||
log("\n");
|
|
||||||
r.begin_transaction();
|
|
||||||
for (auto const& change : read_changes(input_stream)) {
|
|
||||||
switch (change.action) {
|
|
||||||
case Change::Action::Commit:
|
|
||||||
log("c\n");
|
|
||||||
r.commit_transaction();
|
|
||||||
_impl::RealmCoordinator::get_existing_coordinator(r.config().path)->on_change();
|
|
||||||
r.begin_transaction();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Change::Action::Add: {
|
|
||||||
log("a %lld\n", change.value);
|
|
||||||
size_t ndx = table.add_empty_row();
|
|
||||||
table.set_int(0, ndx, id++);
|
|
||||||
table.set_int(1, ndx, change.value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Change::Action::Modify:
|
|
||||||
if (change.index < table.size()) {
|
|
||||||
log("m %zu %lld\n", change.index, change.value);
|
|
||||||
modified.push_back(table.get_int(0, change.index));
|
|
||||||
table.set_int(1, change.index, change.value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Change::Action::Delete:
|
|
||||||
if (change.index < table.size()) {
|
|
||||||
log("d %zu\n", change.index);
|
|
||||||
table.move_last_over(change.index);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.commit_transaction();
|
|
||||||
log("\n");
|
|
||||||
|
|
||||||
auto tv2 = tableview(table);
|
|
||||||
if (tv.size() != tv2.size())
|
if (tv.size() != tv2.size())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -206,16 +74,16 @@ static bool apply_changes(Realm& r, std::istream& input_stream)
|
|||||||
return true;
|
return true;
|
||||||
if (tv.get_int(0, i) != tv2.get_int(0, i))
|
if (tv.get_int(0, i) != tv2.get_int(0, i))
|
||||||
return true;
|
return true;
|
||||||
if (find(begin(modified), end(modified), tv.get_int(0, i)) != end(modified))
|
if (find(begin(state.modified), end(state.modified), tv.get_int(0, i)) != end(state.modified))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verify(CollectionChangeIndices const& changes, std::vector<int64_t> values, Table& table)
|
static void verify(CollectionChangeIndices const& changes, std::vector<int64_t> values, fuzzer::RealmState& state)
|
||||||
{
|
{
|
||||||
auto tv = tableview(table);
|
auto tv = tableview(state);
|
||||||
|
|
||||||
// Apply the changes from the transaction log to our copy of the
|
// Apply the changes from the transaction log to our copy of the
|
||||||
// initial, using UITableView's batching rules (i.e. delete, then
|
// initial, using UITableView's batching rules (i.e. delete, then
|
||||||
@ -253,20 +121,41 @@ static void verify(CollectionChangeIndices const& changes, std::vector<int64_t>
|
|||||||
|
|
||||||
static void test(Realm::Config const& config, SharedRealm& r, SharedRealm& r2, std::istream& input_stream)
|
static void test(Realm::Config const& config, SharedRealm& r, SharedRealm& r2, std::istream& input_stream)
|
||||||
{
|
{
|
||||||
std::vector<int64_t> initial_values = read_initial_values(input_stream);
|
fuzzer::RealmState state = {
|
||||||
if (initial_values.empty()) {
|
*r,
|
||||||
|
*_impl::RealmCoordinator::get_existing_coordinator(r->config().path),
|
||||||
|
*r->read_group()->get_table("class_object"),
|
||||||
|
r->read_group()->get_table("class_linklist")->get_linklist(0, 0),
|
||||||
|
0,
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
fuzzer::CommandFile command(input_stream);
|
||||||
|
if (command.initial_values.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
import_initial_values(r, initial_values);
|
command.import(state);
|
||||||
|
|
||||||
auto& table = *r->read_group()->get_table("class_object");
|
fuzzer::RealmState state2 = {
|
||||||
auto results = Results(r, ObjectSchema(), query(table))
|
*r2,
|
||||||
|
state.coordinator,
|
||||||
|
*r2->read_group()->get_table("class_object"),
|
||||||
|
r2->read_group()->get_table("class_linklist")->get_linklist(0, 0),
|
||||||
|
state.uid,
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if FUZZ_LINKVIEW && !FUZZ_SORTED
|
||||||
|
auto results = List(r, ObjectSchema(), state.lv);
|
||||||
|
#else
|
||||||
|
auto results = Results(r, ObjectSchema(), query(state))
|
||||||
#if FUZZ_SORTED
|
#if FUZZ_SORTED
|
||||||
.sort({{1, 0}, {true, true}})
|
.sort({{1, 0}, {true, true}})
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
#endif // FUZZ_LINKVIEW
|
||||||
|
|
||||||
initial_values.clear();
|
std::vector<int64_t> initial_values;
|
||||||
for (size_t i = 0; i < results.size(); ++i)
|
for (size_t i = 0; i < results.size(); ++i)
|
||||||
initial_values.push_back(results.get(i).get_int(1));
|
initial_values.push_back(results.get(i).get_int(1));
|
||||||
|
|
||||||
@ -279,20 +168,19 @@ static void test(Realm::Config const& config, SharedRealm& r, SharedRealm& r2, s
|
|||||||
++notification_calls;
|
++notification_calls;
|
||||||
});
|
});
|
||||||
|
|
||||||
auto& coordinator = *_impl::RealmCoordinator::get_existing_coordinator(config.path);
|
state.coordinator.on_change(); r->notify();
|
||||||
coordinator.on_change(); r->notify();
|
|
||||||
if (notification_calls != 1) {
|
if (notification_calls != 1) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool expect_notification = apply_changes(*r2, input_stream);
|
bool expect_notification = apply_changes(command, state2);
|
||||||
coordinator.on_change(); r->notify();
|
state.coordinator.on_change(); r->notify();
|
||||||
|
|
||||||
if (notification_calls != 1 + expect_notification) {
|
if (notification_calls != 1 + expect_notification) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(changes, initial_values, table);
|
verify(changes, initial_values, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
@ -311,6 +199,9 @@ int main(int argc, char** argv) {
|
|||||||
{"object", "", {
|
{"object", "", {
|
||||||
{"id", PropertyTypeInt},
|
{"id", PropertyTypeInt},
|
||||||
{"value", PropertyTypeInt}
|
{"value", PropertyTypeInt}
|
||||||
|
}},
|
||||||
|
{"linklist", "", {
|
||||||
|
{"list", PropertyTypeArray, "object"}
|
||||||
}}
|
}}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -321,9 +212,11 @@ int main(int argc, char** argv) {
|
|||||||
auto r2 = Realm::get_shared_realm(config);
|
auto r2 = Realm::get_shared_realm(config);
|
||||||
auto& coordinator = *_impl::RealmCoordinator::get_existing_coordinator(config.path);
|
auto& coordinator = *_impl::RealmCoordinator::get_existing_coordinator(config.path);
|
||||||
|
|
||||||
auto test_on = [&](auto& buffer) {
|
r->begin_transaction();
|
||||||
id = 0;
|
r->read_group()->get_table("class_linklist")->add_empty_row();
|
||||||
|
r->commit_transaction();
|
||||||
|
|
||||||
|
auto test_on = [&](auto& buffer) {
|
||||||
std::istringstream ss(buffer);
|
std::istringstream ss(buffer);
|
||||||
test(config, r, r2, ss);
|
test(config, r, r2, ss);
|
||||||
if (r->is_in_transaction())
|
if (r->is_in_transaction())
|
||||||
|
38
fuzzer/input-lv/0
Normal file
38
fuzzer/input-lv/0
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
3
|
||||||
|
100
|
||||||
|
200
|
||||||
|
400
|
||||||
|
1000
|
||||||
|
2000
|
||||||
|
50
|
||||||
|
80
|
||||||
|
150
|
||||||
|
180
|
||||||
|
6000
|
||||||
|
5000
|
||||||
|
60000
|
||||||
|
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
9
|
||||||
|
10
|
||||||
|
11
|
||||||
|
12
|
||||||
|
|
||||||
|
a 500
|
||||||
|
d 12
|
||||||
|
c
|
||||||
|
m 11 10000
|
||||||
|
a 800
|
||||||
|
i 5 13
|
||||||
|
s 3 8
|
||||||
|
o 2 10
|
||||||
|
w 1 6
|
||||||
|
r 7
|
||||||
|
t 11
|
@ -12,6 +12,7 @@
|
|||||||
5000
|
5000
|
||||||
60000
|
60000
|
||||||
|
|
||||||
|
|
||||||
a 500
|
a 500
|
||||||
d 12
|
d 12
|
||||||
c
|
c
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
112
|
112
|
||||||
113
|
113
|
||||||
|
|
||||||
|
|
||||||
a 114
|
a 114
|
||||||
a 115
|
a 115
|
||||||
a 116
|
a 116
|
||||||
|
Loading…
x
Reference in New Issue
Block a user