<commit_before>// Copyright (c) 2006-2008 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 "webkit/glue/resource_fetcher.h"

#include "base/callback.h"
#include "base/message_loop.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
#include "webkit/glue/unittest_test_server.h"
#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
#include "webkit/tools/test_shell/test_shell_test.h"

#if defined(TOOLKIT_USES_GTK)
#include <gtk/gtk.h>
#endif

using WebKit::WebFrame;
using WebKit::WebURLResponse;
using webkit_glue::ResourceFetcher;
using webkit_glue::ResourceFetcherWithTimeout;

namespace {

class ResourceFetcherTests : public TestShellTest {
 protected:
  UnittestTestServer test_server_;
};

static const int kMaxWaitTimeMs = 5000;
static const int kWaitIntervalMs = 100;

class FetcherDelegate {
 public:
  FetcherDelegate()
      : timer_id_(0), completed_(false), time_elapsed_ms_(0) {
    // Start a repeating timer waiting for the download to complete.  The
    // callback has to be a static function, so we hold on to our instance.
    FetcherDelegate::instance_ = this;
    CreateTimer(kWaitIntervalMs);
  }

  ResourceFetcher::Callback* NewCallback() {
    return ::NewCallback(this, &FetcherDelegate::OnURLFetchComplete);
  }

  void OnURLFetchComplete(const WebURLResponse& response,
                          const std::string& data) {
    response_ = response;
    data_ = data;
    completed_ = true;
    DestroyTimer();
    MessageLoop::current()->Quit();
  }

  bool completed() const { return completed_; }
  bool timed_out() const { return time_elapsed_ms_ > kMaxWaitTimeMs; }

  int time_elapsed_ms() const { return time_elapsed_ms_; }
  std::string data() const { return data_; }
  const WebURLResponse& response() const { return response_; }

  // Wait for the request to complete or timeout.  We use a loop here b/c the
  // testing infrastructure (test_shell) can generate spurious calls to the
  // MessageLoop's Quit method.
  void WaitForResponse() {
    while (!completed() && !timed_out())
      MessageLoop::current()->Run();
  }

  void CreateTimer(int interval) {
#if defined(OS_WIN)
    timer_id_ = ::SetTimer(NULL, NULL, interval,
                           &FetcherDelegate::TimerCallback);
#elif defined(TOOLKIT_USES_GTK)
    timer_id_ = g_timeout_add(interval, &FetcherDelegate::TimerCallback, NULL);
#elif defined(OS_MACOSX)
    // CFAbsoluteTime is in seconds and |interval| is in ms, so make sure we
    // keep the units correct.
    CFTimeInterval interval_in_seconds = static_cast<double>(interval) / 1000.0;
    CFAbsoluteTime fire_date =
        CFAbsoluteTimeGetCurrent() + interval_in_seconds;
    timer_id_ = CFRunLoopTimerCreate(NULL, fire_date, interval_in_seconds, 0,
                                     0, FetcherDelegate::TimerCallback, NULL);
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer_id_, kCFRunLoopCommonModes);
#endif
  }

  void DestroyTimer() {
#if defined(OS_WIN)
    ::KillTimer(NULL, timer_id_);
#elif defined(TOOLKIT_USES_GTK)
    g_source_remove(timer_id_);
#elif defined(OS_MACOSX)
    CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), timer_id_,
                         kCFRunLoopCommonModes);
    CFRelease(timer_id_);
#endif
  }

#if defined(OS_WIN)
  // Static timer callback, just passes through to instance version.
  static VOID CALLBACK TimerCallback(HWND hwnd, UINT msg, UINT_PTR timer_id,
                                     DWORD ms) {
    instance_->TimerFired();
  }
#elif defined(TOOLKIT_USES_GTK)
  static gboolean TimerCallback(gpointer data) {
    instance_->TimerFired();
    return true;
  }
#elif defined(OS_MACOSX)
  static void TimerCallback(CFRunLoopTimerRef timer, void* info) {
    instance_->TimerFired();
  }
#endif

  void TimerFired() {
    ASSERT_FALSE(completed_);

    if (timed_out()) {
      DestroyTimer();
      MessageLoop::current()->Quit();
      FAIL() << "fetch timed out";
      return;
    }

    time_elapsed_ms_ += kWaitIntervalMs;
  }

  static FetcherDelegate* instance_;

 private:
#if defined(OS_WIN)
  UINT_PTR timer_id_;
#elif defined(TOOLKIT_USES_GTK)
  guint timer_id_;
#elif defined(OS_MACOSX)
  CFRunLoopTimerRef timer_id_;
#endif
  bool completed_;
  int time_elapsed_ms_;
  WebURLResponse response_;
  std::string data_;
};

FetcherDelegate* FetcherDelegate::instance_ = NULL;

// Test a fetch from the test server.
TEST_F(ResourceFetcherTests, ResourceFetcherDownload) {
  ASSERT_TRUE(test_server_.Start());

  WebFrame* frame = test_shell_->webView()->mainFrame();

  GURL url(test_server_.GetURL("files/test_shell/index.html"));
  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
      url, frame, delegate->NewCallback()));

  delegate->WaitForResponse();

  ASSERT_TRUE(delegate->completed());
  EXPECT_EQ(delegate->response().httpStatusCode(), 200);
  std::string text = delegate->data();
  EXPECT_TRUE(text.find("What is this page?") != std::string::npos);

  // Test 404 response.
  url = test_server_.GetURL("files/thisfiledoesntexist.html");
  delegate.reset(new FetcherDelegate);
  fetcher.reset(new ResourceFetcher(url, frame, delegate->NewCallback()));

  delegate->WaitForResponse();

  ASSERT_TRUE(delegate->completed());
  EXPECT_EQ(delegate->response().httpStatusCode(), 404);
  EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos);
}

TEST_F(ResourceFetcherTests, ResourceFetcherDidFail) {
  ASSERT_TRUE(test_server_.Start());

  WebFrame* frame = test_shell_->webView()->mainFrame();

  // Try to fetch a page on a site that doesn't exist.
  GURL url("http://localhost:1339/doesnotexist");
  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
      url, frame, delegate->NewCallback()));

  delegate->WaitForResponse();

  // When we fail, we still call the Delegate callback but we pass in empty
  // values.
  EXPECT_TRUE(delegate->completed());
  EXPECT_TRUE(delegate->response().isNull());
  EXPECT_EQ(delegate->data(), std::string());
  EXPECT_TRUE(delegate->time_elapsed_ms() < kMaxWaitTimeMs);
}

TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) {
  ASSERT_TRUE(test_server_.Start());

  WebFrame* frame = test_shell_->webView()->mainFrame();

  // Grab a page that takes at least 1 sec to respond, but set the fetcher to
  // timeout in 0 sec.
  GURL url(test_server_.GetURL("slow?1"));
  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
      url, frame, 0, delegate->NewCallback()));

  delegate->WaitForResponse();

  // When we timeout, we still call the Delegate callback but we pass in empty
  // values.
  EXPECT_TRUE(delegate->completed());
  EXPECT_TRUE(delegate->response().isNull());
  EXPECT_EQ(delegate->data(), std::string());
  EXPECT_TRUE(delegate->time_elapsed_ms() < kMaxWaitTimeMs);
}

}  // namespace
<commit_msg>Mark ResourceFetcherTests.ResourceFetcherDownload and ResourceFetcherDidFail as FLAKY<commit_after>// Copyright (c) 2006-2008 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 "webkit/glue/resource_fetcher.h"

#include "base/callback.h"
#include "base/message_loop.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"
#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
#include "webkit/glue/unittest_test_server.h"
#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
#include "webkit/tools/test_shell/test_shell_test.h"

#if defined(TOOLKIT_USES_GTK)
#include <gtk/gtk.h>
#endif

using WebKit::WebFrame;
using WebKit::WebURLResponse;
using webkit_glue::ResourceFetcher;
using webkit_glue::ResourceFetcherWithTimeout;

namespace {

class ResourceFetcherTests : public TestShellTest {
 protected:
  UnittestTestServer test_server_;
};

static const int kMaxWaitTimeMs = 5000;
static const int kWaitIntervalMs = 100;

class FetcherDelegate {
 public:
  FetcherDelegate()
      : timer_id_(0), completed_(false), time_elapsed_ms_(0) {
    // Start a repeating timer waiting for the download to complete.  The
    // callback has to be a static function, so we hold on to our instance.
    FetcherDelegate::instance_ = this;
    CreateTimer(kWaitIntervalMs);
  }

  ResourceFetcher::Callback* NewCallback() {
    return ::NewCallback(this, &FetcherDelegate::OnURLFetchComplete);
  }

  void OnURLFetchComplete(const WebURLResponse& response,
                          const std::string& data) {
    response_ = response;
    data_ = data;
    completed_ = true;
    DestroyTimer();
    MessageLoop::current()->Quit();
  }

  bool completed() const { return completed_; }
  bool timed_out() const { return time_elapsed_ms_ > kMaxWaitTimeMs; }

  int time_elapsed_ms() const { return time_elapsed_ms_; }
  std::string data() const { return data_; }
  const WebURLResponse& response() const { return response_; }

  // Wait for the request to complete or timeout.  We use a loop here b/c the
  // testing infrastructure (test_shell) can generate spurious calls to the
  // MessageLoop's Quit method.
  void WaitForResponse() {
    while (!completed() && !timed_out())
      MessageLoop::current()->Run();
  }

  void CreateTimer(int interval) {
#if defined(OS_WIN)
    timer_id_ = ::SetTimer(NULL, NULL, interval,
                           &FetcherDelegate::TimerCallback);
#elif defined(TOOLKIT_USES_GTK)
    timer_id_ = g_timeout_add(interval, &FetcherDelegate::TimerCallback, NULL);
#elif defined(OS_MACOSX)
    // CFAbsoluteTime is in seconds and |interval| is in ms, so make sure we
    // keep the units correct.
    CFTimeInterval interval_in_seconds = static_cast<double>(interval) / 1000.0;
    CFAbsoluteTime fire_date =
        CFAbsoluteTimeGetCurrent() + interval_in_seconds;
    timer_id_ = CFRunLoopTimerCreate(NULL, fire_date, interval_in_seconds, 0,
                                     0, FetcherDelegate::TimerCallback, NULL);
    CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer_id_, kCFRunLoopCommonModes);
#endif
  }

  void DestroyTimer() {
#if defined(OS_WIN)
    ::KillTimer(NULL, timer_id_);
#elif defined(TOOLKIT_USES_GTK)
    g_source_remove(timer_id_);
#elif defined(OS_MACOSX)
    CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), timer_id_,
                         kCFRunLoopCommonModes);
    CFRelease(timer_id_);
#endif
  }

#if defined(OS_WIN)
  // Static timer callback, just passes through to instance version.
  static VOID CALLBACK TimerCallback(HWND hwnd, UINT msg, UINT_PTR timer_id,
                                     DWORD ms) {
    instance_->TimerFired();
  }
#elif defined(TOOLKIT_USES_GTK)
  static gboolean TimerCallback(gpointer data) {
    instance_->TimerFired();
    return true;
  }
#elif defined(OS_MACOSX)
  static void TimerCallback(CFRunLoopTimerRef timer, void* info) {
    instance_->TimerFired();
  }
#endif

  void TimerFired() {
    ASSERT_FALSE(completed_);

    if (timed_out()) {
      DestroyTimer();
      MessageLoop::current()->Quit();
      FAIL() << "fetch timed out";
      return;
    }

    time_elapsed_ms_ += kWaitIntervalMs;
  }

  static FetcherDelegate* instance_;

 private:
#if defined(OS_WIN)
  UINT_PTR timer_id_;
#elif defined(TOOLKIT_USES_GTK)
  guint timer_id_;
#elif defined(OS_MACOSX)
  CFRunLoopTimerRef timer_id_;
#endif
  bool completed_;
  int time_elapsed_ms_;
  WebURLResponse response_;
  std::string data_;
};

FetcherDelegate* FetcherDelegate::instance_ = NULL;

// Test a fetch from the test server.
// Flaky, http://crbug.com/51622.
TEST_F(ResourceFetcherTests, FLAKY_ResourceFetcherDownload) {
  ASSERT_TRUE(test_server_.Start());

  WebFrame* frame = test_shell_->webView()->mainFrame();

  GURL url(test_server_.GetURL("files/test_shell/index.html"));
  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
      url, frame, delegate->NewCallback()));

  delegate->WaitForResponse();

  ASSERT_TRUE(delegate->completed());
  EXPECT_EQ(delegate->response().httpStatusCode(), 200);
  std::string text = delegate->data();
  EXPECT_TRUE(text.find("What is this page?") != std::string::npos);

  // Test 404 response.
  url = test_server_.GetURL("files/thisfiledoesntexist.html");
  delegate.reset(new FetcherDelegate);
  fetcher.reset(new ResourceFetcher(url, frame, delegate->NewCallback()));

  delegate->WaitForResponse();

  ASSERT_TRUE(delegate->completed());
  EXPECT_EQ(delegate->response().httpStatusCode(), 404);
  EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos);
}

// Flaky, http://crbug.com/51622.
TEST_F(ResourceFetcherTests, FLAKY_ResourceFetcherDidFail) {
  ASSERT_TRUE(test_server_.Start());

  WebFrame* frame = test_shell_->webView()->mainFrame();

  // Try to fetch a page on a site that doesn't exist.
  GURL url("http://localhost:1339/doesnotexist");
  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
      url, frame, delegate->NewCallback()));

  delegate->WaitForResponse();

  // When we fail, we still call the Delegate callback but we pass in empty
  // values.
  EXPECT_TRUE(delegate->completed());
  EXPECT_TRUE(delegate->response().isNull());
  EXPECT_EQ(delegate->data(), std::string());
  EXPECT_TRUE(delegate->time_elapsed_ms() < kMaxWaitTimeMs);
}

TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) {
  ASSERT_TRUE(test_server_.Start());

  WebFrame* frame = test_shell_->webView()->mainFrame();

  // Grab a page that takes at least 1 sec to respond, but set the fetcher to
  // timeout in 0 sec.
  GURL url(test_server_.GetURL("slow?1"));
  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
      url, frame, 0, delegate->NewCallback()));

  delegate->WaitForResponse();

  // When we timeout, we still call the Delegate callback but we pass in empty
  // values.
  EXPECT_TRUE(delegate->completed());
  EXPECT_TRUE(delegate->response().isNull());
  EXPECT_EQ(delegate->data(), std::string());
  EXPECT_TRUE(delegate->time_elapsed_ms() < kMaxWaitTimeMs);
}

}  // namespace
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <osquery/core.h>
#include <osquery/logger.h>
#include <osquery/tables.h>

#include "osquery/core/conversions.h"
#include "osquery/events/linux/udev.h"

namespace osquery {
namespace tables {

const std::string kUSBKeyVendorID = "ID_VENDOR_ID";
const std::string kUSBKeyVendor = "ID_VENDOR_FROM_DATABASE";
const std::string kUSBKeyModelID = "ID_MODEL_ID";
const std::string kUSBKeyModel = "ID_MODEL_FROM_DATABASE";
const std::string kUSBKeyDriver = "ID_USB_DRIVER";
const std::string kUSBKeySubsystem = "SUBSYSTEM";
const std::string kUSBKeySerial = "ID_SERIAL_SHORT";
const std::string kUSBKeyAddress = "BUSNUM";
const std::string kUSBKeyPort = "DEVNUM";
const std::string kUSBKeyType = "TYPE";

QueryData genUSBDevices(QueryContext &context) {
  QueryData results;

  auto udev_handle = udev_new();
  if (udev_handle == nullptr) {
    VLOG(1) << "Could not get udev handle";
    return results;
  }

  // Perform enumeration/search.
  auto enumerate = udev_enumerate_new(udev_handle);
  udev_enumerate_add_match_subsystem(enumerate, "usb");
  udev_enumerate_scan_devices(enumerate);

  // Get list entries and iterate over entries.
  struct udev_list_entry *device_entries, *entry;
  device_entries = udev_enumerate_get_list_entry(enumerate);

  udev_list_entry_foreach(entry, device_entries) {
    const char *path = udev_list_entry_get_name(entry);
    auto device = udev_device_new_from_syspath(udev_handle, path);

    Row r;
    // r["driver"] = UdevEventPublisher::getValue(device, kUSBKeyDriver);
    r["vendor"] = UdevEventPublisher::getValue(device, kUSBKeyVendor);
    r["model"] = UdevEventPublisher::getValue(device, kUSBKeyModel);

    // USB-specific vendor/model ID properties.
    r["model_id"] = UdevEventPublisher::getValue(device, kUSBKeyModelID);
    r["vendor_id"] = UdevEventPublisher::getValue(device, kUSBKeyVendorID);
    r["serial"] = UdevEventPublisher::getValue(device, kUSBKeySerial);

    // This will be of the form class/subclass/protocol and has to be parsed
    auto devType = UdevEventPublisher::getValue(device, kUSBKeyType);
    auto classInfo = osquery::split(devType, "/");
    if (classInfo.size() == 3) {
      r["class"] = classInfo[0];
      r["subclass"] = classInfo[1];
      r["protocol"] = classInfo[2];
    } else {
      r["class"] = "";
      r["subclass"] = "";
      r["protocol"] = "";
    }

    // Address/port accessors.
    r["usb_address"] = UdevEventPublisher::getValue(device, kUSBKeyAddress);
    r["usb_port"] = UdevEventPublisher::getValue(device, kUSBKeyPort);

    // Removable detection.
    auto removable = UdevEventPublisher::getAttr(device, "removable");
    if (removable == "unknown") {
      r["removable"] = "-1";
    } else {
      r["removable"] = "1";
    }

    if (r["usb_address"].size() > 0 && r["usb_port"].size() > 0) {
      results.push_back(r);
    }
    udev_device_unref(device);
  }

  // Drop references to udev structs.
  udev_enumerate_unref(enumerate);
  udev_unref(udev_handle);

  return results;
}
}
}
<commit_msg>[usb_devices] fallback to ID_MODEL if ID_MODEL_FROM_DATABASE is absent (#3686)<commit_after>/*
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <osquery/core.h>
#include <osquery/logger.h>
#include <osquery/tables.h>

#include "osquery/core/conversions.h"
#include "osquery/events/linux/udev.h"

namespace osquery {
namespace tables {

const std::string kUSBKeyVendorID = "ID_VENDOR_ID";
const std::string kUSBKeyVendor = "ID_VENDOR_FROM_DATABASE";
const std::string kUSBKeyModelID = "ID_MODEL_ID";
const std::string kUSBKeyModel = "ID_MODEL_FROM_DATABASE";
const std::string kUSBKeyModelFallback = "ID_MODEL";
const std::string kUSBKeyDriver = "ID_USB_DRIVER";
const std::string kUSBKeySubsystem = "SUBSYSTEM";
const std::string kUSBKeySerial = "ID_SERIAL_SHORT";
const std::string kUSBKeyAddress = "BUSNUM";
const std::string kUSBKeyPort = "DEVNUM";
const std::string kUSBKeyType = "TYPE";

QueryData genUSBDevices(QueryContext &context) {
  QueryData results;

  auto udev_handle = udev_new();
  if (udev_handle == nullptr) {
    VLOG(1) << "Could not get udev handle";
    return results;
  }

  // Perform enumeration/search.
  auto enumerate = udev_enumerate_new(udev_handle);
  udev_enumerate_add_match_subsystem(enumerate, "usb");
  udev_enumerate_scan_devices(enumerate);

  // Get list entries and iterate over entries.
  struct udev_list_entry *device_entries, *entry;
  device_entries = udev_enumerate_get_list_entry(enumerate);

  udev_list_entry_foreach(entry, device_entries) {
    const char *path = udev_list_entry_get_name(entry);
    auto device = udev_device_new_from_syspath(udev_handle, path);

    Row r;
    // r["driver"] = UdevEventPublisher::getValue(device, kUSBKeyDriver);
    r["vendor"] = UdevEventPublisher::getValue(device, kUSBKeyVendor);
    r["model"] = UdevEventPublisher::getValue(device, kUSBKeyModel);
    if (r["model"].empty()) {
      r["model"] = UdevEventPublisher::getValue(device, kUSBKeyModelFallback);
    }

    // USB-specific vendor/model ID properties.
    r["model_id"] = UdevEventPublisher::getValue(device, kUSBKeyModelID);
    r["vendor_id"] = UdevEventPublisher::getValue(device, kUSBKeyVendorID);
    r["serial"] = UdevEventPublisher::getValue(device, kUSBKeySerial);

    // This will be of the form class/subclass/protocol and has to be parsed
    auto devType = UdevEventPublisher::getValue(device, kUSBKeyType);
    auto classInfo = osquery::split(devType, "/");
    if (classInfo.size() == 3) {
      r["class"] = classInfo[0];
      r["subclass"] = classInfo[1];
      r["protocol"] = classInfo[2];
    } else {
      r["class"] = "";
      r["subclass"] = "";
      r["protocol"] = "";
    }

    // Address/port accessors.
    r["usb_address"] = UdevEventPublisher::getValue(device, kUSBKeyAddress);
    r["usb_port"] = UdevEventPublisher::getValue(device, kUSBKeyPort);

    // Removable detection.
    auto removable = UdevEventPublisher::getAttr(device, "removable");
    if (removable == "unknown") {
      r["removable"] = "-1";
    } else {
      r["removable"] = "1";
    }

    if (r["usb_address"].size() > 0 && r["usb_port"].size() > 0) {
      results.push_back(r);
    }
    udev_device_unref(device);
  }

  // Drop references to udev structs.
  udev_enumerate_unref(enumerate);
  udev_unref(udev_handle);

  return results;
}
}
}
<|endoftext|>


<commit_before>#include <cassert>
#include "CRC/CRC.h"

namespace
{
    const size_t BufferSize = 8192;

    size_t getChunkSize(File::OffsetType currentPos, File::OffsetType maxPos)
    {
        if (currentPos + static_cast<File::OffsetType>(BufferSize) >= maxPos)
            return maxPos - currentPos;
        return BufferSize;
    }
}

CRC::CRC()
{
    progressFunction = nullptr;
}

CRC::~CRC()
{
}

CRCType CRC::getInitialXOR() const
{
    return initialXOR;
}

CRCType CRC::getFinalXOR() const
{
    return finalXOR;
}

void CRC::setInitialXOR(CRCType f)
{
    initialXOR = f;
}

void CRC::setFinalXOR(CRCType f)
{
    finalXOR = f;
}

void CRC::setProgressFunction(const CRC::ProgressFunction &f)
{
    progressFunction = f;
}

/**
 * Method that copies the input to the output, outputting
 * computed patch at given position along the way.
 */
void CRC::applyPatch(
    CRCType finalChecksum,
    File::OffsetType targetPos,
    File &input,
    File &output,
    bool overwrite) const
{
    std::unique_ptr<uint8_t[]> buffer(new uint8_t[BufferSize]);
    CRCType patch = computePatch(finalChecksum, targetPos, input, overwrite);

    input.seek(0, File::Origin::Start);
    File::OffsetType pos = input.tell();
    markProgress(ProgressType::WriteStart, 0, pos, input.getSize());

    //output first half
    while (pos < targetPos)
    {
        markProgress(ProgressType::WriteProgress, 0, pos, input.getSize());
        auto chunkSize = getChunkSize(pos, targetPos);
        input.read(buffer.get(), chunkSize);
        output.write(buffer.get(), chunkSize);
        pos += chunkSize;
    }

    //output patch
    assert(getNumBytes() < BufferSize);
    for (size_t i = 0; i < getNumBytes(); i++)
        buffer[i] = static_cast<uint8_t>(patch >> (i << 3));
    output.write(buffer.get(), getNumBytes());
    if (overwrite)
    {
        pos += getNumBytes();
        input.seek(pos, File::Origin::Start);
    }

    //output second half
    while (pos < input.getSize())
    {
        markProgress(ProgressType::WriteProgress, 0, pos, input.getSize());
        auto chunkSize = getChunkSize(pos, input.getSize());
        input.read(buffer.get(), chunkSize);
        output.write(buffer.get(), chunkSize);
        pos += chunkSize;
    }

    markProgress(ProgressType::WriteEnd, 0, pos, input.getSize());
}

/**
 * Computes the checksum of given file.
 * NOTICE: Leaves internal file pointer position intact.
 */
CRCType CRC::computeChecksum(File &input) const
{
    CRCType checksum = getInitialXOR();
    checksum = computePartialChecksum(input, 0, input.getSize(), checksum);
    return checksum ^ getFinalXOR();
}

/**
 * Computes partial checksum of given file.
 * NOTICE: Leaves internal file pointer position intact.
 */
CRCType CRC::computePartialChecksum(
    File &input,
    File::OffsetType startPos,
    File::OffsetType endPos,
    CRCType initialChecksum) const
{
    assert(startPos <= endPos);
    if (startPos == endPos)
        return initialChecksum;

    CRCType checksum = initialChecksum;
    std::unique_ptr<uint8_t[]> buffer(new uint8_t[BufferSize]);
    File::OffsetType oldPos = input.tell();
    File::OffsetType pos = startPos;
    input.seek(pos, File::Origin::Start);
    markProgress(ProgressType::ChecksumStart, startPos, startPos, endPos);

    while (pos < endPos)
    {
        markProgress(ProgressType::ChecksumProgress, startPos, pos, endPos);
        auto chunkSize = getChunkSize(pos, endPos);
        input.read(buffer.get(), chunkSize);
        for (size_t i = 0; i < chunkSize; i++)
            checksum = makeNextChecksum(checksum, buffer[i]);
        pos += chunkSize;
    }

    markProgress(ProgressType::ChecksumEnd, startPos, endPos, endPos);
    input.seek(oldPos, File::Origin::Start);
    return checksum;
}

/**
 * Computes reverse partial checksum of given file.
 * NOTICE: Leaves internal file pointer position intact.
 */
CRCType CRC::computeReversePartialChecksum(
    File &input,
    File::OffsetType startPos,
    File::OffsetType endPos,
    CRCType initialChecksum) const
{
    assert(startPos >= endPos);
    if (startPos == endPos)
        return initialChecksum;

    CRCType checksum = initialChecksum;
    std::unique_ptr<uint8_t[]> buffer(new uint8_t[BufferSize]);
    File::OffsetType oldPos = input.tell();
    File::OffsetType pos = startPos;
    markProgress(ProgressType::ChecksumStart, startPos, startPos, endPos);

    while (pos > endPos)
    {
        markProgress(ProgressType::ChecksumProgress, startPos, pos, endPos);
        auto chunkSize = getChunkSize(endPos, pos);
        pos -= chunkSize;
        input.seek(pos, File::Origin::Start);
        input.read(buffer.get(), chunkSize);
        for (size_t i = 0, j = chunkSize - 1; i < chunkSize; i++, j--)
            checksum = makePrevChecksum(checksum, buffer[j]);
    }

    markProgress(ProgressType::ChecksumEnd, startPos, endPos, endPos);
    input.seek(oldPos, File::Origin::Start);
    return checksum;
}

void CRC::markProgress(
    ProgressType progressType,
    File::OffsetType startPos,
    File::OffsetType curPos,
    File::OffsetType endPos) const
{
    if (progressFunction != nullptr)
        progressFunction(progressType, startPos, curPos, endPos);
}

CRCType CRC::computePatch(
    CRCType targetChecksum,
    File::OffsetType targetPos,
    File &inputFile,
    bool overwrite) const
{
    uint32_t checksum1 = computePartialChecksum(
        inputFile,
        0,
        targetPos,
        getInitialXOR());

    uint32_t checksum2 = computeReversePartialChecksum(
        inputFile,
        inputFile.getSize(),
        targetPos + (overwrite ? 4 : 0),
        static_cast<uint32_t>(targetChecksum ^ getFinalXOR()));

    uint32_t patch = checksum2;
    for (size_t i = 0, j = getNumBytes() - 1; i < getNumBytes(); i++, j--)
        patch = makePrevChecksum(patch, (checksum1 >> (j << 3)) & 0xff);

    return patch;
}
<commit_msg>Fixed hardcoded byte count in CRC patcher<commit_after>#include <cassert>
#include "CRC/CRC.h"

namespace
{
    const size_t BufferSize = 8192;

    size_t getChunkSize(File::OffsetType currentPos, File::OffsetType maxPos)
    {
        if (currentPos + static_cast<File::OffsetType>(BufferSize) >= maxPos)
            return maxPos - currentPos;
        return BufferSize;
    }
}

CRC::CRC()
{
    progressFunction = nullptr;
}

CRC::~CRC()
{
}

CRCType CRC::getInitialXOR() const
{
    return initialXOR;
}

CRCType CRC::getFinalXOR() const
{
    return finalXOR;
}

void CRC::setInitialXOR(CRCType f)
{
    initialXOR = f;
}

void CRC::setFinalXOR(CRCType f)
{
    finalXOR = f;
}

void CRC::setProgressFunction(const CRC::ProgressFunction &f)
{
    progressFunction = f;
}

/**
 * Method that copies the input to the output, outputting
 * computed patch at given position along the way.
 */
void CRC::applyPatch(
    CRCType finalChecksum,
    File::OffsetType targetPos,
    File &input,
    File &output,
    bool overwrite) const
{
    std::unique_ptr<uint8_t[]> buffer(new uint8_t[BufferSize]);
    CRCType patch = computePatch(finalChecksum, targetPos, input, overwrite);

    input.seek(0, File::Origin::Start);
    File::OffsetType pos = input.tell();
    markProgress(ProgressType::WriteStart, 0, pos, input.getSize());

    //output first half
    while (pos < targetPos)
    {
        markProgress(ProgressType::WriteProgress, 0, pos, input.getSize());
        auto chunkSize = getChunkSize(pos, targetPos);
        input.read(buffer.get(), chunkSize);
        output.write(buffer.get(), chunkSize);
        pos += chunkSize;
    }

    //output patch
    assert(getNumBytes() < BufferSize);
    for (size_t i = 0; i < getNumBytes(); i++)
        buffer[i] = static_cast<uint8_t>(patch >> (i << 3));
    output.write(buffer.get(), getNumBytes());
    if (overwrite)
    {
        pos += getNumBytes();
        input.seek(pos, File::Origin::Start);
    }

    //output second half
    while (pos < input.getSize())
    {
        markProgress(ProgressType::WriteProgress, 0, pos, input.getSize());
        auto chunkSize = getChunkSize(pos, input.getSize());
        input.read(buffer.get(), chunkSize);
        output.write(buffer.get(), chunkSize);
        pos += chunkSize;
    }

    markProgress(ProgressType::WriteEnd, 0, pos, input.getSize());
}

/**
 * Computes the checksum of given file.
 * NOTICE: Leaves internal file pointer position intact.
 */
CRCType CRC::computeChecksum(File &input) const
{
    CRCType checksum = getInitialXOR();
    checksum = computePartialChecksum(input, 0, input.getSize(), checksum);
    return checksum ^ getFinalXOR();
}

/**
 * Computes partial checksum of given file.
 * NOTICE: Leaves internal file pointer position intact.
 */
CRCType CRC::computePartialChecksum(
    File &input,
    File::OffsetType startPos,
    File::OffsetType endPos,
    CRCType initialChecksum) const
{
    assert(startPos <= endPos);
    if (startPos == endPos)
        return initialChecksum;

    CRCType checksum = initialChecksum;
    std::unique_ptr<uint8_t[]> buffer(new uint8_t[BufferSize]);
    File::OffsetType oldPos = input.tell();
    File::OffsetType pos = startPos;
    input.seek(pos, File::Origin::Start);
    markProgress(ProgressType::ChecksumStart, startPos, startPos, endPos);

    while (pos < endPos)
    {
        markProgress(ProgressType::ChecksumProgress, startPos, pos, endPos);
        auto chunkSize = getChunkSize(pos, endPos);
        input.read(buffer.get(), chunkSize);
        for (size_t i = 0; i < chunkSize; i++)
            checksum = makeNextChecksum(checksum, buffer[i]);
        pos += chunkSize;
    }

    markProgress(ProgressType::ChecksumEnd, startPos, endPos, endPos);
    input.seek(oldPos, File::Origin::Start);
    return checksum;
}

/**
 * Computes reverse partial checksum of given file.
 * NOTICE: Leaves internal file pointer position intact.
 */
CRCType CRC::computeReversePartialChecksum(
    File &input,
    File::OffsetType startPos,
    File::OffsetType endPos,
    CRCType initialChecksum) const
{
    assert(startPos >= endPos);
    if (startPos == endPos)
        return initialChecksum;

    CRCType checksum = initialChecksum;
    std::unique_ptr<uint8_t[]> buffer(new uint8_t[BufferSize]);
    File::OffsetType oldPos = input.tell();
    File::OffsetType pos = startPos;
    markProgress(ProgressType::ChecksumStart, startPos, startPos, endPos);

    while (pos > endPos)
    {
        markProgress(ProgressType::ChecksumProgress, startPos, pos, endPos);
        auto chunkSize = getChunkSize(endPos, pos);
        pos -= chunkSize;
        input.seek(pos, File::Origin::Start);
        input.read(buffer.get(), chunkSize);
        for (size_t i = 0, j = chunkSize - 1; i < chunkSize; i++, j--)
            checksum = makePrevChecksum(checksum, buffer[j]);
    }

    markProgress(ProgressType::ChecksumEnd, startPos, endPos, endPos);
    input.seek(oldPos, File::Origin::Start);
    return checksum;
}

void CRC::markProgress(
    ProgressType progressType,
    File::OffsetType startPos,
    File::OffsetType curPos,
    File::OffsetType endPos) const
{
    if (progressFunction != nullptr)
        progressFunction(progressType, startPos, curPos, endPos);
}

CRCType CRC::computePatch(
    CRCType targetChecksum,
    File::OffsetType targetPos,
    File &inputFile,
    bool overwrite) const
{
    uint32_t checksum1 = computePartialChecksum(
        inputFile,
        0,
        targetPos,
        getInitialXOR());

    uint32_t checksum2 = computeReversePartialChecksum(
        inputFile,
        inputFile.getSize(),
        targetPos + (overwrite ? getNumBytes() : 0),
        static_cast<uint32_t>(targetChecksum ^ getFinalXOR()));

    uint32_t patch = checksum2;
    for (size_t i = 0, j = getNumBytes() - 1; i < getNumBytes(); i++, j--)
        patch = makePrevChecksum(patch, (checksum1 >> (j << 3)) & 0xff);

    return patch;
}
<|endoftext|>


<commit_before>/**
 *  Schulich Delta Hermes
 *  Copyright (C) 2015 University of Calgary Solar Car Team
 *
 *  This file is part of Schulich Delta Hermes
 *
 *  Schulich Delta Hermes is free software:
 *  you can redistribute it and/or modify it under the terms
 *  of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  Schulich Delta Hermes is distributed
 *  in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General
 *  Public License along with Schulich Delta Hermes.
 *  If not, see <http://www.gnu.org/licenses/>.
 *
 *  For further contact, email <software@calgarysolarcar.ca>
 */

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <QScopedPointer>
#include <QDebug>
#include <QByteArray>
#include <string>

#include <SimpleAmqpClient/SimpleAmqpClient.h>

#include "CommunicationLayer/CommDeviceControl/UdpMessageForwarder.h"
#include "InfrastructureLayer/Settings/MockSettings.h"

using ::testing::Return;

namespace
{
const QString MOCK_IP = QString("localhost");
const quint16 MOCK_PORT = 5672;
const QString MOCK_QUEUE = "test-queue";
// TODO fix exchange values
const QString MOCK_EXCHANGE = "testExchange";
const QString MOCK_ROUTING_KEY = "x73F34rS0dl";
const QString EXPECTED_1 = "Message Test";
const QString EXPECTED_2 = "Second Message Test";
const QString EXPECTED_3 = "Sp3c1a1** Ch4r4c74r5__ 7357";
}

class UdpMessageForwarderTest : public ::testing::Test
{
protected:

    QScopedPointer<MockSettings> settings_;
    QScopedPointer<UdpMessageForwarder> forwarder;
    AmqpClient::Channel::ptr_t receiver;

    // TODO any new tests?
    // TODO add documentation for rabbitMQ libraries
    // TODO fix travis
    // TODO Fix indentation
    // TODO fix .ini files
    // TODO fix exhange usage in test
    // TODO Only the receiver should be generating the queue
    // TODO Come up with official exchange name

    /**
   * @brief SetUp will set up the receiver to verify messages are being sent, as well as mocking the settings to be used by the UdpMessageForwarder
   */
    virtual void SetUp()
    {
        settings_.reset(new MockSettings());

        ON_CALL(*settings_, ipAddress())
                .WillByDefault(Return(MOCK_IP));
        ON_CALL(*settings_, exchangeName())
                .WillByDefault(Return(MOCK_EXCHANGE));
        ON_CALL(*settings_, udpPort())
                .WillByDefault(Return(MOCK_PORT));
        ON_CALL(*settings_, routingKey())
                .WillByDefault(Return(MOCK_ROUTING_KEY));
    }

    virtual void TearDown() {
        // Delete exchange
        receiver->DeleteExchange(MOCK_EXCHANGE.toStdString());
        cleanReceiver();
    }

    // Test Methods

    void sendMessage(const QString& message);
    QString receiveMessage(bool setupConsume);
    /**
     * @brief setup the receiver for usage
     */
    void setupReceiver();
    /**
     * @brief reset the receiver (clear and delete queue)
     */
    void cleanReceiver();
};

void UdpMessageForwarderTest::sendMessage(const QString& message) {
    QByteArray expectedBytes = QByteArray();
    expectedBytes.append(message);
    forwarder->forwardData(expectedBytes);
}

QString UdpMessageForwarderTest::receiveMessage(bool setupConsume) {
    // Receive message from local server
    if (setupConsume) {
        receiver->BasicConsume(MOCK_QUEUE.toStdString());
    }
    return QString::fromStdString(receiver->BasicConsumeMessage()->Message()->Body());
}

void UdpMessageForwarderTest::setupReceiver() {
    receiver = Channel::Create(MOCK_IP.toStdString(), MOCK_PORT);
    // passive (false), durable (true), exclusive (false), auto_delete (false)
    receiver->DeclareQueue(MOCK_QUEUE.toStdString(), false, true, false, false);
    receiver->DeclareExchange(MOCK_EXCHANGE.toStdString(), AmqpClient::Channel::EXCHANGE_TYPE_FANOUT);
    receiver->BindQueue(MOCK_QUEUE.toStdString(), MOCK_EXCHANGE.toStdString(), MOCK_ROUTING_KEY.toStdString());
}

void UdpMessageForwarderTest::cleanReceiver() {
    receiver->PurgeQueue(MOCK_QUEUE.toStdString());
    receiver->DeleteQueue(MOCK_QUEUE.toStdString());
    receiver.reset();
}

/**
 * @brief Send a single message representing a JSON string via UdpMessageForwarder and verify its success
 */
TEST_F(UdpMessageForwarderTest, testSendingMessage) {
    setupReceiver();
    forwarder.reset(new UdpMessageForwarder(*settings_));
    sendMessage(EXPECTED_1);
    QString ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_1.toStdString(), ACTUAL.toStdString());
}

/**
 * @brief Send a message before the receiver has setup
 */
TEST_F(UdpMessageForwarderTest, testSendingNoReceiver) {
    setupReceiver();
    forwarder.reset(new UdpMessageForwarder(*settings_));
    sendMessage(EXPECTED_1);
    setupReceiver();
    QString ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_1.toStdString(), ACTUAL.toStdString());
}

/**
 * @brief Disconnect the receiver during delivery and ensure messages still arrive
 */
TEST_F(UdpMessageForwarderTest, testSendingReceiverDC) {
    setupReceiver();
    forwarder.reset(new UdpMessageForwarder(*settings_));
    sendMessage(EXPECTED_1);
    QString ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_1.toStdString(), ACTUAL.toStdString());
    receiver.reset();
    sendMessage(EXPECTED_2);
    setupReceiver();
    ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_2.toStdString(), ACTUAL.toStdString());
}

/**
 * @brief test sending message with special characters
 */
TEST_F(UdpMessageForwarderTest, testSendingSpecialChars) {
    setupReceiver();
    forwarder.reset(new UdpMessageForwarder(*settings_));
    sendMessage(EXPECTED_3);
    QString ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_3.toStdString(), ACTUAL.toStdString());
}
<commit_msg>comment changes - TODO's<commit_after>/**
 *  Schulich Delta Hermes
 *  Copyright (C) 2015 University of Calgary Solar Car Team
 *
 *  This file is part of Schulich Delta Hermes
 *
 *  Schulich Delta Hermes is free software:
 *  you can redistribute it and/or modify it under the terms
 *  of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  Schulich Delta Hermes is distributed
 *  in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General
 *  Public License along with Schulich Delta Hermes.
 *  If not, see <http://www.gnu.org/licenses/>.
 *
 *  For further contact, email <software@calgarysolarcar.ca>
 */

#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <QScopedPointer>
#include <QDebug>
#include <QByteArray>
#include <string>

#include <SimpleAmqpClient/SimpleAmqpClient.h>

#include "CommunicationLayer/CommDeviceControl/UdpMessageForwarder.h"
#include "InfrastructureLayer/Settings/MockSettings.h"

using ::testing::Return;

namespace
{
const QString MOCK_IP = QString("localhost");
const quint16 MOCK_PORT = 5672;
const QString MOCK_QUEUE = "test-queue";
const QString MOCK_EXCHANGE = "testExchange";
const QString MOCK_ROUTING_KEY = "x73F34rS0dl";
const QString EXPECTED_1 = "Message Test";
const QString EXPECTED_2 = "Second Message Test";
const QString EXPECTED_3 = "Sp3c1a1** Ch4r4c74r5__ 7357";
}

class UdpMessageForwarderTest : public ::testing::Test
{
protected:

    QScopedPointer<MockSettings> settings_;
    QScopedPointer<UdpMessageForwarder> forwarder;
    AmqpClient::Channel::ptr_t receiver;

    // TODO add documentation for rabbitMQ libraries
    // TODO fix travis

    /**
   * @brief SetUp will set up the receiver to verify messages are being sent, as well as mocking the settings to be used by the UdpMessageForwarder
   */
    virtual void SetUp()
    {
        settings_.reset(new MockSettings());

        ON_CALL(*settings_, ipAddress())
                .WillByDefault(Return(MOCK_IP));
        ON_CALL(*settings_, exchangeName())
                .WillByDefault(Return(MOCK_EXCHANGE));
        ON_CALL(*settings_, udpPort())
                .WillByDefault(Return(MOCK_PORT));
        ON_CALL(*settings_, routingKey())
                .WillByDefault(Return(MOCK_ROUTING_KEY));
    }

    virtual void TearDown() {
        // Delete exchange
        receiver->DeleteExchange(MOCK_EXCHANGE.toStdString());
        cleanReceiver();
    }

    // Test Methods

    void sendMessage(const QString& message);
    QString receiveMessage(bool setupConsume);
    /**
     * @brief setup the receiver for usage
     */
    void setupReceiver();
    /**
     * @brief reset the receiver (clear and delete queue)
     */
    void cleanReceiver();
};

void UdpMessageForwarderTest::sendMessage(const QString& message) {
    QByteArray expectedBytes = QByteArray();
    expectedBytes.append(message);
    forwarder->forwardData(expectedBytes);
}

QString UdpMessageForwarderTest::receiveMessage(bool setupConsume) {
    // Receive message from local server
    if (setupConsume) {
        receiver->BasicConsume(MOCK_QUEUE.toStdString());
    }
    return QString::fromStdString(receiver->BasicConsumeMessage()->Message()->Body());
}

void UdpMessageForwarderTest::setupReceiver() {
    receiver = Channel::Create(MOCK_IP.toStdString(), MOCK_PORT);
    // passive (false), durable (true), exclusive (false), auto_delete (false)
    receiver->DeclareQueue(MOCK_QUEUE.toStdString(), false, true, false, false);
    receiver->DeclareExchange(MOCK_EXCHANGE.toStdString(), AmqpClient::Channel::EXCHANGE_TYPE_FANOUT);
    receiver->BindQueue(MOCK_QUEUE.toStdString(), MOCK_EXCHANGE.toStdString(), MOCK_ROUTING_KEY.toStdString());
}

void UdpMessageForwarderTest::cleanReceiver() {
    receiver->PurgeQueue(MOCK_QUEUE.toStdString());
    receiver->DeleteQueue(MOCK_QUEUE.toStdString());
    receiver.reset();
}

/**
 * @brief Send a single message representing a JSON string via UdpMessageForwarder and verify its success
 */
TEST_F(UdpMessageForwarderTest, testSendingMessage) {
    setupReceiver();
    forwarder.reset(new UdpMessageForwarder(*settings_));
    sendMessage(EXPECTED_1);
    QString ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_1.toStdString(), ACTUAL.toStdString());
}

/**
 * @brief Send a message before the receiver has setup
 */
TEST_F(UdpMessageForwarderTest, testSendingNoReceiver) {
    setupReceiver();
    forwarder.reset(new UdpMessageForwarder(*settings_));
    sendMessage(EXPECTED_1);
    setupReceiver();
    QString ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_1.toStdString(), ACTUAL.toStdString());
}

/**
 * @brief Disconnect the receiver during delivery and ensure messages still arrive
 */
TEST_F(UdpMessageForwarderTest, testSendingReceiverDC) {
    setupReceiver();
    forwarder.reset(new UdpMessageForwarder(*settings_));
    sendMessage(EXPECTED_1);
    QString ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_1.toStdString(), ACTUAL.toStdString());
    receiver.reset();
    sendMessage(EXPECTED_2);
    setupReceiver();
    ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_2.toStdString(), ACTUAL.toStdString());
}

/**
 * @brief test sending message with special characters
 */
TEST_F(UdpMessageForwarderTest, testSendingSpecialChars) {
    setupReceiver();
    forwarder.reset(new UdpMessageForwarder(*settings_));
    sendMessage(EXPECTED_3);
    QString ACTUAL = receiveMessage(true);
    EXPECT_EQ(EXPECTED_3.toStdString(), ACTUAL.toStdString());
}
<|endoftext|>


<commit_before>#include <cppunit/extensions/HelperMacros.h>
#include "spotty_network_failure_test.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <string.h>
#include <libcmm.h>
#include <libcmm_irob.h>
#include "net_interface.h"
#include "test_common.h"
#include "cmm_socket_control.h"
#include "libcmm_ipc.h"
#include "timeops.h"

#include <string>
#include <vector>
using std::string; using std::vector;

#include "proxy_socket.h"

CPPUNIT_TEST_SUITE_REGISTRATION(SpottyNetworkFailureTest);

/* In the process of revising this test as follows.
 *
 * What this test currently does:
 *  1) Fake a multisocket on the server end.
 *  2) Connect a real multisocket to the fake one.
 *  3) Shut down one of the TCP sockets.
 *  4) Try to send/receive data.
 *
 * The trouble with this approach is that the multisocket can
 *  detect the TCP connection being shut down and react to it.
 *  I really want to test what happens when the TCP connection
 *  just stops receiving any messages (including FIN, for example).
 *
 * What the revised test will do:
 *  1) Create a real multisocket on the server end.
 *  2) Create proxy sockets:
 *     a) Between the IntNW listen socket and the client
 *     b) Between the multisocket's internal listen socket
 *        and the client's connecting csockets
 *  3) Rewrite the necessary messages to keep the multisocket
 *     endpoints unaware of the proxy:
 *     a) The listener port in the initial HELLO response
 *  4) Snoop on the csocket setup messages to determine which
 *     one should be considered FG
 *  5) Stop proxying data on that csocket.
 *  6) Try to send/receive FG data.
 */

const in_port_t SpottyNetworkFailureTest::PROXY_PORT = 4243;
const in_port_t SpottyNetworkFailureTest::INTNW_LISTEN_PORT = 42424;

bool process_chunk(int to_sock, char *chunk, size_t len,
                   SpottyNetworkFailureTest *test,
                   SpottyNetworkFailureTest::chunk_proc_method_t processMethod)
{
    return (test->*processMethod)(to_sock, chunk, len);
}

bool process_bootstrap(int to_sock, char *chunk, size_t len,
                       SpottyNetworkFailureTest *test)
{
    return process_chunk(to_sock, chunk, len, test,
                         &SpottyNetworkFailureTest::processBootstrap);
}

bool process_data(int to_sock, char *chunk, size_t len,
                  SpottyNetworkFailureTest *test)
{
    return process_chunk(to_sock, chunk, len, test,
                         &SpottyNetworkFailureTest::processData);
}

void
SpottyNetworkFailureTest::setupReceiver()
{
    bootstrap_done = false;
    fg_socket_rtt = INT_MAX;
    fg_proxy_thread = (pthread_t) -1;
    pthread_mutex_init(&proxy_threads_lock, NULL);

    setListenPort(PROXY_PORT);
    start_proxy_thread(&bootstrap_proxy_thread, TEST_PORT, PROXY_PORT,
                       (chunk_proc_fn_t) process_bootstrap, this);
    start_proxy_thread(&internal_data_proxy_thread,
                       INTNW_LISTEN_PORT + 1, INTNW_LISTEN_PORT,
                       (chunk_proc_fn_t) process_data, this);

    EndToEndTestsBase::setupReceiver();
}

bool
SpottyNetworkFailureTest::processBootstrap(int to_sock, char *chunk, size_t len)
{
    // overwrite internal-listener port with the proxy's port
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t addrlen = sizeof(addr);
    if (!bootstrap_done &&
        getsockname(to_sock, (struct sockaddr *) &addr, &addrlen) == 0 &&
        ntohs(addr.sin_port) == TEST_PORT) {
        // only modify the hello response, not the request
        struct CMMSocketControlHdr *hdr = (struct CMMSocketControlHdr *) chunk;
        if (ntohs(hdr->type) == CMM_CONTROL_MSG_HELLO) {
            in_port_t listener_port = ntohs(hdr->op.hello.listen_port);
            printf("Overwriting listener port %hu in hello response with proxy port %hu\n",
                   listener_port, INTNW_LISTEN_PORT + 1);
            hdr->op.hello.listen_port = htons(INTNW_LISTEN_PORT + 1);
            bootstrap_done = true;
        }
    }

    return true;
}

bool
SpottyNetworkFailureTest::processData(int to_sock, char *chunk, size_t len)
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t addrlen = sizeof(addr);

    int rc = getpeername(to_sock, (struct sockaddr *) &addr, &addrlen);
    if (rc != 0) {
        fprintf(stderr, "Error: getpeername failed: %s\n", strerror(errno));
    } else {
        printf("In processData: checking message heading for %s:%hu\n",
               inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    }

    pthread_mutex_lock(&proxy_threads_lock);
    if (proxy_threads.size() < 2 &&
        ntohs(addr.sin_port) == INTNW_LISTEN_PORT) {

        printf("Looking for new_interface message\n");
        struct CMMSocketControlHdr *hdr = (struct CMMSocketControlHdr *) chunk;
        // XXX: make sure this is in fact the new_interface message for the new csocket
        // XXX:  (probably not strictly necessary, since that message
        // XXX:   is the first message on the csocket, but still
        // XXX:   a good sanity check.)
        if (ntohs(hdr->type) == CMM_CONTROL_MSG_NEW_INTERFACE) {
            if (ntohl(hdr->op.new_interface.RTT) < fg_socket_rtt) {
                fg_socket_rtt = ntohl(hdr->op.new_interface.RTT);
                fg_proxy_thread = pthread_self();
                TIME(fg_proxy_start_time);
                printf("Now treating iface with RTT %d (%s) as FG\n",
                       (int) fg_socket_rtt, inet_ntoa(hdr->op.new_interface.ip_addr));
            }
            proxy_threads.insert(pthread_self());
        }
    }

    bool ret = true;
    if (fg_proxy_thread == pthread_self()) {
        struct timeval now, diff;
        TIME(now);
        TIMEDIFF(fg_proxy_start_time, now, diff);
        pthread_mutex_unlock(&proxy_threads_lock);

        if (diff.tv_sec >= 1) {
            ret = false;
        } else {
            ret = true;
        }
    } else {
        pthread_mutex_unlock(&proxy_threads_lock);
        ret = true;
    }

    printf("%s a %d-byte message to %s:%hu\n",
           ret ? "Proxying" : "Suppressing",
           (int) len,
           inet_ntoa(addr.sin_addr),
           ntohs(addr.sin_port));
    return ret;
}

void
SpottyNetworkFailureTest::tearDown()
{
    if (isReceiver()) {
        EndToEndTestsBase::tearDown();
        stop_proxy_thread(internal_data_proxy_thread);
        stop_proxy_thread(bootstrap_proxy_thread);
    } else {
        EndToEndTestsBase::tearDown();
    }
}

int
connect_to_scout_control()
{
    int sock = socket(PF_INET, SOCK_STREAM, 0);
    handle_error(sock < 0, "creating scout control socket");

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    addr.sin_port = htons(CONTROL_SOCKET_PORT);

    socklen_t addrlen = sizeof(addr);
    int rc = connect(sock, (struct sockaddr *)&addr, addrlen);
    handle_error(rc < 0, "connecting scout control socket");

    return sock;
}

void
SpottyNetworkFailureTest::testOneNetworkFails()
{
    const char expected_str[] = "ABCDEFGHIJ";
    const size_t len = strlen(expected_str);

    char buf[len + 1];
    memset(buf, 0, sizeof(buf));

    if (isReceiver()) {
        int rc = cmm_read(data_sock, buf, len, NULL);
        CPPUNIT_ASSERT_EQUAL((int)len, rc);
        CPPUNIT_ASSERT_EQUAL(string(expected_str), string(buf));

        rc = cmm_write(data_sock, expected_str, len,
                       CMM_LABEL_ONDEMAND, NULL, NULL);
        CPPUNIT_ASSERT_EQUAL((int) len, rc);
    } else {
        int scout_control_sock = connect_to_scout_control();

        sleep(1);
        int rc = cmm_write(data_sock, expected_str, len,
                           CMM_LABEL_ONDEMAND, NULL, NULL);
        CPPUNIT_ASSERT_EQUAL((int)len, rc); // succeeds immediately without waiting for bytes to be sent

        sleep(5);
        char cmd[] = "bg_down\n";
        rc = write(scout_control_sock, cmd, strlen(cmd));
        CPPUNIT_ASSERT_EQUAL((int) strlen(cmd), rc);

        sleep(1);
        memset(buf, 0, sizeof(buf));
        rc = cmm_recv(data_sock, buf, len, MSG_WAITALL, NULL);
        CPPUNIT_ASSERT_EQUAL((int) len, rc);
        CPPUNIT_ASSERT_EQUAL(string(expected_str), string(buf));

        close(scout_control_sock);
    }
}
<commit_msg>Added timeout to the test.  It now fails as expected.<commit_after>#include <cppunit/extensions/HelperMacros.h>
#include "spotty_network_failure_test.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <string.h>
#include <libcmm.h>
#include <libcmm_irob.h>
#include "net_interface.h"
#include "test_common.h"
#include "cmm_socket_control.h"
#include "libcmm_ipc.h"
#include "timeops.h"

#include <string>
#include <vector>
using std::string; using std::vector;

#include "proxy_socket.h"

CPPUNIT_TEST_SUITE_REGISTRATION(SpottyNetworkFailureTest);

/* In the process of revising this test as follows.
 *
 * What this test currently does:
 *  1) Fake a multisocket on the server end.
 *  2) Connect a real multisocket to the fake one.
 *  3) Shut down one of the TCP sockets.
 *  4) Try to send/receive data.
 *
 * The trouble with this approach is that the multisocket can
 *  detect the TCP connection being shut down and react to it.
 *  I really want to test what happens when the TCP connection
 *  just stops receiving any messages (including FIN, for example).
 *
 * What the revised test will do:
 *  1) Create a real multisocket on the server end.
 *  2) Create proxy sockets:
 *     a) Between the IntNW listen socket and the client
 *     b) Between the multisocket's internal listen socket
 *        and the client's connecting csockets
 *  3) Rewrite the necessary messages to keep the multisocket
 *     endpoints unaware of the proxy:
 *     a) The listener port in the initial HELLO response
 *  4) Snoop on the csocket setup messages to determine which
 *     one should be considered FG
 *  5) Stop proxying data on that csocket.
 *  6) Try to send/receive FG data.
 */

const in_port_t SpottyNetworkFailureTest::PROXY_PORT = 4243;
const in_port_t SpottyNetworkFailureTest::INTNW_LISTEN_PORT = 42424;

bool process_chunk(int to_sock, char *chunk, size_t len,
                   SpottyNetworkFailureTest *test,
                   SpottyNetworkFailureTest::chunk_proc_method_t processMethod)
{
    return (test->*processMethod)(to_sock, chunk, len);
}

bool process_bootstrap(int to_sock, char *chunk, size_t len,
                       SpottyNetworkFailureTest *test)
{
    return process_chunk(to_sock, chunk, len, test,
                         &SpottyNetworkFailureTest::processBootstrap);
}

bool process_data(int to_sock, char *chunk, size_t len,
                  SpottyNetworkFailureTest *test)
{
    return process_chunk(to_sock, chunk, len, test,
                         &SpottyNetworkFailureTest::processData);
}

void
SpottyNetworkFailureTest::setupReceiver()
{
    bootstrap_done = false;
    fg_socket_rtt = INT_MAX;
    fg_proxy_thread = (pthread_t) -1;
    pthread_mutex_init(&proxy_threads_lock, NULL);

    setListenPort(PROXY_PORT);
    start_proxy_thread(&bootstrap_proxy_thread, TEST_PORT, PROXY_PORT,
                       (chunk_proc_fn_t) process_bootstrap, this);
    start_proxy_thread(&internal_data_proxy_thread,
                       INTNW_LISTEN_PORT + 1, INTNW_LISTEN_PORT,
                       (chunk_proc_fn_t) process_data, this);

    EndToEndTestsBase::setupReceiver();
}

bool
SpottyNetworkFailureTest::processBootstrap(int to_sock, char *chunk, size_t len)
{
    // overwrite internal-listener port with the proxy's port
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t addrlen = sizeof(addr);
    if (!bootstrap_done &&
        getsockname(to_sock, (struct sockaddr *) &addr, &addrlen) == 0 &&
        ntohs(addr.sin_port) == TEST_PORT) {
        // only modify the hello response, not the request
        struct CMMSocketControlHdr *hdr = (struct CMMSocketControlHdr *) chunk;
        if (ntohs(hdr->type) == CMM_CONTROL_MSG_HELLO) {
            in_port_t listener_port = ntohs(hdr->op.hello.listen_port);
            printf("Overwriting listener port %hu in hello response with proxy port %hu\n",
                   listener_port, INTNW_LISTEN_PORT + 1);
            hdr->op.hello.listen_port = htons(INTNW_LISTEN_PORT + 1);
            bootstrap_done = true;
        }
    }

    return true;
}

bool
SpottyNetworkFailureTest::processData(int to_sock, char *chunk, size_t len)
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t addrlen = sizeof(addr);

    int rc = getpeername(to_sock, (struct sockaddr *) &addr, &addrlen);
    if (rc != 0) {
        fprintf(stderr, "Error: getpeername failed: %s\n", strerror(errno));
    } else {
        printf("In processData: checking message heading for %s:%hu\n",
               inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    }

    pthread_mutex_lock(&proxy_threads_lock);
    if (proxy_threads.size() < 2 &&
        ntohs(addr.sin_port) == INTNW_LISTEN_PORT) {

        printf("Looking for new_interface message\n");
        struct CMMSocketControlHdr *hdr = (struct CMMSocketControlHdr *) chunk;
        // XXX: make sure this is in fact the new_interface message for the new csocket
        // XXX:  (probably not strictly necessary, since that message
        // XXX:   is the first message on the csocket, but still
        // XXX:   a good sanity check.)
        if (ntohs(hdr->type) == CMM_CONTROL_MSG_NEW_INTERFACE) {
            if (ntohl(hdr->op.new_interface.RTT) < fg_socket_rtt) {
                fg_socket_rtt = ntohl(hdr->op.new_interface.RTT);
                fg_proxy_thread = pthread_self();
                TIME(fg_proxy_start_time);
                printf("Now treating iface with RTT %d (%s) as FG\n",
                       (int) fg_socket_rtt, inet_ntoa(hdr->op.new_interface.ip_addr));
            }
            proxy_threads.insert(pthread_self());
        }
    }

    bool ret = true;
    if (fg_proxy_thread == pthread_self()) {
        struct timeval now, diff;
        TIME(now);
        TIMEDIFF(fg_proxy_start_time, now, diff);
        pthread_mutex_unlock(&proxy_threads_lock);

        if (diff.tv_sec >= 1) {
            ret = false;
        } else {
            ret = true;
        }
    } else {
        pthread_mutex_unlock(&proxy_threads_lock);
        ret = true;
    }

    printf("%s a %d-byte message to %s:%hu\n",
           ret ? "Proxying" : "Suppressing",
           (int) len,
           inet_ntoa(addr.sin_addr),
           ntohs(addr.sin_port));
    return ret;
}

void
SpottyNetworkFailureTest::tearDown()
{
    if (isReceiver()) {
        EndToEndTestsBase::tearDown();
        stop_proxy_thread(internal_data_proxy_thread);
        stop_proxy_thread(bootstrap_proxy_thread);
    } else {
        EndToEndTestsBase::tearDown();
    }
}

int
connect_to_scout_control()
{
    int sock = socket(PF_INET, SOCK_STREAM, 0);
    handle_error(sock < 0, "creating scout control socket");

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    addr.sin_port = htons(CONTROL_SOCKET_PORT);

    socklen_t addrlen = sizeof(addr);
    int rc = connect(sock, (struct sockaddr *)&addr, addrlen);
    handle_error(rc < 0, "connecting scout control socket");

    return sock;
}

void
SpottyNetworkFailureTest::testOneNetworkFails()
{
    const char expected_str[] = "ABCDEFGHIJ";
    const size_t len = strlen(expected_str);

    char buf[len + 1];
    memset(buf, 0, sizeof(buf));

    if (isReceiver()) {
        fd_set readable;
        FD_ZERO(&readable);
        FD_SET(data_sock, &readable);
        struct timeval timeout = {4, 0};
        int rc = cmm_select(data_sock + 1, &readable, NULL, NULL, &timeout);
        CPPUNIT_ASSERT_EQUAL(1, rc);

        rc = cmm_read(data_sock, buf, len, NULL);
        CPPUNIT_ASSERT_EQUAL((int)len, rc);
        CPPUNIT_ASSERT_EQUAL(string(expected_str), string(buf));

        rc = cmm_write(data_sock, expected_str, len,
                       CMM_LABEL_ONDEMAND, NULL, NULL);
        CPPUNIT_ASSERT_EQUAL((int) len, rc);
    } else {
        int scout_control_sock = connect_to_scout_control();

        sleep(1);
        int rc = cmm_write(data_sock, expected_str, len,
                           CMM_LABEL_ONDEMAND, NULL, NULL);
        CPPUNIT_ASSERT_EQUAL((int)len, rc); // succeeds immediately without waiting for bytes to be sent

        sleep(5);
        char cmd[] = "bg_down\n";
        rc = write(scout_control_sock, cmd, strlen(cmd));
        CPPUNIT_ASSERT_EQUAL((int) strlen(cmd), rc);

        sleep(1);
        memset(buf, 0, sizeof(buf));
        rc = cmm_recv(data_sock, buf, len, MSG_WAITALL, NULL);
        CPPUNIT_ASSERT_EQUAL((int) len, rc);
        CPPUNIT_ASSERT_EQUAL(string(expected_str), string(buf));

        close(scout_control_sock);
    }
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2019-present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/* HIT_START
 * BUILD: %t %s ../test_common.cpp EXCLUDE_HIP_PLATFORM nvcc vdi
 * TEST: %t
 * HIT_END
 */
#include "test_common.h"

//typedef char T;
const char *sampleName = "simpleTexture3D";

// Texture reference for 3D texture
#if __HIP__
__hip_pinned_shadow__
#endif
texture<float, hipTextureType3D, hipReadModeElementType> texf;

#if __HIP__
__hip_pinned_shadow__
#endif
texture<int, hipTextureType3D, hipReadModeElementType> texi;

#if __HIP__
__hip_pinned_shadow__
#endif
texture<char, hipTextureType3D, hipReadModeElementType> texc;

template <typename T>
__global__ void simpleKernel3DArray(T* outputData,
                                    int width,
                                    int height,int depth)
{
    for (int i = 0; i < depth; i++) {
       for (int j = 0; j < height; j++) {
           for (int k = 0; k < width; k++) {
               if(std::is_same<T, float>::value)
                   outputData[i*width*height + j*width + k] = tex3D(texf, texf.textureObject, k, j, i);
               else if(std::is_same<T, int>::value)
                   outputData[i*width*height + j*width + k] = tex3D(texi, texi.textureObject, k, j, i);
               else if(std::is_same<T, char>::value)
                   outputData[i*width*height + j*width + k] = tex3D(texc, texc.textureObject, k, j, i);
           }
       }
    }
}

////////////////////////////////////////////////////////////////////////////////
//! Run a simple test for tex3D
////////////////////////////////////////////////////////////////////////////////
template <typename T>
void runTest(int width,int height,int depth,texture<T, hipTextureType3D, hipReadModeElementType> *tex)
{
    unsigned int size = width * height * depth * sizeof(T);
    T* hData = (T*) malloc(size);
    memset(hData, 0, size);

    for (int i = 0; i < depth; i++) {
        for (int j = 0; j < height; j++) {
            for (int k = 0; k < width; k++) {
                hData[i*width*height + j*width +k] = i*width*height + j*width + k;
            }
        }
    }

    // Allocate array and copy image data
    hipChannelFormatDesc channelDesc = hipCreateChannelDesc(sizeof(T)*8, 0, 0, 0, hipChannelFormatKindSigned);
    hipArray *arr;

    HIPCHECK(hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, height, depth), hipArrayCubemap));
    hipMemcpy3DParms myparms = {0};
    myparms.srcPos = make_hipPos(0,0,0);
    myparms.dstPos = make_hipPos(0,0,0);
    myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height);
    myparms.dstArray = arr;
    myparms.extent = make_hipExtent(width, height, depth);
    myparms.kind = hipMemcpyHostToDevice;
    HIPCHECK(hipMemcpy3D(&myparms));

    // set texture parameters
    tex->addressMode[0] = hipAddressModeWrap;
    tex->addressMode[1] = hipAddressModeWrap;
    tex->filterMode = hipFilterModePoint;
    tex->normalized = false;

    // Bind the array to the texture
    HIPCHECK(hipBindTextureToArray(*tex, arr, channelDesc));

    // Allocate device memory for result
    T* dData = NULL;
    hipMalloc((void **) &dData, size);

    hipLaunchKernelGGL(simpleKernel3DArray, dim3(1,1,1), dim3(1,1,1), 0, 0, dData, width, height, depth);
    HIPCHECK(hipDeviceSynchronize());

    // Allocate mem for the result on host side
    T *hOutputData = (T*) malloc(size);
    memset(hOutputData, 0,  size);

    // copy result from device to host
    HIPCHECK(hipMemcpy(hOutputData, dData, size, hipMemcpyDeviceToHost));
    HipTest::checkArray(hData,hOutputData,width,height,depth);

    hipFree(dData);
    hipFreeArray(arr);
    free(hData);
    free(hOutputData);
}

////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
    printf("%s starting...\n", sampleName);
    for(int i=1;i<25;i++)
    {
        runTest<float>(i,i,i,&texf);
        runTest<int>(i+1,i,i,&texi);
        runTest<char>(i,i+1,i,&texc);
    }
    passed();
}

<commit_msg>Enable simpleTexture3D test for VDI<commit_after>/*
Copyright (c) 2019-present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/* HIT_START
 * BUILD: %t %s ../test_common.cpp EXCLUDE_HIP_PLATFORM nvcc
 * TEST: %t
 * HIT_END
 */
#include "test_common.h"

//typedef char T;
const char *sampleName = "simpleTexture3D";

// Texture reference for 3D texture
#if __HIP__
__hip_pinned_shadow__
#endif
texture<float, hipTextureType3D, hipReadModeElementType> texf;

#if __HIP__
__hip_pinned_shadow__
#endif
texture<int, hipTextureType3D, hipReadModeElementType> texi;

#if __HIP__
__hip_pinned_shadow__
#endif
texture<char, hipTextureType3D, hipReadModeElementType> texc;

template <typename T>
__global__ void simpleKernel3DArray(T* outputData,
                                    int width,
                                    int height,int depth)
{
    for (int i = 0; i < depth; i++) {
        for (int j = 0; j < height; j++) {
            for (int k = 0; k < width; k++) {
                if(std::is_same<T, float>::value)
                    outputData[i*width*height + j*width + k] = tex3D(texf, k, j, i);
                else if(std::is_same<T, int>::value)
                    outputData[i*width*height + j*width + k] = tex3D(texi, k, j, i);
                else if(std::is_same<T, char>::value)
                    outputData[i*width*height + j*width + k] = tex3D(texc, k, j, i);
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
//! Run a simple test for tex3D
////////////////////////////////////////////////////////////////////////////////
template <typename T>
void runTest(int width,int height,int depth,texture<T, hipTextureType3D, hipReadModeElementType> *tex)
{
    unsigned int size = width * height * depth * sizeof(T);
    T* hData = (T*) malloc(size);
    memset(hData, 0, size);

    for (int i = 0; i < depth; i++) {
        for (int j = 0; j < height; j++) {
            for (int k = 0; k < width; k++) {
                hData[i*width*height + j*width +k] = i*width*height + j*width + k;
            }
        }
    }

    // Allocate array and copy image data
    hipChannelFormatDesc channelDesc = hipCreateChannelDesc<T>();
    hipArray *arr;

    HIPCHECK(hipMalloc3DArray(&arr, &channelDesc, make_hipExtent(width, height, depth), hipArrayDefault));
    hipMemcpy3DParms myparms = {0};
    myparms.srcPos = make_hipPos(0,0,0);
    myparms.dstPos = make_hipPos(0,0,0);
    myparms.srcPtr = make_hipPitchedPtr(hData, width * sizeof(T), width, height);
    myparms.dstArray = arr;
    myparms.extent = make_hipExtent(width, height, depth);
    myparms.kind = hipMemcpyHostToDevice;
    HIPCHECK(hipMemcpy3D(&myparms));

    // set texture parameters
    tex->addressMode[0] = hipAddressModeWrap;
    tex->addressMode[1] = hipAddressModeWrap;
    tex->filterMode = hipFilterModePoint;
    tex->normalized = false;

    // Bind the array to the texture
    HIPCHECK(hipBindTextureToArray(*tex, arr, channelDesc));

    // Allocate device memory for result
    T* dData = NULL;
    hipMalloc((void **) &dData, size);

    hipLaunchKernelGGL(simpleKernel3DArray, dim3(1,1,1), dim3(1,1,1), 0, 0, dData, width, height, depth);
    HIPCHECK(hipDeviceSynchronize());

    // Allocate mem for the result on host side
    T *hOutputData = (T*) malloc(size);
    memset(hOutputData, 0,  size);

    // copy result from device to host
    HIPCHECK(hipMemcpy(hOutputData, dData, size, hipMemcpyDeviceToHost));
    HipTest::checkArray(hData,hOutputData,width,height,depth);

    hipFree(dData);
    hipFreeArray(arr);
    free(hData);
    free(hOutputData);
}

////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
    printf("%s starting...\n", sampleName);
    for(int i=1;i<25;i++)
    {
        runTest<float>(i,i,i,&texf);
        runTest<int>(i+1,i,i,&texi);
        runTest<char>(i,i+1,i,&texc);
    }
    passed();
}

<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX600, RX200 グループ・CMT I/O 制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2013, 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/intr_utils.hpp"
#include "common/vect.h"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  CMT I/O クラス
		@param[in]	CMT	チャネルクラス
		@param[in]	TASK	タイマー動作クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class CMT, class TASK = utils::null_task>
	class cmt_io {

		uint8_t		level_;

		void sleep_() const { asm("nop"); }

		static TASK	task_;

		static volatile uint32_t counter_;

		static INTERRUPT_FUNC void i_task_()
		{
			++counter_;
			task_();
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		cmt_io() : level_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  開始
			@param[in]	freq	タイマー周波数
			@param[in]	level	割り込みレベル（０ならポーリング）
			@param[in]	task	割り込み時に起動する関数 @n
								※割り込み関数は属性「INTERRUPT_FUNC」を付加する。
			@return タイマー周波数が範囲を超えた場合「false」を返す
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t freq, uint8_t level = 0, void (*task)() = nullptr) noexcept
		{
			if(freq == 0) return false;

			uint32_t cmcor = CMT::PCLK / freq / 4;
			if(cmcor & 1) {
				cmcor >>= 1;
				++cmcor;
			} else {
				cmcor >>= 1;
			}

			uint8_t cks = 0;
			while(cmcor > 65536) {
				cmcor >>= 2;
				++cks;
			}
			if(cks > 3 || cmcor == 0) {
				return false;
			}

			level_ = level;

			power_mgr::turn(CMT::PERIPHERAL);

			CMT::enable(false);

			CMT::CMCNT = 0;
		    CMT::CMCOR = cmcor - 1;

			counter_ = 0;

			if(level_ > 0) {
				if(task != nullptr) {
					icu_mgr::set_interrupt(CMT::IVEC, task, level_);
				} else {
					icu_mgr::set_interrupt(CMT::IVEC, i_task_, level_);
				}
			    CMT::CMCR = CMT::CMCR.CKS.b(cks) | CMT::CMCR.CMIE.b();
			} else {
				icu_mgr::set_interrupt(CMT::IVEC, nullptr, 0);
			    CMT::CMCR = CMT::CMCR.CKS.b(cks);
			}
			CMT::enable();

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  廃棄（割り込みを停止して、ユニットを停止）
			@param[in]	power	電源を停止しない場合「true」
		*/
		//-----------------------------------------------------------------//
		void destroy(bool power = false) noexcept
		{
		    CMT::CMCR.CMIE = 0;
			CMT::enable(false);
			power_mgr::turn(CMT::PERIPHERAL, power);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  割り込みと同期
		*/
		//-----------------------------------------------------------------//
		void sync() const noexcept
		{
			if(level_ > 0) {
				volatile uint32_t cnt = counter_;
				while(cnt == counter_) sleep_();
			} else {
				auto ref = CMT::CMCNT();
				while(ref <= CMT::CMCNT()) sleep_();
				task_();
				++counter_;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  割り込みカウンターの値を設定
			@param[in]	n	割り込みカウンターの値
		*/
		//-----------------------------------------------------------------//
		static void set_counter(uint32_t n) noexcept { counter_ = n; }

		//-----------------------------------------------------------------//
		/*!
			@brief  割り込みカウンターの値を取得
			@return 割り込みカウンターの値
		*/
		//-----------------------------------------------------------------//
		static uint32_t get_counter() noexcept { return counter_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  CMCNT レジスターの値を取得
			@return CMCNT レジスター
		*/
		//-----------------------------------------------------------------//
		uint16_t get_cmt_count() const noexcept { return CMT::CMCNT(); }

		//-----------------------------------------------------------------//
		/*!
			@brief  CMCOR レジスターの値を取得
			@return CMCOR レジスター
		*/
		//-----------------------------------------------------------------//
		uint16_t get_cmp_count() const noexcept { return CMT::CMCOR(); }

		//-----------------------------------------------------------------//
		/*!
			@brief  TASK クラスの参照
			@return TASK クラス
		*/
		//-----------------------------------------------------------------//
		static TASK& at_task() noexcept { return task_; }
	};

	template <class CMT, class TASK> volatile uint32_t cmt_io<CMT, TASK>::counter_ = 0;
	template <class CMT, class TASK> TASK cmt_io<CMT, TASK>::task_;
}
<commit_msg>Update: Add CMT real rate API<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX600, RX200 グループ・CMT I/O 制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2013, 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/intr_utils.hpp"
#include "common/vect.h"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  CMT I/O クラス
		@param[in]	CMT	チャネルクラス
		@param[in]	TASK	タイマー動作クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class CMT, class TASK = utils::null_task>
	class cmt_io {

		uint8_t		level_;
		uint32_t	rate_;

		void sleep_() const { asm("nop"); }

		static TASK	task_;

		static volatile uint32_t counter_;

		static INTERRUPT_FUNC void i_task_()
		{
			++counter_;
			task_();
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		cmt_io() : level_(0), rate_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  開始
			@param[in]	freq	タイマー周波数
			@param[in]	level	割り込みレベル（０ならポーリング）
			@param[in]	task	割り込み時に起動する関数 @n
								※割り込み関数は属性「INTERRUPT_FUNC」を付加する。
			@return タイマー周波数が範囲を超えた場合「false」を返す
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t freq, uint8_t level = 0, void (*task)() = nullptr) noexcept
		{
			if(freq == 0) return false;

			uint32_t cmcor = CMT::PCLK / freq / 4;
			cmcor++;
			cmcor >>= 1;

			uint8_t cks = 0;
			while(cmcor > 65536) {
				cmcor >>= 2;
				++cks;
			}
			if(cks > 3 || cmcor == 0) {
				return false;
			}
			rate_ = freq;

			level_ = level;

			power_mgr::turn(CMT::PERIPHERAL);

			CMT::enable(false);

			CMT::CMCNT = 0;
		    CMT::CMCOR = cmcor - 1;

			counter_ = 0;

			if(level_ > 0) {
				if(task != nullptr) {
					icu_mgr::set_interrupt(CMT::IVEC, task, level_);
				} else {
					icu_mgr::set_interrupt(CMT::IVEC, i_task_, level_);
				}
			    CMT::CMCR = CMT::CMCR.CKS.b(cks) | CMT::CMCR.CMIE.b();
			} else {
				icu_mgr::set_interrupt(CMT::IVEC, nullptr, 0);
			    CMT::CMCR = CMT::CMCR.CKS.b(cks);
			}
			CMT::enable();

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  廃棄（割り込みを停止して、ユニットを停止）
			@param[in]	power	電源を停止しない場合「true」
		*/
		//-----------------------------------------------------------------//
		void destroy(bool power = false) noexcept
		{
		    CMT::CMCR.CMIE = 0;
			CMT::enable(false);
			power_mgr::turn(CMT::PERIPHERAL, power);
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  割り込みと同期
		*/
		//-----------------------------------------------------------------//
		void sync() const noexcept
		{
			if(level_ > 0) {
				volatile uint32_t cnt = counter_;
				while(cnt == counter_) sleep_();
			} else {
				auto ref = CMT::CMCNT();
				while(ref <= CMT::CMCNT()) sleep_();
				task_();
				++counter_;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  割り込みカウンターの値を設定
			@param[in]	n	割り込みカウンターの値
		*/
		//-----------------------------------------------------------------//
		static void set_counter(uint32_t n) noexcept { counter_ = n; }

		//-----------------------------------------------------------------//
		/*!
			@brief  割り込みカウンターの値を取得
			@return 割り込みカウンターの値
		*/
		//-----------------------------------------------------------------//
		static uint32_t get_counter() noexcept { return counter_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  CMCNT レジスターの値を取得
			@return CMCNT レジスター
		*/
		//-----------------------------------------------------------------//
		uint16_t get_cmt_count() const noexcept { return CMT::CMCNT(); }

		//-----------------------------------------------------------------//
		/*!
			@brief  CMCOR レジスターの値を取得
			@return CMCOR レジスター
		*/
		//-----------------------------------------------------------------//
		uint16_t get_cmp_count() const noexcept { return CMT::CMCOR(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	周期を取得
			@param[in]	real	「true」にした場合、内部で計算されたリアルな値
			@return 周期
		 */
		//-----------------------------------------------------------------//
		uint32_t get_rate(bool real = false) const noexcept
		{
			if(real) {
				uint32_t rate = CMT::PCLK / (static_cast<uint32_t>(CMT::CMCOR()) + 1);
				rate /= 4 << (CMT::CMCR.CKS() * 2);
				return rate;
			} else {
				return rate_;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  TASK クラスの参照
			@return TASK クラス
		*/
		//-----------------------------------------------------------------//
		static TASK& at_task() noexcept { return task_; }
	};

	template <class CMT, class TASK> volatile uint32_t cmt_io<CMT, TASK>::counter_ = 0;
	template <class CMT, class TASK> TASK cmt_io<CMT, TASK>::task_;
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX マイコン、デバイス固有ヘッダー
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/io_utils.hpp"

#if defined(SIG_RX24T)
#include "RX24T/peripheral.hpp"
#include "RX24T/system.hpp"
#include "RX24T/power_mgr.hpp"
#include "RX24T/icu.hpp"
#include "RX24T/icu_mgr.hpp"
#include "RX24T/port_map.hpp"

#elif defined(SIG_RX62N)
#include "RX62x/system.hpp"
#include "RX62x/icu.hpp"
#include "RX62x/icu_mgr.hpp"

#elif defined(SIG_RX64M) || defined(SIG_RX71M)
#include "RX600/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX600/power_mgr.hpp"
#include "RX600/icu.hpp"
#include "RX600/icu_mgr.hpp"
#include "RX600/port_map.hpp"

#elif defined(SIG_RX72M)
#include "RX72M/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX72M/power_mgr.hpp"
#include "RX72M/icu.hpp"
#include "RX72M/icu_mgr.hpp"
#include "RX72M/port_map.hpp"

#elif defined(SIG_RX72N)
#include "RX72N/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX72N/power_mgr.hpp"
#include "RX72N/icu.hpp"
#include "RX72N/icu_mgr.hpp"
#include "RX72N/port_map.hpp"

#elif defined(SIG_RX65N)
#include "RX65x/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX65x/power_mgr.hpp"
#include "RX65x/icu.hpp"
#include "RX65x/icu_mgr.hpp"
#include "RX65x/port_map.hpp"

#elif defined(SIG_RX66T)
#include "RX66T/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX66T/power_mgr.hpp"
#include "RX66T/icu.hpp"
#include "RX66T/icu_mgr.hpp"
#include "RX66T/port_map.hpp"

#elif defined(SIG_RX72T)
#include "RX72T/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX72T/power_mgr.hpp"
#include "RX72T/icu.hpp"
#include "RX72T/icu_mgr.hpp"
#include "RX72T/port_map.hpp"

#else
#  error "device.hpp: Requires SIG_XXX to be defined"
#endif
<commit_msg>Update: include path (port_map_mtu.hpp)<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX マイコン、デバイス固有ヘッダー
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/io_utils.hpp"

#if defined(SIG_RX24T)
#include "RX24T/peripheral.hpp"
#include "RX24T/system.hpp"
#include "RX24T/power_mgr.hpp"
#include "RX24T/icu.hpp"
#include "RX24T/icu_mgr.hpp"
#include "RX24T/port_map.hpp"
#include "RX24T/port_map_mtu.hpp"

#elif defined(SIG_RX62N)
#include "RX62x/system.hpp"
#include "RX62x/icu.hpp"
#include "RX62x/icu_mgr.hpp"

#elif defined(SIG_RX64M) || defined(SIG_RX71M)
#include "RX600/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX600/power_mgr.hpp"
#include "RX600/icu.hpp"
#include "RX600/icu_mgr.hpp"
#include "RX600/port_map.hpp"
#include "RX600/port_map_mtu.hpp"

#elif defined(SIG_RX72M)
#include "RX72M/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX72M/power_mgr.hpp"
#include "RX72M/icu.hpp"
#include "RX72M/icu_mgr.hpp"
#include "RX72M/port_map.hpp"
#include "RX72M/port_map_mtu.hpp"

#elif defined(SIG_RX72N)
#include "RX72N/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX72N/power_mgr.hpp"
#include "RX72N/icu.hpp"
#include "RX72N/icu_mgr.hpp"
#include "RX72N/port_map.hpp"
#include "RX72N/port_map_mtu.hpp"

#elif defined(SIG_RX65N)
#include "RX65x/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX65x/power_mgr.hpp"
#include "RX65x/icu.hpp"
#include "RX65x/icu_mgr.hpp"
#include "RX65x/port_map.hpp"
#include "RX65x/port_map_mtu.hpp"

#elif defined(SIG_RX66T)
#include "RX66T/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX66T/power_mgr.hpp"
#include "RX66T/icu.hpp"
#include "RX66T/icu_mgr.hpp"
#include "RX66T/port_map.hpp"
#include "RX66T/port_map_mtu.hpp"

#elif defined(SIG_RX72T)
#include "RX72T/peripheral.hpp"
#include "RX600/system.hpp"
#include "RX72T/power_mgr.hpp"
#include "RX72T/icu.hpp"
#include "RX72T/icu_mgr.hpp"
#include "RX72T/port_map.hpp"
#include "RX72T/port_map_mtu.hpp"

#else
#  error "device.hpp: Requires SIG_XXX to be defined"
#endif
<|endoftext|>