<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 "chrome/browser/chrome_browser_main_posix.h"

#include <errno.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <sys/resource.h>
#include <unistd.h>

#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_thread.h"

#if defined(OS_ANDROID)
#include <asm/page.h>  // for PAGE_SIZE needed by PTHREAD_STACK_MIN
#endif

#if defined(TOOLKIT_USES_GTK)
#include "chrome/browser/chrome_browser_main_extra_parts_gtk.h"
#include "chrome/browser/printing/print_dialog_gtk.h"
#endif

using content::BrowserThread;

namespace {

// See comment in |PreEarlyInitialization()|, where sigaction is called.
void SIGCHLDHandler(int signal) {
}

int g_shutdown_pipe_write_fd = -1;
int g_shutdown_pipe_read_fd = -1;

// Common code between SIG{HUP, INT, TERM}Handler.
void GracefulShutdownHandler(int signal) {
  // Reinstall the default handler.  We had one shot at graceful shutdown.
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIG_DFL;
  RAW_CHECK(sigaction(signal, &action, NULL) == 0);

  RAW_CHECK(g_shutdown_pipe_write_fd != -1);
  RAW_CHECK(g_shutdown_pipe_read_fd != -1);
  size_t bytes_written = 0;
  do {
    int rv = HANDLE_EINTR(
        write(g_shutdown_pipe_write_fd,
              reinterpret_cast<const char*>(&signal) + bytes_written,
              sizeof(signal) - bytes_written));
    RAW_CHECK(rv >= 0);
    bytes_written += rv;
  } while (bytes_written < sizeof(signal));
}

// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
void SIGHUPHandler(int signal) {
  RAW_CHECK(signal == SIGHUP);
  GracefulShutdownHandler(signal);
}

// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
void SIGINTHandler(int signal) {
  RAW_CHECK(signal == SIGINT);
  GracefulShutdownHandler(signal);
}

// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
void SIGTERMHandler(int signal) {
  RAW_CHECK(signal == SIGTERM);
  GracefulShutdownHandler(signal);
}

class ShutdownDetector : public base::PlatformThread::Delegate {
 public:
  explicit ShutdownDetector(int shutdown_fd);

  virtual void ThreadMain();

 private:
  const int shutdown_fd_;

  DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
};

ShutdownDetector::ShutdownDetector(int shutdown_fd)
    : shutdown_fd_(shutdown_fd) {
  CHECK_NE(shutdown_fd_, -1);
}

// These functions are used to help us diagnose crash dumps that happen
// during the shutdown process.
NOINLINE void ShutdownFDReadError() {
  // Ensure function isn't optimized away.
  asm("");
  sleep(UINT_MAX);
}

NOINLINE void ShutdownFDClosedError() {
  // Ensure function isn't optimized away.
  asm("");
  sleep(UINT_MAX);
}

NOINLINE void ExitPosted() {
  // Ensure function isn't optimized away.
  asm("");
  sleep(UINT_MAX);
}

void ShutdownDetector::ThreadMain() {
  base::PlatformThread::SetName("CrShutdownDetector");

  int signal;
  size_t bytes_read = 0;
  ssize_t ret;
  do {
    ret = HANDLE_EINTR(
        read(shutdown_fd_,
             reinterpret_cast<char*>(&signal) + bytes_read,
             sizeof(signal) - bytes_read));
    if (ret < 0) {
      NOTREACHED() << "Unexpected error: " << strerror(errno);
      ShutdownFDReadError();
      break;
    } else if (ret == 0) {
      NOTREACHED() << "Unexpected closure of shutdown pipe.";
      ShutdownFDClosedError();
      break;
    }
    bytes_read += ret;
  } while (bytes_read < sizeof(signal));
  VLOG(1) << "Handling shutdown for signal " << signal << ".";
#if defined(OS_CHROMEOS)
  // On ChromeOS, exiting on signal should be always clean.
  base::Closure task = base::Bind(&BrowserList::ExitCleanly);
#else
  base::Closure task = base::Bind(&BrowserList::AttemptExit);
#endif

  if (!BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task)) {
    // Without a UI thread to post the exit task to, there aren't many
    // options.  Raise the signal again.  The default handler will pick it up
    // and cause an ungraceful exit.
    RAW_LOG(WARNING, "No UI thread, exiting ungracefully.");
    kill(getpid(), signal);

    // The signal may be handled on another thread.  Give that a chance to
    // happen.
    sleep(3);

    // We really should be dead by now.  For whatever reason, we're not. Exit
    // immediately, with the exit status set to the signal number with bit 8
    // set.  On the systems that we care about, this exit status is what is
    // normally used to indicate an exit by this signal's default handler.
    // This mechanism isn't a de jure standard, but even in the worst case, it
    // should at least result in an immediate exit.
    RAW_LOG(WARNING, "Still here, exiting really ungracefully.");
    _exit(signal | (1 << 7));
  }
  ExitPosted();
}

// Sets the file descriptor soft limit to |max_descriptors| or the OS hard
// limit, whichever is lower.
void SetFileDescriptorLimit(unsigned int max_descriptors) {
  struct rlimit limits;
  if (getrlimit(RLIMIT_NOFILE, &limits) == 0) {
    unsigned int new_limit = max_descriptors;
    if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) {
      new_limit = limits.rlim_max;
    }
    limits.rlim_cur = new_limit;
    if (setrlimit(RLIMIT_NOFILE, &limits) != 0) {
      PLOG(INFO) << "Failed to set file descriptor limit";
    }
  } else {
    PLOG(INFO) << "Failed to get file descriptor limit";
  }
}

}  // namespace

// ChromeBrowserMainPartsPosix -------------------------------------------------

ChromeBrowserMainPartsPosix::ChromeBrowserMainPartsPosix(
    const content::MainFunctionParams& parameters)
    : ChromeBrowserMainParts(parameters) {
}

void ChromeBrowserMainPartsPosix::PreEarlyInitialization() {
  ChromeBrowserMainParts::PreEarlyInitialization();

  // We need to accept SIGCHLD, even though our handler is a no-op because
  // otherwise we cannot wait on children. (According to POSIX 2001.)
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIGCHLDHandler;
  CHECK(sigaction(SIGCHLD, &action, NULL) == 0);

  const std::string fd_limit_string =
      parsed_command_line().GetSwitchValueASCII(
          switches::kFileDescriptorLimit);
  int fd_limit = 0;
  if (!fd_limit_string.empty()) {
    base::StringToInt(fd_limit_string, &fd_limit);
  }
#if defined(OS_MACOSX)
  // We use quite a few file descriptors for our IPC, and the default limit on
  // the Mac is low (256), so bump it up if there is no explicit override.
  if (fd_limit == 0) {
    fd_limit = 1024;
  }
#endif  // OS_MACOSX
  if (fd_limit > 0)
    SetFileDescriptorLimit(fd_limit);
}

void ChromeBrowserMainPartsPosix::PostMainMessageLoopStart() {
  ChromeBrowserMainParts::PostMainMessageLoopStart();

  int pipefd[2];
  int ret = pipe(pipefd);
  if (ret < 0) {
    PLOG(DFATAL) << "Failed to create pipe";
  } else {
    g_shutdown_pipe_read_fd = pipefd[0];
    g_shutdown_pipe_write_fd = pipefd[1];
    const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN;
    // TODO(viettrungluu,willchan): crbug.com/29675 - This currently leaks, so
    // if you change this, you'll probably need to change the suppression.
    if (!base::PlatformThread::CreateNonJoinable(
            kShutdownDetectorThreadStackSize,
            new ShutdownDetector(g_shutdown_pipe_read_fd))) {
      LOG(DFATAL) << "Failed to create shutdown detector task.";
    }
  }
  // Setup signal handlers for shutdown AFTER shutdown pipe is setup because
  // it may be called right away after handler is set.

  // If adding to this list of signal handlers, note the new signal probably
  // needs to be reset in child processes. See
  // base/process_util_posix.cc:LaunchProcess.

  // We need to handle SIGTERM, because that is how many POSIX-based distros ask
  // processes to quit gracefully at shutdown time.
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIGTERMHandler;
  CHECK(sigaction(SIGTERM, &action, NULL) == 0);
  // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If
  // the browser process is being debugged, GDB will catch the SIGINT first.
  action.sa_handler = SIGINTHandler;
  CHECK(sigaction(SIGINT, &action, NULL) == 0);
  // And SIGHUP, for when the terminal disappears. On shutdown, many Linux
  // distros send SIGHUP, SIGTERM, and then SIGKILL.
  action.sa_handler = SIGHUPHandler;
  CHECK(sigaction(SIGHUP, &action, NULL) == 0);

#if defined(TOOLKIT_USES_GTK)
  printing::PrintingContextGtk::SetCreatePrintDialogFunction(
      &PrintDialogGtk::CreatePrintDialog);
#endif
}

void ChromeBrowserMainPartsPosix::ShowMissingLocaleMessageBox() {
#if defined(OS_CHROMEOS)
  NOTREACHED();  // Should not ever happen on ChromeOS.
#elif defined(OS_ANDROID)
  // TODO(port) Update this as needed.
  // Probably should not ever happen on Android, but at the time of this
  // writing, Android isn't even using ChromeBrowserMainPartsPosix yet.
  NOTREACHED();
#elif defined(OS_MACOSX)
  // Not called on Mac because we load the locale files differently.
  NOTREACHED();
#elif defined(TOOLKIT_USES_GTK)
  ChromeBrowserMainExtraPartsGtk::ShowMessageBox(
      chrome_browser::kMissingLocaleDataMessage);
#else
#error "Need MessageBox implementation."
#endif
}
<commit_msg>Aura/ash split: Fix ToT linux use_aura compile.<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 "chrome/browser/chrome_browser_main_posix.h"

#include <errno.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <sys/resource.h>
#include <unistd.h>

#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_thread.h"

#if defined(OS_ANDROID)
#include <asm/page.h>  // for PAGE_SIZE needed by PTHREAD_STACK_MIN
#endif

#if defined(TOOLKIT_USES_GTK)
#include "chrome/browser/chrome_browser_main_extra_parts_gtk.h"
#include "chrome/browser/printing/print_dialog_gtk.h"
#endif

using content::BrowserThread;

namespace {

// See comment in |PreEarlyInitialization()|, where sigaction is called.
void SIGCHLDHandler(int signal) {
}

int g_shutdown_pipe_write_fd = -1;
int g_shutdown_pipe_read_fd = -1;

// Common code between SIG{HUP, INT, TERM}Handler.
void GracefulShutdownHandler(int signal) {
  // Reinstall the default handler.  We had one shot at graceful shutdown.
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIG_DFL;
  RAW_CHECK(sigaction(signal, &action, NULL) == 0);

  RAW_CHECK(g_shutdown_pipe_write_fd != -1);
  RAW_CHECK(g_shutdown_pipe_read_fd != -1);
  size_t bytes_written = 0;
  do {
    int rv = HANDLE_EINTR(
        write(g_shutdown_pipe_write_fd,
              reinterpret_cast<const char*>(&signal) + bytes_written,
              sizeof(signal) - bytes_written));
    RAW_CHECK(rv >= 0);
    bytes_written += rv;
  } while (bytes_written < sizeof(signal));
}

// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
void SIGHUPHandler(int signal) {
  RAW_CHECK(signal == SIGHUP);
  GracefulShutdownHandler(signal);
}

// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
void SIGINTHandler(int signal) {
  RAW_CHECK(signal == SIGINT);
  GracefulShutdownHandler(signal);
}

// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
void SIGTERMHandler(int signal) {
  RAW_CHECK(signal == SIGTERM);
  GracefulShutdownHandler(signal);
}

class ShutdownDetector : public base::PlatformThread::Delegate {
 public:
  explicit ShutdownDetector(int shutdown_fd);

  virtual void ThreadMain();

 private:
  const int shutdown_fd_;

  DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
};

ShutdownDetector::ShutdownDetector(int shutdown_fd)
    : shutdown_fd_(shutdown_fd) {
  CHECK_NE(shutdown_fd_, -1);
}

// These functions are used to help us diagnose crash dumps that happen
// during the shutdown process.
NOINLINE void ShutdownFDReadError() {
  // Ensure function isn't optimized away.
  asm("");
  sleep(UINT_MAX);
}

NOINLINE void ShutdownFDClosedError() {
  // Ensure function isn't optimized away.
  asm("");
  sleep(UINT_MAX);
}

NOINLINE void ExitPosted() {
  // Ensure function isn't optimized away.
  asm("");
  sleep(UINT_MAX);
}

void ShutdownDetector::ThreadMain() {
  base::PlatformThread::SetName("CrShutdownDetector");

  int signal;
  size_t bytes_read = 0;
  ssize_t ret;
  do {
    ret = HANDLE_EINTR(
        read(shutdown_fd_,
             reinterpret_cast<char*>(&signal) + bytes_read,
             sizeof(signal) - bytes_read));
    if (ret < 0) {
      NOTREACHED() << "Unexpected error: " << strerror(errno);
      ShutdownFDReadError();
      break;
    } else if (ret == 0) {
      NOTREACHED() << "Unexpected closure of shutdown pipe.";
      ShutdownFDClosedError();
      break;
    }
    bytes_read += ret;
  } while (bytes_read < sizeof(signal));
  VLOG(1) << "Handling shutdown for signal " << signal << ".";
#if defined(OS_CHROMEOS)
  // On ChromeOS, exiting on signal should be always clean.
  base::Closure task = base::Bind(&BrowserList::ExitCleanly);
#else
  base::Closure task = base::Bind(&BrowserList::AttemptExit);
#endif

  if (!BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task)) {
    // Without a UI thread to post the exit task to, there aren't many
    // options.  Raise the signal again.  The default handler will pick it up
    // and cause an ungraceful exit.
    RAW_LOG(WARNING, "No UI thread, exiting ungracefully.");
    kill(getpid(), signal);

    // The signal may be handled on another thread.  Give that a chance to
    // happen.
    sleep(3);

    // We really should be dead by now.  For whatever reason, we're not. Exit
    // immediately, with the exit status set to the signal number with bit 8
    // set.  On the systems that we care about, this exit status is what is
    // normally used to indicate an exit by this signal's default handler.
    // This mechanism isn't a de jure standard, but even in the worst case, it
    // should at least result in an immediate exit.
    RAW_LOG(WARNING, "Still here, exiting really ungracefully.");
    _exit(signal | (1 << 7));
  }
  ExitPosted();
}

// Sets the file descriptor soft limit to |max_descriptors| or the OS hard
// limit, whichever is lower.
void SetFileDescriptorLimit(unsigned int max_descriptors) {
  struct rlimit limits;
  if (getrlimit(RLIMIT_NOFILE, &limits) == 0) {
    unsigned int new_limit = max_descriptors;
    if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) {
      new_limit = limits.rlim_max;
    }
    limits.rlim_cur = new_limit;
    if (setrlimit(RLIMIT_NOFILE, &limits) != 0) {
      PLOG(INFO) << "Failed to set file descriptor limit";
    }
  } else {
    PLOG(INFO) << "Failed to get file descriptor limit";
  }
}

}  // namespace

// ChromeBrowserMainPartsPosix -------------------------------------------------

ChromeBrowserMainPartsPosix::ChromeBrowserMainPartsPosix(
    const content::MainFunctionParams& parameters)
    : ChromeBrowserMainParts(parameters) {
}

void ChromeBrowserMainPartsPosix::PreEarlyInitialization() {
  ChromeBrowserMainParts::PreEarlyInitialization();

  // We need to accept SIGCHLD, even though our handler is a no-op because
  // otherwise we cannot wait on children. (According to POSIX 2001.)
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIGCHLDHandler;
  CHECK(sigaction(SIGCHLD, &action, NULL) == 0);

  const std::string fd_limit_string =
      parsed_command_line().GetSwitchValueASCII(
          switches::kFileDescriptorLimit);
  int fd_limit = 0;
  if (!fd_limit_string.empty()) {
    base::StringToInt(fd_limit_string, &fd_limit);
  }
#if defined(OS_MACOSX)
  // We use quite a few file descriptors for our IPC, and the default limit on
  // the Mac is low (256), so bump it up if there is no explicit override.
  if (fd_limit == 0) {
    fd_limit = 1024;
  }
#endif  // OS_MACOSX
  if (fd_limit > 0)
    SetFileDescriptorLimit(fd_limit);
}

void ChromeBrowserMainPartsPosix::PostMainMessageLoopStart() {
  ChromeBrowserMainParts::PostMainMessageLoopStart();

  int pipefd[2];
  int ret = pipe(pipefd);
  if (ret < 0) {
    PLOG(DFATAL) << "Failed to create pipe";
  } else {
    g_shutdown_pipe_read_fd = pipefd[0];
    g_shutdown_pipe_write_fd = pipefd[1];
    const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN;
    // TODO(viettrungluu,willchan): crbug.com/29675 - This currently leaks, so
    // if you change this, you'll probably need to change the suppression.
    if (!base::PlatformThread::CreateNonJoinable(
            kShutdownDetectorThreadStackSize,
            new ShutdownDetector(g_shutdown_pipe_read_fd))) {
      LOG(DFATAL) << "Failed to create shutdown detector task.";
    }
  }
  // Setup signal handlers for shutdown AFTER shutdown pipe is setup because
  // it may be called right away after handler is set.

  // If adding to this list of signal handlers, note the new signal probably
  // needs to be reset in child processes. See
  // base/process_util_posix.cc:LaunchProcess.

  // We need to handle SIGTERM, because that is how many POSIX-based distros ask
  // processes to quit gracefully at shutdown time.
  struct sigaction action;
  memset(&action, 0, sizeof(action));
  action.sa_handler = SIGTERMHandler;
  CHECK(sigaction(SIGTERM, &action, NULL) == 0);
  // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If
  // the browser process is being debugged, GDB will catch the SIGINT first.
  action.sa_handler = SIGINTHandler;
  CHECK(sigaction(SIGINT, &action, NULL) == 0);
  // And SIGHUP, for when the terminal disappears. On shutdown, many Linux
  // distros send SIGHUP, SIGTERM, and then SIGKILL.
  action.sa_handler = SIGHUPHandler;
  CHECK(sigaction(SIGHUP, &action, NULL) == 0);

#if defined(TOOLKIT_USES_GTK)
  printing::PrintingContextGtk::SetCreatePrintDialogFunction(
      &PrintDialogGtk::CreatePrintDialog);
#endif
}

void ChromeBrowserMainPartsPosix::ShowMissingLocaleMessageBox() {
#if defined(OS_CHROMEOS)
  NOTREACHED();  // Should not ever happen on ChromeOS.
#elif defined(OS_ANDROID)
  // TODO(port) Update this as needed.
  // Probably should not ever happen on Android, but at the time of this
  // writing, Android isn't even using ChromeBrowserMainPartsPosix yet.
  NOTREACHED();
#elif defined(OS_MACOSX)
  // Not called on Mac because we load the locale files differently.
  NOTREACHED();
#elif defined(TOOLKIT_USES_GTK)
  ChromeBrowserMainExtraPartsGtk::ShowMessageBox(
      chrome_browser::kMissingLocaleDataMessage);
#elif defined(USE_AURA)
  // TODO(port): We may want a views based message dialog here eventually, but
  // for now, crash.
  NOTREACHED();
#else
#error "Need MessageBox implementation."
#endif
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ImportFilter.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2008-01-10 11:54:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SU_STAR_DRAWING_XDRAWPAGESUPPLIER_HPP_
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
#include <com/sun/star/io/XInputStream.hpp>
#endif
#ifndef INCLUDED_DOMAINMAPPER_HXX
#include <dmapper/DomainMapper.hxx>
#endif
#ifndef _WRITERFILTER_HXX
#include <WriterFilter.hxx>
#endif
#ifndef INCLUDED_WW8_DOCUMENT_HXX
#include <doctok/WW8Document.hxx>
#endif
#ifndef INCLUDED_OOXML_DOCUMENT_HXX
#include <ooxml/OOXMLDocument.hxx>
#endif
#ifdef DEBUG_IMPORT
#include <iostream>
#include <osl/process.h>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool WriterFilter::filter( const uno::Sequence< beans::PropertyValue >& aDescriptor )
   throw (uno::RuntimeException)
{
    sal_Int32 nLength = aDescriptor.getLength();
    const beans::PropertyValue * pValue = aDescriptor.getConstArray();
    uno::Reference < io::XInputStream > xInputStream;
    ::rtl::OUString sFilterName;
    for ( sal_Int32 i = 0 ; i < nLength; i++)
    {
        if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) )
            pValue[i].Value >>= xInputStream;
        else if( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "FilterName" ) ) )
            pValue[i].Value >>= sFilterName;
    }
    if ( !xInputStream.is() )
    {
        return sal_False;
    }

#ifdef DEBUG_IMPORT
    TimeValue t1;
    osl_getSystemTime(&t1);

    writerfilter::logger("DEBUG", "<out>");
    writerfilter::logger("DEBUG", string("<starttime>") + string(t1.Seconds)
                         + "</starttime>");
#endif

    writerfilter::dmapper::SourceDocumentType eType = m_sFilterName.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "writer_MS_Word_2007" ) ) ?
                writerfilter::dmapper::DOCUMENT_OOXML : writerfilter::dmapper::DOCUMENT_DOC;
    writerfilter::Stream::Pointer_t pStream(new writerfilter::dmapper::DomainMapper(m_xContext, m_xDoc, eType));
    //create the tokenizer and domain mapper
    if( eType == writerfilter::dmapper::DOCUMENT_OOXML )
    {
        writerfilter::ooxml::OOXMLStream::Pointer_t pDocStream = writerfilter::ooxml::OOXMLDocumentFactory::createStream(m_xContext, xInputStream);
        writerfilter::ooxml::OOXMLDocument::Pointer_t pDocument(writerfilter::ooxml::OOXMLDocumentFactory::createDocument(pDocStream));

        uno::Reference<frame::XModel> xModel(m_xDoc, uno::UNO_QUERY_THROW);
        pDocument->setModel(xModel);

        uno::Reference<drawing::XDrawPageSupplier> xDrawings
            (m_xDoc, uno::UNO_QUERY_THROW);
        uno::Reference<drawing::XShapes> xShapes
            (xDrawings->getDrawPage(), uno::UNO_QUERY_THROW);
        pDocument->setShapes(xShapes);

        pDocument->resolve(*pStream);
    }
    else
    {
        writerfilter::doctok::WW8Stream::Pointer_t pDocStream = writerfilter::doctok::WW8DocumentFactory::createStream(m_xContext, xInputStream);
        writerfilter::doctok::WW8Document::Pointer_t pDocument(writerfilter::doctok::WW8DocumentFactory::createDocument(pDocStream));

        pDocument->resolve(*pStream);
    }

#ifdef DEBUG_IMPORT
    TimeValue t2;
    osl_getSystemTime(&t2);

    writerfilter::logger("DEBUG", string("<importtime>")
                         + string(t2.Seconds - t1.Seconds) + "</importtime>");
    writerfilter::logger("DEBUG", "</out>");
#endif

    return sal_True;
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void WriterFilter::cancel(  ) throw (uno::RuntimeException)
{
}

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void WriterFilter::setTargetDocument( const uno::Reference< lang::XComponent >& xDoc )
   throw (lang::IllegalArgumentException, uno::RuntimeException)
{
   m_xDoc = xDoc;
}

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void WriterFilter::initialize( const uno::Sequence< uno::Any >& aArguments ) throw (uno::Exception, uno::RuntimeException)
{
   uno::Sequence < beans::PropertyValue > aAnySeq;
   sal_Int32 nLength = aArguments.getLength();
   if ( nLength && ( aArguments[0] >>= aAnySeq ) )
   {
       const beans::PropertyValue * pValue = aAnySeq.getConstArray();
       nLength = aAnySeq.getLength();
       for ( sal_Int32 i = 0 ; i < nLength; i++)
       {
           if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) )
           {
               pValue[i].Value >>= m_sFilterName;
               break;
           }
       }
   }
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
OUString WriterFilter_getImplementationName () throw (uno::RuntimeException)
{
   return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.WriterFilter" ) );
}

#define SERVICE_NAME1 "com.sun.star.document.ImportFilter"
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool WriterFilter_supportsService( const OUString& ServiceName ) throw (uno::RuntimeException)
{
   return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ));
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
uno::Sequence< OUString > WriterFilter_getSupportedServiceNames(  ) throw (uno::RuntimeException)
{
   uno::Sequence < OUString > aRet(1);
   OUString* pArray = aRet.getArray();
   pArray[0] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) );
   return aRet;
}
#undef SERVICE_NAME1

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
uno::Reference< uno::XInterface > WriterFilter_createInstance( const uno::Reference< uno::XComponentContext >& xContext)
                throw( uno::Exception )
{
   return (cppu::OWeakObject*) new WriterFilter( xContext );
}

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
OUString WriterFilter::getImplementationName(  ) throw (uno::RuntimeException)
{
   return WriterFilter_getImplementationName();
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool WriterFilter::supportsService( const OUString& rServiceName ) throw (uno::RuntimeException)
{
    return WriterFilter_supportsService( rServiceName );
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
uno::Sequence< OUString > WriterFilter::getSupportedServiceNames(  ) throw (uno::RuntimeException)
{
    return WriterFilter_getSupportedServiceNames();
}

<commit_msg>INTEGRATION: CWS changefileheader (1.7.20); FILE MERGED 2008/04/01 16:06:45 thb 1.7.20.3: #i85898# Stripping all external header guards 2008/04/01 13:02:30 thb 1.7.20.2: #i85898# Stripping all external header guards 2008/03/28 15:53:02 rt 1.7.20.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ImportFilter.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include <osl/diagnose.h>
#include <com/sun/star/uno/XComponentContext.hpp>
#ifndef _COM_SU_STAR_DRAWING_XDRAWPAGESUPPLIER_HPP_
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#endif
#include <com/sun/star/io/XInputStream.hpp>
#include <dmapper/DomainMapper.hxx>
#include <WriterFilter.hxx>
#include <doctok/WW8Document.hxx>
#include <ooxml/OOXMLDocument.hxx>
#ifdef DEBUG_IMPORT
#include <iostream>
#include <osl/process.h>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool WriterFilter::filter( const uno::Sequence< beans::PropertyValue >& aDescriptor )
   throw (uno::RuntimeException)
{
    sal_Int32 nLength = aDescriptor.getLength();
    const beans::PropertyValue * pValue = aDescriptor.getConstArray();
    uno::Reference < io::XInputStream > xInputStream;
    ::rtl::OUString sFilterName;
    for ( sal_Int32 i = 0 ; i < nLength; i++)
    {
        if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) )
            pValue[i].Value >>= xInputStream;
        else if( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "FilterName" ) ) )
            pValue[i].Value >>= sFilterName;
    }
    if ( !xInputStream.is() )
    {
        return sal_False;
    }

#ifdef DEBUG_IMPORT
    TimeValue t1;
    osl_getSystemTime(&t1);

    writerfilter::logger("DEBUG", "<out>");
    writerfilter::logger("DEBUG", string("<starttime>") + string(t1.Seconds)
                         + "</starttime>");
#endif

    writerfilter::dmapper::SourceDocumentType eType = m_sFilterName.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "writer_MS_Word_2007" ) ) ?
                writerfilter::dmapper::DOCUMENT_OOXML : writerfilter::dmapper::DOCUMENT_DOC;
    writerfilter::Stream::Pointer_t pStream(new writerfilter::dmapper::DomainMapper(m_xContext, m_xDoc, eType));
    //create the tokenizer and domain mapper
    if( eType == writerfilter::dmapper::DOCUMENT_OOXML )
    {
        writerfilter::ooxml::OOXMLStream::Pointer_t pDocStream = writerfilter::ooxml::OOXMLDocumentFactory::createStream(m_xContext, xInputStream);
        writerfilter::ooxml::OOXMLDocument::Pointer_t pDocument(writerfilter::ooxml::OOXMLDocumentFactory::createDocument(pDocStream));

        uno::Reference<frame::XModel> xModel(m_xDoc, uno::UNO_QUERY_THROW);
        pDocument->setModel(xModel);

        uno::Reference<drawing::XDrawPageSupplier> xDrawings
            (m_xDoc, uno::UNO_QUERY_THROW);
        uno::Reference<drawing::XShapes> xShapes
            (xDrawings->getDrawPage(), uno::UNO_QUERY_THROW);
        pDocument->setShapes(xShapes);

        pDocument->resolve(*pStream);
    }
    else
    {
        writerfilter::doctok::WW8Stream::Pointer_t pDocStream = writerfilter::doctok::WW8DocumentFactory::createStream(m_xContext, xInputStream);
        writerfilter::doctok::WW8Document::Pointer_t pDocument(writerfilter::doctok::WW8DocumentFactory::createDocument(pDocStream));

        pDocument->resolve(*pStream);
    }

#ifdef DEBUG_IMPORT
    TimeValue t2;
    osl_getSystemTime(&t2);

    writerfilter::logger("DEBUG", string("<importtime>")
                         + string(t2.Seconds - t1.Seconds) + "</importtime>");
    writerfilter::logger("DEBUG", "</out>");
#endif

    return sal_True;
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void WriterFilter::cancel(  ) throw (uno::RuntimeException)
{
}

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void WriterFilter::setTargetDocument( const uno::Reference< lang::XComponent >& xDoc )
   throw (lang::IllegalArgumentException, uno::RuntimeException)
{
   m_xDoc = xDoc;
}

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
void WriterFilter::initialize( const uno::Sequence< uno::Any >& aArguments ) throw (uno::Exception, uno::RuntimeException)
{
   uno::Sequence < beans::PropertyValue > aAnySeq;
   sal_Int32 nLength = aArguments.getLength();
   if ( nLength && ( aArguments[0] >>= aAnySeq ) )
   {
       const beans::PropertyValue * pValue = aAnySeq.getConstArray();
       nLength = aAnySeq.getLength();
       for ( sal_Int32 i = 0 ; i < nLength; i++)
       {
           if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) )
           {
               pValue[i].Value >>= m_sFilterName;
               break;
           }
       }
   }
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
OUString WriterFilter_getImplementationName () throw (uno::RuntimeException)
{
   return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.WriterFilter" ) );
}

#define SERVICE_NAME1 "com.sun.star.document.ImportFilter"
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool WriterFilter_supportsService( const OUString& ServiceName ) throw (uno::RuntimeException)
{
   return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ));
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
uno::Sequence< OUString > WriterFilter_getSupportedServiceNames(  ) throw (uno::RuntimeException)
{
   uno::Sequence < OUString > aRet(1);
   OUString* pArray = aRet.getArray();
   pArray[0] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) );
   return aRet;
}
#undef SERVICE_NAME1

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
uno::Reference< uno::XInterface > WriterFilter_createInstance( const uno::Reference< uno::XComponentContext >& xContext)
                throw( uno::Exception )
{
   return (cppu::OWeakObject*) new WriterFilter( xContext );
}

/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
OUString WriterFilter::getImplementationName(  ) throw (uno::RuntimeException)
{
   return WriterFilter_getImplementationName();
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_Bool WriterFilter::supportsService( const OUString& rServiceName ) throw (uno::RuntimeException)
{
    return WriterFilter_supportsService( rServiceName );
}
/*-- 09.06.2006 10:15:20---------------------------------------------------

  -----------------------------------------------------------------------*/
uno::Sequence< OUString > WriterFilter::getSupportedServiceNames(  ) throw (uno::RuntimeException)
{
    return WriterFilter_getSupportedServiceNames();
}

<|endoftext|>


<commit_before>#line 2 "sxc:Account/Account.cxx"
// LICENSE/*{{{*/
/*
  sxc - Simple Xmpp Client
  Copyright (C) 2008 Dennis Felsing, Andreas Waidler

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/*}}}*/

// INCLUDE/*{{{*/

#include <string>
#include <pthread.h>
#include <sstream>

#include <gloox/jid.h>
#include <gloox/presence.h>
#include <gloox/clientbase.h>
#include <gloox/message.h>
#include <gloox/disco.h>
#include <gloox/error.h>

#include <libsxc/generateString.hxx>
#include <libsxc/Exception/Exception.hxx>

#include <Account/Account.hxx>
#include <Account/Roster.hxx>
#include <Account/File/Input.hxx>
#include <File/AbcOutput.hxx>

#ifdef HAVE_CONFIG_H
# include <config.hxx>
#endif

#include <libsxc/Debug/Logger.hxx>

#ifdef DEBUG
# include <sstream>
#endif

/*}}}*/

namespace Account
{
  Account::Account(/*{{{*/
    gloox::Client &client,
    Roster &roster,
    ::File::AbcOutput &out)
  : _thread()
  , _client(client) // Fill in the passphrase later.
  , _roster(roster)
#   ifdef DEBUG
  ,   _logHandler()
#   endif
  , _presence(gloox::Presence::Available)
  , _priority(0)
  , _status("")
  , _in(*this, client.jid().bare())
  , _out(out)
  {
    _client.registerConnectionListener(this);

#   ifdef DEBUG
      _client.logInstance().registerLogHandler(
        gloox::LogLevelDebug,
        gloox::LogAreaAll,
        &_logHandler);
#   endif
  }/*}}}*/
  Account::~Account()/*{{{*/
  {
    LOG("Exit.");

    disconnect();
    pthread_join(_thread, NULL);

    _client.removeConnectionListener(this);

#   if DEBUG
      _client.logInstance().removeLogHandler(&_logHandler);
#   endif
  }/*}}}*/

  void Account::run()/*{{{*/
  {
    _in.listen();
  }/*}}}*/
  void Account::setPassphrase(const std::string &pass)/*{{{*/
  {
    LOG("Set passphrase: \"" + pass + "\".");

    _client.setPassword(pass);
  }/*}}}*/
  void Account::setPresence(/*{{{*/
    gloox::Presence::PresenceType presence,
    int priority,
    const std::string &status)
  {
    std::stringstream text;
    text << "Set presence: (\"" << libsxc::genPresenceString(presence)
       << "\" (" << presence << "), priority: " << priority
       << ", message: \"" << status << "\").";;
    LOG(text.str());

    // Don't trust _client, but instead store the presence information
    // locally.
    _presence = presence;
    _priority = priority;
    _status = status;

    _client.setPresence(presence, priority, status);

    // Don't connect if already connected or connecting.
    if (_thread)
      return;
    if ("" == _client.password())
      _out.write("Password not set.");
    else
      pthread_create(&_thread, NULL, _run, (void*)this);
  }/*}}}*/
  void Account::setPresence(/*{{{*/
    gloox::Presence::PresenceType presence,
    const std::string &status)
  {
    setPresence(presence, _priority, status);
  }/*}}}*/
  void Account::setPriority(int priority)/*{{{*/
  {
    setPresence(_presence, priority, _status);
  }/*}}}*/
  void Account::disconnect()/*{{{*/
  {
    LOG("Disconnect.");

    _client.disconnect();
  }/*}}}*/

  void Account::sendMessage(/*{{{*/
    const gloox::JID &to,
    const std::string &body)
  {
    gloox::Message message(
      gloox::Message::Normal, // Not Chat.
      to,
      body);
    _client.send(message);
  }/*}}}*/
  void Account::addContact(const gloox::JID &jid)/*{{{*/
  {
    _roster.addContact(jid);
  }/*}}}*/
  void Account::removeContact(const gloox::JID &jid) const/*{{{*/
  {
    _roster.removeContact(jid);
  }/*}}}*/
  void Account::subscribe(const gloox::JID &jid, const std::string &message) const/*{{{*/
  {
    _roster.subscribe(jid, message);
  }/*}}}*/
  void Account::unsubscribe(/*{{{*/
    const gloox::JID &jid,
    const std::string &message) const
  {
    _roster.unsubscribe(jid, message);
  }/*}}}*/
  void Account::acknowledgeSubscription(const gloox::JID &jid) const/*{{{*/
  {
    _roster.acknowledgeSubscription(jid);
  }/*}}}*/
  void Account::declineSubscription(const gloox::JID &jid) const/*{{{*/
  {
    _roster.declineSubscription(jid);
  }/*}}}*/

  void Account::handleError(/*{{{*/
    libsxc::Exception::Exception &e,
    bool isCritical) const
  {
    if (isCritical) {
      //LOG<Error>(e.what()); // FIXME
      exit(e.getExitCode());
    }
    _out.write(e.what());
  }/*}}}*/

  void Account::onConnect()/*{{{*/
  {
    LOG("Connected: Connection established.");
  }/*}}}*/
  void Account::onDisconnect(gloox::ConnectionError e)/*{{{*/
  {
    LOG("Disconnected: " + libsxc::genConnErrorString(
      e,
      _client.streamError(),
      _client.streamErrorText(),
      _client.authError(),
      /* Debug = */ true));

    std::string text = libsxc::genConnErrorString(
      e,
      _client.streamError(),
      _client.streamErrorText(),
      _client.authError());
    if (!text.empty())
      _out.write("Disconnected: " + text);
  }/*}}}*/
  bool Account::onTLSConnect(const gloox::CertInfo &info)/*{{{*/
  {
    LOG("Acknowledge TLS certificate.");

    return true;
  }/*}}}*/

  void *Account::_run(void *rawThat)/*{{{*/
  {
    LOG("Start socket receiving thread.");

    Account *that = (Account *) rawThat;
    that->_client.connect(); // Blocking.

    LOG("End socket receiving thread.");

    return (void *) NULL;
  }/*}}}*/
}

// Use no tabs at all; two spaces indentation; max. eighty chars per line.
// vim: et ts=2 sw=2 sts=2 tw=80 fdm=marker
<commit_msg>Make threading more stable<commit_after>#line 2 "sxc:Account/Account.cxx"
// LICENSE/*{{{*/
/*
  sxc - Simple Xmpp Client
  Copyright (C) 2008 Dennis Felsing, Andreas Waidler

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/*}}}*/

// INCLUDE/*{{{*/

#include <string>
#include <pthread.h>
#include <sstream>

#include <gloox/jid.h>
#include <gloox/presence.h>
#include <gloox/clientbase.h>
#include <gloox/message.h>
#include <gloox/disco.h>
#include <gloox/error.h>

#include <libsxc/generateString.hxx>
#include <libsxc/Exception/Exception.hxx>

#include <Account/Account.hxx>
#include <Account/Roster.hxx>
#include <Account/File/Input.hxx>
#include <File/AbcOutput.hxx>

#ifdef HAVE_CONFIG_H
# include <config.hxx>
#endif

#include <libsxc/Debug/Logger.hxx>

#ifdef DEBUG
# include <sstream>
#endif

/*}}}*/

namespace Account
{
  Account::Account(/*{{{*/
    gloox::Client &client,
    Roster &roster,
    ::File::AbcOutput &out)
  : _thread(0)
  , _client(client) // Fill in the passphrase later.
  , _roster(roster)
#   ifdef DEBUG
  ,   _logHandler()
#   endif
  , _presence(gloox::Presence::Available)
  , _priority(0)
  , _status("")
  , _in(*this, client.jid().bare())
  , _out(out)
  {
    _client.registerConnectionListener(this);

#   ifdef DEBUG
      _client.logInstance().registerLogHandler(
        gloox::LogLevelDebug,
        gloox::LogAreaAll,
        &_logHandler);
#   endif
  }/*}}}*/
  Account::~Account()/*{{{*/
  {
    pthread_t thread = _thread;
    disconnect();
    if (thread)
      pthread_join(thread, NULL);

    _client.removeConnectionListener(this);

#   if DEBUG
      _client.logInstance().removeLogHandler(&_logHandler);
#   endif
  }/*}}}*/

  void Account::run()/*{{{*/
  {
    _in.listen();
  }/*}}}*/
  void Account::setPassphrase(const std::string &pass)/*{{{*/
  {
    LOG("Set passphrase: \"" + pass + "\".");

    _client.setPassword(pass);
  }/*}}}*/
  void Account::setPresence(/*{{{*/
    gloox::Presence::PresenceType presence,
    int priority,
    const std::string &status)
  {
    std::stringstream text;
    text << "Set presence: (\"" << libsxc::genPresenceString(presence)
       << "\" (" << presence << "), priority: " << priority
       << ", message: \"" << status << "\").";;
    LOG(text.str());

    // Don't trust _client, but instead store the presence information
    // locally.
    _presence = presence;
    _priority = priority;
    _status = status;

    _client.setPresence(presence, priority, status);

    // Don't connect if already connected or connecting.
    if (_thread)
      return;
    if ("" == _client.password())
      _out.write("Password not set.");
    else
      pthread_create(&_thread, NULL, _run, (void*)this);
  }/*}}}*/
  void Account::setPresence(/*{{{*/
    gloox::Presence::PresenceType presence,
    const std::string &status)
  {
    setPresence(presence, _priority, status);
  }/*}}}*/
  void Account::setPriority(int priority)/*{{{*/
  {
    setPresence(_presence, priority, _status);
  }/*}}}*/
  void Account::disconnect()/*{{{*/
  {
    LOG("Disconnect.");

    _client.disconnect();
    _thread = 0; // Reset to be able to restart another thread.
  }/*}}}*/

  void Account::sendMessage(/*{{{*/
    const gloox::JID &to,
    const std::string &body)
  {
    gloox::Message message(
      gloox::Message::Normal, // Not Chat.
      to,
      body);
    _client.send(message);
  }/*}}}*/
  void Account::addContact(const gloox::JID &jid)/*{{{*/
  {
    _roster.addContact(jid);
  }/*}}}*/
  void Account::removeContact(const gloox::JID &jid) const/*{{{*/
  {
    _roster.removeContact(jid);
  }/*}}}*/
  void Account::subscribe(const gloox::JID &jid, const std::string &message) const/*{{{*/
  {
    _roster.subscribe(jid, message);
  }/*}}}*/
  void Account::unsubscribe(/*{{{*/
    const gloox::JID &jid,
    const std::string &message) const
  {
    _roster.unsubscribe(jid, message);
  }/*}}}*/
  void Account::acknowledgeSubscription(const gloox::JID &jid) const/*{{{*/
  {
    _roster.acknowledgeSubscription(jid);
  }/*}}}*/
  void Account::declineSubscription(const gloox::JID &jid) const/*{{{*/
  {
    _roster.declineSubscription(jid);
  }/*}}}*/

  void Account::handleError(/*{{{*/
    libsxc::Exception::Exception &e,
    bool isCritical) const
  {
    if (isCritical) {
      //LOG<Error>(e.what()); // FIXME
      exit(e.getExitCode());
    }
    _out.write(e.what());
  }/*}}}*/

  void Account::onConnect()/*{{{*/
  {
    LOG("Connected: Connection established.");
  }/*}}}*/
  void Account::onDisconnect(gloox::ConnectionError e)/*{{{*/
  {
    LOG("Disconnected: " + libsxc::genConnErrorString(
      e,
      _client.streamError(),
      _client.streamErrorText(),
      _client.authError(),
      /* Debug = */ true));

    std::string text = libsxc::genConnErrorString(
      e,
      _client.streamError(),
      _client.streamErrorText(),
      _client.authError());
    if (!text.empty())
      _out.write("Disconnected: " + text);
  }/*}}}*/
  bool Account::onTLSConnect(const gloox::CertInfo &info)/*{{{*/
  {
    LOG("Acknowledge TLS certificate.");

    return true;
  }/*}}}*/

  void *Account::_run(void *rawThat)/*{{{*/
  {
    LOG("Start socket receiving thread.");

    Account *that = (Account *) rawThat;
    that->_client.connect(); // Blocking.

    LOG("End socket receiving thread.");

    return (void *) NULL;
  }/*}}}*/
}

// Use no tabs at all; two spaces indentation; max. eighty chars per line.
// vim: et ts=2 sw=2 sts=2 tw=80 fdm=marker
<|endoftext|>


<commit_before>/* rsspp - Copyright (C) 2008-2009 Andreas Krennmair <ak@newsbeuter.org>
 * Licensed under the MIT/X Consortium License. See file LICENSE
 * for more information.
 */

#include <config.h>
#include <rsspp.h>
#include <rsspp_internal.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <curl/curl.h>
#include <logger.h>
#include <utils.h>
#include <cstring>
#include <utils.h>

using namespace newsbeuter;

static size_t my_write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
	std::string * pbuf = static_cast<std::string *>(userp);
	pbuf->append(static_cast<const char *>(buffer), size * nmemb);
	return size * nmemb;
}

namespace rsspp {

parser::parser(unsigned int timeout, const char * user_agent, const char * proxy, const char * proxy_auth, curl_proxytype proxy_type)
	: to(timeout), ua(user_agent), prx(proxy), prxauth(proxy_auth), prxtype(proxy_type), doc(0), lm(0) {
}

parser::~parser() {
	if (doc)
		xmlFreeDoc(doc);
}

struct header_values {
	time_t lastmodified;
	std::string etag;
};

static size_t handle_headers(void * ptr, size_t size, size_t nmemb, void * data) {
	char * header = new char[size*nmemb + 1];
	header_values * values = (header_values *)data;

	memcpy(header, ptr, size*nmemb);
	header[size*nmemb] = '\0';

	if (!strncasecmp("Last-Modified:", header, 14)) {
		values->lastmodified = curl_getdate(header+14, NULL);
		LOG(LOG_DEBUG, "handle_headers: got last-modified %s (%d)", header+14, values->lastmodified);
	} else if (!strncasecmp("ETag:",header, 5)) {
		values->etag = std::string(header+5);
		utils::trim(values->etag);
		LOG(LOG_DEBUG, "handle_headers: got etag %s", values->etag.c_str());
	}

	delete[] header;

	return size * nmemb;
}

feed parser::parse_url(const std::string& url, time_t lastmodified, const std::string& etag) {
	std::string buf;
	CURLcode ret;

	CURL * easyhandle = curl_easy_init();
	if (!easyhandle) {
		throw exception(_("couldn't initialize libcurl"));
	}

	if (ua) {
		curl_easy_setopt(easyhandle, CURLOPT_USERAGENT, ua);
	}
	curl_easy_setopt(easyhandle, CURLOPT_URL, url.c_str());
	curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYPEER, 0);
	curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, my_write_data);
	curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &buf);
	curl_easy_setopt(easyhandle, CURLOPT_NOSIGNAL, 1);
	curl_easy_setopt(easyhandle, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(easyhandle, CURLOPT_MAXREDIRS, 10);
	curl_easy_setopt(easyhandle, CURLOPT_FAILONERROR, 1);
	curl_easy_setopt(easyhandle, CURLOPT_ENCODING, "gzip, deflate");
	if (to != 0)
		curl_easy_setopt(easyhandle, CURLOPT_TIMEOUT, to);

	if (prx)
		curl_easy_setopt(easyhandle, CURLOPT_PROXY, prx);

	if (prxauth)
		curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, prxauth);

	curl_easy_setopt(easyhandle, CURLOPT_PROXYTYPE, prxtype);

	header_values hdrs = { 0, "" };

	curl_slist * custom_headers = NULL;

	if (lastmodified != 0) {
		curl_easy_setopt(easyhandle, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
		curl_easy_setopt(easyhandle, CURLOPT_TIMEVALUE, lastmodified);
		curl_easy_setopt(easyhandle, CURLOPT_HEADERDATA, &hdrs);
		curl_easy_setopt(easyhandle, CURLOPT_HEADERFUNCTION, handle_headers);
	}
	if (etag.length() > 0) {
		custom_headers = curl_slist_append(custom_headers, utils::strprintf("If-None-Match: %s", etag.c_str()).c_str());
		curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, custom_headers);
		curl_easy_setopt(easyhandle, CURLOPT_HEADERDATA, &hdrs);
		curl_easy_setopt(easyhandle, CURLOPT_HEADERFUNCTION, handle_headers);
	}

	ret = curl_easy_perform(easyhandle);

	lm = hdrs.lastmodified;
	et = hdrs.etag;

	if (custom_headers) {
		curl_slist_free_all(custom_headers);
	}

	LOG(LOG_DEBUG, "rsspp::parser::parse_url: ret = %d", ret);

	long status;
	curl_easy_getinfo(easyhandle, CURLINFO_HTTP_CONNECTCODE, &status);

	if (status >= 400) {
		LOG(LOG_USERERROR, _("Error: trying to download feed `%s' returned HTTP status code %ld."), url.c_str(), status);
	}

	curl_easy_cleanup(easyhandle);

	if (ret != 0) {
		LOG(LOG_ERROR, "rsspp::parser::parse_url: curl_easy_perform returned err %d: %s", ret, curl_easy_strerror(ret));
		throw exception(curl_easy_strerror(ret));
	}

	LOG(LOG_INFO, "parser::parse_url: retrieved data for %s: %s", url.c_str(), buf.c_str());

	if (buf.length() > 0) {
		LOG(LOG_DEBUG, "parser::parse_url: handing over data to parse_buffer()");
		return parse_buffer(buf.c_str(), buf.length(), url.c_str());
	}

	return feed();
}

feed parser::parse_buffer(const char * buffer, size_t size, const char * url) {
	doc = xmlReadMemory(buffer, size, url, NULL, XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
	if (doc == NULL) {
		throw exception(_("could not parse buffer"));
	}

	xmlNode* root_element = xmlDocGetRootElement(doc);

	feed f = parse_xmlnode(root_element);

	if (doc->encoding) {
		f.encoding = (const char *)doc->encoding;
	}

	LOG(LOG_INFO, "parser::parse_buffer: encoding = %s", f.encoding.c_str());

	return f;
}

feed parser::parse_file(const std::string& filename) {
	doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
	if (doc == NULL) {
		throw exception(_("could not parse file"));
	}

	xmlNode* root_element = xmlDocGetRootElement(doc);

	feed f = parse_xmlnode(root_element);

	if (doc->encoding) {
		f.encoding = (const char *)doc->encoding;
	}

	LOG(LOG_INFO, "parser::parse_file: encoding = %s", f.encoding.c_str());

	return f;
}

feed parser::parse_xmlnode(xmlNode* node) {
	feed f;

	if (node) {
		if (node->name && node->type == XML_ELEMENT_NODE) {
			if (strcmp((const char *)node->name, "rss")==0) {
				const char * version = (const char *)xmlGetProp(node, (const xmlChar *)"version");
				if (!version) {
					xmlFree((void *)version);
					throw exception(_("no RSS version"));
				}
				if (strcmp(version, "0.91")==0)
					f.rss_version = RSS_0_91;
				else if (strcmp(version, "0.92")==0)
					f.rss_version = RSS_0_92;
				else if (strcmp(version, "2.0")==0)
					f.rss_version = RSS_2_0;
				else {
					xmlFree((void *)version);
					throw exception(_("invalid RSS version"));
				}
				xmlFree((void *)version);
			} else if (strcmp((const char *)node->name, "RDF")==0) {
				f.rss_version = RSS_1_0;
			} else if (strcmp((const char *)node->name, "feed")==0) {
				if (node->ns && node->ns->href) {
					if (strcmp((const char *)node->ns->href, ATOM_0_3_URI)==0) {
						f.rss_version = ATOM_0_3;
					} else if (strcmp((const char *)node->ns->href, ATOM_1_0_URI)==0) {
						f.rss_version = ATOM_1_0;
					} else {
						throw exception(_("invalid Atom version"));
					}
				} else {
					throw exception(_("no Atom version"));
				}
			}

			std::tr1::shared_ptr<rss_parser> parser = rss_parser_factory::get_object(f, doc);

			try {
				parser->parse_feed(f, node);
			} catch (exception& e) {
				throw e;
			}
		}
	} else {
		throw exception(_("XML root node is NULL"));
	}

	return f;
}

void parser::global_init() {
	LIBXML_TEST_VERSION
	curl_global_init(CURL_GLOBAL_ALL);
}

void parser::global_cleanup() {
	xmlCleanupParser();
	curl_global_cleanup();
}

}
<commit_msg>added rss version "2" as workaround for broken feeds.<commit_after>/* rsspp - Copyright (C) 2008-2009 Andreas Krennmair <ak@newsbeuter.org>
 * Licensed under the MIT/X Consortium License. See file LICENSE
 * for more information.
 */

#include <config.h>
#include <rsspp.h>
#include <rsspp_internal.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <curl/curl.h>
#include <logger.h>
#include <utils.h>
#include <cstring>
#include <utils.h>

using namespace newsbeuter;

static size_t my_write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
	std::string * pbuf = static_cast<std::string *>(userp);
	pbuf->append(static_cast<const char *>(buffer), size * nmemb);
	return size * nmemb;
}

namespace rsspp {

parser::parser(unsigned int timeout, const char * user_agent, const char * proxy, const char * proxy_auth, curl_proxytype proxy_type)
	: to(timeout), ua(user_agent), prx(proxy), prxauth(proxy_auth), prxtype(proxy_type), doc(0), lm(0) {
}

parser::~parser() {
	if (doc)
		xmlFreeDoc(doc);
}

struct header_values {
	time_t lastmodified;
	std::string etag;
};

static size_t handle_headers(void * ptr, size_t size, size_t nmemb, void * data) {
	char * header = new char[size*nmemb + 1];
	header_values * values = (header_values *)data;

	memcpy(header, ptr, size*nmemb);
	header[size*nmemb] = '\0';

	if (!strncasecmp("Last-Modified:", header, 14)) {
		values->lastmodified = curl_getdate(header+14, NULL);
		LOG(LOG_DEBUG, "handle_headers: got last-modified %s (%d)", header+14, values->lastmodified);
	} else if (!strncasecmp("ETag:",header, 5)) {
		values->etag = std::string(header+5);
		utils::trim(values->etag);
		LOG(LOG_DEBUG, "handle_headers: got etag %s", values->etag.c_str());
	}

	delete[] header;

	return size * nmemb;
}

feed parser::parse_url(const std::string& url, time_t lastmodified, const std::string& etag) {
	std::string buf;
	CURLcode ret;

	CURL * easyhandle = curl_easy_init();
	if (!easyhandle) {
		throw exception(_("couldn't initialize libcurl"));
	}

	if (ua) {
		curl_easy_setopt(easyhandle, CURLOPT_USERAGENT, ua);
	}
	curl_easy_setopt(easyhandle, CURLOPT_URL, url.c_str());
	curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYPEER, 0);
	curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, my_write_data);
	curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, &buf);
	curl_easy_setopt(easyhandle, CURLOPT_NOSIGNAL, 1);
	curl_easy_setopt(easyhandle, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(easyhandle, CURLOPT_MAXREDIRS, 10);
	curl_easy_setopt(easyhandle, CURLOPT_FAILONERROR, 1);
	curl_easy_setopt(easyhandle, CURLOPT_ENCODING, "gzip, deflate");
	if (to != 0)
		curl_easy_setopt(easyhandle, CURLOPT_TIMEOUT, to);

	if (prx)
		curl_easy_setopt(easyhandle, CURLOPT_PROXY, prx);

	if (prxauth)
		curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, prxauth);

	curl_easy_setopt(easyhandle, CURLOPT_PROXYTYPE, prxtype);

	header_values hdrs = { 0, "" };

	curl_slist * custom_headers = NULL;

	if (lastmodified != 0) {
		curl_easy_setopt(easyhandle, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
		curl_easy_setopt(easyhandle, CURLOPT_TIMEVALUE, lastmodified);
		curl_easy_setopt(easyhandle, CURLOPT_HEADERDATA, &hdrs);
		curl_easy_setopt(easyhandle, CURLOPT_HEADERFUNCTION, handle_headers);
	}
	if (etag.length() > 0) {
		custom_headers = curl_slist_append(custom_headers, utils::strprintf("If-None-Match: %s", etag.c_str()).c_str());
		curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, custom_headers);
		curl_easy_setopt(easyhandle, CURLOPT_HEADERDATA, &hdrs);
		curl_easy_setopt(easyhandle, CURLOPT_HEADERFUNCTION, handle_headers);
	}

	ret = curl_easy_perform(easyhandle);

	lm = hdrs.lastmodified;
	et = hdrs.etag;

	if (custom_headers) {
		curl_slist_free_all(custom_headers);
	}

	LOG(LOG_DEBUG, "rsspp::parser::parse_url: ret = %d", ret);

	long status;
	curl_easy_getinfo(easyhandle, CURLINFO_HTTP_CONNECTCODE, &status);

	if (status >= 400) {
		LOG(LOG_USERERROR, _("Error: trying to download feed `%s' returned HTTP status code %ld."), url.c_str(), status);
	}

	curl_easy_cleanup(easyhandle);

	if (ret != 0) {
		LOG(LOG_ERROR, "rsspp::parser::parse_url: curl_easy_perform returned err %d: %s", ret, curl_easy_strerror(ret));
		throw exception(curl_easy_strerror(ret));
	}

	LOG(LOG_INFO, "parser::parse_url: retrieved data for %s: %s", url.c_str(), buf.c_str());

	if (buf.length() > 0) {
		LOG(LOG_DEBUG, "parser::parse_url: handing over data to parse_buffer()");
		return parse_buffer(buf.c_str(), buf.length(), url.c_str());
	}

	return feed();
}

feed parser::parse_buffer(const char * buffer, size_t size, const char * url) {
	doc = xmlReadMemory(buffer, size, url, NULL, XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
	if (doc == NULL) {
		throw exception(_("could not parse buffer"));
	}

	xmlNode* root_element = xmlDocGetRootElement(doc);

	feed f = parse_xmlnode(root_element);

	if (doc->encoding) {
		f.encoding = (const char *)doc->encoding;
	}

	LOG(LOG_INFO, "parser::parse_buffer: encoding = %s", f.encoding.c_str());

	return f;
}

feed parser::parse_file(const std::string& filename) {
	doc = xmlReadFile(filename.c_str(), NULL, XML_PARSE_RECOVER | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
	if (doc == NULL) {
		throw exception(_("could not parse file"));
	}

	xmlNode* root_element = xmlDocGetRootElement(doc);

	feed f = parse_xmlnode(root_element);

	if (doc->encoding) {
		f.encoding = (const char *)doc->encoding;
	}

	LOG(LOG_INFO, "parser::parse_file: encoding = %s", f.encoding.c_str());

	return f;
}

feed parser::parse_xmlnode(xmlNode* node) {
	feed f;

	if (node) {
		if (node->name && node->type == XML_ELEMENT_NODE) {
			if (strcmp((const char *)node->name, "rss")==0) {
				const char * version = (const char *)xmlGetProp(node, (const xmlChar *)"version");
				if (!version) {
					xmlFree((void *)version);
					throw exception(_("no RSS version"));
				}
				if (strcmp(version, "0.91")==0)
					f.rss_version = RSS_0_91;
				else if (strcmp(version, "0.92")==0)
					f.rss_version = RSS_0_92;
				else if (strcmp(version, "2.0")==0 || strcmp(version, "2")==0)
					f.rss_version = RSS_2_0;
				else {
					xmlFree((void *)version);
					throw exception(_("invalid RSS version"));
				}
				xmlFree((void *)version);
			} else if (strcmp((const char *)node->name, "RDF")==0) {
				f.rss_version = RSS_1_0;
			} else if (strcmp((const char *)node->name, "feed")==0) {
				if (node->ns && node->ns->href) {
					if (strcmp((const char *)node->ns->href, ATOM_0_3_URI)==0) {
						f.rss_version = ATOM_0_3;
					} else if (strcmp((const char *)node->ns->href, ATOM_1_0_URI)==0) {
						f.rss_version = ATOM_1_0;
					} else {
						throw exception(_("invalid Atom version"));
					}
				} else {
					throw exception(_("no Atom version"));
				}
			}

			std::tr1::shared_ptr<rss_parser> parser = rss_parser_factory::get_object(f, doc);

			try {
				parser->parse_feed(f, node);
			} catch (exception& e) {
				throw e;
			}
		}
	} else {
		throw exception(_("XML root node is NULL"));
	}

	return f;
}

void parser::global_init() {
	LIBXML_TEST_VERSION
	curl_global_init(CURL_GLOBAL_ALL);
}

void parser::global_cleanup() {
	xmlCleanupParser();
	curl_global_cleanup();
}

}
<|endoftext|>


<commit_before>// Copyright 2009, Google Inc.
// 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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
// OWNER 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.
//
// Author: wan@google.com (Zhanyong Wan)
//
// Tests for Google C++ Mocking Framework (Google Mock)
//
// Sometimes it's desirable to build most of Google Mock's own tests
// by compiling a single file.  This file serves this purpose.
#include "test/gmock-actions_test.cc"
#include "test/gmock-cardinalities_test.cc"
#include "test/gmock-generated-actions_test.cc"
#include "test/gmock-generated-function-mockers_test.cc"
#include "test/gmock-generated-internal-utils_test.cc"
#include "test/gmock-generated-matchers_test.cc"
#include "test/gmock-internal-utils_test.cc"
#include "test/gmock-matchers_test.cc"
#include "test/gmock-more-actions_test.cc"
#include "test/gmock-nice-strict_test.cc"
#include "test/gmock-port_test.cc"
#include "test/gmock-spec-builders_test.cc"
#include "test/gmock_test.cc"
<commit_msg>Clarify the rationale for gmock_all_test.cc, and pull in gtest 669<commit_after>// Copyright 2009, Google Inc.
// 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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
// OWNER 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.
//
// Author: wan@google.com (Zhanyong Wan)
//
// Tests for Google C++ Mocking Framework (Google Mock)
//
// Some users use a build system that Google Mock doesn't support directly,
// yet they still want to build and run Google Mock's own tests.  This file
// includes most such tests, making it easier for these users to maintain
// their build scripts (they just need to build this file, even though the
// below list of actual *_test.cc files might change).
#include "test/gmock-actions_test.cc"
#include "test/gmock-cardinalities_test.cc"
#include "test/gmock-generated-actions_test.cc"
#include "test/gmock-generated-function-mockers_test.cc"
#include "test/gmock-generated-internal-utils_test.cc"
#include "test/gmock-generated-matchers_test.cc"
#include "test/gmock-internal-utils_test.cc"
#include "test/gmock-matchers_test.cc"
#include "test/gmock-more-actions_test.cc"
#include "test/gmock-nice-strict_test.cc"
#include "test/gmock-port_test.cc"
#include "test/gmock-spec-builders_test.cc"
#include "test/gmock_test.cc"
<|endoftext|>


<commit_before>#include "gt/gtl/test_common.hpp"

BOOST_AUTO_TEST_SUITE( Parser )

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

BOOST_AUTO_TEST_CASE( Parser_emptyProgramIsValid  ) {
    // given
    std::string content;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
}

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

BOOST_AUTO_TEST_CASE( Parser_valueParamDefinition  ) {
    // given
    std::string content =
        "LET value1 BE 10;\n"
        "LET value2 BE 20.0;\n"
        "LET value3 BE 3e1;\n"
        "LET value4 BE 4.0e1;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 4 ); // parsed 4 definitions
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 4 ); // created 4 parameters from numbers
}

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

BOOST_AUTO_TEST_CASE( Parser_identifierParamDefinition  ) {
    // given
    std::string content =
        "LET value1 BE id;\n"
        "LET value2 BE _id;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 2 ); // parsed 2 definitions
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 2 ); // created 2 parameters from identifiers
}

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

BOOST_AUTO_TEST_CASE( Parser_playerDefinition  ) {
    // given
    std::string content =
        "LET _player BE\n"
        "PLAYER p1 {\n"
        "  s1,\n"
        "  s2\n"
        "};\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 1 ); // parsed 1 definition
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 1 ); // created 1 player
    BOOST_CHECK_EQUAL( driver.identifiers.getAddedElements(), 2 ); // created collection of 2 strategies
}

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

BOOST_AUTO_TEST_CASE( Parser_strategicGameDefinition  ) {
    // given
    std::string content =
        "LET _game BE\n"
        "STRATEGIC GAME WITH\n"
        "  PLAYER p1 {\n"
        "    s1,\n"
        "    s2\n"
        "  },\n"
        "  PLAYER p2 {\n"
        "    s1,\n"
        "    s2\n"
        "  }\n"
        "SUCH AS\n"
        "  { p1=s1, p2=s1 : 10, param1 },\n"
        "  { p1=s1, p2=s2 : param2, 20.0 },\n"
        "  { p1=s2 :\n"
        "     { p2=s1 : 3e1, param3 },\n"
        "     { p2=s2 : param4, 4.0e1 }\n"
        "  };\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 1 ); // parsed 1 definition
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 2 ); // created 2 players
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 8 ); // created 8 parameters from numbers
}

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

BOOST_AUTO_TEST_CASE( Parser_treeGameDefinition  ) {
    // given
    std::string content =
        "LET _game BE\n"
        "TREE GAME WITH\n"
        "  PLAYER p1 {\n"
        "    s1,\n"
        "    s2\n"
        "  },\n"
        "  PLAYER p2 {\n"
        "    s1,\n"
        "    s2\n"
        "  }\n"
        "SUCH AS\n"
        "  { p1=s1 :\n"
        "     { p2=s1 : 10, param1 },\n"
        "     { p2=s2 : param2, 20.0 }\n"
        "  },\n"
        "  { p1=s2 :\n"
        "     { p2=s1 : 3e1, param3 },\n"
        "     { p2=s2 : param4, 4.0e1 }\n"
        "  };\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 1 ); // parsed 1 definition
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 2 ); // created 2 players
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 8 ); // created 8 parameters from numbers
}

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

BOOST_AUTO_TEST_CASE( Parser_queryForType ) {
    // given
    std::string content =
        "FIND type\n"
        "FOR\n"
        "  10,\n"
        "  20.0,\n"
        "  3e1,\n"
        "  4.0e1,\n"
        "  identifier,\n"
        "  PLAYER p { s1, s2 },\n"
        "  STRATEGIC GAME\n"
        "  WITH\n"
        "    PLAYER p1 { s },\n"
        "    PLAYER p2 { s }\n"
        "  SUCH AS\n"
        "    { p1=s, p2=s : 10, 20 }\n"
        "  END,\n"
        "  TREE GAME\n"
        "  WITH\n"
        "    PLAYER p1 { s },\n"
        "    PLAYER p2 { s }\n"
        "  SUCH AS\n"
        "    { p1=s :\n"
        "      { p2=s : 10, 20 }\n"
        "    }\n"
        "  END;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedQueries(), 1 ); // parser 1 query
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 9 ); // created 9 parameters from numbers (8) nad identifiers (1)
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 5 ); // crated 5 players
    BOOST_CHECK_EQUAL( driver.game.getCreatedStrategicGames(), 1 ); // created 1 strategy game
    BOOST_CHECK_EQUAL( driver.game.getCreatedTreeGames(), 1 ); // created 1 tree game
}

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

BOOST_AUTO_TEST_CASE( Parser_queryForValue ) {
    // given
    std::string content =
        "FIND value\n"
        "FOR\n"
        "  10,\n"
        "  20.0,\n"
        "  3e1,\n"
        "  4.0e1,\n"
        "  identifier;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedQueries(), 1 ); // parser 1 query
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 5 ); // created 5 parameters from numbers (4) nad identifiers (1)
}

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

BOOST_AUTO_TEST_CASE( Parser_queryForEquilibrium ) {
    // given
    std::string content =
        "FIND pure_equilibrium, mixed_equilibrium\n"
        "FOR\n"
        "  STRATEGIC GAME\n"
        "  WITH\n"
        "    PLAYER p1 { s },\n"
        "    PLAYER p2 { s }\n"
        "  SUCH AS\n"
        "    { p1=s, p2=s : 10, 20 }\n"
        "  END,\n"
        "  TREE GAME\n"
        "  WITH\n"
        "    PLAYER p1 { s },\n"
        "    PLAYER p2 { s }\n"
        "  SUCH AS\n"
        "    { p1=s :\n"
        "      { p2=s : 10, 20 }\n"
        "    }\n"
        "  END;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedQueries(), 1 ); // parsed 1 query
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 4 ); // created 4 parameters from numbers
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 4 ); // crated 4 players
    BOOST_CHECK_EQUAL( driver.game.getCreatedStrategicGames(), 1 ); // created 1 strategy game
    BOOST_CHECK_EQUAL( driver.game.getCreatedTreeGames(), 1 ); // created 1 tree game
}

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

BOOST_AUTO_TEST_CASE( Parser_defineThenQuery ) {
    // given
    std::string content =
        "LET player1 BE\n"
        "  PLAYER p1 { s };\n"
        "LET player2 BE\n"
        "  PLAYER p2 { s };\n"
        "FIND pure_equilibrium, mixed_equilibrium\n"
        "FOR\n"
        "  STRATEGIC GAME\n"
        "  WITH\n"
        "    player1,\n"
        "    player2\n"
        "  SUCH AS\n"
        "    { p1=s, p2=s : 10, 20 };\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 2 ); // parsed 2 definitions
    BOOST_CHECK_EQUAL( driver.statement.getExecutedQueries(), 1 ); // parsed 1 query
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 4 ); // created 4 parameters from numbers (2) and identifiers (2)
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 2 ); // crated 2 players
    BOOST_CHECK_EQUAL( driver.game.getCreatedStrategicGames(), 1 ); // created 1 strategy game
}

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

BOOST_AUTO_TEST_CASE( Parser_recoverFromErrorAtStatement ) {
    // given
    std::string content =
        "error;\n"
        "LET player1 BE\n"
        "  PLAYER p1 { s };\n"
        "LET player2 BE\n"
        "  PLAYER p2 { s };\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // recovered from parsing error
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 1 ); // 1 error occured
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 2 ); // parsed 2 definitions
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 2 ); // created 2 players
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>* Modified parser test to match convension used in project.<commit_after>#include "gt/gtl/test_common.hpp"

BOOST_AUTO_TEST_SUITE( Parser )

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

BOOST_AUTO_TEST_CASE( Parser_emptyProgramIsValid  ) {
    // given
    std::string content;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
}

BOOST_AUTO_TEST_CASE( Parser_valueParamDefinition  ) {
    // given
    std::string content =
        "LET value1 BE 10;\n"
        "LET value2 BE 20.0;\n"
        "LET value3 BE 3e1;\n"
        "LET value4 BE 4.0e1;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 4 ); // parsed 4 definitions
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 4 ); // created 4 parameters from numbers
}

BOOST_AUTO_TEST_CASE( Parser_identifierParamDefinition  ) {
    // given
    std::string content =
        "LET value1 BE id;\n"
        "LET value2 BE _id;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 2 ); // parsed 2 definitions
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 2 ); // created 2 parameters from identifiers
}

BOOST_AUTO_TEST_CASE( Parser_playerDefinition  ) {
    // given
    std::string content =
        "LET _player BE\n"
        "PLAYER p1 {\n"
        "  s1,\n"
        "  s2\n"
        "};\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 1 ); // parsed 1 definition
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 1 ); // created 1 player
    BOOST_CHECK_EQUAL( driver.identifiers.getAddedElements(), 2 ); // created collection of 2 strategies
}

BOOST_AUTO_TEST_CASE( Parser_strategicGameDefinition  ) {
    // given
    std::string content =
        "LET _game BE\n"
        "STRATEGIC GAME WITH\n"
        "  PLAYER p1 {\n"
        "    s1,\n"
        "    s2\n"
        "  },\n"
        "  PLAYER p2 {\n"
        "    s1,\n"
        "    s2\n"
        "  }\n"
        "SUCH AS\n"
        "  { p1=s1, p2=s1 : 10, param1 },\n"
        "  { p1=s1, p2=s2 : param2, 20.0 },\n"
        "  { p1=s2 :\n"
        "     { p2=s1 : 3e1, param3 },\n"
        "     { p2=s2 : param4, 4.0e1 }\n"
        "  };\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 1 ); // parsed 1 definition
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 2 ); // created 2 players
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 8 ); // created 8 parameters from numbers
}

BOOST_AUTO_TEST_CASE( Parser_treeGameDefinition  ) {
    // given
    std::string content =
        "LET _game BE\n"
        "TREE GAME WITH\n"
        "  PLAYER p1 {\n"
        "    s1,\n"
        "    s2\n"
        "  },\n"
        "  PLAYER p2 {\n"
        "    s1,\n"
        "    s2\n"
        "  }\n"
        "SUCH AS\n"
        "  { p1=s1 :\n"
        "     { p2=s1 : 10, param1 },\n"
        "     { p2=s2 : param2, 20.0 }\n"
        "  },\n"
        "  { p1=s2 :\n"
        "     { p2=s1 : 3e1, param3 },\n"
        "     { p2=s2 : param4, 4.0e1 }\n"
        "  };\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 1 ); // parsed 1 definition
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 2 ); // created 2 players
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 8 ); // created 8 parameters from numbers
}

BOOST_AUTO_TEST_CASE( Parser_queryForType ) {
    // given
    std::string content =
        "FIND type\n"
        "FOR\n"
        "  10,\n"
        "  20.0,\n"
        "  3e1,\n"
        "  4.0e1,\n"
        "  identifier,\n"
        "  PLAYER p { s1, s2 },\n"
        "  STRATEGIC GAME\n"
        "  WITH\n"
        "    PLAYER p1 { s },\n"
        "    PLAYER p2 { s }\n"
        "  SUCH AS\n"
        "    { p1=s, p2=s : 10, 20 }\n"
        "  END,\n"
        "  TREE GAME\n"
        "  WITH\n"
        "    PLAYER p1 { s },\n"
        "    PLAYER p2 { s }\n"
        "  SUCH AS\n"
        "    { p1=s :\n"
        "      { p2=s : 10, 20 }\n"
        "    }\n"
        "  END;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedQueries(), 1 ); // parser 1 query
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 9 ); // created 9 parameters from numbers (8) nad identifiers (1)
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 5 ); // crated 5 players
    BOOST_CHECK_EQUAL( driver.game.getCreatedStrategicGames(), 1 ); // created 1 strategy game
    BOOST_CHECK_EQUAL( driver.game.getCreatedTreeGames(), 1 ); // created 1 tree game
}

BOOST_AUTO_TEST_CASE( Parser_queryForValue ) {
    // given
    std::string content =
        "FIND value\n"
        "FOR\n"
        "  10,\n"
        "  20.0,\n"
        "  3e1,\n"
        "  4.0e1,\n"
        "  identifier;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedQueries(), 1 ); // parser 1 query
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 5 ); // created 5 parameters from numbers (4) nad identifiers (1)
}

BOOST_AUTO_TEST_CASE( Parser_queryForEquilibrium ) {
    // given
    std::string content =
        "FIND pure_equilibrium, mixed_equilibrium\n"
        "FOR\n"
        "  STRATEGIC GAME\n"
        "  WITH\n"
        "    PLAYER p1 { s },\n"
        "    PLAYER p2 { s }\n"
        "  SUCH AS\n"
        "    { p1=s, p2=s : 10, 20 }\n"
        "  END,\n"
        "  TREE GAME\n"
        "  WITH\n"
        "    PLAYER p1 { s },\n"
        "    PLAYER p2 { s }\n"
        "  SUCH AS\n"
        "    { p1=s :\n"
        "      { p2=s : 10, 20 }\n"
        "    }\n"
        "  END;\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedQueries(), 1 ); // parsed 1 query
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 4 ); // created 4 parameters from numbers
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 4 ); // crated 4 players
    BOOST_CHECK_EQUAL( driver.game.getCreatedStrategicGames(), 1 ); // created 1 strategy game
    BOOST_CHECK_EQUAL( driver.game.getCreatedTreeGames(), 1 ); // created 1 tree game
}

BOOST_AUTO_TEST_CASE( Parser_defineThenQuery ) {
    // given
    std::string content =
        "LET player1 BE\n"
        "  PLAYER p1 { s };\n"
        "LET player2 BE\n"
        "  PLAYER p2 { s };\n"
        "FIND pure_equilibrium, mixed_equilibrium\n"
        "FOR\n"
        "  STRATEGIC GAME\n"
        "  WITH\n"
        "    player1,\n"
        "    player2\n"
        "  SUCH AS\n"
        "    { p1=s, p2=s : 10, 20 };\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // no errors occured
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 0 ); // no errors shown
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 2 ); // parsed 2 definitions
    BOOST_CHECK_EQUAL( driver.statement.getExecutedQueries(), 1 ); // parsed 1 query
    BOOST_CHECK_EQUAL( driver.value.getUsedParameters(), 4 ); // created 4 parameters from numbers (2) and identifiers (2)
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 2 ); // crated 2 players
    BOOST_CHECK_EQUAL( driver.game.getCreatedStrategicGames(), 1 ); // created 1 strategy game
}

BOOST_AUTO_TEST_CASE( Parser_recoverFromErrorAtStatement ) {
    // given
    std::string content =
        "error;\n"
        "LET player1 BE\n"
        "  PLAYER p1 { s };\n"
        "LET player2 BE\n"
        "  PLAYER p2 { s };\n"
    ;
    std::istringstream   stream(content);
    GT::GTL::Scanner     scanner(&stream);
    TestDriverImpl driver;

    // when
    GT::GTL::Parser parser(scanner, driver);
    // parser.set_debug_level(1);

    // then
    BOOST_REQUIRE_EQUAL( parser.parse(), 0 ); // recovered from parsing error
    BOOST_CHECK_EQUAL( driver.getShownErrors(), 1 ); // 1 error occured
    BOOST_CHECK_EQUAL( driver.statement.getExecutedDefinitions(), 2 ); // parsed 2 definitions
    BOOST_CHECK_EQUAL( driver.game.getCreatedPlayers(), 2 ); // created 2 players
}

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

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>