<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbImageKeywordlist.h"

#include <cassert>

#include "otbMacro.h"

#include "ossim/base/ossimKeywordlist.h"
#include "ossim/base/ossimString.h"
#include "ossim/ossimPluginProjectionFactory.h"
#include "ossim/imaging/ossimImageHandlerRegistry.h"
#include "ossim/ossimTileMapModel.h"
#include "ossim/projection/ossimProjectionFactoryRegistry.h"

#include "otbSensorModelAdapter.h"

namespace otb
{

ImageKeywordlist
::ImageKeywordlist()
{
}

ImageKeywordlist
::ImageKeywordlist(const Self& p) : m_Keywordlist(p.m_Keywordlist)
{
}

ImageKeywordlist
::~ImageKeywordlist()
{
}

void
ImageKeywordlist::
operator =(const Self& p)
{
  m_Keywordlist = p.m_Keywordlist;
}

void
ImageKeywordlist::
SetKeywordlist(const ossimKeywordlist& kwl)
{
  m_Keywordlist.clear();
  for (ossimKeywordlist::KeywordMap::const_iterator it = kwl.getMap().begin();
       it != kwl.getMap().end();
       ++it)
    {
    std::string first(it->first);
    std::string second(it->second);
    m_Keywordlist[first] = second;
    }
}

const std::string&
ImageKeywordlist::
GetMetadataByKey(const std::string& key) const
{
  // Search for the key in the output map
  KeywordlistMap::const_iterator it = m_Keywordlist.find(key);

  // If the key can not be found, throw an exception
  if (it == m_Keywordlist.end())
    {
    itkExceptionMacro(<< "Keywordlist has no output with key " << key);
    }

  // Then if everything is ok, return the ossinString
  return it->second;
}

bool
ImageKeywordlist::
HasKey(const std::string& key) const
{
  KeywordlistMap::const_iterator it = m_Keywordlist.find(key);
  return (it != m_Keywordlist.end());
}

void
ImageKeywordlist::
ClearMetadataByKey(const std::string& key)
{
  m_Keywordlist[key] = "";
}

void
ImageKeywordlist::
AddKey(const std::string& key, const std::string& value)
{
  m_Keywordlist[key] = value;
}

void
ImageKeywordlist::
convertToOSSIMKeywordlist(ossimKeywordlist& kwl) const
{
  ossimKeywordlist::KeywordMap ossimMap;
  for(KeywordlistMap::const_iterator it = m_Keywordlist.begin();
      it != m_Keywordlist.end();
      ++it)
    {
    ossimMap[it->first] = it->second;
    }
  kwl.getMap() = ossimMap;
}

void
ImageKeywordlist::
Print(std::ostream& os, itk::Indent indent) const
{
  this->PrintSelf(os, indent.GetNextIndent());
}

void
ImageKeywordlist::
PrintSelf(std::ostream& os, itk::Indent indent) const
{
  ossimKeywordlist kwl;
  convertToOSSIMKeywordlist(kwl);
  os << indent << " Ossim Keyword list:" << std::endl;
  os << indent << kwl;
}

std::ostream &
operator <<(std::ostream& os, const ImageKeywordlist& kwl)
{
  kwl.Print(os);
  return os;
}

ImageKeywordlist
ReadGeometry(const std::string& filename)
{
  return ReadGeometryFromImage(filename);
}

ImageKeywordlist
ReadGeometryFromImage(const std::string& filename)
{
  // Trying to read ossim MetaData
  bool             hasMetaData = false;
  ossimKeywordlist geom_kwl; // = new ossimKeywordlist();
  ImageKeywordlist otb_kwl;

  // Test the plugins factory
  /** Before, the pluginfactory was tested if the ossim one returned false.
      But in the case TSX, the images tif were considered as ossimQuickbirdTiffTileSource
      thus a TSX tif image wasn't read with TSX Model. We don't use the ossimRegisteryFactory
      because the default include factory contains ossimQuickbirdTiffTileSource. */
  ossimProjection * projection = ossimplugins::ossimPluginProjectionFactory::instance()
                                 ->createProjection(ossimFilename(filename.c_str()), 0);

  if (!projection)
    {
    otbMsgDevMacro(<< "OSSIM Instantiate projection FAILED ! ");
    }
  else
    {
    otbMsgDevMacro(<< "OSSIM Instantiate projection SUCCESS ! ");

    hasMetaData = projection->saveState(geom_kwl);
    otb_kwl.SetKeywordlist(geom_kwl);

    // Free memory
    delete projection;
    }

  if (!hasMetaData)
    {
    ossimImageHandler* handler = ossimImageHandlerRegistry::instance()
                                 ->open(ossimFilename(filename.c_str()));
    if (!handler)
      {
      otbMsgDevMacro(<< "OSSIM Open Image FAILED ! ");

      // In some corner cases, ossim is unable to create a ossimImageHandler
      // instance for the provided file.
      // This can happen for TIFF+geom files where the ossimTiffTileSource
      // fails when trying to open the TIFF file (for example
      // because ossim is compiled with a libtiff without BigTIFF support
      // and when the actual TIFF file exceeds the Large File limit).
      // In such cases, we don't actually need ossim to interpret the TIFF file,
      // and just want a valid ossimKeywordlist corresponding to a sensor model.

      // Here is implemented a shortcut used as a fallback scenario,
      // where we bypass the ossimImageHandlerRegistry
      // and directly create a ossimKeywordlist from the ".geom" file.

      // We then verify it is a valid sensor model by using otb::SensorModelAdapter
      // which uses ossimSensorModelFactory and ossimPluginProjectionFactory internally,
      // thus by-passing the need for a valid ossimImageHandler.

      // Try to find a ".geom" file next to 'filename'
      ossimFilename ossimGeomFile = ossimFilename(filename).setExtension(".geom");

      otb_kwl = ReadGeometryFromGEOMFile(ossimGeomFile);
      }
    else
      {
      otbMsgDevMacro(<< "OSSIM Open Image SUCCESS ! ");

      // Add ossimPlugins model
      ossimProjectionFactoryRegistry::instance()->registerFactory(ossimplugins::ossimPluginProjectionFactory::instance());

      //     hasMetaData = handler->getImageGeometry(geom_kwl);
      ossimRefPtr<ossimImageGeometry> geom = handler->getImageGeometry();

      if (geom.valid())
        {
        ossimProjection* projection = geom->getProjection();
        if (projection)
          {
          hasMetaData = projection->saveState(geom_kwl);
          otb_kwl.SetKeywordlist(geom_kwl);
          }
        }
      }
    // Free memory
    delete handler;
    }

  if (!hasMetaData)
    {
    otbMsgDevMacro(<< "OSSIM MetaData not present ! ");
    }
  else
    {
    otbMsgDevMacro(<< "OSSIM MetaData present ! ");
    otbMsgDevMacro(<< geom_kwl);
    }

  return otb_kwl;
}

ImageKeywordlist
ReadGeometryFromGEOMFile(const std::string& filename)
{
  ossimKeywordlist geom_kwl;
  ImageKeywordlist otb_kwl;
  ossimFilename ossimGeomFile = ossimFilename(filename);

  if (ossimGeomFile.exists() && ossimGeomFile.isFile())
    {
    // Interpret the geom file as a KWL
    ossimKeywordlist kwl(ossimGeomFile);

    // Check that the geom file results in a valid ossimKeywordlist
    if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_OK)
      {
      // Be sure there is a corresponding instance of ossimSensorModel
      // which understands this kwl
      SensorModelAdapter::Pointer sensorModel = SensorModelAdapter::New();
      ImageKeywordlist otbkwl;
      otbkwl.SetKeywordlist(kwl);
      sensorModel->CreateProjection(otbkwl);

      if (sensorModel->IsValidSensorModel())
        {
        geom_kwl = kwl;
        }
      }
    }

  otb_kwl.SetKeywordlist(geom_kwl);

  return otb_kwl;
}

void
WriteGeometry(const ImageKeywordlist& otb_kwl, const std::string& filename)
{
  // Write the image keyword list if any
  ossimKeywordlist geom_kwl;
  otb_kwl.convertToOSSIMKeywordlist(geom_kwl);

  if (geom_kwl.getSize() > 0)
    {
    otbMsgDevMacro(<< "Exporting keywordlist ...");
    ossimFilename geomFileName(filename);
    geomFileName.setExtension(".geom");
    geom_kwl.write(geomFileName.chars());
    }
}

} //namespace otb
<commit_msg>BUG: 602: fix loading of geom file<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbImageKeywordlist.h"

#include <cassert>

#include "otbMacro.h"

#include "ossim/base/ossimKeywordlist.h"
#include "ossim/base/ossimString.h"
#include "ossim/ossimPluginProjectionFactory.h"
#include "ossim/imaging/ossimImageHandlerRegistry.h"
#include "ossim/ossimTileMapModel.h"
#include "ossim/projection/ossimProjectionFactoryRegistry.h"

#include "otbSensorModelAdapter.h"

namespace otb
{

ImageKeywordlist
::ImageKeywordlist()
{
}

ImageKeywordlist
::ImageKeywordlist(const Self& p) : m_Keywordlist(p.m_Keywordlist)
{
}

ImageKeywordlist
::~ImageKeywordlist()
{
}

void
ImageKeywordlist::
operator =(const Self& p)
{
  m_Keywordlist = p.m_Keywordlist;
}

void
ImageKeywordlist::
SetKeywordlist(const ossimKeywordlist& kwl)
{
  m_Keywordlist.clear();
  for (ossimKeywordlist::KeywordMap::const_iterator it = kwl.getMap().begin();
       it != kwl.getMap().end();
       ++it)
    {
    std::string first(it->first);
    std::string second(it->second);
    m_Keywordlist[first] = second;
    }
}

const std::string&
ImageKeywordlist::
GetMetadataByKey(const std::string& key) const
{
  // Search for the key in the output map
  KeywordlistMap::const_iterator it = m_Keywordlist.find(key);

  // If the key can not be found, throw an exception
  if (it == m_Keywordlist.end())
    {
    itkExceptionMacro(<< "Keywordlist has no output with key " << key);
    }

  // Then if everything is ok, return the ossinString
  return it->second;
}

bool
ImageKeywordlist::
HasKey(const std::string& key) const
{
  KeywordlistMap::const_iterator it = m_Keywordlist.find(key);
  return (it != m_Keywordlist.end());
}

void
ImageKeywordlist::
ClearMetadataByKey(const std::string& key)
{
  m_Keywordlist[key] = "";
}

void
ImageKeywordlist::
AddKey(const std::string& key, const std::string& value)
{
  m_Keywordlist[key] = value;
}

void
ImageKeywordlist::
convertToOSSIMKeywordlist(ossimKeywordlist& kwl) const
{
  ossimKeywordlist::KeywordMap ossimMap;
  for(KeywordlistMap::const_iterator it = m_Keywordlist.begin();
      it != m_Keywordlist.end();
      ++it)
    {
    ossimMap[it->first] = it->second;
    }
  kwl.getMap() = ossimMap;
}

void
ImageKeywordlist::
Print(std::ostream& os, itk::Indent indent) const
{
  this->PrintSelf(os, indent.GetNextIndent());
}

void
ImageKeywordlist::
PrintSelf(std::ostream& os, itk::Indent indent) const
{
  ossimKeywordlist kwl;
  convertToOSSIMKeywordlist(kwl);
  os << indent << " Ossim Keyword list:" << std::endl;
  os << indent << kwl;
}

std::ostream &
operator <<(std::ostream& os, const ImageKeywordlist& kwl)
{
  kwl.Print(os);
  return os;
}

ImageKeywordlist
ReadGeometry(const std::string& filename)
{
  return ReadGeometryFromImage(filename);
}

ImageKeywordlist
ReadGeometryFromImage(const std::string& filename)
{
  // Trying to read ossim MetaData
  bool             hasMetaData = false;
  ossimKeywordlist geom_kwl; // = new ossimKeywordlist();
  ImageKeywordlist otb_kwl;

  // Test the plugins factory
  /** Before, the pluginfactory was tested if the ossim one returned false.
      But in the case TSX, the images tif were considered as ossimQuickbirdTiffTileSource
      thus a TSX tif image wasn't read with TSX Model. We don't use the ossimRegisteryFactory
      because the default include factory contains ossimQuickbirdTiffTileSource. */
  ossimProjection * projection = ossimplugins::ossimPluginProjectionFactory::instance()
                                 ->createProjection(ossimFilename(filename.c_str()), 0);

  if (!projection)
    {
    otbMsgDevMacro(<< "OSSIM Instantiate projection FAILED ! ");
    }
  else
    {
    otbMsgDevMacro(<< "OSSIM Instantiate projection SUCCESS ! ");

    hasMetaData = projection->saveState(geom_kwl);
    otb_kwl.SetKeywordlist(geom_kwl);

    // Free memory
    delete projection;
    }

  if (!hasMetaData)
    {
    ossimImageHandler* handler = ossimImageHandlerRegistry::instance()
                                 ->open(ossimFilename(filename.c_str()));
    if (!handler)
      {
      otbMsgDevMacro(<< "OSSIM Open Image FAILED ! ");

      // In some corner cases, ossim is unable to create a ossimImageHandler
      // instance for the provided file.
      // This can happen for TIFF+geom files where the ossimTiffTileSource
      // fails when trying to open the TIFF file (for example
      // because ossim is compiled with a libtiff without BigTIFF support
      // and when the actual TIFF file exceeds the Large File limit).
      // In such cases, we don't actually need ossim to interpret the TIFF file,
      // and just want a valid ossimKeywordlist corresponding to a sensor model.

      // Here is implemented a shortcut used as a fallback scenario,
      // where we bypass the ossimImageHandlerRegistry
      // and directly create a ossimKeywordlist from the ".geom" file.

      // We then verify it is a valid sensor model by using otb::SensorModelAdapter
      // which uses ossimSensorModelFactory and ossimPluginProjectionFactory internally,
      // thus by-passing the need for a valid ossimImageHandler.

      // Try to find a ".geom" file next to 'filename'
      ossimFilename ossimGeomFile = ossimFilename(filename).setExtension(".geom");

      otb_kwl = ReadGeometryFromGEOMFile(ossimGeomFile);
      }
    else
      {
      otbMsgDevMacro(<< "OSSIM Open Image SUCCESS ! ");

      // Add ossimPlugins model
      ossimProjectionFactoryRegistry::instance()->registerFactory(ossimplugins::ossimPluginProjectionFactory::instance());

      //     hasMetaData = handler->getImageGeometry(geom_kwl);
      ossimRefPtr<ossimImageGeometry> geom = handler->getImageGeometry();

      if (geom.valid())
        {
        ossimProjection* projection = geom->getProjection();
        if (projection)
          {
          hasMetaData = projection->saveState(geom_kwl);
          otb_kwl.SetKeywordlist(geom_kwl);
          }
        }

      // If still no metadata, try the ".geom" file
      if (!hasMetaData && otb_kwl.GetSize() == 0)
        {
        ossimFilename ossimGeomFile = ossimFilename(filename).setExtension(".geom");
        otb_kwl = ReadGeometryFromGEOMFile(ossimGeomFile);
        }

      }
    // Free memory
    delete handler;
    }

  if (!hasMetaData)
    {
    otbMsgDevMacro(<< "OSSIM MetaData not present ! ");
    }
  else
    {
    otbMsgDevMacro(<< "OSSIM MetaData present ! ");
    otbMsgDevMacro(<< geom_kwl);
    }

  return otb_kwl;
}

ImageKeywordlist
ReadGeometryFromGEOMFile(const std::string& filename)
{
  ossimKeywordlist geom_kwl;
  ImageKeywordlist otb_kwl;
  ossimFilename ossimGeomFile = ossimFilename(filename);

  if (ossimGeomFile.exists() && ossimGeomFile.isFile())
    {
    // Interpret the geom file as a KWL
    ossimKeywordlist kwl(ossimGeomFile);

    // Check that the geom file results in a valid ossimKeywordlist
    if (kwl.getErrorStatus() == ossimErrorCodes::OSSIM_OK)
      {
//       // Be sure there is a corresponding instance of ossimSensorModel
//       // which understands this kwl
//       SensorModelAdapter::Pointer sensorModel = SensorModelAdapter::New();
//       ImageKeywordlist otbkwl;
//       otbkwl.SetKeywordlist(kwl);
//       sensorModel->CreateProjection(otbkwl);
//
//       if (sensorModel->IsValidSensorModel())
//         {
//         geom_kwl = kwl;
//         }
      geom_kwl = kwl;
      }
    }

  otb_kwl.SetKeywordlist(geom_kwl);

  return otb_kwl;
}

void
WriteGeometry(const ImageKeywordlist& otb_kwl, const std::string& filename)
{
  // Write the image keyword list if any
  ossimKeywordlist geom_kwl;
  otb_kwl.convertToOSSIMKeywordlist(geom_kwl);

  if (geom_kwl.getSize() > 0)
    {
    otbMsgDevMacro(<< "Exporting keywordlist ...");
    ossimFilename geomFileName(filename);
    geomFileName.setExtension(".geom");
    geom_kwl.write(geomFileName.chars());
    }
}

} //namespace otb
<|endoftext|>


<commit_before>/*
 * Win32LibraryLoader.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/system/LibraryLoader.hpp>

#include <core/Error.hpp>

namespace core {
namespace system {

Error loadLibrary(const std::string& libPath, void** ppLib)
{
   return Success();
}

Error loadSymbol(void* pLib, const std::string& name, void** ppSymbol)
{

   return Success();
}

Error closeLibrary(void* pLib)
{

   return Success();
}

} // namespace system
} // namespace core
<commit_msg>implement Win32 LibraryLoader<commit_after>/*
 * Win32LibraryLoader.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include <core/system/LibraryLoader.hpp>

#include <windows.h>

#include <core/Error.hpp>

namespace core {
namespace system {

Error loadLibrary(const std::string& libPath, void** ppLib)
{
   *ppLib = NULL;
   *ppLib = (void*)::LoadLibrary(libPath.c_str());
   if (*ppLib == NULL)
   {
      Error error = systemError(::GetLastError(), ERROR_LOCATION);
      error.addProperty("lib-path", libPath);
      return error;
   }
   else
   {
      return Success();
   }
}

Error loadSymbol(void* pLib, const std::string& name, void** ppSymbol)
{
   *ppSymbol = NULL;
   *ppSymbol = (void*)::GetProcAddress((HINSTANCE)pLib, name.c_str());
   if (*ppSymbol == NULL)
   {
      Error error = systemError(::GetLastError(), ERROR_LOCATION);
      error.addProperty("symbol", name);
      return error;
   }
   else
   {
      return Success();
   }
}

Error closeLibrary(void* pLib)
{
   if (!::FreeLibrary((HMODULE)pLib))
      return systemError(::GetLastError(), ERROR_LOCATION);
   else
      return Success();
}

} // namespace system
} // namespace core
<|endoftext|>


<commit_before>// This code is in the public domain -- castanyo@yahoo.es

#include <nvcore/Debug.h>
#include <nvcore/Ptr.h>

#include <nvmath/Color.h>

#include <nvimage/Image.h>
#include <nvimage/ImageIO.h>

using namespace nv;

Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL)
{
}

Image::Image(const Image & img)
{
	allocate(img.m_width, img.m_height);
	m_format = img.m_format;
	memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height);
}

Image::~Image()
{
	free();
}

const Image & Image::operator=(const Image & img)
{
	allocate(img.m_width, img.m_height);
	m_format = img.m_format;
	memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height);
	return *this;
}

void Image::allocate(uint w, uint h)
{
	m_width = w;
	m_height = h;
	m_data = (Color32 *)realloc(m_data, w * h * sizeof(Color32));
}

bool Image::load(const char * name)
{
	free();

	AutoPtr<Image> img(ImageIO::load(name));
	if (img == NULL) {
		return false;
	}

	swap(m_width, img->m_width);
	swap(m_height, img->m_height);
	swap(m_format, img->m_format);
	swap(m_data, img->m_data);

	return true;
}

void Image::wrap(void * data, uint w, uint h)
{
	free();
	m_data = (Color32 *)data;
	m_width = w;
	m_height = h;
}

void Image::unwrap()
{
	m_data = NULL;
	m_width = 0;
	m_height = 0;
}

void Image::free()
{
	::free(m_data);
	m_data = NULL;
}

uint Image::width() const
{
	return m_width;
}

uint Image::height() const
{
	return m_height;
}

const Color32 * Image::scanline(uint h) const
{
	nvDebugCheck(h < m_height);
	return m_data + h * m_width;
}

Color32 * Image::scanline(uint h)
{
	nvDebugCheck(h < m_height);
	return m_data + h * m_width;
}

const Color32 * Image::pixels() const
{
	return m_data;
}

Color32 * Image::pixels()
{
	return m_data;
}

const Color32 & Image::pixel(uint idx) const
{
	nvDebugCheck(idx < m_width * m_height);
	return m_data[idx];
}

Color32 & Image::pixel(uint idx)
{
	nvDebugCheck(idx < m_width * m_height);
	return m_data[idx];
}

Image::Format Image::format() const
{
	return m_format;
}

void Image::setFormat(Image::Format f)
{
	m_format = f;
}

void Image::fill(Color32 c)
{
	const uint size = m_width * m_height;
	for (uint i = 0; i < size; ++i)
	{
		m_data[i] = c;
	}
}

<commit_msg>Fix Image copy ctor bug reported by Richard Sim.<commit_after>// This code is in the public domain -- castanyo@yahoo.es

#include <nvcore/Debug.h>
#include <nvcore/Ptr.h>

#include <nvmath/Color.h>

#include <nvimage/Image.h>
#include <nvimage/ImageIO.h>

using namespace nv;

Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL)
{
}

Image::Image(const Image & img) : m_data(NULL)
{
	allocate(img.m_width, img.m_height);
	m_format = img.m_format;
	memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height);
}

Image::~Image()
{
	free();
}

const Image & Image::operator=(const Image & img)
{
	allocate(img.m_width, img.m_height);
	m_format = img.m_format;
	memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height);
	return *this;
}

void Image::allocate(uint w, uint h)
{
	m_width = w;
	m_height = h;
	m_data = (Color32 *)realloc(m_data, w * h * sizeof(Color32));
}

bool Image::load(const char * name)
{
	free();

	AutoPtr<Image> img(ImageIO::load(name));
	if (img == NULL) {
		return false;
	}

	swap(m_width, img->m_width);
	swap(m_height, img->m_height);
	swap(m_format, img->m_format);
	swap(m_data, img->m_data);

	return true;
}

void Image::wrap(void * data, uint w, uint h)
{
	free();
	m_data = (Color32 *)data;
	m_width = w;
	m_height = h;
}

void Image::unwrap()
{
	m_data = NULL;
	m_width = 0;
	m_height = 0;
}

void Image::free()
{
	::free(m_data);
	m_data = NULL;
}

uint Image::width() const
{
	return m_width;
}

uint Image::height() const
{
	return m_height;
}

const Color32 * Image::scanline(uint h) const
{
	nvDebugCheck(h < m_height);
	return m_data + h * m_width;
}

Color32 * Image::scanline(uint h)
{
	nvDebugCheck(h < m_height);
	return m_data + h * m_width;
}

const Color32 * Image::pixels() const
{
	return m_data;
}

Color32 * Image::pixels()
{
	return m_data;
}

const Color32 & Image::pixel(uint idx) const
{
	nvDebugCheck(idx < m_width * m_height);
	return m_data[idx];
}

Color32 & Image::pixel(uint idx)
{
	nvDebugCheck(idx < m_width * m_height);
	return m_data[idx];
}

Image::Format Image::format() const
{
	return m_format;
}

void Image::setFormat(Image::Format f)
{
	m_format = f;
}

void Image::fill(Color32 c)
{
	const uint size = m_width * m_height;
	for (uint i = 0; i < size; ++i)
	{
		m_data[i] = c;
	}
}

<|endoftext|>


<commit_before>

#ifdef __cplusplus

#ifdef _WIN32
#define SICONOS_EXPORT extern "C" __declspec(dllexport)
#else
#define SICONOS_EXPORT extern "C"
#endif
#define restrict __restrict

#else

#ifdef _WIN32
#define SICONOS_EXPORT __declspec(dllexport)
#else
#define SICONOS_EXPORT
#endif

#endif

#include <stdio.h>

typedef struct
{
  int id;
  double* xk;
  double h;
  double theta;
  double gamma;
  double g;
  double kappa;
  unsigned int f_eval;
  unsigned int nabla_eval;
} data;

SICONOS_EXPORT void compute_F(void* env, int n, double* l, double* F)
{
  data* d = (data*) env;

  double xk0 = d->xk[0];
  double xk1 = d->xk[1];
  double l0 = l[0];
  double l1 = l[1];
  double invR = 1.0/(1.0 - d->kappa*l0*l1);
  F[1] = d->h*d->g*l0*invR;

  double v_gamma = xk1 + d->gamma*F[1];
  F[0] = -d->h*d->kappa*l0*l1*v_gamma;

  double v_theta = xk1 + d->theta*F[1];
  F[0] += xk0 + d->h*v_theta;
  F[1] += xk1;
  d->f_eval += 1;

}

SICONOS_EXPORT void compute_nabla_F(void* env, int n, double* l, double* nabla_F)
{
  data* d = (data*) env;

  double l0 = l[0];
  double l1 = l[1];
  double xk1 = d->xk[1];
  double invR = 1.0/(1.0 - d->kappa*l0*l1);
  double invR2 = invR*invR;
  double rr1 = d->g*l0*invR;

  double v_gamma = xk1 + d->gamma*d->h*rr1;

  nabla_F[1] = d->h*d->g*invR2;
  nabla_F[1 + 2] = d->h*(d->g*d->kappa*l0*l0)/invR2;
//  nabla_F[0] = d->h*(-d->kappa*l1*v_gamma + d->gamma*d->h*(1.0-d->kappa*l0*l1)*nabla_F[1]);
//  nabla_F[0 + 2] = d->h*(-d->kappa*l0*v_gamma + d->gamma*d->h*(1.0-d->kappa*l0*l1)*nabla_F[1 + 2]);
  nabla_F[0] = d->h*(-d->kappa*l1*v_gamma + d->gamma*d->h*(1.0-d->kappa*l0*l1)*nabla_F[1]);
  nabla_F[0 + 2] = d->h*(-d->kappa*l0*v_gamma + d->gamma*d->h*(1.0-d->kappa*l0*l1)*nabla_F[1 + 2]);
  d->nabla_eval += 1;
}

SICONOS_EXPORT void compute_Fmcp(void* env, int n1, int n2, double* restrict z, double* restrict F)
{
  data* d = (data*) env;
  double l0 = 2.0*z[0] - 1.0;
  double l1 = 2.0*z[2] - 1.0;
  double r1 = d->g*l0/(1.0 - d->kappa*l0*l1);
  double v_gamma = (d->xk[1] + d->gamma*(d->h*r1));
  double r0 = -d->kappa*l0*l1*(v_gamma);
  double v_theta = d->xk[1] + d->theta*(d->h*r1);
  F[0] = d->xk[0] + d->h*v_theta + d->h*r0 + z[1];
  F[2] = d->xk[1] + d->h*r1 + z[3];
  F[1] = 1.0 - z[0];
  F[3] = 1.0 - z[2];
  d->f_eval += 1;
}

SICONOS_EXPORT void compute_nabla_Fmcp(void* env, int n1, int n2, double* restrict z, double* restrict nabla_Fmcp)
{
  data* d = (data*) env;
  double l0 = 2.0*z[0] - 1.0;
  double l1 = 2.0*z[2] - 1.0;
  double invR = 1.0/(1.0 - d->kappa*l0*l1);
  double invR2 = invR*invR;
  double r1 = d->g*l0*invR;
  double v_gamma = d->xk[1] + d->gamma*(d->h*r1);

  nabla_Fmcp[2] = 2.0*d->h*d->g*invR2;
  nabla_Fmcp[2 + 4] = 0.0;
  nabla_Fmcp[2 + 2*4] = 2.0*d->h*(d->g*d->kappa*l0*l0)*invR2;
  nabla_Fmcp[2 + 3*4] = 1.0;

  nabla_Fmcp[0] = -2.0*d->h*d->kappa*l1*(v_gamma) + d->h*(d->theta - d->gamma*d->kappa*l0*l1)*nabla_Fmcp[2];
  nabla_Fmcp[0 + 1*4] = 1.0;
  nabla_Fmcp[0 + 2*4] = -2.0*d->h*d->kappa*l0*(v_gamma) + d->h*(d->theta - d->gamma*d->kappa*l0*l1)*nabla_Fmcp[2 + 2*4];
  nabla_Fmcp[0 + 3*4] = 0.0;

  nabla_Fmcp[1] = -1.0;
  nabla_Fmcp[1 + 4] = 0.0;
  nabla_Fmcp[1 + 8] = 0.0;
  nabla_Fmcp[1 + 12] = 0.0;

  nabla_Fmcp[3] = 0.0;
  nabla_Fmcp[3 + 4] = 0.0;
  nabla_Fmcp[3 + 2*4] = -1.0;
  nabla_Fmcp[3 + 3*4] = 0.0;
  d->nabla_eval += 1;
}

SICONOS_EXPORT void compute_nabla_Fmcp2(void* env, int n1, int n2, double* restrict z, double* restrict nabla_Fmcp)
{
  data* d = (data*) env;
  double l0 = 2.0*z[0] - 1.0;
  double l1 = 2.0*z[2] - 1.0;
  double R = (1.0 - d->kappa*l0*l1);
  double R2 = R*R;
  double r1 = d->g*l0/R;
  double v_gamma = d->xk[1] + d->gamma*(d->h*r1);

  nabla_Fmcp[2] = 2.0*d->h*d->g/R2;
  nabla_Fmcp[2 + 4] = 0.0;
  nabla_Fmcp[2 + 2*4] = 2.0*d->h*(d->g*d->kappa*l0*l0)/R2;
  nabla_Fmcp[2 + 3*4] = 1.0;

  nabla_Fmcp[0] = -2.0*d->h*d->kappa*l1*(v_gamma) + d->h*(d->theta - d->gamma*d->kappa*l0*l1)*nabla_Fmcp[2];
  nabla_Fmcp[0 + 1*4] = 1.0;
  nabla_Fmcp[0 + 2*4] = -2.0*d->h*d->kappa*l0*(v_gamma) + d->h*(d->theta - d->gamma*d->kappa*l0*l1)*nabla_Fmcp[2 + 2*4];
  nabla_Fmcp[0 + 3*4] = 0.0;

  nabla_Fmcp[1] = -1.0;
  nabla_Fmcp[1 + 4] = 0.0;
  nabla_Fmcp[1 + 8] = 0.0;
  nabla_Fmcp[1 + 12] = 0.0;

  nabla_Fmcp[3] = 0.0;
  nabla_Fmcp[3 + 4] = 0.0;
  nabla_Fmcp[3 + 2*4] = -1.0;
  nabla_Fmcp[3 + 3*4] = 0.0;
  d->nabla_eval += 1;
}
<commit_msg>add some restrict<commit_after>

#ifdef __cplusplus

#ifdef _WIN32
#define SICONOS_EXPORT extern "C" __declspec(dllexport)
#else
#define SICONOS_EXPORT extern "C"
#endif
#define restrict __restrict

#else

#ifdef _WIN32
#define SICONOS_EXPORT __declspec(dllexport)
#else
#define SICONOS_EXPORT
#endif

#endif

#include <stdio.h>

typedef struct
{
  int id;
  double* xk;
  double h;
  double theta;
  double gamma;
  double g;
  double kappa;
  unsigned int f_eval;
  unsigned int nabla_eval;
} data;

SICONOS_EXPORT void compute_F(void* env, int n, double* restrict l, double* restrict F)
{
  data* d = (data*) env;

  double xk0 = d->xk[0];
  double xk1 = d->xk[1];
  double l0 = l[0];
  double l1 = l[1];
  double invR = 1.0/(1.0 - d->kappa*l0*l1);
  F[1] = d->h*d->g*l0*invR;

  double v_gamma = xk1 + d->gamma*F[1];
  F[0] = -d->h*d->kappa*l0*l1*v_gamma;

  double v_theta = xk1 + d->theta*F[1];
  F[0] += xk0 + d->h*v_theta;
  F[1] += xk1;
  d->f_eval += 1;

}

SICONOS_EXPORT void compute_nabla_F(void* env, int n, double* restrict l, double* restrict nabla_F)
{
  data* d = (data*) env;

  double l0 = l[0];
  double l1 = l[1];
  double xk1 = d->xk[1];
  double invR = 1.0/(1.0 - d->kappa*l0*l1);
  double invR2 = invR*invR;
  double rr1 = d->g*l0*invR;

  double v_gamma = xk1 + d->gamma*d->h*rr1;

  nabla_F[1] = d->h*d->g*invR2;
  nabla_F[1 + 2] = d->h*(d->g*d->kappa*l0*l0)/invR2;
//  nabla_F[0] = d->h*(-d->kappa*l1*v_gamma + d->gamma*d->h*(1.0-d->kappa*l0*l1)*nabla_F[1]);
//  nabla_F[0 + 2] = d->h*(-d->kappa*l0*v_gamma + d->gamma*d->h*(1.0-d->kappa*l0*l1)*nabla_F[1 + 2]);
  nabla_F[0] = d->h*(-d->kappa*l1*v_gamma + d->gamma*d->h*(1.0-d->kappa*l0*l1)*nabla_F[1]);
  nabla_F[0 + 2] = d->h*(-d->kappa*l0*v_gamma + d->gamma*d->h*(1.0-d->kappa*l0*l1)*nabla_F[1 + 2]);
  d->nabla_eval += 1;
}

SICONOS_EXPORT void compute_Fmcp(void* env, int n1, int n2, double* restrict z, double* restrict F)
{
  data* d = (data*) env;
  double l0 = 2.0*z[0] - 1.0;
  double l1 = 2.0*z[2] - 1.0;
  double r1 = d->g*l0/(1.0 - d->kappa*l0*l1);
  double v_gamma = (d->xk[1] + d->gamma*(d->h*r1));
  double r0 = -d->kappa*l0*l1*(v_gamma);
  double v_theta = d->xk[1] + d->theta*(d->h*r1);
  F[0] = d->xk[0] + d->h*v_theta + d->h*r0 + z[1];
  F[2] = d->xk[1] + d->h*r1 + z[3];
  F[1] = 1.0 - z[0];
  F[3] = 1.0 - z[2];
  d->f_eval += 1;
}

SICONOS_EXPORT void compute_nabla_Fmcp(void* env, int n1, int n2, double* restrict z, double* restrict nabla_Fmcp)
{
  data* d = (data*) env;
  double l0 = 2.0*z[0] - 1.0;
  double l1 = 2.0*z[2] - 1.0;
  double invR = 1.0/(1.0 - d->kappa*l0*l1);
  double invR2 = invR*invR;
  double r1 = d->g*l0*invR;
  double v_gamma = d->xk[1] + d->gamma*(d->h*r1);

  nabla_Fmcp[2] = 2.0*d->h*d->g*invR2;
  nabla_Fmcp[2 + 4] = 0.0;
  nabla_Fmcp[2 + 2*4] = 2.0*d->h*(d->g*d->kappa*l0*l0)*invR2;
  nabla_Fmcp[2 + 3*4] = 1.0;

  nabla_Fmcp[0] = -2.0*d->h*d->kappa*l1*(v_gamma) + d->h*(d->theta - d->gamma*d->kappa*l0*l1)*nabla_Fmcp[2];
  nabla_Fmcp[0 + 1*4] = 1.0;
  nabla_Fmcp[0 + 2*4] = -2.0*d->h*d->kappa*l0*(v_gamma) + d->h*(d->theta - d->gamma*d->kappa*l0*l1)*nabla_Fmcp[2 + 2*4];
  nabla_Fmcp[0 + 3*4] = 0.0;

  nabla_Fmcp[1] = -1.0;
  nabla_Fmcp[1 + 4] = 0.0;
  nabla_Fmcp[1 + 8] = 0.0;
  nabla_Fmcp[1 + 12] = 0.0;

  nabla_Fmcp[3] = 0.0;
  nabla_Fmcp[3 + 4] = 0.0;
  nabla_Fmcp[3 + 2*4] = -1.0;
  nabla_Fmcp[3 + 3*4] = 0.0;
  d->nabla_eval += 1;
}

SICONOS_EXPORT void compute_nabla_Fmcp2(void* env, int n1, int n2, double* restrict z, double* restrict nabla_Fmcp)
{
  data* d = (data*) env;
  double l0 = 2.0*z[0] - 1.0;
  double l1 = 2.0*z[2] - 1.0;
  double R = (1.0 - d->kappa*l0*l1);
  double R2 = R*R;
  double r1 = d->g*l0/R;
  double v_gamma = d->xk[1] + d->gamma*(d->h*r1);

  nabla_Fmcp[2] = 2.0*d->h*d->g/R2;
  nabla_Fmcp[2 + 4] = 0.0;
  nabla_Fmcp[2 + 2*4] = 2.0*d->h*(d->g*d->kappa*l0*l0)/R2;
  nabla_Fmcp[2 + 3*4] = 1.0;

  nabla_Fmcp[0] = -2.0*d->h*d->kappa*l1*(v_gamma) + d->h*(d->theta - d->gamma*d->kappa*l0*l1)*nabla_Fmcp[2];
  nabla_Fmcp[0 + 1*4] = 1.0;
  nabla_Fmcp[0 + 2*4] = -2.0*d->h*d->kappa*l0*(v_gamma) + d->h*(d->theta - d->gamma*d->kappa*l0*l1)*nabla_Fmcp[2 + 2*4];
  nabla_Fmcp[0 + 3*4] = 0.0;

  nabla_Fmcp[1] = -1.0;
  nabla_Fmcp[1 + 4] = 0.0;
  nabla_Fmcp[1 + 8] = 0.0;
  nabla_Fmcp[1 + 12] = 0.0;

  nabla_Fmcp[3] = 0.0;
  nabla_Fmcp[3 + 4] = 0.0;
  nabla_Fmcp[3 + 2*4] = -1.0;
  nabla_Fmcp[3 + 3*4] = 0.0;
  d->nabla_eval += 1;
}
<|endoftext|>


<commit_before>/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2010-2020 Couchbase, Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include <memory>

#include "internal.h"
#include "collections.h"
#include "trace.h"
#include "defer.h"

#include "capi/cmd_get.hh"

LIBCOUCHBASE_API lcb_STATUS lcb_respget_status(const lcb_RESPGET *resp)
{
    return resp->ctx.rc;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_error_context(const lcb_RESPGET *resp, const lcb_KEY_VALUE_ERROR_CONTEXT **ctx)
{
    *ctx = &resp->ctx;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_cookie(const lcb_RESPGET *resp, void **cookie)
{
    *cookie = resp->cookie;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_cas(const lcb_RESPGET *resp, uint64_t *cas)
{
    *cas = resp->ctx.cas;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_datatype(const lcb_RESPGET *resp, uint8_t *datatype)
{
    *datatype = resp->datatype;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_flags(const lcb_RESPGET *resp, uint32_t *flags)
{
    *flags = resp->itmflags;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_key(const lcb_RESPGET *resp, const char **key, size_t *key_len)
{
    *key = resp->ctx.key.c_str();
    *key_len = resp->ctx.key.size();
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_value(const lcb_RESPGET *resp, const char **value, size_t *value_len)
{
    *value = (const char *)resp->value;
    *value_len = resp->nvalue;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_create(lcb_CMDGET **cmd)
{
    *cmd = new lcb_CMDGET{};
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_destroy(lcb_CMDGET *cmd)
{
    delete cmd;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_timeout(lcb_CMDGET *cmd, uint32_t timeout)
{
    return cmd->timeout_in_microseconds(timeout);
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_parent_span(lcb_CMDGET *cmd, lcbtrace_SPAN *span)
{
    return cmd->parent_span(span);
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_collection(lcb_CMDGET *cmd, const char *scope, size_t scope_len,
                                                  const char *collection, size_t collection_len)
{
    try {
        lcb::collection_qualifier qualifier(scope, scope_len, collection, collection_len);
        return cmd->collection(std::move(qualifier));
    } catch (const std::invalid_argument &) {
        return LCB_ERR_INVALID_ARGUMENT;
    }
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_key(lcb_CMDGET *cmd, const char *key, size_t key_len)
{
    if (key == nullptr || key_len == 0) {
        return LCB_ERR_INVALID_ARGUMENT;
    }
    return cmd->key(std::string(key, key_len));
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_expiry(lcb_CMDGET *cmd, uint32_t expiration)
{
    return cmd->with_touch(expiration);
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_locktime(lcb_CMDGET *cmd, uint32_t duration)
{
    return cmd->with_lock(duration);
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_on_behalf_of(lcb_CMDGET *cmd, const char *data, size_t data_len)
{
    return cmd->on_behalf_of(std::string(data, data_len));
}

static lcb_STATUS get_validate(lcb_INSTANCE *instance, const lcb_CMDGET *cmd)
{
    if (cmd->key().empty()) {
        return LCB_ERR_EMPTY_KEY;
    }
    if (!LCBT_SETTING(instance, use_collections) && !cmd->collection().is_default_collection()) {
        /* only allow default collection when collections disabled for the instance */
        return LCB_ERR_SDK_FEATURE_UNAVAILABLE;
    }

    return LCB_SUCCESS;
}

static lcb_STATUS get_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGET> cmd)
{
    mc_PIPELINE *pl;
    mc_PACKET *pkt;
    mc_REQDATA *rdata;
    mc_CMDQUEUE *q = &instance->cmdq;
    lcb_uint8_t extlen = 0;
    lcb_uint8_t opcode = PROTOCOL_BINARY_CMD_GET;
    protocol_binary_request_header hdr{};
    lcb_STATUS err;

    std::vector<std::uint8_t> framing_extras;
    if (cmd->want_impersonation()) {
        err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
        if (err != LCB_SUCCESS) {
            return err;
        }
    }

    hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
    auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());

    if (cmd->with_lock()) {
        extlen = 4;
        opcode = PROTOCOL_BINARY_CMD_GET_LOCKED;
    } else if (cmd->with_touch()) {
        extlen = 4;
        opcode = PROTOCOL_BINARY_CMD_GAT;
    }

    lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
    err = mcreq_basic_packet(q, &keybuf, cmd->collection().collection_id(), &hdr, extlen, ffextlen, &pkt, &pl,
                             MCREQ_BASICPACKET_F_FALLBACKOK);
    if (err != LCB_SUCCESS) {
        return err;
    }

    rdata = &pkt->u_rdata.reqdata;
    rdata->cookie = cmd->cookie();
    rdata->start = cmd->start_time_or_default_in_nanoseconds(gethrtime());
    rdata->deadline =
        rdata->start + cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));

    hdr.request.opcode = opcode;
    hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
    hdr.request.bodylen = htonl(extlen + ffextlen + ntohs(hdr.request.keylen));
    hdr.request.opaque = pkt->opaque;
    hdr.request.cas = 0;

    if (cmd->is_cookie_callback()) {
        pkt->flags |= MCREQ_F_PRIVCALLBACK;
    }

    memcpy(SPAN_BUFFER(&pkt->kh_span), &hdr, sizeof(hdr));
    std::size_t offset = sizeof(hdr);
    if (!framing_extras.empty()) {
        memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
        offset += framing_extras.size();
    }
    if (cmd->with_lock()) {
        std::uint32_t lock_expiry = htonl(cmd->lock_time());
        memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, &lock_expiry, sizeof(lock_expiry));
    } else if (cmd->with_touch()) {
        std::uint32_t expiry = htonl(cmd->lock_time());
        memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, &expiry, sizeof(expiry));
    }

    LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_GET, rdata->span);
    LCB_SCHED_ADD(instance, pl, pkt)
    TRACE_GET_BEGIN(instance, &hdr, cmd);
    return LCB_SUCCESS;
}

static lcb_STATUS get_execute(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGET> cmd)
{
    if (!LCBT_SETTING(instance, use_collections)) {
        /* fast path if collections are not enabled */
        return get_schedule(instance, cmd);
    }

    if (collcache_get(instance, cmd->collection()) == LCB_SUCCESS) {
        return get_schedule(instance, cmd);
    }

    return collcache_resolve(
        instance, cmd,
        [instance](lcb_STATUS status, const lcb_RESPGETCID *resp, std::shared_ptr<lcb_CMDGET> operation) {
            const auto callback_type = LCB_CALLBACK_GET;
            lcb_RESPCALLBACK operation_callback = lcb_find_callback(instance, callback_type);
            lcb_RESPGET response{};
            if (resp != nullptr) {
                response.ctx = resp->ctx;
            }
            response.ctx.key = operation->key();
            response.ctx.scope = operation->collection().scope();
            response.ctx.collection = operation->collection().collection();
            response.cookie = operation->cookie();
            if (status == LCB_ERR_SHEDULE_FAILURE || resp == nullptr) {
                response.ctx.rc = LCB_ERR_TIMEOUT;
                operation_callback(instance, callback_type, &response);
                return;
            }
            if (resp->ctx.rc != LCB_SUCCESS) {
                operation_callback(instance, callback_type, &response);
                return;
            }
            response.ctx.rc = get_schedule(instance, operation);
            if (response.ctx.rc != LCB_SUCCESS) {
                operation_callback(instance, callback_type, &response);
            }
        });
}

LIBCOUCHBASE_API
lcb_STATUS lcb_get(lcb_INSTANCE *instance, void *cookie, const lcb_CMDGET *command)
{
    lcb_STATUS rc;

    rc = get_validate(instance, command);
    if (rc != LCB_SUCCESS) {
        return rc;
    }

    auto cmd = std::make_shared<lcb_CMDGET>(*command);
    cmd->cookie(cookie);

    if (instance->cmdq.config == nullptr) {
        cmd->start_time_in_nanoseconds(gethrtime());
        return lcb::defer_operation(instance, [instance, cmd](lcb_STATUS status) {
            const auto callback_type = LCB_CALLBACK_GET;
            lcb_RESPCALLBACK operation_callback = lcb_find_callback(instance, callback_type);
            lcb_RESPGET response{};
            response.ctx.key = cmd->key();
            response.cookie = cmd->cookie();
            if (status == LCB_ERR_REQUEST_CANCELED) {
                response.ctx.rc = status;
                operation_callback(instance, callback_type, &response);
                return;
            }
            response.ctx.rc = get_execute(instance, cmd);
            if (response.ctx.rc != LCB_SUCCESS) {
                operation_callback(instance, callback_type, &response);
            }
        });
    }
    return get_execute(instance, cmd);
}
<commit_msg>CCBC-1489: Fixed get_and_touch to use the correct expiry.<commit_after>/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2010-2020 Couchbase, Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include <memory>

#include "internal.h"
#include "collections.h"
#include "trace.h"
#include "defer.h"

#include "capi/cmd_get.hh"

LIBCOUCHBASE_API lcb_STATUS lcb_respget_status(const lcb_RESPGET *resp)
{
    return resp->ctx.rc;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_error_context(const lcb_RESPGET *resp, const lcb_KEY_VALUE_ERROR_CONTEXT **ctx)
{
    *ctx = &resp->ctx;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_cookie(const lcb_RESPGET *resp, void **cookie)
{
    *cookie = resp->cookie;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_cas(const lcb_RESPGET *resp, uint64_t *cas)
{
    *cas = resp->ctx.cas;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_datatype(const lcb_RESPGET *resp, uint8_t *datatype)
{
    *datatype = resp->datatype;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_flags(const lcb_RESPGET *resp, uint32_t *flags)
{
    *flags = resp->itmflags;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_key(const lcb_RESPGET *resp, const char **key, size_t *key_len)
{
    *key = resp->ctx.key.c_str();
    *key_len = resp->ctx.key.size();
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_respget_value(const lcb_RESPGET *resp, const char **value, size_t *value_len)
{
    *value = (const char *)resp->value;
    *value_len = resp->nvalue;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_create(lcb_CMDGET **cmd)
{
    *cmd = new lcb_CMDGET{};
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_destroy(lcb_CMDGET *cmd)
{
    delete cmd;
    return LCB_SUCCESS;
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_timeout(lcb_CMDGET *cmd, uint32_t timeout)
{
    return cmd->timeout_in_microseconds(timeout);
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_parent_span(lcb_CMDGET *cmd, lcbtrace_SPAN *span)
{
    return cmd->parent_span(span);
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_collection(lcb_CMDGET *cmd, const char *scope, size_t scope_len,
                                                  const char *collection, size_t collection_len)
{
    try {
        lcb::collection_qualifier qualifier(scope, scope_len, collection, collection_len);
        return cmd->collection(std::move(qualifier));
    } catch (const std::invalid_argument &) {
        return LCB_ERR_INVALID_ARGUMENT;
    }
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_key(lcb_CMDGET *cmd, const char *key, size_t key_len)
{
    if (key == nullptr || key_len == 0) {
        return LCB_ERR_INVALID_ARGUMENT;
    }
    return cmd->key(std::string(key, key_len));
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_expiry(lcb_CMDGET *cmd, uint32_t expiration)
{
    return cmd->with_touch(expiration);
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_locktime(lcb_CMDGET *cmd, uint32_t duration)
{
    return cmd->with_lock(duration);
}

LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_on_behalf_of(lcb_CMDGET *cmd, const char *data, size_t data_len)
{
    return cmd->on_behalf_of(std::string(data, data_len));
}

static lcb_STATUS get_validate(lcb_INSTANCE *instance, const lcb_CMDGET *cmd)
{
    if (cmd->key().empty()) {
        return LCB_ERR_EMPTY_KEY;
    }
    if (!LCBT_SETTING(instance, use_collections) && !cmd->collection().is_default_collection()) {
        /* only allow default collection when collections disabled for the instance */
        return LCB_ERR_SDK_FEATURE_UNAVAILABLE;
    }

    return LCB_SUCCESS;
}

static lcb_STATUS get_schedule(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGET> cmd)
{
    mc_PIPELINE *pl;
    mc_PACKET *pkt;
    mc_REQDATA *rdata;
    mc_CMDQUEUE *q = &instance->cmdq;
    lcb_uint8_t extlen = 0;
    lcb_uint8_t opcode = PROTOCOL_BINARY_CMD_GET;
    protocol_binary_request_header hdr{};
    lcb_STATUS err;

    std::vector<std::uint8_t> framing_extras;
    if (cmd->want_impersonation()) {
        err = lcb::flexible_framing_extras::encode_impersonate_user(cmd->impostor(), framing_extras);
        if (err != LCB_SUCCESS) {
            return err;
        }
    }

    hdr.request.magic = framing_extras.empty() ? PROTOCOL_BINARY_REQ : PROTOCOL_BINARY_AREQ;
    auto ffextlen = static_cast<std::uint8_t>(framing_extras.size());

    if (cmd->with_lock()) {
        extlen = 4;
        opcode = PROTOCOL_BINARY_CMD_GET_LOCKED;
    } else if (cmd->with_touch()) {
        extlen = 4;
        opcode = PROTOCOL_BINARY_CMD_GAT;
    }

    lcb_KEYBUF keybuf{LCB_KV_COPY, {cmd->key().c_str(), cmd->key().size()}};
    err = mcreq_basic_packet(q, &keybuf, cmd->collection().collection_id(), &hdr, extlen, ffextlen, &pkt, &pl,
                             MCREQ_BASICPACKET_F_FALLBACKOK);
    if (err != LCB_SUCCESS) {
        return err;
    }

    rdata = &pkt->u_rdata.reqdata;
    rdata->cookie = cmd->cookie();
    rdata->start = cmd->start_time_or_default_in_nanoseconds(gethrtime());
    rdata->deadline =
        rdata->start + cmd->timeout_or_default_in_nanoseconds(LCB_US2NS(LCBT_SETTING(instance, operation_timeout)));

    hdr.request.opcode = opcode;
    hdr.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
    hdr.request.bodylen = htonl(extlen + ffextlen + ntohs(hdr.request.keylen));
    hdr.request.opaque = pkt->opaque;
    hdr.request.cas = 0;

    if (cmd->is_cookie_callback()) {
        pkt->flags |= MCREQ_F_PRIVCALLBACK;
    }

    memcpy(SPAN_BUFFER(&pkt->kh_span), &hdr, sizeof(hdr));
    std::size_t offset = sizeof(hdr);
    if (!framing_extras.empty()) {
        memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, framing_extras.data(), framing_extras.size());
        offset += framing_extras.size();
    }
    if (cmd->with_lock()) {
        std::uint32_t lock_expiry = htonl(cmd->lock_time());
        memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, &lock_expiry, sizeof(lock_expiry));
    } else if (cmd->with_touch()) {
        std::uint32_t expiry = htonl(cmd->expiry());
        memcpy(SPAN_BUFFER(&pkt->kh_span) + offset, &expiry, sizeof(expiry));
    }

    LCBTRACE_KV_START(instance->settings, pkt->opaque, cmd, LCBTRACE_OP_GET, rdata->span);
    LCB_SCHED_ADD(instance, pl, pkt)
    TRACE_GET_BEGIN(instance, &hdr, cmd);
    return LCB_SUCCESS;
}

static lcb_STATUS get_execute(lcb_INSTANCE *instance, std::shared_ptr<lcb_CMDGET> cmd)
{
    if (!LCBT_SETTING(instance, use_collections)) {
        /* fast path if collections are not enabled */
        return get_schedule(instance, cmd);
    }

    if (collcache_get(instance, cmd->collection()) == LCB_SUCCESS) {
        return get_schedule(instance, cmd);
    }

    return collcache_resolve(
        instance, cmd,
        [instance](lcb_STATUS status, const lcb_RESPGETCID *resp, std::shared_ptr<lcb_CMDGET> operation) {
            const auto callback_type = LCB_CALLBACK_GET;
            lcb_RESPCALLBACK operation_callback = lcb_find_callback(instance, callback_type);
            lcb_RESPGET response{};
            if (resp != nullptr) {
                response.ctx = resp->ctx;
            }
            response.ctx.key = operation->key();
            response.ctx.scope = operation->collection().scope();
            response.ctx.collection = operation->collection().collection();
            response.cookie = operation->cookie();
            if (status == LCB_ERR_SHEDULE_FAILURE || resp == nullptr) {
                response.ctx.rc = LCB_ERR_TIMEOUT;
                operation_callback(instance, callback_type, &response);
                return;
            }
            if (resp->ctx.rc != LCB_SUCCESS) {
                operation_callback(instance, callback_type, &response);
                return;
            }
            response.ctx.rc = get_schedule(instance, operation);
            if (response.ctx.rc != LCB_SUCCESS) {
                operation_callback(instance, callback_type, &response);
            }
        });
}

LIBCOUCHBASE_API
lcb_STATUS lcb_get(lcb_INSTANCE *instance, void *cookie, const lcb_CMDGET *command)
{
    lcb_STATUS rc;

    rc = get_validate(instance, command);
    if (rc != LCB_SUCCESS) {
        return rc;
    }

    auto cmd = std::make_shared<lcb_CMDGET>(*command);
    cmd->cookie(cookie);

    if (instance->cmdq.config == nullptr) {
        cmd->start_time_in_nanoseconds(gethrtime());
        return lcb::defer_operation(instance, [instance, cmd](lcb_STATUS status) {
            const auto callback_type = LCB_CALLBACK_GET;
            lcb_RESPCALLBACK operation_callback = lcb_find_callback(instance, callback_type);
            lcb_RESPGET response{};
            response.ctx.key = cmd->key();
            response.cookie = cmd->cookie();
            if (status == LCB_ERR_REQUEST_CANCELED) {
                response.ctx.rc = status;
                operation_callback(instance, callback_type, &response);
                return;
            }
            response.ctx.rc = get_execute(instance, cmd);
            if (response.ctx.rc != LCB_SUCCESS) {
                operation_callback(instance, callback_type, &response);
            }
        });
    }
    return get_execute(instance, cmd);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the test suite of the QtSparql module (not yet part 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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <tracker-sparql.h>

#include <QtTest/QtTest>
#include <QtSparql/QtSparql>

#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>

#define START_BENCHMARK \
    char tsbuf2[32]; \
    struct timeval tv2; \
    gettimeofday(&tv2, NULL); \
    long start = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; \

#define END_BENCHMARK(QSTRINGNAME) \
    gettimeofday(&tv2, NULL); \
    long end = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;          \
    snprintf(tsbuf2, sizeof(tsbuf2), "%s %lu\n", qPrintable(QSTRINGNAME), end - start); \
    write(8, tsbuf2, strlen(tsbuf2))

class tst_QSparqlBenchmark : public QObject
{
    Q_OBJECT

public:
    tst_QSparqlBenchmark();
    virtual ~tst_QSparqlBenchmark();

public slots:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

private slots:
    // Actual benchmarks
    void queryBenchmark();
    void queryBenchmark_data();

    void dataReadingBenchmark();
    void dataReadingBenchmark_data();

    // Reference benchmarks
    void queryWithLibtrackerSparql();
    void queryWithLibtrackerSparql_data();

    void queryWithLibtrackerSparqlInThread();
    void queryWithLibtrackerSparqlInThread_data();

    void dummyThread();
};

namespace {
    // Query strings

    // Test data for running this can be found in the tracker project.
QString artistsAndAlbumsQuery =
    "SELECT nmm:artistName(?artist) GROUP_CONCAT(nie:title(?album),'|') "
    "WHERE "
    "{ "
    "?song a nmm:MusicPiece . "
    "?song nmm:performer ?artist . "
    "?song nmm:musicAlbum ?album . "
        "} GROUP BY ?artist";

int artistsAndAlbumsColumnCount = 2;

QString musicQuery =
    "select ?song ?title "
    "tracker:coalesce(nmm:artistName(nmm:performer(?song)), 'UNKNOWN_ARTIST') "
    "tracker:coalesce(nie:title(nmm:musicAlbum(?song)), 'UNKNOWN_ALBUM') "
    "nfo:duration(?song) "
    "( EXISTS { ?song nao:hasTag nao:predefined-tag-favorite } ) "
    "nfo:genre(?song) nie:contentCreated(?song) "
    "tracker:id(?song) tracker:id(nmm:performer(?song)) "
    "tracker:id(nmm:musicAlbum(?song)) "
    "where { ?song a nmm:MusicPiece . "
    "?song nie:title ?title . } "
    "order by ?title "
    "<http://www.tracker-project.org/ontologies/tracker#id>(?song)";

int musicQueryColumnCount = 11;
}

tst_QSparqlBenchmark::tst_QSparqlBenchmark()
{
}

tst_QSparqlBenchmark::~tst_QSparqlBenchmark()
{
}

void tst_QSparqlBenchmark::initTestCase()
{
    // For running the test without installing the plugins. Should work in
    // normal and vpath builds.
    QCoreApplication::addLibraryPath("../../../plugins");
}

void tst_QSparqlBenchmark::cleanupTestCase()
{
}

void tst_QSparqlBenchmark::init()
{
}

void tst_QSparqlBenchmark::cleanup()
{
}

namespace {
class ResultRetriever : public QObject
{
    Q_OBJECT
public:
    ResultRetriever(QSparqlResult* r)
    : result(r)
    {
        connect(r, SIGNAL(finished()),
                SLOT(onFinished()));
    }

public slots:
    void onFinished()
    {
        // Do something silly with the data
        int total = 0;
        while (result->next()) {
            total += result->value(0).toString().size();
        }
        result->deleteLater();
    }

private:
    QSparqlResult* result;

};

}

void tst_QSparqlBenchmark::queryBenchmark()
{
    QFETCH(QString, benchmarkName);
    QFETCH(QString, connectionName);
    QFETCH(QString, queryString);

    QSparqlQuery query(queryString);
    QSparqlConnection conn(connectionName);
    // Note: connection opening cost is left out of the benchmark. Connection
    // opening is async, so we need to wait here long enough to know that it has
    // opened (there is no signal sent or such to know it has opened).
    QTest::qWait(2000);

    QSparqlResult* r = 0;
    // We run multiple queries here (and don't leave it for QBENCHMARK to
    // run this multiple times, to be able to measure things like "how much
    // does adding a QThreadPool help".
    for (int i = 0; i < 100; ++i) {
        START_BENCHMARK {
            r = conn.exec(query);
            r->waitForFinished();
            QVERIFY(!r->hasError());
            QVERIFY(r->size() > 0);
            delete r;
        }
        END_BENCHMARK(benchmarkName);
    }
}

void tst_QSparqlBenchmark::queryBenchmark_data()
{
    QTest::addColumn<QString>("benchmarkName");
    QTest::addColumn<QString>("connectionName");
    QTest::addColumn<QString>("queryString");

    QTest::newRow("TrackerDBusArtistsAndAlbums")
        << "dbus-artistsandalbums"
        << "QTRACKER"
        << artistsAndAlbumsQuery;

    QTest::newRow("TrackerDirectArtistsAndAlbums")
        << "direct-artistsandalbums"
        << "QTRACKER_DIRECT"
        << artistsAndAlbumsQuery;
}

void tst_QSparqlBenchmark::dataReadingBenchmark()
{
    QFETCH(QString, benchmarkName);
    QFETCH(QString, queryString);
    QFETCH(int, columnCount);

    QSparqlQuery query(queryString);
    QSparqlConnection conn("QTRACKER_DIRECT");
    // Note: connection opening cost is left out of the benchmark. Connection
    // opening is async, so we need to wait here long enough to know that it has
    // opened (there is no signal sent or such to know it has opened).
    QTest::qWait(2000);

    QString finished = benchmarkName + "-fin";
    QString read = benchmarkName + "-read";

    QSparqlResult* r = 0;
    for (int i = 0; i < 100; ++i) {
        {
            START_BENCHMARK {
                r = conn.exec(query);
                QEventLoop loop;
                connect(r, SIGNAL(finished()), &loop, SLOT(quit()));
                loop.exec();
            }
            END_BENCHMARK(finished);
        }
        QVERIFY(!r->hasError());
        QVERIFY(r->size() > 0);
        {
            int size = 0;
            START_BENCHMARK {
                while (r->next()) {
                    for (int c = 0; c < columnCount; ++c) {
                        QVariant var = r->value(c);
                        // Probably it's enough not to do anything with the
                        // value; the statement of getting the value won't be
                        // optimized out since calling r->value() might have
                        // side effects.
                    }
                    ++size;
                }
            }
            END_BENCHMARK(read);
            // For verifying that enough data was really read
            // qDebug() << "No of results" << size;
        }
        delete r;
    }
}

void tst_QSparqlBenchmark::dataReadingBenchmark_data()
{
    QTest::addColumn<QString>("benchmarkName");
    QTest::addColumn<QString>("queryString");
    QTest::addColumn<int>("columnCount");

    QTest::newRow("ReadingArtistsAndAlbums")
        << "read-artistsandalbums"
        << artistsAndAlbumsQuery
        << artistsAndAlbumsColumnCount;

    QTest::newRow("ReadingMusic")
        << "read-music"
        << musicQuery
        << musicQueryColumnCount;
}

void tst_QSparqlBenchmark::queryWithLibtrackerSparql()
{
    g_type_init();
    QFETCH(QString, benchmarkName);
    QFETCH(QString, queryString);
    GError* error = 0;
    TrackerSparqlConnection* connection = tracker_sparql_connection_get(0, &error);
    QVERIFY(connection);
    QVERIFY(error == 0);

    for (int i = 0; i < 100; ++i) {
        START_BENCHMARK {
            TrackerSparqlCursor* cursor =
                tracker_sparql_connection_query(connection,
                                                queryString.toUtf8(),
                                                NULL,
                                                &error);

            QVERIFY(error == 0);
            QVERIFY(cursor);

            QStringList values;
            QList<TrackerSparqlValueType> types;
            while (tracker_sparql_cursor_next (cursor, NULL, &error)) {
                gint n_columns = tracker_sparql_cursor_get_n_columns(cursor);
                for (int i = 0; i < n_columns; i++) {
                    QString value = QString::fromUtf8(
                        tracker_sparql_cursor_get_string(cursor, i, 0));
                    TrackerSparqlValueType type =
                        tracker_sparql_cursor_get_value_type(cursor, i);
                    values << value;
                    types << type;
                }
            }
            QVERIFY(values.size() > 0);
            QVERIFY(types.size() > 0);

            g_object_unref(cursor);
        }
        END_BENCHMARK(benchmarkName);
    }

    g_object_unref(connection);
}

void tst_QSparqlBenchmark::queryWithLibtrackerSparql_data()
{
    QTest::addColumn<QString>("benchmarkName");
    QTest::addColumn<QString>("queryString");

    QTest::newRow("LibtrackerSparqlArtistsAndAlbums")
        << "lts-artistsandalbums"
        << artistsAndAlbumsQuery;

    QTest::newRow("LibtrackersparqlMusic")
        << "lts-music"
        << musicQuery;
}

namespace {
class QueryRunner : public QThread
{
public:
    QueryRunner(TrackerSparqlConnection* c, const QString& q, bool d = false)
        : connection(c), queryString(q), isDummy(d), hasRun(false)
        {
        }
    void run()
        {
            hasRun = true;
            if (isDummy)
                return;

            GError* error = 0;
            TrackerSparqlCursor* cursor =
                tracker_sparql_connection_query(connection,
                                                queryString.toUtf8(),
                                                NULL,
                                                &error);

            QVERIFY(error == 0);
            QVERIFY(cursor);

            QStringList values;
            QList<TrackerSparqlValueType> types;

            while (tracker_sparql_cursor_next(cursor, NULL, &error)) {
                gint n_columns = tracker_sparql_cursor_get_n_columns(cursor);
                for (int i = 0; i < n_columns; i++) {
                    QString value = QString::fromUtf8(
                        tracker_sparql_cursor_get_string(cursor, i, 0));
                    TrackerSparqlValueType type =
                        tracker_sparql_cursor_get_value_type(cursor, i);
                    values << value;
                    types << type;
                }
            }
            QVERIFY(values.size() > 0);
            QVERIFY(types.size() > 0);
            g_object_unref(cursor);
        }
    TrackerSparqlConnection* connection;
    QString queryString;
    bool isDummy;
    bool hasRun;
};

} // unnamed namespace

void tst_QSparqlBenchmark::queryWithLibtrackerSparqlInThread()
{
    g_type_init();
    QFETCH(QString, benchmarkName);
    benchmarkName += QString("-thread");
    QFETCH(QString, queryString);
    GError* error = 0;
    TrackerSparqlConnection* connection = tracker_sparql_connection_get(0, &error);
    QVERIFY(connection);
    QVERIFY(error == 0);

    for (int i = 0; i < 100; ++i) {
        START_BENCHMARK {
            QueryRunner runner(connection, queryString);
            runner.start();
            runner.wait();
        }
        END_BENCHMARK(benchmarkName);
    }

    g_object_unref(connection);
}

void tst_QSparqlBenchmark::queryWithLibtrackerSparqlInThread_data()
{
    queryWithLibtrackerSparql_data();
}

void tst_QSparqlBenchmark::dummyThread()
{
    QBENCHMARK {
        for (int i = 0; i < 100; ++i) {
            QueryRunner runner(0, "", true);
            runner.start();
            runner.wait();
            QVERIFY(runner.hasRun);
        }
    }
}

QTEST_MAIN(tst_QSparqlBenchmark)
#include "tst_qsparql_benchmark.moc"
<commit_msg>Minor benchmark cleanups.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the test suite of the QtSparql module (not yet part 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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <tracker-sparql.h>

#include <QtTest/QtTest>
#include <QtSparql/QtSparql>

#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>

#define BENCHMARK_DATA_FD 8

#define START_BENCHMARK \
    char tsbuf2[32]; \
    struct timeval tv2; \
    gettimeofday(&tv2, NULL); \
    long start = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; \

#define END_BENCHMARK(QSTRINGNAME) \
    gettimeofday(&tv2, NULL); \
    long end = tv2.tv_sec * 1000 + tv2.tv_usec / 1000;          \
    snprintf(tsbuf2, sizeof(tsbuf2), "%s %lu\n", qPrintable(QSTRINGNAME), end - start); \
    write(BENCHMARK_DATA_FD, tsbuf2, strlen(tsbuf2))

#define NO_QUERIES 100

class tst_QSparqlBenchmark : public QObject
{
    Q_OBJECT

public:
    tst_QSparqlBenchmark();
    virtual ~tst_QSparqlBenchmark();

public slots:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

private slots:
    // Actual benchmarks
    void queryBenchmark();
    void queryBenchmark_data();

    void dataReadingBenchmark();
    void dataReadingBenchmark_data();

    // Reference benchmarks
    void queryWithLibtrackerSparql();
    void queryWithLibtrackerSparql_data();

    void queryWithLibtrackerSparqlInThread();
    void queryWithLibtrackerSparqlInThread_data();

    void dummyThread();
};

namespace {
    // Query strings

    // Test data for running this can be found in the tracker project.
const QString artistsAndAlbumsQuery =
    "SELECT nmm:artistName(?artist) GROUP_CONCAT(nie:title(?album),'|') "
    "WHERE "
    "{ "
    "?song a nmm:MusicPiece . "
    "?song nmm:performer ?artist . "
    "?song nmm:musicAlbum ?album . "
        "} GROUP BY ?artist";

const int artistsAndAlbumsColumnCount = 2;

const QString musicQuery =
    "select ?song ?title "
    "tracker:coalesce(nmm:artistName(nmm:performer(?song)), 'UNKNOWN_ARTIST') "
    "tracker:coalesce(nie:title(nmm:musicAlbum(?song)), 'UNKNOWN_ALBUM') "
    "nfo:duration(?song) "
    "( EXISTS { ?song nao:hasTag nao:predefined-tag-favorite } ) "
    "nfo:genre(?song) nie:contentCreated(?song) "
    "tracker:id(?song) tracker:id(nmm:performer(?song)) "
    "tracker:id(nmm:musicAlbum(?song)) "
    "where { ?song a nmm:MusicPiece . "
    "?song nie:title ?title . } "
    "order by ?title "
    "<http://www.tracker-project.org/ontologies/tracker#id>(?song)";

const int musicQueryColumnCount = 11;
}

tst_QSparqlBenchmark::tst_QSparqlBenchmark()
{
}

tst_QSparqlBenchmark::~tst_QSparqlBenchmark()
{
}

void tst_QSparqlBenchmark::initTestCase()
{
    // For running the test without installing the plugins. Should work in
    // normal and vpath builds.
    QCoreApplication::addLibraryPath("../../../plugins");
}

void tst_QSparqlBenchmark::cleanupTestCase()
{
}

void tst_QSparqlBenchmark::init()
{
}

void tst_QSparqlBenchmark::cleanup()
{
}

namespace {
class ResultRetriever : public QObject
{
    Q_OBJECT
public:
    ResultRetriever(QSparqlResult* r)
    : result(r)
    {
        connect(r, SIGNAL(finished()),
                SLOT(onFinished()));
    }

public slots:
    void onFinished()
    {
        // Do something silly with the data
        int total = 0;
        while (result->next()) {
            total += result->value(0).toString().size();
        }
        result->deleteLater();
    }

private:
    QSparqlResult* result;

};

}

void tst_QSparqlBenchmark::queryBenchmark()
{
    QFETCH(QString, benchmarkName);
    QFETCH(QString, connectionName);
    QFETCH(QString, queryString);

    QSparqlQuery query(queryString);
    QSparqlConnection conn(connectionName);
    // Note: connection opening cost is left out of the benchmark. Connection
    // opening is async, so we need to wait here long enough to know that it has
    // opened (there is no signal sent or such to know it has opened).
    QTest::qWait(2000);

    QSparqlResult* r = 0;
    // We run multiple queries here (and don't leave it for QBENCHMARK to
    // run this multiple times, to be able to measure things like "how much
    // does adding a QThreadPool help".
    for (int i = 0; i < NO_QUERIES; ++i) {
        START_BENCHMARK {
            r = conn.exec(query);
            r->waitForFinished();
            QVERIFY(!r->hasError());
            QVERIFY(r->size() > 0);
            delete r;
        }
        END_BENCHMARK(benchmarkName);
    }
}

void tst_QSparqlBenchmark::queryBenchmark_data()
{
    QTest::addColumn<QString>("benchmarkName");
    QTest::addColumn<QString>("connectionName");
    QTest::addColumn<QString>("queryString");

    QTest::newRow("TrackerDBusArtistsAndAlbums")
        << "dbus-artistsandalbums"
        << "QTRACKER"
        << artistsAndAlbumsQuery;

    QTest::newRow("TrackerDirectArtistsAndAlbums")
        << "direct-artistsandalbums"
        << "QTRACKER_DIRECT"
        << artistsAndAlbumsQuery;
}

void tst_QSparqlBenchmark::dataReadingBenchmark()
{
    QFETCH(QString, benchmarkName);
    QFETCH(QString, queryString);
    QFETCH(int, columnCount);

    // Set the dataReadyInterval to be large enough so that it won't affect this
    // test case.
    QSparqlConnectionOptions opts;
    opts.setDataReadyInterval(1000000);

    QSparqlConnection conn("QTRACKER_DIRECT", opts);
    // Note: connection opening cost is left out of the benchmark. Connection
    // opening is async, so we need to wait here long enough to know that it has
    // opened (there is no signal sent or such to know it has opened).
    QTest::qWait(2000);

    QSparqlQuery query(queryString);

    QString finished = benchmarkName + "-fin";
    QString read = benchmarkName + "-read";

    QSparqlResult* r = 0;
    for (int i = 0; i < NO_QUERIES; ++i) {
        {
            START_BENCHMARK {
                r = conn.exec(query);
                QEventLoop loop;
                connect(r, SIGNAL(finished()), &loop, SLOT(quit()));
                loop.exec();
            }
            END_BENCHMARK(finished);
        }
        QVERIFY(!r->hasError());
        QVERIFY(r->size() > 0);
        {
            int size = 0;
            START_BENCHMARK {
                while (r->next()) {
                    for (int c = 0; c < columnCount; ++c) {
                        QVariant var = r->value(c);
                        // Probably it's enough not to do anything with the
                        // value; the statement of getting the value won't be
                        // optimized out since calling r->value() might have
                        // side effects.
                    }
                    ++size;
                }
            }
            END_BENCHMARK(read);
            // For verifying that enough data was really read
            // qDebug() << "No of results" << size;
        }
        delete r;
    }
}

void tst_QSparqlBenchmark::dataReadingBenchmark_data()
{
    QTest::addColumn<QString>("benchmarkName");
    QTest::addColumn<QString>("queryString");
    QTest::addColumn<int>("columnCount");

    QTest::newRow("ReadingArtistsAndAlbums")
        << "read-artistsandalbums"
        << artistsAndAlbumsQuery
        << artistsAndAlbumsColumnCount;

    QTest::newRow("ReadingMusic")
        << "read-music"
        << musicQuery
        << musicQueryColumnCount;
}

void tst_QSparqlBenchmark::queryWithLibtrackerSparql()
{
    g_type_init();
    QFETCH(QString, benchmarkName);
    QFETCH(QString, queryString);
    GError* error = 0;
    TrackerSparqlConnection* connection = tracker_sparql_connection_get(0, &error);
    QVERIFY(connection);
    QVERIFY(error == 0);

    for (int i = 0; i < NO_QUERIES; ++i) {
        START_BENCHMARK {
            TrackerSparqlCursor* cursor =
                tracker_sparql_connection_query(connection,
                                                queryString.toUtf8(),
                                                NULL,
                                                &error);

            QVERIFY(error == 0);
            QVERIFY(cursor);

            QStringList values;
            QList<TrackerSparqlValueType> types;
            while (tracker_sparql_cursor_next (cursor, NULL, &error)) {
                gint n_columns = tracker_sparql_cursor_get_n_columns(cursor);
                for (int i = 0; i < n_columns; i++) {
                    QString value = QString::fromUtf8(
                        tracker_sparql_cursor_get_string(cursor, i, 0));
                    TrackerSparqlValueType type =
                        tracker_sparql_cursor_get_value_type(cursor, i);
                    values << value;
                    types << type;
                }
            }
            QVERIFY(values.size() > 0);
            QVERIFY(types.size() > 0);

            g_object_unref(cursor);
        }
        END_BENCHMARK(benchmarkName);
    }

    g_object_unref(connection);
}

void tst_QSparqlBenchmark::queryWithLibtrackerSparql_data()
{
    QTest::addColumn<QString>("benchmarkName");
    QTest::addColumn<QString>("queryString");

    QTest::newRow("LibtrackerSparqlArtistsAndAlbums")
        << "lts-artistsandalbums"
        << artistsAndAlbumsQuery;

    QTest::newRow("LibtrackersparqlMusic")
        << "lts-music"
        << musicQuery;
}

namespace {
class QueryRunner : public QThread
{
public:
    QueryRunner(TrackerSparqlConnection* c, const QString& q, bool d = false)
        : connection(c), queryString(q), isDummy(d), hasRun(false)
        {
        }
    void run()
        {
            hasRun = true;
            if (isDummy)
                return;

            GError* error = 0;
            TrackerSparqlCursor* cursor =
                tracker_sparql_connection_query(connection,
                                                queryString.toUtf8(),
                                                NULL,
                                                &error);

            QVERIFY(error == 0);
            QVERIFY(cursor);

            QStringList values;
            QList<TrackerSparqlValueType> types;

            while (tracker_sparql_cursor_next(cursor, NULL, &error)) {
                gint n_columns = tracker_sparql_cursor_get_n_columns(cursor);
                for (int i = 0; i < n_columns; i++) {
                    QString value = QString::fromUtf8(
                        tracker_sparql_cursor_get_string(cursor, i, 0));
                    TrackerSparqlValueType type =
                        tracker_sparql_cursor_get_value_type(cursor, i);
                    values << value;
                    types << type;
                }
            }
            QVERIFY(values.size() > 0);
            QVERIFY(types.size() > 0);
            g_object_unref(cursor);
        }
    TrackerSparqlConnection* connection;
    QString queryString;
    bool isDummy;
    bool hasRun;
};

} // unnamed namespace

void tst_QSparqlBenchmark::queryWithLibtrackerSparqlInThread()
{
    g_type_init();
    QFETCH(QString, benchmarkName);
    benchmarkName += QString("-thread");
    QFETCH(QString, queryString);
    GError* error = 0;
    TrackerSparqlConnection* connection = tracker_sparql_connection_get(0, &error);
    QVERIFY(connection);
    QVERIFY(error == 0);

    for (int i = 0; i < NO_QUERIES; ++i) {
        START_BENCHMARK {
            QueryRunner runner(connection, queryString);
            runner.start();
            runner.wait();
        }
        END_BENCHMARK(benchmarkName);
    }

    g_object_unref(connection);
}

void tst_QSparqlBenchmark::queryWithLibtrackerSparqlInThread_data()
{
    queryWithLibtrackerSparql_data();
}

void tst_QSparqlBenchmark::dummyThread()
{
    QBENCHMARK {
        for (int i = 0; i < NO_QUERIES; ++i) {
            QueryRunner runner(0, "", true);
            runner.start();
            runner.wait();
            QVERIFY(runner.hasRun);
        }
    }
}

QTEST_MAIN(tst_QSparqlBenchmark)
#include "tst_qsparql_benchmark.moc"
<|endoftext|>


<commit_before>#include "testing/testing.hpp"

#include "integration_tests/routing_test_tools.hpp"

#include "../indexer/mercator.hpp"

using namespace routing;

UNIT_TEST(Zgrad424aTo1207)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9963, 37.2036), {0., 0.},
      MercatorBounds::FromLatLon(55.9955, 37.1948), 683.);
}

UNIT_TEST(Zgrad924aTo418)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9844, 37.1808), {0., 0.},
      MercatorBounds::FromLatLon(55.9999, 37.2021), 2526.);
}

UNIT_TEST(Zgrad924aToFilaretovskyChurch)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9844, 37.1808), {0., 0.},
      MercatorBounds::FromLatLon(55.9915, 37.1808), 1220.);
}

UNIT_TEST(Zgrad924aTo1145)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9844, 37.1808), {0., 0.},
      MercatorBounds::FromLatLon(55.9924, 37.1853), 1400.);
}

UNIT_TEST(MoscowMuzeonToLebedinoeOzeroGorkyPark)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.7348, 37.606), {0., 0.},
      MercatorBounds::FromLatLon(55.724, 37.5956), 1617.);
}

// Uncomment tests below when PedestrianModel will be improved
/*

UNIT_TEST(Zgrad315parkingToMusicSchoolBus_BadRoute)
{
  // Bad route:
  // route goes through a highway-tertiary.

  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9996, 37.2174), {0., 0.},
      MercatorBounds::FromLatLon(55.9999, 37.2179), 161.);
}

UNIT_TEST(Zgrad924aToKrukovo_BadRoute)
{
  // Bad route:
  // route goes through a highway-primary.

  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9844, 37.1808), {0., 0.},
      MercatorBounds::FromLatLon(55.9802, 37.1736), 0.);
}

UNIT_TEST(MoscowMailRuStarbucksToPetrovskoRazumovskyAlley_BadRoute)
{
  // Bad route:
  // route goes through a highway-tertiary although an available pedestrian road.

  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.7971, 37.5376), {0., 0.},
      MercatorBounds::FromLatLon(55.7953, 37.5597), 0.);
}

*/

UNIT_TEST(AustraliaMelburn_AvoidMotorway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(-37.7936, 144.985), {0., 0.},
      MercatorBounds::FromLatLon(-37.7896, 145.025), 5015.);
}

UNIT_TEST(AustriaWein_AvoidTrunk)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(48.233, 16.3562), {0., 0.},
      MercatorBounds::FromLatLon(48.2458, 16.3704), 2627.);
}

UNIT_TEST(FranceParis_AvoidBridleway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(48.859, 2.25452), {0., 0.},
      MercatorBounds::FromLatLon(48.8634, 2.24315), 1307.);
}

UNIT_TEST(GermanyBerlin_AvoidCycleway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(52.5459, 13.3952), {0., 0.},
      MercatorBounds::FromLatLon(52.5413, 13.3989), 1008.);
}

UNIT_TEST(HungaryBudapest_AvoidMotorway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.5535, 19.1321), {0., 0.},
      MercatorBounds::FromLatLon(47.595, 19.2235), 13265.);
}

UNIT_TEST(PolandWarshaw_AvoidCycleway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(52.2487, 21.0173), {0., 0.},
      MercatorBounds::FromLatLon(52.25, 21.0164), 372.);
}
<commit_msg>Added integration tests<commit_after>#include "testing/testing.hpp"

#include "integration_tests/routing_test_tools.hpp"

#include "../indexer/mercator.hpp"

using namespace routing;

UNIT_TEST(Zgrad424aTo1207)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9963, 37.2036), {0., 0.},
      MercatorBounds::FromLatLon(55.9955, 37.1948), 683.);
}

UNIT_TEST(Zgrad924aTo418)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9844, 37.1808), {0., 0.},
      MercatorBounds::FromLatLon(55.9999, 37.2021), 2526.);
}

UNIT_TEST(Zgrad924aToFilaretovskyChurch)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9844, 37.1808), {0., 0.},
      MercatorBounds::FromLatLon(55.9915, 37.1808), 1220.);
}

UNIT_TEST(Zgrad924aTo1145)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9844, 37.1808), {0., 0.},
      MercatorBounds::FromLatLon(55.9924, 37.1853), 1400.);
}

UNIT_TEST(MoscowMuzeonToLebedinoeOzeroGorkyPark)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.7348, 37.606), {0., 0.},
      MercatorBounds::FromLatLon(55.724, 37.5956), 1617.);
}

/*
UNIT_TEST(Zgrad315parkingToMusicSchoolBus_BadRoute)
{
  // Bad route:
  // route goes through a highway-tertiary.

  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9996, 37.2174), {0., 0.},
      MercatorBounds::FromLatLon(55.9999, 37.2179), 161.);
}
*/

UNIT_TEST(Zgrad924aToKrukovo)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.9844, 37.1808), {0., 0.},
      MercatorBounds::FromLatLon(55.9802, 37.1736), 974.);
}

UNIT_TEST(MoscowMailRuStarbucksToPetrovskoRazumovskyAlley)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.7971, 37.5376), {0., 0.},
      MercatorBounds::FromLatLon(55.7953, 37.5597), 1840.);
}

UNIT_TEST(AustraliaMelburn_AvoidMotorway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(-37.7936, 144.985), {0., 0.},
      MercatorBounds::FromLatLon(-37.7896, 145.025), 5015.);
}

UNIT_TEST(AustriaWein_AvoidTrunk)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(48.233, 16.3562), {0., 0.},
      MercatorBounds::FromLatLon(48.2458, 16.3704), 2145.);
}

UNIT_TEST(FranceParis_AvoidBridleway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(48.859, 2.25452), {0., 0.},
      MercatorBounds::FromLatLon(48.8634, 2.24315), 1307.);
}

UNIT_TEST(HungaryBudapest_AvoidMotorway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.56566, 19.14942), {0., 0.},
      MercatorBounds::FromLatLon(47.593, 19.24018), 10890.);
}

UNIT_TEST(PolandWarshaw_AvoidCycleway)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(52.2487, 21.0173), {0., 0.},
      MercatorBounds::FromLatLon(52.25, 21.0164), 372.);
}

UNIT_TEST(SwedenStockholmSlussenHiltonToMaritimeMuseum)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.32046, 18.06924), {0., 0.},
      MercatorBounds::FromLatLon(59.32728, 18.09078), 3442.);
}

UNIT_TEST(SwedenStockholmSlussenHiltonToAfChapmanHostel)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.32045, 18.06928), {0., 0.},
      MercatorBounds::FromLatLon(59.3254, 18.08022), 2155.);
}

UNIT_TEST(EstoniaTallinnRadissonHiltonToCatherdalChurch)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.4362, 24.7682), {0., 0.},
      MercatorBounds::FromLatLon(59.437, 24.7392), 2016.);
}

UNIT_TEST(EstoniaTallinnRadissonHiltonToSkypeOffice)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.4362, 24.7682), {0., 0.},
      MercatorBounds::FromLatLon(59.3971, 24.661), 8673.);
}

// Following tests cause assertion violations when
// Belarus.mwm and minsk-pass.mwm are overlapped.
// Uncomment these tests as soon as bug will be fixed.
/*
UNIT_TEST(BelarusMinksHotelYubileyniToChurchSaintsSimonAndHelen)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(53.9112, 27.5466), {0., 0.},
      MercatorBounds::FromLatLon(53.8965, 27.5476), 2244.);
}

UNIT_TEST(BelarusMinksBarURatushiToMoscowBusStation)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(53.9045, 27.5569), {0., 0.},
      MercatorBounds::FromLatLon(53.889, 27.5466), 2499.);
}
*/

UNIT_TEST(BelarusBobruisk50LetVlksmToSanatoryShinnik)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(53.1638, 29.1804), {0., 0.},
      MercatorBounds::FromLatLon(53.179, 29.1682), 2661.);
}

UNIT_TEST(BelarusBobruisk50LetVlksmToArena)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(53.1638, 29.1804), {0., 0.},
      MercatorBounds::FromLatLon(53.1424, 29.2467), 6683.);
}

UNIT_TEST(RussiaTaganrogSyzranov10k3ToSoftech)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.2183, 38.8634), {0., 0.},
      MercatorBounds::FromLatLon(47.2, 38.8878), 3868.);
}

UNIT_TEST(RussiaTaganrogSyzranov10k3ToTruseE)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.2183, 38.8634), {0., 0.},
      MercatorBounds::FromLatLon(47.2048, 38.9441), 7463.);
}

UNIT_TEST(RussiaTaganrogSyzranov10k3ToLazo5k2)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.2183, 38.8634), {0., 0.},
      MercatorBounds::FromLatLon(47.2584, 38.9128), 8520.);
}

UNIT_TEST(RussiaTaganrogJukova2ToBolBulvarnaya8)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.2768, 38.9282), {0., 0.},
      MercatorBounds::FromLatLon(47.2412, 38.8902), 6239.);
}

UNIT_TEST(RussiaTaganrogCheckhova267k2ToKotlostroy33)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.2198, 38.8906), {0., 0.},
      MercatorBounds::FromLatLon(47.2459, 38.8937), 3798.);
}

UNIT_TEST(RussiaTaganrogCheckhova267k2ToBolBulvarnaya8)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.2198, 38.8906), {0., 0.},
      MercatorBounds::FromLatLon(47.2412, 38.8902), 2897.);
}

UNIT_TEST(RussiaRostovOnDonPrKosmonavtovToDneprovsky120b)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(47.2811, 39.7178), {0., 0.},
      MercatorBounds::FromLatLon(47.2875, 39.759), 4600.);
}

UNIT_TEST(TurkeyKemerPalmetResortToYachtClub)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(36.6143, 30.5572), {0., 0.},
      MercatorBounds::FromLatLon(36.6004, 30.576), 2992.);
}

UNIT_TEST(CzechPragueNode5ToHilton)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(50.0653, 14.4031), {0., 0.},
      MercatorBounds::FromLatLon(50.0933, 14.4397), 5106.);
}

UNIT_TEST(CzechPragueHiltonToKarlovMost)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(50.0933, 14.4397), {0., 0.},
      MercatorBounds::FromLatLon(50.0864, 14.4124), 2398.);
}

UNIT_TEST(CzechPragueHiltonToNicholasChurch)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(50.0933, 14.4397), {0., 0.},
      MercatorBounds::FromLatLon(50.088, 14.4032), 3103.);
}

UNIT_TEST(CzechPragueHiltonToKvetniceViewpoint)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(50.0933, 14.4397), {0., 0.},
      MercatorBounds::FromLatLon(50.0806, 14.3973), 4335.);
}

UNIT_TEST(RussiaSaintPetersburgMoyka93ToAlexanderColumn)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.9241, 30.323), {0., 0.},
      MercatorBounds::FromLatLon(59.939, 30.3159), 2454.);
}

UNIT_TEST(RussiaSaintPetersburgMoyka93ToMarsovoPole)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.9241, 30.323), {0., 0.},
      MercatorBounds::FromLatLon(59.9436, 30.3318), 2891.);
}

UNIT_TEST(RussiaSaintPetersburgMoyka93ToAvrora)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.9241, 30.323), {0., 0.},
      MercatorBounds::FromLatLon(59.9554, 30.3378), 4770.);
}

UNIT_TEST(RussiaSaintPetersburgPetrPaulChurchToDolphins)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.9502, 30.3165), {0., 0.},
      MercatorBounds::FromLatLon(59.973, 30.2702), 4507.);
}

UNIT_TEST(RussiaPetergofEntranceToErmitagePalace)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.8806, 29.904), {0., 0.},
      MercatorBounds::FromLatLon(59.8889, 29.9034), 1073.);
}

UNIT_TEST(RussiaPetergofMarlyPalaceToTrainStation)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(59.8887, 29.8963), {0., 0.},
      MercatorBounds::FromLatLon(59.8648, 29.9251), 3885.);
}

UNIT_TEST(RussiaMoscowMailRuToTsarCannon)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.79703, 37.53761), {0., 0.},
      MercatorBounds::FromLatLon(55.75146, 37.61792), 7989.);
}

UNIT_TEST(RussiaMoscowHovrinoStationToKasperskyLab)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(55.8701, 37.50833), {0., 0.},
      MercatorBounds::FromLatLon(55.83715, 37.48132), 5162.);
}

UNIT_TEST(ItalyRome_WalkOverStreetWithSidewalkBoth)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(41.9052, 12.4106), {0., 0.},
      MercatorBounds::FromLatLon(41.9226, 12.4216), 2413.);
}

UNIT_TEST(USARedlandsEsriHQToRedlandsCommunity)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(34.0556, -117.19567), {0., 0.},
      MercatorBounds::FromLatLon(34.03682, -117.20649), 3330.);
}

UNIT_TEST(USANewYorkEmpireStateBuildingToUnitedNations)
{
  integration::CalculateRouteAndTestRouteLength(
      integration::GetPedestrianComponents(),
      MercatorBounds::FromLatLon(40.74844, -73.98566), {0., 0.},
      MercatorBounds::FromLatLon(40.75047, -73.96759), 2265.);
}
<|endoftext|>