<commit_before>#include <gst/gst.h>
#include "MediaPipeline.hpp"
#include <WebRtcEndpointImplFactory.hpp>
#include "WebRtcEndpointImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <boost/filesystem.hpp>

#define GST_CAT_DEFAULT kurento_web_rtc_endpoint_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoWebRtcEndpointImpl"

#define FACTORY_NAME "webrtcendpoint"

namespace kurento
{

static const std::string CERTTOOL_TEMPLATE = "autoCerttool.tmpl";
static const std::string CERT_KEY_PEM_FILE = "autoCertkey.pem";

static const uint DEFAULT_STUN_PORT = 0;
static const std::string DEFAULT_STUN_ADDRESS =  "77.72.174.167";

static std::shared_ptr<std::string> pemCertificate;
static std::mutex mutex;
static std::shared_ptr<boost::filesystem::path> temporalDirectory;

static void
remove_certificate (boost::filesystem::path *p)
{
  boost::filesystem::remove_all (*p);
  delete p;
}

static void
create_pem_certificate ()
{
  int ret;
  boost::filesystem::path p = boost::filesystem::unique_path (
                                boost::filesystem::temp_directory_path() / "WebRtcEndpoint_%%%%%%%%" );
  boost::filesystem::create_directories (p);
  temporalDirectory = std::shared_ptr <boost::filesystem::path>
                      (new boost::filesystem::path (p), remove_certificate);

  boost::filesystem::path pemFile = p / CERT_KEY_PEM_FILE;
  std::string pemGenerationCommand =
    "/bin/sh -c \"certtool --generate-privkey --outfile " + pemFile .string()  +
    "\"";

  ret = system (pemGenerationCommand.c_str() );

  if (ret == -1) {
    return;
  }

  boost::filesystem::path templateFile = p / CERTTOOL_TEMPLATE;
  std::string certtoolCommand = "/bin/sh -c \"echo 'organization = kurento' > " +
                                templateFile.string() + " && certtool --generate-self-signed --load-privkey " +
                                pemFile.string() + " --template " + templateFile.string() +  " >> " +
                                pemFile.string() + " 2>/dev/null\"";

  ret = system (certtoolCommand.c_str() );

  if (ret == -1) {
    return;
  }

  pemCertificate = std::shared_ptr <std::string> (new std::string (
                     pemFile.string() ) );
}

static std::shared_ptr<std::string>
getPemCertificate (const boost::property_tree::ptree &conf)
{
  std::unique_lock<std::mutex> lock (mutex);

  if (pemCertificate) {
    return pemCertificate;
  }

  try {
    boost::filesystem::path pem_certificate_file_name (
      conf.get<std::string> ("modules.kurento.WebRtcEndpoint.pemCertificate") );

    if (pem_certificate_file_name.is_relative() ) {
      pem_certificate_file_name = boost::filesystem::path (
                                    conf.get<std::string> ("configPath") ) / pem_certificate_file_name;
    }

    pemCertificate = std::shared_ptr <std::string> (new std::string (
                       pem_certificate_file_name.string() ) );

    return pemCertificate;
  } catch (boost::property_tree::ptree_error &e) {

  }

  create_pem_certificate();

  return pemCertificate;
}

WebRtcEndpointImpl::WebRtcEndpointImpl (const boost::property_tree::ptree &conf,
                                        std::shared_ptr<MediaPipeline>
                                        mediaPipeline) : SdpEndpointImpl (conf,
                                              std::dynamic_pointer_cast<MediaObjectImpl>
                                              (mediaPipeline), FACTORY_NAME)
{
  uint stunPort;
  std::string stunAddress;
  std::string turnURL;

  //set properties
  try {
    stunPort = conf.get<uint> ("modules.WebRtcEndpoint.stunServerPort");
  } catch (boost::property_tree::ptree_error &e) {
    GST_INFO ("Setting default port %d to stun server",
              DEFAULT_STUN_PORT);
    stunPort = DEFAULT_STUN_PORT;
  }

  if (stunPort != 0) {
    try {
      stunAddress =
        conf.get<std::string> ("modules.WebRtcEndpoint.stunServerAddress");
    } catch (boost::property_tree::ptree_error &e) {
      GST_INFO ("Setting default address %s to stun server",
                DEFAULT_STUN_ADDRESS.c_str() );
      stunAddress = DEFAULT_STUN_ADDRESS;
    }

    if (!stunAddress.empty() ) {
      GST_INFO ("stun port %d\n", stunPort );
      g_object_set ( G_OBJECT (element), "stun-server-port",
                     stunPort, NULL);

      GST_INFO ("stun address %s\n", stunAddress.c_str() );
      g_object_set ( G_OBJECT (element), "stun-server",
                     stunAddress.c_str(),
                     NULL);
    }
  }

  try {
    turnURL = conf.get<std::string> ("modules.WebRtcEndpoint.turnURL");
    GST_INFO ("turn info: %s\n", turnURL.c_str() );
    g_object_set ( G_OBJECT (element), "turn-url", turnURL.c_str(),
                   NULL);
  } catch (boost::property_tree::ptree_error &e) {

  }

  g_object_set ( G_OBJECT (element), "certificate-pem-file",
                 getPemCertificate (conf)->c_str(), NULL);
}

MediaObjectImpl *
WebRtcEndpointImplFactory::createObject (const boost::property_tree::ptree
    &conf, std::shared_ptr<MediaPipeline>
    mediaPipeline) const
{
  return new WebRtcEndpointImpl (conf, mediaPipeline);
}

WebRtcEndpointImpl::StaticConstructor WebRtcEndpointImpl::staticConstructor;

WebRtcEndpointImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<commit_msg>WebRtcEndpoint: Perform a correct management of temporal directory<commit_after>#include <gst/gst.h>
#include "MediaPipeline.hpp"
#include <WebRtcEndpointImplFactory.hpp>
#include "WebRtcEndpointImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <boost/filesystem.hpp>

#define GST_CAT_DEFAULT kurento_web_rtc_endpoint_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoWebRtcEndpointImpl"

#define FACTORY_NAME "webrtcendpoint"

namespace kurento
{

static const std::string CERTTOOL_TEMPLATE = "autoCerttool.tmpl";
static const std::string CERT_KEY_PEM_FILE = "autoCertkey.pem";

static const uint DEFAULT_STUN_PORT = 0;
static const std::string DEFAULT_STUN_ADDRESS =  "77.72.174.167";

static std::shared_ptr<std::string> pemCertificate;
static std::mutex mutex;

class TemporalDirectory
{
public:
  ~TemporalDirectory() {
    if (!dir.string ().empty() ) {
      boost::filesystem::remove_all (dir);
    }
  }

  void setDir (boost::filesystem::path &dir) {
    this->dir = dir;
  }
private:
  boost::filesystem::path dir;
};

static TemporalDirectory tmpDir;

static void
create_pem_certificate ()
{
  int ret;
  boost::filesystem::path temporalDirectory = boost::filesystem::unique_path (
        boost::filesystem::temp_directory_path() / "WebRtcEndpoint_%%%%%%%%" );
  boost::filesystem::create_directories (temporalDirectory);
  tmpDir.setDir (temporalDirectory);

  boost::filesystem::path pemFile = temporalDirectory / CERT_KEY_PEM_FILE;
  std::string pemGenerationCommand =
    "/bin/sh -c \"certtool --generate-privkey --outfile " + pemFile .string()  +
    "\"";

  ret = system (pemGenerationCommand.c_str() );

  if (ret == -1) {
    return;
  }

  boost::filesystem::path templateFile = temporalDirectory / CERTTOOL_TEMPLATE;
  std::string certtoolCommand = "/bin/sh -c \"echo 'organization = kurento' > " +
                                templateFile.string() + " && certtool --generate-self-signed --load-privkey " +
                                pemFile.string() + " --template " + templateFile.string() +  " >> " +
                                pemFile.string() + " 2>/dev/null\"";

  ret = system (certtoolCommand.c_str() );

  if (ret == -1) {
    return;
  }

  pemCertificate = std::shared_ptr <std::string> (new std::string (
                     pemFile.string() ) );
}

static std::shared_ptr<std::string>
getPemCertificate (const boost::property_tree::ptree &conf)
{
  std::unique_lock<std::mutex> lock (mutex);

  if (pemCertificate) {
    return pemCertificate;
  }

  try {
    boost::filesystem::path pem_certificate_file_name (
      conf.get<std::string> ("modules.kurento.WebRtcEndpoint.pemCertificate") );

    if (pem_certificate_file_name.is_relative() ) {
      pem_certificate_file_name = boost::filesystem::path (
                                    conf.get<std::string> ("configPath") ) / pem_certificate_file_name;
    }

    pemCertificate = std::shared_ptr <std::string> (new std::string (
                       pem_certificate_file_name.string() ) );

    return pemCertificate;
  } catch (boost::property_tree::ptree_error &e) {

  }

  create_pem_certificate();

  return pemCertificate;
}

WebRtcEndpointImpl::WebRtcEndpointImpl (const boost::property_tree::ptree &conf,
                                        std::shared_ptr<MediaPipeline>
                                        mediaPipeline) : SdpEndpointImpl (conf,
                                              std::dynamic_pointer_cast<MediaObjectImpl>
                                              (mediaPipeline), FACTORY_NAME)
{
  uint stunPort;
  std::string stunAddress;
  std::string turnURL;

  //set properties
  try {
    stunPort = conf.get<uint> ("modules.WebRtcEndpoint.stunServerPort");
  } catch (boost::property_tree::ptree_error &e) {
    GST_INFO ("Setting default port %d to stun server",
              DEFAULT_STUN_PORT);
    stunPort = DEFAULT_STUN_PORT;
  }

  if (stunPort != 0) {
    try {
      stunAddress =
        conf.get<std::string> ("modules.WebRtcEndpoint.stunServerAddress");
    } catch (boost::property_tree::ptree_error &e) {
      GST_INFO ("Setting default address %s to stun server",
                DEFAULT_STUN_ADDRESS.c_str() );
      stunAddress = DEFAULT_STUN_ADDRESS;
    }

    if (!stunAddress.empty() ) {
      GST_INFO ("stun port %d\n", stunPort );
      g_object_set ( G_OBJECT (element), "stun-server-port",
                     stunPort, NULL);

      GST_INFO ("stun address %s\n", stunAddress.c_str() );
      g_object_set ( G_OBJECT (element), "stun-server",
                     stunAddress.c_str(),
                     NULL);
    }
  }

  try {
    turnURL = conf.get<std::string> ("modules.WebRtcEndpoint.turnURL");
    GST_INFO ("turn info: %s\n", turnURL.c_str() );
    g_object_set ( G_OBJECT (element), "turn-url", turnURL.c_str(),
                   NULL);
  } catch (boost::property_tree::ptree_error &e) {

  }

  g_object_set ( G_OBJECT (element), "certificate-pem-file",
                 getPemCertificate (conf)->c_str(), NULL);
}

MediaObjectImpl *
WebRtcEndpointImplFactory::createObject (const boost::property_tree::ptree
    &conf, std::shared_ptr<MediaPipeline>
    mediaPipeline) const
{
  return new WebRtcEndpointImpl (conf, mediaPipeline);
}

WebRtcEndpointImpl::StaticConstructor WebRtcEndpointImpl::staticConstructor;

WebRtcEndpointImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <list>

#include <boost/functional/hash.hpp>

#include <stout/os.hpp>

#include <mesos/appc/spec.hpp>

#include "slave/containerizer/mesos/provisioner/appc/cache.hpp"
#include "slave/containerizer/mesos/provisioner/appc/paths.hpp"

using std::list;
using std::map;
using std::pair;
using std::string;

namespace spec = appc::spec;

namespace mesos {
namespace internal {
namespace slave {
namespace appc {

Try<process::Owned<Cache>> Cache::create(const Path& storeDir)
{
  // TODO(jojy): Should we create a directory if it does not exist ?
  if (!os::exists(storeDir)) {
    return Error(
        "Failed to find store directory '" + stringify(storeDir) + "'");
  }

  return new Cache(storeDir);
}

Cache::Cache(const Path& _storeDir)
  : storeDir(_storeDir) {}

Try<Nothing> Cache::recover()
{
  Try<list<string>> imageDirs = os::ls(paths::getImagesDir(storeDir));
  if (imageDirs.isError()) {
    return Error(
        "Failed to list images under '" +
        paths::getImagesDir(storeDir) + "': " +
        imageDirs.error());
  }

  foreach (const string& imageId, imageDirs.get()) {
    Try<Nothing> adding = add(imageId);
    if (adding.isError()) {
      LOG(WARNING) << "Failed to add image with id '" << imageId
                   << "' to cache: " << adding.error();
      continue;
    }

    LOG(INFO) << "Restored image with id '" << imageId << "'";
  }

  return Nothing();
}

Try<Nothing> Cache::add(const string& imageId)
{
  const Path imageDir(paths::getImagePath(storeDir, imageId));

  Try<string> read = os::read(spec::getImageManifestPath(imageDir));
  if (read.isError()) {
    return Error("Failed to read manifest: " + read.error());
  }

  Try<spec::ImageManifest> manifest = spec::parse(read.get());
  if (manifest.isError()) {
    return Error("Failed to parse manifest: " + manifest.error());
  }

  map<string, string> labels;
  foreach (const spec::ImageManifest::Label& label, manifest.get().labels()) {
    labels.insert({label.name(), label.value()});
  }

  imageIds.put(Key(manifest.get().name(), labels), imageId);

  VLOG(1) << "Added image with id '" << imageId << "' to cache";

  return Nothing();
}

Option<string> Cache::find(const Image::Appc& image) const
{
  // Create a cache key from image.
  Cache::Key key(image);

  if (!imageIds.contains(key)) {
    return None();
  }

  return imageIds.at(key);
}

Cache::Key::Key(const Image::Appc& image)
  : name(image.name())
{
  // Extract labels for easier comparison, this also weeds out duplicates.
  // TODO(xujyan): Detect duplicate labels in image manifest validation
  // and Image::Appc validation.

  // TODO(jojy): Do we need to normalize the labels by adding default labels
  // like os, version and arch if they are missing?
  foreach (const Label& label, image.labels().labels()) {
    labels.insert({label.key(), label.value()});
  }
}

Cache::Key::Key(
    const string& _name,
    const map<string, string>& _labels)
  : name(_name),
    labels(_labels) {}

bool Cache::Key::operator==(const Cache::Key& other) const
{
  if (name != other.name) {
    return false;
  }

  foreachpair (const string& name, const string& value, other.labels) {
    map<string, string>::const_iterator itr = labels.find(name);
    if ((itr == labels.end()) || (labels.at(name) != value)) {
      return false;
    }
  }

  foreachpair (const string& name, const string& value, labels) {
    map<string, string>::const_iterator itr = other.labels.find(name);
    if ((itr == other.labels.end()) || (other.labels.at(name) != value)) {
      return false;
    }
  }

  return true;
}

size_t Cache::KeyHasher::operator()(const Cache::Key& key) const
{
  size_t seed = 0;

  boost::hash_combine(seed, key.name);

  foreachpair (const string& name, const string& value, key.labels) {
    boost::hash_combine(seed, name);
    boost::hash_combine(seed, value);
  }

  return seed;
}

} // namespace appc {
} // namespace slave {
} // namespace internal {
} // namespace mesos {
<commit_msg>Simplified AppC provisioner cache keys hashing.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <list>

#include <boost/functional/hash.hpp>

#include <stout/os.hpp>

#include <mesos/appc/spec.hpp>

#include "slave/containerizer/mesos/provisioner/appc/cache.hpp"
#include "slave/containerizer/mesos/provisioner/appc/paths.hpp"

using std::list;
using std::map;
using std::pair;
using std::string;

namespace spec = appc::spec;

namespace mesos {
namespace internal {
namespace slave {
namespace appc {

Try<process::Owned<Cache>> Cache::create(const Path& storeDir)
{
  // TODO(jojy): Should we create a directory if it does not exist ?
  if (!os::exists(storeDir)) {
    return Error(
        "Failed to find store directory '" + stringify(storeDir) + "'");
  }

  return new Cache(storeDir);
}

Cache::Cache(const Path& _storeDir)
  : storeDir(_storeDir) {}

Try<Nothing> Cache::recover()
{
  Try<list<string>> imageDirs = os::ls(paths::getImagesDir(storeDir));
  if (imageDirs.isError()) {
    return Error(
        "Failed to list images under '" +
        paths::getImagesDir(storeDir) + "': " +
        imageDirs.error());
  }

  foreach (const string& imageId, imageDirs.get()) {
    Try<Nothing> adding = add(imageId);
    if (adding.isError()) {
      LOG(WARNING) << "Failed to add image with id '" << imageId
                   << "' to cache: " << adding.error();
      continue;
    }

    LOG(INFO) << "Restored image with id '" << imageId << "'";
  }

  return Nothing();
}

Try<Nothing> Cache::add(const string& imageId)
{
  const Path imageDir(paths::getImagePath(storeDir, imageId));

  Try<string> read = os::read(spec::getImageManifestPath(imageDir));
  if (read.isError()) {
    return Error("Failed to read manifest: " + read.error());
  }

  Try<spec::ImageManifest> manifest = spec::parse(read.get());
  if (manifest.isError()) {
    return Error("Failed to parse manifest: " + manifest.error());
  }

  map<string, string> labels;
  foreach (const spec::ImageManifest::Label& label, manifest.get().labels()) {
    labels.insert({label.name(), label.value()});
  }

  imageIds.put(Key(manifest.get().name(), labels), imageId);

  VLOG(1) << "Added image with id '" << imageId << "' to cache";

  return Nothing();
}

Option<string> Cache::find(const Image::Appc& image) const
{
  // Create a cache key from image.
  Cache::Key key(image);

  if (!imageIds.contains(key)) {
    return None();
  }

  return imageIds.at(key);
}

Cache::Key::Key(const Image::Appc& image)
  : name(image.name())
{
  // Extract labels for easier comparison, this also weeds out duplicates.
  // TODO(xujyan): Detect duplicate labels in image manifest validation
  // and Image::Appc validation.

  // TODO(jojy): Do we need to normalize the labels by adding default labels
  // like os, version and arch if they are missing?
  foreach (const Label& label, image.labels().labels()) {
    labels.insert({label.key(), label.value()});
  }
}

Cache::Key::Key(
    const string& _name,
    const map<string, string>& _labels)
  : name(_name),
    labels(_labels) {}

bool Cache::Key::operator==(const Cache::Key& other) const
{
  if (name != other.name) {
    return false;
  }

  foreachpair (const string& name, const string& value, other.labels) {
    map<string, string>::const_iterator itr = labels.find(name);
    if ((itr == labels.end()) || (labels.at(name) != value)) {
      return false;
    }
  }

  foreachpair (const string& name, const string& value, labels) {
    map<string, string>::const_iterator itr = other.labels.find(name);
    if ((itr == other.labels.end()) || (other.labels.at(name) != value)) {
      return false;
    }
  }

  return true;
}

size_t Cache::KeyHasher::operator()(const Cache::Key& key) const
{
  size_t seed = 0;

  boost::hash_combine(seed, key.name);
  boost::hash_combine(seed, key.labels);

  return seed;
}

} // namespace appc {
} // namespace slave {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>#include <QtTest/QtTest>

#include "../qtest-platform.h"

#include "archivelistwidget.h"
#include "archivestabwidget.h"

#include "ui_archivestabwidget.h"

#include "TSettings.h"

class TestArchivesTabWidget : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void archivesListWidget();
    void displayArchive();
};

void TestArchivesTabWidget::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    IF_NOT_VISUAL
    {
        // Use a custom message handler to filter out unwanted messages
        orig_message_handler = qInstallMessageHandler(offscreenMessageOutput);
    }

    // Initialization normally done in init_shared.cpp's init_no_app()
    qRegisterMetaType<QVector<File>>("QVector<File>");
}

void TestArchivesTabWidget::cleanupTestCase()
{
    TSettings::destroy();
}

void TestArchivesTabWidget::archivesListWidget()
{
    ArchiveListWidget *alw = new ArchiveListWidget();

    VISUAL_INIT(alw);

    ArchivePtr archive(new Archive);
    archive->setName("archive1");
    ArchivePtr archive2(new Archive);
    archive->setName("backup2");

    alw->addArchive(archive);
    VISUAL_WAIT;

    alw->addArchive(archive2);
    VISUAL_WAIT;

    alw->selectArchive(archive);
    VISUAL_WAIT;

    alw->setFilter("back");
    VISUAL_WAIT;

    alw->inspectArchive(archive2);
    VISUAL_WAIT;

    delete alw;
}

void TestArchivesTabWidget::displayArchive()
{
    ArchivesTabWidget *    archivestabwidget = new ArchivesTabWidget();
    Ui::ArchivesTabWidget *ui                = archivestabwidget->_ui;
    ArchiveListWidget *    alw               = ui->archiveListWidget;

    VISUAL_INIT(archivestabwidget);
    VISUAL_WAIT;

    ArchivePtr archive(new Archive);
    archive->setName("archive1");

    alw->addArchive(archive);
    VISUAL_WAIT;

    archivestabwidget->displayInspectArchive(archive);
    VISUAL_WAIT;

    delete archivestabwidget;
}

QTEST_MAIN(TestArchivesTabWidget)
#include "test-archivestabwidget.moc"
<commit_msg>tests/archivestabwidget: improve names, add date & size<commit_after>#include <QtTest/QtTest>

#include "../qtest-platform.h"

#include "archivelistwidget.h"
#include "archivestabwidget.h"

#include "ui_archivestabwidget.h"

#include "TSettings.h"

class TestArchivesTabWidget : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();

    void archiveListWidget();
    void displayArchive();
};

void TestArchivesTabWidget::initTestCase()
{
    QCoreApplication::setOrganizationName(TEST_NAME);

    IF_NOT_VISUAL
    {
        // Use a custom message handler to filter out unwanted messages
        orig_message_handler = qInstallMessageHandler(offscreenMessageOutput);
    }

    // Initialization normally done in init_shared.cpp's init_no_app()
    qRegisterMetaType<QVector<File>>("QVector<File>");
}

void TestArchivesTabWidget::cleanupTestCase()
{
    TSettings::destroy();
}

void TestArchivesTabWidget::archiveListWidget()
{
    ArchiveListWidget *alw = new ArchiveListWidget();

    VISUAL_INIT(alw);

    ArchivePtr archive(new Archive);
    archive->setName("archive1 pXq");
    archive->setSizeTotal(123000);
    archive->setTimestamp(QDateTime::currentDateTime());

    ArchivePtr archive2(new Archive);
    archive2->setName("backup2");
    archive2->setSizeTotal(4000);
    archive2->setTimestamp(QDateTime::currentDateTime());

    ArchivePtr archive3(new Archive);
    archive3->setName("Job_longname_2019-01-01_02-03-04");
    archive3->setSizeTotal(56);
    archive3->setTimestamp(QDateTime::currentDateTime());
    archive3->setJobRef("logname");

    alw->addArchive(archive);
    VISUAL_WAIT;

    alw->addArchive(archive2);
    VISUAL_WAIT;

    alw->addArchive(archive3);
    VISUAL_WAIT;

    alw->selectArchive(archive);
    VISUAL_WAIT;

    alw->setFilter("back");
    VISUAL_WAIT;

    alw->inspectArchive(archive2);
    VISUAL_WAIT;

    delete alw;
}

void TestArchivesTabWidget::displayArchive()
{
    ArchivesTabWidget *    archivestabwidget = new ArchivesTabWidget();
    Ui::ArchivesTabWidget *ui                = archivestabwidget->_ui;
    ArchiveListWidget *    alw               = ui->archiveListWidget;

    VISUAL_INIT(archivestabwidget);
    VISUAL_WAIT;

    ArchivePtr archive(new Archive);
    archive->setName("archive1");

    alw->addArchive(archive);
    VISUAL_WAIT;

    archivestabwidget->displayInspectArchive(archive);
    VISUAL_WAIT;

    delete archivestabwidget;
}

QTEST_MAIN(TestArchivesTabWidget)
#include "test-archivestabwidget.moc"
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtLocation module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.1, 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgeomappingmanagerengine.h"
#include "qgeotilefetcher.h"
#include "qgeotilefetcher_p.h"
#include "qgeotiledmapreply.h"
#include "qgeotilespec.h"
#include "qgeotiledmapdata_p.h"

#include <QThread>
#include <QNetworkProxy>

QT_BEGIN_NAMESPACE

QGeoTileFetcher::QGeoTileFetcher(QGeoTiledMappingManagerEngine *engine, QObject *parent)
    : QObject(parent),
      d_ptr(new QGeoTileFetcherPrivate(engine))
{
    Q_D(QGeoTileFetcher);
    d->engine_ = engine;
}

QGeoTileFetcher::~QGeoTileFetcher()
{
    Q_D(QGeoTileFetcher);
    delete d;
}

void QGeoTileFetcher::threadStarted()
{
    Q_D(QGeoTileFetcher);

    if (d->stopped_)
        return;

    d->timer_ = new QTimer(this);

    d->timer_->setInterval(0);

    connect(d->timer_,
            SIGNAL(timeout()),
            this,
            SLOT(requestNextTile()));

    d->started_ = true;
    if (!d->queue_.isEmpty())
        d->timer_->start();
}

bool QGeoTileFetcher::init()
{
    return false;
}

void QGeoTileFetcher::threadFinished()
{
    Q_D(QGeoTileFetcher);
    d->stopped_ = true;
    disconnect(d->timer_);
    d->timer_->stop();
    this->deleteLater();
}

void QGeoTileFetcher::updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded,
                                                  const QSet<QGeoTileSpec> &tilesRemoved)
{
    Q_D(QGeoTileFetcher);

    QMutexLocker ml(&d->queueMutex_);

    if (d->stopped_)
        return;

    cancelTileRequests(tilesRemoved);

    d->queue_ += tilesAdded.toList();

    if (!d->queue_.empty())
        d->timer_->start();
}

void QGeoTileFetcher::cancelTileRequests(const QSet<QGeoTileSpec> &tiles)
{
    Q_D(QGeoTileFetcher);

    typedef QSet<QGeoTileSpec>::const_iterator tile_iter;
    tile_iter tile = tiles.constBegin();
    tile_iter end = tiles.constEnd();
    for (; tile != end; ++tile) {
        QGeoTiledMapReply* reply = d->invmap_.value(*tile, 0);
        if (reply) {
            /* when we call abort() it will directly emit finished(), so
             * we must disconnect it first to avoid recursing on the lock */
            disconnect(reply, SIGNAL(finished()),
                       this, SLOT(finished()));
            d->invmap_.remove(*tile);
            reply->abort();
            reply->deleteLater();
        }
        d->queue_.removeAll(*tile);
    }

    if (d->queue_.isEmpty())
        d->timer_->stop();
}

void QGeoTileFetcher::requestNextTile()
{
    Q_D(QGeoTileFetcher);

    QMutexLocker ml(&d->queueMutex_);

    if (d->stopped_)
        return;

    if (d->queue_.isEmpty()) {
        d->timer_->stop();
        return;
    }

    QGeoTileSpec ts = d->queue_.takeFirst();

    QGeoTiledMapReply *reply = getTileImage(ts);

    if (reply->isFinished()) {
        handleReply(reply, ts);
    } else {
        connect(reply,
                SIGNAL(finished()),
                this,
                SLOT(finished()));

        d->invmap_.insert(ts, reply);
    }

    if (d->queue_.isEmpty())
        d->timer_->stop();
}

void QGeoTileFetcher::finished()
{
    Q_D(QGeoTileFetcher);

    QMutexLocker ml(&d->queueMutex_);

    QGeoTiledMapReply *reply = qobject_cast<QGeoTiledMapReply*>(sender());
    if (!reply)
        return;

    QGeoTileSpec spec = reply->tileSpec();

    if (!d->invmap_.contains(spec)) {
        reply->deleteLater();
        return;
    }

    d->invmap_.remove(spec);

    handleReply(reply, spec);
}

void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec)
{
    Q_D(QGeoTileFetcher);

    if (d->stopped_) {
        reply->deleteLater();
        return;
    }

    if (reply->error() == QGeoTiledMapReply::NoError) {
        emit tileFinished(spec, reply->mapImageData(), reply->mapImageFormat());
    } else {
        emit tileError(spec, reply->errorString());
    }

    reply->deleteLater();
}

/*******************************************************************************
*******************************************************************************/

QGeoTileFetcherPrivate::QGeoTileFetcherPrivate(QGeoTiledMappingManagerEngine *engine)
    : started_(false),
      stopped_(false),
      timer_(0),
      engine_(engine) {}

QGeoTileFetcherPrivate::~QGeoTileFetcherPrivate()
{
}

QT_END_NAMESPACE

<commit_msg>Fix for pipelined tile requests receiving incorrect data<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtLocation module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** 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.1, 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.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgeomappingmanagerengine.h"
#include "qgeotilefetcher.h"
#include "qgeotilefetcher_p.h"
#include "qgeotiledmapreply.h"
#include "qgeotilespec.h"
#include "qgeotiledmapdata_p.h"

#include <QThread>
#include <QNetworkProxy>

QT_BEGIN_NAMESPACE

QGeoTileFetcher::QGeoTileFetcher(QGeoTiledMappingManagerEngine *engine, QObject *parent)
    : QObject(parent),
      d_ptr(new QGeoTileFetcherPrivate(engine))
{
    Q_D(QGeoTileFetcher);
    d->engine_ = engine;
}

QGeoTileFetcher::~QGeoTileFetcher()
{
    Q_D(QGeoTileFetcher);
    delete d;
}

void QGeoTileFetcher::threadStarted()
{
    Q_D(QGeoTileFetcher);

    if (d->stopped_)
        return;

    d->timer_ = new QTimer(this);

    d->timer_->setInterval(0);

    connect(d->timer_,
            SIGNAL(timeout()),
            this,
            SLOT(requestNextTile()));

    d->started_ = true;
    if (!d->queue_.isEmpty())
        d->timer_->start();
}

bool QGeoTileFetcher::init()
{
    return false;
}

void QGeoTileFetcher::threadFinished()
{
    Q_D(QGeoTileFetcher);
    d->stopped_ = true;
    disconnect(d->timer_);
    d->timer_->stop();
    this->deleteLater();
}

void QGeoTileFetcher::updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded,
                                                  const QSet<QGeoTileSpec> &tilesRemoved)
{
    Q_D(QGeoTileFetcher);

    QMutexLocker ml(&d->queueMutex_);

    if (d->stopped_)
        return;

    cancelTileRequests(tilesRemoved);

    d->queue_ += tilesAdded.toList();

    if (!d->queue_.empty())
        d->timer_->start();
}

void QGeoTileFetcher::cancelTileRequests(const QSet<QGeoTileSpec> &tiles)
{
    Q_D(QGeoTileFetcher);

    typedef QSet<QGeoTileSpec>::const_iterator tile_iter;
    tile_iter tile = tiles.constBegin();
    tile_iter end = tiles.constEnd();
    for (; tile != end; ++tile) {
        QGeoTiledMapReply* reply = d->invmap_.value(*tile, 0);
        if (reply) {
            d->invmap_.remove(*tile);
            reply->abort();
        }
        d->queue_.removeAll(*tile);
    }

    if (d->queue_.isEmpty())
        d->timer_->stop();
}

void QGeoTileFetcher::requestNextTile()
{
    Q_D(QGeoTileFetcher);

    QMutexLocker ml(&d->queueMutex_);

    if (d->stopped_)
        return;

    if (d->queue_.isEmpty()) {
        d->timer_->stop();
        return;
    }

    QGeoTileSpec ts = d->queue_.takeFirst();

    QGeoTiledMapReply *reply = getTileImage(ts);

    if (reply->isFinished()) {
        handleReply(reply, ts);
    } else {
        connect(reply,
                SIGNAL(finished()),
                this,
                SLOT(finished()),
                Qt::QueuedConnection);

        d->invmap_.insert(ts, reply);
    }

    if (d->queue_.isEmpty())
        d->timer_->stop();
}

void QGeoTileFetcher::finished()
{
    Q_D(QGeoTileFetcher);

    QMutexLocker ml(&d->queueMutex_);

    QGeoTiledMapReply *reply = qobject_cast<QGeoTiledMapReply*>(sender());
    if (!reply)
        return;

    QGeoTileSpec spec = reply->tileSpec();

    if (!d->invmap_.contains(spec)) {
        reply->deleteLater();
        return;
    }

    d->invmap_.remove(spec);

    handleReply(reply, spec);
}

void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec)
{
    Q_D(QGeoTileFetcher);

    if (d->stopped_) {
        reply->deleteLater();
        return;
    }

    if (reply->error() == QGeoTiledMapReply::NoError) {
        emit tileFinished(spec, reply->mapImageData(), reply->mapImageFormat());
    } else {
        emit tileError(spec, reply->errorString());
    }

    reply->deleteLater();
}

/*******************************************************************************
*******************************************************************************/

QGeoTileFetcherPrivate::QGeoTileFetcherPrivate(QGeoTiledMappingManagerEngine *engine)
    : started_(false),
      stopped_(false),
      timer_(0),
      engine_(engine) {}

QGeoTileFetcherPrivate::~QGeoTileFetcherPrivate()
{
}

QT_END_NAMESPACE

<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>

#include <string>
#include <limits>
#include <functional>
#include <pangolin/factory/factory_registry.h>
#include <pangolin/video/video.h>
#include <pangolin/video/video_exception.h>
#include <pangolin/video/iostream_operators.h>

template<typename T>
inline void ExpectExceptionWithMessageFromAction(
    std::function<void()> action,
    const std::string& exceptionMessageBegin
) {
    try
    {
        action();

        FAIL("The action succeeded when it should have failed.");
    }
    catch(const T& ex)
    {
        std::string exceptionMessage = std::string(ex.what());
        std::string exceptionMessageRelevantPortion
            = exceptionMessage.substr(0, exceptionMessageBegin.size());
        REQUIRE(exceptionMessageRelevantPortion.compare(exceptionMessageBegin) == 0);
    }
    catch(...)
    {
        FAIL("Another kind of exception was thrown to the one expected");
    }
}

TEST_CASE("Empty Uri Test")
{
    REQUIRE_THROWS_AS(pangolin::OpenVideo(""), pangolin::VideoException);
}

TEST_CASE("Uri Beginning With Dot Interpreted As Image")
{
    auto testAction = [](){pangolin::OpenVideo(".");};
    ExpectExceptionWithMessageFromAction<std::runtime_error>(testAction,
         "Unsupported image file type");
}

TEST_CASE("Uri Dimension Legal Separator Character")
{

    using char_t = std::string::value_type;
    using char_nl = std::numeric_limits<char_t>;
    for(char_t c = char_nl::min(); c < char_nl::max(); ++c)
    {
        if(c == '\0' || c == '=' || c == ']' || c == ',' || (c >= '0' && c <= '9'))
        {
            continue;
        }

        const int dimWidth = 123, dimHeight = 456;
        const std::string encodedDim = std::to_string(dimWidth) + c
            + std::to_string(dimHeight);
        const std::string fullUri = "abc:[size=" + encodedDim + ",other=value]";
        const pangolin::Uri pangoUri = pangolin::ParseUri(fullUri);

        REQUIRE(pangoUri.params.size() == 2);
        REQUIRE( pangoUri.params[0].first == std::string("size"));
        REQUIRE( pangoUri.params[1].first == std::string("other"));

        const pangolin::ImageDim dim
            = pangoUri.Get<pangolin::ImageDim>("size", pangolin::ImageDim(0,0));
        REQUIRE( dim.x == dimWidth);
        REQUIRE( dim.y == dimHeight);

        const std::string otherValue = pangoUri.Get<std::string>("other", "");
        REQUIRE( otherValue == std::string("value"));

    }
}
<commit_msg>Remove unneeded test erroring on Windows.<commit_after>#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>

#include <string>
#include <limits>
#include <functional>
#include <pangolin/factory/factory_registry.h>
#include <pangolin/video/video.h>
#include <pangolin/video/video_exception.h>
#include <pangolin/video/iostream_operators.h>

template<typename T>
inline void ExpectExceptionWithMessageFromAction(
    std::function<void()> action,
    const std::string& exceptionMessageBegin
) {
    try
    {
        action();

        FAIL("The action succeeded when it should have failed.");
    }
    catch(const T& ex)
    {
        std::string exceptionMessage = std::string(ex.what());
        std::string exceptionMessageRelevantPortion
            = exceptionMessage.substr(0, exceptionMessageBegin.size());
        REQUIRE(exceptionMessageRelevantPortion.compare(exceptionMessageBegin) == 0);
    }
    catch(...)
    {
        FAIL("Another kind of exception was thrown to the one expected");
    }
}

TEST_CASE("Empty Uri Test")
{
    REQUIRE_THROWS_AS(pangolin::OpenVideo(""), pangolin::VideoException);
}

TEST_CASE("Uri Dimension Legal Separator Character")
{

    using char_t = std::string::value_type;
    using char_nl = std::numeric_limits<char_t>;
    for(char_t c = char_nl::min(); c < char_nl::max(); ++c)
    {
        if(c == '\0' || c == '=' || c == ']' || c == ',' || (c >= '0' && c <= '9'))
        {
            continue;
        }

        const int dimWidth = 123, dimHeight = 456;
        const std::string encodedDim = std::to_string(dimWidth) + c
            + std::to_string(dimHeight);
        const std::string fullUri = "abc:[size=" + encodedDim + ",other=value]";
        const pangolin::Uri pangoUri = pangolin::ParseUri(fullUri);

        REQUIRE(pangoUri.params.size() == 2);
        REQUIRE( pangoUri.params[0].first == std::string("size"));
        REQUIRE( pangoUri.params[1].first == std::string("other"));

        const pangolin::ImageDim dim
            = pangoUri.Get<pangolin::ImageDim>("size", pangolin::ImageDim(0,0));
        REQUIRE( dim.x == dimWidth);
        REQUIRE( dim.y == dimHeight);

        const std::string otherValue = pangoUri.Get<std::string>("other", "");
        REQUIRE( otherValue == std::string("value"));

    }
}
<|endoftext|>


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

#include "GrGLProgramBuilder.h"

#include "GrAutoLocaleSetter.h"
#include "GrContext.h"
#include "GrCoordTransform.h"
#include "GrGLProgramBuilder.h"
#include "GrProgramDesc.h"
#include "GrShaderCaps.h"
#include "GrSwizzle.h"
#include "SkAutoMalloc.h"
#include "SkATrace.h"
#include "SkTraceEvent.h"
#include "gl/GrGLGpu.h"
#include "gl/GrGLProgram.h"
#include "gl/builders/GrGLShaderStringBuilder.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLXferProcessor.h"

#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)

GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline,
                                               const GrPrimitiveProcessor& primProc,
                                               GrProgramDesc* desc,
                                               GrGLGpu* gpu) {
    SkASSERT(!pipeline.isBad() && primProc.instantiate(gpu->getContext()->resourceProvider()));

    ATRACE_ANDROID_FRAMEWORK("Shader Compile");
    GrAutoLocaleSetter als("C");

    // create a builder.  This will be handed off to effects so they can use it to add
    // uniforms, varyings, textures, etc
    GrGLProgramBuilder builder(gpu, pipeline, primProc, desc);

    if (gpu->getContext()->getPersistentCache() && gpu->glCaps().programBinarySupport()) {
        sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->keyLength());
        builder.fCached = gpu->getContext()->getPersistentCache()->load(*key);
        // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
        // doing necessary setup in addition to generating the SkSL code. Currently we are only able
        // to skip the SkSL->GLSL step on a cache hit.
    }
    if (!builder.emitAndInstallProcs()) {
        builder.cleanupFragmentProcessors();
        return nullptr;
    }
    return builder.finalize();
}

/////////////////////////////////////////////////////////////////////////////

GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
                                       const GrPipeline& pipeline,
                                       const GrPrimitiveProcessor& primProc,
                                       GrProgramDesc* desc)
    : INHERITED(pipeline, primProc, desc)
    , fGpu(gpu)
    , fVaryingHandler(this)
    , fUniformHandler(this) {
}

const GrCaps* GrGLProgramBuilder::caps() const {
    return fGpu->caps();
}

bool GrGLProgramBuilder::compileAndAttachShaders(const char* glsl,
                                                 int length,
                                                 GrGLuint programId,
                                                 GrGLenum type,
                                                 SkTDArray<GrGLuint>* shaderIds,
                                                 const SkSL::Program::Settings& settings,
                                                 const SkSL::Program::Inputs& inputs) {
    GrGLGpu* gpu = this->gpu();
    GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
                                                   programId,
                                                   type,
                                                   glsl,
                                                   length,
                                                   gpu->stats(),
                                                   settings);
    if (!shaderId) {
        return false;
    }

    *shaderIds->append() = shaderId;
    if (inputs.fFlipY) {
        GrProgramDesc* d = this->desc();
        d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
                                                     this->pipeline().proxy()->origin()));
        d->finalize();
    }

    return true;
}

bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
                                                 GrGLuint programId,
                                                 GrGLenum type,
                                                 SkTDArray<GrGLuint>* shaderIds,
                                                 const SkSL::Program::Settings& settings,
                                                 SkSL::Program::Inputs* outInputs) {
    SkSL::String glsl;
    std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(gpu()->glContext(), type,
                                                 shader.fCompilerStrings.begin(),
                                                 shader.fCompilerStringLengths.begin(),
                                                 shader.fCompilerStrings.count(),
                                                 settings,
                                                 &glsl);
    *outInputs = program->fInputs;
    return this->compileAndAttachShaders(glsl.c_str(),
                                         glsl.size(),
                                         programId,
                                         type,
                                         shaderIds,
                                         settings,
                                         *outInputs);
}

GrGLProgram* GrGLProgramBuilder::finalize() {
    TRACE_EVENT0("skia", TRACE_FUNC);

    // verify we can get a program id
    GrGLuint programID;
    GL_CALL_RET(programID, CreateProgram());
    if (0 == programID) {
        this->cleanupFragmentProcessors();
        return nullptr;
    }

    if (this->gpu()->glCaps().programBinarySupport() &&
        this->gpu()->getContext()->getPersistentCache()) {
        GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
    }

    this->finalizeShaders();

    // compile shaders and bind attributes / uniforms
    const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
    SkSL::Program::Settings settings;
    settings.fCaps = this->gpu()->glCaps().shaderCaps();
    settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
    SkSL::Program::Inputs inputs;
    SkTDArray<GrGLuint> shadersToDelete;
    bool cached = nullptr != fCached.get();
    if (cached) {
        this->bindProgramResourceLocations(programID);
        // cache hit, just hand the binary to GL
        const uint8_t* bytes = fCached->bytes();
        size_t offset = 0;
        memcpy(&inputs, bytes + offset, sizeof(inputs));
        offset += sizeof(inputs);
        if (inputs.fRTHeight) {
            this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
        }
        int binaryFormat;
        memcpy(&binaryFormat, bytes + offset, sizeof(binaryFormat));
        offset += sizeof(binaryFormat);
        GL_CALL(ProgramBinary(programID, binaryFormat, (void*) (bytes + offset),
                              fCached->size() - offset));
    } else {
        // cache miss, compile shaders
        if (fFS.fForceHighPrecision) {
            settings.fForceHighPrecision = true;
        }
        SkSL::String glsl;
        std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
                                                         GR_GL_FRAGMENT_SHADER,
                                                         fFS.fCompilerStrings.begin(),
                                                         fFS.fCompilerStringLengths.begin(),
                                                         fFS.fCompilerStrings.count(),
                                                         settings,
                                                         &glsl);
        inputs = fs->fInputs;
        if (inputs.fRTHeight) {
            this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
        }
        if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                           GR_GL_FRAGMENT_SHADER, &shadersToDelete, settings,
                                           inputs)) {
            this->cleanupProgram(programID, shadersToDelete);
            return nullptr;
        }

        std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
                                                         GR_GL_VERTEX_SHADER,
                                                         fVS.fCompilerStrings.begin(),
                                                         fVS.fCompilerStringLengths.begin(),
                                                         fVS.fCompilerStrings.count(),
                                                         settings,
                                                         &glsl);
        if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                           GR_GL_VERTEX_SHADER, &shadersToDelete, settings,
                                           inputs)) {
            this->cleanupProgram(programID, shadersToDelete);
            return nullptr;
        }

        // NVPR actually requires a vertex shader to compile
        bool useNvpr = primProc.isPathRendering();
        if (!useNvpr) {
            int vaCount = primProc.numAttribs();
            for (int i = 0; i < vaCount; i++) {
                GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
            }
        }

        if (primProc.willUseGeoShader()) {
            std::unique_ptr<SkSL::Program> gs;
            gs = GrSkSLtoGLSL(gpu()->glContext(),
                              GR_GL_GEOMETRY_SHADER,
                              fGS.fCompilerStrings.begin(),
                              fGS.fCompilerStringLengths.begin(),
                              fGS.fCompilerStrings.count(),
                              settings,
                              &glsl);
            if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                               GR_GL_GEOMETRY_SHADER, &shadersToDelete, settings,
                                               inputs)) {
                this->cleanupProgram(programID, shadersToDelete);
                return nullptr;
            }

        }
        this->bindProgramResourceLocations(programID);

        GL_CALL(LinkProgram(programID));
    }
    // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
    bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
#ifdef SK_DEBUG
    checkLinked = true;
#endif
    if (checkLinked) {
        if (!this->checkLinkStatus(programID)) {
            SkDebugf("VS:\n");
            GrGLPrintShader(fGpu->glContext(), GR_GL_VERTEX_SHADER, fVS.fCompilerStrings.begin(),
                            fVS.fCompilerStringLengths.begin(), fVS.fCompilerStrings.count(),
                            settings);
            if (primProc.willUseGeoShader()) {
                SkDebugf("\nGS:\n");
                GrGLPrintShader(fGpu->glContext(), GR_GL_GEOMETRY_SHADER,
                                fGS.fCompilerStrings.begin(), fGS.fCompilerStringLengths.begin(),
                                fGS.fCompilerStrings.count(), settings);
            }
            SkDebugf("\nFS:\n");
            GrGLPrintShader(fGpu->glContext(), GR_GL_FRAGMENT_SHADER, fFS.fCompilerStrings.begin(),
                            fFS.fCompilerStringLengths.begin(), fFS.fCompilerStrings.count(),
                            settings);
            SkDEBUGFAIL("");
            return nullptr;
        }
    }
    this->resolveProgramResourceLocations(programID);

    this->cleanupShaders(shadersToDelete);
    if (!cached && this->gpu()->getContext()->getPersistentCache() &&
        fGpu->glCaps().programBinarySupport()) {
        // store shader in cache
        sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
        GrGLsizei length = 0;
        GrGLenum binaryFormat;
        GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
        std::unique_ptr<char> binary(new char[length]);
        GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
        size_t dataLength = sizeof(inputs) + sizeof(binaryFormat) + length;
        std::unique_ptr<uint8_t> data((uint8_t*) malloc(dataLength));
        size_t offset = 0;
        memcpy(data.get() + offset, &inputs, sizeof(inputs));
        offset += sizeof(inputs);
        memcpy(data.get() + offset, &binaryFormat, sizeof(binaryFormat));
        offset += sizeof(binaryFormat);
        memcpy(data.get() + offset, binary.get(), length);
        this->gpu()->getContext()->getPersistentCache()->store(*key,
                                                               *SkData::MakeWithoutCopy(data.get(),
                                                                                dataLength));
    }
    return this->createProgram(programID);
}

void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
    fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());

    const GrGLCaps& caps = this->gpu()->glCaps();
    if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
        GL_CALL(BindFragDataLocation(programID, 0,
                                     GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
    }
    if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
        GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
                                  GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
    }

    // handle NVPR separable varyings
    if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
        !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
        return;
    }
    int count = fVaryingHandler.fPathProcVaryingInfos.count();
    for (int i = 0; i < count; ++i) {
        GL_CALL(BindFragmentInputLocation(programID, i,
                                       fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
        fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
    }
}

bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
    GrGLint linked = GR_GL_INIT_ZERO;
    GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
    if (!linked) {
        SkDebugf("Program linking failed.\n");
        GrGLint infoLen = GR_GL_INIT_ZERO;
        GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
        SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
        if (infoLen > 0) {
            // retrieve length even though we don't need it to workaround
            // bug in chrome cmd buffer param validation.
            GrGLsizei length = GR_GL_INIT_ZERO;
            GL_CALL(GetProgramInfoLog(programID,
                                      infoLen+1,
                                      &length,
                                      (char*)log.get()));
            SkDebugf("%s", (char*)log.get());
        }
        GL_CALL(DeleteProgram(programID));
        programID = 0;
    }
    return SkToBool(linked);
}

void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
    fUniformHandler.getUniformLocations(programID, fGpu->glCaps());

    // handle NVPR separable varyings
    if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
        fGpu->glPathRendering()->shouldBindFragmentInputs()) {
        return;
    }
    int count = fVaryingHandler.fPathProcVaryingInfos.count();
    for (int i = 0; i < count; ++i) {
        GrGLint location;
        GL_CALL_RET(location, GetProgramResourceLocation(
                                       programID,
                                       GR_GL_FRAGMENT_INPUT,
                                       fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
        fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
    }
}

void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
    GL_CALL(DeleteProgram(programID));
    this->cleanupShaders(shaderIDs);
    this->cleanupFragmentProcessors();
}
void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
    for (int i = 0; i < shaderIDs.count(); ++i) {
      GL_CALL(DeleteShader(shaderIDs[i]));
    }
}

GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
    return new GrGLProgram(fGpu,
                           *this->desc(),
                           fUniformHandles,
                           programID,
                           fUniformHandler.fUniforms,
                           fUniformHandler.fSamplers,
                           fUniformHandler.fTexelBuffers,
                           fVaryingHandler.fPathProcVaryingInfos,
                           std::move(fGeometryProcessor),
                           std::move(fXferProcessor),
                           fFragmentProcessors);
}
<commit_msg>shader cache now ignores shaders with a length of 0<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrGLProgramBuilder.h"

#include "GrAutoLocaleSetter.h"
#include "GrContext.h"
#include "GrCoordTransform.h"
#include "GrGLProgramBuilder.h"
#include "GrProgramDesc.h"
#include "GrShaderCaps.h"
#include "GrSwizzle.h"
#include "SkAutoMalloc.h"
#include "SkATrace.h"
#include "SkTraceEvent.h"
#include "gl/GrGLGpu.h"
#include "gl/GrGLProgram.h"
#include "gl/builders/GrGLShaderStringBuilder.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLXferProcessor.h"

#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)

GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrPipeline& pipeline,
                                               const GrPrimitiveProcessor& primProc,
                                               GrProgramDesc* desc,
                                               GrGLGpu* gpu) {
    SkASSERT(!pipeline.isBad() && primProc.instantiate(gpu->getContext()->resourceProvider()));

    ATRACE_ANDROID_FRAMEWORK("Shader Compile");
    GrAutoLocaleSetter als("C");

    // create a builder.  This will be handed off to effects so they can use it to add
    // uniforms, varyings, textures, etc
    GrGLProgramBuilder builder(gpu, pipeline, primProc, desc);

    if (gpu->getContext()->getPersistentCache() && gpu->glCaps().programBinarySupport()) {
        sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->keyLength());
        builder.fCached = gpu->getContext()->getPersistentCache()->load(*key);
        // the eventual end goal is to completely skip emitAndInstallProcs on a cache hit, but it's
        // doing necessary setup in addition to generating the SkSL code. Currently we are only able
        // to skip the SkSL->GLSL step on a cache hit.
    }
    if (!builder.emitAndInstallProcs()) {
        builder.cleanupFragmentProcessors();
        return nullptr;
    }
    return builder.finalize();
}

/////////////////////////////////////////////////////////////////////////////

GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu,
                                       const GrPipeline& pipeline,
                                       const GrPrimitiveProcessor& primProc,
                                       GrProgramDesc* desc)
    : INHERITED(pipeline, primProc, desc)
    , fGpu(gpu)
    , fVaryingHandler(this)
    , fUniformHandler(this) {
}

const GrCaps* GrGLProgramBuilder::caps() const {
    return fGpu->caps();
}

bool GrGLProgramBuilder::compileAndAttachShaders(const char* glsl,
                                                 int length,
                                                 GrGLuint programId,
                                                 GrGLenum type,
                                                 SkTDArray<GrGLuint>* shaderIds,
                                                 const SkSL::Program::Settings& settings,
                                                 const SkSL::Program::Inputs& inputs) {
    GrGLGpu* gpu = this->gpu();
    GrGLuint shaderId = GrGLCompileAndAttachShader(gpu->glContext(),
                                                   programId,
                                                   type,
                                                   glsl,
                                                   length,
                                                   gpu->stats(),
                                                   settings);
    if (!shaderId) {
        return false;
    }

    *shaderIds->append() = shaderId;
    if (inputs.fFlipY) {
        GrProgramDesc* d = this->desc();
        d->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
                                                     this->pipeline().proxy()->origin()));
        d->finalize();
    }

    return true;
}

bool GrGLProgramBuilder::compileAndAttachShaders(GrGLSLShaderBuilder& shader,
                                                 GrGLuint programId,
                                                 GrGLenum type,
                                                 SkTDArray<GrGLuint>* shaderIds,
                                                 const SkSL::Program::Settings& settings,
                                                 SkSL::Program::Inputs* outInputs) {
    SkSL::String glsl;
    std::unique_ptr<SkSL::Program> program = GrSkSLtoGLSL(gpu()->glContext(), type,
                                                 shader.fCompilerStrings.begin(),
                                                 shader.fCompilerStringLengths.begin(),
                                                 shader.fCompilerStrings.count(),
                                                 settings,
                                                 &glsl);
    *outInputs = program->fInputs;
    return this->compileAndAttachShaders(glsl.c_str(),
                                         glsl.size(),
                                         programId,
                                         type,
                                         shaderIds,
                                         settings,
                                         *outInputs);
}

GrGLProgram* GrGLProgramBuilder::finalize() {
    TRACE_EVENT0("skia", TRACE_FUNC);

    // verify we can get a program id
    GrGLuint programID;
    GL_CALL_RET(programID, CreateProgram());
    if (0 == programID) {
        this->cleanupFragmentProcessors();
        return nullptr;
    }

    if (this->gpu()->glCaps().programBinarySupport() &&
        this->gpu()->getContext()->getPersistentCache()) {
        GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
    }

    this->finalizeShaders();

    // compile shaders and bind attributes / uniforms
    const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
    SkSL::Program::Settings settings;
    settings.fCaps = this->gpu()->glCaps().shaderCaps();
    settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
    SkSL::Program::Inputs inputs;
    SkTDArray<GrGLuint> shadersToDelete;
    bool cached = nullptr != fCached.get();
    if (cached) {
        this->bindProgramResourceLocations(programID);
        // cache hit, just hand the binary to GL
        const uint8_t* bytes = fCached->bytes();
        size_t offset = 0;
        memcpy(&inputs, bytes + offset, sizeof(inputs));
        offset += sizeof(inputs);
        if (inputs.fRTHeight) {
            this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
        }
        int binaryFormat;
        memcpy(&binaryFormat, bytes + offset, sizeof(binaryFormat));
        offset += sizeof(binaryFormat);
        GL_CALL(ProgramBinary(programID, binaryFormat, (void*) (bytes + offset),
                              fCached->size() - offset));
    } else {
        // cache miss, compile shaders
        if (fFS.fForceHighPrecision) {
            settings.fForceHighPrecision = true;
        }
        SkSL::String glsl;
        std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
                                                         GR_GL_FRAGMENT_SHADER,
                                                         fFS.fCompilerStrings.begin(),
                                                         fFS.fCompilerStringLengths.begin(),
                                                         fFS.fCompilerStrings.count(),
                                                         settings,
                                                         &glsl);
        inputs = fs->fInputs;
        if (inputs.fRTHeight) {
            this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
        }
        if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                           GR_GL_FRAGMENT_SHADER, &shadersToDelete, settings,
                                           inputs)) {
            this->cleanupProgram(programID, shadersToDelete);
            return nullptr;
        }

        std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
                                                         GR_GL_VERTEX_SHADER,
                                                         fVS.fCompilerStrings.begin(),
                                                         fVS.fCompilerStringLengths.begin(),
                                                         fVS.fCompilerStrings.count(),
                                                         settings,
                                                         &glsl);
        if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                           GR_GL_VERTEX_SHADER, &shadersToDelete, settings,
                                           inputs)) {
            this->cleanupProgram(programID, shadersToDelete);
            return nullptr;
        }

        // NVPR actually requires a vertex shader to compile
        bool useNvpr = primProc.isPathRendering();
        if (!useNvpr) {
            int vaCount = primProc.numAttribs();
            for (int i = 0; i < vaCount; i++) {
                GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
            }
        }

        if (primProc.willUseGeoShader()) {
            std::unique_ptr<SkSL::Program> gs;
            gs = GrSkSLtoGLSL(gpu()->glContext(),
                              GR_GL_GEOMETRY_SHADER,
                              fGS.fCompilerStrings.begin(),
                              fGS.fCompilerStringLengths.begin(),
                              fGS.fCompilerStrings.count(),
                              settings,
                              &glsl);
            if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                               GR_GL_GEOMETRY_SHADER, &shadersToDelete, settings,
                                               inputs)) {
                this->cleanupProgram(programID, shadersToDelete);
                return nullptr;
            }

        }
        this->bindProgramResourceLocations(programID);

        GL_CALL(LinkProgram(programID));
    }
    // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
    bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
#ifdef SK_DEBUG
    checkLinked = true;
#endif
    if (checkLinked) {
        if (!this->checkLinkStatus(programID)) {
            SkDebugf("VS:\n");
            GrGLPrintShader(fGpu->glContext(), GR_GL_VERTEX_SHADER, fVS.fCompilerStrings.begin(),
                            fVS.fCompilerStringLengths.begin(), fVS.fCompilerStrings.count(),
                            settings);
            if (primProc.willUseGeoShader()) {
                SkDebugf("\nGS:\n");
                GrGLPrintShader(fGpu->glContext(), GR_GL_GEOMETRY_SHADER,
                                fGS.fCompilerStrings.begin(), fGS.fCompilerStringLengths.begin(),
                                fGS.fCompilerStrings.count(), settings);
            }
            SkDebugf("\nFS:\n");
            GrGLPrintShader(fGpu->glContext(), GR_GL_FRAGMENT_SHADER, fFS.fCompilerStrings.begin(),
                            fFS.fCompilerStringLengths.begin(), fFS.fCompilerStrings.count(),
                            settings);
            SkDEBUGFAIL("");
            return nullptr;
        }
    }
    this->resolveProgramResourceLocations(programID);

    this->cleanupShaders(shadersToDelete);
    if (!cached && this->gpu()->getContext()->getPersistentCache() &&
        fGpu->glCaps().programBinarySupport()) {
        GrGLsizei length = 0;
        GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
        if (length > 0) {
            // store shader in cache
            sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
            GrGLenum binaryFormat;
            std::unique_ptr<char> binary(new char[length]);
            GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
            size_t dataLength = sizeof(inputs) + sizeof(binaryFormat) + length;
            std::unique_ptr<uint8_t> data((uint8_t*) malloc(dataLength));
            size_t offset = 0;
            memcpy(data.get() + offset, &inputs, sizeof(inputs));
            offset += sizeof(inputs);
            memcpy(data.get() + offset, &binaryFormat, sizeof(binaryFormat));
            offset += sizeof(binaryFormat);
            memcpy(data.get() + offset, binary.get(), length);
            this->gpu()->getContext()->getPersistentCache()->store(*key,
                                                  *SkData::MakeWithoutCopy(data.get(), dataLength));
        }
    }
    return this->createProgram(programID);
}

void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
    fUniformHandler.bindUniformLocations(programID, fGpu->glCaps());

    const GrGLCaps& caps = this->gpu()->glCaps();
    if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
        GL_CALL(BindFragDataLocation(programID, 0,
                                     GrGLSLFragmentShaderBuilder::DeclaredColorOutputName()));
    }
    if (fFS.hasSecondaryOutput() && caps.shaderCaps()->mustDeclareFragmentShaderOutput()) {
        GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
                                  GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
    }

    // handle NVPR separable varyings
    if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
        !fGpu->glPathRendering()->shouldBindFragmentInputs()) {
        return;
    }
    int count = fVaryingHandler.fPathProcVaryingInfos.count();
    for (int i = 0; i < count; ++i) {
        GL_CALL(BindFragmentInputLocation(programID, i,
                                       fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
        fVaryingHandler.fPathProcVaryingInfos[i].fLocation = i;
    }
}

bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
    GrGLint linked = GR_GL_INIT_ZERO;
    GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
    if (!linked) {
        SkDebugf("Program linking failed.\n");
        GrGLint infoLen = GR_GL_INIT_ZERO;
        GL_CALL(GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
        SkAutoMalloc log(sizeof(char)*(infoLen+1));  // outside if for debugger
        if (infoLen > 0) {
            // retrieve length even though we don't need it to workaround
            // bug in chrome cmd buffer param validation.
            GrGLsizei length = GR_GL_INIT_ZERO;
            GL_CALL(GetProgramInfoLog(programID,
                                      infoLen+1,
                                      &length,
                                      (char*)log.get()));
            SkDebugf("%s", (char*)log.get());
        }
        GL_CALL(DeleteProgram(programID));
        programID = 0;
    }
    return SkToBool(linked);
}

void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID) {
    fUniformHandler.getUniformLocations(programID, fGpu->glCaps());

    // handle NVPR separable varyings
    if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
        fGpu->glPathRendering()->shouldBindFragmentInputs()) {
        return;
    }
    int count = fVaryingHandler.fPathProcVaryingInfos.count();
    for (int i = 0; i < count; ++i) {
        GrGLint location;
        GL_CALL_RET(location, GetProgramResourceLocation(
                                       programID,
                                       GR_GL_FRAGMENT_INPUT,
                                       fVaryingHandler.fPathProcVaryingInfos[i].fVariable.c_str()));
        fVaryingHandler.fPathProcVaryingInfos[i].fLocation = location;
    }
}

void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
    GL_CALL(DeleteProgram(programID));
    this->cleanupShaders(shaderIDs);
    this->cleanupFragmentProcessors();
}
void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
    for (int i = 0; i < shaderIDs.count(); ++i) {
      GL_CALL(DeleteShader(shaderIDs[i]));
    }
}

GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
    return new GrGLProgram(fGpu,
                           *this->desc(),
                           fUniformHandles,
                           programID,
                           fUniformHandler.fUniforms,
                           fUniformHandler.fSamplers,
                           fUniformHandler.fTexelBuffers,
                           fVaryingHandler.fPathProcVaryingInfos,
                           std::move(fGeometryProcessor),
                           std::move(fXferProcessor),
                           fFragmentProcessors);
}
<|endoftext|>


<commit_before>/* endpoint.cc
   Mathieu Stefani, 22 janvier 2016

   Implementation of the http endpoint
*/

#include <pistache/config.h>
#include <pistache/endpoint.h>
#include <pistache/tcp.h>
#include <pistache/peer.h>

namespace Pistache {
namespace Http {

Endpoint::Options::Options()
    : threads_(1)
    , threadsName_("")
    , flags_()
    , backlog_(Const::MaxBacklog)
    , maxRequestSize_(Const::DefaultMaxRequestSize)
    , maxResponseSize_(Const::DefaultMaxResponseSize)
{ }

Endpoint::Options&
Endpoint::Options::threads(int val) {
    threads_ = val;
    return *this;
}

Endpoint::Options&
Endpoint::Options::threadsName(const char* val) {
    strncpy(threadsName_, val, 15);
    threadsName_[15] = '\0';
    return *this;
}

Endpoint::Options&
Endpoint::Options::flags(Flags<Tcp::Options> flags) {
    flags_ = flags;
    return *this;
}

Endpoint::Options&
Endpoint::Options::backlog(int val) {
    backlog_ = val;
    return *this;
}

Endpoint::Options&
Endpoint::Options::maxRequestSize(size_t val) {
    maxRequestSize_ = val;
    return *this;
}

Endpoint::Options&
Endpoint::Options::maxPayload(size_t val) {
    return maxRequestSize(val);
}

Endpoint::Options&
Endpoint::Options::maxResponseSize(size_t val) {
    maxResponseSize_ = val;
    return *this;
}

Endpoint::Endpoint()
{ }

Endpoint::Endpoint(const Address& addr)
    : listener(addr)
{ }

void
Endpoint::init(const Endpoint::Options& options) {
    listener.init(options.threads_,  options.flags_, options.threadsName_);
    ArrayStreamBuf<char>::maxSize = options.maxRequestSize_;
    DynamicStreamBuf::maxSize = options.maxResponseSize_;
}

void
Endpoint::setHandler(const std::shared_ptr<Handler>& handler) {
    handler_ = handler;
}

void
Endpoint::bind() {
    listener.bind();
}

void
Endpoint::bind(const Address& addr) {
    listener.bind(addr);
}

void
Endpoint::serve()
{
    serveImpl(&Tcp::Listener::run);
}

void
Endpoint::serveThreaded()
{
    serveImpl(&Tcp::Listener::runThreaded);
}

void
Endpoint::shutdown()
{
    listener.shutdown();
}

void
Endpoint::useSSL(std::string cert, std::string key, bool use_compression)
{
#ifndef PISTACHE_USE_SSL
    (void)cert;
    (void)key;
    (void)use_compression;
    throw std::runtime_error("Pistache is not compiled with SSL support.");
#else
    listener.setupSSL(cert, key, use_compression);
#endif /* PISTACHE_USE_SSL */
}

void
Endpoint::useSSLAuth(std::string ca_file, std::string ca_path, int (*cb)(int, void *))
{
#ifndef PISTACHE_USE_SSL
    (void)ca_file;
    (void)ca_path;
    (void)cb;
    throw std::runtime_error("Pistache is not compiled with SSL support.");
#else
    listener.setupSSLAuth(ca_file, ca_path, cb);
#endif /* PISTACHE_USE_SSL */

}

Async::Promise<Tcp::Listener::Load>
Endpoint::requestLoad(const Tcp::Listener::Load& old) {
    return listener.requestLoad(old);
}

Endpoint::Options
Endpoint::options() {
    return Options();
}

} // namespace Http
} // namespace Pistache
<commit_msg>Update endpoint.cc<commit_after>/* endpoint.cc
   Mathieu Stefani, 22 janvier 2016

   Implementation of the http endpoint
*/

#include <pistache/config.h>
#include <pistache/endpoint.h>
#include <pistache/tcp.h>
#include <pistache/peer.h>

namespace Pistache {
namespace Http {

Endpoint::Options::Options()
    : threads_(1)
    , threadsName_()
    , flags_()
    , backlog_(Const::MaxBacklog)
    , maxRequestSize_(Const::DefaultMaxRequestSize)
    , maxResponseSize_(Const::DefaultMaxResponseSize)
{ }

Endpoint::Options&
Endpoint::Options::threads(int val) {
    threads_ = val;
    return *this;
}

Endpoint::Options&
Endpoint::Options::threadsName(const char* val) {
    strncpy(threadsName_, val, 15);
    threadsName_[15] = '\0';
    return *this;
}

Endpoint::Options&
Endpoint::Options::flags(Flags<Tcp::Options> flags) {
    flags_ = flags;
    return *this;
}

Endpoint::Options&
Endpoint::Options::backlog(int val) {
    backlog_ = val;
    return *this;
}

Endpoint::Options&
Endpoint::Options::maxRequestSize(size_t val) {
    maxRequestSize_ = val;
    return *this;
}

Endpoint::Options&
Endpoint::Options::maxPayload(size_t val) {
    return maxRequestSize(val);
}

Endpoint::Options&
Endpoint::Options::maxResponseSize(size_t val) {
    maxResponseSize_ = val;
    return *this;
}

Endpoint::Endpoint()
{ }

Endpoint::Endpoint(const Address& addr)
    : listener(addr)
{ }

void
Endpoint::init(const Endpoint::Options& options) {
    listener.init(options.threads_,  options.flags_, options.threadsName_);
    ArrayStreamBuf<char>::maxSize = options.maxRequestSize_;
    DynamicStreamBuf::maxSize = options.maxResponseSize_;
}

void
Endpoint::setHandler(const std::shared_ptr<Handler>& handler) {
    handler_ = handler;
}

void
Endpoint::bind() {
    listener.bind();
}

void
Endpoint::bind(const Address& addr) {
    listener.bind(addr);
}

void
Endpoint::serve()
{
    serveImpl(&Tcp::Listener::run);
}

void
Endpoint::serveThreaded()
{
    serveImpl(&Tcp::Listener::runThreaded);
}

void
Endpoint::shutdown()
{
    listener.shutdown();
}

void
Endpoint::useSSL(std::string cert, std::string key, bool use_compression)
{
#ifndef PISTACHE_USE_SSL
    (void)cert;
    (void)key;
    (void)use_compression;
    throw std::runtime_error("Pistache is not compiled with SSL support.");
#else
    listener.setupSSL(cert, key, use_compression);
#endif /* PISTACHE_USE_SSL */
}

void
Endpoint::useSSLAuth(std::string ca_file, std::string ca_path, int (*cb)(int, void *))
{
#ifndef PISTACHE_USE_SSL
    (void)ca_file;
    (void)ca_path;
    (void)cb;
    throw std::runtime_error("Pistache is not compiled with SSL support.");
#else
    listener.setupSSLAuth(ca_file, ca_path, cb);
#endif /* PISTACHE_USE_SSL */

}

Async::Promise<Tcp::Listener::Load>
Endpoint::requestLoad(const Tcp::Listener::Load& old) {
    return listener.requestLoad(old);
}

Endpoint::Options
Endpoint::options() {
    return Options();
}

} // namespace Http
} // namespace Pistache
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
// #include <glog/logging.h>

int main( int argc, char *argv[] ) {
    testing::InitGoogleTest( &argc, argv );
    // google::InitGoogleLogging(argv[0]);
    // testing::AddGlobalTestEnvironment( new LoggingEnvironment );
    // LOG(INFO) << "in main";
    return RUN_ALL_TESTS( );
}
<commit_msg>ignore: added comment<commit_after>#include "gtest/gtest.h"
// #include "global_env.hpp"

int main( int argc, char *argv[] ) {
    testing::InitGoogleTest( &argc, argv );
    // google::InitGoogleLogging(argv[0]);
    // testing::AddGlobalTestEnvironment( new GlobalEnvironment );
    // LOG(INFO) << "in main";
    return RUN_ALL_TESTS( );
}
<|endoftext|>


<commit_before>
#include "global.h"

#define WIN_WIDTH 1024
#define WIN_HEIGHT 768

class Fixme : public n0::IEventListener
{
public:
	Fixme() {}
	~Fixme() {}
	bool OnEvent(n0::n0Event *evt)
	{
		return false;
	}
	bool OnMouseEvent(n0::n0Event *_evt)
	{
		n0_ASSERT(Hash("TargetClick") == _evt->m_type, "Events are not appearing as they should (OnMouseEvent)");
		n0::SMouseEvent * pEvt = (n0::SMouseEvent *)_evt;
		n0::SMouseEventData * pEvtData = (n0::SMouseEventData *)pEvt->pData;
		printf("Mouse Click at %d,%d\n",pEvtData->x, pEvtData->y);
		return true;
	}
	bool OnKeyEvent(n0::n0Event *_evt)
	{
		n0_ASSERT(Hash("theE") == _evt->m_type, "Events are not appearing as they should (OnKeyEvent)");

		printf("E Pressed \n");
		return true;
	}

};

int main()
{

	int bitDepth = 24;
	int screenW = WIN_WIDTH;
	int screenH = WIN_HEIGHT;
	n0::windows::InitSystem(NULL,screenW,screenH);

	n0::SetFrameRate(30);
	Fixme *evtListener = new Fixme();
	n0::n0Texture * pTex = n0::n0TextureManager::GetInstance()->GenerateTexture(1,256,256);
	n0::n0InputEvents::GetInstance()->RegisterInputEvent(n0::SMouseEvent::kEvent_LeftMBDown,0,"TargetClick",NULL);
	n0::n0InputEvents::GetInstance()->RegisterInputEvent(n0::SKeyEvent::kEvent_KeyDown,'E',"theE",NULL);
	n0::n0InputEvents::GetInstance()->RegisterEventListener(Hash("TargetClick"),evtListener,&Fixme::OnMouseEvent,Hash("fixMeClickEvent"));
	n0::n0InputEvents::GetInstance()->RegisterEventListener(Hash("theE"),evtListener,&Fixme::OnKeyEvent,Hash("fixMeKeyEvent"));

	while(! n0::windows::UserQuitMsg())
	{
		n0::StartFrame();

		n0::DrawTexturedRect(200,200,400,400);
		// draw the UI

		n0::EndFrame();
	}
	delete evtListener;
	return 0;

}

int  APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	n0::windows::SetHInstance(hInstance);
	int bitDepth = 24;
	int screenW = WIN_WIDTH;
	int screenH = WIN_HEIGHT;

	if(n0::InitGraphics(screenW,screenH,bitDepth))
	{
		// audio engine
		//		irrklang::ISoundEngine * pSoundEngine = irrklang::createIrrKlangDevice();

		n0::n0Texture * pTex = n0::n0TextureManager::GetInstance()->GenerateTexture(1,256,256);
		n0::n0InputEvents::GetInstance()->RegisterInputEvent(n0::SMouseEvent::kEvent_LeftMBDown,0,"TargetClick",NULL);
		n0::n0InputEvents::GetInstance()->RegisterEventListener(Hash("TargetClick"),new Fixme(),&Fixme::OnEvent,Hash("fixMeEvent"));

		// 		if (pSoundEngine)
		// 			pSoundEngine->play2D("IsAnyoneThere.mp3");

		//MARK: GAME LOOP
		while(!n0::windows::UserQuitMsg())
		{
			//Do stuff in here
			n0::StartFrame();

			pTex->Bind();
			n0::DrawTexturedRect(200,200,400,400);
			// draw the UI

			n0::EndFrame();

		}

		//MARK: CLEAN UP
		n0::windows::CleanUp(true);
	}
	else
	{
		n0::windows::CleanUp(false);
		return 1;
	}

	return 0;
}

u32 Hash(const char *inputStr)
{
	if(!inputStr)
		return 0;

	const char* str = inputStr;
	u32 hashVal = BASEHASH;

	while(*str)
	{
		hashVal = (hashVal << 5) + (u32)*str;
		str++;
	}

	return hashVal;
}
<commit_msg>Added mouse move tracking<commit_after>
#include "global.h"

#define WIN_WIDTH 1024
#define WIN_HEIGHT 768

class Fixme : public n0::IEventListener
{
public:
	Fixme() {}
	~Fixme() {}
	bool OnEvent(n0::n0Event *evt)
	{
		return false;
	}
	bool OnMouseEvent(n0::n0Event *_evt)
	{
		n0_ASSERT(Hash("TargetClick") == _evt->m_type, "Events are not appearing as they should (OnMouseEvent)");
		n0::SMouseEvent * pEvt = (n0::SMouseEvent *)_evt;
		n0::SMouseEventData * pEvtData = (n0::SMouseEventData *)pEvt->pData;
		printf("Mouse Click at %d,%d\n",pEvtData->x, pEvtData->y);
		return true;
	}
	bool OnKeyEvent(n0::n0Event *_evt)
	{
		n0_ASSERT(Hash("theE") == _evt->m_type, "Events are not appearing as they should (OnKeyEvent)");

		printf("E Pressed \n");
		return true;
	}
	bool OnMouseMoveEvent(n0::n0Event *_evt)
	{

		n0_ASSERT(Hash("Mmove") == _evt->m_type, "Events are not appearing as they should (OnKeyEvent)");
		n0::SMouseEvent * pEvt = (n0::SMouseEvent *)_evt;
		n0::SMouseEventData * pEvtData = (n0::SMouseEventData *)pEvt->pData;
		printf("Mouse moved to %d,%d\n",pEvtData->x, pEvtData->y);

		return true;
	}

};

int main()
{

	int bitDepth = 24;
	int screenW = WIN_WIDTH;
	int screenH = WIN_HEIGHT;
	n0::windows::InitSystem(NULL,screenW,screenH);

	n0::SetFrameRate(30);
	Fixme *evtListener = new Fixme();
	n0::n0Texture * pTex = n0::n0TextureManager::GetInstance()->GenerateTexture(1,256,256);
	n0::n0InputEvents::GetInstance()->RegisterInputEvent(n0::SMouseEvent::kEvent_LeftMBDown,0,"TargetClick",NULL);
	n0::n0InputEvents::GetInstance()->RegisterInputEvent(n0::SMouseEvent::kEvent_MouseMove,0,"Mmove",NULL);
	n0::n0InputEvents::GetInstance()->RegisterInputEvent(n0::SKeyEvent::kEvent_KeyDown,'E',"theE",NULL);
	n0::n0InputEvents::GetInstance()->RegisterEventListener(Hash("TargetClick"),evtListener,&Fixme::OnMouseEvent,Hash("fixMeClickEvent"));
	n0::n0InputEvents::GetInstance()->RegisterEventListener(Hash("theE"),evtListener,&Fixme::OnKeyEvent,Hash("fixMeKeyEvent"));
	n0::n0InputEvents::GetInstance()->RegisterEventListener(Hash("Mmove"),evtListener,&Fixme::OnMouseMoveEvent,Hash("mouseMoveEvent"));

	while(! n0::windows::UserQuitMsg())
	{
		n0::StartFrame();

		n0::DrawTexturedRect(200,200,400,400);
		// draw the UI

		n0::EndFrame();
	}
	delete evtListener;
	return 0;

}

int  APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	n0::windows::SetHInstance(hInstance);
	int bitDepth = 24;
	int screenW = WIN_WIDTH;
	int screenH = WIN_HEIGHT;

	if(n0::InitGraphics(screenW,screenH,bitDepth))
	{
		// audio engine
		//		irrklang::ISoundEngine * pSoundEngine = irrklang::createIrrKlangDevice();

		n0::n0Texture * pTex = n0::n0TextureManager::GetInstance()->GenerateTexture(1,256,256);
		n0::n0InputEvents::GetInstance()->RegisterInputEvent(n0::SMouseEvent::kEvent_LeftMBDown,0,"TargetClick",NULL);
		n0::n0InputEvents::GetInstance()->RegisterEventListener(Hash("TargetClick"),new Fixme(),&Fixme::OnEvent,Hash("fixMeEvent"));

		// 		if (pSoundEngine)
		// 			pSoundEngine->play2D("IsAnyoneThere.mp3");

		//MARK: GAME LOOP
		while(!n0::windows::UserQuitMsg())
		{
			//Do stuff in here
			n0::StartFrame();

			pTex->Bind();
			n0::DrawTexturedRect(200,200,400,400);
			// draw the UI

			n0::EndFrame();

		}

		//MARK: CLEAN UP
		n0::windows::CleanUp(true);
	}
	else
	{
		n0::windows::CleanUp(false);
		return 1;
	}

	return 0;
}

u32 Hash(const char *inputStr)
{
	if(!inputStr)
		return 0;

	const char* str = inputStr;
	u32 hashVal = BASEHASH;

	while(*str)
	{
		hashVal = (hashVal << 5) + (u32)*str;
		str++;
	}

	return hashVal;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string.h>
#include "crypto.h"
#include "account.h"
#include "gen_functions.h"
#include <openssl/sha.h>
using namespace std;
account::account(int an, char * p, int b, bool lock) {
	account_num = an;
	pin_hash = new char[SHA_DIGEST_LENGTH];
	pin_hash = hash_pin(p);
	balance = b;
	locked = lock;
}
bool account::check_creds(int an, char * p_hash) {
	if(account_num != an) {
		return false;
	}
	if(strcmp(p_hash,pin_hash) != 0) {
		return false;
	}
	return true;
}
bool account::withdraw(int amount) {
	// client (ATM) muse interpret these codes...
	if(amount > balance) {
		return false;
	}
	else {
		balance = balance - amount;
		return true;
	}
}
bool account::deposit(int amount) {
	balance += amount;
	return true;
}
int account::get_balance() {
	return balance;
}
bool account::check_creds_act(account act) {
	if(act.check_creds(account_num, pin_hash)) {
		return true;
	}
	return false;
}
bool account::is_locked() {
	return locked;
}
void account::lock() {
	locked = true;
}
void account::login() {
	logged_in = true;
}
void account::logout() {
	logged_in = false;
}
bool account::is_logged_in() {
	return logged_in;
}
<commit_msg>added debugging line to uncomment<commit_after>#include <iostream>
#include <string.h>
#include "crypto.h"
#include "account.h"
#include "gen_functions.h"
#include <openssl/sha.h>
using namespace std;
account::account(int an, char * p, int b, bool lock) {
	account_num = an;
	pin_hash = new char[SHA_DIGEST_LENGTH];
	pin_hash = hash_pin(p);
	balance = b;
	locked = lock;
	// cout << account_num << " " << raw_to_hex((unsigned char*)pin_hash, SHA_DIGEST_LENGTH) << endl;
}
bool account::check_creds(int an, char * p_hash) {
	if(account_num != an) {
		return false;
	}
	if(strcmp(p_hash,pin_hash) != 0) {
		return false;
	}
	return true;
}
bool account::withdraw(int amount) {
	// client (ATM) muse interpret these codes...
	if(amount > balance) {
		return false;
	}
	else {
		balance = balance - amount;
		return true;
	}
}
bool account::deposit(int amount) {
	balance += amount;
	return true;
}
int account::get_balance() {
	return balance;
}
bool account::check_creds_act(account act) {
	if(act.check_creds(account_num, pin_hash)) {
		return true;
	}
	return false;
}
bool account::is_locked() {
	return locked;
}
void account::lock() {
	locked = true;
}
void account::login() {
	logged_in = true;
}
void account::logout() {
	logged_in = false;
}
bool account::is_logged_in() {
	return logged_in;
}
<|endoftext|>