<commit_before>/*
 *
 * Copyright 2015, 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.
 *
 */

#include <list>
#include <thread>
#include <deque>
#include <vector>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/host_port.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>

#include "src/core/support/env.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/qps/driver.h"
#include "test/cpp/qps/histogram.h"
#include "test/cpp/qps/qps_worker.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"

using std::list;
using std::thread;
using std::unique_ptr;
using std::deque;
using std::vector;

namespace grpc {
namespace testing {
static deque<string> get_hosts(const string& name) {
  char* env = gpr_getenv(name.c_str());
  if (!env) return deque<string>();

  deque<string> out;
  char* p = env;
  for (;;) {
    char* comma = strchr(p, ',');
    if (comma) {
      out.emplace_back(p, comma);
      p = comma + 1;
    } else {
      out.emplace_back(p);
      gpr_free(env);
      return out;
    }
  }
}

// Namespace for classes and functions used only in RunScenario
// Using this rather than local definitions to workaround gcc-4.4 limitations
// regarding using templates without linkage
namespace runsc {

// ClientContext allocator
template <class T>
static ClientContext* AllocContext(list<ClientContext>* contexts, T deadline) {
  contexts->emplace_back();
  auto context = &contexts->back();
  context->set_deadline(deadline);
  return context;
}

struct ServerData {
  unique_ptr<WorkerService::Stub> stub;
  unique_ptr<ClientReaderWriter<ServerArgs, ServerStatus>> stream;
};

struct ClientData {
  unique_ptr<WorkerService::Stub> stub;
  unique_ptr<ClientReaderWriter<ClientArgs, ClientStatus>> stream;
};
}  // namespace runsc

std::unique_ptr<ScenarioResult> RunScenario(
    const ClientConfig& initial_client_config, size_t num_clients,
    const ServerConfig& server_config, size_t num_servers, int warmup_seconds,
    int benchmark_seconds, int spawn_local_worker_count) {
  // ClientContext allocations (all are destroyed at scope exit)
  list<ClientContext> contexts;

  // To be added to the result, containing the final configuration used for
  // client and config (including host, etc.)
  ClientConfig result_client_config;
  ServerConfig result_server_config;

  // Get client, server lists
  auto workers = get_hosts("QPS_WORKERS");
  ClientConfig client_config = initial_client_config;

  // Spawn some local workers if desired
  vector<unique_ptr<QpsWorker>> local_workers;
  for (int i = 0; i < abs(spawn_local_worker_count); i++) {
    // act as if we're a new test -- gets a good rng seed
    static bool called_init = false;
    if (!called_init) {
      char args_buf[100];
      strcpy(args_buf, "some-benchmark");
      char* args[] = {args_buf};
      grpc_test_init(1, args);
      called_init = true;
    }

    int driver_port = grpc_pick_unused_port_or_die();
    local_workers.emplace_back(new QpsWorker(driver_port));
    char addr[256];
    sprintf(addr, "localhost:%d", driver_port);
    if (spawn_local_worker_count < 0) {
      workers.push_front(addr);
    } else {
      workers.push_back(addr);
    }
  }

  // TODO(ctiller): support running multiple configurations, and binpack
  // client/server pairs
  // to available workers
  GPR_ASSERT(workers.size() >= num_clients + num_servers);

  // Trim to just what we need
  workers.resize(num_clients + num_servers);

  gpr_timespec deadline =
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                   gpr_time_from_seconds(
                       warmup_seconds + benchmark_seconds + 20, GPR_TIMESPAN));

  // Start servers
  using runsc::ServerData;
  // servers is array rather than std::vector to avoid gcc-4.4 issues
  // where class contained in std::vector must have a copy constructor
  auto* servers = new ServerData[num_servers];
  for (size_t i = 0; i < num_servers; i++) {
    gpr_log(GPR_INFO, "Starting server on %s (worker #%d)",
            workers[i].c_str(), i);
    servers[i].stub = WorkerService::NewStub(
        CreateChannel(workers[i], InsecureChannelCredentials()));
    ServerArgs args;
    result_server_config = server_config;
    *args.mutable_setup() = server_config;
    servers[i].stream =
        servers[i].stub->RunServer(runsc::AllocContext(&contexts, deadline));
    GPR_ASSERT(servers[i].stream->Write(args));
    ServerStatus init_status;
    GPR_ASSERT(servers[i].stream->Read(&init_status));
    char* host;
    char* driver_port;
    char* cli_target;
    gpr_split_host_port(workers[i].c_str(), &host, &driver_port);
    gpr_join_host_port(&cli_target, host, init_status.port());
    client_config.add_server_targets(cli_target);
    gpr_free(host);
    gpr_free(driver_port);
    gpr_free(cli_target);
  }

  // Start clients
  using runsc::ClientData;
  // clients is array rather than std::vector to avoid gcc-4.4 issues
  // where class contained in std::vector must have a copy constructor
  auto* clients = new ClientData[num_clients];
  for (size_t i = 0; i < num_clients; i++) {
    gpr_log(GPR_INFO, "Starting client on %s (worker #%d)",
            workers[i].c_str(), i);
    clients[i].stub = WorkerService::NewStub(
        CreateChannel(workers[i + num_servers], InsecureChannelCredentials()));
    ClientArgs args;
    result_client_config = client_config;
    *args.mutable_setup() = client_config;
    clients[i].stream =
        clients[i].stub->RunClient(runsc::AllocContext(&contexts, deadline));
    GPR_ASSERT(clients[i].stream->Write(args));
    ClientStatus init_status;
    GPR_ASSERT(clients[i].stream->Read(&init_status));
  }

  // Let everything warmup
  gpr_log(GPR_INFO, "Warming up");
  gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
  gpr_sleep_until(
      gpr_time_add(start, gpr_time_from_seconds(warmup_seconds, GPR_TIMESPAN)));

  // Start a run
  gpr_log(GPR_INFO, "Starting");
  ServerArgs server_mark;
  server_mark.mutable_mark()->set_reset(true);
  ClientArgs client_mark;
  client_mark.mutable_mark()->set_reset(true);
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->Write(server_mark));
  }
  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->Write(client_mark));
  }
  ServerStatus server_status;
  ClientStatus client_status;
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->Read(&server_status));
  }
  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->Read(&client_status));
  }

  // Wait some time
  gpr_log(GPR_INFO, "Running");
  // Use gpr_sleep_until rather than this_thread::sleep_until to support
  // compilers that don't work with this_thread
  gpr_sleep_until(gpr_time_add(
      start, gpr_time_from_seconds(benchmark_seconds, GPR_TIMESPAN)));

  // Finish a run
  std::unique_ptr<ScenarioResult> result(new ScenarioResult);
  result->client_config = result_client_config;
  result->server_config = result_server_config;
  gpr_log(GPR_INFO, "Finishing");
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->Write(server_mark));
  }
  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->Write(client_mark));
  }
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->Read(&server_status));
    const auto& stats = server_status.stats();
    result->server_resources.emplace_back(
        stats.time_elapsed(), stats.time_user(), stats.time_system(),
        server_status.cores());
  }
  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->Read(&client_status));
    const auto& stats = client_status.stats();
    result->latencies.MergeProto(stats.latencies());
    result->client_resources.emplace_back(
        stats.time_elapsed(), stats.time_user(), stats.time_system(), -1);
  }

  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->WritesDone());
    GPR_ASSERT(client->stream->Finish().ok());
  }
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->WritesDone());
    GPR_ASSERT(server->stream->Finish().ok());
  }
  delete[] clients;
  delete[] servers;
  return result;
}
}  // namespace testing
}  // namespace grpc
<commit_msg>Properly state client name<commit_after>/*
 *
 * Copyright 2015, 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.
 *
 */

#include <list>
#include <thread>
#include <deque>
#include <vector>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/host_port.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>

#include "src/core/support/env.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/qps/driver.h"
#include "test/cpp/qps/histogram.h"
#include "test/cpp/qps/qps_worker.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"

using std::list;
using std::thread;
using std::unique_ptr;
using std::deque;
using std::vector;

namespace grpc {
namespace testing {
static deque<string> get_hosts(const string& name) {
  char* env = gpr_getenv(name.c_str());
  if (!env) return deque<string>();

  deque<string> out;
  char* p = env;
  for (;;) {
    char* comma = strchr(p, ',');
    if (comma) {
      out.emplace_back(p, comma);
      p = comma + 1;
    } else {
      out.emplace_back(p);
      gpr_free(env);
      return out;
    }
  }
}

// Namespace for classes and functions used only in RunScenario
// Using this rather than local definitions to workaround gcc-4.4 limitations
// regarding using templates without linkage
namespace runsc {

// ClientContext allocator
template <class T>
static ClientContext* AllocContext(list<ClientContext>* contexts, T deadline) {
  contexts->emplace_back();
  auto context = &contexts->back();
  context->set_deadline(deadline);
  return context;
}

struct ServerData {
  unique_ptr<WorkerService::Stub> stub;
  unique_ptr<ClientReaderWriter<ServerArgs, ServerStatus>> stream;
};

struct ClientData {
  unique_ptr<WorkerService::Stub> stub;
  unique_ptr<ClientReaderWriter<ClientArgs, ClientStatus>> stream;
};
}  // namespace runsc

std::unique_ptr<ScenarioResult> RunScenario(
    const ClientConfig& initial_client_config, size_t num_clients,
    const ServerConfig& server_config, size_t num_servers, int warmup_seconds,
    int benchmark_seconds, int spawn_local_worker_count) {
  // ClientContext allocations (all are destroyed at scope exit)
  list<ClientContext> contexts;

  // To be added to the result, containing the final configuration used for
  // client and config (including host, etc.)
  ClientConfig result_client_config;
  ServerConfig result_server_config;

  // Get client, server lists
  auto workers = get_hosts("QPS_WORKERS");
  ClientConfig client_config = initial_client_config;

  // Spawn some local workers if desired
  vector<unique_ptr<QpsWorker>> local_workers;
  for (int i = 0; i < abs(spawn_local_worker_count); i++) {
    // act as if we're a new test -- gets a good rng seed
    static bool called_init = false;
    if (!called_init) {
      char args_buf[100];
      strcpy(args_buf, "some-benchmark");
      char* args[] = {args_buf};
      grpc_test_init(1, args);
      called_init = true;
    }

    int driver_port = grpc_pick_unused_port_or_die();
    local_workers.emplace_back(new QpsWorker(driver_port));
    char addr[256];
    sprintf(addr, "localhost:%d", driver_port);
    if (spawn_local_worker_count < 0) {
      workers.push_front(addr);
    } else {
      workers.push_back(addr);
    }
  }

  // TODO(ctiller): support running multiple configurations, and binpack
  // client/server pairs
  // to available workers
  GPR_ASSERT(workers.size() >= num_clients + num_servers);

  // Trim to just what we need
  workers.resize(num_clients + num_servers);

  gpr_timespec deadline =
      gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
                   gpr_time_from_seconds(
                       warmup_seconds + benchmark_seconds + 20, GPR_TIMESPAN));

  // Start servers
  using runsc::ServerData;
  // servers is array rather than std::vector to avoid gcc-4.4 issues
  // where class contained in std::vector must have a copy constructor
  auto* servers = new ServerData[num_servers];
  for (size_t i = 0; i < num_servers; i++) {
    gpr_log(GPR_INFO, "Starting server on %s (worker #%d)",
            workers[i].c_str(), i);
    servers[i].stub = WorkerService::NewStub(
        CreateChannel(workers[i], InsecureChannelCredentials()));
    ServerArgs args;
    result_server_config = server_config;
    *args.mutable_setup() = server_config;
    servers[i].stream =
        servers[i].stub->RunServer(runsc::AllocContext(&contexts, deadline));
    GPR_ASSERT(servers[i].stream->Write(args));
    ServerStatus init_status;
    GPR_ASSERT(servers[i].stream->Read(&init_status));
    char* host;
    char* driver_port;
    char* cli_target;
    gpr_split_host_port(workers[i].c_str(), &host, &driver_port);
    gpr_join_host_port(&cli_target, host, init_status.port());
    client_config.add_server_targets(cli_target);
    gpr_free(host);
    gpr_free(driver_port);
    gpr_free(cli_target);
  }

  // Start clients
  using runsc::ClientData;
  // clients is array rather than std::vector to avoid gcc-4.4 issues
  // where class contained in std::vector must have a copy constructor
  auto* clients = new ClientData[num_clients];
  for (size_t i = 0; i < num_clients; i++) {
    gpr_log(GPR_INFO, "Starting client on %s (worker #%d)",
            workers[i + num_servers].c_str(), i + num_servers);
    clients[i].stub = WorkerService::NewStub(
        CreateChannel(workers[i + num_servers], InsecureChannelCredentials()));
    ClientArgs args;
    result_client_config = client_config;
    *args.mutable_setup() = client_config;
    clients[i].stream =
        clients[i].stub->RunClient(runsc::AllocContext(&contexts, deadline));
    GPR_ASSERT(clients[i].stream->Write(args));
    ClientStatus init_status;
    GPR_ASSERT(clients[i].stream->Read(&init_status));
  }

  // Let everything warmup
  gpr_log(GPR_INFO, "Warming up");
  gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
  gpr_sleep_until(
      gpr_time_add(start, gpr_time_from_seconds(warmup_seconds, GPR_TIMESPAN)));

  // Start a run
  gpr_log(GPR_INFO, "Starting");
  ServerArgs server_mark;
  server_mark.mutable_mark()->set_reset(true);
  ClientArgs client_mark;
  client_mark.mutable_mark()->set_reset(true);
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->Write(server_mark));
  }
  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->Write(client_mark));
  }
  ServerStatus server_status;
  ClientStatus client_status;
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->Read(&server_status));
  }
  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->Read(&client_status));
  }

  // Wait some time
  gpr_log(GPR_INFO, "Running");
  // Use gpr_sleep_until rather than this_thread::sleep_until to support
  // compilers that don't work with this_thread
  gpr_sleep_until(gpr_time_add(
      start, gpr_time_from_seconds(benchmark_seconds, GPR_TIMESPAN)));

  // Finish a run
  std::unique_ptr<ScenarioResult> result(new ScenarioResult);
  result->client_config = result_client_config;
  result->server_config = result_server_config;
  gpr_log(GPR_INFO, "Finishing");
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->Write(server_mark));
  }
  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->Write(client_mark));
  }
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->Read(&server_status));
    const auto& stats = server_status.stats();
    result->server_resources.emplace_back(
        stats.time_elapsed(), stats.time_user(), stats.time_system(),
        server_status.cores());
  }
  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->Read(&client_status));
    const auto& stats = client_status.stats();
    result->latencies.MergeProto(stats.latencies());
    result->client_resources.emplace_back(
        stats.time_elapsed(), stats.time_user(), stats.time_system(), -1);
  }

  for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
    GPR_ASSERT(client->stream->WritesDone());
    GPR_ASSERT(client->stream->Finish().ok());
  }
  for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
    GPR_ASSERT(server->stream->WritesDone());
    GPR_ASSERT(server->stream->Finish().ok());
  }
  delete[] clients;
  delete[] servers;
  return result;
}
}  // namespace testing
}  // namespace grpc
<|endoftext|>


<commit_before>
#ifndef DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_MULTISCALE_HH
#define DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_MULTISCALE_HH

// system
#include <sstream>
#include <vector>

// dune-common
#include <dune/common/exceptions.hh>
#include <dune/common/shared_ptr.hh>

// dune-grid
#include <dune/grid/io/file/vtk/function.hh>

// dune-grid-multiscale
#include <dune/grid/multiscale/default.hh>

// dune-detailed-discretizations
#include <dune/detailed/discretizations/discretefunction/default.hh>

namespace Dune {

namespace Detailed {

namespace Discretizations {

namespace DiscreteFunction {

template <class MsGridImp, class LocalDiscreteFunctionImp>
class Multiscale;

template <class GridImp, class LocalDiscreteFunctionSpaceImp, class LocalVectorBackendImp>
class Multiscale<Dune::grid::Multiscale::Default<GridImp>,
                 Dune::Detailed::Discretizations::DiscreteFunction::Default<LocalDiscreteFunctionSpaceImp,
                                                                            LocalVectorBackendImp>>
    : public Dune::VTKFunction<typename Dune::grid::Multiscale::Default<GridImp>::GlobalGridViewType>
{
public:
  typedef Multiscale<Dune::grid::Multiscale::Default<GridImp>,
                     Dune::Detailed::Discretizations::DiscreteFunction::Default<LocalDiscreteFunctionSpaceImp,
                                                                                LocalVectorBackendImp>> ThisType;

  typedef Dune::grid::Multiscale::Default<GridImp> MsGridType;

  typedef typename MsGridType::GlobalGridViewType GlobalGridViewType;

  typedef Dune::Detailed::Discretizations::DiscreteFunction::Default<LocalDiscreteFunctionSpaceImp,
                                                                     LocalVectorBackendImp> LocalDiscreteFunctionType;

  typedef typename Dune::VTKFunction<GlobalGridViewType> BaseType;

  typedef typename GlobalGridViewType::template Codim<0>::Iterator::Entity EntityType;

  typedef typename LocalDiscreteFunctionType::DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;

  typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;

  typedef typename FunctionSpaceType::DomainType DomainType;

  typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;

  typedef typename FunctionSpaceType::RangeType RangeType;

  typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;

  static const int dimDomain = LocalDiscreteFunctionType::dimDomain;

  static const int dimRange = LocalDiscreteFunctionType::dimRange;

  static const std::string id;

private:
  typedef typename MsGridType::EntityToSubdomainMapType EntityToSubdomainMapType;

public:
  Multiscale(const MsGridType& msGrid,
             const std::vector<Dune::shared_ptr<LocalDiscreteFunctionType>>& localDiscreteFunctions,
             const std::string name = id)
    : msGrid_(msGrid)
    , entityToSubdomainMap_(msGrid_.entityToSubdomainMap())
    , localDiscreteFunctions_(localDiscreteFunctions)
    , name_(name)
  {
    assert(localDiscreteFunctions_.size() == msGrid_.size());
  }

  Dune::shared_ptr<const LocalDiscreteFunctionType> localDiscreteFunction(const unsigned int subdomain) const
  {
    assert(subdomain < msGrid_.size());
    return localDiscreteFunctions_[subdomain];
  }

  Dune::shared_ptr<LocalDiscreteFunctionType> localDiscreteFunction(const unsigned int subdomain)
  {
    assert(subdomain < msGrid_.size());
    return localDiscreteFunctions_[subdomain];
  }

  virtual std::string name() const
  {
    return name_;
  }

  void setName(const std::string& newName = "")
  {
    name_ = newName;
  }

  /**
      @name Methods to comply with the Dune::VTKFunction interface
      @{
   **/
  virtual int ncomps() const
  {
    return dimRange;
  }

  virtual RangeFieldType evaluate(const int component, const EntityType& entity, const DomainType& x) const
  {
    // get the subdomain of this entity
    const unsigned int globalIndex                                 = msGrid_.globalGridView()->indexSet().index(entity);
    const typename EntityToSubdomainMapType::const_iterator result = entityToSubdomainMap_->find(globalIndex);
    if (result == entityToSubdomainMap_->end()) {
      std::stringstream msg;
      msg << "Error in " << id << ": Entity " << globalIndex << " not found in the multiscale grid!";
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
    const unsigned int subdomain = result->second;
    assert(subdomain < msGrid_.size());
    // get and call the local discrete function of the entity's subdomain
    const LocalDiscreteFunctionType& localDiscreteFunction = *(localDiscreteFunctions_[subdomain]);
    return localDiscreteFunction.evaluate(component, entity, x);
  } // virtual RangeFieldType evaluate(const int component, const EntityType& entity, const DomainType& x) const
  /**
      @}
     **/

private:
  const MsGridType& msGrid_;
  const Dune::shared_ptr<const EntityToSubdomainMapType> entityToSubdomainMap_;
  std::vector<Dune::shared_ptr<LocalDiscreteFunctionType>> localDiscreteFunctions_;
  std::string name_;
}; // class Multiscale

template <class GridType, class LocalDiscreteFunctionSpaceType, class LocalVectorBackendType>
const std::string Multiscale<Dune::grid::Multiscale::Default<GridType>,
                             Dune::Detailed::Discretizations::DiscreteFunction::Default<LocalDiscreteFunctionSpaceType,
                                                                                LocalVectorBackendType>>::id =
    "detailed.discretizations.discretefunction.multiscale";

} // namespace DiscreteFunction

} // namespace Discretizations

} // namespace Detailed

} // namespace Dune

#endif // DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_MULTISCALE_HH
<commit_msg>[discretefunction.multiscale] added localFuntion()<commit_after>
#ifndef DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_MULTISCALE_HH
#define DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_MULTISCALE_HH

// system
#include <sstream>
#include <vector>

// dune-common
#include <dune/common/exceptions.hh>
#include <dune/common/shared_ptr.hh>

// dune-grid
#include <dune/grid/io/file/vtk/function.hh>

// dune-grid-multiscale
#include <dune/grid/multiscale/default.hh>

// dune-detailed-discretizations
#include <dune/detailed/discretizations/discretefunction/default.hh>

namespace Dune {

namespace Detailed {

namespace Discretizations {

namespace DiscreteFunction {

template <class MsGridImp, class LocalDiscreteFunctionImp>
class Multiscale;

template <class GridImp, class LocalDiscreteFunctionSpaceImp, class LocalVectorBackendImp>
class Multiscale<Dune::grid::Multiscale::Default<GridImp>,
                 Dune::Detailed::Discretizations::DiscreteFunction::Default<LocalDiscreteFunctionSpaceImp,
                                                                            LocalVectorBackendImp>>
    : public Dune::VTKFunction<typename Dune::grid::Multiscale::Default<GridImp>::GlobalGridViewType>
{
public:
  typedef Multiscale<Dune::grid::Multiscale::Default<GridImp>,
                     Dune::Detailed::Discretizations::DiscreteFunction::Default<LocalDiscreteFunctionSpaceImp,
                                                                                LocalVectorBackendImp>> ThisType;

  typedef Dune::grid::Multiscale::Default<GridImp> MsGridType;

  typedef typename MsGridType::GlobalGridViewType GlobalGridViewType;

  typedef Dune::Detailed::Discretizations::DiscreteFunction::Default<LocalDiscreteFunctionSpaceImp,
                                                                     LocalVectorBackendImp> LocalDiscreteFunctionType;

  typedef typename LocalDiscreteFunctionType::LocalFunctionType LocalFunctionType;

  typedef typename LocalDiscreteFunctionType::ConstLocalFunctionType ConstLocalFunctionType;

  typedef typename Dune::VTKFunction<GlobalGridViewType> BaseType;

  typedef typename GlobalGridViewType::template Codim<0>::Iterator::Entity EntityType;

  typedef typename LocalDiscreteFunctionType::DiscreteFunctionSpaceType::FunctionSpaceType FunctionSpaceType;

  typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;

  typedef typename FunctionSpaceType::DomainType DomainType;

  typedef typename FunctionSpaceType::RangeFieldType RangeFieldType;

  typedef typename FunctionSpaceType::RangeType RangeType;

  typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;

  static const int dimDomain = LocalDiscreteFunctionType::dimDomain;

  static const int dimRange = LocalDiscreteFunctionType::dimRange;

  static const std::string id;

private:
  typedef typename MsGridType::EntityToSubdomainMapType EntityToSubdomainMapType;

public:
  Multiscale(const MsGridType& msGrid,
             const std::vector<Dune::shared_ptr<LocalDiscreteFunctionType>>& localDiscreteFunctions,
             const std::string name = id)
    : msGrid_(msGrid)
    , entityToSubdomainMap_(msGrid_.entityToSubdomainMap())
    , localDiscreteFunctions_(localDiscreteFunctions)
    , name_(name)
  {
    assert(localDiscreteFunctions_.size() == msGrid_.size());
  }

  const MsGridType& msGrid() const
  {
    return msGrid_;
  }

  unsigned int size() const
  {
    return msGrid_.size();
  }

  Dune::shared_ptr<const LocalDiscreteFunctionType> localDiscreteFunction(const unsigned int subdomain) const
  {
    assert(subdomain < msGrid_.size());
    return localDiscreteFunctions_[subdomain];
  }

  Dune::shared_ptr<LocalDiscreteFunctionType> localDiscreteFunction(const unsigned int subdomain)
  {
    assert(subdomain < msGrid_.size());
    return localDiscreteFunctions_[subdomain];
  }

  LocalFunctionType localFunction(const EntityType& entity)
  {
    // get the subdomain of this entity
    const unsigned int globalIndex                                 = msGrid_.globalGridView()->indexSet().index(entity);
    const typename EntityToSubdomainMapType::const_iterator result = entityToSubdomainMap_->find(globalIndex);
    if (result == entityToSubdomainMap_->end()) {
      std::stringstream msg;
      msg << "Error in " << id << ": Entity " << globalIndex << " not found in the multiscale grid!";
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
    const unsigned int subdomain = result->second;
    assert(subdomain < msGrid_.size());
    // get the corresponding local discrete function
    const LocalDiscreteFunctionType& localDiscreteFunction = *(localDiscreteFunctions_[subdomain]);
    // and return its local function
    return localDiscreteFunction.localFunction(entity);
  }

  ConstLocalFunctionType localFunction(const EntityType& entity) const
  {
    // get the subdomain of this entity
    const unsigned int globalIndex                                 = msGrid_.globalGridView()->indexSet().index(entity);
    const typename EntityToSubdomainMapType::const_iterator result = entityToSubdomainMap_->find(globalIndex);
    if (result == entityToSubdomainMap_->end()) {
      std::stringstream msg;
      msg << "Error in " << id << ": Entity " << globalIndex << " not found in the multiscale grid!";
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
    const unsigned int subdomain = result->second;
    assert(subdomain < msGrid_.size());
    // get the corresponding local discrete function
    const LocalDiscreteFunctionType& localDiscreteFunction = *(localDiscreteFunctions_[subdomain]);
    // and return its local function
    return localDiscreteFunction.localFunction(entity);
  }

  virtual std::string name() const
  {
    return name_;
  }

  void setName(const std::string& newName = "")
  {
    name_ = newName;
  }

  /**
      @name Methods needed, to comply with the Dune::VTKFunction interface
      @{
    */
  virtual int ncomps() const
  {
    return dimRange;
  }

  virtual RangeFieldType evaluate(const int component, const EntityType& entity, const DomainType& x) const
  {
    // get the subdomain of this entity
    const unsigned int globalIndex                                 = msGrid_.globalGridView()->indexSet().index(entity);
    const typename EntityToSubdomainMapType::const_iterator result = entityToSubdomainMap_->find(globalIndex);
    if (result == entityToSubdomainMap_->end()) {
      std::stringstream msg;
      msg << "Error in " << id << ": Entity " << globalIndex << " not found in the multiscale grid!";
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
    const unsigned int subdomain = result->second;
    assert(subdomain < msGrid_.size());
    // get and call the local discrete function of the entity's subdomain
    const LocalDiscreteFunctionType& localDiscreteFunction = *(localDiscreteFunctions_[subdomain]);
    return localDiscreteFunction.evaluate(component, entity, x);
  } // virtual RangeFieldType evaluate(const int component, const EntityType& entity, const DomainType& x) const
  /**
      @}
    */

private:
  const MsGridType& msGrid_;
  const Dune::shared_ptr<const EntityToSubdomainMapType> entityToSubdomainMap_;
  std::vector<Dune::shared_ptr<LocalDiscreteFunctionType>> localDiscreteFunctions_;
  std::string name_;
}; // class Multiscale

template <class GridType, class LocalDiscreteFunctionSpaceType, class LocalVectorBackendType>
const std::string Multiscale<Dune::grid::Multiscale::Default<GridType>,
                             Dune::Detailed::Discretizations::DiscreteFunction::Default<LocalDiscreteFunctionSpaceType,
                                                                                LocalVectorBackendType>>::id =
    "detailed.discretizations.discretefunction.multiscale";

} // namespace DiscreteFunction

} // namespace Discretizations

} // namespace Detailed

} // namespace Dune

#endif // DUNE_DETAILED_DISCRETIZATIONS_DISCRETEFUNCTION_MULTISCALE_HH
<|endoftext|>


<commit_before>#include <QtCore/QEventLoop>
#include <QtTest/QtTest>

#include <TelepathyQt4/Debug>
#include <TelepathyQt4/Types>
#include <TelepathyQt4/Account>
#include <TelepathyQt4/AccountManager>
#include <TelepathyQt4/AccountSet>
#include <TelepathyQt4/ConnectionManager>
#include <TelepathyQt4/PendingAccount>
#include <TelepathyQt4/PendingOperation>
#include <TelepathyQt4/PendingReady>

#include <tests/lib/test.h>

using namespace Tp;

class TestAccountBasics : public Test
{
    Q_OBJECT

public:
    TestAccountBasics(QObject *parent = 0)
        : Test(parent), mServiceNameChanged(false), mAccountsCount(0), mGotAvatarChanged(false)
    { }

protected Q_SLOTS:
    void onNewAccount(const Tp::AccountPtr &);
    void onAccountServiceNameChanged(const QString &);
    void onAvatarChanged(const Tp::Avatar &);

private Q_SLOTS:
    void initTestCase();
    void init();

    void testBasics();

    void cleanup();
    void cleanupTestCase();

private:
    QStringList pathsForAccountList(const QList<Tp::AccountPtr> &list);
    QStringList pathsForAccountSet(const Tp::AccountSetPtr &set);

    Tp::AccountManagerPtr mAM;
    bool mServiceNameChanged;
    QString mServiceName;
    int mAccountsCount;
    bool mGotAvatarChanged;
};

void TestAccountBasics::onNewAccount(const Tp::AccountPtr &acc)
{
    Q_UNUSED(acc);

    mAccountsCount++;
    mLoop->exit(0);
}

void TestAccountBasics::onAccountServiceNameChanged(const QString &serviceName)
{
    mServiceNameChanged = true;
    mServiceName = serviceName;
    mLoop->exit(0);
}

void TestAccountBasics::onAvatarChanged(const Tp::Avatar &avatar)
{
    qDebug() << "on avatar changed";
    mGotAvatarChanged = true;
    QCOMPARE(avatar.avatarData, QByteArray("asdfg"));
    QCOMPARE(avatar.MIMEType, QString(QLatin1String("image/jpeg")));
    mLoop->exit(0);
}

QStringList TestAccountBasics::pathsForAccountList(const QList<Tp::AccountPtr> &list)
{
    QStringList ret;
    Q_FOREACH (const AccountPtr &account, list) {
        ret << account->objectPath();
    }
    return ret;
}

QStringList TestAccountBasics::pathsForAccountSet(const Tp::AccountSetPtr &set)
{
    QStringList ret;
    Q_FOREACH (const AccountPtr &account, set->accounts()) {
        ret << account->objectPath();
    }
    return ret;
}

void TestAccountBasics::initTestCase()
{
    initTestCaseImpl();

    mAM = AccountManager::create();
    QCOMPARE(mAM->isReady(), false);
}

void TestAccountBasics::init()
{
    mGotAvatarChanged = false;

    initImpl();
}

void TestAccountBasics::testBasics()
{
    QVERIFY(connect(mAM->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(mAM->isReady(), true);

    QVERIFY(connect(mAM.data(),
                    SIGNAL(newAccount(const Tp::AccountPtr &)),
                    SLOT(onNewAccount(const Tp::AccountPtr &))));

    QVariantMap parameters;
    parameters[QLatin1String("account")] = QLatin1String("foobar");
    PendingAccount *pacc = mAM->createAccount(QLatin1String("foo"),
            QLatin1String("bar"), QLatin1String("foobar"), parameters);
    QVERIFY(connect(pacc,
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QVERIFY(pacc->account());

    while (mAccountsCount != 1) {
        QCOMPARE(mLoop->exec(), 0);
    }

    QCOMPARE(mAM->interfaces(), QStringList());

    QStringList paths;
    QCOMPARE(pathsForAccountSet(mAM->validAccountsSet()),
            QStringList() <<
            QLatin1String("/org/freedesktop/Telepathy/Account/foo/bar/Account0"));
    QCOMPARE(pathsForAccountSet(mAM->invalidAccountsSet()),
            QStringList());
    QCOMPARE(pathsForAccountList(mAM->allAccounts()),
            QStringList() <<
            QLatin1String("/org/freedesktop/Telepathy/Account/foo/bar/Account0"));

    AccountPtr acc = Account::create(mAM->dbusConnection(), mAM->busName(),
            QLatin1String("/org/freedesktop/Telepathy/Account/foo/bar/Account0"));
    QVERIFY(connect(acc->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    QCOMPARE(acc->displayName(), QString(QLatin1String("foobar (account 0)")));

    qDebug() << "making Account::FeatureAvatar ready";

    QVERIFY(connect(acc->becomeReady(Account::FeatureAvatar),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureAvatar), true);

    QCOMPARE(acc->avatar().MIMEType, QString(QLatin1String("image/png")));

    qDebug() << "connecting to avatarChanged()";

    QVERIFY(connect(acc.data(),
                    SIGNAL(avatarChanged(const Tp::Avatar &)),
                    SLOT(onAvatarChanged(const Tp::Avatar &))));

    qDebug() << "setting the avatar";

    Tp::Avatar avatar = { QByteArray("asdfg"), QLatin1String("image/jpeg") };
    QVERIFY(connect(acc->setAvatar(avatar),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    qDebug() << "making Account::FeatureAvatar ready again (redundantly)";

    QVERIFY(connect(acc->becomeReady(Account::FeatureAvatar),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureAvatar), true);

    // We might have got it already in the earlier mainloop runs
    if (!mGotAvatarChanged) {
        qDebug() << "waiting for the avatarChanged signal";
        QCOMPARE(mLoop->exec(), 0);
    } else {
        qDebug() << "not waiting for avatarChanged because we already got it";
    }

    qDebug() << "creating another account";

    pacc = mAM->createAccount(QLatin1String("spurious"),
            QLatin1String("normal"), QLatin1String("foobar"), parameters);
    QVERIFY(connect(pacc,
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    while (mAccountsCount != 2) {
        QCOMPARE(mLoop->exec(), 0);
    }

    acc = Account::create(mAM->dbusConnection(), mAM->busName(),
            QLatin1String("/org/freedesktop/Telepathy/Account/spurious/normal/Account0"));
    QVERIFY(connect(acc->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    acc = Account::create(mAM->dbusConnection(), mAM->busName(),
            QLatin1String("/org/freedesktop/Telepathy/Account/spurious/normal/Account0"));

    QVERIFY(connect(acc->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    // At this point, there's a set icon
    QCOMPARE(acc->iconName(), QLatin1String("bob.png")); // ?!??

    // Unset that
    QVERIFY(connect(acc->setIconName(QString()),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    // Now that it's unset, an icon name is formed from the protocol name
    QCOMPARE(acc->iconName(), QLatin1String("im-normal"));

    QVERIFY(connect(acc->becomeReady(Account::FeatureProtocolInfo),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureProtocolInfo), true);

    // This time it's fetched from the protocol object (although it probably internally just
    // infers it from the protocol name too)
    QCOMPARE(acc->iconName(), QLatin1String("im-normal"));

    QVERIFY(acc->serviceName() != acc->protocolName());
    QCOMPARE(acc->serviceName(), QString(QLatin1String("bob_service")));
    connect(acc.data(),
            SIGNAL(serviceNameChanged(const QString &)),
            SLOT(onAccountServiceNameChanged(const QString &)));
    connect(acc->setServiceName(acc->protocolName()),
            SIGNAL(finished(Tp::PendingOperation *)),
            SLOT(expectSuccessfulCall(Tp::PendingOperation *)));
    // wait for setServiceName finish
    QCOMPARE(mLoop->exec(), 0);
    // wait for serviceNameChanged
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->serviceName(), acc->protocolName());
    QCOMPARE(mServiceName, acc->serviceName());

    ProtocolInfo *protocolInfo = acc->protocolInfo();
    QCOMPARE((bool) protocolInfo, !((ProtocolInfo *) 0));
    QCOMPARE(protocolInfo->hasParameter(QLatin1String("account")), true);
    QCOMPARE(protocolInfo->hasParameter(QLatin1String("password")), true);
    QCOMPARE(protocolInfo->hasParameter(QLatin1String("register")), true);

    QVERIFY(connect(acc->becomeReady(Account::FeatureAvatar),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureAvatar), true);

    QCOMPARE(acc->avatar().MIMEType, QString(QLatin1String("image/png")));

    QVERIFY(connect(acc->becomeReady(Account::FeatureAvatar | Account::FeatureProtocolInfo),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureAvatar | Account::FeatureProtocolInfo), true);

    QCOMPARE(acc->avatar().MIMEType, QString(QLatin1String("image/png")));
    protocolInfo = acc->protocolInfo();
    QCOMPARE((bool) protocolInfo, !((ProtocolInfo *) 0));

    QList<AccountPtr> allAccounts = mAM->allAccounts();

    QVariantMap filter;
    Tp::AccountSetPtr filteredAccountSet;

    filter.insert(QLatin1String("protocolName"), QLatin1String("foo"));
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), true);

    filter.clear();
    filter.insert(QLatin1String("protocolFoo"), acc->protocolName());
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), false);

    filter.clear();
    filter.insert(QLatin1String("protocolName"), allAccounts.first()->protocolName());
    filteredAccountSet = mAM->filterAccounts(filter);
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QVERIFY(filteredAccountSet->accounts().contains(allAccounts.first()));

    filteredAccountSet = mAM->accountsByProtocol(allAccounts.first()->protocolName());
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QVERIFY(filteredAccountSet->accounts().contains(allAccounts.first()));

    filter.clear();
    filter.insert(QLatin1String("protocolFoo"), acc->protocolName());
    filteredAccountSet = mAM->filterAccounts(filter);
    QCOMPARE(filteredAccountSet->isFilterValid(), false);
    QVERIFY(filteredAccountSet->accounts().isEmpty());

    QCOMPARE(mAM->validAccountsSet()->isFilterValid(), true);
    QCOMPARE(mAM->validAccountsSet()->accounts().isEmpty(), false);
    QCOMPARE(mAM->invalidAccountsSet()->isFilterValid(), true);
    QCOMPARE(mAM->invalidAccountsSet()->accounts().isEmpty(), true);
    QCOMPARE(mAM->enabledAccountsSet()->isFilterValid(), true);
    QCOMPARE(mAM->enabledAccountsSet()->accounts().isEmpty(), false);
    QCOMPARE(mAM->disabledAccountsSet()->isFilterValid(), true);
    QCOMPARE(mAM->disabledAccountsSet()->accounts().isEmpty(), true);
}

void TestAccountBasics::cleanup()
{
    cleanupImpl();
}

void TestAccountBasics::cleanupTestCase()
{
    cleanupTestCaseImpl();
}

QTEST_MAIN(TestAccountBasics)
#include "_gen/account-basics.cpp.moc.hpp"
<commit_msg>account-basics test: Added tests for filter accounts by RCC support.<commit_after>#include <QtCore/QEventLoop>
#include <QtTest/QtTest>

#include <TelepathyQt4/Debug>
#include <TelepathyQt4/Types>
#include <TelepathyQt4/Account>
#include <TelepathyQt4/AccountManager>
#include <TelepathyQt4/AccountSet>
#include <TelepathyQt4/ConnectionManager>
#include <TelepathyQt4/PendingAccount>
#include <TelepathyQt4/PendingOperation>
#include <TelepathyQt4/PendingReady>

#include <tests/lib/test.h>

using namespace Tp;

class TestAccountBasics : public Test
{
    Q_OBJECT

public:
    TestAccountBasics(QObject *parent = 0)
        : Test(parent), mServiceNameChanged(false), mAccountsCount(0), mGotAvatarChanged(false)
    { }

protected Q_SLOTS:
    void onNewAccount(const Tp::AccountPtr &);
    void onAccountServiceNameChanged(const QString &);
    void onAvatarChanged(const Tp::Avatar &);

private Q_SLOTS:
    void initTestCase();
    void init();

    void testBasics();

    void cleanup();
    void cleanupTestCase();

private:
    QStringList pathsForAccountList(const QList<Tp::AccountPtr> &list);
    QStringList pathsForAccountSet(const Tp::AccountSetPtr &set);

    Tp::AccountManagerPtr mAM;
    bool mServiceNameChanged;
    QString mServiceName;
    int mAccountsCount;
    bool mGotAvatarChanged;
};

void TestAccountBasics::onNewAccount(const Tp::AccountPtr &acc)
{
    Q_UNUSED(acc);

    mAccountsCount++;
    mLoop->exit(0);
}

void TestAccountBasics::onAccountServiceNameChanged(const QString &serviceName)
{
    mServiceNameChanged = true;
    mServiceName = serviceName;
    mLoop->exit(0);
}

void TestAccountBasics::onAvatarChanged(const Tp::Avatar &avatar)
{
    qDebug() << "on avatar changed";
    mGotAvatarChanged = true;
    QCOMPARE(avatar.avatarData, QByteArray("asdfg"));
    QCOMPARE(avatar.MIMEType, QString(QLatin1String("image/jpeg")));
    mLoop->exit(0);
}

QStringList TestAccountBasics::pathsForAccountList(const QList<Tp::AccountPtr> &list)
{
    QStringList ret;
    Q_FOREACH (const AccountPtr &account, list) {
        ret << account->objectPath();
    }
    return ret;
}

QStringList TestAccountBasics::pathsForAccountSet(const Tp::AccountSetPtr &set)
{
    QStringList ret;
    Q_FOREACH (const AccountPtr &account, set->accounts()) {
        ret << account->objectPath();
    }
    return ret;
}

void TestAccountBasics::initTestCase()
{
    initTestCaseImpl();

    mAM = AccountManager::create();
    QCOMPARE(mAM->isReady(), false);
}

void TestAccountBasics::init()
{
    mGotAvatarChanged = false;

    initImpl();
}

void TestAccountBasics::testBasics()
{
    QVERIFY(connect(mAM->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(mAM->isReady(), true);

    QVERIFY(connect(mAM.data(),
                    SIGNAL(newAccount(const Tp::AccountPtr &)),
                    SLOT(onNewAccount(const Tp::AccountPtr &))));

    QVariantMap parameters;
    parameters[QLatin1String("account")] = QLatin1String("foobar");
    PendingAccount *pacc = mAM->createAccount(QLatin1String("foo"),
            QLatin1String("bar"), QLatin1String("foobar"), parameters);
    QVERIFY(connect(pacc,
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QVERIFY(pacc->account());

    while (mAccountsCount != 1) {
        QCOMPARE(mLoop->exec(), 0);
    }

    QCOMPARE(mAM->interfaces(), QStringList());

    QStringList paths;
    QCOMPARE(pathsForAccountSet(mAM->validAccountsSet()),
            QStringList() <<
            QLatin1String("/org/freedesktop/Telepathy/Account/foo/bar/Account0"));
    QCOMPARE(pathsForAccountSet(mAM->invalidAccountsSet()),
            QStringList());
    QCOMPARE(pathsForAccountList(mAM->allAccounts()),
            QStringList() <<
            QLatin1String("/org/freedesktop/Telepathy/Account/foo/bar/Account0"));

    AccountPtr acc = Account::create(mAM->dbusConnection(), mAM->busName(),
            QLatin1String("/org/freedesktop/Telepathy/Account/foo/bar/Account0"));
    QVERIFY(connect(acc->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    QCOMPARE(acc->displayName(), QString(QLatin1String("foobar (account 0)")));

    qDebug() << "making Account::FeatureAvatar ready";

    QVERIFY(connect(acc->becomeReady(Account::FeatureAvatar),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureAvatar), true);

    QCOMPARE(acc->avatar().MIMEType, QString(QLatin1String("image/png")));

    qDebug() << "connecting to avatarChanged()";

    QVERIFY(connect(acc.data(),
                    SIGNAL(avatarChanged(const Tp::Avatar &)),
                    SLOT(onAvatarChanged(const Tp::Avatar &))));

    qDebug() << "setting the avatar";

    Tp::Avatar avatar = { QByteArray("asdfg"), QLatin1String("image/jpeg") };
    QVERIFY(connect(acc->setAvatar(avatar),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    qDebug() << "making Account::FeatureAvatar ready again (redundantly)";

    QVERIFY(connect(acc->becomeReady(Account::FeatureAvatar),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureAvatar), true);

    // We might have got it already in the earlier mainloop runs
    if (!mGotAvatarChanged) {
        qDebug() << "waiting for the avatarChanged signal";
        QCOMPARE(mLoop->exec(), 0);
    } else {
        qDebug() << "not waiting for avatarChanged because we already got it";
    }

    qDebug() << "creating another account";

    pacc = mAM->createAccount(QLatin1String("spurious"),
            QLatin1String("normal"), QLatin1String("foobar"), parameters);
    QVERIFY(connect(pacc,
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    while (mAccountsCount != 2) {
        QCOMPARE(mLoop->exec(), 0);
    }

    acc = Account::create(mAM->dbusConnection(), mAM->busName(),
            QLatin1String("/org/freedesktop/Telepathy/Account/spurious/normal/Account0"));
    QVERIFY(connect(acc->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    acc = Account::create(mAM->dbusConnection(), mAM->busName(),
            QLatin1String("/org/freedesktop/Telepathy/Account/spurious/normal/Account0"));

    QVERIFY(connect(acc->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    // At this point, there's a set icon
    QCOMPARE(acc->iconName(), QLatin1String("bob.png")); // ?!??

    // Unset that
    QVERIFY(connect(acc->setIconName(QString()),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);

    // Now that it's unset, an icon name is formed from the protocol name
    QCOMPARE(acc->iconName(), QLatin1String("im-normal"));

    QVERIFY(connect(acc->becomeReady(Account::FeatureProtocolInfo),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureProtocolInfo), true);

    // This time it's fetched from the protocol object (although it probably internally just
    // infers it from the protocol name too)
    QCOMPARE(acc->iconName(), QLatin1String("im-normal"));

    QVERIFY(acc->serviceName() != acc->protocolName());
    QCOMPARE(acc->serviceName(), QString(QLatin1String("bob_service")));
    connect(acc.data(),
            SIGNAL(serviceNameChanged(const QString &)),
            SLOT(onAccountServiceNameChanged(const QString &)));
    connect(acc->setServiceName(acc->protocolName()),
            SIGNAL(finished(Tp::PendingOperation *)),
            SLOT(expectSuccessfulCall(Tp::PendingOperation *)));
    // wait for setServiceName finish
    QCOMPARE(mLoop->exec(), 0);
    // wait for serviceNameChanged
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->serviceName(), acc->protocolName());
    QCOMPARE(mServiceName, acc->serviceName());

    ProtocolInfo *protocolInfo = acc->protocolInfo();
    QCOMPARE((bool) protocolInfo, !((ProtocolInfo *) 0));
    QCOMPARE(protocolInfo->hasParameter(QLatin1String("account")), true);
    QCOMPARE(protocolInfo->hasParameter(QLatin1String("password")), true);
    QCOMPARE(protocolInfo->hasParameter(QLatin1String("register")), true);

    QVERIFY(connect(acc->becomeReady(Account::FeatureAvatar),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureAvatar), true);

    QCOMPARE(acc->avatar().MIMEType, QString(QLatin1String("image/png")));

    QVERIFY(connect(acc->becomeReady(Account::FeatureAvatar | Account::FeatureProtocolInfo),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(expectSuccessfulCall(Tp::PendingOperation *))));
    QCOMPARE(mLoop->exec(), 0);
    QCOMPARE(acc->isReady(Account::FeatureAvatar | Account::FeatureProtocolInfo), true);

    QCOMPARE(acc->avatar().MIMEType, QString(QLatin1String("image/png")));
    protocolInfo = acc->protocolInfo();
    QCOMPARE((bool) protocolInfo, !((ProtocolInfo *) 0));

    QList<AccountPtr> allAccounts = mAM->allAccounts();

    QVariantMap filter;
    Tp::AccountSetPtr filteredAccountSet;

    filter.insert(QLatin1String("protocolName"), QLatin1String("foo"));
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), true);

    filter.clear();
    filter.insert(QLatin1String("protocolFoo"), acc->protocolName());
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), false);

    filter.clear();
    filter.insert(QLatin1String("protocolName"), allAccounts.first()->protocolName());
    filteredAccountSet = mAM->filterAccounts(filter);
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QVERIFY(filteredAccountSet->accounts().contains(allAccounts.first()));

    filteredAccountSet = mAM->accountsByProtocol(allAccounts.first()->protocolName());
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QVERIFY(filteredAccountSet->accounts().contains(allAccounts.first()));

    filter.clear();
    filter.insert(QLatin1String("protocolFoo"), acc->protocolName());
    filteredAccountSet = mAM->filterAccounts(filter);
    QCOMPARE(filteredAccountSet->isFilterValid(), false);
    QVERIFY(filteredAccountSet->accounts().isEmpty());

    QCOMPARE(mAM->validAccountsSet()->isFilterValid(), true);
    QCOMPARE(mAM->validAccountsSet()->accounts().isEmpty(), false);
    QCOMPARE(mAM->invalidAccountsSet()->isFilterValid(), true);
    QCOMPARE(mAM->invalidAccountsSet()->accounts().isEmpty(), true);
    QCOMPARE(mAM->enabledAccountsSet()->isFilterValid(), true);
    QCOMPARE(mAM->enabledAccountsSet()->accounts().isEmpty(), false);
    QCOMPARE(mAM->disabledAccountsSet()->isFilterValid(), true);
    QCOMPARE(mAM->disabledAccountsSet()->accounts().isEmpty(), true);

    filter.clear();
    filter.insert(QLatin1String("cmName"), QLatin1String("spurious"));
    AccountSetPtr spuriousAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(spuriousAccountSet->isFilterValid(), true);

    /* match fixedProperties is complete and allowedProperties is a subset of
     * the allowed properties */
    filter.clear();
    RequestableChannelClassList rccs;
    RequestableChannelClass rcc;
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT));
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
            (uint) HandleTypeContact);
    rcc.allowedProperties.append(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle"));
    rccs.append(rcc);
    filter.insert(QLatin1String("rccSubset"), qVariantFromValue(rccs));
    filter.insert(QLatin1String("cmName"), QLatin1String("spurious"));
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QCOMPARE(filteredAccountSet->accounts(), spuriousAccountSet->accounts());

    /* match fixedProperties and allowedProperties is complete */
    filter.clear();
    rccs.clear();
    rcc.fixedProperties.clear();
    rcc.allowedProperties.clear();
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT));
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
            (uint) HandleTypeContact);
    rcc.allowedProperties.append(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle"));
    rcc.allowedProperties.append(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetID"));
    rccs.append(rcc);
    filter.insert(QLatin1String("rccSubset"), qVariantFromValue(rccs));
    filter.insert(QLatin1String("cmName"), QLatin1String("spurious"));
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QCOMPARE(filteredAccountSet->accounts(), spuriousAccountSet->accounts());

    /* should not match as fixedProperties lack TargetHandleType */
    filter.clear();
    rccs.clear();
    rcc.fixedProperties.clear();
    rcc.allowedProperties.clear();
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT));
    rcc.allowedProperties.append(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle"));
    rccs.append(rcc);
    filter.insert(QLatin1String("rccSubset"), qVariantFromValue(rccs));
    filter.insert(QLatin1String("cmName"), QLatin1String("spurious"));
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QCOMPARE(filteredAccountSet->accounts().isEmpty(), true);

    /* should not match as fixedProperties has more than expected */
    filter.clear();
    rccs.clear();
    rcc.fixedProperties.clear();
    rcc.allowedProperties.clear();
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT));
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
            (uint) HandleTypeContact);
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetID"),
            (uint) HandleTypeContact);
    rcc.allowedProperties.append(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle"));
    rccs.append(rcc);
    filter.insert(QLatin1String("rccSubset"), qVariantFromValue(rccs));
    filter.insert(QLatin1String("cmName"), QLatin1String("spurious"));
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QCOMPARE(filteredAccountSet->accounts().isEmpty(), true);

    /* should not match as allowedProperties has TargetFoo that is not allowed */
    filter.clear();
    rccs.clear();
    rcc.fixedProperties.clear();
    rcc.allowedProperties.clear();
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".ChannelType"),
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL_TYPE_TEXT));
    rcc.fixedProperties.insert(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandleType"),
            (uint) HandleTypeContact);
    rcc.allowedProperties.append(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetHandle"));
    rcc.allowedProperties.append(
            QLatin1String(TELEPATHY_INTERFACE_CHANNEL ".TargetFoo"));
    rccs.append(rcc);
    filter.insert(QLatin1String("rccSubset"), qVariantFromValue(rccs));
    filter.insert(QLatin1String("cmName"), QLatin1String("spurious"));
    filteredAccountSet = AccountSetPtr(new AccountSet(mAM, filter));
    QCOMPARE(filteredAccountSet->isFilterValid(), true);
    QCOMPARE(filteredAccountSet->accounts().isEmpty(), true);
}

void TestAccountBasics::cleanup()
{
    cleanupImpl();
}

void TestAccountBasics::cleanupTestCase()
{
    cleanupTestCaseImpl();
}

QTEST_MAIN(TestAccountBasics)
#include "_gen/account-basics.cpp.moc.hpp"
<|endoftext|>


<commit_before>// @(#)root/rint:$Name$:$Id$
// Author: Rene Brun   17/02/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Rint                                                                 //
//                                                                      //
// Rint is the ROOT Interactive Interface. It allows interactive access //
// to the ROOT system via the CINT C/C++ interpreter.                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TROOT.h"
#include "TClass.h"
#include "TVirtualX.h"
#include "Getline.h"
#include "TStyle.h"
#include "TObjectTable.h"
#include "TClassTable.h"
#include "TStopwatch.h"
#include "TCanvas.h"
#include "TBenchmark.h"
#include "TRint.h"
#include "TSystem.h"
#include "TEnv.h"
#include "TSysEvtHandler.h"
#include "TError.h"
#include "TException.h"
#include "TInterpreter.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TFile.h"
#include "TMapFile.h"
#include "TTabCom.h"

#ifdef R__UNIX
#include <signal.h>

extern "C" {
   extern int G__get_security_error();
   extern int G__genericerror(char* msg);
}
#endif

//----- Interrupt signal handler -----------------------------------------------
//______________________________________________________________________________
class TInterruptHandler : public TSignalHandler {
public:
   TInterruptHandler() : TSignalHandler(kSigInterrupt, kFALSE) { }
   Bool_t  Notify();
};

//______________________________________________________________________________
Bool_t TInterruptHandler::Notify()
{
   // TRint interrupt handler.

   if (fDelay) {
      fDelay++;
      return kTRUE;
   }

   // make sure we use the sbrk heap (in case of mapped files)
   gMmallocDesc = 0;
//  go via the interpreter???
//   if (gProof) gProof->Interrupt(TProof::kHardInterrupt);

   if (!G__get_security_error())
      G__genericerror("\n *** Break *** keyboard interrupt");
   else {
      Printf("\n *** Break *** keyboard interrupt");
      if (TROOT::Initialized()) {
         Getlinem(kInit, "Root > ");
         gInterpreter->RewindDictionary();
         Throw(GetSignal());
      }
   }
   return kTRUE;
}

//----- Terminal Input file handler --------------------------------------------
//______________________________________________________________________________
class TTermInputHandler : public TFileHandler {
public:
   TTermInputHandler(int fd) : TFileHandler(fd, 1) { }
   Bool_t Notify();
   Bool_t ReadNotify() { return Notify(); }
};

//______________________________________________________________________________
Bool_t TTermInputHandler::Notify()
{
   gApplication->HandleTermInput();
   return kTRUE;
}

ClassImp(TRint)

//______________________________________________________________________________
TRint::TRint(const char *appClassName, int *argc, char **argv, void *options,
             int numOptions, Bool_t noLogo)
       : TApplication(appClassName, argc, argv, options, numOptions)
{
   // Create an application environment. The TRint environment provides an
   // interface to the WM manager functionality and eventloop via inheritance
   // of TApplication and in addition provides interactive access to
   // the CINT C++ interpreter via the command line.

   fNcmd          = 0;
   fDefaultPrompt = "root [%d] ";
   fInterrupt     = kFALSE;

   gBenchmark = new TBenchmark();

   if (!noLogo)
      PrintLogo();

   // Everybody expects iostream to be available, so load it...
#ifndef WIN32
   ProcessLine("#include <iostream>");
#endif

   // The following libs are also useful to have,
   // make sure they are loaded...
   gROOT->LoadClass("TGeometry",   "Graf3d");
   gROOT->LoadClass("TTree",       "Tree");
   gROOT->LoadClass("TMatrix",     "Matrix");
   gROOT->LoadClass("TMinuit",     "Minuit");
   gROOT->LoadClass("TPostScript", "Postscript");
   gROOT->LoadClass("TCanvas",     "Gpad");
   gROOT->LoadClass("THtml",       "Html");

   // Load user functions
   const char *logon;
   logon = gEnv->GetValue("Rint.Load", (char*)0);
   if (logon) {
      char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
      if (mac)
         ProcessLine(Form(".L %s",logon));
      delete [] mac;
   }

   // Execute logon macro
   logon = gEnv->GetValue("Rint.Logon", (char*)0);
   if (logon && !NoLogOpt()) {
      char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
      if (mac)
         ProcessFile(logon);
      delete [] mac;
   }

   gInterpreter->SaveContext();
   gInterpreter->SaveGlobalsContext();

   // Install interrupt and terminal input handlers
   TInterruptHandler *ih = new TInterruptHandler();
   gSystem->AddSignalHandler(ih);
   SetSignalHandler(ih);

   TTermInputHandler *th = new TTermInputHandler(0);
   gSystem->AddFileHandler(th);

   // Goto into raw terminal input mode
   char defhist[128];
#ifndef R__VMS
   sprintf(defhist, "%s/.root_hist", gSystem->Getenv("HOME"));
#else
   sprintf(defhist, "%s.root_hist", gSystem->Getenv("HOME"));
#endif
   logon = gEnv->GetValue("Rint.History", defhist);
   Gl_histinit((char *)logon);
   Gl_windowchanged();

   // Setup for tab completion
   gTabCom = new TTabCom;
}

//______________________________________________________________________________
TRint::~TRint()
{

}

//______________________________________________________________________________
void TRint::Run(Bool_t retrn)
{
   // Main application eventloop. First process files given on the command
   // line and then go into the main application event loop.

   Getlinem(kInit, GetPrompt());

   // Process shell command line input files
   if (InputFiles()) {
      TObjString *file;
      TIter next(InputFiles());
      RETRY {
         while ((file = (TObjString *)next())) {
            char cmd[256];
            if (file->String().EndsWith(".root")) {
               const char *rfile = (const char*)file->String();
               Printf("\nAttaching file %s...", rfile);
               char *base = StrDup(gSystem->BaseName(rfile));
               char *s = strchr(base, '.'); *s = 0;
               sprintf(cmd, "TFile *%s = TFile::Open(\"%s\")", base, rfile);
               delete [] base;
            } else {
               Printf("\nProcessing %s...", (const char*)file->String());
               sprintf(cmd, ".x %s", (const char*)file->String());
            }
            Getlinem(kCleanUp, 0);
            Gl_histadd(cmd);
            fNcmd++;
            ProcessLine(cmd);
         }
      } ENDTRY;

      if (QuitOpt())
         Terminate(0);

      ClearInputFiles();

      Getlinem(kInit, GetPrompt());
   }

   TApplication::Run(retrn);

   Getlinem(kCleanUp, 0);
}

//______________________________________________________________________________
void TRint::PrintLogo()
{
   // Print the ROOT logo on standard output.

   Int_t iday,imonth,iyear;
   static const char *months[] = {"January","February","March","April","May",
                                  "June","July","August","September","October",
                                  "November","December"};
   const char *root_version = gROOT->GetVersion();
   Int_t idatqq = gROOT->GetVersionDate();
   iday   = idatqq%100;
   imonth = (idatqq/100)%100;
   iyear  = (idatqq/10000);
   char *root_date = Form("%d %s %4d",iday,months[imonth-1],iyear);

   Printf("  *******************************************");
   Printf("  *                                         *");
   Printf("  *        W E L C O M E  to  R O O T       *");
   Printf("  *                                         *");
   Printf("  *   Version%10s %17s   *",root_version,root_date);
// Printf("  *            Development version          *");
   Printf("  *                                         *");
   Printf("  *  You are welcome to visit our Web site  *");
   Printf("  *          http://root.cern.ch            *");
   Printf("  *                                         *");
   Printf("  *******************************************");

#ifdef R__UNIX
   if (!strcmp(gVirtualX->GetName(), "X11TTF"))
      Printf("\nFreeType Engine v1.1 used to render TrueType fonts.");
#endif
#ifdef _REENTRANT
#ifdef R__UNIX
   else
#endif
      printf("\n");
   Printf("Compiled with thread support.");
#endif

   gInterpreter->PrintIntro();

#ifdef R__UNIX
   // Popdown X logo, only if started with -splash option
   for (int i = 0; i < Argc(); i++)
      if (!strcmp(Argv(i), "-splash"))
         kill(getppid(), SIGUSR1);
#endif
}

//______________________________________________________________________________
char *TRint::GetPrompt()
{
   // Get prompt from interpreter. Either "root [n]" or "end with '}'".

   char *s = gInterpreter->GetPrompt();
   if (s[0])
      strcpy(fPrompt, s);
   else
      sprintf(fPrompt, fDefaultPrompt, fNcmd);

   return fPrompt;
}

//______________________________________________________________________________
const char *TRint::SetPrompt(const char *newPrompt)
{
   // Set a new default prompt. It returns the previous prompt.
   // The prompt may contain a %d which will be replaced by the commend
   // number. The default prompt is "root [%d] ". The maximum length of
   // the prompt is 55 characters. To set the prompt in an interactive
   // session do:
   // root [0] ((TRint*)gROOT->GetApplication())->SetPrompt("aap> ")
   // aap>

   const char *op = fDefaultPrompt;

   if (strlen(newPrompt) <= 55)
      fDefaultPrompt = newPrompt;
   else
      Error("SetPrompt", "newPrompt too long (> 55 characters)");

   return op;
}

//______________________________________________________________________________
void TRint::HandleTermInput()
{
   // Handle input coming from terminal.

   static TStopwatch timer;
   char *line;

   if ((line = Getlinem(kOneChar, 0))) {
      if (gROOT->Timer()) timer.Start();

      Gl_histadd(line);

      char *s = line;
      while (s && *s == ' ') s++;     // strip-off leading blanks
      s[strlen(s)-1] = '\0';          // strip also '\n' off
      fInterrupt = kFALSE;

      if (!gInterpreter->GetMore() && strlen(s) != 0) fNcmd++;

      ProcessLine(s);

      if (strstr(s,".reset") != s)
          gInterpreter->EndOfLineAction();

      if (gROOT->Timer()) timer.Print();

      gTabCom->ClearAll();
      Getlinem(kInit, GetPrompt());
   }
}

//______________________________________________________________________________
void TRint::Terminate(int status)
{
   // Terminate the application. Reset the terminal to sane mode and call
   // the logoff macro defined via Rint.Logoff environment variable.

   Getlinem(kCleanUp, 0);

   if (ReturnFromRun()) {
      gSystem->ExitLoop();
   } else {
      //Execute logoff macro
      const char *logoff;
      logoff = gEnv->GetValue("Rint.Logoff", (char*)0);
      if (logoff && !NoLogOpt()) {
         char *mac = gSystem->Which(TROOT::GetMacroPath(), logoff, kReadPermission);
         if (mac)
            ProcessFile(logoff);
         delete [] mac;
      }

      gSystem->Exit(status);
   }
}
<commit_msg>when getting an empty line check for Gl_eof(). If an eof found terminate. This is the case when there is no more input while reading from a pipe of from a file via stdin<commit_after>// @(#)root/rint:$Name:  $:$Id: TRint.cxx,v 1.1.1.1 2000/05/16 17:00:46 rdm Exp $
// Author: Rene Brun   17/02/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Rint                                                                 //
//                                                                      //
// Rint is the ROOT Interactive Interface. It allows interactive access //
// to the ROOT system via the CINT C/C++ interpreter.                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TROOT.h"
#include "TClass.h"
#include "TVirtualX.h"
#include "Getline.h"
#include "TStyle.h"
#include "TObjectTable.h"
#include "TClassTable.h"
#include "TStopwatch.h"
#include "TCanvas.h"
#include "TBenchmark.h"
#include "TRint.h"
#include "TSystem.h"
#include "TEnv.h"
#include "TSysEvtHandler.h"
#include "TError.h"
#include "TException.h"
#include "TInterpreter.h"
#include "TObjArray.h"
#include "TObjString.h"
#include "TFile.h"
#include "TMapFile.h"
#include "TTabCom.h"

#ifdef R__UNIX
#include <signal.h>

extern "C" {
   extern int G__get_security_error();
   extern int G__genericerror(char* msg);
}
#endif

//----- Interrupt signal handler -----------------------------------------------
//______________________________________________________________________________
class TInterruptHandler : public TSignalHandler {
public:
   TInterruptHandler() : TSignalHandler(kSigInterrupt, kFALSE) { }
   Bool_t  Notify();
};

//______________________________________________________________________________
Bool_t TInterruptHandler::Notify()
{
   // TRint interrupt handler.

   if (fDelay) {
      fDelay++;
      return kTRUE;
   }

   // make sure we use the sbrk heap (in case of mapped files)
   gMmallocDesc = 0;
//  go via the interpreter???
//   if (gProof) gProof->Interrupt(TProof::kHardInterrupt);

   if (!G__get_security_error())
      G__genericerror("\n *** Break *** keyboard interrupt");
   else {
      Printf("\n *** Break *** keyboard interrupt");
      if (TROOT::Initialized()) {
         Getlinem(kInit, "Root > ");
         gInterpreter->RewindDictionary();
         Throw(GetSignal());
      }
   }
   return kTRUE;
}

//----- Terminal Input file handler --------------------------------------------
//______________________________________________________________________________
class TTermInputHandler : public TFileHandler {
public:
   TTermInputHandler(int fd) : TFileHandler(fd, 1) { }
   Bool_t Notify();
   Bool_t ReadNotify() { return Notify(); }
};

//______________________________________________________________________________
Bool_t TTermInputHandler::Notify()
{
   gApplication->HandleTermInput();
   return kTRUE;
}

ClassImp(TRint)

//______________________________________________________________________________
TRint::TRint(const char *appClassName, int *argc, char **argv, void *options,
             int numOptions, Bool_t noLogo)
       : TApplication(appClassName, argc, argv, options, numOptions)
{
   // Create an application environment. The TRint environment provides an
   // interface to the WM manager functionality and eventloop via inheritance
   // of TApplication and in addition provides interactive access to
   // the CINT C++ interpreter via the command line.

   fNcmd          = 0;
   fDefaultPrompt = "root [%d] ";
   fInterrupt     = kFALSE;

   gBenchmark = new TBenchmark();

   if (!noLogo)
      PrintLogo();

   // Everybody expects iostream to be available, so load it...
#ifndef WIN32
   ProcessLine("#include <iostream>");
#endif

   // The following libs are also useful to have,
   // make sure they are loaded...
   gROOT->LoadClass("TGeometry",   "Graf3d");
   gROOT->LoadClass("TTree",       "Tree");
   gROOT->LoadClass("TMatrix",     "Matrix");
   gROOT->LoadClass("TMinuit",     "Minuit");
   gROOT->LoadClass("TPostScript", "Postscript");
   gROOT->LoadClass("TCanvas",     "Gpad");
   gROOT->LoadClass("THtml",       "Html");

   // Load user functions
   const char *logon;
   logon = gEnv->GetValue("Rint.Load", (char*)0);
   if (logon) {
      char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
      if (mac)
         ProcessLine(Form(".L %s",logon));
      delete [] mac;
   }

   // Execute logon macro
   logon = gEnv->GetValue("Rint.Logon", (char*)0);
   if (logon && !NoLogOpt()) {
      char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
      if (mac)
         ProcessFile(logon);
      delete [] mac;
   }

   gInterpreter->SaveContext();
   gInterpreter->SaveGlobalsContext();

   // Install interrupt and terminal input handlers
   TInterruptHandler *ih = new TInterruptHandler();
   gSystem->AddSignalHandler(ih);
   SetSignalHandler(ih);

   TTermInputHandler *th = new TTermInputHandler(0);
   gSystem->AddFileHandler(th);

   // Goto into raw terminal input mode
   char defhist[128];
#ifndef R__VMS
   sprintf(defhist, "%s/.root_hist", gSystem->Getenv("HOME"));
#else
   sprintf(defhist, "%s.root_hist", gSystem->Getenv("HOME"));
#endif
   logon = gEnv->GetValue("Rint.History", defhist);
   Gl_histinit((char *)logon);
   Gl_windowchanged();

   // Setup for tab completion
   gTabCom = new TTabCom;
}

//______________________________________________________________________________
TRint::~TRint()
{

}

//______________________________________________________________________________
void TRint::Run(Bool_t retrn)
{
   // Main application eventloop. First process files given on the command
   // line and then go into the main application event loop.

   Getlinem(kInit, GetPrompt());

   // Process shell command line input files
   if (InputFiles()) {
      TObjString *file;
      TIter next(InputFiles());
      RETRY {
         while ((file = (TObjString *)next())) {
            char cmd[256];
            if (file->String().EndsWith(".root")) {
               const char *rfile = (const char*)file->String();
               Printf("\nAttaching file %s...", rfile);
               char *base = StrDup(gSystem->BaseName(rfile));
               char *s = strchr(base, '.'); *s = 0;
               sprintf(cmd, "TFile *%s = TFile::Open(\"%s\")", base, rfile);
               delete [] base;
            } else {
               Printf("\nProcessing %s...", (const char*)file->String());
               sprintf(cmd, ".x %s", (const char*)file->String());
            }
            Getlinem(kCleanUp, 0);
            Gl_histadd(cmd);
            fNcmd++;
            ProcessLine(cmd);
         }
      } ENDTRY;

      if (QuitOpt())
         Terminate(0);

      ClearInputFiles();

      Getlinem(kInit, GetPrompt());
   }

   TApplication::Run(retrn);

   Getlinem(kCleanUp, 0);
}

//______________________________________________________________________________
void TRint::PrintLogo()
{
   // Print the ROOT logo on standard output.

   Int_t iday,imonth,iyear;
   static const char *months[] = {"January","February","March","April","May",
                                  "June","July","August","September","October",
                                  "November","December"};
   const char *root_version = gROOT->GetVersion();
   Int_t idatqq = gROOT->GetVersionDate();
   iday   = idatqq%100;
   imonth = (idatqq/100)%100;
   iyear  = (idatqq/10000);
   char *root_date = Form("%d %s %4d",iday,months[imonth-1],iyear);

   Printf("  *******************************************");
   Printf("  *                                         *");
   Printf("  *        W E L C O M E  to  R O O T       *");
   Printf("  *                                         *");
   Printf("  *   Version%10s %17s   *",root_version,root_date);
// Printf("  *            Development version          *");
   Printf("  *                                         *");
   Printf("  *  You are welcome to visit our Web site  *");
   Printf("  *          http://root.cern.ch            *");
   Printf("  *                                         *");
   Printf("  *******************************************");

#ifdef R__UNIX
   if (!strcmp(gVirtualX->GetName(), "X11TTF"))
      Printf("\nFreeType Engine v1.1 used to render TrueType fonts.");
#endif
#ifdef _REENTRANT
#ifdef R__UNIX
   else
#endif
      printf("\n");
   Printf("Compiled with thread support.");
#endif

   gInterpreter->PrintIntro();

#ifdef R__UNIX
   // Popdown X logo, only if started with -splash option
   for (int i = 0; i < Argc(); i++)
      if (!strcmp(Argv(i), "-splash"))
         kill(getppid(), SIGUSR1);
#endif
}

//______________________________________________________________________________
char *TRint::GetPrompt()
{
   // Get prompt from interpreter. Either "root [n]" or "end with '}'".

   char *s = gInterpreter->GetPrompt();
   if (s[0])
      strcpy(fPrompt, s);
   else
      sprintf(fPrompt, fDefaultPrompt, fNcmd);

   return fPrompt;
}

//______________________________________________________________________________
const char *TRint::SetPrompt(const char *newPrompt)
{
   // Set a new default prompt. It returns the previous prompt.
   // The prompt may contain a %d which will be replaced by the commend
   // number. The default prompt is "root [%d] ". The maximum length of
   // the prompt is 55 characters. To set the prompt in an interactive
   // session do:
   // root [0] ((TRint*)gROOT->GetApplication())->SetPrompt("aap> ")
   // aap>

   const char *op = fDefaultPrompt;

   if (strlen(newPrompt) <= 55)
      fDefaultPrompt = newPrompt;
   else
      Error("SetPrompt", "newPrompt too long (> 55 characters)");

   return op;
}

//______________________________________________________________________________
void TRint::HandleTermInput()
{
   // Handle input coming from terminal.

   static TStopwatch timer;
   char *line;

   if ((line = Getlinem(kOneChar, 0))) {
      if (line[0] == 0 && Gl_eof())
         Terminate(0);

      if (gROOT->Timer()) timer.Start();

      Gl_histadd(line);

      char *s = line;
      while (s && *s == ' ') s++;     // strip-off leading blanks
      s[strlen(s)-1] = '\0';          // strip also '\n' off
      fInterrupt = kFALSE;

      if (!gInterpreter->GetMore() && strlen(s) != 0) fNcmd++;

      ProcessLine(s);

      if (strstr(s,".reset") != s)
          gInterpreter->EndOfLineAction();

      if (gROOT->Timer()) timer.Print();

      gTabCom->ClearAll();
      Getlinem(kInit, GetPrompt());
   }
}

//______________________________________________________________________________
void TRint::Terminate(int status)
{
   // Terminate the application. Reset the terminal to sane mode and call
   // the logoff macro defined via Rint.Logoff environment variable.

   Getlinem(kCleanUp, 0);

   if (ReturnFromRun()) {
      gSystem->ExitLoop();
   } else {
      //Execute logoff macro
      const char *logoff;
      logoff = gEnv->GetValue("Rint.Logoff", (char*)0);
      if (logoff && !NoLogOpt()) {
         char *mac = gSystem->Which(TROOT::GetMacroPath(), logoff, kReadPermission);
         if (mac)
            ProcessFile(logoff);
         delete [] mac;
      }

      gSystem->Exit(status);
   }
}
<|endoftext|>