Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Sandbox: add support to work on temporary copy
  • Loading branch information
martyone committed Apr 4, 2013
1 parent 5f89a21 commit ea672d4
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 140 deletions.
4 changes: 2 additions & 2 deletions libssu/libssu.pro
Expand Up @@ -7,7 +7,7 @@ public_headers = \

HEADERS = \
$${public_headers} \
sandboxfileenginehandler_p.h \
sandbox_p.h \
ssucoreconfig.h \
ssudeviceinfo.h \
ssulog.h \
Expand All @@ -16,7 +16,7 @@ HEADERS = \
ssurepomanager.h \

SOURCES = \
sandboxfileenginehandler.cpp \
sandbox.cpp \
ssu.cpp \
ssucoreconfig.cpp \
ssudeviceinfo.cpp \
Expand Down
178 changes: 178 additions & 0 deletions libssu/sandbox.cpp
@@ -0,0 +1,178 @@
/**
* @file sandbox.cpp
* @copyright 2013 Jolla Ltd.
* @author Martin Kampas <martin.kampas@tieto.com>
* @date 2013
*/

#include "sandbox_p.h"

#include <QtCore/QAbstractFileEngineHandler>
#include <QtCore/QDir>
#include <QtCore/QFSFileEngine>
#include <QtCore/QFileInfo>
#include <QtCore/QProcessEnvironment>
#include <QtCore/QSet>

#include "libssu/ssucoreconfig.h"
// TODO: rename to ssuconstants.h?
#include "constants.h"

class Sandbox::FileEngineHandler : public QAbstractFileEngineHandler {
public:
FileEngineHandler(const QString &sandboxPath);

QAbstractFileEngine *create(const QString &fileName) const;

private:
const QString m_sandboxPath;
};

/**
* @class Sandbox
*
* Redirects all file operations on system configuration files to files under
* sandbox directory. When constructed without arguments, the directory is get
* from @c SSU_TESTS_SANDBOX environment variable.
*
* When constructed with @a usage UseAsSkeleton, it will first make temporary
* copy of @a sandboxPath to work on and files in the original directory will
* stay untouched.
*
* Internally it is based on QAbstractFileEngineHandler.
*/

Sandbox *Sandbox::s_instance = 0;

QSet<QString> Sandbox::s_ssuConfigFiles = QSet<QString>()
<< SSU_CONFIGURATION
<< SSU_REPO_CONFIGURATION
<< SSU_DEFAULT_CONFIGURATION
<< SSU_BOARD_MAPPING_CONFIGURATION;

QSet<QString> Sandbox::s_ssuConfigDirectories = QSet<QString>()
<< SSU_BOARD_MAPPING_CONFIGURATION_DIR;

Sandbox::Sandbox(){
if (s_instance != 0){
qFatal("%s: Cannot be instantiated more than once", Q_FUNC_INFO);
}

s_instance = this;

m_handler = 0;

m_sandboxPath = QProcessEnvironment::systemEnvironment().value("SSU_TESTS_SANDBOX");

if (m_sandboxPath.isEmpty()){
return;
}

if (!QFileInfo(m_sandboxPath).exists()){
qFatal("%s: Invalid SSU_TESTS_SANDBOX value: No such file or directory",
qPrintable(m_sandboxPath));
}

if (!QFileInfo(m_sandboxPath).isDir()){
qFatal("%s: Invalid SSU_TESTS_SANDBOX value: Not a directory",
qPrintable(m_sandboxPath));
}

m_handler = new FileEngineHandler(m_sandboxPath);
}

Sandbox::Sandbox(const QString &sandboxPath, Usage usage){
if (s_instance != 0){
qFatal("%s: Cannot be instantiated more than once", Q_FUNC_INFO);
}

s_instance = this;

m_handler = 0;

m_sandboxPath = sandboxPath;

if (m_sandboxPath.isEmpty()){
qWarning("%s: Empty sandboxPath", Q_FUNC_INFO);
return;
}

if (!QFileInfo(m_sandboxPath).exists()){
qFatal("%s: Invalid sandboxPath: No such file or directory",
qPrintable(m_sandboxPath));
}

if (!QFileInfo(m_sandboxPath).isDir()){
qFatal("%s: Invalid sandboxPath: Not a directory",
qPrintable(m_sandboxPath));
}

if (usage == UseAsSkeleton){
QProcess mktemp;
mktemp.start("mktemp", QStringList() << "-t" << "-d" << "ssu-sandbox.XXX");
if (!mktemp.waitForFinished() || mktemp.exitCode() != 0){
qFatal("%s: Failed to create sandbox directory", Q_FUNC_INFO);
}

m_tempDir = mktemp.readAllStandardOutput().trimmed();
if (!QFileInfo(m_tempDir).isDir()){
qFatal("%s: Temporary directory disappeared: '%s'", Q_FUNC_INFO, qPrintable(m_tempDir));
}

const QString sandboxCopyPath = QString("%1/configroot").arg(m_tempDir);

if (QProcess::execute("cp", QStringList() << "-r" << m_sandboxPath << sandboxCopyPath) != 0){
qFatal("%s: Failed to copy sandbox directory", Q_FUNC_INFO);
}

m_sandboxPath = sandboxCopyPath;
}

m_handler = new FileEngineHandler(m_sandboxPath);
}

Sandbox::~Sandbox(){
delete m_handler;

if (!m_tempDir.isEmpty() && QFileInfo(m_tempDir).exists()){
if (QProcess::execute("rm", QStringList() << "-rf" << m_tempDir) != 0){
qWarning("%s: Failed to remove temporary directory", Q_FUNC_INFO);
}
}

s_instance = 0;
}

/*
* @class Sandbox::FileEngineHandler
*/

Sandbox::FileEngineHandler::FileEngineHandler(const QString &sandboxPath):
m_sandboxPath(sandboxPath){
Q_ASSERT(!sandboxPath.isEmpty());
}

QAbstractFileEngine *Sandbox::FileEngineHandler::create(const QString &fileName) const{
Q_ASSERT(!m_sandboxPath.isEmpty());

if (!fileName.startsWith('/')){
return 0;
}

if (!s_ssuConfigFiles.contains(fileName)){
bool match = false;
foreach (const QString &ssuConfigDirectory, s_ssuConfigDirectories){
if (fileName.startsWith(ssuConfigDirectory + '/')){
match = true;
break;
}
}
if (!match){
return 0;
}
}

const QString fileName_ = QDir(m_sandboxPath).absoluteFilePath(QString(fileName).remove(0, 1));

return new QFSFileEngine(fileName_);
}
37 changes: 37 additions & 0 deletions libssu/sandbox_p.h
@@ -0,0 +1,37 @@
/**
* @file sandbox_p.h
* @copyright 2013 Jolla Ltd.
* @author Martin Kampas <martin.kampas@tieto.com>
* @date 2013
*/

#ifndef _SANDBOX_P_H
#define _SANDBOX_P_H

#include <QtCore/QSet>
#include <QtCore/QString>

class Sandbox {
class FileEngineHandler;

public:
enum Usage {
UseDirectly,
UseAsSkeleton,
};

public:
Sandbox();
Sandbox(const QString &sandboxPath, Usage usage);
~Sandbox();

private:
static Sandbox *s_instance;
static QSet<QString> s_ssuConfigFiles;
static QSet<QString> s_ssuConfigDirectories;
QString m_sandboxPath;
QString m_tempDir;
FileEngineHandler *m_handler;
};

#endif
106 changes: 0 additions & 106 deletions libssu/sandboxfileenginehandler.cpp

This file was deleted.

27 changes: 0 additions & 27 deletions libssu/sandboxfileenginehandler_p.h

This file was deleted.

6 changes: 3 additions & 3 deletions tests/testutils/sandboxhook.cpp
@@ -1,11 +1,11 @@
#include <dlfcn.h>

#include "libssu/sandboxfileenginehandler_p.h"
#include "libssu/sandbox_p.h"

extern "C" void qt_startup_hook()
{
SandboxFileEngineHandler *const handler = new SandboxFileEngineHandler();
Q_UNUSED(handler);
Sandbox *const sandbox = new Sandbox();
Q_UNUSED(sandbox);

static void(*next_qt_startup_hook)() = (void (*)()) dlsym(RTLD_NEXT, "qt_startup_hook");
next_qt_startup_hook();
Expand Down
4 changes: 2 additions & 2 deletions tests/ut_urlresolver/main.cpp
Expand Up @@ -7,11 +7,11 @@

#include <QtTest/QtTest>

#include "libssu/sandboxfileenginehandler_p.h"
#include "libssu/sandbox_p.h"
#include "urlresolvertest.cpp"

int main(int argc, char **argv){
SandboxFileEngineHandler h;
Sandbox s;

UrlResolverTest urlResolverTest;

Expand Down

0 comments on commit ea672d4

Please sign in to comment.