<commit_before>/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */

#include <ns3/core-module.h>
#include <ns3/callback.h>
#include <ns3/packet.h>
#include "BitAlternante.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("BitAlternante");

BitAlternanteTx::BitAlternanteTx(Ptr<NetDevice> disp,
                                 Time           espera,
                                 uint32_t       tamPqt,
                                 uint8_t        tamVentana)
{
  NS_LOG_FUNCTION (disp << espera << tamPqt);

  // Inicializamos las variables privadas
  m_disp          = disp;
  m_esperaACK     = espera;
  m_tamPqt        = tamPqt;
  m_inicioVentana = 0;
  m_tamVentana    = tamVentana;
  m_tx            = m_inicioVentana;
  m_totalPqt      = 0;
}

void
BitAlternanteTx::ACKRecibido(Ptr<NetDevice>        receptor,
                             Ptr<const Packet>     recibido,
                             uint16_t              protocolo,
                             const Address &       desde,
                             const Address &       hacia,
                             NetDevice::PacketType tipoPaquete)
{
  NS_LOG_FUNCTION (receptor << recibido->GetSize () <<
                   std::hex << protocolo <<
                   desde << hacia << tipoPaquete);
  uint8_t contenido;

  // Copiamos el primer octeto del campo de datos del paquete recibido
  // (que es el que contiene el número de secuencia)
  recibido->CopyData(&contenido, 1);
  NS_LOG_DEBUG ("    Recibido ACK en nodo " << m_node->GetId() << " con "
                << (unsigned int) contenido);

  /* Comprobamos si el siguiente paquete a enviar (valor de ACK) es el
     de inicio de ventana. En ese caso enviamos reenviamos todos los paquetes
     de la ventana (ha habido un error) */
  if (contenido == m_inicioVentana) {
    m_tx = m_inicioVentana;
    EnviaPaquete();
  }
  /* Comprobamos que el siguiente paquete a enviar se encuentra entre
  los valores esperados */
  else if (CompruebaACK(contenido)) {
    //El valor es valido, por lo que avanzamos la ventana
    m_inicioVentana = contenido;
    //Enviamos los paquetes que faltan por enviar en la ventana
    EnviaPaquete();
  }

  /* Si el valor esta fuera de la ventana, el paquete es ignorado */

  // Comprobamos si el número de secuencia del ACK se corresponde con
  // el de secuencia del siguiente paquete a transmitir
  /*if (contenido == m_tx + 1 || 2 * tamVentana - contenido == 0) {
     // Si es correcto desactivo el temporizador
    Simulator::Cancel(m_temporizador);
    // Incrementamos el numero de secuencia
    if (++m_tx == 2 * m_tamVentana + 1) {
      m_tx = 0;
    }
    // Incrementamos el total de paquetes (ELIMINAR)
    m_totalPqt++;
    // Se transmite un nuevo paquete
    m_paquete = Create<Packet> (&m_tx, m_tamPqt + 1);
    EnviaPaquete();
  }*/
}

int
BitAlternanteTx::CompruebaACK(uint8_t contenido) {

  int resultado = 0;
  //Evitamos el desborde
  if (contenido < m_inicioVentana) {
    contenido = contenido + m_tamVentana;
  }

  if (contenido > m_inicioVentana &&
      contenido <= m_inicioVentana + m_tamVentana + 1) {
    resultado = 1;
  }
  return resultado;
}

void BitAlternanteTx::IncrementaNumSeq() {
  if (++m_tx == 2 * m_tamVentana + 1)
    m_tx = 0;
}

void
BitAlternanteTx::VenceTemporizador()
{
  NS_LOG_FUNCTION_NOARGS ();
  NS_LOG_DEBUG("¡¡¡TIMEOUT!!! Reenviando");
  // Reenviamos el último paquete transmitido
  m_paquete = Create<Packet> (&m_tx, m_tamPqt + 1);
  EnviaPaquete ();
}

/**
 * EnviaPaquete: transmite paquetes deste m_tx hasta el final de la ventana.
 */
void
BitAlternanteTx::EnviaPaquete()
{
  NS_LOG_FUNCTION_NOARGS ();

  // Paquete a enviar
  Ptr<Packet> m_paquete;

  //Se transmiten los paquetes desde m_tx hasta el final de la ventana
  for ( ; m_tx <= m_inicioVentana + m_tamVentana; IncrementaNumSeq()) {
    // Envío el paquete
    m_paquete = Create<Packet> (&m_tx, m_tamPqt + 1);
    m_node->GetDevice(0)->Send(m_paquete, m_disp->GetAddress(), 0x0800);

    NS_LOG_DEBUG ("Transmitido paquete de " << m_paquete->GetSize () <<
                 " octetos en nodo " << m_node->GetId() <<
                 " con " << (unsigned int) m_tx <<
                 " en " << Simulator::Now());
  }

  // Programo el temporizador
  if (m_esperaACK != 0)
    m_temporizador = Simulator::Schedule (m_esperaACK, &BitAlternanteTx::VenceTemporizador, this);
}

uint32_t
BitAlternanteTx::TotalDatos()
{
  // Devuelvo el total de paquetes enviados
  return m_totalPqt;
}

BitAlternanteRx::BitAlternanteRx(Ptr<NetDevice> disp, uint8_t tamVentana)
{
  NS_LOG_FUNCTION (disp);

  m_disp = disp;
  m_rx   = 0;
  m_tamVentana = tamVentana;
}

void
BitAlternanteRx::PaqueteRecibido(Ptr<NetDevice>        receptor,
                                 Ptr<const Packet>     recibido,
                                 uint16_t              protocolo,
                                 const Address &       desde,
                                 const Address &       hacia,
                                 NetDevice::PacketType tipoPaquete)
{
  NS_LOG_FUNCTION (receptor << recibido->GetSize () <<
                   std::hex << protocolo <<
                   desde << hacia << tipoPaquete);
  uint8_t contenido;

  // Obtengo el valor del número de secuecia
  recibido->CopyData(&contenido, 1);
  NS_LOG_DEBUG ("    Recibido paquete en nodo " << m_node->GetId() << " con "
                << (unsigned int) contenido);
  // Si el número de secuencia es correcto
  if (contenido == m_rx) {
    // Si es correcto, incrementamos el numero de secuencia
    IncrementaNumSeq()
  }
  // Transmito en cualquier caso un ACK
  EnviaACK();
}

void BitAlternanteRx::IncrementaNumSeq() {
  if (++m_rx == 2 * m_tamVentana + 1)
    m_rx = 0;
}

void
BitAlternanteRx::EnviaACK()
{
  NS_LOG_FUNCTION_NOARGS ();
  Ptr<Packet> p = Create<Packet> (&m_rx, 1);

  NS_LOG_DEBUG ("  Transmitido ACK de " << p->GetSize () <<
                " octetos en nodo " << m_node->GetId() <<
                " con " << (unsigned int) m_rx <<
                " en " << Simulator::Now());
  m_node->GetDevice(0)->Send(p, m_disp->GetAddress(), 0x0800);
}

<commit_msg>First part of P04 (9)<commit_after>/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */

#include <ns3/core-module.h>
#include <ns3/callback.h>
#include <ns3/packet.h>
#include "BitAlternante.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("BitAlternante");

BitAlternanteTx::BitAlternanteTx(Ptr<NetDevice> disp,
                                 Time           espera,
                                 uint32_t       tamPqt,
                                 uint8_t        tamVentana)
{
  NS_LOG_FUNCTION (disp << espera << tamPqt);

  // Inicializamos las variables privadas
  m_disp          = disp;
  m_esperaACK     = espera;
  m_tamPqt        = tamPqt;
  m_inicioVentana = 0;
  m_tamVentana    = tamVentana;
  m_tx            = m_inicioVentana;
  m_totalPqt      = 0;
}

void
BitAlternanteTx::ACKRecibido(Ptr<NetDevice>        receptor,
                             Ptr<const Packet>     recibido,
                             uint16_t              protocolo,
                             const Address &       desde,
                             const Address &       hacia,
                             NetDevice::PacketType tipoPaquete)
{
  NS_LOG_FUNCTION (receptor << recibido->GetSize () <<
                   std::hex << protocolo <<
                   desde << hacia << tipoPaquete);
  uint8_t contenido;

  // Copiamos el primer octeto del campo de datos del paquete recibido
  // (que es el que contiene el número de secuencia)
  recibido->CopyData(&contenido, 1);
  NS_LOG_DEBUG ("    Recibido ACK en nodo " << m_node->GetId() << " con "
                << (unsigned int) contenido);

  /* Comprobamos si el siguiente paquete a enviar (valor de ACK) es el
     de inicio de ventana. En ese caso enviamos reenviamos todos los paquetes
     de la ventana (ha habido un error) */
  if (contenido == m_inicioVentana) {
    m_tx = m_inicioVentana;
    EnviaPaquete();
  }
  /* Comprobamos que el siguiente paquete a enviar se encuentra entre
  los valores esperados */
  else if (CompruebaACK(contenido)) {
    //El valor es valido, por lo que avanzamos la ventana
    m_inicioVentana = contenido;
    //Enviamos los paquetes que faltan por enviar en la ventana
    EnviaPaquete();
  }

  /* Si el valor esta fuera de la ventana, el paquete es ignorado */

  // Comprobamos si el número de secuencia del ACK se corresponde con
  // el de secuencia del siguiente paquete a transmitir
  /*if (contenido == m_tx + 1 || 2 * tamVentana - contenido == 0) {
     // Si es correcto desactivo el temporizador
    Simulator::Cancel(m_temporizador);
    // Incrementamos el numero de secuencia
    if (++m_tx == 2 * m_tamVentana + 1) {
      m_tx = 0;
    }
    // Incrementamos el total de paquetes (ELIMINAR)
    m_totalPqt++;
    // Se transmite un nuevo paquete
    m_paquete = Create<Packet> (&m_tx, m_tamPqt + 1);
    EnviaPaquete();
  }*/
}

int
BitAlternanteTx::CompruebaACK(uint8_t contenido) {

  int resultado = 0;
  //Evitamos el desborde
  if (contenido < m_inicioVentana) {
    contenido = contenido + m_tamVentana;
  }

  if (contenido > m_inicioVentana &&
      contenido <= m_inicioVentana + m_tamVentana + 1) {
    resultado = 1;
  }
  return resultado;
}

void BitAlternanteTx::IncrementaNumSeq() {
  if (++m_tx == 2 * m_tamVentana + 1)
    m_tx = 0;
}

void
BitAlternanteTx::VenceTemporizador()
{
  NS_LOG_FUNCTION_NOARGS ();
  NS_LOG_DEBUG("¡¡¡TIMEOUT!!! Reenviando");
  // Reenviamos el último paquete transmitido
  m_paquete = Create<Packet> (&m_tx, m_tamPqt + 1);
  EnviaPaquete ();
}

/**
 * EnviaPaquete: transmite paquetes deste m_tx hasta el final de la ventana.
 */
void
BitAlternanteTx::EnviaPaquete()
{
  NS_LOG_FUNCTION_NOARGS ();

  // Paquete a enviar
  Ptr<Packet> m_paquete;

  //Se transmiten los paquetes desde m_tx hasta el final de la ventana
  for ( ; m_tx <= m_inicioVentana + m_tamVentana; IncrementaNumSeq()) {
    // Envío el paquete
    m_paquete = Create<Packet> (&m_tx, m_tamPqt + 1);
    m_node->GetDevice(0)->Send(m_paquete, m_disp->GetAddress(), 0x0800);

    NS_LOG_DEBUG ("Transmitido paquete de " << m_paquete->GetSize () <<
                 " octetos en nodo " << m_node->GetId() <<
                 " con " << (unsigned int) m_tx <<
                 " en " << Simulator::Now());
  }

  // Programo el temporizador
  if (m_esperaACK != 0)
    m_temporizador = Simulator::Schedule (m_esperaACK, &BitAlternanteTx::VenceTemporizador, this);
}

uint32_t
BitAlternanteTx::TotalDatos()
{
  // Devuelvo el total de paquetes enviados
  return m_totalPqt;
}

BitAlternanteRx::BitAlternanteRx(Ptr<NetDevice> disp, uint8_t tamVentana)
{
  NS_LOG_FUNCTION (disp);

  m_disp = disp;
  m_rx   = 0;
  m_tamVentana = tamVentana;
}

void
BitAlternanteRx::PaqueteRecibido(Ptr<NetDevice>        receptor,
                                 Ptr<const Packet>     recibido,
                                 uint16_t              protocolo,
                                 const Address &       desde,
                                 const Address &       hacia,
                                 NetDevice::PacketType tipoPaquete)
{
  NS_LOG_FUNCTION (receptor << recibido->GetSize () <<
                   std::hex << protocolo <<
                   desde << hacia << tipoPaquete);
  uint8_t contenido;

  // Obtengo el valor del número de secuecia
  recibido->CopyData(&contenido, 1);
  NS_LOG_DEBUG ("    Recibido paquete en nodo " << m_node->GetId() << " con "
                << (unsigned int) contenido);
  // Si el número de secuencia es correcto
  if (contenido == m_rx) {
    // Si es correcto, incrementamos el numero de secuencia
    IncrementaNumSeq();
  }
  // Transmito en cualquier caso un ACK
  EnviaACK();
}

void BitAlternanteRx::IncrementaNumSeq() {
  if (++m_rx == 2 * m_tamVentana + 1)
    m_rx = 0;
}

void
BitAlternanteRx::EnviaACK()
{
  NS_LOG_FUNCTION_NOARGS ();
  Ptr<Packet> p = Create<Packet> (&m_rx, 1);

  NS_LOG_DEBUG ("  Transmitido ACK de " << p->GetSize () <<
                " octetos en nodo " << m_node->GetId() <<
                " con " << (unsigned int) m_rx <<
                " en " << Simulator::Now());
  m_node->GetDevice(0)->Send(p, m_disp->GetAddress(), 0x0800);
}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Build Suite.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "tst_api.h"

#include "../../src/app/shared/qbssettings.h"

#include <api/jobs.h>
#include <api/project.h>
#include <api/projectdata.h>
#include <logging/ilogsink.h>
#include <tools/hostosinfo.h>
#include <tools/installoptions.h>
#include <tools/preferences.h>
#include <tools/setupprojectparameters.h>

#include <QCoreApplication>
#include <QDir>
#include <QEventLoop>
#include <QScopedPointer>
#include <QTest>

class LogSink: public qbs::ILogSink
{
    void doPrintWarning(const qbs::ErrorInfo &error) {
        qDebug("%s", qPrintable(error.toString()));
    }
    void doPrintMessage(qbs::LoggerLevel, const QString &, const QString &) { }
};

TestApi::TestApi() : m_logSink(new LogSink)
{
}

TestApi::~TestApi()
{
    delete m_logSink;
}

static void waitForFinished(qbs::AbstractJob *job)
{
    QEventLoop loop;
    QObject::connect(job, SIGNAL(finished(bool,qbs::AbstractJob*)), &loop, SLOT(quit()));
    loop.exec();
}

void TestApi::disabledInstallGroup()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/testdata"
        "/disabled_install_group/project.qbs")));
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    qbs::Project project = job->project();
    qbs::ProjectData projectData = project.projectData();
    QCOMPARE(projectData.allProducts().count(), 1);
    qbs::ProductData product = projectData.allProducts().first();
    const QList<qbs::TargetArtifact> targets = product.targetArtifacts();
    QCOMPARE(targets.count(), 1);
    QVERIFY(targets.first().isExecutable());
    QList<qbs::InstallableFile> installableFiles
            = project.installableFilesForProduct(product, qbs::InstallOptions());
    QCOMPARE(installableFiles.count(), 0);
    QCOMPARE(project.targetExecutable(product, qbs::InstallOptions()), targets.first().filePath());
}

void TestApi::fileTagsFilterOverride()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/testdata"
        "/filetagsfilter_override/project.qbs")));
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    qbs::Project project = job->project();
    qbs::ProjectData projectData = project.projectData();
    QCOMPARE(projectData.allProducts().count(), 1);
    const qbs::ProductData product = projectData.allProducts().first();
    QList<qbs::InstallableFile> installableFiles
            = project.installableFilesForProduct(product, qbs::InstallOptions());
    QCOMPARE(installableFiles.count(), 1);
    QEXPECT_FAIL(0, "QBS-424", Continue);
    QVERIFY(installableFiles.first().targetDirectory().contains("habicht"));
}

void TestApi::installableFiles()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/../blackbox/testdata"
        "/installed_artifact/installed_artifact.qbs")));
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    qbs::Project project = job->project();
    qbs::ProjectData projectData = project.projectData();
    QCOMPARE(projectData.allProducts().count(), 1);
    qbs::ProductData product = projectData.allProducts().first();
    qbs::InstallOptions installOptions;
    installOptions.setInstallRoot(QLatin1String("/tmp"));
    QList<qbs::InstallableFile> installableFiles
            = project.installableFilesForProduct(product, installOptions);
    QCOMPARE(installableFiles.count(), 2);
    qbs::InstallableFile const application = installableFiles.first();
    QVERIFY(application.isExecutable());
    QString expectedTargetFilePath
            = qbs::Internal::HostOsInfo::appendExecutableSuffix(QLatin1String("/tmp/usr/bin/installedApp"));
    QCOMPARE(application.targetFilePath(), expectedTargetFilePath);
    QCOMPARE(project.targetExecutable(product, installOptions), expectedTargetFilePath);

    setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/../blackbox/testdata"
        "/recursive_wildcards/recursive_wildcards.qbs")));
    job.reset(qbs::Project::setupProject(setupParams, m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    project = job->project();
    projectData = project.projectData();
    QCOMPARE(projectData.allProducts().count(), 1);
    product = projectData.allProducts().first();
    installableFiles = project.installableFilesForProduct(product, installOptions);
    QCOMPARE(installableFiles.count(), 2);
    foreach (const qbs::InstallableFile &f, installableFiles)
        QVERIFY(!f.isExecutable());
    QCOMPARE(installableFiles.first().targetFilePath(), QLatin1String("/tmp/dir/file1.txt"));
    QCOMPARE(installableFiles.last().targetFilePath(), QLatin1String("/tmp/dir/file2.txt"));
}

void TestApi::listBuildSystemFiles()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    const QString projectDir
            = QDir::cleanPath(QLatin1String(SRCDIR "/../blackbox/testdata/subprojects"));
    const QString topLevelProjectFile = projectDir + QLatin1String("/toplevelproject.qbs");
    setupParams.setProjectFilePath(topLevelProjectFile);
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    const QSet<QString> buildSystemFiles = job->project().buildSystemFiles();
    QVERIFY(buildSystemFiles.contains(topLevelProjectFile));
    QVERIFY(buildSystemFiles.contains(projectDir + QLatin1String("/subproject2/subproject2.qbs")));
    QVERIFY(buildSystemFiles.contains(projectDir
                                      + QLatin1String("/subproject2/subproject3/subproject3.qbs")));
}

void TestApi::nonexistingProjectPropertyFromProduct()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    const QString projectDir
            = QDir::cleanPath(QLatin1String(SRCDIR "/testdata/nonexistingprojectproperties"));
    const QString topLevelProjectFile = projectDir + QLatin1String("/invalidaccessfromproduct.qbs");
    setupParams.setProjectFilePath(topLevelProjectFile);
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QEXPECT_FAIL("", "QBS-432", Abort);
    QVERIFY(job->error().hasError());
    QVERIFY2(job->error().toString().contains(QLatin1String("blubb")),
             qPrintable(job->error().toString()));
}

void TestApi::nonexistingProjectPropertyFromCommandLine()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    const QString projectDir
            = QDir::cleanPath(QLatin1String(SRCDIR "/testdata/nonexistingprojectproperties"));
    const QString topLevelProjectFile = projectDir + QLatin1String("/project.qbs");
    setupParams.setProjectFilePath(topLevelProjectFile);
    QVariantMap projectProperties;
    projectProperties.insert(QLatin1String("project.blubb"), QLatin1String("true"));
    setupParams.setOverriddenValues(projectProperties);
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY(job->error().hasError());
    QVERIFY2(job->error().toString().contains(QLatin1String("blubb")),
             qPrintable(job->error().toString()));
}

qbs::SetupProjectParameters TestApi::defaultSetupParameters() const
{
    qbs::SetupProjectParameters setupParams;
    setupParams.setDryRun(true); // So no build graph gets created.
    setupParams.setBuildRoot(QLatin1String("/blubb")); // Must be set and be absolute.
    setupParams.setRestoreBehavior(qbs::SetupProjectParameters::ResolveOnly); // No restoring.

    const QString qbsRootPath = QDir::cleanPath(QCoreApplication::applicationDirPath()
                                                + QLatin1String("/../"));
    SettingsPtr settings = qbsSettings();
    setupParams.setSearchPaths(qbs::Preferences(settings.data()).searchPaths(qbsRootPath));
    setupParams.setPluginPaths(qbs::Preferences(settings.data()).pluginPaths(qbsRootPath));
    QVariantMap buildConfig;
    buildConfig.insert(QLatin1String("qbs.profile"), QLatin1String("qbs_autotests"));
    buildConfig.insert(QLatin1String("qbs.buildVariant"), QLatin1String("debug"));
    setupParams.setBuildConfiguration(buildConfig);
    setupParams.expandBuildConfiguration(settings.data());
    return setupParams;
}

QTEST_MAIN(TestApi)
<commit_msg>Fix API test.<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Build Suite.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "tst_api.h"

#include "../../src/app/shared/qbssettings.h"

#include <api/jobs.h>
#include <api/project.h>
#include <api/projectdata.h>
#include <logging/ilogsink.h>
#include <tools/hostosinfo.h>
#include <tools/installoptions.h>
#include <tools/preferences.h>
#include <tools/setupprojectparameters.h>

#include <QCoreApplication>
#include <QDir>
#include <QEventLoop>
#include <QScopedPointer>
#include <QTest>

class LogSink: public qbs::ILogSink
{
    void doPrintWarning(const qbs::ErrorInfo &error) {
        qDebug("%s", qPrintable(error.toString()));
    }
    void doPrintMessage(qbs::LoggerLevel, const QString &, const QString &) { }
};

TestApi::TestApi() : m_logSink(new LogSink)
{
}

TestApi::~TestApi()
{
    delete m_logSink;
}

static void waitForFinished(qbs::AbstractJob *job)
{
    QEventLoop loop;
    QObject::connect(job, SIGNAL(finished(bool,qbs::AbstractJob*)), &loop, SLOT(quit()));
    loop.exec();
}

void TestApi::disabledInstallGroup()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/testdata"
        "/disabled_install_group/project.qbs")));
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    qbs::Project project = job->project();
    qbs::ProjectData projectData = project.projectData();
    QCOMPARE(projectData.allProducts().count(), 1);
    qbs::ProductData product = projectData.allProducts().first();
    const QList<qbs::TargetArtifact> targets = product.targetArtifacts();
    QCOMPARE(targets.count(), 1);
    QVERIFY(targets.first().isExecutable());
    QList<qbs::InstallableFile> installableFiles
            = project.installableFilesForProduct(product, qbs::InstallOptions());
    QCOMPARE(installableFiles.count(), 0);
    QCOMPARE(project.targetExecutable(product, qbs::InstallOptions()), targets.first().filePath());
}

void TestApi::fileTagsFilterOverride()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/testdata"
        "/filetagsfilter_override/project.qbs")));
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    qbs::Project project = job->project();
    qbs::ProjectData projectData = project.projectData();
    QCOMPARE(projectData.allProducts().count(), 1);
    const qbs::ProductData product = projectData.allProducts().first();
    QList<qbs::InstallableFile> installableFiles
            = project.installableFilesForProduct(product, qbs::InstallOptions());
    QCOMPARE(installableFiles.count(), 1);
    QEXPECT_FAIL(0, "QBS-424", Continue);
    QVERIFY(installableFiles.first().targetDirectory().contains("habicht"));
}

void TestApi::installableFiles()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/../blackbox/testdata"
        "/installed_artifact/installed_artifact.qbs")));
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    qbs::Project project = job->project();
    qbs::ProjectData projectData = project.projectData();
    QCOMPARE(projectData.allProducts().count(), 1);
    qbs::ProductData product = projectData.allProducts().first();
    qbs::InstallOptions installOptions;
    installOptions.setInstallRoot(QLatin1String("/tmp"));
    QList<qbs::InstallableFile> installableFiles
            = project.installableFilesForProduct(product, installOptions);
    QCOMPARE(installableFiles.count(), 2);
    foreach (const qbs::InstallableFile &f,installableFiles) {
        if (!f.sourceFilePath().endsWith("main.cpp")) {
            QVERIFY(f.isExecutable());
            QString expectedTargetFilePath = qbs::Internal::HostOsInfo
                    ::appendExecutableSuffix(QLatin1String("/tmp/usr/bin/installedApp"));
            QCOMPARE(f.targetFilePath(), expectedTargetFilePath);
            QCOMPARE(project.targetExecutable(product, installOptions), expectedTargetFilePath);
            break;
        }
    }

    setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/../blackbox/testdata"
        "/recursive_wildcards/recursive_wildcards.qbs")));
    job.reset(qbs::Project::setupProject(setupParams, m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    project = job->project();
    projectData = project.projectData();
    QCOMPARE(projectData.allProducts().count(), 1);
    product = projectData.allProducts().first();
    installableFiles = project.installableFilesForProduct(product, installOptions);
    QCOMPARE(installableFiles.count(), 2);
    foreach (const qbs::InstallableFile &f, installableFiles)
        QVERIFY(!f.isExecutable());
    QCOMPARE(installableFiles.first().targetFilePath(), QLatin1String("/tmp/dir/file1.txt"));
    QCOMPARE(installableFiles.last().targetFilePath(), QLatin1String("/tmp/dir/file2.txt"));
}

void TestApi::listBuildSystemFiles()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    const QString projectDir
            = QDir::cleanPath(QLatin1String(SRCDIR "/../blackbox/testdata/subprojects"));
    const QString topLevelProjectFile = projectDir + QLatin1String("/toplevelproject.qbs");
    setupParams.setProjectFilePath(topLevelProjectFile);
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
    const QSet<QString> buildSystemFiles = job->project().buildSystemFiles();
    QVERIFY(buildSystemFiles.contains(topLevelProjectFile));
    QVERIFY(buildSystemFiles.contains(projectDir + QLatin1String("/subproject2/subproject2.qbs")));
    QVERIFY(buildSystemFiles.contains(projectDir
                                      + QLatin1String("/subproject2/subproject3/subproject3.qbs")));
}

void TestApi::nonexistingProjectPropertyFromProduct()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    const QString projectDir
            = QDir::cleanPath(QLatin1String(SRCDIR "/testdata/nonexistingprojectproperties"));
    const QString topLevelProjectFile = projectDir + QLatin1String("/invalidaccessfromproduct.qbs");
    setupParams.setProjectFilePath(topLevelProjectFile);
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QEXPECT_FAIL("", "QBS-432", Abort);
    QVERIFY(job->error().hasError());
    QVERIFY2(job->error().toString().contains(QLatin1String("blubb")),
             qPrintable(job->error().toString()));
}

void TestApi::nonexistingProjectPropertyFromCommandLine()
{
    qbs::SetupProjectParameters setupParams = defaultSetupParameters();
    const QString projectDir
            = QDir::cleanPath(QLatin1String(SRCDIR "/testdata/nonexistingprojectproperties"));
    const QString topLevelProjectFile = projectDir + QLatin1String("/project.qbs");
    setupParams.setProjectFilePath(topLevelProjectFile);
    QVariantMap projectProperties;
    projectProperties.insert(QLatin1String("project.blubb"), QLatin1String("true"));
    setupParams.setOverriddenValues(projectProperties);
    QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
                                                                        m_logSink, 0));
    waitForFinished(job.data());
    QVERIFY(job->error().hasError());
    QVERIFY2(job->error().toString().contains(QLatin1String("blubb")),
             qPrintable(job->error().toString()));
}

qbs::SetupProjectParameters TestApi::defaultSetupParameters() const
{
    qbs::SetupProjectParameters setupParams;
    setupParams.setDryRun(true); // So no build graph gets created.
    setupParams.setBuildRoot(QLatin1String("/blubb")); // Must be set and be absolute.
    setupParams.setRestoreBehavior(qbs::SetupProjectParameters::ResolveOnly); // No restoring.

    const QString qbsRootPath = QDir::cleanPath(QCoreApplication::applicationDirPath()
                                                + QLatin1String("/../"));
    SettingsPtr settings = qbsSettings();
    setupParams.setSearchPaths(qbs::Preferences(settings.data()).searchPaths(qbsRootPath));
    setupParams.setPluginPaths(qbs::Preferences(settings.data()).pluginPaths(qbsRootPath));
    QVariantMap buildConfig;
    buildConfig.insert(QLatin1String("qbs.profile"), QLatin1String("qbs_autotests"));
    buildConfig.insert(QLatin1String("qbs.buildVariant"), QLatin1String("debug"));
    setupParams.setBuildConfiguration(buildConfig);
    setupParams.expandBuildConfiguration(settings.data());
    return setupParams;
}

QTEST_MAIN(TestApi)
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
//      https://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 "bindings/java/com/google/iree/native/instance_wrapper.h"

#include <mutex>

#include "iree/base/flags.h"
#include "iree/hal/drivers/init.h"
#include "iree/modules/hal/hal_module.h"
#include "iree/modules/strings/strings_module.h"
#include "iree/modules/tensorlist/native_module.h"

namespace iree {
namespace java {

namespace {

void SetupVm() {
  // TODO(jennik): Pass flags through from java and us iree_flags_parse.
  // This checked version will abort()/exit() and that's... not great.
  char binname[] = "libiree.so";
  char* argv[] = {binname};
  char** aargv = argv;
  int argc = 1;
  iree_flags_parse_checked(&argc, &aargv);

  IREE_CHECK_OK(iree_hal_register_all_available_drivers());
  IREE_CHECK_OK(iree_vm_register_builtin_types());
  IREE_CHECK_OK(iree_hal_module_register_types());
  IREE_CHECK_OK(iree_tensorlist_module_register_types());
  IREE_CHECK_OK(iree_strings_module_register_types());
}

}  // namespace

Status InstanceWrapper::Create() {
  static std::once_flag setup_vm_once;
  std::call_once(setup_vm_once, [] { SetupVm(); });

  return iree_vm_instance_create(iree_allocator_system(), &instance_);
}

iree_vm_instance_t* InstanceWrapper::instance() const { return instance_; }

InstanceWrapper::~InstanceWrapper() { iree_vm_instance_release(instance_); }

}  // namespace java
}  // namespace iree
<commit_msg>Only register VMLA driver in bindings/java/.<commit_after>// Copyright 2020 Google LLC
//
// 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
//
//      https://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 "bindings/java/com/google/iree/native/instance_wrapper.h"

#include <mutex>

#include "iree/base/flags.h"
#include "iree/hal/vmla/registration/driver_module.h"
#include "iree/modules/hal/hal_module.h"
#include "iree/modules/strings/strings_module.h"
#include "iree/modules/tensorlist/native_module.h"

namespace iree {
namespace java {

namespace {

void SetupVm() {
  // TODO(jennik): Pass flags through from java and us iree_flags_parse.
  // This checked version will abort()/exit() and that's... not great.
  char binname[] = "libiree.so";
  char* argv[] = {binname};
  char** aargv = argv;
  int argc = 1;
  iree_flags_parse_checked(&argc, &aargv);

  // TODO(jennik): register all available drivers
  IREE_CHECK_OK(iree_hal_vmla_driver_module_register());
  IREE_CHECK_OK(iree_vm_register_builtin_types());
  IREE_CHECK_OK(iree_hal_module_register_types());
  IREE_CHECK_OK(iree_tensorlist_module_register_types());
  IREE_CHECK_OK(iree_strings_module_register_types());
}

}  // namespace

Status InstanceWrapper::Create() {
  static std::once_flag setup_vm_once;
  std::call_once(setup_vm_once, [] { SetupVm(); });

  return iree_vm_instance_create(iree_allocator_system(), &instance_);
}

iree_vm_instance_t* InstanceWrapper::instance() const { return instance_; }

InstanceWrapper::~InstanceWrapper() { iree_vm_instance_release(instance_); }

}  // namespace java
}  // namespace iree
<|endoftext|>


<commit_before>#include <atomic>
#include <iostream>

#include "test.hpp"

#include "caf/all.hpp"

using std::cout;
using std::endl;
using namespace caf;

namespace {
std::atomic<long> s_testees;
} // namespace <anonymous>

class testee : public event_based_actor {
 public:
  testee() {
    ++s_testees;
  }

  ~testee();

  behavior make_behavior() {
    return {
      others() >> [=] {
        return last_dequeued();
      }
    };
  }
};

testee::~testee() {
  // avoid weak-vtables warning
  --s_testees;
}

template <class ExitMsgType>
behavior tester(event_based_actor* self, const actor& aut) {
  CAF_CHECKPOINT();
  if (std::is_same<ExitMsgType, exit_msg>::value) {
    self->trap_exit(true);
    self->link_to(aut);
  } else {
    self->monitor(aut);
  }
  CAF_CHECKPOINT();
  anon_send_exit(aut, exit_reason::user_shutdown);
  CAF_CHECKPOINT();
  return {
    [self](const ExitMsgType&) {
      // must be still alive at this point
      CAF_CHECK_EQUAL(s_testees.load(), 1);
      // testee might be still running its cleanup code in
      // another worker thread; by waiting some milliseconds, we make sure
      // testee had enough time to return control to the scheduler
      // which in turn destroys it by dropping the last remaining reference
      self->delayed_send(self, std::chrono::milliseconds(30),
                         check_atom::value);
    },
    [self](check_atom) {
      // make sure dude's dtor has been called
      CAF_CHECK_EQUAL(s_testees.load(), 0);
      self->quit();
    }
  };
}

template <spawn_options O1, spawn_options O2>
void run() {
  CAF_PRINT("run test using links");
  spawn<O1>(tester<exit_msg>, spawn<testee, O2>());
  await_all_actors_done();
  CAF_PRINT("run test using monitors");
  spawn<O1>(tester<down_msg>, spawn<testee, O2>());
  await_all_actors_done();
}

void test_actor_lifetime() {
  CAF_PRINT("run<no_spawn_options, no_spawn_options>");
  run<no_spawn_options, no_spawn_options>();
  CAF_PRINT("run<detached, no_spawn_options>");
  run<detached, no_spawn_options>();
  CAF_PRINT("run<no_spawn_options, detached>");
  run<no_spawn_options, detached>();
  CAF_PRINT("run<detached, detached>");
  run<detached, detached>();
}

int main() {
  CAF_TEST(test_actor_lifetime);
  test_actor_lifetime();
  CAF_CHECK_EQUAL(s_testees.load(), 0);
  return CAF_TEST_RESULT();
}
<commit_msg>Test whether `on_exit()` is called correctly<commit_after>#include <atomic>
#include <iostream>

#include "test.hpp"

#include "caf/all.hpp"

using std::cout;
using std::endl;
using namespace caf;

namespace {
std::atomic<long> s_testees;
std::atomic<long> s_pending_on_exits;
} // namespace <anonymous>

class testee : public event_based_actor {
 public:
  testee();
  ~testee();
  void on_exit();
  behavior make_behavior() override;
};

testee::testee() {
  ++s_testees;
  ++s_pending_on_exits;
}

testee::~testee() {
  // avoid weak-vtables warning
  --s_testees;
}

void testee::on_exit() {
  --s_pending_on_exits;
}

behavior testee::make_behavior() {
  return {
    others() >> [=] {
      return last_dequeued();
    }
  };
}

template <class ExitMsgType>
behavior tester(event_based_actor* self, const actor& aut) {
  CAF_CHECKPOINT();
  if (std::is_same<ExitMsgType, exit_msg>::value) {
    self->trap_exit(true);
    self->link_to(aut);
  } else {
    self->monitor(aut);
  }
  CAF_CHECKPOINT();
  anon_send_exit(aut, exit_reason::user_shutdown);
  CAF_CHECKPOINT();
  return {
    [self](const ExitMsgType& msg) {
      // must be still alive at this point
      CAF_CHECK_EQUAL(s_testees.load(), 1);
      CAF_CHECK_EQUAL(msg.reason, exit_reason::user_shutdown);
      CAF_CHECK_EQUAL(self->last_dequeued().vals()->get_reference_count(), 1);
      CAF_CHECK(&msg == self->last_dequeued().at(0));
      // testee might be still running its cleanup code in
      // another worker thread; by waiting some milliseconds, we make sure
      // testee had enough time to return control to the scheduler
      // which in turn destroys it by dropping the last remaining reference
      self->delayed_send(self, std::chrono::milliseconds(30),
                         check_atom::value);
    },
    [self](check_atom) {
      // make sure aut's dtor and on_exit() have been called
      CAF_CHECK_EQUAL(s_testees.load(), 0);
      CAF_CHECK_EQUAL(s_pending_on_exits.load(), 0);
      self->quit();
    }
  };
}

#define BREAK_ON_ERROR() if (CAF_TEST_RESULT() > 0) return

template <spawn_options O1, spawn_options O2>
void run() {
  CAF_PRINT("run test using links");
  spawn<O1>(tester<exit_msg>, spawn<testee, O2>());
  await_all_actors_done();
  BREAK_ON_ERROR();
  CAF_PRINT("run test using monitors");
  spawn<O1>(tester<down_msg>, spawn<testee, O2>());
  await_all_actors_done();
}

void test_actor_lifetime() {
  CAF_PRINT("run<no_spawn_options, no_spawn_options>");
  run<no_spawn_options, no_spawn_options>();
  BREAK_ON_ERROR();
  CAF_PRINT("run<detached, no_spawn_options>");
  run<detached, no_spawn_options>();
  BREAK_ON_ERROR();
  CAF_PRINT("run<no_spawn_options, detached>");
  run<no_spawn_options, detached>();
  BREAK_ON_ERROR();
  CAF_PRINT("run<detached, detached>");
  run<detached, detached>();
}

int main() {
  CAF_TEST(test_actor_lifetime);
  test_actor_lifetime();
  return CAF_TEST_RESULT();
}
<|endoftext|>


<commit_before>#include <QDebug>
#include <cdio/cdio.h>
#include "CdromManager.h"
#include "Player.h"

#define INTERFACE "com.EnnaMediaServer.Cdrom"
#define SIGNAL_NAME_INSERT "inserted"
#define SIGNAL_NAME_REMOVE "removed"

/* ---------------------------------------------------------
 *                          UTILS
 * --------------------------------------------------------- */
static inline int cddb_sum(int n)
{
    int result = 0;
    while (n > 0)
    {
        result += n % 10;
        n /= 10;
    }
    return result;
}

void CdromManager::getAvailableCdroms(QVector<EMSCdrom> *cdromsOut)
{
    cdromsOut->clear();
    mutex.lock();
    for (unsigned int i=0; i<cdroms.size(); i++)
    {
        cdromsOut->append(cdroms.at(i));
    }
    mutex.unlock();
}

bool CdromManager::getCdrom(QString device, EMSCdrom *cdrom)
{
    bool found = false;

    mutex.lock();
    for (unsigned int i=0; i<cdroms.size(); i++)
    {
        if (cdroms.at(i).device == device)
        {
            *cdrom = cdroms.at(i);
            found = true;
            break;
        }
    }
    mutex.unlock();

    return found;
}

/* ---------------------------------------------------------
 *                    INSERT/REMOVE HOOK
 * --------------------------------------------------------- */
void CdromManager::dbusMessageInsert(QString message)
{
    EMSCdrom newCD;
    unsigned int sum = 0;

    /* Check the new CD is not already in the list */
    if (getCdrom(message, &newCD))
    {
        qCritical() << "CD already in the list of current CDROM.";
        return;
    }

    /* The given message only contain the device name */
    newCD.device = message;
    qDebug() << "New CDROM inserted : " << newCD.device;

    /* Open the CD and get track data (number, duration, ...) */
    CdIo_t *cdrom = cdio_open(newCD.device.toStdString().c_str(), DRIVER_UNKNOWN);
    if (!cdrom)
    {
        qCritical() << "Unable to open device " << newCD.device;
        return;
    }

    /* Check that the inserted cdrom is a CD-DA */
    discmode_t mode = cdio_get_discmode(cdrom);
    if (mode != CDIO_DISC_MODE_CD_DA)
    {
        /* Ignore not valid CDROM */
        qDebug() << "Inserted disk is not an audio CD " << QString("(%1)").arg(mode);
        return;
    }

    /* Get size of the disck */
    track_t trackNumber = cdio_get_num_tracks(cdrom);
    if (trackNumber <= 0)
    {
        qCritical() << "Unable to read CDROM TOC";
    }
    qDebug() << "Found " << QString("%1").arg(trackNumber) << " tracks in " << newCD.device;

    /* Retrieve each track data */
    for (track_t i=1; i<=trackNumber; ++i)
    {
        EMSTrack track;
        track.filename = newCD.device;
        track.name = QString("Track %1").arg(i);
        track.type = TRACK_TYPE_CDROM;
        track.position = i;
        lsn_t begin = cdio_get_track_lsn(cdrom, i);
        lsn_t end = cdio_get_track_last_lsn(cdrom, i);
        track.duration = (end - begin + 1) / CDIO_CD_FRAMES_PER_SEC; /* One sector = 1/75s */
        newCD.tracks.append(track);
        /* For disc id computation */
        lba_t lba = cdio_lsn_to_lba (begin);
        sum += cddb_sum(lba / CDIO_CD_FRAMES_PER_SEC);
    }

    /* Compute the discid
     * Code copied from libcdio/example/discid.c
     */
    unsigned start_sec = cdio_get_track_lba(cdrom, 1) / CDIO_CD_FRAMES_PER_SEC;
    unsigned leadout_sec = cdio_get_track_lba(cdrom, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC;
    unsigned total = leadout_sec - start_sec;
    unsigned id = ((sum % 0xff) << 24 | total << 8 | trackNumber);

    newCD.disc_id = QString().sprintf("%08X %d", id, trackNumber);
    for (track_t i=1; i <= trackNumber; ++i)
    {
        lba_t lba = cdio_get_track_lba(cdrom, i);
        newCD.disc_id += QString().sprintf(" %ld", (long) lba);
    }
    newCD.disc_id += QString().sprintf(" %ld", (long) cdio_get_track_lba(cdrom, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC);
    cdio_destroy(cdrom);

    qDebug() << "Computed DISCID is " << newCD.disc_id;

    /* Add the new CDROM in the list and emit signal to warn listeners */
    mutex.lock();
    cdroms.append(newCD);
    mutex.unlock();
    emit cdromInserted(newCD);

    /* TODO:
     * If network, ask Gracenote additional data (using disc_id)
     * Fill CDrom tracks structure with additional data
     * Emit signal with new CDrom struct
     */
}

void CdromManager::dbusMessageRemove(QString message)
{
    bool found = false;
    EMSCdrom cdrom;
    mutex.lock();
    for (unsigned int i=0; i<cdroms.size(); i++)
    {
        if (cdroms.at(i).device == message)
        {
            cdrom = cdroms.at(i);
            cdroms.removeAt(i);
            found = true;
            break;
        }
    }
    mutex.unlock();

    if (!found)
    {
        /* Ejected CDROM is not found */
        return;
    }

    qDebug() << "CDROM ejected : " << cdrom.device;

    /* Remove played CDROM from the current playlist */
    EMSPlaylist playlist = Player::instance()->getCurentPlaylist();
    for (unsigned int i=0; i<playlist.tracks.size(); i++)
    {
        EMSTrack track = playlist.tracks.at(i);
        if (track.type == TRACK_TYPE_CDROM && track.filename == cdrom.device)
        {
            Player::instance()->removeTrack(track);
        }
    }

    emit cdromEjected(cdrom);
}

/* ---------------------------------------------------------
 *                  START/STOP CDROM MANAGER
 * --------------------------------------------------------- */

CdromManager* CdromManager::_instance = 0;

CdromManager::CdromManager(QObject *parent) : QObject(parent), bus(QDBusConnection::systemBus())
{
    cdio_init();
}

CdromManager::~CdromManager()
{

}

bool CdromManager::startMonitor()
{
    if (!bus.isConnected())
    {
        qCritical() << "Could not connect to session bus ! No CDROM management.";
        return false;
    }
    else
    {
        bus.connect(QString(), QString(), INTERFACE , SIGNAL_NAME_INSERT, this, SLOT(dbusMessageInsert(QString)));
        bus.connect(QString(), QString(), INTERFACE , SIGNAL_NAME_REMOVE, this, SLOT(dbusMessageRemove(QString)));
    }

    /* In case of CDROM already present, trigger actions using udevadm
     * Note: EMS must be launched with root rights or be able to trigger action using udev.
     */
    QProcess cmd;
    cmd.execute(QString("/bin/udevadm"), QString("trigger --action=change --sysname-match=sr[0-9]").split(' '));

    return true;
}

void CdromManager::stopMonitor()
{
    if (bus.isConnected())
    {
        bus.disconnect(QString(), QString(), INTERFACE , SIGNAL_NAME_INSERT, this, SLOT(dbusMessageInsert(QString)));
        bus.disconnect(QString(), QString(), INTERFACE , SIGNAL_NAME_REMOVE, this, SLOT(dbusMessageRemove(QString)));
    }
}
<commit_msg>ems: fix a bug, the CdromManager added the leadout track<commit_after>#include <QDebug>
#include <cdio/cdio.h>
#include "CdromManager.h"
#include "Player.h"

#define INTERFACE "com.EnnaMediaServer.Cdrom"
#define SIGNAL_NAME_INSERT "inserted"
#define SIGNAL_NAME_REMOVE "removed"

/* ---------------------------------------------------------
 *                          UTILS
 * --------------------------------------------------------- */
static inline int cddb_sum(int n)
{
    int result = 0;
    while (n > 0)
    {
        result += n % 10;
        n /= 10;
    }
    return result;
}

void CdromManager::getAvailableCdroms(QVector<EMSCdrom> *cdromsOut)
{
    cdromsOut->clear();
    mutex.lock();
    for (unsigned int i=0; i<cdroms.size(); i++)
    {
        cdromsOut->append(cdroms.at(i));
    }
    mutex.unlock();
}

bool CdromManager::getCdrom(QString device, EMSCdrom *cdrom)
{
    bool found = false;

    mutex.lock();
    for (unsigned int i=0; i<cdroms.size(); i++)
    {
        if (cdroms.at(i).device == device)
        {
            *cdrom = cdroms.at(i);
            found = true;
            break;
        }
    }
    mutex.unlock();

    return found;
}

/* ---------------------------------------------------------
 *                    INSERT/REMOVE HOOK
 * --------------------------------------------------------- */
void CdromManager::dbusMessageInsert(QString message)
{
    EMSCdrom newCD;
    unsigned int sum = 0;

    /* Check the new CD is not already in the list */
    if (getCdrom(message, &newCD))
    {
        qCritical() << "CD already in the list of current CDROM.";
        return;
    }

    /* The given message only contain the device name */
    newCD.device = message;
    qDebug() << "New CDROM inserted : " << newCD.device;

    /* Open the CD and get track data (number, duration, ...) */
    CdIo_t *cdrom = cdio_open(newCD.device.toStdString().c_str(), DRIVER_UNKNOWN);
    if (!cdrom)
    {
        qCritical() << "Unable to open device " << newCD.device;
        return;
    }

    /* Check that the inserted cdrom is a CD-DA */
    discmode_t mode = cdio_get_discmode(cdrom);
    if (mode != CDIO_DISC_MODE_CD_DA)
    {
        /* Ignore not valid CDROM */
        qDebug() << "Inserted disk is not an audio CD " << QString("(%1)").arg(mode);
        return;
    }

    /* Get size of the disck */
    track_t trackNumber = cdio_get_num_tracks(cdrom);
    if (trackNumber <= 1)
    {
        qCritical() << "Unable to read CDROM TOC";
    }
    qDebug() << "Found " << QString("%1").arg(trackNumber-1) << " tracks in " << newCD.device;

    /* Retrieve each track data */
    for (track_t i=1; i<trackNumber; i++)
    {
        EMSTrack track;
        track.filename = newCD.device;
        track.name = QString("Track %1").arg(i);
        track.type = TRACK_TYPE_CDROM;
        track.position = i;
        lsn_t begin = cdio_get_track_lsn(cdrom, i);
        lsn_t end = cdio_get_track_last_lsn(cdrom, i);
        track.duration = (end - begin + 1) / CDIO_CD_FRAMES_PER_SEC; /* One sector = 1/75s */
        newCD.tracks.append(track);
        /* For disc id computation */
        lba_t lba = cdio_lsn_to_lba (begin);
        sum += cddb_sum(lba / CDIO_CD_FRAMES_PER_SEC);
    }

    /* Plus last track which is the lead out */
    sum += cddb_sum(cdio_get_track_lba(cdrom, trackNumber) / CDIO_CD_FRAMES_PER_SEC);

    /* Compute the discid
     * Code copied from libcdio/example/discid.c
     */
    unsigned start_sec = cdio_get_track_lba(cdrom, 1) / CDIO_CD_FRAMES_PER_SEC;
    unsigned leadout_sec = cdio_get_track_lba(cdrom, CDIO_CDROM_LEADOUT_TRACK) / CDIO_CD_FRAMES_PER_SEC;
    unsigned total = leadout_sec - start_sec;
    unsigned id = ((sum % 0xff) << 24 | total << 8 | trackNumber);

    newCD.disc_id = QString().sprintf("%08X %d", id, trackNumber);
    for (track_t i=1; i <=trackNumber; i++)
    {
        lba_t lba = cdio_get_track_lba(cdrom, i);
        newCD.disc_id += QString().sprintf(" %ld", (long) lba);
    }
    newCD.disc_id += QString().sprintf(" %ld", leadout_sec);
    cdio_destroy(cdrom);

    qDebug() << "Computed DISCID is " << newCD.disc_id;

    /* Add the new CDROM in the list and emit signal to warn listeners */
    mutex.lock();
    cdroms.append(newCD);
    mutex.unlock();
    emit cdromInserted(newCD);

    /* TODO:
     * If network, ask Gracenote additional data (using disc_id)
     * Fill CDrom tracks structure with additional data
     * Emit signal with new CDrom struct
     */
}

void CdromManager::dbusMessageRemove(QString message)
{
    bool found = false;
    EMSCdrom cdrom;
    mutex.lock();
    for (unsigned int i=0; i<cdroms.size(); i++)
    {
        if (cdroms.at(i).device == message)
        {
            cdrom = cdroms.at(i);
            cdroms.removeAt(i);
            found = true;
            break;
        }
    }
    mutex.unlock();

    if (!found)
    {
        /* Ejected CDROM is not found */
        return;
    }

    qDebug() << "CDROM ejected : " << cdrom.device;

    /* Remove played CDROM from the current playlist */
    EMSPlaylist playlist = Player::instance()->getCurentPlaylist();
    for (unsigned int i=0; i<playlist.tracks.size(); i++)
    {
        EMSTrack track = playlist.tracks.at(i);
        if (track.type == TRACK_TYPE_CDROM && track.filename == cdrom.device)
        {
            Player::instance()->removeTrack(track);
        }
    }

    emit cdromEjected(cdrom);
}

/* ---------------------------------------------------------
 *                  START/STOP CDROM MANAGER
 * --------------------------------------------------------- */

CdromManager* CdromManager::_instance = 0;

CdromManager::CdromManager(QObject *parent) : QObject(parent), bus(QDBusConnection::systemBus())
{
    cdio_init();
}

CdromManager::~CdromManager()
{

}

bool CdromManager::startMonitor()
{
    if (!bus.isConnected())
    {
        qCritical() << "Could not connect to session bus ! No CDROM management.";
        return false;
    }
    else
    {
        bus.connect(QString(), QString(), INTERFACE , SIGNAL_NAME_INSERT, this, SLOT(dbusMessageInsert(QString)));
        bus.connect(QString(), QString(), INTERFACE , SIGNAL_NAME_REMOVE, this, SLOT(dbusMessageRemove(QString)));
    }

    /* In case of CDROM already present, trigger actions using udevadm
     * Note: EMS must be launched with root rights or be able to trigger action using udev.
     */
    QProcess cmd;
    cmd.execute(QString("/bin/udevadm"), QString("trigger --action=change --sysname-match=sr[0-9]").split(' '));

    return true;
}

void CdromManager::stopMonitor()
{
    if (bus.isConnected())
    {
        bus.disconnect(QString(), QString(), INTERFACE , SIGNAL_NAME_INSERT, this, SLOT(dbusMessageInsert(QString)));
        bus.disconnect(QString(), QString(), INTERFACE , SIGNAL_NAME_REMOVE, this, SLOT(dbusMessageRemove(QString)));
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <e32base.h>

#ifdef Q_OS_SYMBIAN

typedef void TLeavingFunc();

class tst_qmainexceptions : public QObject
{
    Q_OBJECT
public:
    tst_qmainexceptions(){};
    ~tst_qmainexceptions(){};

    void TestSchedulerCatchesError(TLeavingFunc* f, int error);
    void TestSymbianRoundTrip(int leave, int trap);

    bool event(QEvent *event);

public slots:
    void initTestCase();
private slots:
    void trap();
    void cleanupstack();
    void leave();
    void testTranslateBadAlloc();
    void testTranslateBigAlloc();
    void testRoundTrip();
    void testTrap();
    void testPropagation();
    void testDtor1();
    void testDtor2();
    void testNestedExceptions();
};

class CDummy : public CBase
{
public:
    CDummy(){}
    ~CDummy(){}
};

void tst_qmainexceptions::initTestCase()
{
}

void tst_qmainexceptions::trap()
{
    TTrapHandler *th= User::TrapHandler();
    QVERIFY((int)th);
}

void tst_qmainexceptions::cleanupstack()
{
    __UHEAP_MARK;
    //fails if OOM
    CDummy* dummy1 = new (ELeave) CDummy;
    __UHEAP_CHECK(1);
    CleanupStack::PushL(dummy1);
    CleanupStack::PopAndDestroy(dummy1);
    __UHEAP_MARKEND;
}
void tst_qmainexceptions::leave()
{
    __UHEAP_MARK;
    CDummy* dummy1 = 0;
    TRAPD(err,{
        CDummy* csDummy = new (ELeave) CDummy;
        CleanupStack::PushL(csDummy);
        __UHEAP_FAILNEXT(1);
        dummy1 = new (ELeave) CDummy;
        //CleanupStack::PopAndDestroy(csDummy); not executed as previous line throws
    });
    QCOMPARE(err,KErrNoMemory);
    QVERIFY(!((int)dummy1));
    __UHEAP_MARKEND;
}

class CTestActive : public CActive
    {
public:
    CTestActive(TLeavingFunc* aFunc) : CActive(EPriorityStandard), iFunc(aFunc)
        {
        CActiveScheduler::Add(this);
        }
    ~CTestActive()
        {
        Cancel();
        }
    void DoCancel()
        {}
    void Test()
        {
        // complete this AO in a nested scheduler, to make it synchronous
        TRequestStatus* s = &iStatus;
        SetActive();
        User::RequestComplete(s, KErrNone);
        CActiveScheduler::Start();
        }
    void RunL()
        {
        (*iFunc)();
        CActiveScheduler::Stop();   // will only get here if iFunc does not leave
        }
    TInt RunError(TInt aError)
        {
        error = aError;
        CActiveScheduler::Stop();   // will only get here if iFunc leaves
        return KErrNone;
        }
public:
    TLeavingFunc* iFunc;
    int error;
    };

void tst_qmainexceptions::TestSchedulerCatchesError(TLeavingFunc* f, int error)
    {
    CTestActive *act = new(ELeave) CTestActive(f);
    act->Test();
    QCOMPARE(act->error, error);
    delete act;
    }

void ThrowBadAlloc()
{
    throw std::bad_alloc();
}

void TranslateThrowBadAllocL()
{
    QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(ThrowBadAlloc());
}

void tst_qmainexceptions::testTranslateBadAlloc()
{
    // bad_alloc should give KErrNoMemory in an AO
    TestSchedulerCatchesError(&TranslateThrowBadAllocL, KErrNoMemory);
}

void BigAlloc()
{
    int *x = new int[100000000];
    delete [] x;
}

void TranslateBigAllocL()
{
    QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(BigAlloc());
}

void tst_qmainexceptions::testTranslateBigAlloc()
{
    // this test will fail if new does not throw on failure, otherwise should give KErrNoMemory in AO
    TestSchedulerCatchesError(&TranslateBigAllocL, KErrNoMemory);
}

void tst_qmainexceptions::TestSymbianRoundTrip(int leave, int trap)
{
    // check that leave converted to exception, converted to error gives expected error code
    int trapped;
    QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_ERROR(
            trapped,
            QT_TRANSLATE_SYMBIAN_LEAVE_TO_EXCEPTION(
                    User::LeaveIfError(leave)));
    QCOMPARE(trap, trapped);
}

void tst_qmainexceptions::testRoundTrip()
{
    for (int e=-50; e<0; e++)
        TestSymbianRoundTrip(e, e);
    TestSymbianRoundTrip(KErrNone, KErrNone);
    // positive error codes are not errors
    TestSymbianRoundTrip(1, KErrNone);
    TestSymbianRoundTrip(1000000000, KErrNone);
}

void tst_qmainexceptions::testTrap()
{
    // testing qt_translateExceptionToSymbianErrorL
    TRAPD(err, qt_translateExceptionToSymbianErrorL(std::bad_alloc()));
    QCOMPARE(err, KErrNoMemory);
}

bool tst_qmainexceptions::event(QEvent *aEvent)
    {
    if (aEvent->type() == QEvent::User+1)
        throw std::bad_alloc();
    else if (aEvent->type() == QEvent::User+2)
        {
        QEvent event(QEvent::Type(QEvent::User+1));
        QApplication::sendEvent(this, &event);
        }
    return QObject::event(aEvent);
    }

void tst_qmainexceptions::testPropagation()
{
    // test exception thrown from event is propagated back to sender
    QEvent event(QEvent::Type(QEvent::User+1));
    bool caught = false;
    try { QApplication::sendEvent(this, &event); }
    catch (const std::bad_alloc&) { caught = true; }
    QCOMPARE(caught, true);

    // testing nested events propagate back to top level sender
    caught = false;
    QEvent event2(QEvent::Type(QEvent::User+2));
    try { QApplication::sendEvent(this, &event2); }
    catch (const std::bad_alloc&) { caught = true; }
    QCOMPARE(caught, true);
}

void tst_qmainexceptions::testDtor1()
{
    // destructors work on exception
    int i = 0;
    struct SAutoInc {
        SAutoInc(int& aI) : i(aI) { ++i; }
        ~SAutoInc() { --i; }
        int &i;
    } ai(i);
    QCOMPARE(i, 1);
    try {
        SAutoInc ai2(i);
        QCOMPARE(i, 2);
        throw std::bad_alloc();
        QFAIL("should not get here");
    } catch (const std::bad_alloc&) {
        QCOMPARE(i, 1);
    }
    QCOMPARE(i, 1);
}

void tst_qmainexceptions::testDtor2()
{
    // memory is cleaned up correctly on exception
    // this crashes with winscw compiler build < 481
    __UHEAP_MARK;
    try {
        QString str("abc");
        str += "def";
        throw std::bad_alloc();
        QFAIL("should not get here");
    } catch (const std::bad_alloc&) { }
    __UHEAP_MARKEND;
}

void tst_qmainexceptions::testNestedExceptions()
{
    // throwing exceptions while handling exceptions
    struct Oops {
        Oops* next;
        Oops(int level) : next(level > 0 ? new Oops(level-1) : 0) {}
        ~Oops() {
            try { throw std::bad_alloc(); }
            catch (const std::exception&) {delete next;}
        }
    };
    try {
        Oops oops(5);
        throw std::bad_alloc();
    }
    catch (const std::exception&) {}
}

QTEST_MAIN(tst_qmainexceptions)
#include "tst_qmainexceptions.moc"
#else
QTEST_NOOP_MAIN
#endif
<commit_msg>fixed code formatting to Qt style<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <e32base.h>

#ifdef Q_OS_SYMBIAN

typedef void TLeavingFunc();

class tst_qmainexceptions : public QObject
{
    Q_OBJECT
public:
    tst_qmainexceptions(){};
    ~tst_qmainexceptions(){};

    void TestSchedulerCatchesError(TLeavingFunc* f, int error);
    void TestSymbianRoundTrip(int leave, int trap);

    bool event(QEvent *event);

public slots:
    void initTestCase();
private slots:
    void trap();
    void cleanupstack();
    void leave();
    void testTranslateBadAlloc();
    void testTranslateBigAlloc();
    void testRoundTrip();
    void testTrap();
    void testPropagation();
    void testDtor1();
    void testDtor2();
    void testNestedExceptions();
};

class CDummy : public CBase
{
public:
    CDummy(){}
    ~CDummy(){}
};

void tst_qmainexceptions::initTestCase()
{
}

void tst_qmainexceptions::trap()
{
    TTrapHandler *th= User::TrapHandler();
    QVERIFY((int)th);
}

void tst_qmainexceptions::cleanupstack()
{
    __UHEAP_MARK;
    //fails if OOM
    CDummy* dummy1 = new (ELeave) CDummy;
    __UHEAP_CHECK(1);
    CleanupStack::PushL(dummy1);
    CleanupStack::PopAndDestroy(dummy1);
    __UHEAP_MARKEND;
}

void tst_qmainexceptions::leave()
{
    __UHEAP_MARK;
    CDummy* dummy1 = 0;
    TRAPD(err,{
        CDummy* csDummy = new (ELeave) CDummy;
        CleanupStack::PushL(csDummy);
        __UHEAP_FAILNEXT(1);
        dummy1 = new (ELeave) CDummy;
        //CleanupStack::PopAndDestroy(csDummy); not executed as previous line throws
    });
    QCOMPARE(err,KErrNoMemory);
    QVERIFY(!((int)dummy1));
    __UHEAP_MARKEND;
}

class CTestActive : public CActive
{
public:
    CTestActive(TLeavingFunc* aFunc) : CActive(EPriorityStandard), iFunc(aFunc)
    {
        CActiveScheduler::Add(this);
    }
    ~CTestActive()
    {
        Cancel();
    }
    void DoCancel() {}
    void Test()
    {
        // complete this AO in a nested scheduler, to make it synchronous
        TRequestStatus* s = &iStatus;
        SetActive();
        User::RequestComplete(s, KErrNone);
        CActiveScheduler::Start();
    }
    void RunL()
    {
        (*iFunc)();
        CActiveScheduler::Stop();   // will only get here if iFunc does not leave
    }
    TInt RunError(TInt aError)
    {
        error = aError;
        CActiveScheduler::Stop();   // will only get here if iFunc leaves
        return KErrNone;
    }
public:
    TLeavingFunc* iFunc;
    int error;
};

void tst_qmainexceptions::TestSchedulerCatchesError(TLeavingFunc* f, int error)
{
    CTestActive *act = new(ELeave) CTestActive(f);
    act->Test();
    QCOMPARE(act->error, error);
    delete act;
}

void ThrowBadAlloc()
{
    throw std::bad_alloc();
}

void TranslateThrowBadAllocL()
{
    QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(ThrowBadAlloc());
}

void tst_qmainexceptions::testTranslateBadAlloc()
{
    // bad_alloc should give KErrNoMemory in an AO
    TestSchedulerCatchesError(&TranslateThrowBadAllocL, KErrNoMemory);
}

void BigAlloc()
{
    int *x = new int[100000000];
    delete [] x;
}

void TranslateBigAllocL()
{
    QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(BigAlloc());
}

void tst_qmainexceptions::testTranslateBigAlloc()
{
    // this test will fail if new does not throw on failure, otherwise should give KErrNoMemory in AO
    TestSchedulerCatchesError(&TranslateBigAllocL, KErrNoMemory);
}

void tst_qmainexceptions::TestSymbianRoundTrip(int leave, int trap)
{
    // check that leave converted to exception, converted to error gives expected error code
    int trapped;
    QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_ERROR(
        trapped,
        QT_TRANSLATE_SYMBIAN_LEAVE_TO_EXCEPTION(
            User::LeaveIfError(leave)));
    QCOMPARE(trap, trapped);
}

void tst_qmainexceptions::testRoundTrip()
{
    for (int e=-50; e<0; e++)
        TestSymbianRoundTrip(e, e);
    TestSymbianRoundTrip(KErrNone, KErrNone);
    // positive error codes are not errors
    TestSymbianRoundTrip(1, KErrNone);
    TestSymbianRoundTrip(1000000000, KErrNone);
}

void tst_qmainexceptions::testTrap()
{
    // testing qt_translateExceptionToSymbianErrorL
    TRAPD(err, qt_translateExceptionToSymbianErrorL(std::bad_alloc()));
    QCOMPARE(err, KErrNoMemory);
}

bool tst_qmainexceptions::event(QEvent *aEvent)
{
    if (aEvent->type() == QEvent::User+1)
        throw std::bad_alloc();
    else if (aEvent->type() == QEvent::User+2) {
        QEvent event(QEvent::Type(QEvent::User+1));
        QApplication::sendEvent(this, &event);
    }
    return QObject::event(aEvent);
}

void tst_qmainexceptions::testPropagation()
{
    // test exception thrown from event is propagated back to sender
    QEvent event(QEvent::Type(QEvent::User+1));
    bool caught = false;
    try {
        QApplication::sendEvent(this, &event);
    } catch (const std::bad_alloc&) {
        caught = true;
    }
    QCOMPARE(caught, true);

    // testing nested events propagate back to top level sender
    caught = false;
    QEvent event2(QEvent::Type(QEvent::User+2));
    try {
        QApplication::sendEvent(this, &event2);
    } catch (const std::bad_alloc&) {
        caught = true;
    }
    QCOMPARE(caught, true);
}

void tst_qmainexceptions::testDtor1()
{
    // destructors work on exception
    int i = 0;
    struct SAutoInc {
        SAutoInc(int& aI) : i(aI) { ++i; }
        ~SAutoInc() { --i; }
        int &i;
    } ai(i);
    QCOMPARE(i, 1);
    try {
        SAutoInc ai2(i);
        QCOMPARE(i, 2);
        throw std::bad_alloc();
        QFAIL("should not get here");
    } catch (const std::bad_alloc&) {
        QCOMPARE(i, 1);
    }
    QCOMPARE(i, 1);
}

void tst_qmainexceptions::testDtor2()
{
    // memory is cleaned up correctly on exception
    // this crashes with winscw compiler build < 481
    __UHEAP_MARK;
    try {
        QString str("abc");
        str += "def";
        throw std::bad_alloc();
        QFAIL("should not get here");
    } catch (const std::bad_alloc&) { }
    __UHEAP_MARKEND;
}

void tst_qmainexceptions::testNestedExceptions()
{
    // throwing exceptions while handling exceptions
    struct Oops {
        Oops* next;
        Oops(int level) : next(level > 0 ? new Oops(level-1) : 0) {}
        ~Oops() {
            try { throw std::bad_alloc(); }
            catch (const std::exception&) {delete next;}
        }
    };
    try {
        Oops oops(5);
        throw std::bad_alloc();
    }
    catch (const std::exception&) {}
}

QTEST_MAIN(tst_qmainexceptions)
#include "tst_qmainexceptions.moc"
#else
QTEST_NOOP_MAIN
#endif
<|endoftext|>


<commit_before>//
//  TiledVectorLayerTileImageProvider.cpp
//  G3MiOSSDK
//
//  Created by Diego Gomez Deck on 4/30/14.
//
//

#include "TiledVectorLayerTileImageProvider.hpp"
#include "TiledVectorLayer.hpp"
#include "Tile.hpp"
#include "IDownloader.hpp"
#include "TileImageListener.hpp"
#include "TileImageContribution.hpp"
#include "GEOJSONParser.hpp"
#include "GEOObject.hpp"
#include "GEORasterSymbolizer.hpp"
#include "IFactory.hpp"
#include "ICanvas.hpp"
#include "GEORasterProjection.hpp"

TiledVectorLayerTileImageProvider::GEOJSONBufferParser::~GEOJSONBufferParser() {
  _imageAssembler->deletedParser();

  if (_buffer) printf("    ****** (2) Deleting buffer=%p\n", _buffer);
  delete _buffer;
  if (_geoObject) printf("    ****** (2) Deleting geoObject=%p\n", _geoObject);
  delete _geoObject;
#ifdef JAVA_CODE
  super.dispose();
#endif
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::cancel() {
  _imageAssembler = NULL;

//  printf("    ****** (1) Deleting buffer=%p\n", _buffer);
//  delete _buffer;
//  _buffer = NULL;
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::runInBackground(const G3MContext* context) {
  if ((_imageAssembler != NULL) && (_buffer != NULL)) {
    printf("    ****** Parsing buffer=%p\n", _buffer);
    _geoObject = GEOJSONParser::parseJSON(_buffer);
    printf("    ****** Parsed geoObject=%p\n", _geoObject);
  }
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::onPostExecute(const G3MContext* context) {
  if (_imageAssembler != NULL) {
    _imageAssembler->parsedGEOObject(_geoObject);
    _geoObject = NULL; // moves ownership of _geoObject to _imageAssembler
  }
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onDownload(const URL& url,
                                                                                IByteBuffer* buffer,
                                                                                bool expired) {
  _imageAssembler->bufferDownloaded(buffer);
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onError(const URL& url) {
  _imageAssembler->bufferDownloadError(url);
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onCancel(const URL& url) {
  _imageAssembler->bufferDownloadCanceled();
}

TiledVectorLayerTileImageProvider::ImageAssembler::ImageAssembler(TiledVectorLayerTileImageProvider* tileImageProvider,
                                                                  const Tile*                        tile,
                                                                  const TileImageContribution*       contribution,
                                                                  TileImageListener*                 listener,
                                                                  bool                               deleteListener,
                                                                  const Vector2I&                    imageResolution,
                                                                  IDownloader*                       downloader,
                                                                  const IThreadUtils*                threadUtils) :
_tileImageProvider(tileImageProvider),
_tileId(tile->_id),
_tileSector(tile->_sector),
_tileIsMercator(tile->_mercator),
_tileLevel(tile->_level),
_contribution(contribution),
_listener(listener),
_deleteListener(deleteListener),
_imageWidth(imageResolution._x),
_imageHeight(imageResolution._y),
_downloader(downloader),
_threadUtils(threadUtils),
_canceled(false),
_downloadListener(NULL),
_downloadRequestId(-1),
_parser(NULL),
_symbolizer(NULL)
{

}

void TiledVectorLayerTileImageProvider::ImageAssembler::start(const TiledVectorLayer* layer,
                                                              const Tile*             tile,
                                                              long long               tileDownloadPriority,
                                                              bool                    logDownloadActivity) {
  _downloadListener = new GEOJSONBufferDownloadListener(this);

  _symbolizer = layer->symbolizerCopy();

  _downloadRequestId = layer->requestGEOJSONBuffer(tile,
                                                   _downloader,
                                                   tileDownloadPriority,
                                                   logDownloadActivity,
                                                   _downloadListener,
                                                   true /* deleteListener */);

}

TiledVectorLayerTileImageProvider::ImageAssembler::~ImageAssembler() {
  if (_deleteListener) {
    delete _listener;
  }
  TileImageContribution::deleteContribution(_contribution);
  delete _symbolizer;
}

void TiledVectorLayerTileImageProvider::ImageAssembler::cancel() {
  _canceled = true;
  if (_downloadRequestId >= 0) {
    _downloader->cancelRequest(_downloadRequestId);
    _downloadRequestId = -1;
  }
  if (_parser != NULL) {
    _parser->cancel();
  }

#warning TODO call listener cancel
  _listener->imageCreationCanceled(_tileId);
  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloaded(IByteBuffer* buffer) {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  if (!_canceled) {
    _parser = new GEOJSONBufferParser(this, buffer);
    _threadUtils->invokeAsyncTask(_parser,
                                  true);
  }

#warning Diego at work!
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloadError(const URL& url) {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  _listener->imageCreationError(_tileId,
                                "Download error - " + url.getPath());
  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloadCanceled() {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  // do nothing here, the cancel() method already notified the listener
//  _listener->imageCreationCanceled(_tileId);
//  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::parsedGEOObject(GEOObject* geoObject) {
  if (geoObject == NULL) {
    _listener->imageCreationError(_tileId, "GEOJSON parser error");
    if (_deleteListener) {
      delete _listener;
    }
  }
  else {
#warning Diego at work!
    //ILogger::instance()->logInfo("Parsed geojson");

    if (_canceled) {
      printf("    ****** <<CANCELED>> Rasterizing geoObject=%p\n", geoObject);
    }
    else {
      printf("    ****** Rasterizing geoObject=%p\n", geoObject);
    }

    ICanvas* canvas = IFactory::instance()->createCanvas();

    canvas->initialize(_imageWidth, _imageHeight);

    const GEORasterProjection* projection = new GEORasterProjection(_tileSector,
                                                                    _tileIsMercator,
                                                                    _imageWidth,
                                                                    _imageHeight);;
    geoObject->rasterize(_symbolizer,
                         canvas,
                         projection,
                         _tileLevel);

    delete projection;
    delete canvas;

    printf("    ****** (1) Deleting geoObject=%p\n", geoObject);
    delete geoObject;

#warning remove this
    _listener->imageCreationError(_tileId,
                                  "NOT YET IMPLEMENTED");

    TileImageContribution::deleteContribution(_contribution);
    _contribution = NULL;

    _tileImageProvider->requestFinish(_tileId);
  }
}

void TiledVectorLayerTileImageProvider::ImageAssembler::deletedParser() {
  _parser = NULL;
}

const TileImageContribution* TiledVectorLayerTileImageProvider::contribution(const Tile* tile) {
  return _layer->contribution(tile);
}

void TiledVectorLayerTileImageProvider::create(const Tile* tile,
                                               const TileImageContribution* contribution,
                                               const Vector2I& resolution,
                                               long long tileDownloadPriority,
                                               bool logDownloadActivity,
                                               TileImageListener* listener,
                                               bool deleteListener,
                                               FrameTasksExecutor* frameTasksExecutor) {

  ImageAssembler* assembler = new ImageAssembler(this,
                                                 tile,
                                                 contribution,
                                                 listener,
                                                 deleteListener,
                                                 resolution,
                                                 _downloader,
                                                 _threadUtils);

  _assemblers[tile->_id] = assembler;

  assembler->start(_layer,
                   tile,
                   tileDownloadPriority,
                   logDownloadActivity);
}

void TiledVectorLayerTileImageProvider::cancel(const std::string& tileId) {
#ifdef C_CODE
  if (_assemblers.find(tileId) != _assemblers.end()) {
    ImageAssembler* assembler = _assemblers[tileId];

    assembler->cancel();
  }
#endif
#ifdef JAVA_CODE
  final ImageAssembler assembler = _assemblers.get(tileId);
  if (assembler != null) {
    assembler.cancelRequest();
  }
#endif
}

void TiledVectorLayerTileImageProvider::requestFinish(const std::string& tileId) {
#ifdef C_CODE
  if (_assemblers.find(tileId) != _assemblers.end()) {
    ImageAssembler* assembler = _assemblers[tileId];

    delete assembler;

    _assemblers.erase(tileId);
  }
#endif
#ifdef JAVA_CODE
  final ImageAssembler assembler = _assemblers.remove(tileId);
  if (assembler != null) {
    assembler.dispose();
  }
#endif
}
<commit_msg>Tile's image creation refactoring - NOT YET USABLE<commit_after>//
//  TiledVectorLayerTileImageProvider.cpp
//  G3MiOSSDK
//
//  Created by Diego Gomez Deck on 4/30/14.
//
//

#include "TiledVectorLayerTileImageProvider.hpp"
#include "TiledVectorLayer.hpp"
#include "Tile.hpp"
#include "IDownloader.hpp"
#include "TileImageListener.hpp"
#include "TileImageContribution.hpp"
#include "GEOJSONParser.hpp"
#include "GEOObject.hpp"
#include "GEORasterSymbolizer.hpp"
#include "IFactory.hpp"
#include "ICanvas.hpp"
#include "GEORasterProjection.hpp"

TiledVectorLayerTileImageProvider::GEOJSONBufferParser::~GEOJSONBufferParser() {
  _imageAssembler->deletedParser();

  if (_buffer) printf("    ****** (2) Deleting buffer=%p\n", _buffer);
  delete _buffer;
  if (_geoObject) printf("    ****** (2) Deleting geoObject=%p\n", _geoObject);
  delete _geoObject;
#ifdef JAVA_CODE
  super.dispose();
#endif
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::cancel() {
  _imageAssembler = NULL;

//  printf("    ****** (1) Deleting buffer=%p\n", _buffer);
//  delete _buffer;
//  _buffer = NULL;
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::runInBackground(const G3MContext* context) {
  if ((_imageAssembler != NULL) && (_buffer != NULL)) {
    printf("    ****** Parsing buffer=%p\n", _buffer);
    _geoObject = GEOJSONParser::parseJSON(_buffer);
    printf("    ****** Parsed geoObject=%p\n", _geoObject);
  }
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferParser::onPostExecute(const G3MContext* context) {
  if (_imageAssembler != NULL) {
    _imageAssembler->parsedGEOObject(_geoObject);
    _geoObject = NULL; // moves ownership of _geoObject to _imageAssembler
  }
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onDownload(const URL& url,
                                                                                IByteBuffer* buffer,
                                                                                bool expired) {
  _imageAssembler->bufferDownloaded(buffer);
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onError(const URL& url) {
  _imageAssembler->bufferDownloadError(url);
}

void TiledVectorLayerTileImageProvider::GEOJSONBufferDownloadListener::onCancel(const URL& url) {
  _imageAssembler->bufferDownloadCanceled();
}

TiledVectorLayerTileImageProvider::ImageAssembler::ImageAssembler(TiledVectorLayerTileImageProvider* tileImageProvider,
                                                                  const Tile*                        tile,
                                                                  const TileImageContribution*       contribution,
                                                                  TileImageListener*                 listener,
                                                                  bool                               deleteListener,
                                                                  const Vector2I&                    imageResolution,
                                                                  IDownloader*                       downloader,
                                                                  const IThreadUtils*                threadUtils) :
_tileImageProvider(tileImageProvider),
_tileId(tile->_id),
_tileSector(tile->_sector),
_tileIsMercator(tile->_mercator),
_tileLevel(tile->_level),
_contribution(contribution),
_listener(listener),
_deleteListener(deleteListener),
_imageWidth(imageResolution._x),
_imageHeight(imageResolution._y),
_downloader(downloader),
_threadUtils(threadUtils),
_canceled(false),
_downloadListener(NULL),
_downloadRequestId(-1),
_parser(NULL),
_symbolizer(NULL)
{

}

void TiledVectorLayerTileImageProvider::ImageAssembler::start(const TiledVectorLayer* layer,
                                                              const Tile*             tile,
                                                              long long               tileDownloadPriority,
                                                              bool                    logDownloadActivity) {
  _downloadListener = new GEOJSONBufferDownloadListener(this);

  _symbolizer = layer->symbolizerCopy();

  _downloadRequestId = layer->requestGEOJSONBuffer(tile,
                                                   _downloader,
                                                   tileDownloadPriority,
                                                   logDownloadActivity,
                                                   _downloadListener,
                                                   true /* deleteListener */);

}

TiledVectorLayerTileImageProvider::ImageAssembler::~ImageAssembler() {
  if (_deleteListener) {
    delete _listener;
  }
  TileImageContribution::deleteContribution(_contribution);
  delete _symbolizer;
}

void TiledVectorLayerTileImageProvider::ImageAssembler::cancel() {
  _canceled = true;
  if (_downloadRequestId >= 0) {
    _downloader->cancelRequest(_downloadRequestId);
    _downloadRequestId = -1;
  }
  if (_parser != NULL) {
    _parser->cancel();
  }

#warning TODO call listener cancel
  _listener->imageCreationCanceled(_tileId);
  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloaded(IByteBuffer* buffer) {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  if (!_canceled) {
    _parser = new GEOJSONBufferParser(this, buffer);
    _threadUtils->invokeAsyncTask(_parser,
                                  true);
  }

#warning Diego at work!
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloadError(const URL& url) {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  _listener->imageCreationError(_tileId,
                                "Download error - " + url.getPath());
  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::bufferDownloadCanceled() {
  _downloadListener = NULL;
  _downloadRequestId = -1;

  // do nothing here, the cancel() method already notified the listener
//  _listener->imageCreationCanceled(_tileId);
//  _tileImageProvider->requestFinish(_tileId);
}

void TiledVectorLayerTileImageProvider::ImageAssembler::parsedGEOObject(GEOObject* geoObject) {
  if (geoObject == NULL) {
    _listener->imageCreationError(_tileId, "GEOJSON parser error");
    if (_deleteListener) {
      delete _listener;
    }
  }
  else {
#warning Diego at work!
    //ILogger::instance()->logInfo("Parsed geojson");

    if (_canceled) {
      printf("    ****** <<CANCELED>> Rasterizing geoObject=%p\n", geoObject);
    }
    else {
      printf("    ****** Rasterizing geoObject=%p\n", geoObject);
    }

    ICanvas* canvas = IFactory::instance()->createCanvas();

    canvas->initialize(_imageWidth, _imageHeight);

    const GEORasterProjection* projection = new GEORasterProjection(_tileSector,
                                                                    _tileIsMercator,
                                                                    _imageWidth,
                                                                    _imageHeight);;
    geoObject->rasterize(_symbolizer,
                         canvas,
                         projection,
                         _tileLevel);

    delete projection;
    delete canvas;

    printf("    ****** (1) Deleting geoObject=%p\n", geoObject);
    delete geoObject;

#warning remove this
    _listener->imageCreationError(_tileId,
                                  "NOT YET IMPLEMENTED");

    TileImageContribution::deleteContribution(_contribution);
    _contribution = NULL;

    _tileImageProvider->requestFinish(_tileId);
  }
}

void TiledVectorLayerTileImageProvider::ImageAssembler::deletedParser() {
  _parser = NULL;
}

const TileImageContribution* TiledVectorLayerTileImageProvider::contribution(const Tile* tile) {
  return _layer->contribution(tile);
}

void TiledVectorLayerTileImageProvider::create(const Tile* tile,
                                               const TileImageContribution* contribution,
                                               const Vector2I& resolution,
                                               long long tileDownloadPriority,
                                               bool logDownloadActivity,
                                               TileImageListener* listener,
                                               bool deleteListener,
                                               FrameTasksExecutor* frameTasksExecutor) {

  ImageAssembler* assembler = new ImageAssembler(this,
                                                 tile,
                                                 contribution,
                                                 listener,
                                                 deleteListener,
                                                 resolution,
                                                 _downloader,
                                                 _threadUtils);

  _assemblers[tile->_id] = assembler;

  assembler->start(_layer,
                   tile,
                   tileDownloadPriority,
                   logDownloadActivity);
}

void TiledVectorLayerTileImageProvider::cancel(const std::string& tileId) {
#ifdef C_CODE
  if (_assemblers.find(tileId) != _assemblers.end()) {
    ImageAssembler* assembler = _assemblers[tileId];

    assembler->cancel();
  }
#endif
#ifdef JAVA_CODE
  final ImageAssembler assembler = _assemblers.get(tileId);
  if (assembler != null) {
    assembler.cancel();
  }
#endif
}

void TiledVectorLayerTileImageProvider::requestFinish(const std::string& tileId) {
#ifdef C_CODE
  if (_assemblers.find(tileId) != _assemblers.end()) {
    ImageAssembler* assembler = _assemblers[tileId];

    delete assembler;

    _assemblers.erase(tileId);
  }
#endif
#ifdef JAVA_CODE
  final ImageAssembler assembler = _assemblers.remove(tileId);
  if (assembler != null) {
    assembler.dispose();
  }
#endif
}
<|endoftext|>