<commit_before>// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_stream/socket_stream.h"

#include <arpa/inet.h>
#include <unistd.h>

#include <cstring>

#include "pw_log/log.h"

namespace pw::stream {
namespace {

constexpr uint32_t kMaxConcurrentUser = 1;
constexpr const char* kLocalhostAddress = "127.0.0.1";

}  // namespace

// Listen to the port and return after a client is connected
Status SocketStream::Serve(uint16_t port) {
  listen_port_ = port;
  socket_fd_ = socket(AF_INET, SOCK_STREAM, 0);
  if (socket_fd_ == kInvalidFd) {
    PW_LOG_ERROR("Failed to create socket: %s", std::strerror(errno));
    return Status::Unknown();
  }

  struct sockaddr_in addr = {};
  addr.sin_family = AF_INET;
  addr.sin_port = htons(listen_port_);
  addr.sin_addr.s_addr = INADDR_ANY;

  // Configure the socket to allow reusing the address. Closing a socket does
  // not immediately close it. Instead, the socket waits for some period of time
  // before it is actually closed. Setting SO_REUSEADDR allows this socket to
  // bind to an address that may still be in use by a recently closed socket.
  // Without this option, running a program multiple times in series may fail
  // unexpectedly.
  constexpr int value = 1;

  if (setsockopt(socket_fd_, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int)) <
      0) {
    PW_LOG_WARN("Failed to set SO_REUSEADDR: %s", std::strerror(errno));
  }

  if (bind(socket_fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
    PW_LOG_ERROR("Failed to bind socket to localhost:%hu: %s",
                 listen_port_,
                 std::strerror(errno));
    return Status::Unknown();
  }

  if (listen(socket_fd_, kMaxConcurrentUser) < 0) {
    PW_LOG_ERROR("Failed to listen to socket: %s", std::strerror(errno));
    return Status::Unknown();
  }

  socklen_t len = sizeof(sockaddr_client_);

  connection_fd_ =
      accept(socket_fd_, reinterpret_cast<sockaddr*>(&sockaddr_client_), &len);
  if (connection_fd_ < 0) {
    return Status::Unknown();
  }
  return OkStatus();
}

Status SocketStream::SocketStream::Connect(const char* host, uint16_t port) {
  connection_fd_ = socket(AF_INET, SOCK_STREAM, 0);

  sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);

  if (host == nullptr || std::strcmp(host, "localhost") == 0) {
    host = kLocalhostAddress;
  }

  if (inet_pton(AF_INET, host, &addr.sin_addr) <= 0) {
    PW_LOG_ERROR("Failed to configure connection address for socket");
    return Status::InvalidArgument();
  }

  if (connect(connection_fd_,
              reinterpret_cast<sockaddr*>(&addr),
              sizeof(addr)) < 0) {
    PW_LOG_ERROR(
        "Failed to connect to %s:%d: %s", host, port, std::strerror(errno));
    return Status::Unknown();
  }

  return OkStatus();
}

void SocketStream::Close() {
  if (socket_fd_ != kInvalidFd) {
    close(socket_fd_);
    socket_fd_ = kInvalidFd;
  }

  if (connection_fd_ != kInvalidFd) {
    close(connection_fd_);
    connection_fd_ = kInvalidFd;
  }
}

Status SocketStream::DoWrite(std::span<const std::byte> data) {
  // Use MSG_NOSIGNAL to avoid getting a SIGPIPE signal when the remote
  // peer drops the connection.
  ssize_t bytes_sent =
      send(connection_fd_, data.data(), data.size_bytes(), MSG_NOSIGNAL);

  if (bytes_sent < 0 || static_cast<size_t>(bytes_sent) != data.size()) {
    if (errno == EPIPE) {
      // An EPIPE indicates that the connection is close.  Return as successful
      // zero length write to inform the caller.
      return Status::OutOfRange();
    }

    return Status::Unknown();
  }
  return OkStatus();
}

StatusWithSize SocketStream::DoRead(ByteSpan dest) {
  ssize_t bytes_rcvd = recv(connection_fd_, dest.data(), dest.size_bytes(), 0);
  if (bytes_rcvd < 0) {
    return StatusWithSize::Unknown();
  }

  // TODO(b/229988958): Return Status::OutOfRange() on connection closed
  // (bytes_rcvd == 0) This is a breaking API change and needs to be
  // managed with a soft transition
  return StatusWithSize(bytes_rcvd);
}

};  // namespace pw::stream
<commit_msg>pw_stream: SocketStream reports out of range status on connection closed<commit_after>// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_stream/socket_stream.h"

#include <arpa/inet.h>
#include <unistd.h>

#include <cstring>

#include "pw_log/log.h"

namespace pw::stream {
namespace {

constexpr uint32_t kMaxConcurrentUser = 1;
constexpr const char* kLocalhostAddress = "127.0.0.1";

}  // namespace

// Listen to the port and return after a client is connected
Status SocketStream::Serve(uint16_t port) {
  listen_port_ = port;
  socket_fd_ = socket(AF_INET, SOCK_STREAM, 0);
  if (socket_fd_ == kInvalidFd) {
    PW_LOG_ERROR("Failed to create socket: %s", std::strerror(errno));
    return Status::Unknown();
  }

  struct sockaddr_in addr = {};
  addr.sin_family = AF_INET;
  addr.sin_port = htons(listen_port_);
  addr.sin_addr.s_addr = INADDR_ANY;

  // Configure the socket to allow reusing the address. Closing a socket does
  // not immediately close it. Instead, the socket waits for some period of time
  // before it is actually closed. Setting SO_REUSEADDR allows this socket to
  // bind to an address that may still be in use by a recently closed socket.
  // Without this option, running a program multiple times in series may fail
  // unexpectedly.
  constexpr int value = 1;

  if (setsockopt(socket_fd_, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int)) <
      0) {
    PW_LOG_WARN("Failed to set SO_REUSEADDR: %s", std::strerror(errno));
  }

  if (bind(socket_fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
    PW_LOG_ERROR("Failed to bind socket to localhost:%hu: %s",
                 listen_port_,
                 std::strerror(errno));
    return Status::Unknown();
  }

  if (listen(socket_fd_, kMaxConcurrentUser) < 0) {
    PW_LOG_ERROR("Failed to listen to socket: %s", std::strerror(errno));
    return Status::Unknown();
  }

  socklen_t len = sizeof(sockaddr_client_);

  connection_fd_ =
      accept(socket_fd_, reinterpret_cast<sockaddr*>(&sockaddr_client_), &len);
  if (connection_fd_ < 0) {
    return Status::Unknown();
  }
  return OkStatus();
}

Status SocketStream::SocketStream::Connect(const char* host, uint16_t port) {
  connection_fd_ = socket(AF_INET, SOCK_STREAM, 0);

  sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);

  if (host == nullptr || std::strcmp(host, "localhost") == 0) {
    host = kLocalhostAddress;
  }

  if (inet_pton(AF_INET, host, &addr.sin_addr) <= 0) {
    PW_LOG_ERROR("Failed to configure connection address for socket");
    return Status::InvalidArgument();
  }

  if (connect(connection_fd_,
              reinterpret_cast<sockaddr*>(&addr),
              sizeof(addr)) < 0) {
    PW_LOG_ERROR(
        "Failed to connect to %s:%d: %s", host, port, std::strerror(errno));
    return Status::Unknown();
  }

  return OkStatus();
}

void SocketStream::Close() {
  if (socket_fd_ != kInvalidFd) {
    close(socket_fd_);
    socket_fd_ = kInvalidFd;
  }

  if (connection_fd_ != kInvalidFd) {
    close(connection_fd_);
    connection_fd_ = kInvalidFd;
  }
}

Status SocketStream::DoWrite(std::span<const std::byte> data) {
  // Use MSG_NOSIGNAL to avoid getting a SIGPIPE signal when the remote
  // peer drops the connection.
  ssize_t bytes_sent =
      send(connection_fd_, data.data(), data.size_bytes(), MSG_NOSIGNAL);

  if (bytes_sent < 0 || static_cast<size_t>(bytes_sent) != data.size()) {
    if (errno == EPIPE) {
      // An EPIPE indicates that the connection is close.  Return an OutOfRange
      // error.
      return Status::OutOfRange();
    }

    return Status::Unknown();
  }
  return OkStatus();
}

StatusWithSize SocketStream::DoRead(ByteSpan dest) {
  ssize_t bytes_rcvd = recv(connection_fd_, dest.data(), dest.size_bytes(), 0);
  if (bytes_rcvd == 0) {
    // Remote peer has closed the connection.
    Close();
    return StatusWithSize::OutOfRange();
  } else if (bytes_rcvd < 0) {
    return StatusWithSize::Unknown();
  }
  return StatusWithSize(bytes_rcvd);
}

};  // namespace pw::stream
<|endoftext|>


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

#include <string>

#include "base/bind.h"
#include "base/message_loop.h"
#include "chrome/browser/chrome_plugin_service_filter.h"
#include "chrome/browser/chromeos/gview_request_interceptor.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/browser/plugin_prefs_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_pref_service.h"
#include "content/browser/mock_resource_context.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/dummy_resource_handler.h"
#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/plugins/npapi/plugin_list.h"

namespace chromeos {

namespace {

class GViewURLRequestTestJob : public net::URLRequestTestJob {
 public:
  explicit GViewURLRequestTestJob(net::URLRequest* request)
      : net::URLRequestTestJob(request, true) {
  }

  virtual bool GetMimeType(std::string* mime_type) const {
    // During the course of a single test, two URLRequestJobs are
    // created -- the first is for the viewable document URL, and the
    // second is for the rediected URL.  In order to test the
    // interceptor, the mime type of the first request must be one of
    // the supported viewable mime types.  So when the net::URLRequestJob
    // is a request for one of the test URLs that point to viewable
    // content, return an appropraite mime type.  Otherwise, return
    // "text/html".
    if (request_->url() == GURL("http://foo.com/file.pdf")) {
      *mime_type = "application/pdf";
    } else if (request_->url() == GURL("http://foo.com/file.ppt")) {
      *mime_type = "application/vnd.ms-powerpoint";
    } else {
      *mime_type = "text/html";
    }
    return true;
  }

 private:
  ~GViewURLRequestTestJob() {}
};

class GViewRequestProtocolFactory
    : public net::URLRequestJobFactory::ProtocolHandler {
 public:
  GViewRequestProtocolFactory() {}
  virtual ~GViewRequestProtocolFactory() {}

  virtual net::URLRequestJob* MaybeCreateJob(net::URLRequest* request) const {
    return new GViewURLRequestTestJob(request);
  }
};

void QuitMessageLoop(const std::vector<webkit::WebPluginInfo>&) {
  MessageLoop::current()->Quit();
}

class GViewRequestInterceptorTest : public testing::Test {
 public:
  GViewRequestInterceptorTest()
      : ui_thread_(BrowserThread::UI, &message_loop_),
        file_thread_(BrowserThread::FILE, &message_loop_),
        io_thread_(BrowserThread::IO, &message_loop_) {}

  virtual void SetUp() {
    content::ResourceContext* resource_context =
        content::MockResourceContext::GetInstance();
    net::URLRequestContext* request_context =
        resource_context->request_context();
    old_factory_ = request_context->job_factory();
    job_factory_.SetProtocolHandler("http", new GViewRequestProtocolFactory);
    job_factory_.AddInterceptor(new GViewRequestInterceptor);
    request_context->set_job_factory(&job_factory_);
    PluginPrefsFactory::GetInstance()->ForceRegisterPrefsForTest(&prefs_);
    plugin_prefs_ = new PluginPrefs();
    plugin_prefs_->SetPrefs(&prefs_);
    ChromePluginServiceFilter* filter =
        ChromePluginServiceFilter::GetInstance();
    filter->RegisterResourceContext(plugin_prefs_, resource_context);
    PluginService::GetInstance()->set_filter(filter);

    ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path_));

    handler_ = new content::DummyResourceHandler();
  }

  virtual void TearDown() {
    plugin_prefs_->ShutdownOnUIThread();
    content::ResourceContext* resource_context =
        content::MockResourceContext::GetInstance();
    net::URLRequestContext* request_context =
        resource_context->request_context();
    request_context->set_job_factory(old_factory_);
    ChromePluginServiceFilter* filter =
        ChromePluginServiceFilter::GetInstance();
    filter->UnregisterResourceContext(resource_context);
    PluginService::GetInstance()->set_filter(NULL);
  }

  // GetPluginInfoByPath() will only use stale information. Because plugin
  // refresh is asynchronous, spin a MessageLoop until the callback is run,
  // after which, the test will continue.
  void RegisterPDFPlugin() {
    webkit::WebPluginInfo info;
    info.path = pdf_path_;
    webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info);

    PluginService::GetInstance()->RefreshPluginList();
    PluginService::GetInstance()->GetPlugins(base::Bind(&QuitMessageLoop));
    MessageLoop::current()->Run();
  }

  void UnregisterPDFPlugin() {
    webkit::npapi::PluginList::Singleton()->UnregisterInternalPlugin(pdf_path_);

    PluginService::GetInstance()->RefreshPluginList();
    PluginService::GetInstance()->GetPlugins(base::Bind(&QuitMessageLoop));
    MessageLoop::current()->Run();
  }

  void SetPDFPluginLoadedState(bool want_loaded) {
    webkit::WebPluginInfo info;
    bool is_loaded = PluginService::GetInstance()->GetPluginInfoByPath(
        pdf_path_, &info);
    if (is_loaded && !want_loaded) {
      UnregisterPDFPlugin();
      is_loaded = PluginService::GetInstance()->GetPluginInfoByPath(
          pdf_path_, &info);
    } else if (!is_loaded && want_loaded) {
      // This "loads" the plug-in even if it's not present on the
      // system - which is OK since we don't actually use it, just
      // need it to be "enabled" for the test.
      RegisterPDFPlugin();
      is_loaded = PluginService::GetInstance()->GetPluginInfoByPath(
          pdf_path_, &info);
    }
    EXPECT_EQ(want_loaded, is_loaded);
  }

  void SetupRequest(net::URLRequest* request) {
    content::ResourceContext* context =
        content::MockResourceContext::GetInstance();
    ResourceDispatcherHostRequestInfo* info =
        new ResourceDispatcherHostRequestInfo(handler_,
                                              ChildProcessInfo::RENDER_PROCESS,
                                              -1,          // child_id
                                              MSG_ROUTING_NONE,
                                              0,           // origin_pid
                                              request->identifier(),
                                              false,       // is_main_frame
                                              -1,          // frame_id
                                              ResourceType::MAIN_FRAME,
                                              PageTransition::LINK,
                                              0,           // upload_size
                                              false,       // is_download
                                              true,        // allow_download
                                              false,       // has_user_gesture
                                              context);
    request->SetUserData(NULL, info);
    request->set_context(context->request_context());
  }

 protected:
  MessageLoopForIO message_loop_;
  BrowserThread ui_thread_;
  BrowserThread file_thread_;
  BrowserThread io_thread_;
  TestingPrefService prefs_;
  scoped_refptr<PluginPrefs> plugin_prefs_;
  net::URLRequestJobFactory job_factory_;
  const net::URLRequestJobFactory* old_factory_;
  scoped_refptr<ResourceHandler> handler_;
  TestDelegate test_delegate_;
  FilePath pdf_path_;
};

TEST_F(GViewRequestInterceptorTest, DoNotInterceptHtml) {
  net::URLRequest request(GURL("http://foo.com/index.html"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(0, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://foo.com/index.html"), request.url());
}

TEST_F(GViewRequestInterceptorTest, DoNotInterceptDownload) {
  net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
  SetupRequest(&request);
  request.set_load_flags(net::LOAD_IS_DOWNLOAD);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(0, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://foo.com/file.pdf"), request.url());
}

TEST_F(GViewRequestInterceptorTest, DoNotInterceptPdfWhenEnabled) {
  SetPDFPluginLoadedState(true);
  plugin_prefs_->EnablePlugin(true, pdf_path_);

  net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(0, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://foo.com/file.pdf"), request.url());
}

TEST_F(GViewRequestInterceptorTest, InterceptPdfWhenDisabled) {
  SetPDFPluginLoadedState(true);
  plugin_prefs_->EnablePlugin(false, pdf_path_);

  net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(1, test_delegate_.received_redirect_count());
  EXPECT_EQ(
      GURL("http://docs.google.com/gview?url=http%3A//foo.com/file.pdf"),
      request.url());
}

TEST_F(GViewRequestInterceptorTest, InterceptPdfWithNoPlugin) {
  SetPDFPluginLoadedState(false);

  net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(1, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://docs.google.com/gview?url=http%3A//foo.com/file.pdf"),
                 request.url());
}

TEST_F(GViewRequestInterceptorTest, InterceptPowerpoint) {
  net::URLRequest request(GURL("http://foo.com/file.ppt"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(1, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://docs.google.com/gview?url=http%3A//foo.com/file.ppt"),
                 request.url());
}

}  // namespace

}  // namespace chromeos
<commit_msg>Fix linux_chromeos build, PageTransition rename<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/bind.h"
#include "base/message_loop.h"
#include "chrome/browser/chrome_plugin_service_filter.h"
#include "chrome/browser/chromeos/gview_request_interceptor.h"
#include "chrome/browser/plugin_prefs.h"
#include "chrome/browser/plugin_prefs_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_pref_service.h"
#include "content/browser/mock_resource_context.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/dummy_resource_handler.h"
#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/plugins/npapi/plugin_list.h"

namespace chromeos {

namespace {

class GViewURLRequestTestJob : public net::URLRequestTestJob {
 public:
  explicit GViewURLRequestTestJob(net::URLRequest* request)
      : net::URLRequestTestJob(request, true) {
  }

  virtual bool GetMimeType(std::string* mime_type) const {
    // During the course of a single test, two URLRequestJobs are
    // created -- the first is for the viewable document URL, and the
    // second is for the rediected URL.  In order to test the
    // interceptor, the mime type of the first request must be one of
    // the supported viewable mime types.  So when the net::URLRequestJob
    // is a request for one of the test URLs that point to viewable
    // content, return an appropraite mime type.  Otherwise, return
    // "text/html".
    if (request_->url() == GURL("http://foo.com/file.pdf")) {
      *mime_type = "application/pdf";
    } else if (request_->url() == GURL("http://foo.com/file.ppt")) {
      *mime_type = "application/vnd.ms-powerpoint";
    } else {
      *mime_type = "text/html";
    }
    return true;
  }

 private:
  ~GViewURLRequestTestJob() {}
};

class GViewRequestProtocolFactory
    : public net::URLRequestJobFactory::ProtocolHandler {
 public:
  GViewRequestProtocolFactory() {}
  virtual ~GViewRequestProtocolFactory() {}

  virtual net::URLRequestJob* MaybeCreateJob(net::URLRequest* request) const {
    return new GViewURLRequestTestJob(request);
  }
};

void QuitMessageLoop(const std::vector<webkit::WebPluginInfo>&) {
  MessageLoop::current()->Quit();
}

class GViewRequestInterceptorTest : public testing::Test {
 public:
  GViewRequestInterceptorTest()
      : ui_thread_(BrowserThread::UI, &message_loop_),
        file_thread_(BrowserThread::FILE, &message_loop_),
        io_thread_(BrowserThread::IO, &message_loop_) {}

  virtual void SetUp() {
    content::ResourceContext* resource_context =
        content::MockResourceContext::GetInstance();
    net::URLRequestContext* request_context =
        resource_context->request_context();
    old_factory_ = request_context->job_factory();
    job_factory_.SetProtocolHandler("http", new GViewRequestProtocolFactory);
    job_factory_.AddInterceptor(new GViewRequestInterceptor);
    request_context->set_job_factory(&job_factory_);
    PluginPrefsFactory::GetInstance()->ForceRegisterPrefsForTest(&prefs_);
    plugin_prefs_ = new PluginPrefs();
    plugin_prefs_->SetPrefs(&prefs_);
    ChromePluginServiceFilter* filter =
        ChromePluginServiceFilter::GetInstance();
    filter->RegisterResourceContext(plugin_prefs_, resource_context);
    PluginService::GetInstance()->set_filter(filter);

    ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path_));

    handler_ = new content::DummyResourceHandler();
  }

  virtual void TearDown() {
    plugin_prefs_->ShutdownOnUIThread();
    content::ResourceContext* resource_context =
        content::MockResourceContext::GetInstance();
    net::URLRequestContext* request_context =
        resource_context->request_context();
    request_context->set_job_factory(old_factory_);
    ChromePluginServiceFilter* filter =
        ChromePluginServiceFilter::GetInstance();
    filter->UnregisterResourceContext(resource_context);
    PluginService::GetInstance()->set_filter(NULL);
  }

  // GetPluginInfoByPath() will only use stale information. Because plugin
  // refresh is asynchronous, spin a MessageLoop until the callback is run,
  // after which, the test will continue.
  void RegisterPDFPlugin() {
    webkit::WebPluginInfo info;
    info.path = pdf_path_;
    webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info);

    PluginService::GetInstance()->RefreshPluginList();
    PluginService::GetInstance()->GetPlugins(base::Bind(&QuitMessageLoop));
    MessageLoop::current()->Run();
  }

  void UnregisterPDFPlugin() {
    webkit::npapi::PluginList::Singleton()->UnregisterInternalPlugin(pdf_path_);

    PluginService::GetInstance()->RefreshPluginList();
    PluginService::GetInstance()->GetPlugins(base::Bind(&QuitMessageLoop));
    MessageLoop::current()->Run();
  }

  void SetPDFPluginLoadedState(bool want_loaded) {
    webkit::WebPluginInfo info;
    bool is_loaded = PluginService::GetInstance()->GetPluginInfoByPath(
        pdf_path_, &info);
    if (is_loaded && !want_loaded) {
      UnregisterPDFPlugin();
      is_loaded = PluginService::GetInstance()->GetPluginInfoByPath(
          pdf_path_, &info);
    } else if (!is_loaded && want_loaded) {
      // This "loads" the plug-in even if it's not present on the
      // system - which is OK since we don't actually use it, just
      // need it to be "enabled" for the test.
      RegisterPDFPlugin();
      is_loaded = PluginService::GetInstance()->GetPluginInfoByPath(
          pdf_path_, &info);
    }
    EXPECT_EQ(want_loaded, is_loaded);
  }

  void SetupRequest(net::URLRequest* request) {
    content::ResourceContext* context =
        content::MockResourceContext::GetInstance();
    ResourceDispatcherHostRequestInfo* info =
        new ResourceDispatcherHostRequestInfo(handler_,
                                              ChildProcessInfo::RENDER_PROCESS,
                                              -1,          // child_id
                                              MSG_ROUTING_NONE,
                                              0,           // origin_pid
                                              request->identifier(),
                                              false,       // is_main_frame
                                              -1,          // frame_id
                                              ResourceType::MAIN_FRAME,
                                              content::PAGE_TRANSITION_LINK,
                                              0,           // upload_size
                                              false,       // is_download
                                              true,        // allow_download
                                              false,       // has_user_gesture
                                              context);
    request->SetUserData(NULL, info);
    request->set_context(context->request_context());
  }

 protected:
  MessageLoopForIO message_loop_;
  BrowserThread ui_thread_;
  BrowserThread file_thread_;
  BrowserThread io_thread_;
  TestingPrefService prefs_;
  scoped_refptr<PluginPrefs> plugin_prefs_;
  net::URLRequestJobFactory job_factory_;
  const net::URLRequestJobFactory* old_factory_;
  scoped_refptr<ResourceHandler> handler_;
  TestDelegate test_delegate_;
  FilePath pdf_path_;
};

TEST_F(GViewRequestInterceptorTest, DoNotInterceptHtml) {
  net::URLRequest request(GURL("http://foo.com/index.html"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(0, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://foo.com/index.html"), request.url());
}

TEST_F(GViewRequestInterceptorTest, DoNotInterceptDownload) {
  net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
  SetupRequest(&request);
  request.set_load_flags(net::LOAD_IS_DOWNLOAD);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(0, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://foo.com/file.pdf"), request.url());
}

TEST_F(GViewRequestInterceptorTest, DoNotInterceptPdfWhenEnabled) {
  SetPDFPluginLoadedState(true);
  plugin_prefs_->EnablePlugin(true, pdf_path_);

  net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(0, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://foo.com/file.pdf"), request.url());
}

TEST_F(GViewRequestInterceptorTest, InterceptPdfWhenDisabled) {
  SetPDFPluginLoadedState(true);
  plugin_prefs_->EnablePlugin(false, pdf_path_);

  net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(1, test_delegate_.received_redirect_count());
  EXPECT_EQ(
      GURL("http://docs.google.com/gview?url=http%3A//foo.com/file.pdf"),
      request.url());
}

TEST_F(GViewRequestInterceptorTest, InterceptPdfWithNoPlugin) {
  SetPDFPluginLoadedState(false);

  net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(1, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://docs.google.com/gview?url=http%3A//foo.com/file.pdf"),
                 request.url());
}

TEST_F(GViewRequestInterceptorTest, InterceptPowerpoint) {
  net::URLRequest request(GURL("http://foo.com/file.ppt"), &test_delegate_);
  SetupRequest(&request);
  request.Start();
  MessageLoop::current()->Run();
  EXPECT_EQ(1, test_delegate_.received_redirect_count());
  EXPECT_EQ(GURL("http://docs.google.com/gview?url=http%3A//foo.com/file.ppt"),
                 request.url());
}

}  // namespace

}  // namespace chromeos
<|endoftext|>


<commit_before>//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef GPUMEMORY_HPP_
#define GPUMEMORY_HPP_

#include "top.hpp"
#include "thread/atomic.hpp"
#include "device/gpu/gpuresource.hpp"
#include "device/gpu/gpuheap.hpp"
#include "device/gpu/gpudevice.hpp"
#include <map>

/*! \addtogroup GPU
 *  @{
 */
namespace device {
class Memory;
}

//! GPU Device Implementation
namespace gpu {

class Device;
class Heap;
class Resource;
class Memory;
class VirtualGPU;
class HeapBlock;

//! GPU memory object.
//  Wrapper that can contain a heap block or an interop buffer/image.
class Memory: public device::Memory, public Resource
{
public:
    enum InteropType {
        InteropNone         = 0,    //!< None interop memory
        InteropHwEmulation  = 1,    //!< Uses HW emulaiton with calMemCopy
        InteropDirectAccess = 2     //!< Uses direct access to the interop surface
    };

    //! Constructor (with owner)
    Memory(
        const Device&   gpuDev,
        amd::Memory&    owner,
        HeapBlock*      hb,
        size_t          size = 0);

    //! Constructor (nonfat version for local scratch mem use)
    Memory(
        const Device&   gpuDev,
        HeapBlock&      hb);

    //! Constructor (nonfat version for local scratch mem use without heap block)
    Memory(
        const Device&   gpuDev,
        size_t          size);

    //! Constructor memory for buffer (without global heap allocaton)
    Memory(
        const Device&   gpuDev, //!< GPU device object
        amd::Memory&    owner,  //!< Abstraction layer memory object
        size_t          width,  //!< Memory width
        cmSurfFmt       format  //!< CAL format
        );

    //! Constructor memory for buffer (without global heap allocaton)
    Memory(
        const Device&   gpuDev, //!< GPU device object
        size_t          size,   //!< Memory object size
        size_t          width,  //!< Memory width
        cmSurfFmt       format  //!< CAL format
        );

    //! Constructor memory for images (without global heap allocaton)
    Memory(
        const Device&   gpuDev,         //!< GPU device object
        amd::Memory&    owner,          //!< Abstraction layer memory object
        size_t          width,          //!< Allocated memory width
        size_t          height,         //!< Allocated memory height
        size_t          depth,          //!< Allocated memory depth
        cmSurfFmt       format,         //!< Memory format
        gslChannelOrder chOrder,        //!< Channel order
        cl_mem_object_type imageType    //!< CL image type
        );

    //! Constructor memory for images (without global heap allocaton)
    Memory(
        const Device&   gpuDev,         //!< GPU device object
        size_t          size,           //!< Memory object size
        size_t          width,          //!< Allocated memory width
        size_t          height,         //!< Allocated memory height
        size_t          depth,          //!< Allocated memory depth
        cmSurfFmt       format,         //!< Memory format
        gslChannelOrder chOrder,        //!< Channel order
        cl_mem_object_type imageType    //!< CL image type
        );

    //! Default destructor
    ~Memory();

    //! Reallocates the memory object in the new heap block
    bool reallocate(
        HeapBlock*      hb,     //! The new heap block for this memory object
        const Resource* parent  //! Parent resource for view reallocaiton
        );

    //! Creates the interop memory
    bool createInterop(
        InteropType     type    //!< The interop type
        );

    //! Overloads the resource create method
    virtual bool create(
        Resource::MemoryType    memType,        //!< Memory type
        Resource::CreateParams* params = NULL   //!< Prameters for create
        );

    //! Allocate memory for API-level maps
    virtual void* allocMapTarget(
        const amd::Coord3D& origin, //!< The map location in memory
        const amd::Coord3D& region, //!< The map region in memory
        uint    mapFlags,           //!< Map flags
        size_t* rowPitch = NULL,    //!< Row pitch for the mapped memory
        size_t* slicePitch = NULL   //!< Slice for the mapped memory
        );

    //! Pins system memory associated with this memory object
    virtual bool pinSystemMemory(
        void*   hostPtr,            //!< System memory address
        size_t  size                //!< Size of allocated system memory
        );

    //! Releases indirect map surface
    virtual void releaseIndirectMap() { decIndMapCount(); }

    //! Map the device memory to CPU visible
    virtual void* cpuMap(
        device::VirtualDevice& vDev,//!< Virtual device for map operaiton
        uint flags = 0,             //!< flags for the map operation
        // Optimization for multilayer map/unmap
        uint startLayer = 0,        //!< Start layer for multilayer map
        uint numLayers = 0,         //!< End layer for multilayer map
        size_t* rowPitch = NULL,    //!< Row pitch for the device memory
        size_t* slicePitch = NULL   //!< Slice pitch for the device memory
        );

    //! Unmap the device memory
    virtual void cpuUnmap(
        device::VirtualDevice& vDev //!< Virtual device for unmap operaiton
        );

    //! Updates device memory from the owner's host allocation
    void syncCacheFromHost(
        VirtualGPU& gpu,            //!< Virtual GPU device object
        //! Synchronization flags
        device::Memory::SyncFlags   syncFlags = device::Memory::SyncFlags()
        );

    //! Updates the owner's host allocation from device memory
    virtual void syncHostFromCache(
        //! Synchronization flags
        device::Memory::SyncFlags   syncFlags = device::Memory::SyncFlags()
        );

    //! Creates a view from current resource
    virtual Memory* createBufferView(
        amd::Memory&    subBufferOwner  //!< The abstraction layer subbuf owner
        );

    //! Allocates host memory for synchronization with MGPU context
    void mgpuCacheWriteBack();

    //! Transfers objects data to the destination object
    bool moveTo(Memory& dst);

    //! Accessors for indirect map memory object
    Memory* mapMemory() const;

    //! Returns the interop memory for this memory object
    Memory* interop() const { return interopMemory_; }

    //! Gets interop type for this memory object
    InteropType interopType() const { return interopType_; }

    //! Sets interop type for this memory object
    void setInteropType(InteropType type) { interopType_ = type; }

    //! Returns the HeapBlock pointer
    const HeapBlock* hb() const { return hb_; }

    //! Set the owner
    void setOwner(amd::Memory* owner) { owner_ = owner; }

    // Decompress GL depth-stencil/MSAA resources for CL access
    // Invalidates any FBOs the resource may be bound to, otherwise the GL driver may crash.
   virtual bool processGLResource(GLResourceOP operation);

    //! Returns the interop resource for this memory object
    const Memory* parent() const { return parent_; }

    //! Returns TRUE if direct map is acceaptable
    //! The method detects forced USWC memory on APU and
    //! will cause a switch to indirect map for MAP_READ operations
    bool isDirectMap(uint mapFlags)
    {
        return (isCacheable() || (owner()->getMemFlags() & CL_MEM_ALLOC_HOST_PTR) ||
            !isHostMemDirectAccess() || !(mapFlags & CL_MAP_READ));
    }

protected:
    //! Decrement map count
    void decIndMapCount();

    //! Initialize the object members
    void init();

private:
    //! Disable copy constructor
    Memory(const Memory&);

    //! Disable operator=
    Memory& operator=(const Memory&);

    InteropType interopType_;   //!< Interop type
    Memory*     interopMemory_; //!< interop memory

    HeapBlock*  hb_;            //!< Heap Block, or NULL if not in-heap memory
    Memory*     pinnedMemory_;  //!< Memory used as pinned system memory
    const Memory*   parent_;        //!< Parent memory object
};

class Buffer: public gpu::Memory
{
public:
    //! Buffer constructor
    Buffer(
        const Device&   gpuDev,     //!< GPU device object
        amd::Memory&    owner,      //!< Abstraction layer memory object
        size_t          size        //!< Buffer size
        )
        : gpu::Memory(gpuDev, owner,
            amd::alignUp(size, ElementSize) / ElementSize, ElementType)
        {}

    //! Creates a view from current resource
    virtual Memory* createBufferView(
        amd::Memory&    subBufferOwner  //!< The abstraction layer subbuf owner
        ) const;

private:
    //! Disable copy constructor
    Buffer(const Buffer&);

    //! Disable operator=
    Buffer& operator=(const Buffer&);

    //! The size of buffer element in bytes
    static const size_t ElementSize = 4;

    //! The type of buffer element
    static const cmSurfFmt ElementType = CM_SURF_FMT_R32I;
};

class Image: public gpu::Memory
{
public:
    //! Image constructor
    Image(
        const Device&   gpuDev,     //!< GPU device object
        amd::Memory&    owner,      //!< Abstraction layer memory object
        size_t          width,      //!< Allocated memory width
        size_t          height,     //!< Allocated memory height
        size_t          depth,      //!< Allocated memory depth
        cmSurfFmt       format,     //!< Memory format
        gslChannelOrder chOrder,    //!< Channel order
        cl_mem_object_type imageType    //!< CL image type
        )
        : gpu::Memory(gpuDev, owner, width, height, depth, format, chOrder, imageType)
        {}

    //! Image constructor
    Image(
        const Device&   gpuDev,     //!< GPU device object
        size_t          size,       //!< Memory size
        size_t          width,      //!< Allocated memory width
        size_t          height,     //!< Allocated memory height
        size_t          depth,      //!< Allocated memory depth
        cmSurfFmt       format,     //!< Memory format
        gslChannelOrder chOrder,    //!< Channel order
        cl_mem_object_type imageType    //!< CL image type
        )
        : gpu::Memory(gpuDev, size, width, height, depth, format, chOrder, imageType)
        {}

    //! Allocate memory for API-level maps
    virtual void* allocMapTarget(
        const amd::Coord3D& origin, //!< The map location in memory
        const amd::Coord3D& region, //!< The map region in memory
        uint    mapFlags,           //!< Map flags
        size_t* rowPitch = NULL,    //!< Row pitch for the mapped memory
        size_t* slicePitch = NULL   //!< Slice for the mapped memory
        );

private:
    //! Disable copy constructor
    Image(const Image&);

    //! Disable operator=
    Image& operator=(const Image&);
};

} // namespace gpu

#endif // GPUMEMORY_HPP_
<commit_msg>P4 to Git Change 1102960 by gandryey@gera-dev-w7 on 2014/12/05 10:51:47<commit_after>//
// Copyright (c) 2009 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef GPUMEMORY_HPP_
#define GPUMEMORY_HPP_

#include "top.hpp"
#include "thread/atomic.hpp"
#include "device/gpu/gpuresource.hpp"
#include "device/gpu/gpuheap.hpp"
#include "device/gpu/gpudevice.hpp"
#include <map>

/*! \addtogroup GPU
 *  @{
 */
namespace device {
class Memory;
}

//! GPU Device Implementation
namespace gpu {

class Device;
class Heap;
class Resource;
class Memory;
class VirtualGPU;
class HeapBlock;

//! GPU memory object.
//  Wrapper that can contain a heap block or an interop buffer/image.
class Memory: public device::Memory, public Resource
{
public:
    enum InteropType {
        InteropNone         = 0,    //!< None interop memory
        InteropHwEmulation  = 1,    //!< Uses HW emulaiton with calMemCopy
        InteropDirectAccess = 2     //!< Uses direct access to the interop surface
    };

    //! Constructor (with owner)
    Memory(
        const Device&   gpuDev,
        amd::Memory&    owner,
        HeapBlock*      hb,
        size_t          size = 0);

    //! Constructor (nonfat version for local scratch mem use)
    Memory(
        const Device&   gpuDev,
        HeapBlock&      hb);

    //! Constructor (nonfat version for local scratch mem use without heap block)
    Memory(
        const Device&   gpuDev,
        size_t          size);

    //! Constructor memory for buffer (without global heap allocaton)
    Memory(
        const Device&   gpuDev, //!< GPU device object
        amd::Memory&    owner,  //!< Abstraction layer memory object
        size_t          width,  //!< Memory width
        cmSurfFmt       format  //!< CAL format
        );

    //! Constructor memory for buffer (without global heap allocaton)
    Memory(
        const Device&   gpuDev, //!< GPU device object
        size_t          size,   //!< Memory object size
        size_t          width,  //!< Memory width
        cmSurfFmt       format  //!< CAL format
        );

    //! Constructor memory for images (without global heap allocaton)
    Memory(
        const Device&   gpuDev,         //!< GPU device object
        amd::Memory&    owner,          //!< Abstraction layer memory object
        size_t          width,          //!< Allocated memory width
        size_t          height,         //!< Allocated memory height
        size_t          depth,          //!< Allocated memory depth
        cmSurfFmt       format,         //!< Memory format
        gslChannelOrder chOrder,        //!< Channel order
        cl_mem_object_type imageType    //!< CL image type
        );

    //! Constructor memory for images (without global heap allocaton)
    Memory(
        const Device&   gpuDev,         //!< GPU device object
        size_t          size,           //!< Memory object size
        size_t          width,          //!< Allocated memory width
        size_t          height,         //!< Allocated memory height
        size_t          depth,          //!< Allocated memory depth
        cmSurfFmt       format,         //!< Memory format
        gslChannelOrder chOrder,        //!< Channel order
        cl_mem_object_type imageType    //!< CL image type
        );

    //! Default destructor
    ~Memory();

    //! Reallocates the memory object in the new heap block
    bool reallocate(
        HeapBlock*      hb,     //! The new heap block for this memory object
        const Resource* parent  //! Parent resource for view reallocaiton
        );

    //! Creates the interop memory
    bool createInterop(
        InteropType     type    //!< The interop type
        );

    //! Overloads the resource create method
    virtual bool create(
        Resource::MemoryType    memType,        //!< Memory type
        Resource::CreateParams* params = NULL   //!< Prameters for create
        );

    //! Allocate memory for API-level maps
    virtual void* allocMapTarget(
        const amd::Coord3D& origin, //!< The map location in memory
        const amd::Coord3D& region, //!< The map region in memory
        uint    mapFlags,           //!< Map flags
        size_t* rowPitch = NULL,    //!< Row pitch for the mapped memory
        size_t* slicePitch = NULL   //!< Slice for the mapped memory
        );

    //! Pins system memory associated with this memory object
    virtual bool pinSystemMemory(
        void*   hostPtr,            //!< System memory address
        size_t  size                //!< Size of allocated system memory
        );

    //! Releases indirect map surface
    virtual void releaseIndirectMap() { decIndMapCount(); }

    //! Map the device memory to CPU visible
    virtual void* cpuMap(
        device::VirtualDevice& vDev,//!< Virtual device for map operaiton
        uint flags = 0,             //!< flags for the map operation
        // Optimization for multilayer map/unmap
        uint startLayer = 0,        //!< Start layer for multilayer map
        uint numLayers = 0,         //!< End layer for multilayer map
        size_t* rowPitch = NULL,    //!< Row pitch for the device memory
        size_t* slicePitch = NULL   //!< Slice pitch for the device memory
        );

    //! Unmap the device memory
    virtual void cpuUnmap(
        device::VirtualDevice& vDev //!< Virtual device for unmap operaiton
        );

    //! Updates device memory from the owner's host allocation
    void syncCacheFromHost(
        VirtualGPU& gpu,            //!< Virtual GPU device object
        //! Synchronization flags
        device::Memory::SyncFlags   syncFlags = device::Memory::SyncFlags()
        );

    //! Updates the owner's host allocation from device memory
    virtual void syncHostFromCache(
        //! Synchronization flags
        device::Memory::SyncFlags   syncFlags = device::Memory::SyncFlags()
        );

    //! Creates a view from current resource
    virtual Memory* createBufferView(
        amd::Memory&    subBufferOwner  //!< The abstraction layer subbuf owner
        );

    //! Allocates host memory for synchronization with MGPU context
    void mgpuCacheWriteBack();

    //! Transfers objects data to the destination object
    bool moveTo(Memory& dst);

    //! Accessors for indirect map memory object
    Memory* mapMemory() const;

    //! Returns the interop memory for this memory object
    Memory* interop() const { return interopMemory_; }

    //! Gets interop type for this memory object
    InteropType interopType() const { return interopType_; }

    //! Sets interop type for this memory object
    void setInteropType(InteropType type) { interopType_ = type; }

    //! Returns the HeapBlock pointer
    const HeapBlock* hb() const { return hb_; }

    //! Set the owner
    void setOwner(amd::Memory* owner) { owner_ = owner; }

    // Decompress GL depth-stencil/MSAA resources for CL access
    // Invalidates any FBOs the resource may be bound to, otherwise the GL driver may crash.
   virtual bool processGLResource(GLResourceOP operation);

    //! Returns the interop resource for this memory object
    const Memory* parent() const { return parent_; }

    //! Returns TRUE if direct map is acceaptable
    //! The method detects forced USWC memory on APU and
    //! will cause a switch to indirect map for MAP_READ operations
    bool isDirectMap(uint mapFlags)
    {
        return (((isCacheable() || (owner()->getMemFlags() & CL_MEM_ALLOC_HOST_PTR) ||
            !isHostMemDirectAccess() || !(mapFlags & CL_MAP_READ)) &&
            // If map(indirect) memory isn't NULL,
            // then it's a double map from the app with different map flags.
            // If runtime will provide different regions,
            // then it won't be able to guarantee coherency
            (mapMemory_ == NULL)) ||
            // Keep direct map always if the first map was direct already
            ((indirectMapCount_ > 1) && (mapMemory_ == NULL)));
    }

protected:
    //! Decrement map count
    void decIndMapCount();

    //! Initialize the object members
    void init();

private:
    //! Disable copy constructor
    Memory(const Memory&);

    //! Disable operator=
    Memory& operator=(const Memory&);

    InteropType interopType_;   //!< Interop type
    Memory*     interopMemory_; //!< interop memory

    HeapBlock*  hb_;            //!< Heap Block, or NULL if not in-heap memory
    Memory*     pinnedMemory_;  //!< Memory used as pinned system memory
    const Memory*   parent_;        //!< Parent memory object
};

class Buffer: public gpu::Memory
{
public:
    //! Buffer constructor
    Buffer(
        const Device&   gpuDev,     //!< GPU device object
        amd::Memory&    owner,      //!< Abstraction layer memory object
        size_t          size        //!< Buffer size
        )
        : gpu::Memory(gpuDev, owner,
            amd::alignUp(size, ElementSize) / ElementSize, ElementType)
        {}

    //! Creates a view from current resource
    virtual Memory* createBufferView(
        amd::Memory&    subBufferOwner  //!< The abstraction layer subbuf owner
        ) const;

private:
    //! Disable copy constructor
    Buffer(const Buffer&);

    //! Disable operator=
    Buffer& operator=(const Buffer&);

    //! The size of buffer element in bytes
    static const size_t ElementSize = 4;

    //! The type of buffer element
    static const cmSurfFmt ElementType = CM_SURF_FMT_R32I;
};

class Image: public gpu::Memory
{
public:
    //! Image constructor
    Image(
        const Device&   gpuDev,     //!< GPU device object
        amd::Memory&    owner,      //!< Abstraction layer memory object
        size_t          width,      //!< Allocated memory width
        size_t          height,     //!< Allocated memory height
        size_t          depth,      //!< Allocated memory depth
        cmSurfFmt       format,     //!< Memory format
        gslChannelOrder chOrder,    //!< Channel order
        cl_mem_object_type imageType    //!< CL image type
        )
        : gpu::Memory(gpuDev, owner, width, height, depth, format, chOrder, imageType)
        {}

    //! Image constructor
    Image(
        const Device&   gpuDev,     //!< GPU device object
        size_t          size,       //!< Memory size
        size_t          width,      //!< Allocated memory width
        size_t          height,     //!< Allocated memory height
        size_t          depth,      //!< Allocated memory depth
        cmSurfFmt       format,     //!< Memory format
        gslChannelOrder chOrder,    //!< Channel order
        cl_mem_object_type imageType    //!< CL image type
        )
        : gpu::Memory(gpuDev, size, width, height, depth, format, chOrder, imageType)
        {}

    //! Allocate memory for API-level maps
    virtual void* allocMapTarget(
        const amd::Coord3D& origin, //!< The map location in memory
        const amd::Coord3D& region, //!< The map region in memory
        uint    mapFlags,           //!< Map flags
        size_t* rowPitch = NULL,    //!< Row pitch for the mapped memory
        size_t* slicePitch = NULL   //!< Slice for the mapped memory
        );

private:
    //! Disable copy constructor
    Image(const Image&);

    //! Disable operator=
    Image& operator=(const Image&);
};

} // namespace gpu

#endif // GPUMEMORY_HPP_
<|endoftext|>


<commit_before>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                               libparaver-api                              *
 *                      API Library for libparaver-kernel                    *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in 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 LGPL 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *\
 | @file: $HeadURL$
 | @last_commit: $Date$
 | @version:     $Revision$
\* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */

#include <algorithm>
#include <functional>
#include "trace.h"
#include "histogramtotals.h"
#include "paraverkernelexception.h"

template < typename SelType, typename LevelType >
SelectionManagement< SelType, LevelType >::SelectionManagement()
{
}

template < typename SelType, typename LevelType >
SelectionManagement< SelType, LevelType >::SelectionManagement( const SelectionManagement& whichSelection )
{
  for ( size_t i = 0 ; i < whichSelection.selectedSet.size(); ++i )
  {
    selectedSet.push_back( whichSelection.selectedSet[ i ] );
  }
  for ( size_t i = 0 ; i < whichSelection.selected.size(); ++i )
  {
    selected.push_back( whichSelection.selected[ i ] );
  }
}

template < typename SelType, typename LevelType >
SelectionManagement< SelType, LevelType >::~SelectionManagement()
{
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::init( Trace *trace )
{
  selected.clear();
  selectedSet.clear();

  std::vector< bool > auxSelected;

  for ( PRV_UINT32 level = ( PRV_UINT32 )NONE; level <= ( PRV_UINT32 )CPU; ++level )
  {
    auxSelected.clear();
    selected.push_back( std::vector< bool >( ) );
    selectedSet.push_back( std::vector< TObjectOrder >( ) );

    switch ( level )
    {
      case APPLICATION:
        auxSelected.insert( auxSelected.begin(),
                            ( size_t ) trace->totalApplications(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

      case TASK:
        auxSelected.insert( auxSelected.begin(),
                            ( size_t ) trace->totalTasks(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

      case THREAD:
        auxSelected.insert( auxSelected.begin(),
                            ( size_t ) trace->totalThreads(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

      case NODE:
        auxSelected.insert( auxSelected.begin(),
                            trace->totalNodes(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

      case CPU:
        auxSelected.insert( auxSelected.begin(),
                            trace->totalCPUs(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

//    NONE, WORKLOAD, SYSTEM
      default:
        auxSelected.insert( auxSelected.begin(),
                            1,
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;
    }
  }
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::init( HistogramTotals *totals,
    PRV_UINT16 idStat,
    THistogramColumn numColumns,
    THistogramColumn whichPlane )
{
  selected.clear();
  selectedSet.clear();

  selected.push_back( std::vector< bool >( ) );
  selectedSet.push_back( std::vector< SelType >( ) );

  std::vector< bool > auxSelected;
  for ( THistogramColumn i = 0; i < numColumns; ++i )
  {
    if ( totals->getTotal( idStat, i, whichPlane ) == 0 )
      auxSelected.push_back( false );
    else
      auxSelected.push_back( true );
  }

  setSelected( auxSelected, 0 );
}

template < typename SelType, typename LevelType >
void SelectionManagement<SelType, LevelType>::copy( const SelectionManagement &whichSelection )
{
  selected = whichSelection.selected;
  selectedSet = whichSelection.selectedSet;
}

template < typename SelType, typename LevelType >
bool SelectionManagement<SelType, LevelType>:: operator== ( const SelectionManagement<SelType, LevelType> &whichSelection ) const
{
  bool equal = false;

  if ( selected.size()    == whichSelection.selected.size() &&
       selectedSet.size() == whichSelection.selectedSet.size() )
  {
    std::vector< std::vector< bool > >::const_iterator it1 = whichSelection.selected.begin();
    for ( std::vector< std::vector< bool > >::const_iterator it2 = selected.begin(); it2 != selected.end(); ++it2 )
    {
      equal = std::equal( (*it1).begin(), (*it1).end(), (*it2).begin() );
      if ( !equal )
      {
        break;
      }
      else
      {
        ++it1;
      }
    }

    if ( equal )
    {
      for ( size_t i = 0 ; i < selectedSet.size(); ++i ) // O( selected.size() )
      {
        equal = whichSelection.selectedSet[ i ].size() == selectedSet[ i ].size();
        if ( !equal )
        {
          break;
        }
      }

      if ( equal ) // O( selected.size() * num_elems )
      {
        for ( size_t i = 0 ; i < selectedSet.size(); ++i )
        {
          equal = std::equal( selectedSet[ i ].begin(), selectedSet[ i ].end(), whichSelection.selectedSet[ i ].begin() );
          if ( !equal )
          {
            break;
          }
        }
      }
    }
  }

  return equal;
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::setSelected( std::vector< bool > &selection, LevelType level )
{
  selectedSet[ level ].clear();
  if ( selected[ level ].size() >= selection.size() )
  {
    std::copy( selection.begin(), selection.end(), selected[ level ].begin() );
  }
  else
  {
    size_t size = selected[ level ].size();
    if ( size > 0 )
      selected[ level ].resize( size );
    selected[ level ] = selection;
  }

  if ( !selected[ level ].empty() )
  {
    for ( size_t current = 0; current < selected[ level ].size(); ++current )
    {
      if ( selected[ level ][ current ] )
        selectedSet[ level ].push_back( current );
    }
  }
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::setSelected( std::vector< SelType > &selection,
    SelType maxElems,
    LevelType level )
{
  // Prepare vectors for update
  selected[ level ].clear();
  selectedSet[ level ] = selection;

  typename std::vector<SelType>::iterator it;

  // Delete any SelType greater than maxElems ( number of level objects)
  it = std::find_if( selectedSet[ level ].begin(),
                     selectedSet[ level ].end(),
                     std::bind2nd( std::greater_equal<SelType>(), maxElems ) );
  if ( it != selectedSet[ level ].end() )
    selectedSet[ level ].erase( it, selectedSet[ level ].end() );

  // Any reamining row?
  if ( !selectedSet[ level ].empty() )
  {
    it = selectedSet[ level ].begin();
    for ( size_t current = 0; current < ( size_t ) maxElems; ++current )
    {
      if ( it != selectedSet[level].end() && current == ( size_t )*it )
      {
        selected[ level ].push_back( true );
        ++it;
      }
      else
      {
        selected[ level ].push_back( false );
      }
    }
  }
}

template < typename SelType, typename LevelType >
bool SelectionManagement< SelType, LevelType >::isSelectedPosition( SelType whichSelected,
    LevelType level ) const
{
  return selected[ level ][ whichSelected ];
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::getSelected( std::vector< bool > &whichSelected,
    LevelType level )
{
  whichSelected = selected[ level ];
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::getSelected( std::vector< bool > &whichSelected,
    SelType first,
    SelType last,
    LevelType level )
{
  whichSelected.clear();

  for ( SelType i = first; i <= last; ++ i )
    whichSelected.push_back( ( selected[ level ] )[ i ] );
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::getSelected( std::vector< SelType > &whichSelected,
    LevelType level )
{
  whichSelected = selectedSet[ level ];
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::getSelected( std::vector< SelType > &whichSelected,
    SelType first,
    SelType last,
    LevelType level )
{
  whichSelected.clear();
  typename std::vector< SelType >::iterator it;
  for ( it = selectedSet[ level ].begin(); it != selectedSet[ level ].end(); ++it )
  {
    if ( ( *it >= first ) && ( *it <= last ) )
      whichSelected.push_back( *it );
    if ( *it == last )
      break;
  }
}

template < typename SelType, typename LevelType >
SelType SelectionManagement< SelType, LevelType >::shiftFirst( SelType whichFirst, PRV_INT64 shiftAmount, LevelType level ) const
{
  const typename std::vector<SelType>& tmpSelectedSet = selectedSet[ level ];
  const std::vector<bool>& tmpSelected = selected[ level ];

  if( whichFirst >= tmpSelected.size() )
    throw ParaverKernelException( ParaverKernelException::indexOutOfRange );

  SelType iFirst = 0;
  if( tmpSelected.size() == tmpSelectedSet.size() )
  {
    iFirst = whichFirst;
  }
  else
  {
    while( whichFirst < tmpSelectedSet[ iFirst ] )
    {
      ++iFirst;
      if( iFirst >= tmpSelectedSet.size() )
      {
        iFirst = tmpSelectedSet.size() - 1;
        break;
      }
    }
  }

  if( (PRV_INT64)iFirst + shiftAmount < 0 )
    return tmpSelectedSet[ 0 ];
  else if( (PRV_INT64)iFirst + shiftAmount >= tmpSelected.size() )
    return tmpSelectedSet[ tmpSelectedSet.size() - 1 ];

  return tmpSelectedSet[ iFirst + shiftAmount ];
}

template < typename SelType, typename LevelType >
SelType SelectionManagement< SelType, LevelType >::shiftLast( SelType whichLast, PRV_INT64 shiftAmount, LevelType level ) const
{
  const typename std::vector<SelType>& tmpSelectedSet = selectedSet[ level ];
  const std::vector<bool>& tmpSelected = selected[ level ];

  if( whichLast >= tmpSelected.size() )
    throw ParaverKernelException( ParaverKernelException::indexOutOfRange );

  SelType iLast = tmpSelectedSet.size() - 1;
  if( tmpSelected.size() == tmpSelectedSet.size() )
  {
    iLast = whichLast;
  }
  else
  {
    while( whichLast > tmpSelectedSet[ iLast ] )
    {
      --iLast;
      if( iLast == 0 )
      {
        break;
      }
    }
  }

  if( (PRV_INT64)iLast + shiftAmount < 0 )
    return tmpSelectedSet[ 0 ];
  else if( (PRV_INT64)iLast + shiftAmount >= tmpSelectedSet.size() )
    return tmpSelectedSet[ tmpSelectedSet.size() - 1 ];

  return tmpSelectedSet[ iLast + shiftAmount ];
}
<commit_msg>Shift first/last search fixed<commit_after>/*****************************************************************************\
 *                        ANALYSIS PERFORMANCE TOOLS                         *
 *                               libparaver-api                              *
 *                      API Library for libparaver-kernel                    *
 *****************************************************************************
 *     ___     This library is free software; you can redistribute it and/or *
 *    /  __         modify it under the terms of the GNU LGPL as published   *
 *   /  /  _____    by the Free Software Foundation; either version 2.1      *
 *  /  /  /     \   of the License, or (at your option) any later version.   *
 * (  (  ( B S C )                                                           *
 *  \  \  \_____/   This library is distributed in 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 LGPL 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA          *
 * The GNU LEsser General Public License is contained in the file COPYING.   *
 *                                 ---------                                 *
 *   Barcelona Supercomputing Center - Centro Nacional de Supercomputacion   *
\*****************************************************************************/

/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *\
 | @file: $HeadURL$
 | @last_commit: $Date$
 | @version:     $Revision$
\* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */

#include <algorithm>
#include <functional>
#include "trace.h"
#include "histogramtotals.h"
#include "paraverkernelexception.h"

template < typename SelType, typename LevelType >
SelectionManagement< SelType, LevelType >::SelectionManagement()
{
}

template < typename SelType, typename LevelType >
SelectionManagement< SelType, LevelType >::SelectionManagement( const SelectionManagement& whichSelection )
{
  for ( size_t i = 0 ; i < whichSelection.selectedSet.size(); ++i )
  {
    selectedSet.push_back( whichSelection.selectedSet[ i ] );
  }
  for ( size_t i = 0 ; i < whichSelection.selected.size(); ++i )
  {
    selected.push_back( whichSelection.selected[ i ] );
  }
}

template < typename SelType, typename LevelType >
SelectionManagement< SelType, LevelType >::~SelectionManagement()
{
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::init( Trace *trace )
{
  selected.clear();
  selectedSet.clear();

  std::vector< bool > auxSelected;

  for ( PRV_UINT32 level = ( PRV_UINT32 )NONE; level <= ( PRV_UINT32 )CPU; ++level )
  {
    auxSelected.clear();
    selected.push_back( std::vector< bool >( ) );
    selectedSet.push_back( std::vector< TObjectOrder >( ) );

    switch ( level )
    {
      case APPLICATION:
        auxSelected.insert( auxSelected.begin(),
                            ( size_t ) trace->totalApplications(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

      case TASK:
        auxSelected.insert( auxSelected.begin(),
                            ( size_t ) trace->totalTasks(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

      case THREAD:
        auxSelected.insert( auxSelected.begin(),
                            ( size_t ) trace->totalThreads(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

      case NODE:
        auxSelected.insert( auxSelected.begin(),
                            trace->totalNodes(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

      case CPU:
        auxSelected.insert( auxSelected.begin(),
                            trace->totalCPUs(),
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;

//    NONE, WORKLOAD, SYSTEM
      default:
        auxSelected.insert( auxSelected.begin(),
                            1,
                            true );
        setSelected( auxSelected, ( TWindowLevel )level );
        break;
    }
  }
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::init( HistogramTotals *totals,
    PRV_UINT16 idStat,
    THistogramColumn numColumns,
    THistogramColumn whichPlane )
{
  selected.clear();
  selectedSet.clear();

  selected.push_back( std::vector< bool >( ) );
  selectedSet.push_back( std::vector< SelType >( ) );

  std::vector< bool > auxSelected;
  for ( THistogramColumn i = 0; i < numColumns; ++i )
  {
    if ( totals->getTotal( idStat, i, whichPlane ) == 0 )
      auxSelected.push_back( false );
    else
      auxSelected.push_back( true );
  }

  setSelected( auxSelected, 0 );
}

template < typename SelType, typename LevelType >
void SelectionManagement<SelType, LevelType>::copy( const SelectionManagement &whichSelection )
{
  selected = whichSelection.selected;
  selectedSet = whichSelection.selectedSet;
}

template < typename SelType, typename LevelType >
bool SelectionManagement<SelType, LevelType>:: operator== ( const SelectionManagement<SelType, LevelType> &whichSelection ) const
{
  bool equal = false;

  if ( selected.size()    == whichSelection.selected.size() &&
       selectedSet.size() == whichSelection.selectedSet.size() )
  {
    std::vector< std::vector< bool > >::const_iterator it1 = whichSelection.selected.begin();
    for ( std::vector< std::vector< bool > >::const_iterator it2 = selected.begin(); it2 != selected.end(); ++it2 )
    {
      equal = std::equal( (*it1).begin(), (*it1).end(), (*it2).begin() );
      if ( !equal )
      {
        break;
      }
      else
      {
        ++it1;
      }
    }

    if ( equal )
    {
      for ( size_t i = 0 ; i < selectedSet.size(); ++i ) // O( selected.size() )
      {
        equal = whichSelection.selectedSet[ i ].size() == selectedSet[ i ].size();
        if ( !equal )
        {
          break;
        }
      }

      if ( equal ) // O( selected.size() * num_elems )
      {
        for ( size_t i = 0 ; i < selectedSet.size(); ++i )
        {
          equal = std::equal( selectedSet[ i ].begin(), selectedSet[ i ].end(), whichSelection.selectedSet[ i ].begin() );
          if ( !equal )
          {
            break;
          }
        }
      }
    }
  }

  return equal;
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::setSelected( std::vector< bool > &selection, LevelType level )
{
  selectedSet[ level ].clear();
  if ( selected[ level ].size() >= selection.size() )
  {
    std::copy( selection.begin(), selection.end(), selected[ level ].begin() );
  }
  else
  {
    size_t size = selected[ level ].size();
    if ( size > 0 )
      selected[ level ].resize( size );
    selected[ level ] = selection;
  }

  if ( !selected[ level ].empty() )
  {
    for ( size_t current = 0; current < selected[ level ].size(); ++current )
    {
      if ( selected[ level ][ current ] )
        selectedSet[ level ].push_back( current );
    }
  }
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::setSelected( std::vector< SelType > &selection,
    SelType maxElems,
    LevelType level )
{
  // Prepare vectors for update
  selected[ level ].clear();
  selectedSet[ level ] = selection;

  typename std::vector<SelType>::iterator it;

  // Delete any SelType greater than maxElems ( number of level objects)
  it = std::find_if( selectedSet[ level ].begin(),
                     selectedSet[ level ].end(),
                     std::bind2nd( std::greater_equal<SelType>(), maxElems ) );
  if ( it != selectedSet[ level ].end() )
    selectedSet[ level ].erase( it, selectedSet[ level ].end() );

  // Any reamining row?
  if ( !selectedSet[ level ].empty() )
  {
    it = selectedSet[ level ].begin();
    for ( size_t current = 0; current < ( size_t ) maxElems; ++current )
    {
      if ( it != selectedSet[level].end() && current == ( size_t )*it )
      {
        selected[ level ].push_back( true );
        ++it;
      }
      else
      {
        selected[ level ].push_back( false );
      }
    }
  }
}

template < typename SelType, typename LevelType >
bool SelectionManagement< SelType, LevelType >::isSelectedPosition( SelType whichSelected,
    LevelType level ) const
{
  return selected[ level ][ whichSelected ];
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::getSelected( std::vector< bool > &whichSelected,
    LevelType level )
{
  whichSelected = selected[ level ];
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::getSelected( std::vector< bool > &whichSelected,
    SelType first,
    SelType last,
    LevelType level )
{
  whichSelected.clear();

  for ( SelType i = first; i <= last; ++ i )
    whichSelected.push_back( ( selected[ level ] )[ i ] );
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::getSelected( std::vector< SelType > &whichSelected,
    LevelType level )
{
  whichSelected = selectedSet[ level ];
}

template < typename SelType, typename LevelType >
void SelectionManagement< SelType, LevelType >::getSelected( std::vector< SelType > &whichSelected,
    SelType first,
    SelType last,
    LevelType level )
{
  whichSelected.clear();
  typename std::vector< SelType >::iterator it;
  for ( it = selectedSet[ level ].begin(); it != selectedSet[ level ].end(); ++it )
  {
    if ( ( *it >= first ) && ( *it <= last ) )
      whichSelected.push_back( *it );
    if ( *it == last )
      break;
  }
}

template < typename SelType, typename LevelType >
SelType SelectionManagement< SelType, LevelType >::shiftFirst( SelType whichFirst, PRV_INT64 shiftAmount, LevelType level ) const
{
  const typename std::vector<SelType>& tmpSelectedSet = selectedSet[ level ];
  const std::vector<bool>& tmpSelected = selected[ level ];

  if( whichFirst >= tmpSelected.size() )
    throw ParaverKernelException( ParaverKernelException::indexOutOfRange );

  SelType iFirst = 0;
  if( tmpSelected.size() == tmpSelectedSet.size() )
  {
    iFirst = whichFirst;
  }
  else
  {
    while( whichFirst > tmpSelectedSet[ iFirst ] )
    {
      ++iFirst;
      if( iFirst >= tmpSelectedSet.size() )
      {
        iFirst = tmpSelectedSet.size() - 1;
        break;
      }
    }
  }

  if( (PRV_INT64)iFirst + shiftAmount < 0 )
    return tmpSelectedSet[ 0 ];
  else if( (PRV_INT64)iFirst + shiftAmount >= tmpSelected.size() )
    return tmpSelectedSet[ tmpSelectedSet.size() - 1 ];

  return tmpSelectedSet[ iFirst + shiftAmount ];
}

template < typename SelType, typename LevelType >
SelType SelectionManagement< SelType, LevelType >::shiftLast( SelType whichLast, PRV_INT64 shiftAmount, LevelType level ) const
{
  const typename std::vector<SelType>& tmpSelectedSet = selectedSet[ level ];
  const std::vector<bool>& tmpSelected = selected[ level ];

  if( whichLast >= tmpSelected.size() )
    throw ParaverKernelException( ParaverKernelException::indexOutOfRange );

  SelType iLast = tmpSelectedSet.size() - 1;
  if( tmpSelected.size() == tmpSelectedSet.size() )
  {
    iLast = whichLast;
  }
  else
  {
    while( whichLast < tmpSelectedSet[ iLast ] )
    {
      --iLast;
      if( iLast == 0 )
      {
        break;
      }
    }
  }

  if( (PRV_INT64)iLast + shiftAmount < 0 )
    return tmpSelectedSet[ 0 ];
  else if( (PRV_INT64)iLast + shiftAmount >= tmpSelectedSet.size() )
    return tmpSelectedSet[ tmpSelectedSet.size() - 1 ];

  return tmpSelectedSet[ iLast + shiftAmount ];
}
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2017 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include "tests/unit-tests/AbstractSyncAsyncTest.cpp"

#include <string>

#include <gmock/gmock.h>

#include "joynr/tests/testJoynrMessagingConnector.h"
#include "joynr/IReplyCaller.h"
#include "joynr/ISubscriptionCallback.h"
#include "joynr/MulticastSubscriptionQos.h"
#include "joynr/SingleThreadedIOService.h"
#include "joynr/types/DiscoveryEntryWithMetaInfo.h"

#include "tests/JoynrTest.h"
#include "tests/mock/MockSubscriptionManager.h"
#include "tests/mock/MockGpsFloatSubscriptionListener.h"

using ::testing::A;
using ::testing::_;
using ::testing::Return;
using ::testing::Eq;
using ::testing::NotNull;
using ::testing::AllOf;
using ::testing::Property;
using ::testing::Invoke;
using ::testing::Unused;

using namespace joynr;

/**
 * @brief Fixutre.
 */
class TestJoynrMessagingConnectorTest : public AbstractSyncAsyncTest {
public:

    TestJoynrMessagingConnectorTest():
        singleThreadedIOService(std::make_shared<SingleThreadedIOService>()),
        mockSubscriptionManager(std::make_shared<MockSubscriptionManager>(singleThreadedIOService->getIOService(), nullptr)),
        gpsLocation(types::Localisation::GpsLocation(
                        9.0,
                        51.0,
                        508.0,
                        types::Localisation::GpsFixEnum::MODE2D,
                        0.0,
                        0.0,
                        0.0,
                        0.0,
                        444,
                        444,
                        2)),
        floatValue(123.45),
        semaphore(0)
    {
        singleThreadedIOService->start();
    }

    // sets the expectations on the call expected on the MessageSender from the connector
    testing::internal::TypedExpectation<void(
            const std::string&, // sender participant ID
            const std::string&, // receiver participant ID
            const MessagingQos&, // messaging QoS
            const Request&, // request object to send
            std::shared_ptr<IReplyCaller>, // reply caller to notify when reply is received
            bool isLocalMessage
    )>& setExpectationsForSendRequestCall(std::string methodName) override {
        return EXPECT_CALL(
                    *mockMessageSender,
                    sendRequest(
                        Eq(proxyParticipantId), // sender participant ID
                        Eq(providerParticipantId), // receiver participant ID
                        _, // messaging QoS
                        Property(&Request::getMethodName, Eq(methodName)), // request object to send
                        Property(&std::shared_ptr<IReplyCaller>::get,NotNull()), // reply caller to notify when reply is received
                        _ // isLocalMessage flag
                    )
        );
    }

    std::shared_ptr<SingleThreadedIOService> singleThreadedIOService;
    std::shared_ptr<MockSubscriptionManager> mockSubscriptionManager;
    joynr::types::Localisation::GpsLocation gpsLocation;
    float floatValue;
    Semaphore semaphore;

    std::shared_ptr<tests::testJoynrMessagingConnector> createConnector() {
        types::DiscoveryEntryWithMetaInfo discoveryEntry;

        discoveryEntry.setParticipantId(providerParticipantId);
        discoveryEntry.setIsLocal(false);

        return std::make_shared<tests::testJoynrMessagingConnector>(
                    mockMessageSender,
                    mockSubscriptionManager,
                    "myDomain",
                    proxyParticipantId,
                    MessagingQos(),
                    discoveryEntry);
    }

    std::shared_ptr<tests::Itest> createFixture() override {
        return std::dynamic_pointer_cast<tests::Itest>(createConnector());
    }

    void invokeMulticastSubscriptionCallback(const std::string& subscribeToName,
                                             const std::string& subscriberParticipantId,
                                             const std::string& providerParticipantId,
                                             const std::vector<std::string>& partitions,
                                             std::shared_ptr<joynr::ISubscriptionCallback> subscriptionCaller,
                                             std::shared_ptr<ISubscriptionListenerBase> subscriptionListener,
                                             std::shared_ptr<joynr::SubscriptionQos> qos,
                                             joynr::MulticastSubscriptionRequest& subscriptionRequest,
                                             std::function<void()> onSuccess,
                                             std::function<void(const joynr::exceptions::ProviderRuntimeException&)> onError) {
        std::ignore = subscribeToName;
        std::ignore = subscriberParticipantId;
        std::ignore = providerParticipantId;
        std::ignore = partitions;
        std::ignore = subscriptionCaller;
        std::ignore = onSuccess;
        std::ignore = onError;
        subscriptionRequest.setQos(qos);
        std::shared_ptr<ISubscriptionListener<joynr::types::Localisation::GpsLocation, float>> typedListener =
                std::dynamic_pointer_cast<ISubscriptionListener<joynr::types::Localisation::GpsLocation, float>>(subscriptionListener);

        typedListener->onReceive(gpsLocation, floatValue);
    }
};

typedef TestJoynrMessagingConnectorTest TestJoynrMessagingConnectorTestDeathTest;

/*
 * Tests
 */

TEST_F(TestJoynrMessagingConnectorTest, async_getAttributeNotCached) {
    testAsync_getAttributeNotCached();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_setAttributeNotCached) {
    testSync_setAttributeNotCached();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_getAttributeNotCached) {
    testSync_getAttributeNotCached();
}

TEST_F(TestJoynrMessagingConnectorTest, async_getterCallReturnsProviderRuntimeException) {
    testAsync_getterCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_getterCallReturnsProviderRuntimeException) {
    testSync_getterCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_getterCallReturnsMethodInvocationException) {
    testAsync_getterCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_getterCallReturnsMethodInvocationException) {
    testSync_getterCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_setterCallReturnsProviderRuntimeException) {
    testAsync_setterCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_setterCallReturnsProviderRuntimeException) {
    testSync_setterCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_setterCallReturnsMethodInvocationException) {
    testAsync_setterCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_setterCallReturnsMethodInvocationException) {
    testSync_setterCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsProviderRuntimeException) {
    testAsync_methodCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsProviderRuntimeException) {
    testSync_methodCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsMethodInvocationException) {
    testAsync_methodCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsMethodInvocationException) {
    testSync_methodCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsErrorEnum) {
    testAsync_methodCallReturnsErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsErrorEnum) {
    testSync_methodCallReturnsErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsExtendedErrorEnum) {
    testAsync_methodCallReturnsExtendedErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsExtendedErrorEnum) {
    testSync_methodCallReturnsExtendedErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsInlineErrorEnum) {
    testAsync_methodCallReturnsInlineErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsInlineErrorEnum) {
    testSync_methodCallReturnsInlineErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, async_OperationWithNoArguments) {
    testAsync_OperationWithNoArguments();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_OperationWithNoArguments) {
    testSync_OperationWithNoArguments();
}

TEST_F(TestJoynrMessagingConnectorTest, subscribeToAttribute) {
    testSubscribeToAttribute();
}

TEST_F(TestJoynrMessagingConnectorTest, testBroadcastListenerWrapper) {
    std::shared_ptr<tests::testJoynrMessagingConnector> connector (createConnector());

    auto mockListener = std::make_shared<MockGpsFloatSubscriptionListener>();

    EXPECT_CALL(
        *mockSubscriptionManager,
        registerSubscription(
            Eq("locationUpdateWithSpeed"), //subscribeToName
            _, // subscriberParticipantId
            _, // providerParticipantId
            _, // partitions
            _, // subscriptionCaller
            _, // subscriptionListener
            _, // messaging QoS
            _, // subscriptionRequest
            _, // onSuccess
            _ // onError
        )
    ).WillOnce(
            testing::Invoke(this, &TestJoynrMessagingConnectorTest::invokeMulticastSubscriptionCallback)
    );

    // Use a semaphore to count and wait on calls to the mock listener
    EXPECT_CALL(*mockListener, onReceive(Eq(gpsLocation), Eq(floatValue)))
            .WillOnce(ReleaseSemaphore(&semaphore));

    auto qos = std::make_shared<MulticastSubscriptionQos>();
    connector->subscribeToLocationUpdateWithSpeedBroadcast(mockListener, qos);

    // Wait for a subscription message to arrive
    ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(2)));
    EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(mockSubscriptionManager.get()));
}
<commit_msg>[C++] Stop SingleThreadedIOService in TestJoynrMessagingConnectorTest<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2017 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include "tests/unit-tests/AbstractSyncAsyncTest.cpp"

#include <string>

#include <gmock/gmock.h>

#include "joynr/tests/testJoynrMessagingConnector.h"
#include "joynr/IReplyCaller.h"
#include "joynr/ISubscriptionCallback.h"
#include "joynr/MulticastSubscriptionQos.h"
#include "joynr/SingleThreadedIOService.h"
#include "joynr/types/DiscoveryEntryWithMetaInfo.h"

#include "tests/JoynrTest.h"
#include "tests/mock/MockSubscriptionManager.h"
#include "tests/mock/MockGpsFloatSubscriptionListener.h"

using ::testing::A;
using ::testing::_;
using ::testing::Return;
using ::testing::Eq;
using ::testing::NotNull;
using ::testing::AllOf;
using ::testing::Property;
using ::testing::Invoke;
using ::testing::Unused;

using namespace joynr;

/**
 * @brief Fixutre.
 */
class TestJoynrMessagingConnectorTest : public AbstractSyncAsyncTest {
public:

    TestJoynrMessagingConnectorTest():
        singleThreadedIOService(std::make_shared<SingleThreadedIOService>()),
        mockSubscriptionManager(std::make_shared<MockSubscriptionManager>(singleThreadedIOService->getIOService(), nullptr)),
        gpsLocation(types::Localisation::GpsLocation(
                        9.0,
                        51.0,
                        508.0,
                        types::Localisation::GpsFixEnum::MODE2D,
                        0.0,
                        0.0,
                        0.0,
                        0.0,
                        444,
                        444,
                        2)),
        floatValue(123.45),
        semaphore(0)
    {
        singleThreadedIOService->start();
    }

    ~TestJoynrMessagingConnectorTest() {
        singleThreadedIOService->stop();
    }

    // sets the expectations on the call expected on the MessageSender from the connector
    testing::internal::TypedExpectation<void(
            const std::string&, // sender participant ID
            const std::string&, // receiver participant ID
            const MessagingQos&, // messaging QoS
            const Request&, // request object to send
            std::shared_ptr<IReplyCaller>, // reply caller to notify when reply is received
            bool isLocalMessage
    )>& setExpectationsForSendRequestCall(std::string methodName) override {
        return EXPECT_CALL(
                    *mockMessageSender,
                    sendRequest(
                        Eq(proxyParticipantId), // sender participant ID
                        Eq(providerParticipantId), // receiver participant ID
                        _, // messaging QoS
                        Property(&Request::getMethodName, Eq(methodName)), // request object to send
                        Property(&std::shared_ptr<IReplyCaller>::get,NotNull()), // reply caller to notify when reply is received
                        _ // isLocalMessage flag
                    )
        );
    }

    std::shared_ptr<SingleThreadedIOService> singleThreadedIOService;
    std::shared_ptr<MockSubscriptionManager> mockSubscriptionManager;
    joynr::types::Localisation::GpsLocation gpsLocation;
    float floatValue;
    Semaphore semaphore;

    std::shared_ptr<tests::testJoynrMessagingConnector> createConnector() {
        types::DiscoveryEntryWithMetaInfo discoveryEntry;

        discoveryEntry.setParticipantId(providerParticipantId);
        discoveryEntry.setIsLocal(false);

        return std::make_shared<tests::testJoynrMessagingConnector>(
                    mockMessageSender,
                    mockSubscriptionManager,
                    "myDomain",
                    proxyParticipantId,
                    MessagingQos(),
                    discoveryEntry);
    }

    std::shared_ptr<tests::Itest> createFixture() override {
        return std::dynamic_pointer_cast<tests::Itest>(createConnector());
    }

    void invokeMulticastSubscriptionCallback(const std::string& subscribeToName,
                                             const std::string& subscriberParticipantId,
                                             const std::string& providerParticipantId,
                                             const std::vector<std::string>& partitions,
                                             std::shared_ptr<joynr::ISubscriptionCallback> subscriptionCaller,
                                             std::shared_ptr<ISubscriptionListenerBase> subscriptionListener,
                                             std::shared_ptr<joynr::SubscriptionQos> qos,
                                             joynr::MulticastSubscriptionRequest& subscriptionRequest,
                                             std::function<void()> onSuccess,
                                             std::function<void(const joynr::exceptions::ProviderRuntimeException&)> onError) {
        std::ignore = subscribeToName;
        std::ignore = subscriberParticipantId;
        std::ignore = providerParticipantId;
        std::ignore = partitions;
        std::ignore = subscriptionCaller;
        std::ignore = onSuccess;
        std::ignore = onError;
        subscriptionRequest.setQos(qos);
        std::shared_ptr<ISubscriptionListener<joynr::types::Localisation::GpsLocation, float>> typedListener =
                std::dynamic_pointer_cast<ISubscriptionListener<joynr::types::Localisation::GpsLocation, float>>(subscriptionListener);

        typedListener->onReceive(gpsLocation, floatValue);
    }
};

typedef TestJoynrMessagingConnectorTest TestJoynrMessagingConnectorTestDeathTest;

/*
 * Tests
 */

TEST_F(TestJoynrMessagingConnectorTest, async_getAttributeNotCached) {
    testAsync_getAttributeNotCached();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_setAttributeNotCached) {
    testSync_setAttributeNotCached();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_getAttributeNotCached) {
    testSync_getAttributeNotCached();
}

TEST_F(TestJoynrMessagingConnectorTest, async_getterCallReturnsProviderRuntimeException) {
    testAsync_getterCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_getterCallReturnsProviderRuntimeException) {
    testSync_getterCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_getterCallReturnsMethodInvocationException) {
    testAsync_getterCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_getterCallReturnsMethodInvocationException) {
    testSync_getterCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_setterCallReturnsProviderRuntimeException) {
    testAsync_setterCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_setterCallReturnsProviderRuntimeException) {
    testSync_setterCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_setterCallReturnsMethodInvocationException) {
    testAsync_setterCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_setterCallReturnsMethodInvocationException) {
    testSync_setterCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsProviderRuntimeException) {
    testAsync_methodCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsProviderRuntimeException) {
    testSync_methodCallReturnsProviderRuntimeException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsMethodInvocationException) {
    testAsync_methodCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsMethodInvocationException) {
    testSync_methodCallReturnsMethodInvocationException();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsErrorEnum) {
    testAsync_methodCallReturnsErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsErrorEnum) {
    testSync_methodCallReturnsErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsExtendedErrorEnum) {
    testAsync_methodCallReturnsExtendedErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsExtendedErrorEnum) {
    testSync_methodCallReturnsExtendedErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, async_methodCallReturnsInlineErrorEnum) {
    testAsync_methodCallReturnsInlineErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_methodCallReturnsInlineErrorEnum) {
    testSync_methodCallReturnsInlineErrorEnum();
}

TEST_F(TestJoynrMessagingConnectorTest, async_OperationWithNoArguments) {
    testAsync_OperationWithNoArguments();
}

TEST_F(TestJoynrMessagingConnectorTest, sync_OperationWithNoArguments) {
    testSync_OperationWithNoArguments();
}

TEST_F(TestJoynrMessagingConnectorTest, subscribeToAttribute) {
    testSubscribeToAttribute();
}

TEST_F(TestJoynrMessagingConnectorTest, testBroadcastListenerWrapper) {
    std::shared_ptr<tests::testJoynrMessagingConnector> connector (createConnector());

    auto mockListener = std::make_shared<MockGpsFloatSubscriptionListener>();

    EXPECT_CALL(
        *mockSubscriptionManager,
        registerSubscription(
            Eq("locationUpdateWithSpeed"), //subscribeToName
            _, // subscriberParticipantId
            _, // providerParticipantId
            _, // partitions
            _, // subscriptionCaller
            _, // subscriptionListener
            _, // messaging QoS
            _, // subscriptionRequest
            _, // onSuccess
            _ // onError
        )
    ).WillOnce(
            testing::Invoke(this, &TestJoynrMessagingConnectorTest::invokeMulticastSubscriptionCallback)
    );

    // Use a semaphore to count and wait on calls to the mock listener
    EXPECT_CALL(*mockListener, onReceive(Eq(gpsLocation), Eq(floatValue)))
            .WillOnce(ReleaseSemaphore(&semaphore));

    auto qos = std::make_shared<MulticastSubscriptionQos>();
    connector->subscribeToLocationUpdateWithSpeedBroadcast(mockListener, qos);

    // Wait for a subscription message to arrive
    ASSERT_TRUE(semaphore.waitFor(std::chrono::seconds(2)));
    EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(mockSubscriptionManager.get()));
}
<|endoftext|>


<commit_before>
#include <iostream>
using namespace std;

void func1()
{
	cout << "func1" << endl;
}

void func2()
{
	cout << "func2" << endl;
}

void main()
{

	cout << "Hello World" << endl;

	func1();
	func2();

}
<commit_msg>update func3<commit_after>
#include <iostream>
using namespace std;

void func1()
{
	cout << "func1" << endl;
}

void func2()
{
	cout << "func2" << endl;
}

void func3()
{
	cout << "func3" << endl;
}

void main()
{

	cout << "Hello World" << endl;

	func1();
	func2();
	func3();

}
<|endoftext|>