<commit_before>// Copyright (c) 2012 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 "net/socket/tcp_server_socket.h"

#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/tcp_client_socket.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

namespace net {

namespace {
const int kListenBacklog = 5;

class TCPServerSocketTest : public PlatformTest {
 protected:
  TCPServerSocketTest()
      : socket_(NULL, NetLog::Source()) {
  }

  void SetUpIPv4() {
    IPEndPoint address;
    ParseAddress("127.0.0.1", 0, &address);
    ASSERT_EQ(OK, socket_.Listen(address, kListenBacklog));
    ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
  }

  void SetUpIPv6(bool* success) {
    *success = false;
    IPEndPoint address;
    ParseAddress("::1", 0, &address);
    if (socket_.Listen(address, kListenBacklog) != 0) {
      LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is "
          "disabled. Skipping the test";
      return;
    }
    ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
    *success = true;
  }

  void ParseAddress(std::string ip_str, int port, IPEndPoint* address) {
    IPAddressNumber ip_number;
    bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
    if (!rv)
      return;
    *address = IPEndPoint(ip_number, port);
  }

  static IPEndPoint GetPeerAddress(StreamSocket* socket) {
    IPEndPoint address;
    EXPECT_EQ(OK, socket->GetPeerAddress(&address));
    return address;
  }

  AddressList local_address_list() const {
    return AddressList(local_address_);
  }

  TCPServerSocket socket_;
  IPEndPoint local_address_;
};

TEST_F(TCPServerSocketTest, Accept) {
  ASSERT_NO_FATAL_FAILURE(SetUpIPv4());

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;
  int result = socket_.Accept(&accepted_socket, accept_callback.callback());
  if (result == ERR_IO_PENDING)
    result = accept_callback.WaitForResult();
  ASSERT_EQ(OK, result);

  ASSERT_TRUE(accepted_socket.get() != NULL);

  // Both sockets should be on the loopback network interface.
  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());

  EXPECT_EQ(OK, connect_callback.WaitForResult());
}

// Test Accept() callback.
TEST_F(TCPServerSocketTest, AcceptAsync) {
  ASSERT_NO_FATAL_FAILURE(SetUpIPv4());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;

  ASSERT_EQ(ERR_IO_PENDING,
            socket_.Accept(&accepted_socket, accept_callback.callback()));

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  EXPECT_EQ(OK, connect_callback.WaitForResult());
  EXPECT_EQ(OK, accept_callback.WaitForResult());

  EXPECT_TRUE(accepted_socket != NULL);

  // Both sockets should be on the loopback network interface.
  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());
}

// Accept two connections simultaneously.
TEST_F(TCPServerSocketTest, Accept2Connections) {
  ASSERT_NO_FATAL_FAILURE(SetUpIPv4());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;

  ASSERT_EQ(ERR_IO_PENDING,
            socket_.Accept(&accepted_socket, accept_callback.callback()));

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  TestCompletionCallback connect_callback2;
  TCPClientSocket connecting_socket2(local_address_list(),
                                     NULL, NetLog::Source());
  connecting_socket2.Connect(connect_callback2.callback());

  EXPECT_EQ(OK, accept_callback.WaitForResult());

  TestCompletionCallback accept_callback2;
  scoped_ptr<StreamSocket> accepted_socket2;
  int result = socket_.Accept(&accepted_socket2, accept_callback2.callback());
  if (result == ERR_IO_PENDING)
    result = accept_callback2.WaitForResult();
  ASSERT_EQ(OK, result);

  EXPECT_EQ(OK, connect_callback.WaitForResult());

  EXPECT_TRUE(accepted_socket != NULL);
  EXPECT_TRUE(accepted_socket2 != NULL);
  EXPECT_NE(accepted_socket.get(), accepted_socket2.get());

  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());
  EXPECT_EQ(GetPeerAddress(accepted_socket2.get()).address(),
            local_address_.address());
}

TEST_F(TCPServerSocketTest, AcceptIPv6) {
  bool initialized = false;
  ASSERT_NO_FATAL_FAILURE(SetUpIPv6(&initialized));
  if (!initialized)
    return;

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;
  int result = socket_.Accept(&accepted_socket, accept_callback.callback());
  if (result == ERR_IO_PENDING)
    result = accept_callback.WaitForResult();
  ASSERT_EQ(OK, result);

  ASSERT_TRUE(accepted_socket.get() != NULL);

  // Both sockets should be on the loopback network interface.
  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());

  EXPECT_EQ(OK, connect_callback.WaitForResult());
}

TEST_F(TCPServerSocketTest, AcceptIO) {
  ASSERT_NO_FATAL_FAILURE(SetUpIPv4());

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;
  int result = socket_.Accept(&accepted_socket, accept_callback.callback());
  ASSERT_EQ(OK, accept_callback.GetResult(result));

  ASSERT_TRUE(accepted_socket.get() != NULL);

  // Both sockets should be on the loopback network interface.
  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());

  EXPECT_EQ(OK, connect_callback.WaitForResult());

  const std::string message("test message");
  std::vector<char> buffer(message.size());

  size_t bytes_written = 0;
  while (bytes_written < message.size()) {
    scoped_refptr<net::IOBufferWithSize> write_buffer(
        new net::IOBufferWithSize(message.size() - bytes_written));
    memmove(write_buffer->data(), message.data(), message.size());

    TestCompletionCallback write_callback;
    int write_result = accepted_socket->Write(
        write_buffer.get(), write_buffer->size(), write_callback.callback());
    write_result = write_callback.GetResult(write_result);
    ASSERT_TRUE(write_result >= 0);
    ASSERT_TRUE(bytes_written + write_result <= message.size());
    bytes_written += write_result;
  }

  size_t bytes_read = 0;
  while (bytes_read < message.size()) {
    scoped_refptr<net::IOBufferWithSize> read_buffer(
        new net::IOBufferWithSize(message.size() - bytes_read));
    TestCompletionCallback read_callback;
    int read_result = connecting_socket.Read(
        read_buffer.get(), read_buffer->size(), read_callback.callback());
    read_result = read_callback.GetResult(read_result);
    ASSERT_TRUE(read_result >= 0);
    ASSERT_TRUE(bytes_read + read_result <= message.size());
    memmove(&buffer[bytes_read], read_buffer->data(), read_result);
    bytes_read += read_result;
  }

  std::string received_message(buffer.begin(), buffer.end());
  ASSERT_EQ(message, received_message);
}

}  // namespace

}  // namespace net
<commit_msg>After removing allowReuseAddress and always setting SO_REUSEADDR, we need a test to ensure that the ports are not reused on *nix systems.<commit_after>// Copyright (c) 2012 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 "net/socket/tcp_server_socket.h"

#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/tcp_client_socket.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

namespace net {

namespace {
const int kListenBacklog = 5;

class TCPServerSocketTest : public PlatformTest {
 protected:
  TCPServerSocketTest()
      : socket_(NULL, NetLog::Source()) {
  }

  void SetUpIPv4() {
    IPEndPoint address;
    ParseAddress("127.0.0.1", 0, &address);
    ASSERT_EQ(OK, socket_.Listen(address, kListenBacklog));
    ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
  }

  void SetUpIPv6(bool* success) {
    *success = false;
    IPEndPoint address;
    ParseAddress("::1", 0, &address);
    if (socket_.Listen(address, kListenBacklog) != 0) {
      LOG(ERROR) << "Failed to listen on ::1 - probably because IPv6 is "
          "disabled. Skipping the test";
      return;
    }
    ASSERT_EQ(OK, socket_.GetLocalAddress(&local_address_));
    *success = true;
  }

  void ParseAddress(std::string ip_str, int port, IPEndPoint* address) {
    IPAddressNumber ip_number;
    bool rv = ParseIPLiteralToNumber(ip_str, &ip_number);
    if (!rv)
      return;
    *address = IPEndPoint(ip_number, port);
  }

  static IPEndPoint GetPeerAddress(StreamSocket* socket) {
    IPEndPoint address;
    EXPECT_EQ(OK, socket->GetPeerAddress(&address));
    return address;
  }

  AddressList local_address_list() const {
    return AddressList(local_address_);
  }

  TCPServerSocket socket_;
  IPEndPoint local_address_;
};

TEST_F(TCPServerSocketTest, Accept) {
  ASSERT_NO_FATAL_FAILURE(SetUpIPv4());

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;
  int result = socket_.Accept(&accepted_socket, accept_callback.callback());
  if (result == ERR_IO_PENDING)
    result = accept_callback.WaitForResult();
  ASSERT_EQ(OK, result);

  ASSERT_TRUE(accepted_socket.get() != NULL);

  // Both sockets should be on the loopback network interface.
  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());

  EXPECT_EQ(OK, connect_callback.WaitForResult());
}

// Test Accept() callback.
TEST_F(TCPServerSocketTest, AcceptAsync) {
  ASSERT_NO_FATAL_FAILURE(SetUpIPv4());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;

  ASSERT_EQ(ERR_IO_PENDING,
            socket_.Accept(&accepted_socket, accept_callback.callback()));

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  EXPECT_EQ(OK, connect_callback.WaitForResult());
  EXPECT_EQ(OK, accept_callback.WaitForResult());

  EXPECT_TRUE(accepted_socket != NULL);

  // Both sockets should be on the loopback network interface.
  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());
}

// Accept two connections simultaneously.
TEST_F(TCPServerSocketTest, Accept2Connections) {
  ASSERT_NO_FATAL_FAILURE(SetUpIPv4());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;

  ASSERT_EQ(ERR_IO_PENDING,
            socket_.Accept(&accepted_socket, accept_callback.callback()));

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  TestCompletionCallback connect_callback2;
  TCPClientSocket connecting_socket2(local_address_list(),
                                     NULL, NetLog::Source());
  connecting_socket2.Connect(connect_callback2.callback());

  EXPECT_EQ(OK, accept_callback.WaitForResult());

  TestCompletionCallback accept_callback2;
  scoped_ptr<StreamSocket> accepted_socket2;
  int result = socket_.Accept(&accepted_socket2, accept_callback2.callback());
  if (result == ERR_IO_PENDING)
    result = accept_callback2.WaitForResult();
  ASSERT_EQ(OK, result);

  EXPECT_EQ(OK, connect_callback.WaitForResult());

  EXPECT_TRUE(accepted_socket != NULL);
  EXPECT_TRUE(accepted_socket2 != NULL);
  EXPECT_NE(accepted_socket.get(), accepted_socket2.get());

  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());
  EXPECT_EQ(GetPeerAddress(accepted_socket2.get()).address(),
            local_address_.address());
}

TEST_F(TCPServerSocketTest, AcceptIPv6) {
  bool initialized = false;
  ASSERT_NO_FATAL_FAILURE(SetUpIPv6(&initialized));
  if (!initialized)
    return;

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;
  int result = socket_.Accept(&accepted_socket, accept_callback.callback());
  if (result == ERR_IO_PENDING)
    result = accept_callback.WaitForResult();
  ASSERT_EQ(OK, result);

  ASSERT_TRUE(accepted_socket.get() != NULL);

  // Both sockets should be on the loopback network interface.
  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());

  EXPECT_EQ(OK, connect_callback.WaitForResult());
}

TEST_F(TCPServerSocketTest, AcceptIO) {
  ASSERT_NO_FATAL_FAILURE(SetUpIPv4());

  TestCompletionCallback connect_callback;
  TCPClientSocket connecting_socket(local_address_list(),
                                    NULL, NetLog::Source());
  connecting_socket.Connect(connect_callback.callback());

  TestCompletionCallback accept_callback;
  scoped_ptr<StreamSocket> accepted_socket;
  int result = socket_.Accept(&accepted_socket, accept_callback.callback());
  ASSERT_EQ(OK, accept_callback.GetResult(result));

  ASSERT_TRUE(accepted_socket.get() != NULL);

  // Both sockets should be on the loopback network interface.
  EXPECT_EQ(GetPeerAddress(accepted_socket.get()).address(),
            local_address_.address());

  EXPECT_EQ(OK, connect_callback.WaitForResult());

  const std::string message("test message");
  std::vector<char> buffer(message.size());

  size_t bytes_written = 0;
  while (bytes_written < message.size()) {
    scoped_refptr<net::IOBufferWithSize> write_buffer(
        new net::IOBufferWithSize(message.size() - bytes_written));
    memmove(write_buffer->data(), message.data(), message.size());

    TestCompletionCallback write_callback;
    int write_result = accepted_socket->Write(
        write_buffer.get(), write_buffer->size(), write_callback.callback());
    write_result = write_callback.GetResult(write_result);
    ASSERT_TRUE(write_result >= 0);
    ASSERT_TRUE(bytes_written + write_result <= message.size());
    bytes_written += write_result;
  }

  size_t bytes_read = 0;
  while (bytes_read < message.size()) {
    scoped_refptr<net::IOBufferWithSize> read_buffer(
        new net::IOBufferWithSize(message.size() - bytes_read));
    TestCompletionCallback read_callback;
    int read_result = connecting_socket.Read(
        read_buffer.get(), read_buffer->size(), read_callback.callback());
    read_result = read_callback.GetResult(read_result);
    ASSERT_TRUE(read_result >= 0);
    ASSERT_TRUE(bytes_read + read_result <= message.size());
    memmove(&buffer[bytes_read], read_buffer->data(), read_result);
    bytes_read += read_result;
  }

  std::string received_message(buffer.begin(), buffer.end());
  ASSERT_EQ(message, received_message);
}

TEST_F(TCPServerSocketTest, Rebind) {
  IPEndPoint address;
  // Bind to a random, unused port.
  ParseAddress("127.0.0.1", 0, &address);

  scoped_ptr<TCPServerSocket> socket(
      new TCPServerSocket(NULL, NetLog::Source()));
  ASSERT_EQ(OK, socket->Listen(address, kListenBacklog));

  // Retrieve the real endpoint bound.
  ASSERT_EQ(OK, socket->GetLocalAddress(&address));

  scoped_ptr<TCPServerSocket> conflict_socket(
      new TCPServerSocket(NULL, NetLog::Source()));
  ASSERT_NE(OK, conflict_socket->Listen(address, kListenBacklog));

  // Unbind.
  socket.reset(NULL);

  ASSERT_EQ(OK, conflict_socket->Listen(address, kListenBacklog));
}

}  // namespace

}  // namespace net
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "../Util/GitDescription.h"
#include "../Util/SimpleLogger.h"
#include "../Server/DataStructures/SharedBarriers.h"

#include <iostream>

int main() {
    LogPolicy::GetInstance().Unmute();
    SimpleLogger().Write() <<
            "starting up engines, " << g_GIT_DESCRIPTION << ", " <<
            "compiled at " << __DATE__ << ", " __TIME__;
    SimpleLogger().Write() << "Releasing all locks";
    SharedBarriers barrier;
    barrier.pending_update_mutex.unlock();
    barrier.query_mutex.unlock();
    barrier.update_mutex.unlock();
    return 0;
}
<commit_msg>catch exceptions that may occur, coverity issue 1198846<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "../Util/GitDescription.h"
#include "../Util/SimpleLogger.h"
#include "../Server/DataStructures/SharedBarriers.h"

#include <iostream>

int main() {
    LogPolicy::GetInstance().Unmute();
    try
    {
        SimpleLogger().Write() <<
                "starting up engines, " << g_GIT_DESCRIPTION << ", " <<
                "compiled at " << __DATE__ << ", " __TIME__;
        SimpleLogger().Write() << "Releasing all locks";
        SharedBarriers barrier;
        barrier.pending_update_mutex.unlock();
        barrier.query_mutex.unlock();
        barrier.update_mutex.unlock();
    }
    catch(const std::exception & e)
    {
        SimpleLogger().Write(logWARNING) << "[excpetion] " << e.what();
    }
    return 0;
}
<|endoftext|>


<commit_before>/*
 *     Copyright (C) 2005 by Thorsten Staerk <kde@staerk.de>
 *                   2007 the ktimetracker developers
 *
 *   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; either version 2 of the License, or
 *   (at your option) 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 Street, Fifth Floor
 *      Boston, MA  02110-1301  USA.
 *
 */

#include "karm_part.h"

#include <QByteArray>
#include <QFile>
#include <QMenu>
#include <QTextStream>
#include <QtDBus>

#include <KAboutData>
#include <KAction>
#include <KActionCollection>
#include <KComponentData>
#include <KFileDialog>
#include <KGlobal>
#include <KIcon>
#include <KLocale>
#include <KStandardAction>
#include <KStandardDirs>
#include <KXMLGUIFactory>

#include <kdemacros.h>

#include "mainwindow.h"
#include "kaccelmenuwatch.h"
#include "karmerrors.h"
#include "task.h"
#include "preferences.h"
#include "tray.h"
#include "version.h"
#include "ktimetracker.h"
#include "timetrackerwidget.h"

karmPart::karmPart( QWidget *parentWidget, QObject *parent )
    : KParts::ReadWritePart(parent)
{
  // we need an instance
  setComponentData( karmPartFactory::componentData() );

  mMainWidget = new TimetrackerWidget( parentWidget );
  setWidget( mMainWidget );
  makeMenus();
  mMainWidget->openFile( KStandardDirs::locateLocal( "appdata",
                        QString::fromLatin1( "karm.ics" ) ) );

  // connections
  connect( mMainWidget, SIGNAL( totalTimesChanged( long, long ) ),
           this, SLOT( updateTime( long, long ) ) );
  connect( mMainWidget, SIGNAL( statusBarTextChangeRequested( QString ) ),
                 this, SLOT( setStatusBar( QString ) ) );

  // Setup context menu request handling
  connect( mMainWidget,
           SIGNAL( contextMenuRequested( const QPoint& ) ),
           this,
           SLOT( taskViewCustomContextMenuRequested( const QPoint& ) ) );

  if ( KTimeTrackerSettings::trayIcon() ) mTray = new TrayIcon( this );
  else mTray = new TrayIcon( );

  connect( mTray, SIGNAL( quitSelected() ), SLOT( quit() ) );

  connect( mMainWidget, SIGNAL( timersActive() ), mTray, SLOT( startClock() ) );
  connect( mMainWidget, SIGNAL( timersInactive() ), mTray, SLOT( stopClock() ) );
  connect( mMainWidget, SIGNAL( tasksChanged( const QList<Task*>& ) ),
           mTray, SLOT( updateToolTip( QList<Task*> ) ));
}

karmPart::~karmPart()
{
}

void karmPart::makeMenus()
{
  mMainWidget->setupActions( actionCollection() );
  KAction *actionKeyBindings;

  actionKeyBindings = KStandardAction::keyBindings( this, SLOT( keyBindings() ),
      actionCollection() );

  setXMLFile( QString::fromLatin1( "karmui.rc" ) );

  // Tool tops must be set after the createGUI.
  actionKeyBindings->setToolTip( i18n("Configure key bindings") );
  actionKeyBindings->setWhatsThis( i18n("This will let you configure key"
                                        "bindings which is specific to ktimetracer") );
}

void karmPart::setStatusBar(const QString & qs)
{
  kDebug(5970) <<"Entering setStatusBar";
  emit setStatusBarText(qs);
}

bool karmPart::openFile()
{
  mMainWidget->openFile();

  return true;
}

bool karmPart::saveFile()
{
  mMainWidget->saveFile();

  return true;
}

// It's usually safe to leave the factory code alone.. with the
// notable exception of the KAboutData data
KComponentData *karmPartFactory::s_instance = 0L;
KAboutData* karmPartFactory::s_about = 0L;

karmPartFactory::karmPartFactory()
    : KParts::Factory()
{
}

karmPartFactory::~karmPartFactory()
{
    delete s_instance;
    delete s_about;

    s_instance = 0L;
}

KParts::Part* karmPartFactory::createPartObject( QWidget *parentWidget, QObject *parent,
                                                 const char* classname, const QStringList &args )
{
  Q_UNUSED( args );

  // Create an instance of our Part
  karmPart* obj = new karmPart( parentWidget, parent );

  // See if we are to be read-write or not
  if ( QLatin1String( classname ) == QLatin1String( "KParts::ReadOnlyPart" ) )
      obj->setReadWrite(false);

  return obj;
}

const KComponentData &karmPartFactory::componentData()
{
    if( !s_instance )
    {
        s_about = new KAboutData("karmpart", 0, ki18n("karmPart"), "0.1");
        s_about->addAuthor(ki18n("Thorsten Staerk"), KLocalizedString(), "thorsten@staerk.de");
        s_instance = new KComponentData(s_about);
    }
    return *s_instance;
}

extern "C"
{
    KDE_EXPORT void* init_libkarmpart()
    {
	KGlobal::locale()->insertCatalog("karm");
        return new karmPartFactory;
    }
}

void karmPart::taskViewCustomContextMenuRequested( const QPoint& point )
{
    QMenu* pop = dynamic_cast<QMenu*>(
                          factory()->container( i18n( "task_popup" ), this ) );
    if ( pop )
      pop->popup( point );
}

#include "karm_part.moc"
<commit_msg>* Type<commit_after>/*
 *     Copyright (C) 2005 by Thorsten Staerk <kde@staerk.de>
 *                   2007 the ktimetracker developers
 *
 *   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; either version 2 of the License, or
 *   (at your option) 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 Street, Fifth Floor
 *      Boston, MA  02110-1301  USA.
 *
 */

#include "karm_part.h"

#include <QByteArray>
#include <QFile>
#include <QMenu>
#include <QTextStream>
#include <QtDBus>

#include <KAboutData>
#include <KAction>
#include <KActionCollection>
#include <KComponentData>
#include <KFileDialog>
#include <KGlobal>
#include <KIcon>
#include <KLocale>
#include <KStandardAction>
#include <KStandardDirs>
#include <KXMLGUIFactory>

#include <kdemacros.h>

#include "mainwindow.h"
#include "kaccelmenuwatch.h"
#include "karmerrors.h"
#include "task.h"
#include "preferences.h"
#include "tray.h"
#include "version.h"
#include "ktimetracker.h"
#include "timetrackerwidget.h"

karmPart::karmPart( QWidget *parentWidget, QObject *parent )
    : KParts::ReadWritePart(parent)
{
  // we need an instance
  setComponentData( karmPartFactory::componentData() );

  mMainWidget = new TimetrackerWidget( parentWidget );
  setWidget( mMainWidget );
  makeMenus();
  mMainWidget->openFile( KStandardDirs::locateLocal( "appdata",
                        QString::fromLatin1( "karm.ics" ) ) );

  // connections
  connect( mMainWidget, SIGNAL( totalTimesChanged( long, long ) ),
           this, SLOT( updateTime( long, long ) ) );
  connect( mMainWidget, SIGNAL( statusBarTextChangeRequested( QString ) ),
                 this, SLOT( setStatusBar( QString ) ) );

  // Setup context menu request handling
  connect( mMainWidget,
           SIGNAL( contextMenuRequested( const QPoint& ) ),
           this,
           SLOT( taskViewCustomContextMenuRequested( const QPoint& ) ) );

  if ( KTimeTrackerSettings::trayIcon() ) mTray = new TrayIcon( this );
  else mTray = new TrayIcon( );

  connect( mTray, SIGNAL( quitSelected() ), SLOT( quit() ) );

  connect( mMainWidget, SIGNAL( timersActive() ), mTray, SLOT( startClock() ) );
  connect( mMainWidget, SIGNAL( timersInactive() ), mTray, SLOT( stopClock() ) );
  connect( mMainWidget, SIGNAL( tasksChanged( const QList<Task*>& ) ),
           mTray, SLOT( updateToolTip( QList<Task*> ) ));
}

karmPart::~karmPart()
{
}

void karmPart::makeMenus()
{
  mMainWidget->setupActions( actionCollection() );
  KAction *actionKeyBindings;

  actionKeyBindings = KStandardAction::keyBindings( this, SLOT( keyBindings() ),
      actionCollection() );

  setXMLFile( QString::fromLatin1( "karmui.rc" ) );

  // Tool tops must be set after the createGUI.
  actionKeyBindings->setToolTip( i18n("Configure key bindings") );
  actionKeyBindings->setWhatsThis( i18n("This will let you configure key"
                                        "bindings which is specific to ktimetracker") );
}

void karmPart::setStatusBar(const QString & qs)
{
  kDebug(5970) <<"Entering setStatusBar";
  emit setStatusBarText(qs);
}

bool karmPart::openFile()
{
  mMainWidget->openFile();

  return true;
}

bool karmPart::saveFile()
{
  mMainWidget->saveFile();

  return true;
}

// It's usually safe to leave the factory code alone.. with the
// notable exception of the KAboutData data
KComponentData *karmPartFactory::s_instance = 0L;
KAboutData* karmPartFactory::s_about = 0L;

karmPartFactory::karmPartFactory()
    : KParts::Factory()
{
}

karmPartFactory::~karmPartFactory()
{
    delete s_instance;
    delete s_about;

    s_instance = 0L;
}

KParts::Part* karmPartFactory::createPartObject( QWidget *parentWidget, QObject *parent,
                                                 const char* classname, const QStringList &args )
{
  Q_UNUSED( args );

  // Create an instance of our Part
  karmPart* obj = new karmPart( parentWidget, parent );

  // See if we are to be read-write or not
  if ( QLatin1String( classname ) == QLatin1String( "KParts::ReadOnlyPart" ) )
      obj->setReadWrite(false);

  return obj;
}

const KComponentData &karmPartFactory::componentData()
{
    if( !s_instance )
    {
        s_about = new KAboutData("karmpart", 0, ki18n("karmPart"), "0.1");
        s_about->addAuthor(ki18n("Thorsten Staerk"), KLocalizedString(), "thorsten@staerk.de");
        s_instance = new KComponentData(s_about);
    }
    return *s_instance;
}

extern "C"
{
    KDE_EXPORT void* init_libkarmpart()
    {
	KGlobal::locale()->insertCatalog("karm");
        return new karmPartFactory;
    }
}

void karmPart::taskViewCustomContextMenuRequested( const QPoint& point )
{
    QMenu* pop = dynamic_cast<QMenu*>(
                          factory()->container( i18n( "task_popup" ), this ) );
    if ( pop )
      pop->popup( point );
}

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


<commit_before>/*
 *
 * synchronization_tests
 * ledger-core
 *
 * Created by Khalil Bellakrid on 15/05/2018.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <gtest/gtest.h>
#include "../BaseFixture.h"
#include <set>
#include <api/KeychainEngines.hpp>
#include <utils/DateUtils.hpp>
#include <wallet/bitcoin/database/BitcoinLikeAccountDatabaseHelper.h>
#include <wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.h>

class BitcoinLikeWalletP2SHSynchronization : public BaseFixture {

};

TEST_F(BitcoinLikeWalletP2SHSynchronization, MediumXpubSynchronization) {
    auto pool = newDefaultPool();
    {
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE,api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,"49'/<coin_type>'/<account>'/<node>/<address>");

        auto wallet = uv::wait(pool->createWallet("e847815f-488a-4301-b67c-378a5e9c8a61", "bitcoin_testnet", configuration));
        {
            auto nextIndex = uv::wait(wallet->getNextAccountIndex());
            EXPECT_EQ(nextIndex, 0);

            auto account = createBitcoinLikeAccount(wallet, nextIndex, P2SH_XPUB_INFO);

            auto receiver = make_receiver([=](const std::shared_ptr<api::Event> &event) {
                fmt::print("Received event {}\n", api::to_string(event->getCode()));
                if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                    return;
                EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
                EXPECT_EQ(event->getCode(),
                          api::EventCode::SYNCHRONIZATION_SUCCEED_ON_PREVIOUSLY_EMPTY_ACCOUNT);
                dispatcher->stop();
            });

            auto bus = account->synchronize();
            bus->subscribe(getTestExecutionContext(),receiver);

            dispatcher->waitUntilStopped();

            auto block = uv::wait(account->getLastBlock());
            auto blockHash = block.blockHash;
        }
    }
}

TEST_F(BitcoinLikeWalletP2SHSynchronization, SynchronizeOnceAtATime) {
    auto pool = newDefaultPool();
    {
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE,api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,"49'/<coin_type>'/<account>'/<node>/<address>");

        auto wallet = uv::wait(pool->createWallet("e847815f-488a-4301-b67c-378a5e9c8a62", "bitcoin_testnet",configuration));
        {
            auto nextIndex = uv::wait(wallet->getNextAccountIndex());
            EXPECT_EQ(nextIndex, 0);
            auto account = createBitcoinLikeAccount(wallet, nextIndex, P2SH_XPUB_INFO);
            auto eventBus = pool->getEventBus();
            eventBus->subscribe(getTestExecutionContext(),
                                           make_receiver([](const std::shared_ptr<api::Event> &event) {
                                               fmt::print("Received event {}\n", api::to_string(event->getCode()));
                                           }));
            auto bus = account->synchronize();
            bus->subscribe(getTestExecutionContext(),
                                              make_receiver([=](const std::shared_ptr<api::Event> &event) {
                                                  fmt::print("Received event {}\n", api::to_string(event->getCode()));
                                                  if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                                                      return;
                                                  EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
                                                  EXPECT_EQ(event->getCode(),
                                                            api::EventCode::SYNCHRONIZATION_SUCCEED_ON_PREVIOUSLY_EMPTY_ACCOUNT);
                                                  dispatcher->stop();
                                              }));
            EXPECT_EQ(bus, account->synchronize());
            dispatcher->waitUntilStopped();
        }
    }
}

TEST_F(BitcoinLikeWalletP2SHSynchronization, SynchronizeFromLastBlock) {
    auto pool = newDefaultPool();
    {
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE,api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,"49'/<coin_type>'/<account>'/<node>/<address>");

        auto wallet = uv::wait(pool->createWallet("e847815f-488a-4301-b67c-378a5e9c8a63", "bitcoin_testnet",configuration));
        createBitcoinLikeAccount(wallet, 0, P2SH_XPUB_INFO);
        auto synchronize = [wallet, pool, this] (bool expectNewOp) {
            auto account = uv::wait(wallet->getAccount(0));
            auto numberOfOp = 0;

            auto receiverNumberOp = make_receiver([&numberOfOp](const std::shared_ptr<api::Event> &event) {
                numberOfOp += 1;
            });

            auto eventBus = pool->getEventBus();
            eventBus->subscribe(getTestExecutionContext(),receiverNumberOp);
            auto bus = account->synchronize();

            auto receiver = make_receiver([=, &numberOfOp](const std::shared_ptr<api::Event> &event) {
                fmt::print("Received event {}\n", api::to_string(event->getCode()));
                if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                    return;

                EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
                EXPECT_EQ(expectNewOp, (numberOfOp > 0));
                dispatcher->stop();
            });

            bus->subscribe(getTestExecutionContext(),receiver);
            auto newBus = account->synchronize();
            EXPECT_EQ(bus, newBus);
            dispatcher->waitUntilStopped();
            return bus;
        };

        auto b1 = synchronize(true);
        auto b2 = synchronize(false);
        EXPECT_NE(b1, b2);
    }
}

TEST_F(BitcoinLikeWalletP2SHSynchronization, EraseDataSinceAfterSynchronization) {
    auto pool = newDefaultPool();
    const auto walletName = randomWalletName();
    {
        //Set configuration
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE, api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,
                                 "49'/<coin_type>'/<account>'/<node>/<address>");
        //Create wallet
        auto wallet = uv::wait(pool->createWallet(walletName, "bitcoin_testnet", configuration));
        //Create account
        auto account = createBitcoinLikeAccount(wallet, 0, P2SH_XPUB_INFO);
        //Sync account
        auto bus = account->synchronize();
        auto receiver = make_receiver([=](const std::shared_ptr<api::Event> &event) {
            fmt::print("Received event {}\n", api::to_string(event->getCode()));
            if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                return;

            EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
            dispatcher->stop();
        });
        bus->subscribe(getTestExecutionContext(),receiver);
        dispatcher->waitUntilStopped();

        auto accountCount = uv::wait(wallet->getAccountCount());
        EXPECT_EQ(accountCount, 1);
        auto accountFromWallet = uv::wait(wallet->getAccount(0));
        EXPECT_EQ(account, accountFromWallet);

        auto date = "2000-03-27T09:10:22Z";
        auto formatedDate = DateUtils::fromJSON(date);

        //Delete account
        auto code = uv::wait(wallet->eraseDataSince(formatedDate));
        EXPECT_EQ(code, api::ErrorCode::FUTURE_WAS_SUCCESSFULL);

        //Check if account was successfully deleted
        auto newAccountCount = uv::wait(wallet->getAccountCount());
        EXPECT_EQ(newAccountCount, 0);
        {
            soci::session sql(pool->getDatabaseSessionPool()->getPool());
            BitcoinLikeAccountDatabaseEntry entry;
            auto result = BitcoinLikeAccountDatabaseHelper::queryAccount(sql, account->getAccountUid(), entry);
            EXPECT_EQ(result, false);
        }

        //Delete wallet
        auto walletCode = uv::wait(pool->eraseDataSince(formatedDate));
        EXPECT_EQ(walletCode, api::ErrorCode::FUTURE_WAS_SUCCESSFULL);

        //Check if wallet was successfully deleted
        auto walletCount = uv::wait(pool->getWalletCount());
        EXPECT_EQ(walletCount, 0);
    }
}
TEST_F(BitcoinLikeWalletP2SHSynchronization, TestNetSynchronization) {
    auto pool = newDefaultPool();
    {
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE,api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,"49'/<coin_type>'/<account>'/<node>/<address>");
        auto wallet = uv::wait(pool->createWallet("testnet_wallet", "bitcoin_testnet",configuration));
        {
            auto nextIndex = uv::wait(wallet->getNextAccountIndex());
            auto info = uv::wait(wallet->getNextExtendedKeyAccountCreationInfo());
            info.extendedKeys.push_back("tpubDCcvqEHx7prGddpWTfEviiew5YLMrrKy4oJbt14teJZenSi6AYMAs2SNXwYXFzkrNYwECSmobwxESxMCrpfqw4gsUt88bcr8iMrJmbb8P2q");
            EXPECT_EQ(nextIndex, 0);
            auto account = createBitcoinLikeAccount(wallet, nextIndex, info);
            auto receiver = make_receiver([=](const std::shared_ptr<api::Event> &event) {
                fmt::print("Received event {}\n", api::to_string(event->getCode()));
                if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                    return;
                EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
                dispatcher->stop();
            });

            auto bus = account->synchronize();
            bus->subscribe(getTestExecutionContext(),receiver);
            dispatcher->waitUntilStopped();
        }
    }
}

TEST_F(BitcoinLikeWalletP2SHSynchronization, DecredParsingAndSerialization) {
    auto pool = newDefaultPool();
    {
        auto wallet = uv::wait(pool->createWallet("testnet_wallet", "decred",DynamicObject::newInstance()));
        auto strTx = "01000000016b9b4d4cdd2cf78907e62cddf31911ae4d4af1d89228ae4afc4459edee6a60c40100000000ffffff000240420f000000000000001976a9141d19445f397f6f0d3e2e6d741f61ba66b53886cf88acf0d31d000000000000001976a91415101bac61dca29add75996a0836a469dc8eee0788ac00000000ffffffff01000000000000000000000000ffffffff6a47304402200466bbc2aa8a742e85c3b68911502e73cdcb620ceaaa7a3cd199dbb4f8e9b969022063afeedd37d05e44b655a9de92eb36124acc045baf7b9e2941f81e41af91f1150121030ac79bab351084fdc82b4fa46eaa6a9cd2b5eb97ee93e367422bf47219b54a14";
        auto tx = BitcoinLikeTransactionApi::parseRawSignedTransaction(wallet->getCurrency(), hex::toByteArray(strTx), 0);
        EXPECT_EQ(hex::toString(tx->serialize()), strTx);
    }
}
<commit_msg>Update and disable BitcoinLikeWalletP2SHSynchronization.SynchronizeFromLastBlock<commit_after>/*
 *
 * synchronization_tests
 * ledger-core
 *
 * Created by Khalil Bellakrid on 15/05/2018.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Ledger
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <gtest/gtest.h>
#include "../BaseFixture.h"
#include <set>
#include <api/KeychainEngines.hpp>
#include <utils/DateUtils.hpp>
#include <wallet/bitcoin/database/BitcoinLikeAccountDatabaseHelper.h>
#include <wallet/bitcoin/api_impl/BitcoinLikeTransactionApi.h>

class BitcoinLikeWalletP2SHSynchronization : public BaseFixture {

};

TEST_F(BitcoinLikeWalletP2SHSynchronization, MediumXpubSynchronization) {
    auto pool = newDefaultPool();
    {
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE,api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,"49'/<coin_type>'/<account>'/<node>/<address>");

        auto wallet = uv::wait(pool->createWallet("e847815f-488a-4301-b67c-378a5e9c8a61", "bitcoin_testnet", configuration));
        {
            auto nextIndex = uv::wait(wallet->getNextAccountIndex());
            EXPECT_EQ(nextIndex, 0);

            auto account = createBitcoinLikeAccount(wallet, nextIndex, P2SH_XPUB_INFO);

            auto receiver = make_receiver([=](const std::shared_ptr<api::Event> &event) {
                fmt::print("Received event {}\n", api::to_string(event->getCode()));
                if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                    return;
                EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
                EXPECT_EQ(event->getCode(),
                          api::EventCode::SYNCHRONIZATION_SUCCEED_ON_PREVIOUSLY_EMPTY_ACCOUNT);
                dispatcher->stop();
            });

            auto bus = account->synchronize();
            bus->subscribe(getTestExecutionContext(),receiver);

            dispatcher->waitUntilStopped();

            auto block = uv::wait(account->getLastBlock());
            auto blockHash = block.blockHash;
        }
    }
}

TEST_F(BitcoinLikeWalletP2SHSynchronization, SynchronizeOnceAtATime) {
    auto pool = newDefaultPool();
    {
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE,api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,"49'/<coin_type>'/<account>'/<node>/<address>");

        auto wallet = uv::wait(pool->createWallet("e847815f-488a-4301-b67c-378a5e9c8a62", "bitcoin_testnet",configuration));
        {
            auto nextIndex = uv::wait(wallet->getNextAccountIndex());
            EXPECT_EQ(nextIndex, 0);
            auto account = createBitcoinLikeAccount(wallet, nextIndex, P2SH_XPUB_INFO);
            auto eventBus = pool->getEventBus();
            eventBus->subscribe(getTestExecutionContext(),
                                           make_receiver([](const std::shared_ptr<api::Event> &event) {
                                               fmt::print("Received event {}\n", api::to_string(event->getCode()));
                                           }));
            auto bus = account->synchronize();
            bus->subscribe(getTestExecutionContext(),
                                              make_receiver([=](const std::shared_ptr<api::Event> &event) {
                                                  fmt::print("Received event {}\n", api::to_string(event->getCode()));
                                                  if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                                                      return;
                                                  EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
                                                  EXPECT_EQ(event->getCode(),
                                                            api::EventCode::SYNCHRONIZATION_SUCCEED_ON_PREVIOUSLY_EMPTY_ACCOUNT);
                                                  dispatcher->stop();
                                              }));
            EXPECT_EQ(bus, account->synchronize());
            dispatcher->waitUntilStopped();
        }
    }
}

TEST_F(BitcoinLikeWalletP2SHSynchronization, DISABLED_SynchronizeFromLastBlock) {
    auto pool = newDefaultPool();
    {
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE,api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,"49'/<coin_type>'/<account>'/<node>/<address>");
        const auto walletName = randomWalletName();
        auto wallet = uv::wait(pool->createWallet(walletName, "bitcoin_testnet",configuration));
        createBitcoinLikeAccount(wallet, 0, P2SH_XPUB_INFO);
        auto synchronize = [wallet, pool, this] (std::shared_ptr<uv::SequentialExecutionContext> context, bool expectNewOp) {
            auto account = uv::wait(wallet->getAccount(0));
            auto numberOfOp = 0;

            auto receiverNumberOp = make_receiver([&numberOfOp](const std::shared_ptr<api::Event> &event) {
                numberOfOp += 1;
            });

            auto eventBus = pool->getEventBus();
            eventBus->subscribe(context, receiverNumberOp);
            auto bus = account->synchronize();

            auto receiver = make_receiver([=, &numberOfOp](const std::shared_ptr<api::Event> &event) {
                fmt::print("Received event {}\n", api::to_string(event->getCode()));
                if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                    return;

                EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
                EXPECT_EQ(expectNewOp, (numberOfOp > 0));
                context->stop();
            });

            bus->subscribe(context, receiver);
            auto newBus = account->synchronize();
            EXPECT_EQ(bus, newBus);
            context->waitUntilStopped();
            return bus;
        };

        auto b1 = synchronize(std::dynamic_pointer_cast<uv::SequentialExecutionContext>(
                                  dispatcher->getSerialExecutionContext("__sync1__")), true);
        auto b2 = synchronize(std::dynamic_pointer_cast<uv::SequentialExecutionContext>(
                                  dispatcher->getSerialExecutionContext("__sync2__")), false);
        EXPECT_NE(b1, b2);
    }
}

TEST_F(BitcoinLikeWalletP2SHSynchronization, EraseDataSinceAfterSynchronization) {
    auto pool = newDefaultPool();
    const auto walletName = randomWalletName();
    {
        //Set configuration
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE, api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,
                                 "49'/<coin_type>'/<account>'/<node>/<address>");
        //Create wallet
        auto wallet = uv::wait(pool->createWallet(walletName, "bitcoin_testnet", configuration));
        //Create account
        auto account = createBitcoinLikeAccount(wallet, 0, P2SH_XPUB_INFO);
        //Sync account
        auto bus = account->synchronize();
        auto receiver = make_receiver([=](const std::shared_ptr<api::Event> &event) {
            fmt::print("Received event {}\n", api::to_string(event->getCode()));
            if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                return;

            EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
            dispatcher->stop();
        });
        bus->subscribe(getTestExecutionContext(),receiver);
        dispatcher->waitUntilStopped();

        auto accountCount = uv::wait(wallet->getAccountCount());
        EXPECT_EQ(accountCount, 1);
        auto accountFromWallet = uv::wait(wallet->getAccount(0));
        EXPECT_EQ(account, accountFromWallet);

        auto date = "2000-03-27T09:10:22Z";
        auto formatedDate = DateUtils::fromJSON(date);

        //Delete account
        auto code = uv::wait(wallet->eraseDataSince(formatedDate));
        EXPECT_EQ(code, api::ErrorCode::FUTURE_WAS_SUCCESSFULL);

        //Check if account was successfully deleted
        auto newAccountCount = uv::wait(wallet->getAccountCount());
        EXPECT_EQ(newAccountCount, 0);
        {
            soci::session sql(pool->getDatabaseSessionPool()->getPool());
            BitcoinLikeAccountDatabaseEntry entry;
            auto result = BitcoinLikeAccountDatabaseHelper::queryAccount(sql, account->getAccountUid(), entry);
            EXPECT_EQ(result, false);
        }

        //Delete wallet
        auto walletCode = uv::wait(pool->eraseDataSince(formatedDate));
        EXPECT_EQ(walletCode, api::ErrorCode::FUTURE_WAS_SUCCESSFULL);

        //Check if wallet was successfully deleted
        auto walletCount = uv::wait(pool->getWalletCount());
        EXPECT_EQ(walletCount, 0);
    }
}
TEST_F(BitcoinLikeWalletP2SHSynchronization, TestNetSynchronization) {
    auto pool = newDefaultPool();
    {
        auto configuration = DynamicObject::newInstance();
        configuration->putString(api::Configuration::KEYCHAIN_ENGINE,api::KeychainEngines::BIP49_P2SH);
        configuration->putString(api::Configuration::KEYCHAIN_DERIVATION_SCHEME,"49'/<coin_type>'/<account>'/<node>/<address>");
        auto wallet = uv::wait(pool->createWallet("testnet_wallet", "bitcoin_testnet",configuration));
        {
            auto nextIndex = uv::wait(wallet->getNextAccountIndex());
            auto info = uv::wait(wallet->getNextExtendedKeyAccountCreationInfo());
            info.extendedKeys.push_back("tpubDCcvqEHx7prGddpWTfEviiew5YLMrrKy4oJbt14teJZenSi6AYMAs2SNXwYXFzkrNYwECSmobwxESxMCrpfqw4gsUt88bcr8iMrJmbb8P2q");
            EXPECT_EQ(nextIndex, 0);
            auto account = createBitcoinLikeAccount(wallet, nextIndex, info);
            auto receiver = make_receiver([=](const std::shared_ptr<api::Event> &event) {
                fmt::print("Received event {}\n", api::to_string(event->getCode()));
                if (event->getCode() == api::EventCode::SYNCHRONIZATION_STARTED)
                    return;
                EXPECT_NE(event->getCode(), api::EventCode::SYNCHRONIZATION_FAILED);
                dispatcher->stop();
            });

            auto bus = account->synchronize();
            bus->subscribe(getTestExecutionContext(),receiver);
            dispatcher->waitUntilStopped();
        }
    }
}

TEST_F(BitcoinLikeWalletP2SHSynchronization, DecredParsingAndSerialization) {
    auto pool = newDefaultPool();
    {
        auto wallet = uv::wait(pool->createWallet("testnet_wallet", "decred",DynamicObject::newInstance()));
        auto strTx = "01000000016b9b4d4cdd2cf78907e62cddf31911ae4d4af1d89228ae4afc4459edee6a60c40100000000ffffff000240420f000000000000001976a9141d19445f397f6f0d3e2e6d741f61ba66b53886cf88acf0d31d000000000000001976a91415101bac61dca29add75996a0836a469dc8eee0788ac00000000ffffffff01000000000000000000000000ffffffff6a47304402200466bbc2aa8a742e85c3b68911502e73cdcb620ceaaa7a3cd199dbb4f8e9b969022063afeedd37d05e44b655a9de92eb36124acc045baf7b9e2941f81e41af91f1150121030ac79bab351084fdc82b4fa46eaa6a9cd2b5eb97ee93e367422bf47219b54a14";
        auto tx = BitcoinLikeTransactionApi::parseRawSignedTransaction(wallet->getCurrency(), hex::toByteArray(strTx), 0);
        EXPECT_EQ(hex::toString(tx->serialize()), strTx);
    }
}
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2020 Intel Corporation. All Rights Reserved.

#include "split-filter.h"

namespace librealsense
{
    split_filter::split_filter()
        : generic_processing_block("Split Filter"),
        _selected_stream_id(0.f)
    {
        auto selected_stream_id = std::make_shared<ptr_option<float>>(0.f, 3.f, 1.f, 1.f,
            &_selected_stream_id, "Selected stream id for display");
        register_option(RS2_OPTION_SELECT_ID, selected_stream_id);

        _last_frame[0] = nullptr;
        _last_frame[1] = nullptr;
        _last_frame[2] = nullptr;
    }

    // processing only simple frames (not framesets)
    // only depth frames
    // only index 0
    bool split_filter::should_process(const rs2::frame& frame)
    {
        if (!frame)
            return false;

        auto set = frame.as<rs2::frameset>();
        if (set)
            return false;

        auto depth_frame = frame.as<rs2::depth_frame>();
        if (!depth_frame)
            return false;

        auto profile = frame.get_profile();
        rs2_stream stream = profile.stream_type();
        if (stream != RS2_STREAM_DEPTH)
            return false;

        int index = profile.stream_index();
        if (index != 0)
            return false;

        return true;
    }

    rs2::frame split_filter::process_frame(const rs2::frame_source& source, const rs2::frame& f)
    {
        // steps:
        // only for depth:
        // 1. check hdr seq id in metadata - if not as the option selected id, return last frame
        // 2. create new profile with stream index so that:
        //    - stream with seq_id 1 will have index 1
        //    - stream with seq_id 2 will have index 2
        // 3. allocate new frame
        // 4. memcpy src to target for data

        // 1. check hdr seq id in metadata
        auto depth_frame = f.as<rs2::depth_frame>();
        auto depth_exposure = depth_frame.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_EXPOSURE);
        //int hdr_seq_id = depth_frame.get_frame_metadata(RS2_FRAME_METADATA_HDR_SEQUENCE_ID);
        int hdr_seq_id = 1;
        if (depth_exposure == 1.f)
        {
            hdr_seq_id = 2;
        }

        if (!is_selected_id(hdr_seq_id))
        {
            if (_last_frame[hdr_seq_id])
            {
                auto lf_exposure = _last_frame[hdr_seq_id].get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_EXPOSURE);
                return _last_frame[hdr_seq_id];
            }
            return f;
        }

        // 2. create new profile with stream index so that:
        //    - stream with seq_id 1 will have index 1
        //    - stream with seq_id 2 will have index 2
        rs2::stream_profile new_profile = depth_frame.get_profile().
            clone(depth_frame.get_profile().stream_type(), hdr_seq_id, depth_frame.get_profile().format());

        // 3. allocate new frame
        auto width = depth_frame.get_width();
        auto height = depth_frame.get_height();
        auto split_frame = source.allocate_video_frame(new_profile, f, depth_frame.get_bytes_per_pixel(),
            width, height, depth_frame.get_stride_in_bytes(), RS2_EXTENSION_DEPTH_FRAME);

        // 4. memcpy src to target for data
        if (split_frame)
        {
            auto ptr = dynamic_cast<librealsense::depth_frame*>((librealsense::frame_interface*)split_frame.get());
            auto orig = dynamic_cast<librealsense::depth_frame*>((librealsense::frame_interface*)f.get());

            auto new_data = (uint16_t*)(ptr->get_frame_data());
            auto orig_data = (uint16_t*)(orig->get_frame_data());
            memcpy(new_data, orig_data, width * height * sizeof(uint16_t));

            ptr->set_sensor(orig->get_sensor());

            _last_frame[hdr_seq_id] = split_frame;

            return split_frame;
        }

        return f;
    }

    bool split::is_selected_id(int sequence_id)
    {
        if (_selected_stream_id != 0 && sequence_id != _selected_stream_id)
            return false;
        return true;
    }
}<commit_msg>few improvements in split pb<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2020 Intel Corporation. All Rights Reserved.

#include "split-filter.h"

namespace librealsense
{
    split_filter::split_filter()
        : generic_processing_block("Split Filter"),
        _selected_stream_id(1.f)
    {
        auto selected_stream_id = std::make_shared<ptr_option<float>>(0.f, 3.f, 1.f, 1.f,
            &_selected_stream_id, "Selected stream id for display");
        register_option(RS2_OPTION_SELECT_ID, selected_stream_id);

        _last_frame[0] = nullptr;
        _last_frame[1] = nullptr;
        _last_frame[2] = nullptr;
    }

    // processing only simple frames (not framesets)
    // only depth frames
    // only index 0
    bool split_filter::should_process(const rs2::frame& frame)
    {
        if (!frame)
            return false;

        auto set = frame.as<rs2::frameset>();
        if (set)
            return false;

        auto depth_frame = frame.as<rs2::depth_frame>();
        if (!depth_frame)
            return false;

        auto profile = frame.get_profile();
        rs2_stream stream = profile.stream_type();
        if (stream != RS2_STREAM_DEPTH)
            return false;

        int index = profile.stream_index();
        if (index != 0)
            return false;

        return true;
    }

    rs2::frame split_filter::process_frame(const rs2::frame_source& source, const rs2::frame& f)
    {
        // steps:
        // only for depth:
        // 1. check hdr seq id in metadata - if not as the option selected id, return last frame
        // 2. create new profile with stream index so that:
        //    - stream with seq_id 1 will have index 1
        //    - stream with seq_id 2 will have index 2
        // 3. allocate new frame
        // 4. memcpy src to target for data

        // 1. check hdr seq id in metadata
        auto depth_frame = f.as<rs2::depth_frame>();
        auto depth_exposure = depth_frame.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_EXPOSURE);
        //int hdr_seq_id = depth_frame.get_frame_metadata(RS2_FRAME_METADATA_HDR_SEQUENCE_ID);
        int hdr_seq_id = 1;
        if (depth_exposure == 1.f)
        {
            hdr_seq_id = 2;
        }

        if (!is_selected_id(hdr_seq_id))
        {
            if (_last_frame[static_cast<int>(_selected_stream_id)])
                return _last_frame[static_cast<int>(_selected_stream_id)];
            return f;
        }

        // 2. create new profile with stream index so that:
        //    - stream with seq_id 1 will have index 1
        //    - stream with seq_id 2 will have index 2
        rs2::stream_profile new_profile = depth_frame.get_profile().
            clone(depth_frame.get_profile().stream_type(), hdr_seq_id, depth_frame.get_profile().format());

        // 3. allocate new frame
        auto width = depth_frame.get_width();
        auto height = depth_frame.get_height();
        auto split_frame = source.allocate_video_frame(new_profile, f, depth_frame.get_bytes_per_pixel(),
            width, height, depth_frame.get_stride_in_bytes(), RS2_EXTENSION_DEPTH_FRAME);

        // 4. memcpy src to target for data
        if (split_frame)
        {
            auto ptr = dynamic_cast<librealsense::depth_frame*>((librealsense::frame_interface*)split_frame.get());
            auto orig = dynamic_cast<librealsense::depth_frame*>((librealsense::frame_interface*)f.get());

            auto new_data = (uint16_t*)(ptr->get_frame_data());
            auto orig_data = (uint16_t*)(orig->get_frame_data());
            memcpy(new_data, orig_data, width * height * sizeof(uint16_t));

            ptr->set_sensor(orig->get_sensor());

            _last_frame[hdr_seq_id] = split_frame;

            return split_frame;
        }

        return f;
    }

    bool split::is_selected_id(int sequence_id)
    {
        if ( 0 != static_cast<int>(_selected_stream_id) &&
            sequence_id != static_cast<int>(_selected_stream_id))
            return false;
        return true;
    }
}<|endoftext|>


<commit_before><commit_msg>Consider "certificate revoked" as the most serious certificate error.<commit_after><|endoftext|>


<commit_before><commit_msg>Enable a test, by masking failures if the system does not support IPv6.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) [2004-2014] Novell, Inc.
 * Copyright (c) [2016-2018] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * 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, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include <locale>
#include <cmath>
#include <vector>
#include <sstream>
#include <boost/algorithm/string.hpp>

#include "storage/Utils/Text.h"
#include "storage/Utils/HumanString.h"
#include "storage/Utils/Math.h"
#include "storage/Utils/ExceptionImpl.h"

namespace storage
{
    using std::string;

    int
    num_suffixes()
    {
	return 7;
    }

    vector<Text>
    get_all_suffixes(int i, bool all = false, bool sloppy = false)
    {
	vector<Text> ret;

	switch (i)
	{
	    case 0:
		// TRANSLATORS: symbol for "bytes" (best keep untranslated)
		ret.push_back(_("B"));
		if (sloppy)
		    ret.push_back(Text("", ""));
		break;

	    case 1:
		// TRANSLATORS: symbol for "kibi bytes" (best keep untranslated)
		ret.push_back(_("KiB"));
		if (all)
		    // TRANSLATORS: symbol for "kilo bytes" (best keep untranslated)
		    ret.push_back(_("kB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "kilo" (best keep untranslated)
		    ret.push_back(_("k"));
		break;

	    case 2:
		// TRANSLATORS: symbol for "mebi bytes" (best keep untranslated)
		ret.push_back(_("MiB"));
		if (all)
		    // TRANSLATORS: symbol for "mega bytes" (best keep untranslated)
		    ret.push_back(_("MB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "mega" (best keep untranslated)
		    ret.push_back(_("M"));
		break;

	    case 3:
		// TRANSLATORS: symbol for "gibi bytes" (best keep untranslated)
		ret.push_back(_("GiB"));
		if (all)
		    // TRANSLATORS: symbol for "giga bytes" (best keep untranslated)
		    ret.push_back(_("GB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "giga" (best keep untranslated)
		    ret.push_back(_("G"));
		break;

	    case 4:
		// TRANSLATORS: symbol for "tebi bytes" (best keep untranslated)
		ret.push_back(_("TiB"));
		if (all)
		    // TRANSLATORS: symbol for "tera bytes" (best keep untranslated)
		    ret.push_back(_("TB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "tera" (best keep untranslated)
		    ret.push_back(_("T"));
		break;

	    case 5:
		// TRANSLATORS: symbol for "pebi bytes" (best keep untranslated)
		ret.push_back(_("PiB"));
		if (all)
		    // TRANSLATORS: symbol for "peta bytes" (best keep untranslated)
		    ret.push_back(_("PB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "peta" (best keep untranslated)
		    ret.push_back(_("P"));
		break;

	    case 6:
		// TRANSLATORS: symbol for "exbi bytes" (best keep untranslated)
		ret.push_back(_("EiB"));
		if (all)
		    // TRANSLATORS: symbol for "exa bytes" (best keep untranslated)
		    ret.push_back(_("EB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "exa" (best keep untranslated)
		    ret.push_back(_("E"));
		break;
	}

	return ret;
    }

    string
    get_suffix(int i, bool classic)
    {
	return classic ? get_all_suffixes(i).front().native : get_all_suffixes(i).front().translated;
    }

    // Both byte_to_humanstring and humanstring_to_byte use integer arithmetic
    // as long as possible to provide exact results for those cases.

    string
    byte_to_humanstring(unsigned long long size, bool classic, int precision, bool omit_zeroes)
    {
	const locale loc = classic ? locale::classic() : locale();

	// Calculate the index of the suffix to use. The index increases by 1
	// when the number of leading zeros decreases by 10.

	int i = size > 0 ? (64 - (clz(size) + 1)) / 10 : 0;

	if ((i == 0) || (omit_zeroes && is_multiple_of(size, 1ULL << 10 * i)))
	{
	    unsigned long long v = size >> 10 * i;

	    std::ostringstream s;
	    s.imbue(loc);
	    s << v << ' ' << get_suffix(i, classic);
	    return s.str();
	}
	else
	{
	    long double v = std::ldexp((long double)(size), - 10 * i);

	    std::ostringstream s;
	    s.imbue(loc);
	    s.setf(ios::fixed);
	    s.precision(precision);
	    s << v << ' ' << get_suffix(i, classic);
	    return s.str();
	}
    }

    namespace
    {
	// Helper functions to parse a number as int or float, multiply
	// according to the suffix. Do all required error checks.

	pair<bool, unsigned long long>
	parse_i(const string& str, int i, const locale& loc)
	{
	    istringstream s(str);
	    s.imbue(loc);

	    unsigned long long v;
	    s >> v;

	    if (!s.eof())
		return make_pair(false, 0);

	    if (s.fail())
	    {
		if (v == std::numeric_limits<unsigned long long>::max())
		    ST_THROW(OverflowException());

		return make_pair(false, 0);
	    }

	    if (v != 0 && str[0] == '-')
		ST_THROW(OverflowException());

	    if (v > 0 && clz(v) < 10 * i)
		ST_THROW(OverflowException());

	    v <<= 10 * i;

	    return make_pair(true, v);
	}

	pair<bool, unsigned long long>
	parse_f(const string& str, int i, const locale& loc)
	{
	    istringstream s(str);
	    s.imbue(loc);

	    long double v;
	    s >> v;

	    if (!s.eof())
		return make_pair(false, 0);

	    if (s.fail())
	    {
		if (v == std::numeric_limits<long double>::max())
		    ST_THROW(OverflowException());

		return make_pair(false, 0);
	    }

	    if (v < 0.0)
		ST_THROW(OverflowException());

	    v = std::round(std::ldexp(v, 10 * i));

	    if (v > std::numeric_limits<unsigned long long>::max())
		ST_THROW(OverflowException());

	    return make_pair(true, v);
	}

    }

    unsigned long long
    humanstring_to_byte(const string& str, bool classic)
    {
	const locale loc = classic ? locale::classic() : locale();

	const string str_trimmed = boost::trim_copy(str, loc);

	for (int i = 0; i < num_suffixes(); ++i)
	{
	    vector<Text> suffixes = get_all_suffixes(i, true, !classic);

	    for (const Text& suffix : suffixes)
	    {
		const string& tmp = classic ? suffix.native : suffix.translated;

		if (boost::iends_with(str_trimmed, tmp, loc))
		{
		    string number = boost::trim_copy(str_trimmed.substr(0, str_trimmed.size() - tmp.size()), loc);

		    pair<bool, unsigned long long> v;

		    v = parse_i(number, i, loc);
		    if (v.first)
			return v.second;

		    v = parse_f(number, i, loc);
		    if (v.first)
			return v.second;
		}
	    }
	}

	ST_THROW(ParseException("failed to parse", str, "something like 1 GiB"));
    }

}
<commit_msg>- ported check from snapper<commit_after>/*
 * Copyright (c) [2004-2014] Novell, Inc.
 * Copyright (c) [2016-2018] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * 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, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include <locale>
#include <cmath>
#include <vector>
#include <sstream>
#include <boost/algorithm/string.hpp>

#include "storage/Utils/Text.h"
#include "storage/Utils/HumanString.h"
#include "storage/Utils/Math.h"
#include "storage/Utils/ExceptionImpl.h"

namespace storage
{
    using std::string;

    int
    num_suffixes()
    {
	return 7;
    }

    vector<Text>
    get_all_suffixes(int i, bool all = false, bool sloppy = false)
    {
	vector<Text> ret;

	switch (i)
	{
	    case 0:
		// TRANSLATORS: symbol for "bytes" (best keep untranslated)
		ret.push_back(_("B"));
		if (sloppy)
		    ret.push_back(Text("", ""));
		break;

	    case 1:
		// TRANSLATORS: symbol for "kibi bytes" (best keep untranslated)
		ret.push_back(_("KiB"));
		if (all)
		    // TRANSLATORS: symbol for "kilo bytes" (best keep untranslated)
		    ret.push_back(_("kB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "kilo" (best keep untranslated)
		    ret.push_back(_("k"));
		break;

	    case 2:
		// TRANSLATORS: symbol for "mebi bytes" (best keep untranslated)
		ret.push_back(_("MiB"));
		if (all)
		    // TRANSLATORS: symbol for "mega bytes" (best keep untranslated)
		    ret.push_back(_("MB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "mega" (best keep untranslated)
		    ret.push_back(_("M"));
		break;

	    case 3:
		// TRANSLATORS: symbol for "gibi bytes" (best keep untranslated)
		ret.push_back(_("GiB"));
		if (all)
		    // TRANSLATORS: symbol for "giga bytes" (best keep untranslated)
		    ret.push_back(_("GB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "giga" (best keep untranslated)
		    ret.push_back(_("G"));
		break;

	    case 4:
		// TRANSLATORS: symbol for "tebi bytes" (best keep untranslated)
		ret.push_back(_("TiB"));
		if (all)
		    // TRANSLATORS: symbol for "tera bytes" (best keep untranslated)
		    ret.push_back(_("TB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "tera" (best keep untranslated)
		    ret.push_back(_("T"));
		break;

	    case 5:
		// TRANSLATORS: symbol for "pebi bytes" (best keep untranslated)
		ret.push_back(_("PiB"));
		if (all)
		    // TRANSLATORS: symbol for "peta bytes" (best keep untranslated)
		    ret.push_back(_("PB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "peta" (best keep untranslated)
		    ret.push_back(_("P"));
		break;

	    case 6:
		// TRANSLATORS: symbol for "exbi bytes" (best keep untranslated)
		ret.push_back(_("EiB"));
		if (all)
		    // TRANSLATORS: symbol for "exa bytes" (best keep untranslated)
		    ret.push_back(_("EB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "exa" (best keep untranslated)
		    ret.push_back(_("E"));
		break;
	}

	return ret;
    }

    string
    get_suffix(int i, bool classic)
    {
	return classic ? get_all_suffixes(i).front().native : get_all_suffixes(i).front().translated;
    }

    // Both byte_to_humanstring and humanstring_to_byte use integer arithmetic
    // as long as possible to provide exact results for those cases.

    string
    byte_to_humanstring(unsigned long long size, bool classic, int precision, bool omit_zeroes)
    {
	const locale loc = classic ? locale::classic() : locale();

	// Calculate the index of the suffix to use. The index increases by 1
	// when the number of leading zeros decreases by 10.

	static_assert(sizeof(size) == 8, "unsigned long long not 64 bit");

	int i = size > 0 ? (64 - (clz(size) + 1)) / 10 : 0;

	if ((i == 0) || (omit_zeroes && is_multiple_of(size, 1ULL << 10 * i)))
	{
	    unsigned long long v = size >> 10 * i;

	    std::ostringstream s;
	    s.imbue(loc);
	    s << v << ' ' << get_suffix(i, classic);
	    return s.str();
	}
	else
	{
	    long double v = std::ldexp((long double)(size), - 10 * i);

	    std::ostringstream s;
	    s.imbue(loc);
	    s.setf(ios::fixed);
	    s.precision(precision);
	    s << v << ' ' << get_suffix(i, classic);
	    return s.str();
	}
    }

    namespace
    {
	// Helper functions to parse a number as int or float, multiply
	// according to the suffix. Do all required error checks.

	pair<bool, unsigned long long>
	parse_i(const string& str, int i, const locale& loc)
	{
	    istringstream s(str);
	    s.imbue(loc);

	    unsigned long long v;
	    s >> v;

	    if (!s.eof())
		return make_pair(false, 0);

	    if (s.fail())
	    {
		if (v == std::numeric_limits<unsigned long long>::max())
		    ST_THROW(OverflowException());

		return make_pair(false, 0);
	    }

	    if (v != 0 && str[0] == '-')
		ST_THROW(OverflowException());

	    if (v > 0 && clz(v) < 10 * i)
		ST_THROW(OverflowException());

	    v <<= 10 * i;

	    return make_pair(true, v);
	}

	pair<bool, unsigned long long>
	parse_f(const string& str, int i, const locale& loc)
	{
	    istringstream s(str);
	    s.imbue(loc);

	    long double v;
	    s >> v;

	    if (!s.eof())
		return make_pair(false, 0);

	    if (s.fail())
	    {
		if (v == std::numeric_limits<long double>::max())
		    ST_THROW(OverflowException());

		return make_pair(false, 0);
	    }

	    if (v < 0.0)
		ST_THROW(OverflowException());

	    v = std::round(std::ldexp(v, 10 * i));

	    if (v > std::numeric_limits<unsigned long long>::max())
		ST_THROW(OverflowException());

	    return make_pair(true, v);
	}

    }

    unsigned long long
    humanstring_to_byte(const string& str, bool classic)
    {
	const locale loc = classic ? locale::classic() : locale();

	const string str_trimmed = boost::trim_copy(str, loc);

	for (int i = 0; i < num_suffixes(); ++i)
	{
	    vector<Text> suffixes = get_all_suffixes(i, true, !classic);

	    for (const Text& suffix : suffixes)
	    {
		const string& tmp = classic ? suffix.native : suffix.translated;

		if (boost::iends_with(str_trimmed, tmp, loc))
		{
		    string number = boost::trim_copy(str_trimmed.substr(0, str_trimmed.size() - tmp.size()), loc);

		    pair<bool, unsigned long long> v;

		    v = parse_i(number, i, loc);
		    if (v.first)
			return v.second;

		    v = parse_f(number, i, loc);
		    if (v.first)
			return v.second;
		}
	    }
	}

	ST_THROW(ParseException("failed to parse", str, "something like 1 GiB"));
    }

}
<|endoftext|>