text:
#include "stdafx.h"

#include "DataStore.h"
#include "MockFlashCard.h"
#include "Note.h"
#include "Notebook.h"
#include "Test.h"
#include "UserModel.h"

#include <boost/ref.hpp>
#include <fstream>

using namespace boost;
using namespace std;

//----------------------
// auxillary definitions
//----------------------

const wchar_t * const storeName   = L"test";
const wchar_t * const storeFolder = L"Program Files\\MobileTest";
const wchar_t * const storeFile   = L"Program Files\\MobileTest\\test.db";

struct DataStoreFixture
{
	MockFlashCard flashCard;

	DataStore store;
	UserModel userModel;

	DataStoreFixture()
		: userModel (store, storeFolder, flashCard)
	{
		::DeleteFile(storeFile);
		userModel.LoadOrCreate(storeName);
	}

	~DataStoreFixture()
	{
		::DeleteFile(storeFile);
	}
};

bool FileExists(const wchar_t * path)
{
	return ::GetFileAttributes(path) != 0xFFFFFFFF;
}

struct SignalCheck
{
	bool signalled;
	SignalCheck() : signalled(false) {}
	void operator () () { signalled = true; }
};

Note MakeNote(const wchar_t * name)
{
	Note note;
	note.name = name;
	return note;
}

Note MakeNote(const wchar_t * name, int timestamp)
{
	Note note;
	note.name = name;
	note.modificationDate = timestamp;
	return note;
}

Note MakeNote(const Guid & guid, const wchar_t * name = L"")
{
	Note note;
	note.guid = guid;
	note.name = name;
	return note;
}

Note MakeNote
	( const Guid    & guid
	, const wchar_t * name
	, Timestamp       modificationDate
	, int             usn
	, bool            isDirty
	)
{
	Note note;
	note.guid             = guid;
	note.name             = name;
	note.modificationDate = modificationDate;
	note.usn              = usn;
	note.isDirty          = isDirty;
	return note;
}

#define TestNoteEquality(note1, note2)                                                        \
        TEST_CHECK_EQUAL(note1.guid,                       note2.guid);                       \
        TEST_CHECK_EQUAL(note1.usn,                        note2.usn);                        \
        TEST_CHECK_EQUAL(note1.name,                       note2.name);                       \
        TEST_CHECK_EQUAL(note1.isDirty,                    note2.isDirty);                    \
        TEST_CHECK_EQUAL(note1.creationDate.GetTime(),     note2.creationDate.GetTime());     \
        TEST_CHECK_EQUAL(note1.modificationDate.GetTime(), note2.modificationDate.GetTime()); \
        TEST_CHECK_EQUAL(note1.subjectDate.GetTime(),      note2.subjectDate.GetTime());      \
        TEST_CHECK_EQUAL(note1.Location.Altitude,          note2.Location.Altitude);          \
        TEST_CHECK_EQUAL(note1.Location.Latitude,          note2.Location.Latitude);          \
        TEST_CHECK_EQUAL(note1.Location.Longitude,         note2.Location.Longitude);         \
        TEST_CHECK_EQUAL(note1.Author,                     note2.Author);                     \
        TEST_CHECK_EQUAL(note1.Source,                     note2.Source);                     \
        TEST_CHECK_EQUAL(note1.SourceUrl,                  note2.SourceUrl);                  \
        TEST_CHECK_EQUAL(note1.SourceApplication,          note2.SourceApplication);          \

//-----------
// test suite
//-----------

FIXTURE_TEST_CASE(UserModelAddNote, DataStoreFixture)
{
	Note note0;
	note0.usn                = 3;
	note0.isDirty            = true;
	note0.name               = L"note-0";
	note0.creationDate       = Timestamp(2);
	note0.modificationDate   = Timestamp(3);
	note0.subjectDate        = Timestamp(4);
	note0.Location.IsValid   = true;
	note0.Location.Altitude  = -0.5;
	note0.Location.Latitude  = 0.5;
	note0.Location.Longitude = 1.5;
	note0.Author             = L"Motoko";
	note0.Source             = L"Sea of information";
	note0.SourceApplication  = L"Project 2501";
	note0.SourceUrl          = L"http://peoplesnote.org";
	wstring body0(L"note body 0");

	Note note1;
	note1.usn              = 8;
	note1.isDirty          = true;
	note1.name             = L"note-1";
	note1.creationDate     = Timestamp(5);
	note1.modificationDate = Timestamp(6);
	note1.subjectDate      = Timestamp(7);
	wstring body1(L"note body 1");

	Guid notebook;
	userModel.GetLastUsedNotebook(notebook);
	userModel.AddNote(note0, body0, L"", notebook);
	userModel.AddNote(note1, body1, L"", notebook);

	Tag tag0;
	tag0.name    = L"test-tag-0";
	tag0.usn     = 2;
	tag0.isDirty = true;

	Tag tag1;
	tag1.name    = L"test-tag-1";
	tag1.usn     = 3;
	tag1.isDirty = false;

	Tag tag2;
	tag2.name    = L"test-tag-2";

	userModel.AddTag(tag2);
	userModel.AddTag(tag0);
	userModel.AddTag(tag1);

	userModel.AddTagToNote(tag2.guid, note0);
	userModel.AddTagToNote(tag1.guid, note0);

	{
		Note result;
		userModel.GetNote(note0.guid, result);
		TestNoteEquality(result, note0);

		wstring loaded;
		userModel.GetNoteBody(note0.guid, loaded);
		TEST_CHECK_EQUAL(loaded, L"note body 0");
	}
	{
		Note result;
		userModel.GetNote(note1.guid, result);
		TEST_CHECK_EQUAL(result.usn,                        8);
		TEST_CHECK_EQUAL(result.isDirty,                    true);
		TEST_CHECK_EQUAL(result.name,                       L"note-1");
		TEST_CHECK_EQUAL(result.creationDate.GetTime(),     5L);
		TEST_CHECK_EQUAL(result.modificationDate.GetTime(), 6L);
		TEST_CHECK_EQUAL(result.subjectDate.GetTime(),      7L);

		wstring loaded;
		userModel.GetNoteBody(note1.guid, loaded);
		TEST_CHECK_EQUAL(loaded, L"note body 1");
	}
	{
		TagList tags;
		userModel.GetTags(tags);
		TEST_CHECK_EQUAL(tags.size(), 3);
		TEST_CHECK_EQUAL(tags.at(0).guid,       tag0.guid);
		TEST_CHECK_EQUAL(tags.at(0).name,       L"test-tag-0");
		TEST_CHECK_EQUAL(tags.at(0).usn,        2);
		TEST_CHECK_EQUAL(tags.at(0).isDirty,    true);
		TEST_CHECK_EQUAL(tags.at(0).parentGuid, tag0.parentGuid);
		TEST_CHECK_EQUAL(tags.at(1).guid,       tag1.guid);
		TEST_CHECK_EQUAL(tags.at(1).name,       L"test-tag-1");
		TEST_CHECK_EQUAL(tags.at(1).usn,        3);
		TEST_CHECK_EQUAL(tags.at(1).isDirty,    false);
		TEST_CHECK_EQUAL(tags.at(2).guid,       tag2.guid);
		TEST_CHECK_EQUAL(tags.at(2).name,       L"test-tag-2");
	}
	{
		TagList tags;
		userModel.GetNoteTags(note0, tags);
		TEST_CHECK_EQUAL(tags.size(), 2);
		TEST_CHECK_EQUAL(tags.at(0).guid,       tag1.guid);
		TEST_CHECK_EQUAL(tags.at(0).name,       L"test-tag-1");
		TEST_CHECK_EQUAL(tags.at(0).usn,        3);
		TEST_CHECK_EQUAL(tags.at(0).isDirty,    false);
		TEST_CHECK_EQUAL(tags.at(0).parentGuid, tag1.parentGuid);
		TEST_CHECK_EQUAL(tags.at(1).guid,       tag2.guid);
		TEST_CHECK_EQUAL(tags.at(1).name,       L"test-tag-2");

		tags.clear();
		userModel.GetNoteTags(note1, tags);
		TEST_CHECK(tags.empty());
	}
}

FIXTURE_TEST_CASE(UserModelAddNotebook, DataStoreFixture)
{
	Notebook notebook;
	notebook.name = L"test-notebook";
	notebook.CreationDate     = Timestamp(1);
	notebook.ModificationDate = Timestamp(2);
	userModel.AddNotebook(notebook);

	TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 2);

	userModel.AddNotebook(notebook);
	TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 2);
}

FIXTURE_TEST_CASE(UserModelAttachments, DataStoreFixture)
{
	Guid notebook;
	userModel.GetDefaultNotebook(notebook);

	Note note0;
	Note note1;
	userModel.AddNote(note0, L"", L"", notebook);
	userModel.AddNote(note1, L"", L"", notebook);

	Resource resource0;
	Resource resource1;
	Resource resource2;
	Resource resource3;
	Resource resource4;
	resource0.Hash = "0";
	resource1.Hash = "1";
	resource2.Hash = "2";
	resource3.Hash = "3";
	resource4.Hash = "4";
	resource0.Mime = L"image/png";
	resource1.Mime = L"image/jpg";
	resource2.Mime = L"audio/wav";
	resource0.FileName = L"file0";
	resource1.FileName = L"file1"; // sort by filename
	resource2.FileName = L"file1"; // sort by timestamp
	resource3.FileName = L"";      // skip
	resource4.FileName = L"file2";
	resource0.Timestamp = 0;
	resource1.Timestamp = 1;
	resource2.Timestamp = 2;
	resource3.Timestamp = 3;
	resource4.Timestamp = 4;
	resource0.Note = note0.guid;
	resource1.Note = note0.guid;
	resource2.Note = note0.guid;
	resource3.Note = note0.guid;
	resource4.Note = note1.guid; // skip

	userModel.AddResource(resource3);
	userModel.AddResource(resource2);
	userModel.AddResource(resource1);
	userModel.AddResource(resource4);
	userModel.AddResource(resource0);

	AttachmentList attachments;
	userModel.GetNoteAttachments(note0.guid, attachments);

	TEST_CHECK_EQUAL(attachments.size(), 3);
	TEST_CHECK_EQUAL(attachments.at(0).Guid, resource0.Guid);
	TEST_CHECK_EQUAL(attachments.at(1).Guid, resource1.Guid);
	TEST_CHECK_EQUAL(attachments.at(2).Guid, resource2.Guid);
	TEST_CHECK_EQUAL(attachments.at(0).Mime, L"image/png");
	TEST_CHECK_EQUAL(attachments.at(1).Mime, L"image/jpg");
	TEST_CHECK_EQUAL(attachments.at(2).Mime, L"audio/wav");
	TEST_CHECK_EQUAL(attachments.at(0).FileName, L"file0");
	TEST_CHECK_EQUAL(attachments.at(1).FileName, L"file1");
	TEST_CHECK_EQUAL(attachments.at(2).FileName, L"file1");
}

FIXTURE_TEST_CASE(UserModelCascade, DataStoreFixture)
{
	Notebook notebook;
	Note note0;
	Note note1;
	Resource resource0;
	Resource resource1;

	resource0.Note = note0.guid;
	resource1.Note = note0.guid;
	resource0.Hash = "0";
	resource1.Hash = "1";

	userModel.AddNotebook(notebook);
	userModel.AddNote(note0, L"", L"", notebook.guid);
	userModel.AddNote(note1, L"", L"", notebook.guid);
	userModel.AddResource(resource0);
	userModel.AddResource(resource1);

	TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 2);
	TEST_CHECK_EQUAL(userModel.GetNoteCount(),     2);
	TEST_CHECK_EQUAL(userModel.GetResourceCount(), 2);

	userModel.ExpungeNote(note0.guid);

	TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 2);
	TEST_CHECK_EQUAL(userModel.GetNoteCount(),     1);
	TEST_CHECK_EQUAL(userModel.GetResourceCount(), 0);

	userModel.ExpungeNotebook(notebook.guid);

	TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 1);
	TEST_CHECK_EQUAL(userModel.GetNoteCount(),     0);
	TEST_CHECK_EQUAL(userModel.GetResourceCount(), 0);
}

FIXTURE_TEST_CASE(UserModelDeleteNote, DataStoreFixture)
{
	Guid notebook;
	userModel.GetDefaultNotebook(notebook);

	Note note1;
	Note note2;
	userModel.AddNote(note1, L"", L"", notebook);
	userModel.AddNote(note2, L"", L"", notebook);

	userModel.DeleteNote(note2.guid);

	NoteList notes;
	userModel.GetNotes(notebook, L"", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 1);
	TEST_CHECK_EQUAL(notes.at(0).guid, note1.guid);

	GuidList deletedNotes;
	userModel.GetDeletedNotes(deletedNotes);
	TEST_CHECK_EQUAL(deletedNotes.size(), 1);
	TEST_CHECK_EQUAL(deletedNotes.at(0), note2.guid);
}

FIXTURE_TEST_CASE(UserModelExpungeNote, DataStoreFixture)
{
	Guid notebook;
	userModel.GetDefaultNotebook(notebook);

	Note note;
	userModel.AddNote(note, L"", L"", notebook);
	userModel.ExpungeNote(note.guid);

	NoteList notes;
	userModel.GetNotes(notebook, L"", 0, 0, notes);
	TEST_CHECK(notes.empty());
}

FIXTURE_TEST_CASE(UserModelExpungeNotebook, DataStoreFixture)
{
	Guid defaultNotebook;
	userModel.GetDefaultNotebook(defaultNotebook);

	userModel.ExpungeNotebook(defaultNotebook);
	TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 1);

	Notebook newNotebook;
	userModel.AddNotebook(newNotebook);
	userModel.MakeNotebookLastUsed(newNotebook.guid);
	TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 2);

	Guid lastUsedNotebook;
	userModel.GetLastUsedNotebook(lastUsedNotebook);
	TEST_CHECK_EQUAL(lastUsedNotebook, newNotebook.guid);

	userModel.ExpungeNotebook(lastUsedNotebook);
	TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 1);
}

FIXTURE_TEST_CASE(UserModelExpungedTag, DataStoreFixture)
{
	Tag tag;
	userModel.AddTag(tag);
	userModel.ExpungeTag(tag.guid);

	TagList tags;
	userModel.GetTags(tags);
	TEST_CHECK(tags.empty());
}

AUTO_TEST_CASE(UserModelExists)
{
	MockFlashCard flashCard;

	DataStore store;
	UserModel userModel(store, storeFolder, flashCard);

	::DeleteFile(storeFile);
	TEST_CHECK(!userModel.Exists(storeName));

	{ ofstream(storeFile) << 0; }
	TEST_CHECK(userModel.Exists(storeName));
}

FIXTURE_TEST_CASE(UserModelNoteForeignKey, DataStoreFixture)
{
	Notebook notebook;
	notebook.name = L"test-notebook";
	userModel.AddNotebook(notebook);

	wstring empty;
	userModel.AddNote
		( MakeNote(L"note-0")
		, empty
		, empty
		, notebook.guid
		);

	Notebook fakeNotebook;
	fakeNotebook.name = L"fake-notebook";

	TEST_CHECK_EXCEPTION
		( userModel.AddNote
			( MakeNote(L"note-1")
			, empty
			, empty
			, fakeNotebook.guid
			)
		, std::exception
		, MESSAGE_EQUALS("foreign key constraint failed")
		);
}

FIXTURE_TEST_CASE(UserModelDefaultNotebook, DataStoreFixture)
{
	Notebook notebook;
	notebook.name = L"test-notebook";
	userModel.AddNotebook(notebook);
	userModel.MakeNotebookDefault(notebook.guid);

	Guid defaultNotebook;
	userModel.GetDefaultNotebook(defaultNotebook);

	userModel.GetNotebook(defaultNotebook, notebook);
	TEST_CHECK_EQUAL(notebook.name, L"test-notebook");
}

FIXTURE_TEST_CASE(UserModelGetDirtyNoteCount, DataStoreFixture)
{
	Guid notebook;
	userModel.GetDefaultNotebook(notebook);

	Note notes[3];
	notes[0].name    = L"note-0";
	notes[0].isDirty = true;
	notes[1].name    = L"note-1";
	notes[1].isDirty = false;
	notes[2].name    = L"note-2";
	notes[2].isDirty = true;

	for (int i(0); i != 3; ++i)
		userModel.AddNote(notes[i], L"", L"", notebook);

	int dirtyNoteCount(userModel.GetDirtyNoteCount(notebook));
	TEST_CHECK_EQUAL(dirtyNoteCount, 2);
}

FIXTURE_TEST_CASE(UserModelGetNotebook, DataStoreFixture)
{
	Notebook notebook;
	notebook.name = L"test-notebook";
	userModel.AddNotebook(notebook);

	Notebook result;
	userModel.GetNotebook(notebook.guid, result);

	TEST_CHECK_EQUAL(result.name, L"test-notebook");
}

FIXTURE_TEST_CASE(UserModelReplacement, DataStoreFixture)
{
	Notebook notebook0;
	Notebook notebook1;
	Note note0;
	Note note1;
	Tag tag0;
	Tag tag1;
	Resource resource0;
	Resource resource1;
	Resource resource2;
	Resource resource;

	notebook1.guid = notebook0.guid;
	notebook0.name = L"notebook-0";
	notebook1.name = L"notebook-1";
	notebook0.CreationDate     = Timestamp(1);
	notebook1.CreationDate     = Timestamp(2);
	notebook0.ModificationDate = Timestamp(3);
	notebook1.ModificationDate = Timestamp(4);
	note1.guid     = note0.guid;
	note0.name     = L"note-0";
	note1.name     = L"note-1";
	tag1.guid      = tag0.guid;
	tag0.name      = L"tag-0";
	tag1.name      = L"tag-1";
	resource1.Guid = resource0.Guid;
	resource0.Hash = "0";
	resource1.Hash = "1";
	resource2.Hash = "1";
	resource0.Note = note1.guid;
	resource1.Note = note1.guid;
	resource2.Note = note1.guid;

	resource0.Data.push_back(2);
	resource1.Data.push_back(3);
	resource2.Data.push_back(5);

	userModel.AddNotebook(notebook0);
	userModel.AddNotebook(notebook1);

	NotebookList notebooks;
	userModel.GetNotebooks(notebooks);
	TEST_CHECK_EQUAL(notebooks.size(), 2);
	TEST_CHECK_EQUAL(notebooks.at(1).name, L"notebook-1");
	TEST_CHECK_EQUAL(notebooks.at(1).CreationDate.GetTime(),     2L);
	TEST_CHECK_EQUAL(notebooks.at(1).ModificationDate.GetTime(), 4L);

	userModel.AddNote(note0, L"", L"", notebook1.guid);
	userModel.AddNote(note1, L"", L"", notebook1.guid);

	NoteList notes;
	userModel.GetNotes(notebook1.guid, L"", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 1);
	TEST_CHECK_EQUAL(notes.at(0).name, L"note-1");

	userModel.AddTag(tag0);
	userModel.AddTag(tag1);

	TagList tags;
	userModel.GetTags(tags);
	TEST_CHECK_EQUAL(tags.size(), 1);
	TEST_CHECK_EQUAL(tags.at(0).name, L"tag-1");

	userModel.AddResource(resource0);
	userModel.AddResource(resource1);

	TEST_CHECK_EQUAL(userModel.GetResourceCount(), 1);

	userModel.GetResource(resource0.Guid, resource);
	TEST_CHECK_EQUAL(resource.Hash, "1");
	TEST_CHECK_EQUAL(resource.Data.at(0), 3);

	userModel.AddResource(resource2);

	TEST_CHECK_EQUAL(userModel.GetResourceCount(), 1);

	userModel.GetResource(resource2.Guid, resource);
	TEST_CHECK_EQUAL(resource.Hash, "1");
	TEST_CHECK_EQUAL(resource.Data.at(0), 5);
}

FIXTURE_TEST_CASE(UserModelResource0, DataStoreFixture)
{
	Note note(MakeNote(L"note-0"));

	Resource resource;
	resource.Data.push_back(2);
	resource.Data.push_back(3);
	resource.Data.push_back(5);
	resource.Data.push_back(7);
	resource.Hash = "hash";
	resource.Note = note.guid;

	TEST_CHECK_EXCEPTION
		( userModel.AddResource(resource)
		, std::exception
		, MESSAGE_EQUALS("foreign key constraint failed")
		);
}

FIXTURE_TEST_CASE(UserModelResource1, DataStoreFixture)
{
	std::string hash ("hash");
	Note        note (MakeNote(L"note-0"));

	Resource resource;
	resource.Data.push_back(2);
	resource.Data.push_back(3);
	resource.Data.push_back(5);
	resource.Data.push_back(7);
	resource.Hash = hash;
	resource.Note = note.guid;

	Guid notebook;
	userModel.GetLastUsedNotebook(notebook);
	userModel.AddNote(note, L"", L"", notebook);
	userModel.AddResource(resource);
	userModel.AddResource(resource);

	Blob loaded;
	userModel.GetResource(hash, loaded);
	TEST_CHECK_EQUAL(resource.Data.size(), loaded.size());
	for (int i = 0; i != resource.Data.size(); ++i)
		TEST_CHECK_EQUAL(resource.Data.at(i), loaded.at(i));
}

FIXTURE_TEST_CASE(UserModelLastUsedNotebook, DataStoreFixture)
{
	Notebook notebook0;
	notebook0.name = L"notebook0";
	Notebook notebook1;
	notebook1.name    = L"notebook1";
	notebook1.isDirty = true;
	notebook1.usn     = 2;
	Notebook notebook2;
	notebook2.name = L"notebook2";
	userModel.AddNotebook(notebook0);
	userModel.AddNotebook(notebook1);
	userModel.AddNotebook(notebook2);
	userModel.MakeNotebookLastUsed(notebook1.guid);

	Guid lastUsedNotebook;
	userModel.GetLastUsedNotebook(lastUsedNotebook);
	TEST_CHECK_EQUAL(lastUsedNotebook, notebook1.guid);
}

AUTO_TEST_CASE(UserModelLoad)
{
	MockFlashCard flashCard;

	DataStore store;
	UserModel userModel(store, storeFolder, flashCard);

	SignalCheck check;
	userModel.ConnectLoaded(boost::ref(check));

	::DeleteFile(storeFile);
	TEST_CHECK_EXCEPTION
		( userModel.Load(storeName)
		, std::exception
		, MESSAGE_EQUALS("Database could not be loaded.")
		);
	TEST_CHECK(!check.signalled);

	{
		MockFlashCard flashCard;

		DataStore store;
		UserModel userModel(store, storeFolder, flashCard);

		userModel.LoadOrCreate(storeName);
	}

	userModel.Load(storeName);
	TEST_CHECK(check.signalled);

	TEST_CHECK_EQUAL(userModel.GetUsername(), storeName);
}

AUTO_TEST_CASE(UserModelLoadAs)
{
	MockFlashCard flashCard;

	DataStore store;
	UserModel userModel(store, storeFolder, flashCard);

	SignalCheck check;
	userModel.ConnectLoaded(boost::ref(check));

	const wchar_t * dstName = L"test2";
	const wchar_t * dstFile = L"Program Files\\MobileTest\\test2.db";

	::DeleteFile(storeFile);
	TEST_CHECK_EXCEPTION
		( userModel.LoadAs(storeName, dstName)
		, std::exception
		, MESSAGE_EQUALS("Database could not be found.")
		);
	TEST_CHECK(!check.signalled);

	{
		MockFlashCard flashCard;

		DataStore store;
		UserModel userModel(store, storeFolder, flashCard);

		userModel.LoadOrCreate(storeName);
	}

	{ ofstream(dstFile) << 0; }
	TEST_CHECK_EXCEPTION
		( userModel.LoadAs(storeName, dstName)
		, std::exception
		, MESSAGE_EQUALS("Database could not be renamed.")
		);
	TEST_CHECK(!check.signalled);

	::DeleteFile(dstFile);
	userModel.LoadAs(storeName, dstName);
	TEST_CHECK(check.signalled);

	TEST_CHECK_EQUAL(userModel.GetUsername(), dstName);
}

AUTO_TEST_CASE(UserModelLoadOrCreate)
{
	{
		MockFlashCard flashCard;

		DataStore store;
		UserModel userModel(store, storeFolder, flashCard);

		SignalCheck check;
		userModel.ConnectLoaded(boost::ref(check));

		::DeleteFile(storeFile);
		TEST_CHECK(!FileExists(storeFile));
		userModel.LoadOrCreate(storeName);
		TEST_CHECK(FileExists(storeFile));
		TEST_CHECK(check.signalled);

		TEST_CHECK_EQUAL(userModel.GetUsername(),      storeName);
		TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 1);

		userModel.SetCredentials(storeName, L"test-pwd");

		userModel.AddNotebook(Notebook());
	}
	{
		MockFlashCard flashCard;

		DataStore store;
		UserModel userModel(store, storeFolder, flashCard);
		SignalCheck check;
		userModel.ConnectLoaded(boost::ref(check));

		userModel.LoadOrCreate(storeName);
		TEST_CHECK(check.signalled);

		TEST_CHECK_EQUAL(userModel.GetUsername(),     storeName);
		TEST_CHECK_EQUAL(userModel.GetPasswordHash(), L"test-pwd");
		TEST_CHECK_EQUAL(userModel.GetNotebookCount(), 2);
	}
}

FIXTURE_TEST_CASE(UserModelNotebooks, DataStoreFixture)
{
	Notebook notebook0;
	notebook0.name = L"notebook0";
	Notebook notebook1;
	notebook1.name = L"notebook1";
	Notebook notebook2;
	notebook2.name = L"notebook2";
	userModel.AddNotebook(notebook1);
	userModel.AddNotebook(notebook0);
	userModel.AddNotebook(notebook2);

	NotebookList notebooks;
	userModel.GetNotebooks(notebooks);
	TEST_CHECK_EQUAL(notebooks.size(), 4);
	TEST_CHECK_EQUAL(notebooks.at(0).name, L"Notes");
	TEST_CHECK_EQUAL(notebooks.at(1).name, L"notebook0");
	TEST_CHECK_EQUAL(notebooks.at(2).name, L"notebook1");
	TEST_CHECK_EQUAL(notebooks.at(3).name, L"notebook2");
}

FIXTURE_TEST_CASE(UserModelNotesByNotebook, DataStoreFixture)
{
	vector<Notebook> notebooks;
	notebooks.push_back(Notebook());
	notebooks.back().name = L"notebook-0";
	notebooks.push_back(Notebook());
	notebooks.back().name = L"notebook-1";
	foreach (const Notebook & notebook, notebooks)
		userModel.AddNotebook(notebook);

	wstring empty;

	userModel.AddNote
		( MakeNote(L"note-0")
		, empty
		, empty
		, notebooks.at(0).guid
		);
	userModel.AddNote
		( MakeNote(L"note-1")
		, empty
		, empty
		, notebooks.at(1).guid
		);
	userModel.AddNote
		( MakeNote(L"note-2")
		, empty
		, empty
		, notebooks.at(0).guid
		);

	NoteList notes;
	userModel.GetNotes(notebooks.at(0).guid, L"", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 2);
	TEST_CHECK_EQUAL(notes.at(0).name, L"note-0");
	TEST_CHECK_EQUAL(notes.at(1).name, L"note-2");
}

FIXTURE_TEST_CASE(UserModelGetNotesBySearch1, DataStoreFixture)
{
	Notebook notebook;
	notebook.name = L"notebook";
	userModel.AddNotebook(notebook);

	wstring empty;

	userModel.AddNote
		( MakeNote(L"useful software", 0)
		, empty
		, empty
		, notebook.guid
		);
	userModel.AddNote
		( MakeNote(L"software use", 1)
		, empty
		, empty
		, notebook.guid
		);

	NoteList notes;
	userModel.GetNotes(notebook.guid, L"software", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 2);
	TEST_CHECK_EQUAL(notes.at(0).name, L"software use");
	TEST_CHECK_EQUAL(notes.at(1).name, L"useful software");

	notes.clear();
	userModel.GetNotes(notebook.guid, L"use", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 1);
	TEST_CHECK_EQUAL(notes.at(0).name, L"software use");
}

FIXTURE_TEST_CASE(UserModelGetNotesBySearch2, DataStoreFixture)
{
	vector<Notebook> notebooks(2);
	notebooks[0].name = L"notebook0";
	notebooks[1].name = L"notebook1";
	notebooks[1].guid = Guid();
	foreach (const Notebook & notebook, notebooks)
		userModel.AddNotebook(notebook);

	wstring empty;

	userModel.AddNote
		( MakeNote(L"Ангара", 0)
		, empty
		, L"Восточный"
		, notebooks[0].guid
		);
	userModel.AddNote
		( MakeNote(L"Ангара", 0)
		, empty
		, L"Восточный"
		, notebooks[1].guid
		);

	NoteList notes;
	userModel.GetNotes(notebooks[0].guid, L"ангара", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 1);

	userModel.GetNotes(notebooks[0].guid, L"восточный", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 1);

	userModel.GetNotes(Guid::GetEmpty(), L"восточный", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 2);
}

FIXTURE_TEST_CASE(UserModelTags, DataStoreFixture)
{
	TagList tags1;
	tags1.push_back(Tag());
	tags1.back().name = L"tag-c";
	tags1.push_back(Tag());
	tags1.back().name = L"tag-a";
	tags1.push_back(Tag());
	tags1.back().name = L"tag-b";

	foreach (const Tag & tag, tags1)
		userModel.AddTag(tag);

	TagList tags2;
	userModel.GetTags(tags2);
	TEST_CHECK_EQUAL(tags2.size(), 3);
	TEST_CHECK_EQUAL(tags2.at(0).name, L"tag-a");
	TEST_CHECK_EQUAL(tags2.at(1).name, L"tag-b");
	TEST_CHECK_EQUAL(tags2.at(2).name, L"tag-c");
}

FIXTURE_TEST_CASE(UserModelThumbnail, DataStoreFixture)
{
	Guid notebook;
	userModel.GetDefaultNotebook(notebook);

	wstring empty;

	Guid guid;

	userModel.AddNote
		( MakeNote(guid, L"note")
		, empty
		, empty
		, notebook
		);

	Thumbnail in;
	in.Data.push_back(2);
	in.Data.push_back(3);
	in.Data.push_back(5);
	in.Width  = 7;
	in.Height = 11;
	userModel.SetNoteThumbnail(guid, in);

	Thumbnail out;
	userModel.GetNoteThumbnail(guid, out);
	TEST_CHECK_EQUAL(out.Data.size(), 3);
	TEST_CHECK_EQUAL(out.Data.at(0), 2);
	TEST_CHECK_EQUAL(out.Data.at(1), 3);
	TEST_CHECK_EQUAL(out.Data.at(2), 5);
	TEST_CHECK_EQUAL(out.Width,  7);
	TEST_CHECK_EQUAL(out.Height, 11);

	userModel.DeleteNoteThumbnail(guid);

	out.Data.clear();
	userModel.GetNoteThumbnail(guid, out);
	TEST_CHECK(out.Data.empty());
}

FIXTURE_TEST_CASE(UserModelUnload, DataStoreFixture)
{
	TEST_CHECK_EQUAL(::DeleteFile(storeFile), FALSE);
	userModel.Unload();
	TEST_CHECK_EQUAL(::DeleteFile(storeFile), TRUE);
}

FIXTURE_TEST_CASE(UserModelUpdateNote, DataStoreFixture)
{
	Guid notebook;
	userModel.GetDefaultNotebook(notebook);

	Guid guid1;
	Note note;
	note.guid               = guid1;
	note.usn                = 1;
	note.name               = L"note 1";
	note.isDirty            = true;
	note.creationDate       = Timestamp(1);
	note.modificationDate   = Timestamp(2);
	note.subjectDate        = Timestamp(3);
	note.Location.IsValid   = true;
	note.Location.Altitude  = 1;
	note.Location.Latitude  = 2;
	note.Location.Longitude = 3;
	note.Author             = L"Motoko";
	note.Source             = L"Sea of informaiton";
	note.SourceApplication  = L"Project 2501";
	note.SourceUrl          = L"http://www.peoplesnote.org";

	userModel.AddNote(note, L"", L"", notebook);

	NoteList notes;
	userModel.GetNotes(notebook, L"", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 1);
	TestNoteEquality(notes.at(0), note);

	Guid guid2;
	note.guid               = guid2;
	note.usn                = 2;
	note.name               = L"note 2";
	note.isDirty            = false;
	note.creationDate       = Timestamp(4);
	note.modificationDate   = Timestamp(5);
	note.subjectDate        = Timestamp(6);
	note.Location.IsValid   = false;
	note.Location.Altitude  = 7;
	note.Location.Latitude  = 8;
	note.Location.Longitude = 9;
	note.Author             = L"Kusanagi";
	note.Source             = L"Section 9";
	note.SourceApplication  = L"Public Security";
	note.SourceUrl          = L"http://peoplesnote.org";

	userModel.UpdateNote(guid1, note);

	note.Location.Altitude  = 0;
	note.Location.Latitude  = 0;
	note.Location.Longitude = 0;

	notes.clear();
	userModel.GetNotes(notebook, L"", 0, 0, notes);
	TEST_CHECK_EQUAL(notes.size(), 1);
	TestNoteEquality(notes.at(0), note);
}

FIXTURE_TEST_CASE(UserModelUpdateNotebook, DataStoreFixture)
{
	Guid notebook;
	userModel.GetDefaultNotebook(notebook);

	Note note;
	note.name = L"note-0";
	userModel.AddNote(note, L"", L"", notebook);

	Notebook replacementNotebook;
	replacementNotebook.guid    = Guid("{1}");
	replacementNotebook.isDirty = false;
	replacementNotebook.name    = L"notebook-1";
	replacementNotebook.usn     = 1;

	userModel.UpdateNotebook(notebook, replacementNotebook);

	NotebookList notebooks;
	userModel.GetNotebooks(notebooks);

	TEST_CHECK_EQUAL(notebooks.size(), 1);
	TEST_CHECK_EQUAL(notebooks.at(0).guid,    replacementNotebook.guid);
	TEST_CHECK_EQUAL(notebooks.at(0).isDirty, replacementNotebook.isDirty);
	TEST_CHECK_EQUAL(notebooks.at(0).name,    replacementNotebook.name);
	TEST_CHECK_EQUAL(notebooks.at(0).usn,     replacementNotebook.usn);

	Guid defaultNotebook;
	userModel.GetDefaultNotebook(defaultNotebook);
	TEST_CHECK_EQUAL(defaultNotebook, replacementNotebook.guid);

	Guid lastUsedNotebook;
	userModel.GetLastUsedNotebook(lastUsedNotebook);
	TEST_CHECK_EQUAL(lastUsedNotebook, replacementNotebook.guid);

	NoteList notes;
	userModel.GetNotes(replacementNotebook.guid, L"", 0, 0, notes);

	TEST_CHECK_EQUAL(notes.size(), 1);
	TEST_CHECK_EQUAL(notes.at(0).name, L"note-0");
}

FIXTURE_TEST_CASE(UserModelUpdateResource, DataStoreFixture)
{
	Guid notebook;
	userModel.GetDefaultNotebook(notebook);

	Note note;
	userModel.AddNote(note, L"", L"", notebook);

	Resource resource;
	resource.Note = note.guid;
	userModel.AddResource(resource);

	RecognitionEntry entry;
	entry.Resource = resource.Guid;
	userModel.AddRecognitionEntry(entry);

	TEST_CHECK_EQUAL(userModel.GetRecognitionEntryCount(), 1);

	Resource replacement;
	replacement.Note = note.guid;
	userModel.UpdateResource(resource.Guid, replacement);

	TEST_CHECK_EQUAL(userModel.GetRecognitionEntryCount(), 1);

	userModel.AddResource(replacement);

	TEST_CHECK_EQUAL(userModel.GetRecognitionEntryCount(), 0);
}

FIXTURE_TEST_CASE(UserModelUpdateTag, DataStoreFixture)
{
	Tag tag;
	tag.guid    = Guid("{0}");
	tag.isDirty = true;
	tag.name    = L"tag-0";
	tag.usn     = 0;

	userModel.AddTag(tag);

	Tag replacementTag;
	replacementTag.guid    = Guid("{1}");
	replacementTag.isDirty = false;
	replacementTag.name    = L"tag-1";
	replacementTag.usn     = 1;

	userModel.UpdateTag(tag.guid, replacementTag);

	TagList tags;
	userModel.GetTags(tags);

	TEST_CHECK_EQUAL(tags.size(), 1);
	TEST_CHECK_EQUAL(tags.at(0).guid,    replacementTag.guid);
	TEST_CHECK_EQUAL(tags.at(0).isDirty, replacementTag.isDirty);
	TEST_CHECK_EQUAL(tags.at(0).name,    replacementTag.name);
	TEST_CHECK_EQUAL(tags.at(0).usn,     replacementTag.usn);
}

FIXTURE_TEST_CASE(UserModelSyncVersion, DataStoreFixture)
{
	userModel.SetSyncVersion(17);
	TEST_CHECK_EQUAL(userModel.GetSyncVersion(), 17);
}

max_stars_repo_name: don-reba/peoples-note

max_issues_repo_name: don-reba/peoples-note

max_forks_repo_name: don-reba/peoples-note


text:
#include "cutting_plane.hpp"
#include "ell.hpp"
#include "profit_oracle.hpp"
#include "ldlt_ext.hpp"
//#include <boost/numeric/ublas/symmetric.hpp>
#include <xtensor/xarray.hpp>
#include <xtensor-blas/xlinalg.hpp>
//#include <fmt/format.h>
#include <iostream>

//#include <boost/numeric/ublas/io.hpp>

// Versions: (latest first)
// http://melpon.org/wandbox/permlink/CcvL0BHfVJhHZH4M
// http://melpon.org/wandbox/permlink/ExQoromITFQ7WOxO
// http://melpon.org/wandbox/permlink/YiLtKIriWtkigZs8

int test1() {
  //namespace bnu = boost::numeric::ublas;
  //using Vec = bnu::vector<double>;
  //using Mat = xt::xarray<double, xt::layout_type::row_major>;
  using Vec = xt::xarray<double, xt::layout_type::row_major>;

  double p = 20, A = 40, alpha = 0.1, beta = 0.4;
  double v1 = 10, v2 = 35, k = 30.5;
  double fb;
  int niter, status;
  bool feasible;

  {
    ell E(100., Vec{0., 0.});
    profit_oracle P(p, A, alpha, beta, v1, v2, k);
    std::tie(std::ignore, fb, niter, feasible, status) =
        cutting_plane_dc(P, E, 0.);
    // fmt::print("{:f} {} {} {} \n", fb, niter, feasible, status);
    std::cout << fb << ", " << niter << ", " << feasible << ", " << status << "\n";
  }

  double ui = 1., e1 = 0.003, e2 = 0.007, e3 = 1.;

  {
    ell E1(100., Vec{0., 0.});
    profit_rb_oracle P1(p, A, alpha, beta, v1, v2, k, ui, e1, e2, e3);
    std::tie(std::ignore, fb, niter, feasible, status) =
        cutting_plane_dc(P1, E1, 0.);
    // fmt::print("{:f} {} {} {} \n", fb, niter, feasible, status);
    std::cout << fb << ", " << niter << ", " << feasible << ", " << status
              << "\n";
  }

  {
    ell E2(100., Vec{2., 0.});
    profit_q_oracle P2(p, A, alpha, beta, v1, v2, k);
    std::tie(std::ignore, fb, niter, feasible, status) =
        cutting_plane_q(P2, E2, 0.);
    // fmt::print("{:f} {} {} {} \n", fb, niter, feasible, status);
    std::cout << fb << ", " << niter << ", " << feasible << ", " << status
             << "\n";
  }

  return 0;
}

int main() {
  using Arr = xt::xarray<double, xt::layout_type::row_major>;
  using xt::placeholders::_;
  using xt::linalg::dot;

  auto m1 = Arr({{25., 15., -5.},
                {15., 18.,  0.},
                {-5.,  0., 11.}});
  std::cout << m1.shape()[0] << "\n";
  auto Q1 = ldlt_ext(m1.shape()[0]);
  Q1.factorize(m1);
  if (!Q1.is_sd()) {
    auto v = Q1.witness();
    auto p = v.size();
    auto sub = xt::range(0, p);
    Arr App = xt::view(m1, sub, sub);
    Arr Appv = dot(App, v);
    auto fj = -dot(v, Appv)();
    std::cout << fj << std::endl;
  }

  auto m2 = Arr({{18., 22.,  54.,  42.},
                {22., -70.,  86.,  62.},
                {54., 86., -174., 134.},
                {42., 62., 134., -106.}});
  std::cout << m2.shape()[0] << "\n";
  auto Q2 = ldlt_ext(m2.shape()[0]);
  Q2.factorize(m2);
  if (!Q2.is_sd()) {
    auto v = Q2.witness();
    auto p = v.size();
    auto sub = xt::range(0, p);
    Arr App = xt::view(m2, sub, sub);
    Arr Appv = dot(App, v);
    auto fj = -dot(v, Appv)();
    std::cout << fj << std::endl;
  }

  return 0;
}

ext: tpp


text:
// Copyright (c) 2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "coins.h"
#include "random.h"
#include "script/standard.h"
#include "uint256.h"
#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
#include "consensus/validation.h"
#include "main.h"
#include "undo.h"
#include "pubkey.h"

#include <vector>
#include <map>

#include <boost/test/unit_test.hpp>
#include "zelcash/IncrementalMerkleTree.hpp"

namespace
{
class CCoinsViewTest : public CCoinsView
{
    uint256 hashBestBlock_;
    uint256 hashBestAnchor_;
    std::map<uint256, CCoins> map_;
    std::map<uint256, ZCIncrementalMerkleTree> mapAnchors_;
    std::map<uint256, bool> mapNullifiers_;

public:
    CCoinsViewTest() {
        hashBestAnchor_ = ZCIncrementalMerkleTree::empty_root();
    }

    bool GetAnchorAt(const uint256& rt, ZCIncrementalMerkleTree &tree) const {
        if (rt == ZCIncrementalMerkleTree::empty_root()) {
            ZCIncrementalMerkleTree new_tree;
            tree = new_tree;
            return true;
        }

        std::map<uint256, ZCIncrementalMerkleTree>::const_iterator it = mapAnchors_.find(rt);
        if (it == mapAnchors_.end()) {
            return false;
        } else {
            tree = it->second;
            return true;
        }
    }

    bool GetNullifier(const uint256 &nf) const
    {
        std::map<uint256, bool>::const_iterator it = mapNullifiers_.find(nf);

        if (it == mapNullifiers_.end()) {
            return false;
        } else {
            // The map shouldn't contain any false entries.
            assert(it->second);
            return true;
        }
    }

    uint256 GetBestAnchor() const { return hashBestAnchor_; }

    bool GetCoins(const uint256& txid, CCoins& coins) const
    {
        std::map<uint256, CCoins>::const_iterator it = map_.find(txid);
        if (it == map_.end()) {
            return false;
        }
        coins = it->second;
        if (coins.IsPruned() && insecure_rand() % 2 == 0) {
            // Randomly return false in case of an empty entry.
            return false;
        }
        return true;
    }

    bool HaveCoins(const uint256& txid) const
    {
        CCoins coins;
        return GetCoins(txid, coins);
    }

    uint256 GetBestBlock() const { return hashBestBlock_; }

    bool BatchWrite(CCoinsMap& mapCoins,
                    const uint256& hashBlock,
                    const uint256& hashAnchor,
                    CAnchorsMap& mapAnchors,
                    CNullifiersMap& mapNullifiers)
    {
        for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) {
            map_[it->first] = it->second.coins;
            if (it->second.coins.IsPruned() && insecure_rand() % 3 == 0) {
                // Randomly delete empty entries on write.
                map_.erase(it->first);
            }
            mapCoins.erase(it++);
        }
        for (CAnchorsMap::iterator it = mapAnchors.begin(); it != mapAnchors.end(); ) {
            if (it->second.entered) {
                std::map<uint256, ZCIncrementalMerkleTree>::iterator ret =
                    mapAnchors_.insert(std::make_pair(it->first, ZCIncrementalMerkleTree())).first;

                ret->second = it->second.tree;
            } else {
                mapAnchors_.erase(it->first);
            }
            mapAnchors.erase(it++);
        }
        for (CNullifiersMap::iterator it = mapNullifiers.begin(); it != mapNullifiers.end(); ) {
            if (it->second.entered) {
                mapNullifiers_[it->first] = true;
            } else {
                mapNullifiers_.erase(it->first);
            }
            mapNullifiers.erase(it++);
        }
        mapCoins.clear();
        mapAnchors.clear();
        mapNullifiers.clear();
        hashBestBlock_ = hashBlock;
        hashBestAnchor_ = hashAnchor;
        return true;
    }

    bool GetStats(CCoinsStats& stats) const { return false; }
};

class CCoinsViewCacheTest : public CCoinsViewCache
{
public:
    CCoinsViewCacheTest(CCoinsView* base) : CCoinsViewCache(base) {}

    void SelfTest() const
    {
        // Manually recompute the dynamic usage of the whole data, and compare it.
        size_t ret = memusage::DynamicUsage(cacheCoins) +
                     memusage::DynamicUsage(cacheAnchors) +
                     memusage::DynamicUsage(cacheNullifiers);
        for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) {
            ret += it->second.coins.DynamicMemoryUsage();
        }
        BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret);
    }

};

}

uint256 appendRandomCommitment(ZCIncrementalMerkleTree &tree)
{
    libzelcash::SpendingKey k = libzelcash::SpendingKey::random();
    libzelcash::PaymentAddress addr = k.address();

    libzelcash::Note note(addr.a_pk, 0, uint256(), uint256());

    auto cm = note.cm();
    tree.append(cm);
    return cm;
}

BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(nullifier_regression_test)
{
    // Correct behavior:
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Insert a nullifier into the base.
        uint256 nf = GetRandHash();
        cache1.SetNullifier(nf, true);
        cache1.Flush(); // Flush to base.

        // Remove the nullifier from cache
        cache1.SetNullifier(nf, false);

        // The nullifier now should be `false`.
        BOOST_CHECK(!cache1.GetNullifier(nf));
    }

    // Also correct behavior:
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Insert a nullifier into the base.
        uint256 nf = GetRandHash();
        cache1.SetNullifier(nf, true);
        cache1.Flush(); // Flush to base.

        // Remove the nullifier from cache
        cache1.SetNullifier(nf, false);
        cache1.Flush(); // Flush to base.

        // The nullifier now should be `false`.
        BOOST_CHECK(!cache1.GetNullifier(nf));
    }

    // Works because we bring it from the parent cache:
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Insert a nullifier into the base.
        uint256 nf = GetRandHash();
        cache1.SetNullifier(nf, true);
        cache1.Flush(); // Empties cache.

        // Create cache on top.
        {
            // Remove the nullifier.
            CCoinsViewCacheTest cache2(&cache1);
            BOOST_CHECK(cache2.GetNullifier(nf));
            cache2.SetNullifier(nf, false);
            cache2.Flush(); // Empties cache, flushes to cache1.
        }

        // The nullifier now should be `false`.
        BOOST_CHECK(!cache1.GetNullifier(nf));
    }

    // Was broken:
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Insert a nullifier into the base.
        uint256 nf = GetRandHash();
        cache1.SetNullifier(nf, true);
        cache1.Flush(); // Empties cache.

        // Create cache on top.
        {
            // Remove the nullifier.
            CCoinsViewCacheTest cache2(&cache1);
            cache2.SetNullifier(nf, false);
            cache2.Flush(); // Empties cache, flushes to cache1.
        }

        // The nullifier now should be `false`.
        BOOST_CHECK(!cache1.GetNullifier(nf));
    }
}

BOOST_AUTO_TEST_CASE(anchor_pop_regression_test)
{
    // Correct behavior:
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Create dummy anchor/commitment
        ZCIncrementalMerkleTree tree;
        uint256 cm = GetRandHash();
        tree.append(cm);

        // Add the anchor
        cache1.PushAnchor(tree);
        cache1.Flush();

        // Remove the anchor
        cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root());
        cache1.Flush();

        // Add the anchor back
        cache1.PushAnchor(tree);
        cache1.Flush();

        // The base contains the anchor, of course!
        {
            ZCIncrementalMerkleTree checktree;
            BOOST_CHECK(cache1.GetAnchorAt(tree.root(), checktree));
            BOOST_CHECK(checktree.root() == tree.root());
        }
    }

    // Previously incorrect behavior
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Create dummy anchor/commitment
        ZCIncrementalMerkleTree tree;
        uint256 cm = GetRandHash();
        tree.append(cm);

        // Add the anchor and flush to disk
        cache1.PushAnchor(tree);
        cache1.Flush();

        // Remove the anchor, but don't flush yet!
        cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root());

        {
            CCoinsViewCacheTest cache2(&cache1); // Build cache on top
            cache2.PushAnchor(tree); // Put the same anchor back!
            cache2.Flush(); // Flush to cache1
        }

        // cache2's flush kinda worked, i.e. cache1 thinks the
        // tree is there, but it didn't bring down the correct
        // treestate...
        {
            ZCIncrementalMerkleTree checktree;
            BOOST_CHECK(cache1.GetAnchorAt(tree.root(), checktree));
            BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks.
        }

        // Flushing cache won't help either, just makes the inconsistency
        // permanent.
        cache1.Flush();
        {
            ZCIncrementalMerkleTree checktree;
            BOOST_CHECK(cache1.GetAnchorAt(tree.root(), checktree));
            BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks.
        }
    }
}

BOOST_AUTO_TEST_CASE(anchor_regression_test)
{
    // Correct behavior:
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Insert anchor into base.
        ZCIncrementalMerkleTree tree;
        uint256 cm = GetRandHash();
        tree.append(cm);
        cache1.PushAnchor(tree);
        cache1.Flush();

        cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root());
        BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root());
        BOOST_CHECK(!cache1.GetAnchorAt(tree.root(), tree));
    }

    // Also correct behavior:
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Insert anchor into base.
        ZCIncrementalMerkleTree tree;
        uint256 cm = GetRandHash();
        tree.append(cm);
        cache1.PushAnchor(tree);
        cache1.Flush();

        cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root());
        cache1.Flush();
        BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root());
        BOOST_CHECK(!cache1.GetAnchorAt(tree.root(), tree));
    }

    // Works because we bring the anchor in from parent cache.
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Insert anchor into base.
        ZCIncrementalMerkleTree tree;
        uint256 cm = GetRandHash();
        tree.append(cm);
        cache1.PushAnchor(tree);
        cache1.Flush();

        {
            // Pop anchor.
            CCoinsViewCacheTest cache2(&cache1);
            BOOST_CHECK(cache2.GetAnchorAt(tree.root(), tree));
            cache2.PopAnchor(ZCIncrementalMerkleTree::empty_root());
            cache2.Flush();
        }

        BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root());
        BOOST_CHECK(!cache1.GetAnchorAt(tree.root(), tree));
    }

    // Was broken:
    {
        CCoinsViewTest base;
        CCoinsViewCacheTest cache1(&base);

        // Insert anchor into base.
        ZCIncrementalMerkleTree tree;
        uint256 cm = GetRandHash();
        tree.append(cm);
        cache1.PushAnchor(tree);
        cache1.Flush();

        {
            // Pop anchor.
            CCoinsViewCacheTest cache2(&cache1);
            cache2.PopAnchor(ZCIncrementalMerkleTree::empty_root());
            cache2.Flush();
        }

        BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root());
        BOOST_CHECK(!cache1.GetAnchorAt(tree.root(), tree));
    }
}

BOOST_AUTO_TEST_CASE(nullifiers_test)
{
    CCoinsViewTest base;
    CCoinsViewCacheTest cache(&base);

    uint256 nf = GetRandHash();

    BOOST_CHECK(!cache.GetNullifier(nf));
    cache.SetNullifier(nf, true);
    BOOST_CHECK(cache.GetNullifier(nf));
    cache.Flush();

    CCoinsViewCacheTest cache2(&base);

    BOOST_CHECK(cache2.GetNullifier(nf));
    cache2.SetNullifier(nf, false);
    BOOST_CHECK(!cache2.GetNullifier(nf));
    cache2.Flush();

    CCoinsViewCacheTest cache3(&base);

    BOOST_CHECK(!cache3.GetNullifier(nf));
}

BOOST_AUTO_TEST_CASE(anchors_flush_test)
{
    CCoinsViewTest base;
    uint256 newrt;
    {
        CCoinsViewCacheTest cache(&base);
        ZCIncrementalMerkleTree tree;
        BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), tree));
        appendRandomCommitment(tree);

        newrt = tree.root();

        cache.PushAnchor(tree);
        cache.Flush();
    }

    {
        CCoinsViewCacheTest cache(&base);
        ZCIncrementalMerkleTree tree;
        BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), tree));

        // Get the cached entry.
        BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), tree));

        uint256 check_rt = tree.root();

        BOOST_CHECK(check_rt == newrt);
    }
}

BOOST_AUTO_TEST_CASE(chained_joinsplits)
{
    CCoinsViewTest base;
    CCoinsViewCacheTest cache(&base);

    ZCIncrementalMerkleTree tree;

    JSDescription js1;
    js1.anchor = tree.root();
    js1.commitments[0] = appendRandomCommitment(tree);
    js1.commitments[1] = appendRandomCommitment(tree);

    // Although it's not possible given our assumptions, if
    // two joinsplits create the same treestate twice, we should
    // still be able to anchor to it.
    JSDescription js1b;
    js1b.anchor = tree.root();
    js1b.commitments[0] = js1.commitments[0];
    js1b.commitments[1] = js1.commitments[1];

    JSDescription js2;
    JSDescription js3;

    js2.anchor = tree.root();
    js3.anchor = tree.root();

    js2.commitments[0] = appendRandomCommitment(tree);
    js2.commitments[1] = appendRandomCommitment(tree);

    js3.commitments[0] = appendRandomCommitment(tree);
    js3.commitments[1] = appendRandomCommitment(tree);

    {
        CMutableTransaction mtx;
        mtx.vjoinsplit.push_back(js2);

        BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx));
    }

    {
        // js2 is trying to anchor to js1 but js1
        // appears afterwards -- not a permitted ordering
        CMutableTransaction mtx;
        mtx.vjoinsplit.push_back(js2);
        mtx.vjoinsplit.push_back(js1);

        BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx));
    }

    {
        CMutableTransaction mtx;
        mtx.vjoinsplit.push_back(js1);
        mtx.vjoinsplit.push_back(js2);

        BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx));
    }

    {
        CMutableTransaction mtx;
        mtx.vjoinsplit.push_back(js1);
        mtx.vjoinsplit.push_back(js2);
        mtx.vjoinsplit.push_back(js3);

        BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx));
    }

    {
        CMutableTransaction mtx;
        mtx.vjoinsplit.push_back(js1);
        mtx.vjoinsplit.push_back(js1b);
        mtx.vjoinsplit.push_back(js2);
        mtx.vjoinsplit.push_back(js3);

        BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx));
    }
}

BOOST_AUTO_TEST_CASE(anchors_test)
{
    // TODO: These tests should be more methodical.
    //       Or, integrate with Bitcoin's tests later.

    CCoinsViewTest base;
    CCoinsViewCacheTest cache(&base);

    BOOST_CHECK(cache.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root());

    {
        ZCIncrementalMerkleTree tree;

        BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), tree));
        BOOST_CHECK(cache.GetBestAnchor() == tree.root());
        appendRandomCommitment(tree);
        appendRandomCommitment(tree);
        appendRandomCommitment(tree);
        appendRandomCommitment(tree);
        appendRandomCommitment(tree);
        appendRandomCommitment(tree);
        appendRandomCommitment(tree);

        ZCIncrementalMerkleTree save_tree_for_later;
        save_tree_for_later = tree;

        uint256 newrt = tree.root();
        uint256 newrt2;

        cache.PushAnchor(tree);
        BOOST_CHECK(cache.GetBestAnchor() == newrt);

        {
            ZCIncrementalMerkleTree confirm_same;
            BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), confirm_same));

            BOOST_CHECK(confirm_same.root() == newrt);
        }

        appendRandomCommitment(tree);
        appendRandomCommitment(tree);

        newrt2 = tree.root();

        cache.PushAnchor(tree);
        BOOST_CHECK(cache.GetBestAnchor() == newrt2);

        ZCIncrementalMerkleTree test_tree;
        BOOST_CHECK(cache.GetAnchorAt(cache.GetBestAnchor(), test_tree));

        BOOST_CHECK(tree.root() == test_tree.root());

        {
            ZCIncrementalMerkleTree test_tree2;
            cache.GetAnchorAt(newrt, test_tree2);

            BOOST_CHECK(test_tree2.root() == newrt);
        }

        {
            cache.PopAnchor(newrt);
            ZCIncrementalMerkleTree obtain_tree;
            assert(!cache.GetAnchorAt(newrt2, obtain_tree)); // should have been popped off
            assert(cache.GetAnchorAt(newrt, obtain_tree));

            assert(obtain_tree.root() == newrt);
        }
    }
}

static const unsigned int NUM_SIMULATION_ITERATIONS = 40000;

// This is a large randomized insert/remove simulation test on a variable-size
// stack of caches on top of CCoinsViewTest.
//
// It will randomly create/update/delete CCoins entries to a tip of caches, with
// txids picked from a limited list of random 256-bit hashes. Occasionally, a
// new tip is added to the stack of caches, or the tip is flushed and removed.
//
// During the process, booleans are kept to make sure that the randomized
// operation hits all branches.
BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
{
    // Various coverage trackers.
    bool removed_all_caches = false;
    bool reached_4_caches = false;
    bool added_an_entry = false;
    bool removed_an_entry = false;
    bool updated_an_entry = false;
    bool found_an_entry = false;
    bool missed_an_entry = false;

    // A simple map to track what we expect the cache stack to represent.
    std::map<uint256, CCoins> result;

    // The cache stack.
    CCoinsViewTest base; // A CCoinsViewTest at the bottom.
    std::vector<CCoinsViewCacheTest*> stack; // A stack of CCoinsViewCaches on top.
    stack.push_back(new CCoinsViewCacheTest(&base)); // Start with one cache.

    // Use a limited set of random transaction ids, so we do test overwriting entries.
    std::vector<uint256> txids;
    txids.resize(NUM_SIMULATION_ITERATIONS / 8);
    for (unsigned int i = 0; i < txids.size(); i++) {
        txids[i] = GetRandHash();
    }

    for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) {
        // Do a random modification.
        {
            uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration.
            CCoins& coins = result[txid];
            CCoinsModifier entry = stack.back()->ModifyCoins(txid);
            BOOST_CHECK(coins == *entry);
            if (insecure_rand() % 5 == 0 || coins.IsPruned()) {
                if (coins.IsPruned()) {
                    added_an_entry = true;
                } else {
                    updated_an_entry = true;
                }
                coins.nVersion = insecure_rand();
                coins.vout.resize(1);
                coins.vout[0].nValue = insecure_rand();
                *entry = coins;
            } else {
                coins.Clear();
                entry->Clear();
                removed_an_entry = true;
            }
        }

        // Once every 1000 iterations and at the end, verify the full cache.
        if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
            for (std::map<uint256, CCoins>::iterator it = result.begin(); it != result.end(); it++) {
                const CCoins* coins = stack.back()->AccessCoins(it->first);
                if (coins) {
                    BOOST_CHECK(*coins == it->second);
                    found_an_entry = true;
                } else {
                    BOOST_CHECK(it->second.IsPruned());
                    missed_an_entry = true;
                }
            }
            BOOST_FOREACH(const CCoinsViewCacheTest *test, stack) {
                test->SelfTest();
            }
        }

        if (insecure_rand() % 100 == 0) {
            // Every 100 iterations, change the cache stack.
            if (stack.size() > 0 && insecure_rand() % 2 == 0) {
                stack.back()->Flush();
                delete stack.back();
                stack.pop_back();
            }
            if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) {
                CCoinsView* tip = &base;
                if (stack.size() > 0) {
                    tip = stack.back();
                } else {
                    removed_all_caches = true;
                }
                stack.push_back(new CCoinsViewCacheTest(tip));
                if (stack.size() == 4) {
                    reached_4_caches = true;
                }
            }
        }
    }

    // Clean up the stack.
    while (stack.size() > 0) {
        delete stack.back();
        stack.pop_back();
    }

    // Verify coverage.
    BOOST_CHECK(removed_all_caches);
    BOOST_CHECK(reached_4_caches);
    BOOST_CHECK(added_an_entry);
    BOOST_CHECK(removed_an_entry);
    BOOST_CHECK(updated_an_entry);
    BOOST_CHECK(found_an_entry);
    BOOST_CHECK(missed_an_entry);
}

BOOST_AUTO_TEST_CASE(coins_coinbase_spends)
{
    CCoinsViewTest base;
    CCoinsViewCacheTest cache(&base);

    // Create coinbase transaction
    CMutableTransaction mtx;
    mtx.vin.resize(1);
    mtx.vin[0].scriptSig = CScript() << OP_1;
    mtx.vin[0].nSequence = 0;
    mtx.vout.resize(1);
    mtx.vout[0].nValue = 500;
    mtx.vout[0].scriptPubKey = CScript() << OP_1;

    CTransaction tx(mtx);

    BOOST_CHECK(tx.IsCoinBase());

    CValidationState state;
    UpdateCoins(tx, state, cache, 100);

    // Create coinbase spend
    CMutableTransaction mtx2;
    mtx2.vin.resize(1);
    mtx2.vin[0].prevout = COutPoint(tx.GetHash(), 0);
    mtx2.vin[0].scriptSig = CScript() << OP_1;
    mtx2.vin[0].nSequence = 0;

    {
        CTransaction tx2(mtx2);
        BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus()));
    }

    mtx2.vout.resize(1);
    mtx2.vout[0].nValue = 500;
    mtx2.vout[0].scriptPubKey = CScript() << OP_1;

    {
        CTransaction tx2(mtx2);
        BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus()));
        BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs");
    }
}

BOOST_AUTO_TEST_CASE(ccoins_serialization)
{
    // Good example
    CDataStream ss1(ParseHex("0104835800816115944e077fe7c803cfa57f29b36bf87c1d358bb85e"), SER_DISK, CLIENT_VERSION);
    CCoins cc1;
    ss1 >> cc1;
    BOOST_CHECK_EQUAL(cc1.nVersion, 1);
    BOOST_CHECK_EQUAL(cc1.fCoinBase, false);
    BOOST_CHECK_EQUAL(cc1.nHeight, 203998);
    BOOST_CHECK_EQUAL(cc1.vout.size(), 2);
    BOOST_CHECK_EQUAL(cc1.IsAvailable(0), false);
    BOOST_CHECK_EQUAL(cc1.IsAvailable(1), true);
    BOOST_CHECK_EQUAL(cc1.vout[1].nValue, 60000000000ULL);
    BOOST_CHECK_EQUAL(HexStr(cc1.vout[1].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))))));

    // Good example
    CDataStream ss2(ParseHex("0109044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa486af3b"), SER_DISK, CLIENT_VERSION);
    CCoins cc2;
    ss2 >> cc2;
    BOOST_CHECK_EQUAL(cc2.nVersion, 1);
    BOOST_CHECK_EQUAL(cc2.fCoinBase, true);
    BOOST_CHECK_EQUAL(cc2.nHeight, 120891);
    BOOST_CHECK_EQUAL(cc2.vout.size(), 17);
    for (int i = 0; i < 17; i++) {
        BOOST_CHECK_EQUAL(cc2.IsAvailable(i), i == 4 || i == 16);
    }
    BOOST_CHECK_EQUAL(cc2.vout[4].nValue, 234925952);
    BOOST_CHECK_EQUAL(HexStr(cc2.vout[4].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("61b01caab50f1b8e9c50a5057eb43c2d9563a4ee"))))));
    BOOST_CHECK_EQUAL(cc2.vout[16].nValue, 110397);
    BOOST_CHECK_EQUAL(HexStr(cc2.vout[16].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"))))));

    // Smallest possible example
    CDataStream ssx(SER_DISK, CLIENT_VERSION);
    BOOST_CHECK_EQUAL(HexStr(ssx.begin(), ssx.end()), "");

    CDataStream ss3(ParseHex("0002000600"), SER_DISK, CLIENT_VERSION);
    CCoins cc3;
    ss3 >> cc3;
    BOOST_CHECK_EQUAL(cc3.nVersion, 0);
    BOOST_CHECK_EQUAL(cc3.fCoinBase, false);
    BOOST_CHECK_EQUAL(cc3.nHeight, 0);
    BOOST_CHECK_EQUAL(cc3.vout.size(), 1);
    BOOST_CHECK_EQUAL(cc3.IsAvailable(0), true);
    BOOST_CHECK_EQUAL(cc3.vout[0].nValue, 0);
    BOOST_CHECK_EQUAL(cc3.vout[0].scriptPubKey.size(), 0);

    // scriptPubKey that ends beyond the end of the stream
    CDataStream ss4(ParseHex("0002000800"), SER_DISK, CLIENT_VERSION);
    try {
        CCoins cc4;
        ss4 >> cc4;
        BOOST_CHECK_MESSAGE(false, "We should have thrown");
    } catch (const std::ios_base::failure& e) {
    }

    // Very large scriptPubKey (3*10^9 bytes) past the end of the stream
    CDataStream tmp(SER_DISK, CLIENT_VERSION);
    uint64_t x = 3000000000ULL;
    tmp << VARINT(x);
    BOOST_CHECK_EQUAL(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00");
    CDataStream ss5(ParseHex("0002008a95c0bb0000"), SER_DISK, CLIENT_VERSION);
    try {
        CCoins cc5;
        ss5 >> cc5;
        BOOST_CHECK_MESSAGE(false, "We should have thrown");
    } catch (const std::ios_base::failure& e) {
    }
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_stars_repo_name: TheTrunk/zelcash

max_issues_repo_name: TheTrunk/zelcash

max_forks_repo_name: TheTrunk/zelcash


text:
#ifndef VI_PID_CONFIG_HPP
#define VI_PID_CONFIG_HPP

// Libraries
#include <boost/cstdfloat.hpp>

// Ros
#include <ros/ros.h>

// Standard
#include <cstdint>
#include <string>

namespace vi
{

using float64_t = boost::float64_t; ///< Alias for 64 bit float

/// @brief Class to store config values for vehicle interface
class PIDConfig
{
public:
    /// @brief Default constructor
    /// @param pnh Private nodehandle used to snipe params
    PIDConfig(ros::NodeHandle& pnh, const std::string& prefix)
    {
        pnh.getParam(prefix + "_p",     m_p);
        pnh.getParam(prefix + "_i",     m_i);
        pnh.getParam(prefix + "_d",     m_d);
        pnh.getParam("max_dt_s",        m_max_dt_s);
        pnh.getParam("ctl_buffer_size", m_ctl_buffer_size);
    }

    /// @brief Default destructor for forward declares
    ~PIDConfig() = default;

    /// @brief Accessor
    /// @return Val
    /// @{
    float64_t    getPGain()             const noexcept {return m_p;}
    float64_t    getIGain()             const noexcept {return m_i;}
    float64_t    getDGain()             const noexcept {return m_d;}
    float64_t    getMaxDtS()            const noexcept {return m_max_dt_s;}
    std::int32_t getControlBufferSize() const noexcept {return m_ctl_buffer_size;}
    /// @}

private:
    /// @brief Gains
    /// @{
    float64_t m_p{0.0}; ///< Proportional gain
    float64_t m_i{0.0}; ///< Integral gain
    float64_t m_d{0.0}; ///< Derivative gain
    /// @}

    /// @brief Sanity checks
    /// @{
    float64_t m_max_dt_s; ///< Max allowable DT in seconds
    /// @}

    /// @brief Filter configs
    /// @{
    std::int32_t m_ctl_buffer_size{100};
    /// @}
};

} // namespace vi

#endif // VI_PID_CONFIG_HPP

ext: hpp


text:
/*
 *          Copyright Andrey Semashev 2007 - 2010.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
/*!
 * \file   channel_feature.hpp
 * \author Andrey Semashev
 * \date   28.02.2008
 *
 * The header contains implementation of a channel support feature.
 */

#if (defined(_MSC_VER) && _MSC_VER > 1000)
#pragma once
#endif // _MSC_VER > 1000

#ifndef BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/parameter/binding.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/log/detail/prologue.hpp>
#include <boost/log/keywords/channel.hpp>
#include <boost/log/attributes/constant.hpp>
#include <boost/log/sources/threading_models.hpp> // strictest_lock
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/thread/locks.hpp>
#endif // !defined(BOOST_LOG_NO_THREADS)

#ifdef _MSC_VER
#pragma warning(push)
// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B'
#pragma warning(disable: 4251)
#endif // _MSC_VER

namespace boost {

namespace BOOST_LOG_NAMESPACE {

namespace sources {

namespace aux {

    //! A helper traits to get channel attribute name constant in the proper type
    template< typename >
    struct channel_attribute_name;

#ifdef BOOST_LOG_USE_CHAR
    template< >
    struct channel_attribute_name< char >
    {
        static const char* get() { return "Channel"; }
    };
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
    template< >
    struct channel_attribute_name< wchar_t >
    {
        static const wchar_t* get() { return L"Channel"; }
    };
#endif

} // namespace aux

/*!
 * \brief Channel feature implementation
 */
template< typename BaseT, typename ChannelT >
class basic_channel_logger :
    public BaseT
{
    //! Base type
    typedef BaseT base_type;

public:
    //! Character type
    typedef typename base_type::char_type char_type;
    //! Final type
    typedef typename base_type::final_type final_type;
    //! Attribute set type
    typedef typename base_type::attribute_set_type attribute_set_type;
    //! String type
    typedef typename base_type::string_type string_type;
    //! Threading model being used
    typedef typename base_type::threading_model threading_model;

    //! Channel type
    typedef ChannelT channel_type;
    //! Channel attribute type
    typedef attributes::constant< channel_type > channel_attribute;

private:
    //! Channel attribute
    shared_ptr< channel_attribute > m_pChannel;

public:
    /*!
     * Default constructor. The constructed logger does not have the channel attribute.
     */
    basic_channel_logger() : base_type()
    {
    }
    /*!
     * Copy constructor
     */
    basic_channel_logger(basic_channel_logger const& that) :
        base_type(static_cast< base_type const& >(that)),
        m_pChannel(that.m_pChannel)
    {
    }
    /*!
     * Constructor with arguments. Allows to register a channel name attribute on construction.
     *
     * \param args A set of named arguments. The following arguments are supported:
     *             \li \c channel - a string that represents the channel name
     */
    template< typename ArgsT >
    explicit basic_channel_logger(ArgsT const& args) :
        base_type(args)
    {
        init_channel_attribute(args, typename is_void<
            typename parameter::binding< ArgsT, keywords::tag::channel, void >::type
        >::type());
    }

    /*!
     * The observer of the channel attribute presence
     *
     * \return \c true if the channel attribute is set by the logger, \c false otherwise
     */
    bool has_channel() const { return !!m_pChannel; }

    /*!
     * The observer of the channel name
     *
     * \pre <tt>this->has_channel() == true</tt>
     * \return The channel name that was set by the logger
     */
    channel_type const& channel() const { return m_pChannel->get(); }

protected:
    /*!
     * Channel attribute accessor
     */
    shared_ptr< channel_attribute > const& get_channel_attribute() const { return m_pChannel; }

    //! Lock requirement for the swap_unlocked method
    typedef typename strictest_lock<
        typename base_type::swap_lock,
#ifndef BOOST_LOG_NO_THREADS
        lock_guard< threading_model >
#else
        no_lock
#endif // !defined(BOOST_LOG_NO_THREADS)
    >::type swap_lock;

    /*!
     * Unlocked swap
     */
    void swap_unlocked(basic_channel_logger& that)
    {
        base_type::swap_unlocked(static_cast< base_type& >(that));
        m_pChannel.swap(that.m_pChannel);
    }

private:
#ifndef BOOST_LOG_DOXYGEN_PASS
    //! Initializes the channel attribute
    template< typename ArgsT >
    void init_channel_attribute(ArgsT const& args, mpl::false_ const&)
    {
        channel_type channel_name(args[keywords::channel]);
        m_pChannel = boost::make_shared< channel_attribute >(channel_name);
        base_type::add_attribute_unlocked(
            aux::channel_attribute_name< char_type >::get(),
            m_pChannel);
    }
    //! Initializes the channel attribute (dummy, if no channel is specified)
    template< typename ArgsT >
    void init_channel_attribute(ArgsT const& args, mpl::true_ const&)
    {
    }
#endif // BOOST_LOG_DOXYGEN_PASS
};

/*!
 * \brief Channel support feature
 *
 * The logger with this feature automatically registers constant attribute with the specified
 * on construction value, which is a channel name. The channel name cannot be modified
 * through the logger life time.
 *
 * The type of the channel name can be customized by providing it as a template parameter
 * to the feature template. By default, a string with the corresponding character type will be used.
 */
template< typename ChannelT = void >
struct channel
{
    template< typename BaseT >
    struct apply
    {
        typedef basic_channel_logger<
            BaseT,
            typename mpl::if_<
                is_void< ChannelT >,
                typename BaseT::string_type,
                ChannelT
            >::type
        > type;
    };
};

} // namespace sources

} // namespace log

} // namespace boost

#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER

#endif // BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_


text:
#include <stdexcept>

#include <Eigen/Geometry>
#include <gtest/gtest.h>

#include "drake/common/find_resource.h"
#include "drake/common/test_utilities/eigen_matrix_compare.h"
#include "drake/examples/quadrotor/quadrotor_plant.h"
#include "drake/math/rigid_transform.h"
#include "drake/multibody/parsing/parser.h"
#include "drake/multibody/plant/multibody_plant.h"
#include "drake/systems/analysis/simulator.h"
#include "drake/systems/framework/diagram.h"
#include "drake/systems/framework/diagram_builder.h"
#include "drake/systems/primitives/constant_vector_source.h"

namespace drake {
namespace examples {
namespace quadrotor {
namespace {

using Eigen::Quaterniond;
using Eigen::VectorXd;
using Eigen::Vector3d;
using math::RigidTransformd;
using math::RollPitchYawd;
using multibody::Body;
using multibody::MultibodyPlant;
using multibody::Parser;
using multibody::SpatialVelocity;
using systems::ConstantVectorSource;
using systems::Context;
using systems::ContinuousState;
using systems::Diagram;
using systems::DiagramBuilder;
using systems::Simulator;

// This test program compares the behaviour of two plants:
//
// (#1) a GenericQuadrotor created from a QuadrotorPlant, and
//
// (#2) a MultibodyQuadrotor created from parsing a corresponding model URDF
// file into a MultibodyPlant.
//
// Both types of plant provide a method SetState whose argument is organized as
// [x, y, z, r, p, y, xdot, ydot, zdot, rdot, pdot, ydot], but the underlying
// State representation in the Context is NOT necessarily organized that way.
//
// Both types also provide GetPose.

// The models are integrated and compared for the duration specified by the
// following constant.
const double kSimulationDuration = 0.1;

// Case (#1): The Diagram that wraps a QuadrotorPlant.
class GenericQuadrotor: public Diagram<double> {
 public:
  GenericQuadrotor() {
    DiagramBuilder<double> builder;
    plant_ = builder.template AddSystem<QuadrotorPlant<double>>();
    auto* source = builder.template AddSystem<ConstantVectorSource<double>>(
        VectorXd::Zero(plant_->num_total_inputs()));
    builder.Cascade(*source, *plant_);
    builder.BuildInto(this);
  }

  // The `x` is a 12-element state vector per the file overview.
  void SetState(Context<double>* context, const VectorXd& x) const {
    DRAKE_DEMAND(x.size() == 12);
    Context<double>& plant_context =
        this->GetMutableSubsystemContext(*plant_, context);
    plant_context.SetContinuousState(x);
  }

  RigidTransformd GetPose(const Context<double>& context) const {
    const VectorXd state =
        context.get_continuous_state().get_vector().CopyToVector();
    const Vector3d xyz = state.segment(0, 3);
    const Vector3d rpy = state.segment(6, 3);
    return RigidTransformd(RollPitchYawd(rpy), xyz);
  }

 private:
  QuadrotorPlant<double>* plant_{};
};

// Case (#2): The Diagram that wraps a MultibodyPlant.
class MultibodyQuadrotor: public Diagram<double> {
 public:
  MultibodyQuadrotor() {
    auto owned_plant = std::make_unique<MultibodyPlant<double>>(0.0);
    plant_ = owned_plant.get();
    Parser(plant_).AddModelFromFile(FindResourceOrThrow(
        "drake/examples/quadrotor/quadrotor.urdf"));
    plant_->Finalize();
    body_ = &plant_->GetBodyByName("base_link");
    DiagramBuilder<double> builder;
    builder.AddSystem(std::move(owned_plant));
    builder.BuildInto(this);
  }

  // The `x` is a 12-element state vector per the file overview.
  void SetState(Context<double>* context, const VectorXd& x) const {
    // Unpack x into its elements as given by the file overview.
    const Vector3d xyz = x.segment(0, 3);
    const Vector3d rpy = x.segment(3, 3);
    const Vector3d xyz_dot = x.segment(6, 3);
    const Vector3d rpy_dot = x.segment(9, 3);

    // Convert the state values into our conventional multibody types.
    const Vector3d p_WB(xyz);
    const RollPitchYawd R_WB(rpy);
    const Vector3d v_WB(xyz_dot);
    const Vector3d w_WB = R_WB.CalcAngularVelocityInParentFromRpyDt(rpy_dot);
    const RigidTransformd X_WB(R_WB, p_WB);
    const SpatialVelocity<double> V_WB(w_WB, v_WB);

    // Set the state of the base_link.
    Context<double>& plant_context =
        this->GetMutableSubsystemContext(*plant_, context);
    plant_->SetFreeBodyPoseInWorldFrame(&plant_context, *body_, X_WB);
    plant_->SetFreeBodySpatialVelocity(&plant_context, *body_, V_WB);
  }

  RigidTransformd GetPose(const Context<double>& context) const {
    const Context<double>& plant_context =
        this->GetSubsystemContext(*plant_, context);
    return plant_->EvalBodyPoseInWorld(plant_context, *body_);
  }

 private:
  MultibodyPlant<double>* plant_{};
  const Body<double>* body_{};
};

void TestPassiveBehavior(const VectorXd& x0) {
  const GenericQuadrotor ge_model;
  const MultibodyQuadrotor mb_model;
  Simulator<double> ge_simulator(ge_model);
  Simulator<double> mb_simulator(mb_model);
  auto& ge_context = ge_simulator.get_mutable_context();
  auto& mb_context = mb_simulator.get_mutable_context();

  ge_model.SetState(&ge_context, x0);
  mb_model.SetState(&mb_context, x0);
  ge_simulator.AdvanceTo(kSimulationDuration);
  mb_simulator.AdvanceTo(kSimulationDuration);

  const RigidTransformd ge_pose = ge_model.GetPose(ge_context);
  const RigidTransformd mb_pose = mb_model.GetPose(mb_context);
  EXPECT_TRUE(CompareMatrices(
        ge_pose.translation(), mb_pose.translation(),
        1e-10, MatrixCompareType::absolute));
  EXPECT_TRUE(ge_pose.rotation().IsNearlyEqualTo(ge_pose.rotation(), 1e-10));
}

// Test comparing the state for of each kind of plant under passive behaviour.
// Each plant is dropped from rest at the origin.
GTEST_TEST(QuadrotorDynamicsTest, DropFromRest) {
  VectorXd x0 = VectorXd::Zero(12);
  TestPassiveBehavior(x0);
}

// Test comparing the state for of each kind of plant under passive behaviour.
// Each plant is dropped from the origin with an initial translational velocity.
GTEST_TEST(QuadrotorDynamicsTest, DropFromInitialVelocity) {
  VectorXd x0 = VectorXd::Zero(12);
  x0.segment(6, 3) << 1, 1, 1;  // Some translational velocity.
  TestPassiveBehavior(x0);
}

// Test comparing the state for of each kind of plant under passive behaviour.
// Each plant is dropped from the origin with an initial rotational velocity.
GTEST_TEST(QuadrotorDynamicsTest, DropFromInitialRotation) {
  VectorXd x0 = VectorXd::Zero(12);
  x0.segment(9, 3) << 1, 1, 1;  // Some rotary velocity.
  TestPassiveBehavior(x0);
}

// Test comparing the state for of each kind of plant under passive behaviour.
// Each plant is dropped from and arbitrary initial state.
GTEST_TEST(QuadrotorDynamicsTest, DropFromArbitraryState) {
  VectorXd x0 = VectorXd::Zero(12);
  x0 << 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6;  // Some initial state.
  TestPassiveBehavior(x0);
}

}  // namespace
}  // namespace quadrotor
}  // namespace examples
}  // namespace drake

ext: cc


text:
#include "JSONRPC.h"

#include <boost/asio.hpp>
#include <boost/exception/all.hpp>
#include "Util.h"
#include "Log.h"

using namespace boost::asio::ip;

bool JSONRPC::Connect(JSONRPCConnectionInfo connInfo)
{
    _connInfo = connInfo;

    if (_connInfo.B64Auth.empty())
        _connInfo.B64Auth = Util::ToBase64(_connInfo.User + ":" + _connInfo.Pass, false);

    sLog.Debug(LOG_JSONRPC, "JSONRPC::Connect(): B64Auth: %s", _connInfo.B64Auth.c_str());

    tcp::resolver resolver(_ios);
    tcp::resolver::query q(tcp::v4(), connInfo.Host, connInfo.Port);
    tcp::resolver::iterator epi = resolver.resolve(q);
    tcp::resolver::iterator end;

    boost::system::error_code error = boost::asio::error::host_not_found;

    while (error && epi != end)
    {
        _ep = *epi++;
        _sock.close();
        _sock.connect(_ep, error);
    }

    if (error) {
        _sock.close();
        throw JSONRPCException(Util::FS("JSONRPC::Connect(): Error connecting to '%s': %s", _connInfo.Host.c_str(), boost::system::system_error(error).what()));
    }

    _sock.close();

    return true;
}

JSON JSONRPC::Query(std::string method, JSON params)
{
    JSON request;
    request["jsonrpc"] = "1.0";
    request["id"] = int64(1);
    request["method"] = method;
    if (params.Size() > 0)
        request["params"] = params;
    std::string jsonstring = request.ToString();

    sLog.Debug(LOG_JSONRPC, "JSONRPC::Query(): JSONString: %s", jsonstring.c_str());

    boost::system::error_code error;

    _sock.close();
    _sock.connect(_ep, error);

    if (error) {
        _sock.close();
        throw JSONRPCException(Util::FS("JSONRPC::Connect(): Error connecting to '%s': %s", _connInfo.Host.c_str(), boost::system::system_error(error).what()));
    }

    boost::asio::streambuf request_buf;
    std::ostream request_info(&request_buf);
    request_info << "POST / HTTP/1.1\n";
    request_info << "Host: 127.0.0.1\n";
    request_info << "Content-Type: application/json-rpc\n";
    request_info << "Authorization: Basic " << _connInfo.B64Auth << "\n";
    request_info << "Content-Length: " << jsonstring.size() << "\n\n";
    request_info << jsonstring;

    boost::asio::write(_sock, request_buf);

    boost::asio::streambuf response;
    boost::asio::read_until(_sock, response, "\n");

    std::istream response_stream(&response);

    std::string http_version;
    uint32_t status_code;
    std::string status_message;

    response_stream >> http_version >> status_code;
    std::getline(response_stream, status_message);

    if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
        _sock.close();
        throw JSONRPCException("JSONRPC::Query(): Malformed HTTP Response");
    }

    if (status_code != 200) {
        _sock.close();
        throw JSONRPCException(Util::FS("JSONRPC::Query(): Returned status code: %u", status_code));
    }

    std::vector<std::string> headers;
    std::string header;
    while (std::getline(response_stream, header) && header != "\r")
        headers.push_back(header);

    std::string jsonresponse = "";

    if (_sock.available())
        boost::asio::read_until(_sock, response, '\n');

    if (response.size() > 0) {
        std::ostringstream oss;
        oss << &response;
        jsonresponse += oss.str();
    }

    _sock.close();

    sLog.Debug(LOG_JSONRPC, "JSONRPC::Query(): JSON Response: %s", jsonresponse.c_str());

    JSON data = JSON::FromString(jsonresponse);

    return data["result"];
}

max_stars_repo_name: chemicstry/poolserver

max_issues_repo_name: chemicstry/poolserver

max_forks_repo_name: chemicstry/poolserver