<commit_before>/*  Copyright (C) 2009  Adenilson Cavalcanti <savagobr@yahoo.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; by version 2 of the License or (at your
 *  choice) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "gcalresource.h"
#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>
#include <kabc/key.h>
#include <kabc/errorhandler.h>
#include <kcal/event.h>
#include <qstring.h>
#include <KWindowSystem>
#include <akonadi/changerecorder.h>
#include <akonadi/itemfetchscope.h>
#include <KUrl>

extern "C" {
#include <gcalendar.h>
#include <gcal_status.h>
}

using namespace Akonadi;

GCalResource::GCalResource( const QString &id )
	: ResourceBase(id)
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject(
		QLatin1String( "/Settings" ), Settings::self(),
		QDBusConnection::ExportAdaptors );

	changeRecorder()->itemFetchScope().fetchFullPayload();

    if (!(gcal = gcal_new(GCALENDAR)))
		exit(1);
    gcal_set_store_xml(gcal, 1);
    all_events.length = 0;
    all_events.entries = NULL;
}

GCalResource::~GCalResource()
{
    gcal_cleanup_events(&all_events);
    pending.clear();
    deleted.clear();
}

void GCalResource::retrieveTimestamp(QString &timestamp)
{
	timestamp = Settings::self()->timestamp();
}

void GCalResource::saveTimestamp(QString &timestamp)
{
    Settings::self()->setTimestamp(timestamp);
    Settings::self()->writeConfig();
}

void GCalResource::retrieveCollections()
{
    if(!authenticated) {
		kError() << "No authentication for Google Calendar available";
                const QString message = i18nc("@info: status",
					      "Not yet authenticated for "
					      "use of Google Calendar");

        emit error(message);

        emit status(Broken, message);
        return;
    }

    Collection c;
    c.setParent(Collection::root());
    c.setRemoteId("google-calendar");
    c.setName(name());

    QStringList mimeTypes;
    mimeTypes << "text/calendar";
    c.setContentMimeTypes(mimeTypes);

    Collection::List list;
    list << c;
    collectionsRetrieved(list);
}

void GCalResource::retrieveItems( const Akonadi::Collection &collection )
{
    Q_UNUSED(collection);
    Item::List items;
    int result;
	gcal_event_t event;
	QString timestamp;
	QByteArray t_byte;

	kError() << "\n............. retrieveItems ...........\n";
	if (!authenticated) {
		kError() << "No authentication for Google calendar available";
		const QString message = i18nc("@info:status",
					      "Not yet authenticated for"
					      " use of Google calendar");
		emit error(message);
		emit status(Broken, message);
		return;
	}

	/* Query by updated */
	retrieveTimestamp(timestamp);
	t_byte = timestamp.toLocal8Bit();
	if (t_byte.length() > TIMESTAMP_SIZE) {
		//TODO: implement getUpdated
		//result = getUpdated(t_byte.data());
		return;
	}
	kError() << "First retrieve";

	if ((result = gcal_get_events(gcal, &all_events)))
		exit(1);

	/* GCalendar returns last updated entry as first element */
	event = gcal_event_element(&all_events, 0);
	if (!event) {
		kError() << "Failed to retrieve last updated event.";
		const QString message = i18nc("@info:status",
					      "Failed getting last updated"
					      " event");
		emit error(message);
		emit status(Broken, message);
		return;

	}

	timestamp = gcal_event_get_updated(event);
	saveTimestamp(timestamp);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_events.length; ++i) {
		Item item(QLatin1String("text/calendar"));
		KCal::Event kevent;
		QString temp;
		event = gcal_event_element(&all_events, i);

		temp = gcal_event_get_title(event);
		kevent.setSummary(temp);

		temp = gcal_event_get_where(event);
		kevent.setLocation(temp);

		temp = gcal_event_get_status(event);
		KCal::Incidence::Status status;
		if (gcal_event_is_deleted(event))
			status = KCal::Incidence::StatusCanceled;
		else
			status = KCal::Incidence::StatusConfirmed;
		kevent.setStatus(status);

		temp = gcal_event_get_content(event);
		kevent.setDescription(temp);

		temp = gcal_event_get_start(event);
		temp = gcal_event_get_end(event);
		//TODO: create a KDateTime
		//kevent.set

	}
}

bool GCalResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
	return true;
}

void GCalResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void GCalResource::doSetOnline(bool online)
{
	Q_UNUSED(online);
}

int GCalResource::getUpdated(char *timestamp)
{
	Q_UNUSED(timestamp);

	return -1;
}

void GCalResource::configure( WId windowId )
{
	Q_UNUSED(windowId);

}

void GCalResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{
	Q_UNUSED(collection);
	Q_UNUSED(item);
}

void GCalResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
}

void GCalResource::itemRemoved( const Akonadi::Item &item )
{
	Q_UNUSED(item);
}

AKONADI_RESOURCE_MAIN( GCalResource )

#include "gcalresource.moc"
<commit_msg>Setting event duration (not happy with current code).<commit_after>/*  Copyright (C) 2009  Adenilson Cavalcanti <savagobr@yahoo.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; by version 2 of the License or (at your
 *  choice) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "gcalresource.h"
#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <QDate>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>
#include <kabc/key.h>
#include <kabc/errorhandler.h>
#include <kcal/event.h>
#include <kdatetime.h>
#include <qstring.h>
#include <KWindowSystem>
#include <akonadi/changerecorder.h>
#include <akonadi/itemfetchscope.h>
#include <KUrl>

extern "C" {
#include <gcalendar.h>
#include <gcal_status.h>
}

using namespace Akonadi;

GCalResource::GCalResource( const QString &id )
	: ResourceBase(id)
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject(
		QLatin1String( "/Settings" ), Settings::self(),
		QDBusConnection::ExportAdaptors );

	changeRecorder()->itemFetchScope().fetchFullPayload();

    if (!(gcal = gcal_new(GCALENDAR)))
		exit(1);
    gcal_set_store_xml(gcal, 1);
    all_events.length = 0;
    all_events.entries = NULL;
}

GCalResource::~GCalResource()
{
    gcal_cleanup_events(&all_events);
    pending.clear();
    deleted.clear();
}

void GCalResource::retrieveTimestamp(QString &timestamp)
{
	timestamp = Settings::self()->timestamp();
}

void GCalResource::saveTimestamp(QString &timestamp)
{
    Settings::self()->setTimestamp(timestamp);
    Settings::self()->writeConfig();
}

void GCalResource::retrieveCollections()
{
    if(!authenticated) {
		kError() << "No authentication for Google Calendar available";
                const QString message = i18nc("@info: status",
					      "Not yet authenticated for "
					      "use of Google Calendar");

        emit error(message);

        emit status(Broken, message);
        return;
    }

    Collection c;
    c.setParent(Collection::root());
    c.setRemoteId("google-calendar");
    c.setName(name());

    QStringList mimeTypes;
    mimeTypes << "text/calendar";
    c.setContentMimeTypes(mimeTypes);

    Collection::List list;
    list << c;
    collectionsRetrieved(list);
}

void GCalResource::retrieveItems( const Akonadi::Collection &collection )
{
    Q_UNUSED(collection);
    Item::List items;
    int result;
	gcal_event_t event;
	QString timestamp;
	QByteArray t_byte;

	kError() << "\n............. retrieveItems ...........\n";
	if (!authenticated) {
		kError() << "No authentication for Google calendar available";
		const QString message = i18nc("@info:status",
					      "Not yet authenticated for"
					      " use of Google calendar");
		emit error(message);
		emit status(Broken, message);
		return;
	}

	/* Query by updated */
	retrieveTimestamp(timestamp);
	t_byte = timestamp.toLocal8Bit();
	if (t_byte.length() > TIMESTAMP_SIZE) {
		//TODO: implement getUpdated
		//result = getUpdated(t_byte.data());
		return;
	}
	kError() << "First retrieve";

	if ((result = gcal_get_events(gcal, &all_events)))
		exit(1);

	/* GCalendar returns last updated entry as first element */
	event = gcal_event_element(&all_events, 0);
	if (!event) {
		kError() << "Failed to retrieve last updated event.";
		const QString message = i18nc("@info:status",
					      "Failed getting last updated"
					      " event");
		emit error(message);
		emit status(Broken, message);
		return;

	}

	timestamp = gcal_event_get_updated(event);
	saveTimestamp(timestamp);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_events.length; ++i) {
		Item item(QLatin1String("text/calendar"));
		KCal::Event kevent;
		QString temp;
		event = gcal_event_element(&all_events, i);

		temp = gcal_event_get_title(event);
		kevent.setSummary(temp);

		temp = gcal_event_get_where(event);
		kevent.setLocation(temp);

		temp = gcal_event_get_status(event);
		KCal::Incidence::Status status;
		if (gcal_event_is_deleted(event))
			status = KCal::Incidence::StatusCanceled;
		else
			status = KCal::Incidence::StatusConfirmed;
		kevent.setStatus(status);

		temp = gcal_event_get_content(event);
		kevent.setDescription(temp);

		/* TODO: there must exit an easier way */
		QDate start, end;
		temp = gcal_event_get_start(event);
		start.fromString(temp, Qt::ISODate);
		temp = gcal_event_get_end(event);
		end.fromString(temp, Qt::ISODate);
		KDateTime time_start(start), time_end(end);
		kevent.setDtStart(time_start);
		kevent.setDtEnd(time_end);

	}
}

bool GCalResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
	return true;
}

void GCalResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void GCalResource::doSetOnline(bool online)
{
	Q_UNUSED(online);
}

int GCalResource::getUpdated(char *timestamp)
{
	Q_UNUSED(timestamp);

	return -1;
}

void GCalResource::configure( WId windowId )
{
	Q_UNUSED(windowId);

}

void GCalResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{
	Q_UNUSED(collection);
	Q_UNUSED(item);
}

void GCalResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED(parts);
	Q_UNUSED(item);
}

void GCalResource::itemRemoved( const Akonadi::Item &item )
{
	Q_UNUSED(item);
}

AKONADI_RESOURCE_MAIN( GCalResource )

#include "gcalresource.moc"
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_OPERATORS_BASE_HH
#define DUNE_GDT_OPERATORS_BASE_HH

#include <dune/stuff/la/solver.hh>

#include "interfaces.hh"

namespace Dune {
namespace GDT {
namespace Operators {

template< class Traits >
class MatrixBased
  : public AssemblableOperatorInterface< Traits >
{
  typedef AssemblableOperatorInterface< Traits > BaseType;
public:
  using typename BaseType::GridViewType;
  using typename BaseType::SourceSpaceType;
  using typename BaseType::RangeSpaceType;
  using typename BaseType::MatrixType;
private:
  typedef Stuff::LA::Solver< MatrixType > LinearSolverType;

public:
  MatrixBased(MatrixType& matrix,
              const SourceSpaceType& source_space,
              const RangeSpaceType& range_space,
              const GridViewType& grid_view)
    : matrix_(matrix)
    , source_space_(source_space)
    , range_space_(range_space)
    , grid_view_(grid_view)
    , assembled_(false)
  {}

  MatrixBased(MatrixType& matrix, const SourceSpaceType& source_space, const RangeSpaceType& range_space)
    : matrix_(matrix)
    , source_space_(source_space)
    , range_space_(range_space)
    , grid_view_(*(source_space_.grid_view()))
    , assembled_(false)
  {}

  MatrixBased(MatrixType& matrix, const SourceSpaceType& source_space)
    : matrix_(matrix)
    , source_space_(source_space)
    , range_space_(source_space_)
    , grid_view_(*(source_space_.grid_view()))
    , assembled_(false)
  {}

  const GridViewType& grid_view() const
  {
    return grid_view_;
  }

  const RangeSpaceType& range_space() const
  {
    return range_space_;
  }

  const SourceSpaceType& source_space() const
  {
    return source_space_;
  }

  MatrixType& matrix()
  {
    return matrix_;
  }

  const MatrixType& matrix() const
  {
    return matrix_;
  }

  virtual void assemble() = 0;

  template< class S, class R >
  void apply(const Stuff::LA::VectorInterface< S >& source, Stuff::LA::VectorInterface< R >& range)
  {
    assemble();
    matrix_.mv(source.as_imp(), range.as_imp());
  } // ... apply(...)

  static std::vector< std::string > invert_options()
  {
    return LinearSolverType::options();
  }

  static Stuff::Common::ConfigTree invert_options(const std::string& type)
  {
    return LinearSolverType::options(type);
  }

  template< class R, class S >
  void apply_inverse(const Stuff::LA::VectorInterface< R >& range,
                     Stuff::LA::VectorInterface< S >& source,
                     const Stuff::Common::ConfigTree& opts)
  {
    assemble();
    LinearSolverType(matrix).apply(range.as_imp(), source.as_imp(), opts);
  } // ... apply_inverse(...)

private:
  MatrixType& matrix_;
  const SourceSpaceType& source_space_;
  const RangeSpaceType& range_space_;
  const GridViewType& grid_view_;
  bool assembled_;
}; // class MatrixBased

} // namespace Operators
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_OPERATORS_BASE_HH
<commit_msg>[operators.base] added missing vortial dtor<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_OPERATORS_BASE_HH
#define DUNE_GDT_OPERATORS_BASE_HH

#include <dune/stuff/la/solver.hh>

#include "interfaces.hh"

namespace Dune {
namespace GDT {
namespace Operators {

template< class Traits >
class MatrixBased
  : public AssemblableOperatorInterface< Traits >
{
  typedef AssemblableOperatorInterface< Traits > BaseType;
public:
  using typename BaseType::GridViewType;
  using typename BaseType::SourceSpaceType;
  using typename BaseType::RangeSpaceType;
  using typename BaseType::MatrixType;
private:
  typedef Stuff::LA::Solver< MatrixType > LinearSolverType;

public:
  MatrixBased(MatrixType& matrix,
              const SourceSpaceType& source_space,
              const RangeSpaceType& range_space,
              const GridViewType& grid_view)
    : matrix_(matrix)
    , source_space_(source_space)
    , range_space_(range_space)
    , grid_view_(grid_view)
    , assembled_(false)
  {}

  MatrixBased(MatrixType& matrix, const SourceSpaceType& source_space, const RangeSpaceType& range_space)
    : matrix_(matrix)
    , source_space_(source_space)
    , range_space_(range_space)
    , grid_view_(*(source_space_.grid_view()))
    , assembled_(false)
  {}

  MatrixBased(MatrixType& matrix, const SourceSpaceType& source_space)
    : matrix_(matrix)
    , source_space_(source_space)
    , range_space_(source_space_)
    , grid_view_(*(source_space_.grid_view()))
    , assembled_(false)
  {}

  virtual ~MatrixBased() {}

  const GridViewType& grid_view() const
  {
    return grid_view_;
  }

  const RangeSpaceType& range_space() const
  {
    return range_space_;
  }

  const SourceSpaceType& source_space() const
  {
    return source_space_;
  }

  MatrixType& matrix()
  {
    return matrix_;
  }

  const MatrixType& matrix() const
  {
    return matrix_;
  }

  virtual void assemble() = 0;

  template< class S, class R >
  void apply(const Stuff::LA::VectorInterface< S >& source, Stuff::LA::VectorInterface< R >& range)
  {
    assemble();
    matrix_.mv(source.as_imp(), range.as_imp());
  } // ... apply(...)

  static std::vector< std::string > invert_options()
  {
    return LinearSolverType::options();
  }

  static Stuff::Common::ConfigTree invert_options(const std::string& type)
  {
    return LinearSolverType::options(type);
  }

  template< class R, class S >
  void apply_inverse(const Stuff::LA::VectorInterface< R >& range,
                     Stuff::LA::VectorInterface< S >& source,
                     const Stuff::Common::ConfigTree& opts)
  {
    assemble();
    LinearSolverType(matrix).apply(range.as_imp(), source.as_imp(), opts);
  } // ... apply_inverse(...)

private:
  MatrixType& matrix_;
  const SourceSpaceType& source_space_;
  const RangeSpaceType& range_space_;
  const GridViewType& grid_view_;
  bool assembled_;
}; // class MatrixBased

} // namespace Operators
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_OPERATORS_BASE_HH
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/password_manager/password_form_data.h"
#include "chrome/test/live_sync/live_passwords_sync_test.h"

using webkit_glue::PasswordForm;

IN_PROC_BROWSER_TEST_F(MultipleClientLivePasswordsSyncTest, Sanity) {
  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";

  for (int i = 0; i < num_clients(); ++i) {
    PasswordForm form = CreateTestPasswordForm(i);
    AddLogin(GetPasswordStore(i), form);
  }
  ASSERT_TRUE(AwaitQuiescence());

  std::vector<PasswordForm> forms0;
  GetLogins(GetPasswordStore(0), forms0);
  ASSERT_EQ((size_t) num_clients(), forms0.size());

  for (int i = 1; i < num_clients(); ++i) {
    std::vector<PasswordForm> forms;
    GetLogins(GetPasswordStore(i), forms);
    ASSERT_TRUE(ContainsSamePasswordForms(forms0, forms));
  }
}
<commit_msg>Marking MultipleClientLivePasswordsSyncTest.Sanity as failing<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/password_manager/password_form_data.h"
#include "chrome/test/live_sync/live_passwords_sync_test.h"

using webkit_glue::PasswordForm;

// TODO(rsimha): This test fails intermittently -- see http://crbug.com/77993.
IN_PROC_BROWSER_TEST_F(MultipleClientLivePasswordsSyncTest, FAILS_Sanity) {
  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";

  for (int i = 0; i < num_clients(); ++i) {
    PasswordForm form = CreateTestPasswordForm(i);
    AddLogin(GetPasswordStore(i), form);
  }
  ASSERT_TRUE(AwaitQuiescence());

  std::vector<PasswordForm> forms0;
  GetLogins(GetPasswordStore(0), forms0);
  ASSERT_EQ((size_t) num_clients(), forms0.size());

  for (int i = 1; i < num_clients(); ++i) {
    std::vector<PasswordForm> forms;
    GetLogins(GetPasswordStore(i), forms);
    ASSERT_TRUE(ContainsSamePasswordForms(forms0, forms));
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- c-modules used -----------------------------------------------------------

//--- standard modules used ----------------------------------------------------
#include "Anything.h"
#include "Dbg.h"

//--- test modules used --------------------------------------------------------
#include "TestSuite.h"

//--- module under test --------------------------------------------------------

//--- interface include --------------------------------------------------------
#include "LDAPDAICachePolicyTest.h"
#include "LDAPDAICachePolicyModule.h"
#include "System.h"
#include "StringStream.h"
#include "Application.h"
#include "Threads.h"

//---- LDAPDAICachePolicyTest ----------------------------------------------------------------
LDAPDAICachePolicyTest::LDAPDAICachePolicyTest(TString name) : TestCase(name)
{
	StartTrace(LDAPDAICachePolicyTest.Ctor);
}

LDAPDAICachePolicyTest::~LDAPDAICachePolicyTest()
{
	StartTrace(LDAPDAICachePolicyTest.Dtor);
}

// setup for this TestCase
void LDAPDAICachePolicyTest::setUp ()
{
	StartTrace(LDAPDAICachePolicyTest.setUp);
	t_assert(System::LoadConfigFile(fGlobalConfig, "Config"));
	t_assert(fGlobalConfig.IsDefined("Modules"));
	Application::InitializeGlobalConfig(fGlobalConfig);
	assertEqualm(0, WDModule::Install(fGlobalConfig), "WDModule::Install should have worked.");
}

void LDAPDAICachePolicyTest::setUp (const String &configName)
{
	StartTrace(LDAPDAICachePolicyTest.setUp);
	t_assert(System::LoadConfigFile(fGlobalConfig, configName));
	TraceAny(fGlobalConfig, "Global Config");
	t_assert(fGlobalConfig.IsDefined("Modules"));
	Application::InitializeGlobalConfig(fGlobalConfig);
	// Will fail because of NoDataDA and LdapCachePolicyModule return
	// code check is mandatory
	assertEqualm(-1, WDModule::Install(fGlobalConfig), "WDModule::Install should have failed.");
}

void LDAPDAICachePolicyTest::tearDown ()
{
	StartTrace(LDAPDAICachePolicyTest.tearDown);
	t_assert(fGlobalConfig.IsDefined("Modules"));
	WDModule::Terminate(fGlobalConfig);
}

void LDAPDAICachePolicyTest::NoDataReadTest()
{
	StartTrace(LDAPDAICachePolicyTest.NoDataReadTest);
	setUp();
	tearDown();
	setUp(String("NoDataQueryConfig"));
	// re-install "good" config
	tearDown();
	setUp();
}

void LDAPDAICachePolicyTest::ReInitTest()
{
	StartTrace(LDAPDAICachePolicyTest.ReInitTest);
	for (int i = 0; i < 5; i++) {
		ROAnything result;
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA1", ":0.name"));
		assertEqualm("ifs APPL. User Directory", result.AsString(), "Reset test failed.");
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA2", ":0.pd-dn"));
		assertEqualm("cn=CH10601-tkgae,dc=tkfpd.hsr.ch", result.AsString(), "Reset test failed.");
		assertEqualm(0, WDModule::Reset(fGlobalConfig, fGlobalConfig), "WDModule::Reset should have worked");
		break;
	}
	for (int i = 0; i < 5; i++) {
		ROAnything result;
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA1Action", ":0.name"));
		assertEqualm("ifs APPL. User Directory", result.AsString(), "Reset test failed.");
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA2Action", ":0.pd-dn"));
		assertEqualm("cn=CH10601-tkgae,dc=tkfpd.hsr.ch", result.AsString(), "Reset test failed.");
		assertEqualm(0, WDModule::Reset(fGlobalConfig, fGlobalConfig), "WDModule::Reset should have worked");
		break;
	}
}

void LDAPDAICachePolicyTest::CallsInARow()
{
	StartTrace(LDAPDAICachePolicyTest.ReInitTest);
	for (int i = 0; i < 5; i++) {
		ROAnything result;
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA1", ":0.name"));
		assertEqualm("ifs APPL. User Directory", result.AsString(), "Reset test failed.");
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA2", ":0.pd-dn"));
		assertEqualm("cn=CH10601-tkgae,dc=tkfpd.hsr.ch", result.AsString(), "Reset test failed.");
	}
	for (int i = 0; i < 5; i++) {
		ROAnything result;
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA1Action", ":0.name"));
		assertEqualm("ifs APPL. User Directory", result.AsString(), "Reset test failed.");
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA2Action", ":0.pd-dn"));
		assertEqualm("cn=CH10601-tkgae,dc=tkfpd.hsr.ch", result.AsString(), "Reset test failed.");
	}
}

void LDAPDAICachePolicyTest::testCase()
{
	StartTrace(LDAPDAICachePolicyTest.testCase);
//	t_assert(false);
}

// builds up a suite of testcases, add a line for each testmethod
Test *LDAPDAICachePolicyTest::suite ()
{
	StartTrace(LDAPDAICachePolicyTest.suite);
	TestSuite *testSuite = new TestSuite;
	testSuite->addTest (NEW_CASE(LDAPDAICachePolicyTest, NoDataReadTest));
	testSuite->addTest (NEW_CASE(LDAPDAICachePolicyTest, CallsInARow));
	testSuite->addTest (NEW_CASE(LDAPDAICachePolicyTest, ReInitTest));
	return testSuite;
}
<commit_msg>corrected double defined/used variable<commit_after>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- c-modules used -----------------------------------------------------------

//--- standard modules used ----------------------------------------------------
#include "Anything.h"
#include "Dbg.h"

//--- test modules used --------------------------------------------------------
#include "TestSuite.h"

//--- module under test --------------------------------------------------------

//--- interface include --------------------------------------------------------
#include "LDAPDAICachePolicyTest.h"
#include "LDAPDAICachePolicyModule.h"
#include "System.h"
#include "StringStream.h"
#include "Application.h"
#include "Threads.h"

//---- LDAPDAICachePolicyTest ----------------------------------------------------------------
LDAPDAICachePolicyTest::LDAPDAICachePolicyTest(TString name) : TestCase(name)
{
	StartTrace(LDAPDAICachePolicyTest.Ctor);
}

LDAPDAICachePolicyTest::~LDAPDAICachePolicyTest()
{
	StartTrace(LDAPDAICachePolicyTest.Dtor);
}

// setup for this TestCase
void LDAPDAICachePolicyTest::setUp ()
{
	StartTrace(LDAPDAICachePolicyTest.setUp);
	t_assert(System::LoadConfigFile(fGlobalConfig, "Config"));
	t_assert(fGlobalConfig.IsDefined("Modules"));
	Application::InitializeGlobalConfig(fGlobalConfig);
	assertEqualm(0, WDModule::Install(fGlobalConfig), "WDModule::Install should have worked.");
}

void LDAPDAICachePolicyTest::setUp (const String &configName)
{
	StartTrace(LDAPDAICachePolicyTest.setUp);
	t_assert(System::LoadConfigFile(fGlobalConfig, configName));
	TraceAny(fGlobalConfig, "Global Config");
	t_assert(fGlobalConfig.IsDefined("Modules"));
	Application::InitializeGlobalConfig(fGlobalConfig);
	// Will fail because of NoDataDA and LdapCachePolicyModule return
	// code check is mandatory
	assertEqualm(-1, WDModule::Install(fGlobalConfig), "WDModule::Install should have failed.");
}

void LDAPDAICachePolicyTest::tearDown ()
{
	StartTrace(LDAPDAICachePolicyTest.tearDown);
	t_assert(fGlobalConfig.IsDefined("Modules"));
	WDModule::Terminate(fGlobalConfig);
}

void LDAPDAICachePolicyTest::NoDataReadTest()
{
	StartTrace(LDAPDAICachePolicyTest.NoDataReadTest);
	setUp();
	tearDown();
	setUp(String("NoDataQueryConfig"));
	// re-install "good" config
	tearDown();
	setUp();
}

void LDAPDAICachePolicyTest::ReInitTest()
{
	StartTrace(LDAPDAICachePolicyTest.ReInitTest);
	int i;
	for (i = 0; i < 5; i++) {
		ROAnything result;
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA1", ":0.name"));
		assertEqualm("ifs APPL. User Directory", result.AsString(), "Reset test failed.");
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA2", ":0.pd-dn"));
		assertEqualm("cn=CH10601-tkgae,dc=tkfpd.hsr.ch", result.AsString(), "Reset test failed.");
		assertEqualm(0, WDModule::Reset(fGlobalConfig, fGlobalConfig), "WDModule::Reset should have worked");
		break;
	}
	for (i = 0; i < 5; i++) {
		ROAnything result;
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA1Action", ":0.name"));
		assertEqualm("ifs APPL. User Directory", result.AsString(), "Reset test failed.");
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA2Action", ":0.pd-dn"));
		assertEqualm("cn=CH10601-tkgae,dc=tkfpd.hsr.ch", result.AsString(), "Reset test failed.");
		assertEqualm(0, WDModule::Reset(fGlobalConfig, fGlobalConfig), "WDModule::Reset should have worked");
		break;
	}
}

void LDAPDAICachePolicyTest::CallsInARow()
{
	StartTrace(LDAPDAICachePolicyTest.ReInitTest);
	int i;
	for (i = 0; i < 5; i++) {
		ROAnything result;
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA1", ":0.name"));
		assertEqualm("ifs APPL. User Directory", result.AsString(), "Reset test failed.");
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA2", ":0.pd-dn"));
		assertEqualm("cn=CH10601-tkgae,dc=tkfpd.hsr.ch", result.AsString(), "Reset test failed.");
	}
	for (i = 0; i < 5; i++) {
		ROAnything result;
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA1Action", ":0.name"));
		assertEqualm("ifs APPL. User Directory", result.AsString(), "Reset test failed.");
		t_assert(LDAPDAICacheGetter::Get(result, "TestDA2Action", ":0.pd-dn"));
		assertEqualm("cn=CH10601-tkgae,dc=tkfpd.hsr.ch", result.AsString(), "Reset test failed.");
	}
}

void LDAPDAICachePolicyTest::testCase()
{
	StartTrace(LDAPDAICachePolicyTest.testCase);
//	t_assert(false);
}

// builds up a suite of testcases, add a line for each testmethod
Test *LDAPDAICachePolicyTest::suite ()
{
	StartTrace(LDAPDAICachePolicyTest.suite);
	TestSuite *testSuite = new TestSuite;
	testSuite->addTest (NEW_CASE(LDAPDAICachePolicyTest, NoDataReadTest));
	testSuite->addTest (NEW_CASE(LDAPDAICachePolicyTest, CallsInARow));
	testSuite->addTest (NEW_CASE(LDAPDAICachePolicyTest, ReInitTest));
	return testSuite;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

// must be first
#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>

#include "basecontainernode.hxx"
#include "eventqueue.hxx"
#include "tools.hxx"
#include "nodetools.hxx"
#include "delayevent.hxx"

#include <boost/bind.hpp>
#include <boost/mem_fn.hpp>
#include <algorithm>

using namespace com::sun::star;

namespace slideshow {
namespace internal {

BaseContainerNode::BaseContainerNode(
    const uno::Reference< animations::XAnimationNode >&     xNode,
    const BaseContainerNodeSharedPtr&                       rParent,
    const NodeContext&                                      rContext )
    : BaseNode( xNode, rParent, rContext ),
      maChildren(),
      mnFinishedChildren(0),
      mbDurationIndefinite( isIndefiniteTiming( xNode->getEnd() ) &&
                            isIndefiniteTiming( xNode->getDuration() ) )
{
}

void BaseContainerNode::dispose()
{
    forEachChildNode( boost::mem_fn(&Disposable::dispose) );
    maChildren.clear();
    BaseNode::dispose();
}

bool BaseContainerNode::init_st()
{
   if( !(getXAnimationNode()->getRepeatCount() >>= mnLeftIterations) )
        mnLeftIterations = 1.0;
   return init_children();
}

bool BaseContainerNode::init_children()
{
    mnFinishedChildren = 0;

    // initialize all children
    return (std::count_if(
                maChildren.begin(), maChildren.end(),
                boost::mem_fn(&AnimationNode::init) ) ==
            static_cast<VectorOfNodes::difference_type>(maChildren.size()));
}

void BaseContainerNode::deactivate_st( NodeState eDestState )
{
    mnLeftIterations = 0; // in order to make skip effect work correctly
    if (eDestState == FROZEN) {
        // deactivate all children that are not FROZEN or ENDED:
        forEachChildNode( boost::mem_fn(&AnimationNode::deactivate),
                          ~(FROZEN | ENDED) );
    }
    else {
        // end all children that are not ENDED:
        forEachChildNode( boost::mem_fn(&AnimationNode::end), ~ENDED );
    }
}

bool BaseContainerNode::hasPendingAnimation() const
{
    // does any of our children returns "true" on
    // AnimationNode::hasPendingAnimation()?
    // If yes, we, too, return true
    VectorOfNodes::const_iterator const iEnd( maChildren.end() );
    return (std::find_if(
                maChildren.begin(), iEnd,
                boost::mem_fn(&AnimationNode::hasPendingAnimation) ) != iEnd);
}

void BaseContainerNode::appendChildNode( AnimationNodeSharedPtr const& pNode )
{
    if (! checkValidNode())
        return;

    // register derived classes as end listeners at all children.
    // this is necessary to control the children animation
    // sequence, and to determine our own end event
    if (pNode->registerDeactivatingListener( getSelf() )) {
        maChildren.push_back( pNode );
    }
}

bool BaseContainerNode::isChildNode( AnimationNodeSharedPtr const& pNode ) const
{
    // find given notifier in child vector
    VectorOfNodes::const_iterator const iEnd( maChildren.end() );
    VectorOfNodes::const_iterator const iFind(
        std::find( maChildren.begin(), iEnd, pNode ) );
    return (iFind != iEnd);
}

bool BaseContainerNode::notifyDeactivatedChild(
    AnimationNodeSharedPtr const& pChildNode )
{
    OSL_ASSERT( pChildNode->getState() == FROZEN ||
                pChildNode->getState() == ENDED );
    // early exit on invalid nodes
    OSL_ASSERT( getState() != INVALID );
    if( getState() == INVALID )
        return false;

    if (! isChildNode(pChildNode)) {
        OSL_FAIL( "unknown notifier!" );
        return false;
    }

    std::size_t const nSize = maChildren.size();
    OSL_ASSERT( mnFinishedChildren < nSize );
    ++mnFinishedChildren;
    bool bFinished = (mnFinishedChildren >= nSize);

    // all children finished, and we've got indefinite duration?
    // think of ParallelTimeContainer::notifyDeactivating()
    // if duration given, we will be deactivated by some end event
    // @see fillCommonParameters()
    if (bFinished && isDurationIndefinite()) {
        if( mnLeftIterations >= 1.0 )
        {
            mnLeftIterations -= 1.0;
        }
        if( mnLeftIterations >= 1.0 )
        {
            bFinished = false;
            EventSharedPtr aRepetitionEvent =
                    makeDelay( boost::bind( &BaseContainerNode::repeat, this ),
                               0.0,
                               "BaseContainerNode::repeat");
            getContext().mrEventQueue.addEvent( aRepetitionEvent );
        }
        else
        {
            deactivate();
        }
    }

    return bFinished;
}

bool BaseContainerNode::repeat()
{
    forEachChildNode( boost::mem_fn(&AnimationNode::end), ~ENDED );
    sal_Bool bState = init_children();
    if( bState )
        activate_st();
    return bState;
}

#if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
void BaseContainerNode::showState() const
{
    for( std::size_t i=0; i<maChildren.size(); ++i )
    {
        BaseNodeSharedPtr pNode =
            boost::shared_dynamic_cast<BaseNode>(maChildren[i]);
        VERBOSE_TRACE(
            "Node connection: n0x%X -> n0x%X",
            (const char*)this+debugGetCurrentOffset(),
            (const char*)pNode.get()+debugGetCurrentOffset() );
        pNode->showState();
    }

    BaseNode::showState();
}
#endif

} // namespace internal
} // namespace slideshow

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>boost::shared_dynamic_cast -> boost::dynamic_pointer_cast<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

// must be first
#include <canvas/debug.hxx>
#include <canvas/verbosetrace.hxx>

#include "basecontainernode.hxx"
#include "eventqueue.hxx"
#include "tools.hxx"
#include "nodetools.hxx"
#include "delayevent.hxx"

#include <boost/bind.hpp>
#include <boost/mem_fn.hpp>
#include <algorithm>

using namespace com::sun::star;

namespace slideshow {
namespace internal {

BaseContainerNode::BaseContainerNode(
    const uno::Reference< animations::XAnimationNode >&     xNode,
    const BaseContainerNodeSharedPtr&                       rParent,
    const NodeContext&                                      rContext )
    : BaseNode( xNode, rParent, rContext ),
      maChildren(),
      mnFinishedChildren(0),
      mbDurationIndefinite( isIndefiniteTiming( xNode->getEnd() ) &&
                            isIndefiniteTiming( xNode->getDuration() ) )
{
}

void BaseContainerNode::dispose()
{
    forEachChildNode( boost::mem_fn(&Disposable::dispose) );
    maChildren.clear();
    BaseNode::dispose();
}

bool BaseContainerNode::init_st()
{
   if( !(getXAnimationNode()->getRepeatCount() >>= mnLeftIterations) )
        mnLeftIterations = 1.0;
   return init_children();
}

bool BaseContainerNode::init_children()
{
    mnFinishedChildren = 0;

    // initialize all children
    return (std::count_if(
                maChildren.begin(), maChildren.end(),
                boost::mem_fn(&AnimationNode::init) ) ==
            static_cast<VectorOfNodes::difference_type>(maChildren.size()));
}

void BaseContainerNode::deactivate_st( NodeState eDestState )
{
    mnLeftIterations = 0; // in order to make skip effect work correctly
    if (eDestState == FROZEN) {
        // deactivate all children that are not FROZEN or ENDED:
        forEachChildNode( boost::mem_fn(&AnimationNode::deactivate),
                          ~(FROZEN | ENDED) );
    }
    else {
        // end all children that are not ENDED:
        forEachChildNode( boost::mem_fn(&AnimationNode::end), ~ENDED );
    }
}

bool BaseContainerNode::hasPendingAnimation() const
{
    // does any of our children returns "true" on
    // AnimationNode::hasPendingAnimation()?
    // If yes, we, too, return true
    VectorOfNodes::const_iterator const iEnd( maChildren.end() );
    return (std::find_if(
                maChildren.begin(), iEnd,
                boost::mem_fn(&AnimationNode::hasPendingAnimation) ) != iEnd);
}

void BaseContainerNode::appendChildNode( AnimationNodeSharedPtr const& pNode )
{
    if (! checkValidNode())
        return;

    // register derived classes as end listeners at all children.
    // this is necessary to control the children animation
    // sequence, and to determine our own end event
    if (pNode->registerDeactivatingListener( getSelf() )) {
        maChildren.push_back( pNode );
    }
}

bool BaseContainerNode::isChildNode( AnimationNodeSharedPtr const& pNode ) const
{
    // find given notifier in child vector
    VectorOfNodes::const_iterator const iEnd( maChildren.end() );
    VectorOfNodes::const_iterator const iFind(
        std::find( maChildren.begin(), iEnd, pNode ) );
    return (iFind != iEnd);
}

bool BaseContainerNode::notifyDeactivatedChild(
    AnimationNodeSharedPtr const& pChildNode )
{
    OSL_ASSERT( pChildNode->getState() == FROZEN ||
                pChildNode->getState() == ENDED );
    // early exit on invalid nodes
    OSL_ASSERT( getState() != INVALID );
    if( getState() == INVALID )
        return false;

    if (! isChildNode(pChildNode)) {
        OSL_FAIL( "unknown notifier!" );
        return false;
    }

    std::size_t const nSize = maChildren.size();
    OSL_ASSERT( mnFinishedChildren < nSize );
    ++mnFinishedChildren;
    bool bFinished = (mnFinishedChildren >= nSize);

    // all children finished, and we've got indefinite duration?
    // think of ParallelTimeContainer::notifyDeactivating()
    // if duration given, we will be deactivated by some end event
    // @see fillCommonParameters()
    if (bFinished && isDurationIndefinite()) {
        if( mnLeftIterations >= 1.0 )
        {
            mnLeftIterations -= 1.0;
        }
        if( mnLeftIterations >= 1.0 )
        {
            bFinished = false;
            EventSharedPtr aRepetitionEvent =
                    makeDelay( boost::bind( &BaseContainerNode::repeat, this ),
                               0.0,
                               "BaseContainerNode::repeat");
            getContext().mrEventQueue.addEvent( aRepetitionEvent );
        }
        else
        {
            deactivate();
        }
    }

    return bFinished;
}

bool BaseContainerNode::repeat()
{
    forEachChildNode( boost::mem_fn(&AnimationNode::end), ~ENDED );
    sal_Bool bState = init_children();
    if( bState )
        activate_st();
    return bState;
}

#if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
void BaseContainerNode::showState() const
{
    for( std::size_t i=0; i<maChildren.size(); ++i )
    {
        BaseNodeSharedPtr pNode =
            boost::dynamic_pointer_cast<BaseNode>(maChildren[i]);
        VERBOSE_TRACE(
            "Node connection: n0x%X -> n0x%X",
            (const char*)this+debugGetCurrentOffset(),
            (const char*)pNode.get()+debugGetCurrentOffset() );
        pNode->showState();
    }

    BaseNode::showState();
}
#endif

} // namespace internal
} // namespace slideshow

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/xml/CCopasiXMLInterface.cpp,v $
   $Revision: 1.28 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/06/24 20:07:55 $
   End CVS Header */

/**
 * CCopasiXMLInterface class.
 * The class CCopasiXMLInterface is the interface to various XML document
 * containing Copasi relevant informtion.
 *
 * Created for Copasi by Stefan Hoops 2003
 */

#include <fstream>
#include <limits>

#include "copasi.h"
#include "CCopasiXMLInterface.h"
#include "model/CModel.h"
#include "report/CReportDefinition.h"
#include "report/CReportDefinitionVector.h"
#include "plot/COutputDefinitionVector.h"
#include "plot/CPlotSpecification.h"
#include "CCopasiXMLParser.h"
#include "utilities/CCopasiVector.h"
#include "utilities/CSlider.h"

SCopasiXMLGUI::SCopasiXMLGUI():
    pSliderList(new CCopasiVector<CSlider>)
{}

SCopasiXMLGUI::~SCopasiXMLGUI()
{
  pdelete(pSliderList);
}

void encodeNONE(const char & chr, std::ostringstream & xml)
{
  xml << chr;
  return;
}

void encodeSTD(const char & chr, std::ostringstream & xml)
{
  switch (chr)
    {
    case '&':
      xml << "&";
      break;

    case '\'':
      xml << "'";
      break;

    case '<':
      xml << "<";
      break;

    case '>':
      xml << ">";
      break;

    case '\"':
      xml << """;
      break;

    default:
      xml << chr;
      break;
    }
  return;
}

void encodeATTRIBUTE(const char & chr, std::ostringstream & xml)
{
  switch (chr)
    {
    case '&':
      xml << "&";
      break;

    case '<':
      xml << "<";
      break;

    case '\"':
      xml << """;
      break;

    case '\t':      // Without this <tab> is converted to <space>
      xml << "	";
      break;

    default:
      xml << chr;
      break;
    }
  return;
}

void encodeCHARACTER(const char & chr, std::ostringstream & xml)
{
  switch (chr)
    {
    case '&':
      xml << "&";
      break;

    case '<':
      xml << "<";
      break;

    default:
      xml << chr;
      break;
    }
  return;
}

std::string CCopasiXMLInterface::encode(const std::string & str, const EncodingType & type)
{
  /* All COPASI std::strings and char are already UTF-8 encoded.*/
  std::string tmp = str;
  std::ostringstream xml;

  void (*encode)(const char & chr, std::ostringstream & xml);
  std::string::const_iterator it = str.begin();
  std::string::const_iterator end = str.end();

  switch (type)
    {
    case none:
      encode = encodeNONE;
      break;

    case std:
      encode = encodeSTD;
      break;

    case attribute:
      encode = encodeATTRIBUTE;
      break;

    case character:
      encode = encodeCHARACTER;
      break;
    }

  for (; it != end; ++it)
    encode(*it, xml);

  return xml.str();
}

std::string CCopasiXMLInterface::encodeDBL(const C_FLOAT64 & dbl)
{
  std::ostringstream value;

  if (dbl != dbl) // NaN != NaN
    value << "NaN";
  else if (dbl == std::numeric_limits<C_FLOAT64>::infinity())
    value << "INF";
  else if (-dbl == std::numeric_limits<C_FLOAT64>::infinity())
    value << "-INF";
  else
    value << dbl;

  return value.str();
}

std::string CCopasiXMLInterface::utf8(const std::string & str)
{
  return str;

  std::ostringstream utf8;

  /* Based on RFC 2279.
     Since every string whithin COPASI is treated as latin1 and input
     is only optained through QT and Expat which will provide latin1
     encoded strings the below should suffice. */
  unsigned C_INT32 i, imax;
  for (i = 0, imax = str.length(); i < imax; i++)
    {
      if ((unsigned char) str[i] < 0x80) utf8 << str[i];
      else
        {
          utf8 << 0xc0 + ((str[i] >> 6) & 0x03);
          utf8 << 0x80 + (str[i] & 0x3f);
        }
    }
  return utf8.str();
}

CCopasiXMLInterface::CCopasiXMLInterface():
    mpModel(NULL),
    mpFunctionList(NULL),
    mpTaskList(NULL),
    mpReportList(NULL),
    mpPlotList(NULL),
    mpGUI(NULL),
    mpIstream(NULL),
    mpOstream(NULL),
    mIndent()
{}

CCopasiXMLInterface::~CCopasiXMLInterface() {}

bool CCopasiXMLInterface::load(const std::string & fileName)
{
  std::ifstream is(fileName.c_str());

  if (is.fail()) return false;
  else return load(is);
}

bool CCopasiXMLInterface::save(const std::string & fileName)
{
  std::ofstream os(fileName.c_str());

  if (os.fail()) return false;
  else return save(os);
}

bool CCopasiXMLInterface::setModel(const CModel & model)
{
  mpModel = const_cast<CModel *>(&model);
  return true;
}

CModel * CCopasiXMLInterface::getModel() const {return mpModel;}

bool CCopasiXMLInterface::haveModel() const {return mpModel != NULL;}

bool CCopasiXMLInterface::freeModel()
{
  pdelete(mpModel);
  return true;
}

bool CCopasiXMLInterface::setFunctionList(const CCopasiVectorN< CEvaluationTree > & functionList)
{
  mpFunctionList = const_cast<CCopasiVectorN< CEvaluationTree > *>(&functionList);
  return true;
}

CCopasiVectorN< CEvaluationTree > * CCopasiXMLInterface::getFunctionList() const
  {return mpFunctionList;}

bool CCopasiXMLInterface::haveFunctionList() const
  {return mpFunctionList != NULL;}

bool CCopasiXMLInterface::freeFunctionList()
{
  pdelete(mpFunctionList);
  return true;
}

bool CCopasiXMLInterface::setTaskList(const CCopasiVectorN< CCopasiTask > & taskList)
{
  mpTaskList = const_cast<CCopasiVectorN< CCopasiTask > *>(&taskList);
  return true;
}

CCopasiVectorN< CCopasiTask > * CCopasiXMLInterface::getTaskList() const
  {return mpTaskList;}

bool CCopasiXMLInterface::haveTaskList() const
  {return mpTaskList != NULL;}

bool CCopasiXMLInterface::freeTaskList()
{
  pdelete(mpTaskList);
  return true;
}

bool CCopasiXMLInterface::setPlotList(const COutputDefinitionVector & plotList)
{
  mpPlotList = const_cast<COutputDefinitionVector *>(&plotList);
  return true;
}

COutputDefinitionVector * CCopasiXMLInterface::getPlotList() const
  {return mpPlotList;}

bool CCopasiXMLInterface::havePlotList() const
  {return mpPlotList != NULL;}

bool CCopasiXMLInterface::freePlotList()
{
  pdelete(mpPlotList);
  return true;
}

bool CCopasiXMLInterface::setReportList(const CReportDefinitionVector & reportList)
{
  mpReportList = const_cast<CReportDefinitionVector *>(&reportList);
  return true;
}

CReportDefinitionVector * CCopasiXMLInterface::getReportList() const
  {return mpReportList;}

bool CCopasiXMLInterface::haveReportList() const
  {return mpReportList != NULL;}

bool CCopasiXMLInterface::freeReportList()
{
  pdelete(mpReportList);
  return true;
}

bool CCopasiXMLInterface::setGUI(const SCopasiXMLGUI & GUI)
{
  mpGUI = const_cast<SCopasiXMLGUI *>(&GUI);
  return true;
}

SCopasiXMLGUI * CCopasiXMLInterface::getGUI() const {return mpGUI;}

bool CCopasiXMLInterface::haveGUI() const {return mpGUI != NULL;}

bool CCopasiXMLInterface::freeGUI()
{
  pdelete(mpGUI);
  return true;
}

bool CCopasiXMLInterface::saveData(const std::string & data)
{
  *mpOstream << mIndent << CCopasiXMLInterface::encode(data) << std::endl;

  return true;
}

bool CCopasiXMLInterface::saveElement(const std::string & name,
                                      CXMLAttributeList & attributeList)
{
  *mpOstream << mIndent << "<" << name;

  unsigned C_INT32 i, imax;

  for (i = 0, imax = attributeList.size(); i < imax; i++)
    *mpOstream << attributeList.getAttribute(i);

  *mpOstream << "/>" << std::endl;

  return true;
}

bool CCopasiXMLInterface::startSaveElement(const std::string & name)
{
  *mpOstream << mIndent << "<" << name << ">" << std::endl;

  mIndent += "  ";
  return true;
}

bool CCopasiXMLInterface::startSaveElement(const std::string & name,
    CXMLAttributeList & attributeList)
{
  *mpOstream << mIndent << "<" << name;

  unsigned C_INT32 i, imax;
  for (i = 0, imax = attributeList.size(); i < imax; i++)
    *mpOstream << attributeList.getAttribute(i);

  *mpOstream << ">" << std::endl;

  mIndent += "  ";
  return true;
}

bool CCopasiXMLInterface::endSaveElement(const std::string & name)
{
  mIndent = mIndent.substr(0, mIndent.length() - 2);
  *mpOstream << mIndent << "</" << name << ">" << std::endl;

  return true;
}

CXMLAttributeList::CXMLAttributeList():
    mAttributeList(),
    mSaveList()
{}

CXMLAttributeList::CXMLAttributeList(const CXMLAttributeList & src):
    mAttributeList(src.mAttributeList),
    mSaveList(src.mSaveList)
{}

CXMLAttributeList::~CXMLAttributeList() {}

bool CXMLAttributeList::erase()
{
  mAttributeList.clear();
  mSaveList.clear();

  return true;
}

unsigned C_INT32 CXMLAttributeList::size() {return mAttributeList.size() / 2;}

bool CXMLAttributeList::add(const std::string & name, const C_FLOAT64 & value)
{
  return add(name,
             CCopasiXMLInterface::encodeDBL(value),
             CCopasiXMLInterface::attribute);
}

bool CXMLAttributeList::setName(const unsigned C_INT32 & index,
                                const std::string & name)
{
  mAttributeList[2 * index] = name;
  return true;
}

const std::string & CXMLAttributeList::getName(const unsigned C_INT32 & index) const
  {return mAttributeList[2 * index];}

const std::string & CXMLAttributeList::getValue(const unsigned C_INT32 & index) const
  {return mAttributeList[2 * index + 1];}

bool CXMLAttributeList::skip(const unsigned C_INT32 & index)
{
  mSaveList[index] = false;
  return true;
}

std::string CXMLAttributeList::getAttribute(const unsigned C_INT32 & index) const
  {
    if (mSaveList[index])
      return " " + mAttributeList[2 * index] + "=\"" + mAttributeList[2 * index + 1] + "\"";
    else
      return "";
  }
<commit_msg>Use _isnan in encodeDBL to detect NaN.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/xml/CCopasiXMLInterface.cpp,v $
   $Revision: 1.29 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/06/28 14:27:14 $
   End CVS Header */

/**
 * CCopasiXMLInterface class.
 * The class CCopasiXMLInterface is the interface to various XML document
 * containing Copasi relevant informtion.
 *
 * Created for Copasi by Stefan Hoops 2003
 */

#include <fstream>
#include <limits>
#include <float.h>

#include "copasi.h"
#include "CCopasiXMLInterface.h"
#include "model/CModel.h"
#include "report/CReportDefinition.h"
#include "report/CReportDefinitionVector.h"
#include "plot/COutputDefinitionVector.h"
#include "plot/CPlotSpecification.h"
#include "CCopasiXMLParser.h"
#include "utilities/CCopasiVector.h"
#include "utilities/CSlider.h"

SCopasiXMLGUI::SCopasiXMLGUI():
    pSliderList(new CCopasiVector<CSlider>)
{}

SCopasiXMLGUI::~SCopasiXMLGUI()
{
  pdelete(pSliderList);
}

void encodeNONE(const char & chr, std::ostringstream & xml)
{
  xml << chr;
  return;
}

void encodeSTD(const char & chr, std::ostringstream & xml)
{
  switch (chr)
    {
    case '&':
      xml << "&";
      break;

    case '\'':
      xml << "'";
      break;

    case '<':
      xml << "<";
      break;

    case '>':
      xml << ">";
      break;

    case '\"':
      xml << """;
      break;

    default:
      xml << chr;
      break;
    }
  return;
}

void encodeATTRIBUTE(const char & chr, std::ostringstream & xml)
{
  switch (chr)
    {
    case '&':
      xml << "&";
      break;

    case '<':
      xml << "<";
      break;

    case '\"':
      xml << """;
      break;

    case '\t':       // Without this <tab> is converted to <space>
      xml << "	";
      break;

    default:
      xml << chr;
      break;
    }
  return;
}

void encodeCHARACTER(const char & chr, std::ostringstream & xml)
{
  switch (chr)
    {
    case '&':
      xml << "&";
      break;

    case '<':
      xml << "<";
      break;

    default:
      xml << chr;
      break;
    }
  return;
}

std::string CCopasiXMLInterface::encode(const std::string & str, const EncodingType & type)
{
  /* All COPASI std::strings and char are already UTF-8 encoded.*/
  std::string tmp = str;
  std::ostringstream xml;

  void (*encode)(const char & chr, std::ostringstream & xml);
  std::string::const_iterator it = str.begin();
  std::string::const_iterator end = str.end();

  switch (type)
    {
    case none:
      encode = encodeNONE;
      break;

    case std:
      encode = encodeSTD;
      break;

    case attribute:
      encode = encodeATTRIBUTE;
      break;

    case character:
      encode = encodeCHARACTER;
      break;
    }

  for (; it != end; ++it)
    encode(*it, xml);

  return xml.str();
}

std::string CCopasiXMLInterface::encodeDBL(const C_FLOAT64 & dbl)
{
  std::ostringstream value;

  if (_isnan(dbl))
    value << "NaN";
  else if (dbl == std::numeric_limits<C_FLOAT64>::infinity())
    value << "INF";
  else if (-dbl == std::numeric_limits<C_FLOAT64>::infinity())
    value << "-INF";
  else
    value << dbl;

  return value.str();
}

std::string CCopasiXMLInterface::utf8(const std::string & str)
{
  return str;

  std::ostringstream utf8;

  /* Based on RFC 2279.
     Since every string whithin COPASI is treated as latin1 and input
     is only optained through QT and Expat which will provide latin1
     encoded strings the below should suffice. */
  unsigned C_INT32 i, imax;
  for (i = 0, imax = str.length(); i < imax; i++)
    {
      if ((unsigned char) str[i] < 0x80) utf8 << str[i];
      else
        {
          utf8 << 0xc0 + ((str[i] >> 6) & 0x03);
          utf8 << 0x80 + (str[i] & 0x3f);
        }
    }
  return utf8.str();
}

CCopasiXMLInterface::CCopasiXMLInterface():
    mpModel(NULL),
    mpFunctionList(NULL),
    mpTaskList(NULL),
    mpReportList(NULL),
    mpPlotList(NULL),
    mpGUI(NULL),
    mpIstream(NULL),
    mpOstream(NULL),
    mIndent()
{}

CCopasiXMLInterface::~CCopasiXMLInterface() {}

bool CCopasiXMLInterface::load(const std::string & fileName)
{
  std::ifstream is(fileName.c_str());

  if (is.fail()) return false;
  else return load(is);
}

bool CCopasiXMLInterface::save(const std::string & fileName)
{
  std::ofstream os(fileName.c_str());

  if (os.fail()) return false;
  else return save(os);
}

bool CCopasiXMLInterface::setModel(const CModel & model)
{
  mpModel = const_cast<CModel *>(&model);
  return true;
}

CModel * CCopasiXMLInterface::getModel() const {return mpModel;}

bool CCopasiXMLInterface::haveModel() const {return mpModel != NULL;}

bool CCopasiXMLInterface::freeModel()
{
  pdelete(mpModel);
  return true;
}

bool CCopasiXMLInterface::setFunctionList(const CCopasiVectorN< CEvaluationTree > & functionList)
{
  mpFunctionList = const_cast<CCopasiVectorN< CEvaluationTree > *>(&functionList);
  return true;
}

CCopasiVectorN< CEvaluationTree > * CCopasiXMLInterface::getFunctionList() const
  {return mpFunctionList;}

bool CCopasiXMLInterface::haveFunctionList() const
  {return mpFunctionList != NULL;}

bool CCopasiXMLInterface::freeFunctionList()
{
  pdelete(mpFunctionList);
  return true;
}

bool CCopasiXMLInterface::setTaskList(const CCopasiVectorN< CCopasiTask > & taskList)
{
  mpTaskList = const_cast<CCopasiVectorN< CCopasiTask > *>(&taskList);
  return true;
}

CCopasiVectorN< CCopasiTask > * CCopasiXMLInterface::getTaskList() const
  {return mpTaskList;}

bool CCopasiXMLInterface::haveTaskList() const
  {return mpTaskList != NULL;}

bool CCopasiXMLInterface::freeTaskList()
{
  pdelete(mpTaskList);
  return true;
}

bool CCopasiXMLInterface::setPlotList(const COutputDefinitionVector & plotList)
{
  mpPlotList = const_cast<COutputDefinitionVector *>(&plotList);
  return true;
}

COutputDefinitionVector * CCopasiXMLInterface::getPlotList() const
  {return mpPlotList;}

bool CCopasiXMLInterface::havePlotList() const
  {return mpPlotList != NULL;}

bool CCopasiXMLInterface::freePlotList()
{
  pdelete(mpPlotList);
  return true;
}

bool CCopasiXMLInterface::setReportList(const CReportDefinitionVector & reportList)
{
  mpReportList = const_cast<CReportDefinitionVector *>(&reportList);
  return true;
}

CReportDefinitionVector * CCopasiXMLInterface::getReportList() const
  {return mpReportList;}

bool CCopasiXMLInterface::haveReportList() const
  {return mpReportList != NULL;}

bool CCopasiXMLInterface::freeReportList()
{
  pdelete(mpReportList);
  return true;
}

bool CCopasiXMLInterface::setGUI(const SCopasiXMLGUI & GUI)
{
  mpGUI = const_cast<SCopasiXMLGUI *>(&GUI);
  return true;
}

SCopasiXMLGUI * CCopasiXMLInterface::getGUI() const {return mpGUI;}

bool CCopasiXMLInterface::haveGUI() const {return mpGUI != NULL;}

bool CCopasiXMLInterface::freeGUI()
{
  pdelete(mpGUI);
  return true;
}

bool CCopasiXMLInterface::saveData(const std::string & data)
{
  *mpOstream << mIndent << CCopasiXMLInterface::encode(data) << std::endl;

  return true;
}

bool CCopasiXMLInterface::saveElement(const std::string & name,
                                      CXMLAttributeList & attributeList)
{
  *mpOstream << mIndent << "<" << name;

  unsigned C_INT32 i, imax;

  for (i = 0, imax = attributeList.size(); i < imax; i++)
    *mpOstream << attributeList.getAttribute(i);

  *mpOstream << "/>" << std::endl;

  return true;
}

bool CCopasiXMLInterface::startSaveElement(const std::string & name)
{
  *mpOstream << mIndent << "<" << name << ">" << std::endl;

  mIndent += "  ";
  return true;
}

bool CCopasiXMLInterface::startSaveElement(const std::string & name,
    CXMLAttributeList & attributeList)
{
  *mpOstream << mIndent << "<" << name;

  unsigned C_INT32 i, imax;
  for (i = 0, imax = attributeList.size(); i < imax; i++)
    *mpOstream << attributeList.getAttribute(i);

  *mpOstream << ">" << std::endl;

  mIndent += "  ";
  return true;
}

bool CCopasiXMLInterface::endSaveElement(const std::string & name)
{
  mIndent = mIndent.substr(0, mIndent.length() - 2);
  *mpOstream << mIndent << "</" << name << ">" << std::endl;

  return true;
}

CXMLAttributeList::CXMLAttributeList():
    mAttributeList(),
    mSaveList()
{}

CXMLAttributeList::CXMLAttributeList(const CXMLAttributeList & src):
    mAttributeList(src.mAttributeList),
    mSaveList(src.mSaveList)
{}

CXMLAttributeList::~CXMLAttributeList() {}

bool CXMLAttributeList::erase()
{
  mAttributeList.clear();
  mSaveList.clear();

  return true;
}

unsigned C_INT32 CXMLAttributeList::size() {return mAttributeList.size() / 2;}

bool CXMLAttributeList::add(const std::string & name, const C_FLOAT64 & value)
{
  return add(name,
             CCopasiXMLInterface::encodeDBL(value),
             CCopasiXMLInterface::attribute);
}

bool CXMLAttributeList::setName(const unsigned C_INT32 & index,
                                const std::string & name)
{
  mAttributeList[2 * index] = name;
  return true;
}

const std::string & CXMLAttributeList::getName(const unsigned C_INT32 & index) const
  {return mAttributeList[2 * index];}

const std::string & CXMLAttributeList::getValue(const unsigned C_INT32 & index) const
  {return mAttributeList[2 * index + 1];}

bool CXMLAttributeList::skip(const unsigned C_INT32 & index)
{
  mSaveList[index] = false;
  return true;
}

std::string CXMLAttributeList::getAttribute(const unsigned C_INT32 & index) const
  {
    if (mSaveList[index])
      return " " + mAttributeList[2 * index] + "=\"" + mAttributeList[2 * index + 1] + "\"";
    else
      return "";
  }
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/basictypes.h"
#include "base/run_loop.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"

// IPC messages for testing ---------------------------------------------------

#define IPC_MESSAGE_IMPL
#include "ipc/ipc_message_macros.h"

#define IPC_MESSAGE_START TestMsgStart

IPC_MESSAGE_CONTROL0(TestMsg_Message);
IPC_MESSAGE_CONTROL1(TestMsg_Request, int);
IPC_MESSAGE_CONTROL1(TestMsg_Response, int);

// ---------------------------------------------------------------------------

namespace content {

namespace {

static const int kRenderProcessId = 1;

class MessageReceiver : public EmbeddedWorkerTestHelper {
 public:
  MessageReceiver(ServiceWorkerContextCore* context)
      : EmbeddedWorkerTestHelper(context, kRenderProcessId),
        current_embedded_worker_id_(0),
        current_request_id_(0) {}
  virtual ~MessageReceiver() {}

  virtual bool OnSendMessageToWorker(int thread_id,
                                     int embedded_worker_id,
                                     int request_id,
                                     const IPC::Message& message) OVERRIDE {
    if (EmbeddedWorkerTestHelper::OnSendMessageToWorker(
            thread_id, embedded_worker_id, request_id, message)) {
      return true;
    }
    current_embedded_worker_id_ = embedded_worker_id;
    current_request_id_ = request_id;
    bool handled = true;
    IPC_BEGIN_MESSAGE_MAP(MessageReceiver, message)
      IPC_MESSAGE_HANDLER(TestMsg_Message, OnMessage)
      IPC_MESSAGE_HANDLER(TestMsg_Request, OnRequest)
      IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP()
    return handled;
  }

 private:
  void OnMessage() {
    // Do nothing.
  }

  void OnRequest(int value) {
    // Double the given value and send back the response.
    SimulateSendMessageToBrowser(current_embedded_worker_id_,
                                 current_request_id_,
                                 TestMsg_Response(value * 2));
  }

  int current_embedded_worker_id_;
  int current_request_id_;
  DISALLOW_COPY_AND_ASSIGN(MessageReceiver);
};

void ReceiveResponse(ServiceWorkerStatusCode* status_out,
                     int* value_out,
                     ServiceWorkerStatusCode status,
                     const IPC::Message& message) {
  Tuple1<int> param;
  ASSERT_TRUE(TestMsg_Response::Read(&message, &param));
  *status_out = status;
  *value_out = param.a;
}

void VerifyCalled(bool* called) {
  *called = true;
}

void ObserveStatusChanges(ServiceWorkerVersion* version,
                          std::vector<ServiceWorkerVersion::Status>* statuses) {
  statuses->push_back(version->status());
  version->RegisterStatusChangeCallback(
      base::Bind(&ObserveStatusChanges, make_scoped_refptr(version), statuses));
}

}  // namespace

class ServiceWorkerVersionTest : public testing::Test {
 protected:
  ServiceWorkerVersionTest()
      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}

  virtual void SetUp() OVERRIDE {
    context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL));
    helper_.reset(new MessageReceiver(context_.get()));

    registration_ = new ServiceWorkerRegistration(
        GURL("http://www.example.com/*"),
        GURL("http://www.example.com/service_worker.js"),
        1L, context_->AsWeakPtr());
    version_ = new ServiceWorkerVersion(
        registration_,
        1L, context_->AsWeakPtr());

    // Simulate adding one process to the worker.
    int embedded_worker_id = version_->embedded_worker()->embedded_worker_id();
    helper_->SimulateAddProcessToWorker(embedded_worker_id, kRenderProcessId);
  }

  virtual void TearDown() OVERRIDE {
    version_ = 0;
    registration_ = 0;
    helper_.reset();
    context_.reset();
  }

  TestBrowserThreadBundle thread_bundle_;
  scoped_ptr<ServiceWorkerContextCore> context_;
  scoped_ptr<EmbeddedWorkerTestHelper> helper_;
  scoped_refptr<ServiceWorkerRegistration> registration_;
  scoped_refptr<ServiceWorkerVersion> version_;
  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
};

TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
  // Call StartWorker() multiple times.
  ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(CreateReceiverOnCurrentThread(&status1));
  version_->StartWorker(CreateReceiverOnCurrentThread(&status2));

  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Call StartWorker() after it's started.
  version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
  base::RunLoop().RunUntilIdle();

  // All should just succeed.
  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_EQ(SERVICE_WORKER_OK, status3);

  // Call StopWorker() multiple times.
  status1 = SERVICE_WORKER_ERROR_FAILED;
  status2 = SERVICE_WORKER_ERROR_FAILED;
  status3 = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
  version_->StopWorker(CreateReceiverOnCurrentThread(&status2));

  // Also try calling StartWorker while StopWorker is in queue.
  version_->StartWorker(CreateReceiverOnCurrentThread(&status3));

  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // All StopWorker should just succeed, while StartWorker fails.
  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status3);
}

TEST_F(ServiceWorkerVersionTest, SendMessage) {
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // Send a message without starting the worker.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->SendMessage(TestMsg_Message(),
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);

  // The worker should be now started.
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Stop the worker, and then send the message immediately.
  ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
  version_->SendMessage(TestMsg_Message(),
                       CreateReceiverOnCurrentThread(&msg_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, stop_status);

  // SendMessage should return START_WORKER_FAILED error since it tried to
  // start a worker while it was stopping.
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
}

TEST_F(ServiceWorkerVersionTest, ReSendMessageAfterStop) {
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // Start the worker.
  ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(CreateReceiverOnCurrentThread(&start_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, start_status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Stop the worker, and then send the message immediately.
  ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
  version_->SendMessage(TestMsg_Message(),
                       CreateReceiverOnCurrentThread(&msg_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, stop_status);

  // SendMessage should return START_WORKER_FAILED error since it tried to
  // start a worker while it was stopping.
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);

  // Resend the message, which should succeed and restart the worker.
  version_->SendMessage(TestMsg_Message(),
                       CreateReceiverOnCurrentThread(&msg_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, msg_status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
}

TEST_F(ServiceWorkerVersionTest, SendMessageAndRegisterCallback) {
  // Send multiple messages and verify responses.
  ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
  int value1 = -1, value2 = -1;

  version_->SendMessageAndRegisterCallback(
      TestMsg_Request(111),
      base::Bind(&ReceiveResponse, &status1, &value1));
  version_->SendMessageAndRegisterCallback(
      TestMsg_Request(333),
      base::Bind(&ReceiveResponse, &status2, &value2));
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_EQ(111 * 2, value1);
  EXPECT_EQ(333 * 2, value2);
}

TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
  EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());

  // Dispatch an install event.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
  EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());

  // Wait for the completion.
  bool status_change_called = false;
  version_->RegisterStatusChangeCallback(
      base::Bind(&VerifyCalled, &status_change_called));

  base::RunLoop().RunUntilIdle();

  // After successful completion, version's status must be changed to
  // INSTALLED, and status change callback must have been fired.
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(status_change_called);
  EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version_->status());
}

TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
  version_->SetStatus(ServiceWorkerVersion::INSTALLED);
  EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version_->status());

  // Dispatch an activate event.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
  EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());

  // Wait for the completion.
  bool status_change_called = false;
  version_->RegisterStatusChangeCallback(
      base::Bind(&VerifyCalled, &status_change_called));

  base::RunLoop().RunUntilIdle();

  // After successful completion, version's status must be changed to
  // ACTIVE, and status change callback must have been fired.
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(status_change_called);
  EXPECT_EQ(ServiceWorkerVersion::ACTIVE, version_->status());
}

TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
  EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());

  // Repeatedly observe status changes (the callback re-registers itself).
  std::vector<ServiceWorkerVersion::Status> statuses;
  version_->RegisterStatusChangeCallback(
      base::Bind(&ObserveStatusChanges, version_, &statuses));

  // Dispatch some events.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);

  status = SERVICE_WORKER_ERROR_FAILED;
  version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);

  // Verify that we could successfully observe repeated status changes.
  ASSERT_EQ(4U, statuses.size());
  ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
  ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
  ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
  ASSERT_EQ(ServiceWorkerVersion::ACTIVE, statuses[3]);
}

}  // namespace content
<commit_msg>Disable ServiceWorkerVersionTest.RepeatedlyObserveStatusChanges<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/basictypes.h"
#include "base/run_loop.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"

// IPC messages for testing ---------------------------------------------------

#define IPC_MESSAGE_IMPL
#include "ipc/ipc_message_macros.h"

#define IPC_MESSAGE_START TestMsgStart

IPC_MESSAGE_CONTROL0(TestMsg_Message);
IPC_MESSAGE_CONTROL1(TestMsg_Request, int);
IPC_MESSAGE_CONTROL1(TestMsg_Response, int);

// ---------------------------------------------------------------------------

namespace content {

namespace {

static const int kRenderProcessId = 1;

class MessageReceiver : public EmbeddedWorkerTestHelper {
 public:
  MessageReceiver(ServiceWorkerContextCore* context)
      : EmbeddedWorkerTestHelper(context, kRenderProcessId),
        current_embedded_worker_id_(0),
        current_request_id_(0) {}
  virtual ~MessageReceiver() {}

  virtual bool OnSendMessageToWorker(int thread_id,
                                     int embedded_worker_id,
                                     int request_id,
                                     const IPC::Message& message) OVERRIDE {
    if (EmbeddedWorkerTestHelper::OnSendMessageToWorker(
            thread_id, embedded_worker_id, request_id, message)) {
      return true;
    }
    current_embedded_worker_id_ = embedded_worker_id;
    current_request_id_ = request_id;
    bool handled = true;
    IPC_BEGIN_MESSAGE_MAP(MessageReceiver, message)
      IPC_MESSAGE_HANDLER(TestMsg_Message, OnMessage)
      IPC_MESSAGE_HANDLER(TestMsg_Request, OnRequest)
      IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP()
    return handled;
  }

 private:
  void OnMessage() {
    // Do nothing.
  }

  void OnRequest(int value) {
    // Double the given value and send back the response.
    SimulateSendMessageToBrowser(current_embedded_worker_id_,
                                 current_request_id_,
                                 TestMsg_Response(value * 2));
  }

  int current_embedded_worker_id_;
  int current_request_id_;
  DISALLOW_COPY_AND_ASSIGN(MessageReceiver);
};

void ReceiveResponse(ServiceWorkerStatusCode* status_out,
                     int* value_out,
                     ServiceWorkerStatusCode status,
                     const IPC::Message& message) {
  Tuple1<int> param;
  ASSERT_TRUE(TestMsg_Response::Read(&message, &param));
  *status_out = status;
  *value_out = param.a;
}

void VerifyCalled(bool* called) {
  *called = true;
}

void ObserveStatusChanges(ServiceWorkerVersion* version,
                          std::vector<ServiceWorkerVersion::Status>* statuses) {
  statuses->push_back(version->status());
  version->RegisterStatusChangeCallback(
      base::Bind(&ObserveStatusChanges, make_scoped_refptr(version), statuses));
}

}  // namespace

class ServiceWorkerVersionTest : public testing::Test {
 protected:
  ServiceWorkerVersionTest()
      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}

  virtual void SetUp() OVERRIDE {
    context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL));
    helper_.reset(new MessageReceiver(context_.get()));

    registration_ = new ServiceWorkerRegistration(
        GURL("http://www.example.com/*"),
        GURL("http://www.example.com/service_worker.js"),
        1L, context_->AsWeakPtr());
    version_ = new ServiceWorkerVersion(
        registration_,
        1L, context_->AsWeakPtr());

    // Simulate adding one process to the worker.
    int embedded_worker_id = version_->embedded_worker()->embedded_worker_id();
    helper_->SimulateAddProcessToWorker(embedded_worker_id, kRenderProcessId);
  }

  virtual void TearDown() OVERRIDE {
    version_ = 0;
    registration_ = 0;
    helper_.reset();
    context_.reset();
  }

  TestBrowserThreadBundle thread_bundle_;
  scoped_ptr<ServiceWorkerContextCore> context_;
  scoped_ptr<EmbeddedWorkerTestHelper> helper_;
  scoped_refptr<ServiceWorkerRegistration> registration_;
  scoped_refptr<ServiceWorkerVersion> version_;
  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
};

TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
  // Call StartWorker() multiple times.
  ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(CreateReceiverOnCurrentThread(&status1));
  version_->StartWorker(CreateReceiverOnCurrentThread(&status2));

  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Call StartWorker() after it's started.
  version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
  base::RunLoop().RunUntilIdle();

  // All should just succeed.
  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_EQ(SERVICE_WORKER_OK, status3);

  // Call StopWorker() multiple times.
  status1 = SERVICE_WORKER_ERROR_FAILED;
  status2 = SERVICE_WORKER_ERROR_FAILED;
  status3 = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
  version_->StopWorker(CreateReceiverOnCurrentThread(&status2));

  // Also try calling StartWorker while StopWorker is in queue.
  version_->StartWorker(CreateReceiverOnCurrentThread(&status3));

  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // All StopWorker should just succeed, while StartWorker fails.
  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status3);
}

TEST_F(ServiceWorkerVersionTest, SendMessage) {
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // Send a message without starting the worker.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->SendMessage(TestMsg_Message(),
                        CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);

  // The worker should be now started.
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Stop the worker, and then send the message immediately.
  ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
  version_->SendMessage(TestMsg_Message(),
                       CreateReceiverOnCurrentThread(&msg_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, stop_status);

  // SendMessage should return START_WORKER_FAILED error since it tried to
  // start a worker while it was stopping.
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
}

TEST_F(ServiceWorkerVersionTest, ReSendMessageAfterStop) {
  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());

  // Start the worker.
  ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StartWorker(CreateReceiverOnCurrentThread(&start_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, start_status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());

  // Stop the worker, and then send the message immediately.
  ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
  version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
  version_->SendMessage(TestMsg_Message(),
                       CreateReceiverOnCurrentThread(&msg_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, stop_status);

  // SendMessage should return START_WORKER_FAILED error since it tried to
  // start a worker while it was stopping.
  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);

  // Resend the message, which should succeed and restart the worker.
  version_->SendMessage(TestMsg_Message(),
                       CreateReceiverOnCurrentThread(&msg_status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, msg_status);
  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
}

TEST_F(ServiceWorkerVersionTest, SendMessageAndRegisterCallback) {
  // Send multiple messages and verify responses.
  ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
  ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
  int value1 = -1, value2 = -1;

  version_->SendMessageAndRegisterCallback(
      TestMsg_Request(111),
      base::Bind(&ReceiveResponse, &status1, &value1));
  version_->SendMessageAndRegisterCallback(
      TestMsg_Request(333),
      base::Bind(&ReceiveResponse, &status2, &value2));
  base::RunLoop().RunUntilIdle();

  EXPECT_EQ(SERVICE_WORKER_OK, status1);
  EXPECT_EQ(SERVICE_WORKER_OK, status2);
  EXPECT_EQ(111 * 2, value1);
  EXPECT_EQ(333 * 2, value2);
}

TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
  EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());

  // Dispatch an install event.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
  EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());

  // Wait for the completion.
  bool status_change_called = false;
  version_->RegisterStatusChangeCallback(
      base::Bind(&VerifyCalled, &status_change_called));

  base::RunLoop().RunUntilIdle();

  // After successful completion, version's status must be changed to
  // INSTALLED, and status change callback must have been fired.
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(status_change_called);
  EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version_->status());
}

TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
  version_->SetStatus(ServiceWorkerVersion::INSTALLED);
  EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version_->status());

  // Dispatch an activate event.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
  EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());

  // Wait for the completion.
  bool status_change_called = false;
  version_->RegisterStatusChangeCallback(
      base::Bind(&VerifyCalled, &status_change_called));

  base::RunLoop().RunUntilIdle();

  // After successful completion, version's status must be changed to
  // ACTIVE, and status change callback must have been fired.
  EXPECT_EQ(SERVICE_WORKER_OK, status);
  EXPECT_TRUE(status_change_called);
  EXPECT_EQ(ServiceWorkerVersion::ACTIVE, version_->status());
}

TEST_F(ServiceWorkerVersionTest, DISABLED_RepeatedlyObserveStatusChanges) {
  EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());

  // Repeatedly observe status changes (the callback re-registers itself).
  std::vector<ServiceWorkerVersion::Status> statuses;
  version_->RegisterStatusChangeCallback(
      base::Bind(&ObserveStatusChanges, version_, &statuses));

  // Dispatch some events.
  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);

  status = SERVICE_WORKER_ERROR_FAILED;
  version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(SERVICE_WORKER_OK, status);

  // Verify that we could successfully observe repeated status changes.
  ASSERT_EQ(4U, statuses.size());
  ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
  ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
  ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
  ASSERT_EQ(ServiceWorkerVersion::ACTIVE, statuses[3]);
}

}  // namespace content
<|endoftext|>


<commit_before>#pragma once
#include <complex>
#include <string>
#include <type_traits>
#include <limits>

namespace tbm { namespace num {

namespace detail {
    template<class scalar_t>
    struct complex_traits {
        using real_t = scalar_t;
        using complex_t = std::complex<scalar_t>;
        static constexpr bool is_complex = false;
    };

    template<class scalar_t>
    struct complex_traits<std::complex<scalar_t>> {
        using real_t = scalar_t;
        using complex_t = std::complex<scalar_t>;
        static constexpr bool is_complex = true;
    };
} // namespace detail

template<class scalar_t>
using get_real_t = typename detail::complex_traits<scalar_t>::real_t;
template<class scalar_t>
using get_complex_t = typename detail::complex_traits<scalar_t>::complex_t;

template<class scalar_t>
inline constexpr bool is_complex() { return detail::complex_traits<scalar_t>::is_complex; }

template<class scalar_t>
inline scalar_t conjugate(scalar_t value) { return value; }
template<class scalar_t>
inline std::complex<scalar_t> conjugate(std::complex<scalar_t> value) { return std::conj(value); }

template<class scalar_t>
inline scalar_t complex_cast(std::complex<double> v) { return v; }
template<>
inline std::complex<float> complex_cast(std::complex<double> v) {
    return {static_cast<float>(v.real()), static_cast<float>(v.imag())};
}
template<>
inline double complex_cast<double>(std::complex<double> v) { return v.real(); }
template<>
inline float complex_cast<float>(std::complex<double> v) { return static_cast<float>(v.real()); }

template<class scalar_t>
inline std::string scalar_name() { return ""; }
template<> inline std::string scalar_name<float>() { return "float"; }
template<> inline std::string scalar_name<double>() { return "double"; }
template<> inline std::string scalar_name<std::complex<float>>() { return "complex<float>"; }
template<> inline std::string scalar_name<std::complex<double>>() { return "complex<double>"; }

/**
  Floating-point equality with precision in ULP (units in the last place)
 */
template<class T, class = typename std::enable_if<std::is_floating_point<T>::value, void>::type>
bool approx_equal(T x, T y, int ulp = 1) {
    auto const diff = std::abs(x - y);
    auto const scale = std::abs(x + y);
    return diff <= std::numeric_limits<T>::epsilon() * scale * ulp
           || diff <= std::numeric_limits<T>::min(); // subnormal case
}

}} // namespace tbm::num
<commit_msg>Document numeric traits<commit_after>#pragma once
#include <complex>
#include <string>
#include <type_traits>
#include <limits>

namespace tbm { namespace num {

namespace detail {
    template<class T>
    struct complex_traits {
        static_assert(std::is_arithmetic<T>::value, "");

        using real_t = T;
        using complex_t = std::complex<T>;
        static constexpr bool is_complex = false;
    };

    template<class T>
    struct complex_traits<std::complex<T>> {
        using real_t = T;
        using complex_t = std::complex<T>;
        static constexpr bool is_complex = true;
    };
} // namespace detail

/**
 Return the real type corresponding to the given scalar type

 For example:
   std::complex<float> -> float
   float               -> float
 */
template<class scalar_t>
using get_real_t = typename detail::complex_traits<scalar_t>::real_t;

/**
 Return the complex type corresponding to the given scalar type

 For example:
   std::complex<float> -> std::complex<float>
   float               -> std::complex<float>
 */
template<class scalar_t>
using get_complex_t = typename detail::complex_traits<scalar_t>::complex_t;

/**
 Is the given scalar type complex?
 */
template<class scalar_t>
inline constexpr bool is_complex() { return detail::complex_traits<scalar_t>::is_complex; }

/**
 Return the complex conjugate in the same scalar type as the input

 The standard `conj` function always returns `std::complex<T>`
 which is not convenient for generic algorithms.
 */
template<class scalar_t>
inline scalar_t conjugate(scalar_t value) { return value; }
template<class scalar_t>
inline std::complex<scalar_t> conjugate(std::complex<scalar_t> value) { return std::conj(value); }

/**
 Cast a `std::complex<double>` to another scalar

 The conversion loses precision and/or the imaginary part, as intended.
 */
template<class scalar_t>
inline scalar_t complex_cast(std::complex<double> v) { return v; }
template<>
inline std::complex<float> complex_cast<std::complex<float>>(std::complex<double> v) {
    return {static_cast<float>(v.real()), static_cast<float>(v.imag())};
}
template<>
inline double complex_cast<double>(std::complex<double> v) { return v.real(); }
template<>
inline float complex_cast<float>(std::complex<double> v) { return static_cast<float>(v.real()); }

/**
 Return a human readable name of the scalar type
 */
template<class scalar_t> inline std::string scalar_name();
template<> inline std::string scalar_name<float>() { return "float"; }
template<> inline std::string scalar_name<double>() { return "double"; }
template<> inline std::string scalar_name<std::complex<float>>() { return "complex<float>"; }
template<> inline std::string scalar_name<std::complex<double>>() { return "complex<double>"; }

/**
 Floating-point equality with precision in ULP (units in the last place)
 */
template<class T, class = typename std::enable_if<std::is_floating_point<T>::value, void>::type>
bool approx_equal(T x, T y, int ulp = 1) {
    auto const diff = std::abs(x - y);
    auto const scale = std::abs(x + y);
    return diff <= std::numeric_limits<T>::epsilon() * scale * ulp
           || diff <= std::numeric_limits<T>::min(); // subnormal case
}

}} // namespace tbm::num
<|endoftext|>