<commit_before>#include "artworkrepository_tests.h"
#include <QSignalSpy>
#include "../../xpiks-qt/Models/artworksrepository.h"
#include "Mocks/commandmanagermock.h"

void ArtworkRepositoryTests::simpleAccountFileTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename = "C:/path/to/some/file";
    QString directory = "C:/path/to/some";
#else
    QString filename = "/path/to/some/file";
    QString directory = "/path/to/some";
#endif
    qint64 dirID = 0;
    bool status = repository.accountFile(filename, dirID);

    QCOMPARE(status, true);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
    QCOMPARE(repository.getDirectory(0), directory);
    QCOMPARE(repository.getFilesCountForDirectory(directory), 1);
}

void ArtworkRepositoryTests::accountSameFileTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename = "C:/path/to/some/file";
    QString directory = "C:/path/to/some";
#else
    QString filename = "/path/to/some/file";
    QString directory = "/path/to/some";
#endif

    qint64 dirID = 0;
    repository.accountFile(filename, dirID);
    bool status = repository.accountFile(filename, dirID);

    QCOMPARE(status, false);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
    QCOMPARE(repository.getDirectory(0), directory);
    QCOMPARE(repository.getFilesCountForDirectory(directory), 1);
}

void ArtworkRepositoryTests::addFilesFromOneDirectoryTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);;

#ifdef Q_OS_WIN
    QString filenameTemplate = "C:/path/to/some/file%1.jpg";
    QString directory = "C:/path/to/some";
#else
    QString filenameTemplate = "/path/to/some/file%1.jpg";
    QString directory = "/path/to/some";
    #endif

    bool anyWrong = false;
    int count = 5;
    while (count--) {
        QString filename = filenameTemplate.arg(5 - count - 1);
        qint64 dirID = 0;
        if (!repository.accountFile(filename, dirID)) {
            anyWrong = true;
        }
    }

    QCOMPARE(anyWrong, false);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
    QCOMPARE(repository.getFilesCountForDirectory(directory), 5);
}

void ArtworkRepositoryTests::addAndRemoveSameFileTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename = "C:/path/to/some/file";
    QString directory = "C:/path/to/some";
#else
    QString filename = "/path/to/some/file";
    QString directory = "/path/to/some";
#endif

    qint64 dirID = 0;
    bool status = repository.accountFile(filename, dirID);
    QCOMPARE(status, true);

    bool removeResult = repository.removeFile(filename, directory);
    repository.cleanupEmptyDirectories();

    QCOMPARE(repository.getArtworksSourcesCount(), 0);
    QCOMPARE(removeResult, true);
}

void ArtworkRepositoryTests::removeNotExistingFileTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
    QString directory = "C:/path/to/some";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
    QString directory = "/path/to/some";
#endif

    qint64 dirID = 0;
    bool status = repository.accountFile(filename1, dirID);
    QCOMPARE(status, true);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);

    bool removeResult = repository.removeFile(filename2, directory);
    repository.cleanupEmptyDirectories();

    QCOMPARE(removeResult, false);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
}

void ArtworkRepositoryTests::brandNewDirectoriesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    int newDirsCount = repository.getNewDirectoriesCount(files);
    QCOMPARE(newDirsCount, 1);
    QCOMPARE(repository.getArtworksSourcesCount(), 0);
    QCOMPARE(repository.rowCount(), 0);
}

void ArtworkRepositoryTests::differentNewDirectoriesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/other/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/other/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    int newDirsCount = repository.getNewDirectoriesCount(files);
    QCOMPARE(newDirsCount, files.length());
    QCOMPARE(repository.getArtworksSourcesCount(), 0);
    QCOMPARE(repository.rowCount(), 0);
}

void ArtworkRepositoryTests::newFilesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    int newFilesCount = repository.getNewFilesCount(files);
    QCOMPARE(newFilesCount, files.length());
    QCOMPARE(repository.getArtworksSourcesCount(), 0);
    QCOMPARE(repository.rowCount(), 0);
}

void ArtworkRepositoryTests::noNewDirectoriesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
#endif

    qint64 dirID = 0;
    repository.accountFile(filename1, dirID);

    QStringList files;
    files << filename2;

    int newFilesCount = repository.getNewDirectoriesCount(files);
    QCOMPARE(newFilesCount, 0);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
}

void ArtworkRepositoryTests::noNewFilesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    qint64 dirID = 0;
    foreach (const QString &file, files) {
        repository.accountFile(file, dirID);
    }

    int newFilesCount = repository.getNewFilesCount(files);
    QCOMPARE(newFilesCount, 0);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
}

void ArtworkRepositoryTests::endAccountingWithNoNewFilesTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);
    QSignalSpy endSpy(&repository, SIGNAL(rowsInserted(QModelIndex,int,int)));

    repository.endAccountingFiles(false);
    QVERIFY(endSpy.isEmpty());
}

void ArtworkRepositoryTests::startAccountingNewFilesEmitsTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/other/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/other/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    QSignalSpy beginSpy(&repository, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
    bool newFiles = repository.beginAccountingFiles(files);

    QCOMPARE(newFiles, true);
    QCOMPARE(beginSpy.count(), 1);
    QList<QVariant> addArguments = beginSpy.takeFirst();
    QCOMPARE(addArguments.at(1).toInt(), 0);
    QCOMPARE(addArguments.at(2).toInt(), files.length() - 1);
}

void ArtworkRepositoryTests::selectFolderTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path1/to/some/file";
    QString filename2 = "C:/path2/to/some/file";
    QString filename3 = "C:/path3/to/some/file";
    QString filename4 = "C:/path4/to/some/file";
#else
    QString filename1 = "/path1/to/some/file";
    QString filename2 = "/path2/to/some/file";
    QString filename3 = "/path3/to/some/file";
    QString filename4 = "/path4/to/some/file";
#endif

    QStringList files;
    files << filename1 << filename2 << filename3;

    std::vector<qint64> dirIDs;
    foreach (const QString &file, files) {
        qint64 dirID;
        repository.accountFile(file, dirID);
        dirIDs.push_back(dirID);
    }

    // Initially all directories are selected.
    QCOMPARE(repository.isDirSelected(dirIDs[0]), true);
    QCOMPARE(repository.isDirSelected(dirIDs[1]), true);
    QCOMPARE(repository.isDirSelected(dirIDs[2]), true);

    //If All are selected and you click on 1, you select it and deselect others.
    repository.setDirSelected(0);
    QCOMPARE(repository.isDirSelected(dirIDs[0]), true);
    QCOMPARE(repository.isDirSelected(dirIDs[1]), false);
    QCOMPARE(repository.isDirSelected(dirIDs[2]), false);

    //If not all are selected and you click on 1, you add it to the selection.
    repository.setDirSelected(2);
    QCOMPARE(repository.isDirSelected(dirIDs[0]), true);
    QCOMPARE(repository.isDirSelected(dirIDs[1]), false);
    QCOMPARE(repository.isDirSelected(dirIDs[2]), true);

    repository.setDirSelected(0);
    QCOMPARE(repository.isDirSelected(dirIDs[0]), false);
    QCOMPARE(repository.isDirSelected(dirIDs[1]), false);
    QCOMPARE(repository.isDirSelected(dirIDs[2]), true);

    //If you unselect last selected, all get selected.
    repository.setDirSelected(2);
    QCOMPARE(repository.isDirSelected(dirIDs[0]), true);
    QCOMPARE(repository.isDirSelected(dirIDs[1]), true);
    QCOMPARE(repository.isDirSelected(dirIDs[2]), true);

    repository.setDirSelected(2);
    QCOMPARE(repository.isDirSelected(dirIDs[0]), false);
    QCOMPARE(repository.isDirSelected(dirIDs[1]), false);
    QCOMPARE(repository.isDirSelected(dirIDs[2]), true);

    //If you remove last selected directory, all get selected.
    repository.removeItem(2);
    QCOMPARE(repository.isDirSelected(dirIDs[0]), true);
    QCOMPARE(repository.isDirSelected(dirIDs[1]), true);

    //If you add a new directory, it gets selected by default.
    qint64 dirID;
    repository.accountFile(filename4, dirID);
    dirIDs.push_back(dirID);
    QCOMPARE(repository.isDirSelected(dirIDs[3]), true);

}
<commit_msg>Fixes for tests<commit_after>#include "artworkrepository_tests.h"
#include <QSignalSpy>
#include "../../xpiks-qt/Models/artworksrepository.h"
#include "Mocks/commandmanagermock.h"

void ArtworkRepositoryTests::simpleAccountFileTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename = "C:/path/to/some/file";
    QString directory = "C:/path/to/some";
#else
    QString filename = "/path/to/some/file";
    QString directory = "/path/to/some";
#endif
    qint64 dirID = 0;
    bool status = repository.accountFile(filename, dirID);

    QCOMPARE(status, true);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
    QCOMPARE(repository.getDirectory(0), directory);
    QCOMPARE(repository.getFilesCountForDirectory(directory), 1);
}

void ArtworkRepositoryTests::accountSameFileTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename = "C:/path/to/some/file";
    QString directory = "C:/path/to/some";
#else
    QString filename = "/path/to/some/file";
    QString directory = "/path/to/some";
#endif

    qint64 dirID = 0;
    repository.accountFile(filename, dirID);
    bool status = repository.accountFile(filename, dirID);

    QCOMPARE(status, false);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
    QCOMPARE(repository.getDirectory(0), directory);
    QCOMPARE(repository.getFilesCountForDirectory(directory), 1);
}

void ArtworkRepositoryTests::addFilesFromOneDirectoryTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);;

#ifdef Q_OS_WIN
    QString filenameTemplate = "C:/path/to/some/file%1.jpg";
    QString directory = "C:/path/to/some";
#else
    QString filenameTemplate = "/path/to/some/file%1.jpg";
    QString directory = "/path/to/some";
    #endif

    bool anyWrong = false;
    int count = 5;
    while (count--) {
        QString filename = filenameTemplate.arg(5 - count - 1);
        qint64 dirID = 0;
        if (!repository.accountFile(filename, dirID)) {
            anyWrong = true;
        }
    }

    QCOMPARE(anyWrong, false);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
    QCOMPARE(repository.getFilesCountForDirectory(directory), 5);
}

void ArtworkRepositoryTests::addAndRemoveSameFileTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename = "C:/path/to/some/file";
    QString directory = "C:/path/to/some";
#else
    QString filename = "/path/to/some/file";
    QString directory = "/path/to/some";
#endif

    qint64 dirID = 0;
    bool status = repository.accountFile(filename, dirID);
    QCOMPARE(status, true);

    bool removeResult = repository.removeFile(filename, directory);
    repository.cleanupEmptyDirectories();

    QCOMPARE(repository.getArtworksSourcesCount(), 0);
    QCOMPARE(removeResult, true);
}

void ArtworkRepositoryTests::removeNotExistingFileTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
    QString directory = "C:/path/to/some";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
    QString directory = "/path/to/some";
#endif

    qint64 dirID = 0;
    bool status = repository.accountFile(filename1, dirID);
    QCOMPARE(status, true);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);

    bool removeResult = repository.removeFile(filename2, directory);
    repository.cleanupEmptyDirectories();

    QCOMPARE(removeResult, false);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
}

void ArtworkRepositoryTests::brandNewDirectoriesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    int newDirsCount = repository.getNewDirectoriesCount(files);
    QCOMPARE(newDirsCount, 1);
    QCOMPARE(repository.getArtworksSourcesCount(), 0);
    QCOMPARE(repository.rowCount(), 0);
}

void ArtworkRepositoryTests::differentNewDirectoriesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/other/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/other/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    int newDirsCount = repository.getNewDirectoriesCount(files);
    QCOMPARE(newDirsCount, files.length());
    QCOMPARE(repository.getArtworksSourcesCount(), 0);
    QCOMPARE(repository.rowCount(), 0);
}

void ArtworkRepositoryTests::newFilesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    int newFilesCount = repository.getNewFilesCount(files);
    QCOMPARE(newFilesCount, files.length());
    QCOMPARE(repository.getArtworksSourcesCount(), 0);
    QCOMPARE(repository.rowCount(), 0);
}

void ArtworkRepositoryTests::noNewDirectoriesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
#endif

    qint64 dirID = 0;
    repository.accountFile(filename1, dirID);

    QStringList files;
    files << filename2;

    int newFilesCount = repository.getNewDirectoriesCount(files);
    QCOMPARE(newFilesCount, 0);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
}

void ArtworkRepositoryTests::noNewFilesCountTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    qint64 dirID = 0;
    foreach (const QString &file, files) {
        repository.accountFile(file, dirID);
    }

    int newFilesCount = repository.getNewFilesCount(files);
    QCOMPARE(newFilesCount, 0);
    QCOMPARE(repository.getArtworksSourcesCount(), 1);
}

void ArtworkRepositoryTests::endAccountingWithNoNewFilesTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);
    QSignalSpy endSpy(&repository, SIGNAL(rowsInserted(QModelIndex,int,int)));

    repository.endAccountingFiles(false);
    QVERIFY(endSpy.isEmpty());
}

void ArtworkRepositoryTests::startAccountingNewFilesEmitsTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path/to/some/file1";
    QString filename2 = "C:/path/to/some/other/file2";
#else
    QString filename1 = "/path/to/some/file1";
    QString filename2 = "/path/to/some/other/file2";
#endif

    QStringList files;
    files << filename1 << filename2;

    QSignalSpy beginSpy(&repository, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
    bool newFiles = repository.beginAccountingFiles(files);

    QCOMPARE(newFiles, true);
    QCOMPARE(beginSpy.count(), 1);
    QList<QVariant> addArguments = beginSpy.takeFirst();
    QCOMPARE(addArguments.at(1).toInt(), 0);
    QCOMPARE(addArguments.at(2).toInt(), files.length() - 1);
}

void ArtworkRepositoryTests::selectFolderTest() {
    Mocks::CommandManagerMock commandManagerMock;
    Models::ArtworksRepository repository;
    commandManagerMock.InjectDependency(&repository);

#ifdef Q_OS_WIN
    QString filename1 = "C:/path1/to/some/file";
    QString filename2 = "C:/path2/to/some/file";
    QString filename3 = "C:/path3/to/some/file";
    QString filename4 = "C:/path4/to/some/file";
#else
    QString filename1 = "/path1/to/some/file";
    QString filename2 = "/path2/to/some/file";
    QString filename3 = "/path3/to/some/file";
    QString filename4 = "/path4/to/some/file";
#endif

    QStringList files;
    files << filename1 << filename2 << filename3;

    std::vector<qint64> dirIDs;
    foreach (const QString &file, files) {
        qint64 dirID;
        repository.accountFile(file, dirID);
        dirIDs.push_back(dirID);
    }

    // Initially all directories are selected.
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[0]), true);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[1]), true);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[2]), true);

    //If All are selected and you click on 1, you select it and deselect others.
    repository.selectDirectory(0);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[0]), true);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[1]), false);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[2]), false);

    //If not all are selected and you click on 1, you add it to the selection.
    repository.selectDirectory(2);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[0]), true);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[1]), false);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[2]), true);

    repository.selectDirectory(0);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[0]), false);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[1]), false);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[2]), true);

    //If you unselect last selected, all get selected.
    repository.selectDirectory(2);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[0]), true);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[1]), true);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[2]), true);

    repository.selectDirectory(2);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[0]), false);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[1]), false);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[2]), true);

    //If you remove last selected directory, all get selected.
    repository.removeItem(2);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[0]), true);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[1]), true);

    //If you add a new directory, it gets selected by default.
    qint64 dirID;
    repository.accountFile(filename4, dirID);
    dirIDs.push_back(dirID);
    QCOMPARE(repository.isDirectoryIncluded(dirIDs[3]), true);

}
<|endoftext|>


<commit_before>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <cstring>

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class T> struct UnaryAction {
  Handle<Value> apply(Buffer& buffer, const Arguments& args);

  Handle<Value> operator()(const Arguments& args) {
    if (args[0]->IsObject()) {
      Local<Object> object = args[0]->ToObject();
      if (Buffer::HasInstance(object)) {
        Buffer& buffer = *ObjectWrap::Unwrap<Buffer>(object);
        return static_cast<T*>(this)->apply(buffer, args);
      }
    }
    static Persistent<String> notBufferError = Persistent<String>::New(String::New("First argument should be a buffer."));
    return ThrowException(Exception::TypeError(notBufferError));
  }
};

template <class T> struct BinaryAction {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args);

  Handle<Value> operator()(const Arguments& args) {
    if (args[0]->IsObject() && args[1]->IsObject()) {
      Local<Object> arg0 = args[0]->ToObject();
      Local<Object> arg1 = args[0]->ToObject();
      if (Buffer::HasInstance(arg0) && Buffer::HasInstance(arg1)) {
        Buffer& a = *ObjectWrap::Unwrap<Buffer>(arg0);
        Buffer& b = *ObjectWrap::Unwrap<Buffer>(arg1);
        return static_cast<T*>(this)->apply(a, b, args);
      }
    }
    static Persistent<String> notBufferError = Persistent<String>::New(String::New("First and second argument should be a buffer."));
    return ThrowException(Exception::TypeError(notBufferError));
  }
};

struct ClearAction: UnaryAction<ClearAction> {
  Handle<Value> apply(Buffer& buffer, const Arguments& args) {
    const int c = args[1]->IsInt32() ? args[1]->ToInt32()->Int32Value() : 0;
    memset(buffer.data(), c, buffer.length());
    return buffer.handle_;
  }
};

int compare(Buffer& a, Buffer& b) {
  if (a.length() != b.length()) {
    return a.length() > b.length() ? 1 : -1;
  }
  return memcmp(a.data(), b.data(), a.length());
}

struct EqualsAction: BinaryAction<EqualsAction> {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
    HandleScope scope;
    return scope.Close(Boolean::New(compare(a, b)));
  }
};

struct CompareAction: BinaryAction<CompareAction> {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
    HandleScope scope;
    return scope.Close(Integer::New(compare(a, b)));
  }
};

Handle<Value> Clear(const Arguments& args) {
  return ClearAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
  return CompareAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
  return CompareAction()(args);
}

extern "C" void init(Handle<Object> target) {
  HandleScope scope;

  target->Set(String::New("clear"), FunctionTemplate::New(Clear)->GetFunction());
  target->Set(String::New("equals"), FunctionTemplate::New(Equals)->GetFunction());
  target->Set(String::New("compare"), FunctionTemplate::New(Compare)->GetFunction());
}

}
<commit_msg>Add fill() function.<commit_after>#include <v8.h>
#include <node.h>
#include <node_buffer.h>

#include <cstring>

using namespace v8;
using namespace node;

namespace {

// this is an application of the Curiously Recurring Template Pattern
template <class T> struct UnaryAction {
  Handle<Value> apply(Buffer& buffer, const Arguments& args);

  Handle<Value> operator()(const Arguments& args) {
    if (args[0]->IsObject()) {
      Local<Object> object = args[0]->ToObject();
      if (Buffer::HasInstance(object)) {
        Buffer& buffer = *ObjectWrap::Unwrap<Buffer>(object);
        return static_cast<T*>(this)->apply(buffer, args);
      }
    }
    static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First argument should be a buffer."));
    return ThrowException(Exception::TypeError(illegalArgumentException));
  }
};

template <class T> struct BinaryAction {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args);

  Handle<Value> operator()(const Arguments& args) {
    if (args[0]->IsObject() && args[1]->IsObject()) {
      Local<Object> arg0 = args[0]->ToObject();
      Local<Object> arg1 = args[0]->ToObject();
      if (Buffer::HasInstance(arg0) && Buffer::HasInstance(arg1)) {
        Buffer& a = *ObjectWrap::Unwrap<Buffer>(arg0);
        Buffer& b = *ObjectWrap::Unwrap<Buffer>(arg1);
        return static_cast<T*>(this)->apply(a, b, args);
      }
    }
    static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New("First and second argument should be a buffer."));
    return ThrowException(Exception::TypeError(illegalArgumentException));
  }
};

//
// helper functions
//
Handle<Value> clear(Buffer& buffer, int c) {
  memset(buffer.data(), c, buffer.length());
  return buffer.handle_;
}

Handle<Value> fill(Buffer& buffer, void* pattern, size_t size) {
  if (size >= buffer.length()) {
    memcpy(buffer.data(), pattern, buffer.length());
  } else {
    const int n_copies = buffer.length() / size;
    const int remainder = buffer.length() % size;
    for (int i = 0; i < n_copies; i++) {
      memcpy(buffer.data() + size * i, pattern, size);
    }
    memcpy(buffer.data() + size * n_copies, pattern, remainder);
  }
  return buffer.handle_;
}

int compare(Buffer& a, Buffer& b) {
  if (a.length() != b.length()) {
    return a.length() > b.length() ? 1 : -1;
  }
  return memcmp(a.data(), b.data(), a.length());
}

//
// actions
//
struct ClearAction: UnaryAction<ClearAction> {
  Handle<Value> apply(Buffer& buffer, const Arguments& args) {
    const int c = args[1]->IsInt32() ? args[1]->ToInt32()->Int32Value() : 0;
    return clear(buffer, c);
  }
};

struct FillAction: UnaryAction<FillAction> {
  Handle<Value> apply(Buffer& buffer, const Arguments& args) {
    if (args[1]->IsInt32()) {
      int c = args[1]->ToInt32()->Int32Value();
      return clear(buffer, c);
    }
    if (args[1]->IsString()) {
      String::AsciiValue s(args[1]->ToString());
      return fill(buffer, *s, s.length());
    }
    if (args[1]->IsObject()) {
      Local<Object> o = args[1]->ToObject();
      if (Buffer::HasInstance(o)) {
        Buffer& src = *Buffer::Unwrap<Buffer>(o);
        return fill(buffer, src.data(), src.length());
      }
    }
    static Persistent<String> illegalArgumentException = Persistent<String>::New(String::New(
        "Second argument should be either a string, a buffer or an integer."));
    return ThrowException(Exception::TypeError(illegalArgumentException));
  }
};

struct EqualsAction: BinaryAction<EqualsAction> {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
    HandleScope scope;
    return scope.Close(Boolean::New(compare(a, b)));
  }
};

struct CompareAction: BinaryAction<CompareAction> {
  Handle<Value> apply(Buffer& a, Buffer& b, const Arguments& args) {
    HandleScope scope;
    return scope.Close(Integer::New(compare(a, b)));
  }
};

//
// V8 function callbacks
//
Handle<Value> Clear(const Arguments& args) {
  return ClearAction()(args);
}

Handle<Value> Fill(const Arguments& args) {
  return FillAction()(args);
}

Handle<Value> Equals(const Arguments& args) {
  return CompareAction()(args);
}

Handle<Value> Compare(const Arguments& args) {
  return CompareAction()(args);
}

extern "C" void init(Handle<Object> target) {
  HandleScope scope;
  target->Set(String::New("fill"), FunctionTemplate::New(Fill)->GetFunction());
  target->Set(String::New("clear"), FunctionTemplate::New(Clear)->GetFunction());
  target->Set(String::New("equals"), FunctionTemplate::New(Equals)->GetFunction());
  target->Set(String::New("compare"), FunctionTemplate::New(Compare)->GetFunction());
}

}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <string>
#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/contrib/lite/context.h"
#include "tensorflow/contrib/lite/kernels/kernel_util.h"
#include "tensorflow/contrib/lite/kernels/test_util.h"
#include "tensorflow/contrib/lite/model.h"
#include "tensorflow/contrib/lite/profiling/profile_summarizer.h"
#include "tensorflow/contrib/lite/testing/util.h"
#include "tensorflow/contrib/lite/version.h"

namespace tflite {
namespace profiling {

namespace {

#ifdef TFLITE_PROFILING_ENABLED
TfLiteStatus SimpleOpEval(TfLiteContext* context, TfLiteNode* node) {
  const TfLiteTensor* input1 = tflite::GetInput(context, node, /*index=*/0);
  const TfLiteTensor* input2 = tflite::GetInput(context, node, /*index=*/1);

  TfLiteTensor* output = GetOutput(context, node, /*index=*/0);

  int32_t* output_data = output->data.i32;
  *output_data = *(input1->data.i32) + *(input2->data.i32);
  return kTfLiteOk;
}

const char* SimpleOpProfilingString(const TfLiteContext* context,
                                    const TfLiteNode* node) {
  return "Profile";
}

TfLiteRegistration* RegisterSimpleOp() {
  static TfLiteRegistration registration = {
      nullptr,        nullptr, nullptr,
      SimpleOpEval,   nullptr, tflite::BuiltinOperator_CUSTOM,
      "SimpleOpEval", 1};
  return &registration;
}

TfLiteRegistration* RegisterSimpleOpWithProfilingDetails() {
  static TfLiteRegistration registration = {nullptr,
                                            nullptr,
                                            nullptr,
                                            SimpleOpEval,
                                            SimpleOpProfilingString,
                                            tflite::BuiltinOperator_CUSTOM,
                                            "SimpleOpEval",
                                            1};
  return &registration;
}
#endif

class SimpleOpModel : public SingleOpModel {
 public:
  void Init(const std::function<TfLiteRegistration*()>& registration);
  tflite::Interpreter* GetInterpreter() { return interpreter_.get(); }
  void SetInputs(int32_t x, int32_t y) {
    PopulateTensor(inputs_[0], {x});
    PopulateTensor(inputs_[1], {y});
  }
  int32_t GetOutput() { return ExtractVector<int32_t>(output_)[0]; }

 private:
  int inputs_[2];
  int output_;
};

void SimpleOpModel::Init(
    const std::function<TfLiteRegistration*()>& registration) {
  inputs_[0] = AddInput({TensorType_INT32, {1}});
  inputs_[1] = AddInput({TensorType_INT32, {1}});
  output_ = AddOutput({TensorType_INT32, {}});
  SetCustomOp("SimpleAdd", {}, registration);
  BuildInterpreter({GetShape(inputs_[0]), GetShape(inputs_[1])});
}

TEST(ProfileSummarizerTest, Empty) {
  ProfileSummarizer summarizer;
  std::string output = summarizer.GetOutputString();
  EXPECT_GT(output.size(), 0);
}

#ifdef TFLITE_PROFILING_ENABLED
TEST(ProfileSummarizerTest, Interpreter) {
  Profiler profiler;
  SimpleOpModel m;
  m.Init(RegisterSimpleOp);
  auto interpreter = m.GetInterpreter();
  interpreter->SetProfiler(&profiler);
  profiler.StartProfiling();
  m.SetInputs(1, 2);
  m.Invoke();
  // 3 = 1 + 2
  EXPECT_EQ(m.GetOutput(), 3);
  profiler.StopProfiling();
  ProfileSummarizer summarizer;
  auto events = profiler.GetProfileEvents();
  EXPECT_EQ(1, events.size());
  summarizer.ProcessProfiles(profiler.GetProfileEvents(), *interpreter);
  auto output = summarizer.GetOutputString();
  // TODO(shashishekhar): Add a better test here.
  ASSERT_TRUE(output.find("SimpleOpEval") != std::string::npos) << output;
}

TEST(ProfileSummarizerTest, InterpreterPlusProfilingDetails) {
  Profiler profiler;
  SimpleOpModel m;
  m.Init(RegisterSimpleOpWithProfilingDetails);
  auto interpreter = m.GetInterpreter();
  interpreter->SetProfiler(&profiler);
  profiler.StartProfiling();
  m.SetInputs(1, 2);
  m.Invoke();
  // 3 = 1 + 2
  EXPECT_EQ(m.GetOutput(), 3);
  profiler.StopProfiling();
  ProfileSummarizer summarizer;
  auto events = profiler.GetProfileEvents();
  EXPECT_EQ(1, events.size());
  summarizer.ProcessProfiles(profiler.GetProfileEvents(), *interpreter);
  auto output = summarizer.GetOutputString();
  // TODO(shashishekhar): Add a better test here.
  ASSERT_TRUE(output.find("SimpleOpEval:Profile") != std::string::npos)
      << output;
}

#endif

}  // namespace
}  // namespace profiling
}  // namespace tflite

int main(int argc, char** argv) {
  ::tflite::LogToStderr();
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Fix a test. - SetCustomOp also sets the name of the custom op. Test was checking against the wrong name in the profile.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <string>
#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/contrib/lite/context.h"
#include "tensorflow/contrib/lite/kernels/kernel_util.h"
#include "tensorflow/contrib/lite/kernels/test_util.h"
#include "tensorflow/contrib/lite/model.h"
#include "tensorflow/contrib/lite/profiling/profile_summarizer.h"
#include "tensorflow/contrib/lite/testing/util.h"
#include "tensorflow/contrib/lite/version.h"

namespace tflite {
namespace profiling {

namespace {

const char* kOpName = "SimpleOpEval";

#ifdef TFLITE_PROFILING_ENABLED
TfLiteStatus SimpleOpEval(TfLiteContext* context, TfLiteNode* node) {
  const TfLiteTensor* input1 = tflite::GetInput(context, node, /*index=*/0);
  const TfLiteTensor* input2 = tflite::GetInput(context, node, /*index=*/1);

  TfLiteTensor* output = GetOutput(context, node, /*index=*/0);

  int32_t* output_data = output->data.i32;
  *output_data = *(input1->data.i32) + *(input2->data.i32);
  return kTfLiteOk;
}

const char* SimpleOpProfilingString(const TfLiteContext* context,
                                    const TfLiteNode* node) {
  return "Profile";
}

TfLiteRegistration* RegisterSimpleOp() {
  static TfLiteRegistration registration = {
      nullptr,        nullptr, nullptr,
      SimpleOpEval,   nullptr, tflite::BuiltinOperator_CUSTOM,
      "SimpleOpEval", 1};
  return &registration;
}

TfLiteRegistration* RegisterSimpleOpWithProfilingDetails() {
  static TfLiteRegistration registration = {nullptr,
                                            nullptr,
                                            nullptr,
                                            SimpleOpEval,
                                            SimpleOpProfilingString,
                                            tflite::BuiltinOperator_CUSTOM,
                                            kOpName,
                                            1};
  return &registration;
}
#endif

class SimpleOpModel : public SingleOpModel {
 public:
  void Init(const std::function<TfLiteRegistration*()>& registration);
  tflite::Interpreter* GetInterpreter() { return interpreter_.get(); }
  void SetInputs(int32_t x, int32_t y) {
    PopulateTensor(inputs_[0], {x});
    PopulateTensor(inputs_[1], {y});
  }
  int32_t GetOutput() { return ExtractVector<int32_t>(output_)[0]; }

 private:
  int inputs_[2];
  int output_;
};

void SimpleOpModel::Init(
    const std::function<TfLiteRegistration*()>& registration) {
  inputs_[0] = AddInput({TensorType_INT32, {1}});
  inputs_[1] = AddInput({TensorType_INT32, {1}});
  output_ = AddOutput({TensorType_INT32, {}});
  SetCustomOp(kOpName, {}, registration);
  BuildInterpreter({GetShape(inputs_[0]), GetShape(inputs_[1])});
}

TEST(ProfileSummarizerTest, Empty) {
  ProfileSummarizer summarizer;
  std::string output = summarizer.GetOutputString();
  EXPECT_GT(output.size(), 0);
}

#ifdef TFLITE_PROFILING_ENABLED
TEST(ProfileSummarizerTest, Interpreter) {
  Profiler profiler;
  SimpleOpModel m;
  m.Init(RegisterSimpleOp);
  auto interpreter = m.GetInterpreter();
  interpreter->SetProfiler(&profiler);
  profiler.StartProfiling();
  m.SetInputs(1, 2);
  m.Invoke();
  // 3 = 1 + 2
  EXPECT_EQ(m.GetOutput(), 3);
  profiler.StopProfiling();
  ProfileSummarizer summarizer;
  auto events = profiler.GetProfileEvents();
  EXPECT_EQ(1, events.size());
  summarizer.ProcessProfiles(profiler.GetProfileEvents(), *interpreter);
  auto output = summarizer.GetOutputString();
  // TODO(shashishekhar): Add a better test here.
  ASSERT_TRUE(output.find("SimpleOpEval") != std::string::npos) << output;
}

TEST(ProfileSummarizerTest, InterpreterPlusProfilingDetails) {
  Profiler profiler;
  SimpleOpModel m;
  m.Init(RegisterSimpleOpWithProfilingDetails);
  auto interpreter = m.GetInterpreter();
  interpreter->SetProfiler(&profiler);
  profiler.StartProfiling();
  m.SetInputs(1, 2);
  m.Invoke();
  // 3 = 1 + 2
  EXPECT_EQ(m.GetOutput(), 3);
  profiler.StopProfiling();
  ProfileSummarizer summarizer;
  auto events = profiler.GetProfileEvents();
  EXPECT_EQ(1, events.size());
  summarizer.ProcessProfiles(profiler.GetProfileEvents(), *interpreter);
  auto output = summarizer.GetOutputString();
  // TODO(shashishekhar): Add a better test here.
  ASSERT_TRUE(output.find("SimpleOpEval:Profile") != std::string::npos)
      << output;
}

#endif

}  // namespace
}  // namespace profiling
}  // namespace tflite

int main(int argc, char** argv) {
  ::tflite::LogToStderr();
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (C) 2015 Mark Charlebois. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/
/**
 * @file main.cpp
 * Basic shell to execute builtin "apps"
 *
 * @author Mark Charlebois <charlebm@gmail.com>
 * @author Roman Bapst <bapstroman@gmail.com>
 */

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include "apps.h"
#include "px4_middleware.h"
#include "DriverFramework.hpp"
#include <termios.h>

namespace px4
{
void init_once(void);
}

using namespace std;

typedef int (*px4_main_t)(int argc, char *argv[]);

#define CMD_BUFF_SIZE	100

static bool _ExitFlag = false;

extern "C" {
	void _SigIntHandler(int sig_num);
	void _SigIntHandler(int sig_num)
	{
		cout.flush();
		cout << endl << "Exiting..." << endl;
		cout.flush();
		_ExitFlag = true;
	}
	void _SigFpeHandler(int sig_num);
	void _SigFpeHandler(int sig_num)
	{
		cout.flush();
		cout << endl << "floating point exception" << endl;
		PX4_BACKTRACE();
		cout.flush();
	}
}

static void print_prompt()
{
	cout.flush();
	cout << "pxh> ";
	cout.flush();
}

static void run_cmd(const vector<string> &appargs, bool exit_on_fail)
{
	// command is appargs[0]
	string command = appargs[0];

	if (apps.find(command) != apps.end()) {
		const char *arg[appargs.size() + 2];

		unsigned int i = 0;

		while (i < appargs.size() && appargs[i] != "") {
			arg[i] = (char *)appargs[i].c_str();
			++i;
		}

		arg[i] = (char *)0;

		cout << endl;

		int retval = apps[command](i, (char **)arg);

		if (retval) {
			cout << "Command failed, returned " << retval << endl;

			if (exit_on_fail && retval) {
				exit(retval);
			}
		}

	} else if (command.compare("help") == 0) {
		list_builtins();

	} else if (command.length() == 0) {
		// Do nothing

	} else {
		cout << endl << "Invalid command: " << command << "\ntype 'help' for a list of commands" << endl;

	}
}

static void usage()
{

	cout << "./mainapp [-d] [startup_config] -h" << std::endl;
	cout << "   -d            - Optional flag to run the app in daemon mode and does not listen for user input." <<
	     std::endl;
	cout << "                   This is needed if mainapp is intended to be run as a upstart job on linux" << std::endl;
	cout << "<startup_config> - config file for starting/stopping px4 modules" << std::endl;
	cout << "   -h            - help/usage information" << std::endl;
}

static void process_line(string &line, bool exit_on_fail)
{
	if (line.length() == 0) {
		printf("\n");
	}

	vector<string> appargs(10);

	stringstream(line) >> appargs[0] >> appargs[1] >> appargs[2] >> appargs[3] >> appargs[4] >> appargs[5] >> appargs[6] >>
			   appargs[7] >> appargs[8] >> appargs[9];
	run_cmd(appargs, exit_on_fail);
}

int main(int argc, char **argv)
{
	bool daemon_mode = false;
	bool chroot_on = false;

	struct sigaction sig_int;
	memset(&sig_int, 0, sizeof(struct sigaction));
	sig_int.sa_handler = _SigIntHandler;
	sig_int.sa_flags = 0;// not SA_RESTART!;

	struct sigaction sig_fpe;
	memset(&sig_fpe, 0, sizeof(struct sigaction));
	sig_fpe.sa_handler = _SigFpeHandler;
	sig_fpe.sa_flags = 0;// not SA_RESTART!;

	sigaction(SIGINT, &sig_int, NULL);
	//sigaction(SIGTERM, &sig_int, NULL);
	sigaction(SIGFPE, &sig_fpe, NULL);

	int index = 1;
	char *commands_file = nullptr;

	while (index < argc) {
		if (argv[index][0] == '-') {
			// the arg starts with -
			if (strcmp(argv[index], "-d") == 0) {
				daemon_mode = true;

			} else if (strcmp(argv[index], "-h") == 0) {
				usage();
				return 0;

			} else if (strcmp(argv[index], "-c") == 0) {
				chroot_on = true;

			} else {
				PX4_WARN("Unknown/unhandled parameter: %s", argv[index]);
				return 1;
			}

		} else {
			// this is an argument that does not have '-' prefix; treat it like a file name
			ifstream infile(argv[index]);

			if (infile.good()) {
				infile.close();
				commands_file = argv[index];

			} else {
				PX4_WARN("Error opening file: %s", argv[index]);
				return -1;
			}
		}

		++index;
	}

	DriverFramework::Framework::initialize();
	px4::init_once();

	px4::init(argc, argv, "mainapp");

	// if commandfile is present, process the commands from the file
	if (commands_file != nullptr) {
		ifstream infile(commands_file);

		if (infile.is_open()) {
			for (string line; getline(infile, line, '\n');) {
				// TODO: this should be true but for that we have to check all startup files
				process_line(line, false);
			}

		} else {
			PX4_WARN("Error opening file: %s", commands_file);
		}
	}

	if (chroot_on) {
		// Lock this application in the current working dir
		// this is not an attempt to secure the environment,
		// rather, to replicate a deployed file system.

#ifdef PATH_MAX
		const unsigned path_max_len = PATH_MAX;
#else
		const unsigned path_max_len = 1024;
#endif

		char pwd_path[path_max_len];
		const char *folderpath = "/rootfs/";

		if (nullptr == getcwd(pwd_path, sizeof(pwd_path))) {
			PX4_ERR("Failed acquiring working dir, abort.");
			exit(1);
		}

		if (nullptr == strcat(pwd_path, folderpath)) {
			PX4_ERR("Failed completing path, abort.");
			exit(1);
		}

		if (chroot(pwd_path)) {
			PX4_ERR("Failed chrooting application, path: %s, error: %s.", pwd_path, strerror(errno));
			exit(1);
		}

		if (chdir("/")) {
			PX4_ERR("Failed changing to root dir, path: %s, error: %s.", pwd_path, strerror(errno));
			exit(1);
		}
	}

	if (!daemon_mode) {
		string mystr = "";
		string string_buffer[CMD_BUFF_SIZE];
		int buf_ptr_write = 0;
		int buf_ptr_read = 0;

		print_prompt();

		// change input mode so that we can manage shell
		struct termios term;
		tcgetattr(0, &term);
		term.c_lflag &= ~ICANON;
		term.c_lflag &= ~ECHO;
		tcsetattr(0, TCSANOW, &term);
		setbuf(stdin, NULL);

		while (!_ExitFlag) {

			char c = getchar();

			switch (c) {
			case 127:	// backslash
				if (mystr.length() > 0) {
					mystr.pop_back();
					printf("%c[2K", 27);	// clear line
					cout << (char)13;
					print_prompt();
					cout << mystr;
				}

				break;

			case'\n':	// user hit enter
				if (buf_ptr_write == CMD_BUFF_SIZE) {
					buf_ptr_write = 0;
				}

				if (buf_ptr_write > 0) {
					if (mystr != string_buffer[buf_ptr_write - 1]) {
						string_buffer[buf_ptr_write] = mystr;
						buf_ptr_write++;
					}

				} else {
					if (mystr != string_buffer[CMD_BUFF_SIZE - 1]) {
						string_buffer[buf_ptr_write] = mystr;
						buf_ptr_write++;
					}
				}

				process_line(mystr, false);
				mystr = "";
				buf_ptr_read = buf_ptr_write;

				print_prompt();
				break;

			case '\033': {	// arrow keys
					c = getchar();	// skip first one, does not have the info
					c = getchar();

					// arrow up
					if (c == 'A') {
						buf_ptr_read--;
						// arrow down

					} else if (c == 'B') {
						if (buf_ptr_read < buf_ptr_write) {
							buf_ptr_read++;
						}

					} else {
						// TODO: Support editing current line
					}

					if (buf_ptr_read < 0) {
						buf_ptr_read = 0;
					}

					string saved_cmd = string_buffer[buf_ptr_read];
					printf("%c[2K", 27);
					cout << (char)13;
					mystr = saved_cmd;
					print_prompt();
					cout << mystr;
					break;
				}

			default:	// any other input
				cout << c;
				mystr += c;
				break;
			}
		}

	} else {
		while (!_ExitFlag) {
			usleep(100000);
		}
	}

	// TODO: Always try to stop muorb for QURT because px4_task_is_running doesn't seem to work.
	if (true) {
	//if (px4_task_is_running("muorb")) {
		// sending muorb stop is needed if it is running to exit cleanly
		vector<string> muorb_stop_cmd = { "muorb", "stop" };
		run_cmd(muorb_stop_cmd, !daemon_mode);
	}

	vector<string> shutdown_cmd = { "shutdown" };
	run_cmd(shutdown_cmd, true);
	DriverFramework::Framework::shutdown();

	return OK;
}
<commit_msg>Fixed terminal when exiting mainapp<commit_after>/****************************************************************************
 *
 *   Copyright (C) 2015 Mark Charlebois. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/
/**
 * @file main.cpp
 * Basic shell to execute builtin "apps"
 *
 * @author Mark Charlebois <charlebm@gmail.com>
 * @author Roman Bapst <bapstroman@gmail.com>
 */

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include "apps.h"
#include "px4_middleware.h"
#include "DriverFramework.hpp"
#include <termios.h>

namespace px4
{
void init_once(void);
}

using namespace std;

typedef int (*px4_main_t)(int argc, char *argv[]);

#define CMD_BUFF_SIZE	100

static bool _ExitFlag = false;

static struct termios orig_term;

extern "C" {
	void _SigIntHandler(int sig_num);
	void _SigIntHandler(int sig_num)
	{
		cout.flush();
		cout << endl << "Exiting..." << endl;
		cout.flush();
		_ExitFlag = true;
	}
	void _SigFpeHandler(int sig_num);
	void _SigFpeHandler(int sig_num)
	{
		cout.flush();
		cout << endl << "floating point exception" << endl;
		PX4_BACKTRACE();
		cout.flush();
	}
}

static void print_prompt()
{
	cout.flush();
	cout << "pxh> ";
	cout.flush();
}

static void run_cmd(const vector<string> &appargs, bool exit_on_fail)
{
	// command is appargs[0]
	string command = appargs[0];

	if (apps.find(command) != apps.end()) {
		const char *arg[appargs.size() + 2];

		unsigned int i = 0;

		while (i < appargs.size() && appargs[i] != "") {
			arg[i] = (char *)appargs[i].c_str();
			++i;
		}

		arg[i] = (char *)0;

		cout << endl;

		int retval = apps[command](i, (char **)arg);

		if (retval) {
			cout << "Command failed, returned " << retval << endl;

			if (exit_on_fail && retval) {
				exit(retval);
			}
		}

	} else if (command.compare("help") == 0) {
		list_builtins();

	} else if (command.length() == 0) {
		// Do nothing

	} else {
		cout << endl << "Invalid command: " << command << "\ntype 'help' for a list of commands" << endl;

	}
}

static void usage()
{

	cout << "./mainapp [-d] [startup_config] -h" << std::endl;
	cout << "   -d            - Optional flag to run the app in daemon mode and does not listen for user input." <<
	     std::endl;
	cout << "                   This is needed if mainapp is intended to be run as a upstart job on linux" << std::endl;
	cout << "<startup_config> - config file for starting/stopping px4 modules" << std::endl;
	cout << "   -h            - help/usage information" << std::endl;
}

static void process_line(string &line, bool exit_on_fail)
{
	if (line.length() == 0) {
		printf("\n");
	}

	vector<string> appargs(10);

	stringstream(line) >> appargs[0] >> appargs[1] >> appargs[2] >> appargs[3] >> appargs[4] >> appargs[5] >> appargs[6] >>
			   appargs[7] >> appargs[8] >> appargs[9];
	run_cmd(appargs, exit_on_fail);
}

static void restore_term(void)
{
	cout << "Restoring terminal\n";
	tcsetattr (0, TCSANOW, &orig_term);
}

int main(int argc, char **argv)
{
	bool daemon_mode = false;
	bool chroot_on = false;

	tcgetattr(0, &orig_term);
	atexit(restore_term);

	struct sigaction sig_int;
	memset(&sig_int, 0, sizeof(struct sigaction));
	sig_int.sa_handler = _SigIntHandler;
	sig_int.sa_flags = 0;// not SA_RESTART!;

	struct sigaction sig_fpe;
	memset(&sig_fpe, 0, sizeof(struct sigaction));
	sig_fpe.sa_handler = _SigFpeHandler;
	sig_fpe.sa_flags = 0;// not SA_RESTART!;

	sigaction(SIGINT, &sig_int, NULL);
	//sigaction(SIGTERM, &sig_int, NULL);
	sigaction(SIGFPE, &sig_fpe, NULL);

	int index = 1;
	char *commands_file = nullptr;

	while (index < argc) {
		if (argv[index][0] == '-') {
			// the arg starts with -
			if (strcmp(argv[index], "-d") == 0) {
				daemon_mode = true;

			} else if (strcmp(argv[index], "-h") == 0) {
				usage();
				return 0;

			} else if (strcmp(argv[index], "-c") == 0) {
				chroot_on = true;

			} else {
				PX4_WARN("Unknown/unhandled parameter: %s", argv[index]);
				return 1;
			}

		} else {
			// this is an argument that does not have '-' prefix; treat it like a file name
			ifstream infile(argv[index]);

			if (infile.good()) {
				infile.close();
				commands_file = argv[index];

			} else {
				PX4_WARN("Error opening file: %s", argv[index]);
				return -1;
			}
		}

		++index;
	}

	DriverFramework::Framework::initialize();
	px4::init_once();

	px4::init(argc, argv, "mainapp");

	// if commandfile is present, process the commands from the file
	if (commands_file != nullptr) {
		ifstream infile(commands_file);

		if (infile.is_open()) {
			for (string line; getline(infile, line, '\n');) {
				// TODO: this should be true but for that we have to check all startup files
				process_line(line, false);
			}

		} else {
			PX4_WARN("Error opening file: %s", commands_file);
		}
	}

	if (chroot_on) {
		// Lock this application in the current working dir
		// this is not an attempt to secure the environment,
		// rather, to replicate a deployed file system.

#ifdef PATH_MAX
		const unsigned path_max_len = PATH_MAX;
#else
		const unsigned path_max_len = 1024;
#endif

		char pwd_path[path_max_len];
		const char *folderpath = "/rootfs/";

		if (nullptr == getcwd(pwd_path, sizeof(pwd_path))) {
			PX4_ERR("Failed acquiring working dir, abort.");
			exit(1);
		}

		if (nullptr == strcat(pwd_path, folderpath)) {
			PX4_ERR("Failed completing path, abort.");
			exit(1);
		}

		if (chroot(pwd_path)) {
			PX4_ERR("Failed chrooting application, path: %s, error: %s.", pwd_path, strerror(errno));
			exit(1);
		}

		if (chdir("/")) {
			PX4_ERR("Failed changing to root dir, path: %s, error: %s.", pwd_path, strerror(errno));
			exit(1);
		}
	}

	if (!daemon_mode) {
		string mystr = "";
		string string_buffer[CMD_BUFF_SIZE];
		int buf_ptr_write = 0;
		int buf_ptr_read = 0;

		print_prompt();

		// change input mode so that we can manage shell
		struct termios term;
		tcgetattr(0, &term);
		term.c_lflag &= ~ICANON;
		term.c_lflag &= ~ECHO;
		tcsetattr(0, TCSANOW, &term);
		setbuf(stdin, NULL);

		while (!_ExitFlag) {

			char c = getchar();

			switch (c) {
			case 127:	// backslash
				if (mystr.length() > 0) {
					mystr.pop_back();
					printf("%c[2K", 27);	// clear line
					cout << (char)13;
					print_prompt();
					cout << mystr;
				}

				break;

			case'\n':	// user hit enter
				if (buf_ptr_write == CMD_BUFF_SIZE) {
					buf_ptr_write = 0;
				}

				if (buf_ptr_write > 0) {
					if (mystr != string_buffer[buf_ptr_write - 1]) {
						string_buffer[buf_ptr_write] = mystr;
						buf_ptr_write++;
					}

				} else {
					if (mystr != string_buffer[CMD_BUFF_SIZE - 1]) {
						string_buffer[buf_ptr_write] = mystr;
						buf_ptr_write++;
					}
				}

				process_line(mystr, false);
				mystr = "";
				buf_ptr_read = buf_ptr_write;

				print_prompt();
				break;

			case '\033': {	// arrow keys
					c = getchar();	// skip first one, does not have the info
					c = getchar();

					// arrow up
					if (c == 'A') {
						buf_ptr_read--;
						// arrow down

					} else if (c == 'B') {
						if (buf_ptr_read < buf_ptr_write) {
							buf_ptr_read++;
						}

					} else {
						// TODO: Support editing current line
					}

					if (buf_ptr_read < 0) {
						buf_ptr_read = 0;
					}

					string saved_cmd = string_buffer[buf_ptr_read];
					printf("%c[2K", 27);
					cout << (char)13;
					mystr = saved_cmd;
					print_prompt();
					cout << mystr;
					break;
				}

			default:	// any other input
				cout << c;
				mystr += c;
				break;
			}
		}

	} else {
		while (!_ExitFlag) {
			usleep(100000);
		}
	}

	// TODO: Always try to stop muorb for QURT because px4_task_is_running doesn't seem to work.
	if (true) {
	//if (px4_task_is_running("muorb")) {
		// sending muorb stop is needed if it is running to exit cleanly
		vector<string> muorb_stop_cmd = { "muorb", "stop" };
		run_cmd(muorb_stop_cmd, !daemon_mode);
	}

	vector<string> shutdown_cmd = { "shutdown" };
	run_cmd(shutdown_cmd, true);
	DriverFramework::Framework::shutdown();

	return OK;
}
<|endoftext|>


<commit_before>/*************************************************************************************
    garlic-player: SMIL Player for Digital Signage
    Copyright (C) 2016 Nikolaos Saghiadinos <ns@smil-control.com>
    This file is part of the garlic-player source code

    This program is free software: you can redistribute it and/or  modify
    it under the terms of the GNU Affero General Public License, version 3,
    as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*************************************************************************************/

#include "region.h"
#include <QLayout>

TRegion::TRegion(QWidget *parent) : QWidget(parent)
{
    setParent(parent);
    layout.reset(new QStackedLayout(this));
    layout.data()->setMargin(0);
    setLayout(layout.data());
 }

TRegion::~TRegion()
{
}

/**
 * @brief TRegion::paintEvent needed to draw a background color setted in smil layout header
 * @param event
 */
void TRegion::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
    QStyleOption o;
    o.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this);
}

void TRegion::startShowMedia(BaseMedia *media)
{
    qDebug(Develop) << "begin" << Q_FUNC_INFO;
    MyMedia = MyMediaFactory.initMedia(media);
    layout.data()->addWidget(MyMedia->getView());
    qDebug(Develop) << "end" << Q_FUNC_INFO;
}

void TRegion::stopShowMedia()
{
    qDebug(Develop) << "begin" << Q_FUNC_INFO;
    layout.data()->removeWidget(MyMedia->getView());
    MyMedia->deinit();
    qDebug(Develop) << "end" << Q_FUNC_INFO;
}

/**
 * Needs the real pixel of the actual root size regardless
 * if fullscreen or in window
 *
 * @brief TRegion::setRootSize
 * @param w
 * @param h
 */
void TRegion::setRootSize(int w, int h)
{
    root_width_px  = w;
    root_height_px = h;
    resizeGeometry();
}

void TRegion::setRegion(Region r)
{
    region = r;
    setStyleSheet("background-color:"+region.backgroundColor+";");
}

void TRegion::resizeGeometry()
{
    qreal  xr, yr, wr, hr = 0.0;
    xr = (root_width_px*region.left);
    yr = (root_height_px*region.top);
    wr = (root_width_px*region.width*1);
    hr = (root_height_px*region.height*1);
    setGeometry(qRound(xr), qRound(yr), qRound(wr), qRound(hr));
    if (MyMedia != Q_NULLPTR)
        MyMedia->changeSize(qRound(wr), qRound(hr));
}

<commit_msg>Fixed issue #6 Segmentation fault when media not found in player-widget<commit_after>/*************************************************************************************
    garlic-player: SMIL Player for Digital Signage
    Copyright (C) 2016 Nikolaos Saghiadinos <ns@smil-control.com>
    This file is part of the garlic-player source code

    This program is free software: you can redistribute it and/or  modify
    it under the terms of the GNU Affero General Public License, version 3,
    as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*************************************************************************************/

#include "region.h"
#include <QLayout>

TRegion::TRegion(QWidget *parent) : QWidget(parent)
{
    setParent(parent);
    layout.reset(new QStackedLayout(this));
    layout.data()->setMargin(0);
    setLayout(layout.data());
 }

TRegion::~TRegion()
{
}

/**
 * @brief TRegion::paintEvent needed to draw a background color setted in smil layout header
 * @param event
 */
void TRegion::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
    QStyleOption o;
    o.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &o, &p, this);
}

void TRegion::startShowMedia(BaseMedia *media)
{
    qDebug(Develop) << "begin" << Q_FUNC_INFO;
    MyMedia = MyMediaFactory.initMedia(media);

    QWidget *widget = MyMedia->getView();
    if (widget != Q_NULLPTR)
    {
        layout.data()->addWidget(widget);
    }
    qDebug(Develop) << "end" << Q_FUNC_INFO;
}

void TRegion::stopShowMedia()
{
    qDebug(Develop) << "begin" << Q_FUNC_INFO;
    QWidget *widget = MyMedia->getView();
    if (widget != Q_NULLPTR)
    {
        layout.data()->removeWidget(widget);
    }
    MyMedia->deinit();
    qDebug(Develop) << "end" << Q_FUNC_INFO;
}

/**
 * Needs the real pixel of the actual root size regardless
 * if fullscreen or in window
 *
 * @brief TRegion::setRootSize
 * @param w
 * @param h
 */
void TRegion::setRootSize(int w, int h)
{
    root_width_px  = w;
    root_height_px = h;
    resizeGeometry();
}

void TRegion::setRegion(Region r)
{
    region = r;
    setStyleSheet("background-color:"+region.backgroundColor+";");
}

void TRegion::resizeGeometry()
{
    qreal  xr, yr, wr, hr = 0.0;
    xr = (root_width_px*region.left);
    yr = (root_height_px*region.top);
    wr = (root_width_px*region.width*1);
    hr = (root_height_px*region.height*1);
    setGeometry(qRound(xr), qRound(yr), qRound(wr), qRound(hr));
    if (MyMedia != Q_NULLPTR)
        MyMedia->changeSize(qRound(wr), qRound(hr));
}

<|endoftext|>


<commit_before>/*
 * datasetfmri.cpp
 *
 *  Created on: Aug 9, 2013
 *      Author: schurade
 */

#include "datasetfmri.h"
#include "../models.h"

#include <QTimer>

DatasetFMRI::DatasetFMRI( QDir filename, QVector<float> data, nifti_image* header ) :
    DatasetNifti( filename, Fn::DatasetType::NIFTI_FMRI, header ),
    m_data( data )
{
    m_properties["maingl"]->create( Fn::Property::D_COLORMAP, 0, 0, (int)Fn::ColormapEnum::NONE - 1, "color" );
    m_properties["maingl"]->create( Fn::Property::D_INTERPOLATION, false, "general" );
    m_properties["maingl"]->create( Fn::Property::D_ALPHA, 1.0f, 0.0, 1.0, "general" );

    examineDataset();

    m_properties["maingl"]->create( Fn::Property::D_HAS_TEXTURE, true );

    PropertyGroup* props2 = new PropertyGroup( *( m_properties["maingl"] ) );
    m_properties.insert( "maingl2", props2 );
    m_properties["maingl2"]->getProperty( Fn::Property::D_ACTIVE )->setPropertyTab( "general" );

    m_properties["maingl"]->create( Fn::Property::D_AUTOPLAY, false, "autoplay" );
    m_properties["maingl"]->create( Fn::Property::D_AUTOPLAY_INTERVAL, 25, 10, 1000, "autoplay" );
    connect( m_properties["maingl"]->getProperty( Fn::Property::D_AUTOPLAY ), SIGNAL( valueChanged( QVariant ) ), this, SLOT( autoplay() ) );
}

DatasetFMRI::~DatasetFMRI()
{
    // TODO Auto-generated destructor stub
}

QVector<float>* DatasetFMRI::getData()
{
    return &m_data;
}

void DatasetFMRI::examineDataset()
{
    int nx = m_properties["maingl"]->get( Fn::Property::D_NX ).toInt();
    int ny = m_properties["maingl"]->get( Fn::Property::D_NY ).toInt();
    int nz = m_properties["maingl"]->get( Fn::Property::D_NZ ).toInt();
    int dim = m_properties["maingl"]->get( Fn::Property::D_DIM ).toInt();

    float min = std::numeric_limits<float>::max();
    float max = 0;

    int size = nx * ny * nz * dim;
    for ( int i = 0; i < size; ++i )
    {
        min = qMin( min, m_data[i] );
        max = qMax( max, m_data[i] );
    }

    m_properties["maingl"]->create( Fn::Property::D_SIZE, static_cast<int>( size * sizeof(float) ) );
    m_properties["maingl"]->create( Fn::Property::D_MIN, min );
    m_properties["maingl"]->create( Fn::Property::D_MAX, max );
    m_properties["maingl"]->create( Fn::Property::D_SELECTED_MIN, min, min, max, "general" );
    m_properties["maingl"]->create( Fn::Property::D_SELECTED_MAX, max, min, max, "general" );
    m_properties["maingl"]->create( Fn::Property::D_LOWER_THRESHOLD, min + (max-min)/100., min, max, "general" );
    m_properties["maingl"]->create( Fn::Property::D_UPPER_THRESHOLD, max, min, max, "general" );

    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MIN ), SIGNAL( valueChanged( QVariant ) ),
              m_properties["maingl"]->getProperty( Fn::Property::D_LOWER_THRESHOLD ), SLOT( setMax( QVariant ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MAX ), SIGNAL( valueChanged( QVariant ) ),
              m_properties["maingl"]->getProperty( Fn::Property::D_UPPER_THRESHOLD ), SLOT( setMin( QVariant ) ) );

    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MIN ), SIGNAL( valueChanged( QVariant ) ),
              m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MAX ), SLOT( setMin( QVariant ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MAX ), SIGNAL( valueChanged( QVariant ) ),
              m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MIN ), SLOT( setMax( QVariant ) ) );

    if ( m_qform.Determinant() < 0.0 && m_qform( 1, 1 ) < 0 )
    {
        qDebug() << m_properties["maingl"]->get( Fn::Property::D_NAME ).toString() << ": RADIOLOGICAL orientation in q-form detected. Flipping voxels on X-Axis";
        flipX();
    }
    else
    {
        if ( m_sform.Determinant() < 0.0 && m_sform( 1, 1 ) < 0 )
        {
            qDebug() << m_properties["maingl"]->get( Fn::Property::D_NAME ).toString() << ": RADIOLOGICAL orientation in s-form detected. Flipping voxels on X-Axis";
            flipX();
        }
    }

    m_properties["maingl"]->create( Fn::Property::D_PAINTMODE, { "off", "paint" }, 0, "paint" );
    m_properties["maingl"]->create( Fn::Property::D_PAINTSIZE, 1, 1, 10, "paint" );
    m_properties["maingl"]->create( Fn::Property::D_PAINTVALUE, max - 1.0, min, max - 1.0, "paint" );
    m_properties["maingl"]->create( Fn::Property::D_PAINT_LINK_CURSOR, false, "paint" );

    m_properties["maingl"]->create( Fn::Property::D_SELECTED_TEXTURE, 0, 0, dim - 1, "general" );
    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_TEXTURE ), SIGNAL( valueChanged( QVariant ) ), this, SLOT( selectTexture() ) );
    connect ( m_properties["maingl"], SIGNAL( signalSetProp( int ) ), this, SLOT( slotPropSet( int ) ) );
}

void DatasetFMRI::createTexture()
{
    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

    glGenTextures( 1, &m_textureGLuint );

    glBindTexture( GL_TEXTURE_3D, m_textureGLuint );

    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP );

    int nx = m_properties["maingl"]->get( Fn::Property::D_NX ).toInt();
    int ny = m_properties["maingl"]->get( Fn::Property::D_NY ).toInt();
    int nz = m_properties["maingl"]->get( Fn::Property::D_NZ ).toInt();

    float min = m_properties["maingl"]->get( Fn::Property::D_MIN ).toFloat();
    float max = m_properties["maingl"]->get( Fn::Property::D_MAX ).toFloat();
    max = max + ( (max-min)/100. );

    int frame = m_properties["maingl"]->get( Fn::Property::D_SELECTED_TEXTURE ).toInt();
    int offset = nx * ny * nz * frame;

    unsigned char* tmpData = new unsigned char[nx * ny * nz * 4];
    for ( int i = 0; i < nx * ny * nz; ++i )
    {
        unsigned int tmp = ( ( m_data[i + offset] - min ) / ( max - min ) ) * 256 * 256 * 256 * 256;
        tmpData[4 * i + 3 ] = (tmp / (256 * 256 * 256)) % 256;
        tmpData[4 * i + 2 ] = (tmp / (256 * 256)) % 256;
        tmpData[4 * i + 1 ] = (tmp / (256)) % 256;
        tmpData[4 * i + 0 ] = tmp % 256 ;
    }

    glTexImage3D( GL_TEXTURE_3D, 0, GL_RGBA, nx, ny, nz, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpData );
    delete[] tmpData;
}

void DatasetFMRI::flipX()
{
//    int nx = m_properties["maingl"]->get( Fn::Property::D_NX ).toInt();
//    int ny = m_properties["maingl"]->get( Fn::Property::D_NY ).toInt();
//    int nz = m_properties["maingl"]->get( Fn::Property::D_NZ ).toInt();
//
//    QVector<float> newData;
//
//    for ( int z = 0; z < nz; ++z )
//    {
//        for ( int y = 0; y < ny; ++y )
//        {
//            for ( int x = nx - 1; x >= 0; --x )
//            {
//                newData.push_back( m_data[x + y * nx + z * nx * ny] );
//            }
//        }
//    }
//
//    m_header->qoffset_x = 0.0;
//
//    m_header->qto_xyz.m[0][0] = qMax( m_header->qto_xyz.m[0][0], m_header->qto_xyz.m[0][0] * -1.0f );
//    m_header->sto_xyz.m[0][0] = qMax( m_header->sto_xyz.m[0][0], m_header->sto_xyz.m[0][0] * -1.0f );
//    m_header->qto_xyz.m[0][3] = 0.0;
//    m_header->sto_xyz.m[0][3] = 0.0;
//
//    m_data.clear();
//    m_data = newData;
}

void DatasetFMRI::draw( QMatrix4x4 pMatrix, QMatrix4x4 mvMatrix, int width, int height, int renderMode, QString target )
{
}

QString DatasetFMRI::getValueAsString( int x, int y, int z )
{
    return QString( "" );
}

bool DatasetFMRI::mousePick( int pickId, QVector3D pos, Qt::KeyboardModifiers modifiers, QString target )
{
    return false;
}

void DatasetFMRI::selectTexture()
{
    glDeleteTextures( 1, &m_textureGLuint );
    m_textureGLuint = 0;
}

void DatasetFMRI::autoplay()
{
    if ( m_properties["maingl"]->get( Fn::Property::D_AUTOPLAY ).toBool() )
    {
        int dim = m_properties["maingl"]->get( Fn::Property::D_DIM ).toInt();
        int currentframe = m_properties["maingl"]->get( Fn::Property::D_SELECTED_TEXTURE ).toInt();
        ++currentframe;
        if ( currentframe >= dim )
        {
            currentframe = 0;
        }
        m_properties["maingl"]->set( Fn::Property::D_SELECTED_TEXTURE, currentframe );
        selectTexture();
        Models::d()->submit();

        int interval = m_properties["maingl"]->get( Fn::Property::D_AUTOPLAY_INTERVAL ).toInt();
        QTimer::singleShot( interval, this, SLOT( autoplay() ) );
    }
}

void DatasetFMRI::slotPropSet( int id )
{
    if ( id == (int)Fn::Property::D_SELECTED_TEXTURE )
    {
        selectTexture();
    }
}
<commit_msg>added range check for selected frame<commit_after>/*
 * datasetfmri.cpp
 *
 *  Created on: Aug 9, 2013
 *      Author: schurade
 */

#include "datasetfmri.h"
#include "../models.h"

#include <QTimer>

DatasetFMRI::DatasetFMRI( QDir filename, QVector<float> data, nifti_image* header ) :
    DatasetNifti( filename, Fn::DatasetType::NIFTI_FMRI, header ),
    m_data( data )
{
    m_properties["maingl"]->create( Fn::Property::D_COLORMAP, 0, 0, (int)Fn::ColormapEnum::NONE - 1, "color" );
    m_properties["maingl"]->create( Fn::Property::D_INTERPOLATION, false, "general" );
    m_properties["maingl"]->create( Fn::Property::D_ALPHA, 1.0f, 0.0, 1.0, "general" );

    examineDataset();

    m_properties["maingl"]->create( Fn::Property::D_HAS_TEXTURE, true );

    PropertyGroup* props2 = new PropertyGroup( *( m_properties["maingl"] ) );
    m_properties.insert( "maingl2", props2 );
    m_properties["maingl2"]->getProperty( Fn::Property::D_ACTIVE )->setPropertyTab( "general" );

    m_properties["maingl"]->create( Fn::Property::D_AUTOPLAY, false, "autoplay" );
    m_properties["maingl"]->create( Fn::Property::D_AUTOPLAY_INTERVAL, 25, 10, 1000, "autoplay" );
    connect( m_properties["maingl"]->getProperty( Fn::Property::D_AUTOPLAY ), SIGNAL( valueChanged( QVariant ) ), this, SLOT( autoplay() ) );
}

DatasetFMRI::~DatasetFMRI()
{
    // TODO Auto-generated destructor stub
}

QVector<float>* DatasetFMRI::getData()
{
    return &m_data;
}

void DatasetFMRI::examineDataset()
{
    int nx = m_properties["maingl"]->get( Fn::Property::D_NX ).toInt();
    int ny = m_properties["maingl"]->get( Fn::Property::D_NY ).toInt();
    int nz = m_properties["maingl"]->get( Fn::Property::D_NZ ).toInt();
    int dim = m_properties["maingl"]->get( Fn::Property::D_DIM ).toInt();

    float min = std::numeric_limits<float>::max();
    float max = 0;

    int size = nx * ny * nz * dim;
    for ( int i = 0; i < size; ++i )
    {
        min = qMin( min, m_data[i] );
        max = qMax( max, m_data[i] );
    }

    m_properties["maingl"]->create( Fn::Property::D_SIZE, static_cast<int>( size * sizeof(float) ) );
    m_properties["maingl"]->create( Fn::Property::D_MIN, min );
    m_properties["maingl"]->create( Fn::Property::D_MAX, max );
    m_properties["maingl"]->create( Fn::Property::D_SELECTED_MIN, min, min, max, "general" );
    m_properties["maingl"]->create( Fn::Property::D_SELECTED_MAX, max, min, max, "general" );
    m_properties["maingl"]->create( Fn::Property::D_LOWER_THRESHOLD, min + (max-min)/100., min, max, "general" );
    m_properties["maingl"]->create( Fn::Property::D_UPPER_THRESHOLD, max, min, max, "general" );

    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MIN ), SIGNAL( valueChanged( QVariant ) ),
              m_properties["maingl"]->getProperty( Fn::Property::D_LOWER_THRESHOLD ), SLOT( setMax( QVariant ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MAX ), SIGNAL( valueChanged( QVariant ) ),
              m_properties["maingl"]->getProperty( Fn::Property::D_UPPER_THRESHOLD ), SLOT( setMin( QVariant ) ) );

    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MIN ), SIGNAL( valueChanged( QVariant ) ),
              m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MAX ), SLOT( setMin( QVariant ) ) );
    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MAX ), SIGNAL( valueChanged( QVariant ) ),
              m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_MIN ), SLOT( setMax( QVariant ) ) );

    if ( m_qform.Determinant() < 0.0 && m_qform( 1, 1 ) < 0 )
    {
        qDebug() << m_properties["maingl"]->get( Fn::Property::D_NAME ).toString() << ": RADIOLOGICAL orientation in q-form detected. Flipping voxels on X-Axis";
        flipX();
    }
    else
    {
        if ( m_sform.Determinant() < 0.0 && m_sform( 1, 1 ) < 0 )
        {
            qDebug() << m_properties["maingl"]->get( Fn::Property::D_NAME ).toString() << ": RADIOLOGICAL orientation in s-form detected. Flipping voxels on X-Axis";
            flipX();
        }
    }

    m_properties["maingl"]->create( Fn::Property::D_PAINTMODE, { "off", "paint" }, 0, "paint" );
    m_properties["maingl"]->create( Fn::Property::D_PAINTSIZE, 1, 1, 10, "paint" );
    m_properties["maingl"]->create( Fn::Property::D_PAINTVALUE, max - 1.0, min, max - 1.0, "paint" );
    m_properties["maingl"]->create( Fn::Property::D_PAINT_LINK_CURSOR, false, "paint" );

    m_properties["maingl"]->create( Fn::Property::D_SELECTED_TEXTURE, 0, 0, dim - 1, "general" );
    connect( m_properties["maingl"]->getProperty( Fn::Property::D_SELECTED_TEXTURE ), SIGNAL( valueChanged( QVariant ) ), this, SLOT( selectTexture() ) );
    connect ( m_properties["maingl"], SIGNAL( signalSetProp( int ) ), this, SLOT( slotPropSet( int ) ) );
}

void DatasetFMRI::createTexture()
{
    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

    glGenTextures( 1, &m_textureGLuint );

    glBindTexture( GL_TEXTURE_3D, m_textureGLuint );

    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP );

    int nx = m_properties["maingl"]->get( Fn::Property::D_NX ).toInt();
    int ny = m_properties["maingl"]->get( Fn::Property::D_NY ).toInt();
    int nz = m_properties["maingl"]->get( Fn::Property::D_NZ ).toInt();

    float min = m_properties["maingl"]->get( Fn::Property::D_MIN ).toFloat();
    float max = m_properties["maingl"]->get( Fn::Property::D_MAX ).toFloat();
    max = max + ( (max-min)/100. );

    int dim = m_properties["maingl"]->get( Fn::Property::D_DIM ).toInt();
    int frame = m_properties["maingl"]->get( Fn::Property::D_SELECTED_TEXTURE ).toInt();
    if ( frame < 0 )
    {
        frame = 0;
    }

    if ( frame > dim - 1 )
    {
        frame = dim - 1;
    }
    int offset = nx * ny * nz * frame;

    unsigned char* tmpData = new unsigned char[nx * ny * nz * 4];
    for ( int i = 0; i < nx * ny * nz; ++i )
    {
        unsigned int tmp = ( ( m_data[i + offset] - min ) / ( max - min ) ) * 256 * 256 * 256 * 256;
        tmpData[4 * i + 3 ] = (tmp / (256 * 256 * 256)) % 256;
        tmpData[4 * i + 2 ] = (tmp / (256 * 256)) % 256;
        tmpData[4 * i + 1 ] = (tmp / (256)) % 256;
        tmpData[4 * i + 0 ] = tmp % 256 ;
    }

    glTexImage3D( GL_TEXTURE_3D, 0, GL_RGBA, nx, ny, nz, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpData );
    delete[] tmpData;
}

void DatasetFMRI::flipX()
{
//    int nx = m_properties["maingl"]->get( Fn::Property::D_NX ).toInt();
//    int ny = m_properties["maingl"]->get( Fn::Property::D_NY ).toInt();
//    int nz = m_properties["maingl"]->get( Fn::Property::D_NZ ).toInt();
//
//    QVector<float> newData;
//
//    for ( int z = 0; z < nz; ++z )
//    {
//        for ( int y = 0; y < ny; ++y )
//        {
//            for ( int x = nx - 1; x >= 0; --x )
//            {
//                newData.push_back( m_data[x + y * nx + z * nx * ny] );
//            }
//        }
//    }
//
//    m_header->qoffset_x = 0.0;
//
//    m_header->qto_xyz.m[0][0] = qMax( m_header->qto_xyz.m[0][0], m_header->qto_xyz.m[0][0] * -1.0f );
//    m_header->sto_xyz.m[0][0] = qMax( m_header->sto_xyz.m[0][0], m_header->sto_xyz.m[0][0] * -1.0f );
//    m_header->qto_xyz.m[0][3] = 0.0;
//    m_header->sto_xyz.m[0][3] = 0.0;
//
//    m_data.clear();
//    m_data = newData;
}

void DatasetFMRI::draw( QMatrix4x4 pMatrix, QMatrix4x4 mvMatrix, int width, int height, int renderMode, QString target )
{
}

QString DatasetFMRI::getValueAsString( int x, int y, int z )
{
    return QString( "" );
}

bool DatasetFMRI::mousePick( int pickId, QVector3D pos, Qt::KeyboardModifiers modifiers, QString target )
{
    return false;
}

void DatasetFMRI::selectTexture()
{
    glDeleteTextures( 1, &m_textureGLuint );
    m_textureGLuint = 0;
}

void DatasetFMRI::autoplay()
{
    if ( m_properties["maingl"]->get( Fn::Property::D_AUTOPLAY ).toBool() )
    {
        int dim = m_properties["maingl"]->get( Fn::Property::D_DIM ).toInt();
        int currentframe = m_properties["maingl"]->get( Fn::Property::D_SELECTED_TEXTURE ).toInt();
        ++currentframe;
        if ( currentframe >= dim )
        {
            currentframe = 0;
        }
        m_properties["maingl"]->set( Fn::Property::D_SELECTED_TEXTURE, currentframe );
        selectTexture();
        Models::d()->submit();

        int interval = m_properties["maingl"]->get( Fn::Property::D_AUTOPLAY_INTERVAL ).toInt();
        QTimer::singleShot( interval, this, SLOT( autoplay() ) );
    }
}

void DatasetFMRI::slotPropSet( int id )
{
    if ( id == (int)Fn::Property::D_SELECTED_TEXTURE )
    {
        selectTexture();
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "tests/Test.h"

#include "src/core/SkPaintParamsKey.h"
#include "src/core/SkShaderCodeDictionary.h"

#include "src/gpu/graphite/ContextPriv.h"

namespace {

SkPaintParamsKey create_key_with_data(SkPaintParamsKeyBuilder* builder,
                                      int snippetID,
                                      SkSpan<const uint8_t> span) {
    SkDEBUGCODE(builder->checkReset());

    builder->beginBlock(snippetID);

    builder->addBytes(span.size(), span.data());

    builder->endBlock();

    return builder->lockAsKey();
}

SkPaintParamsKey create_key(SkPaintParamsKeyBuilder* builder, int snippetID, int size) {
    SkASSERT(size <= 1024);
    static constexpr uint8_t kDummyData[1024] = {};
    return create_key_with_data(builder, snippetID, SkMakeSpan(kDummyData, size));
}

} // anonymous namespace

// These are intended to be unit tests of the SkPaintParamsKeyBuilder and SkPaintParamsKey.
DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyWithInvalidCodeSnippetIDTest, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite);

    // Invalid code snippet ID, key creation fails.
    SkPaintParamsKey key = create_key(&builder, kBuiltInCodeSnippetIDCount, /*size=*/32);
    REPORTER_ASSERT(reporter, key.isErrorKey());
}

DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyValidBlockSizeTest, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite);

    // _Just_ on the edge of being too big
    static const int kMaxBlockDataSize = SkPaintParamsKey::kMaxBlockSize -
                                         SkPaintParamsKey::kBlockHeaderSizeInBytes;
    static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = {
            {"data", SkPaintParamsKey::DataPayloadType::kByte, kMaxBlockDataSize},
    };

    int dummySnippetID = dict->addUserDefinedSnippet("keyAlmostTooBig", SkMakeSpan(kDataFields));
    SkPaintParamsKey key = create_key(&builder, dummySnippetID, kMaxBlockDataSize);

    // Key is created successfully.
    REPORTER_ASSERT(reporter, key.sizeInBytes() == SkPaintParamsKey::kMaxBlockSize);
}

DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyTooLargeBlockSizeTest, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite);

    // Too big by one byte
    static const int kBlockDataSize = SkPaintParamsKey::kMaxBlockSize -
                                      SkPaintParamsKey::kBlockHeaderSizeInBytes + 1;
    static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = {
            {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize},
    };

    int dummySnippetID = dict->addUserDefinedSnippet("keyTooBig", SkMakeSpan(kDataFields));
    SkPaintParamsKey key = create_key(&builder, dummySnippetID, kBlockDataSize);

    // Key creation fails.
    REPORTER_ASSERT(reporter, key.isErrorKey());
}

DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyEqualityChecksData, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    static const int kBlockDataSize = 4;
    static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = {
            {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize},
    };

    int dummySnippetID = dict->addUserDefinedSnippet("key", SkMakeSpan(kDataFields));

    static constexpr uint8_t kData [4] = {1, 2, 3, 4};
    static constexpr uint8_t kData2[4] = {1, 2, 3, 99};

    SkPaintParamsKeyBuilder builderA(dict, SkBackend::kGraphite);
    SkPaintParamsKeyBuilder builderB(dict, SkBackend::kGraphite);
    SkPaintParamsKeyBuilder builderC(dict, SkBackend::kGraphite);
    SkPaintParamsKey keyA = create_key_with_data(&builderA, dummySnippetID, SkMakeSpan(kData));
    SkPaintParamsKey keyB = create_key_with_data(&builderB, dummySnippetID, SkMakeSpan(kData));
    SkPaintParamsKey keyC = create_key_with_data(&builderC, dummySnippetID, SkMakeSpan(kData2));

    // Verify that keyA matches keyB, and that it does not match keyC.
    REPORTER_ASSERT(reporter, keyA == keyB);
    REPORTER_ASSERT(reporter, keyA != keyC);
    REPORTER_ASSERT(reporter, !(keyA == keyC));
    REPORTER_ASSERT(reporter, !(keyA != keyB));
}
<commit_msg>Add more equality/inequality tests to KeyTest.<commit_after>/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "tests/Test.h"

#include "src/core/SkPaintParamsKey.h"
#include "src/core/SkShaderCodeDictionary.h"

#include "src/gpu/graphite/ContextPriv.h"

namespace {

SkPaintParamsKey create_key_with_data(SkPaintParamsKeyBuilder* builder,
                                      int snippetID,
                                      SkSpan<const uint8_t> span) {
    SkDEBUGCODE(builder->checkReset());

    builder->beginBlock(snippetID);

    builder->addBytes(span.size(), span.data());

    builder->endBlock();

    return builder->lockAsKey();
}

SkPaintParamsKey create_key(SkPaintParamsKeyBuilder* builder, int snippetID, int size) {
    SkASSERT(size <= 1024);
    static constexpr uint8_t kDummyData[1024] = {};
    return create_key_with_data(builder, snippetID, SkMakeSpan(kDummyData, size));
}

} // anonymous namespace

// These are intended to be unit tests of the SkPaintParamsKeyBuilder and SkPaintParamsKey.
DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyWithInvalidCodeSnippetIDTest, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite);

    // Invalid code snippet ID, key creation fails.
    SkPaintParamsKey key = create_key(&builder, kBuiltInCodeSnippetIDCount, /*size=*/32);
    REPORTER_ASSERT(reporter, key.isErrorKey());
}

DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyValidBlockSizeTest, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite);

    // _Just_ on the edge of being too big
    static const int kMaxBlockDataSize = SkPaintParamsKey::kMaxBlockSize -
                                         SkPaintParamsKey::kBlockHeaderSizeInBytes;
    static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = {
            {"data", SkPaintParamsKey::DataPayloadType::kByte, kMaxBlockDataSize},
    };

    int dummySnippetID = dict->addUserDefinedSnippet("keyAlmostTooBig", SkMakeSpan(kDataFields));
    SkPaintParamsKey key = create_key(&builder, dummySnippetID, kMaxBlockDataSize);

    // Key is created successfully.
    REPORTER_ASSERT(reporter, key.sizeInBytes() == SkPaintParamsKey::kMaxBlockSize);
}

DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyTooLargeBlockSizeTest, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    SkPaintParamsKeyBuilder builder(dict, SkBackend::kGraphite);

    // Too big by one byte
    static const int kBlockDataSize = SkPaintParamsKey::kMaxBlockSize -
                                      SkPaintParamsKey::kBlockHeaderSizeInBytes + 1;
    static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = {
            {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize},
    };

    int dummySnippetID = dict->addUserDefinedSnippet("keyTooBig", SkMakeSpan(kDataFields));
    SkPaintParamsKey key = create_key(&builder, dummySnippetID, kBlockDataSize);

    // Key creation fails.
    REPORTER_ASSERT(reporter, key.isErrorKey());
}

DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyEqualityChecksSnippetID, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    static const int kBlockDataSize = 4;
    static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = {
            {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize},
    };

    int dummySnippetID1 = dict->addUserDefinedSnippet("key1", SkMakeSpan(kDataFields));
    int dummySnippetID2 = dict->addUserDefinedSnippet("key2", SkMakeSpan(kDataFields));

    SkPaintParamsKeyBuilder builderA(dict, SkBackend::kGraphite);
    SkPaintParamsKeyBuilder builderB(dict, SkBackend::kGraphite);
    SkPaintParamsKeyBuilder builderC(dict, SkBackend::kGraphite);
    SkPaintParamsKey keyA = create_key(&builderA, dummySnippetID1, kBlockDataSize);
    SkPaintParamsKey keyB = create_key(&builderB, dummySnippetID1, kBlockDataSize);
    SkPaintParamsKey keyC = create_key(&builderC, dummySnippetID2, kBlockDataSize);

    // Verify that keyA matches keyB, and that it does not match keyC.
    REPORTER_ASSERT(reporter, keyA == keyB);
    REPORTER_ASSERT(reporter, keyA != keyC);
    REPORTER_ASSERT(reporter, !(keyA == keyC));
    REPORTER_ASSERT(reporter, !(keyA != keyB));
}

DEF_GRAPHITE_TEST_FOR_CONTEXTS(KeyEqualityChecksData, reporter, context) {

    auto dict = context->priv().shaderCodeDictionary();
    static const int kBlockDataSize = 4;
    static constexpr SkPaintParamsKey::DataPayloadField kDataFields[] = {
            {"data", SkPaintParamsKey::DataPayloadType::kByte, kBlockDataSize},
    };

    int dummySnippetID = dict->addUserDefinedSnippet("key", SkMakeSpan(kDataFields));

    static constexpr uint8_t kData [4] = {1, 2, 3, 4};
    static constexpr uint8_t kData2[4] = {1, 2, 3, 99};

    SkPaintParamsKeyBuilder builderA(dict, SkBackend::kGraphite);
    SkPaintParamsKeyBuilder builderB(dict, SkBackend::kGraphite);
    SkPaintParamsKeyBuilder builderC(dict, SkBackend::kGraphite);
    SkPaintParamsKey keyA = create_key_with_data(&builderA, dummySnippetID, SkMakeSpan(kData));
    SkPaintParamsKey keyB = create_key_with_data(&builderB, dummySnippetID, SkMakeSpan(kData));
    SkPaintParamsKey keyC = create_key_with_data(&builderC, dummySnippetID, SkMakeSpan(kData2));

    // Verify that keyA matches keyB, and that it does not match keyC.
    REPORTER_ASSERT(reporter, keyA == keyB);
    REPORTER_ASSERT(reporter, keyA != keyC);
    REPORTER_ASSERT(reporter, !(keyA == keyC));
    REPORTER_ASSERT(reporter, !(keyA != keyB));
}
<|endoftext|>