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

#include "chrome/gpu/gpu_video_decoder.h"

#include "base/command_line.h"
#include "chrome/common/child_thread.h"
#include "chrome/common/gpu_messages.h"
#include "chrome/gpu/gpu_channel.h"
#include "chrome/gpu/media/fake_gl_video_decode_engine.h"
#include "chrome/gpu/media/fake_gl_video_device.h"
#include "media/base/data_buffer.h"
#include "media/base/media_switches.h"
#include "media/base/video_frame.h"

#if defined(OS_WIN)
#include "chrome/gpu/media/mft_angle_video_device.h"
#include "media/video/mft_h264_decode_engine.h"
#include <d3d9.h>
#endif

void GpuVideoDecoder::OnChannelConnected(int32 peer_pid) {
}

void GpuVideoDecoder::OnChannelError() {
}

void GpuVideoDecoder::OnMessageReceived(const IPC::Message& msg) {
  IPC_BEGIN_MESSAGE_MAP(GpuVideoDecoder, msg)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Initialize,
                        OnInitialize)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Destroy,
                        OnUninitialize)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Flush,
                        OnFlush)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Preroll,
                        OnPreroll)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_EmptyThisBuffer,
                        OnEmptyThisBuffer)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_ProduceVideoFrame,
                        OnProduceVideoFrame)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_VideoFrameAllocated,
                        OnVideoFrameAllocated)
    IPC_MESSAGE_UNHANDLED_ERROR()
  IPC_END_MESSAGE_MAP()
}

bool GpuVideoDecoder::CreateInputTransferBuffer(
    uint32 size,
    base::SharedMemoryHandle* handle) {
  input_transfer_buffer_.reset(new base::SharedMemory);
  if (!input_transfer_buffer_.get())
    return false;

  if (!input_transfer_buffer_->Create(std::string(), false, false, size))
    return false;

  if (!input_transfer_buffer_->Map(size))
    return false;

  if (!input_transfer_buffer_->ShareToProcess(renderer_handle_, handle))
    return false;

  return true;
}

void GpuVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) {
  info_ = info;
  GpuVideoDecoderInitDoneParam param;
  param.success = false;
  param.input_buffer_handle = base::SharedMemory::NULLHandle();

  if (!info.success) {
    SendInitializeDone(param);
    return;
  }

  // TODO(jiesun): Check the assumption of input size < original size.
  param.input_buffer_size = config_.width * config_.height * 3 / 2;
  if (!CreateInputTransferBuffer(param.input_buffer_size,
                                 &param.input_buffer_handle)) {
    SendInitializeDone(param);
    return;
  }

  param.success = true;
  SendInitializeDone(param);
}

void GpuVideoDecoder::OnUninitializeComplete() {
  SendUninitializeDone();
}

void GpuVideoDecoder::OnFlushComplete() {
  SendFlushDone();
}

void GpuVideoDecoder::OnSeekComplete() {
  SendPrerollDone();
}

void GpuVideoDecoder::OnError() {
  NOTIMPLEMENTED();
}

void GpuVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) {
  NOTIMPLEMENTED();
}

void GpuVideoDecoder::ProduceVideoSample(scoped_refptr<Buffer> buffer) {
  SendEmptyBufferDone();
}

void GpuVideoDecoder::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) {
  if (frame->IsEndOfStream()) {
    SendConsumeVideoFrame(kGpuVideoInvalidFrameId, 0, 0, kGpuVideoEndOfStream);
    return;
  }

  int32 frame_id = kGpuVideoInvalidFrameId;
  for (VideoFrameMap::iterator i = video_frame_map_.begin();
       i != video_frame_map_.end(); ++i) {
    if (i->second == frame) {
      frame_id = i->first;
      break;
    }
  }
  DCHECK_NE(-1, frame_id) << "VideoFrame not recognized";

  SendConsumeVideoFrame(frame_id, frame->GetTimestamp().InMicroseconds(),
                        frame->GetDuration().InMicroseconds(), 0);
}

void* GpuVideoDecoder::GetDevice() {
  bool ret = gles2_decoder_->MakeCurrent();
  DCHECK(ret) << "Failed to switch context";

  // Simply delegate the method call to GpuVideoDevice.
  return video_device_->GetDevice();
}

void GpuVideoDecoder::AllocateVideoFrames(
    int n, size_t width, size_t height, media::VideoFrame::Format format,
    std::vector<scoped_refptr<media::VideoFrame> >* frames, Task* task) {
  // Since the communication between Renderer and GPU process is by GL textures.
  // We need to obtain a set of GL textures by sending IPC commands to the
  // Renderer process. The recipient of these commands will be IpcVideoDecoder.
  //
  // After IpcVideoDecoder replied with a set of textures. We'll assign these
  // textures to GpuVideoDevice. They will be used to generate platform
  // specific VideoFrames objects that are used by VideoDecodeEngine.
  //
  // After GL textures are assigned we'll proceed with allocation the
  // VideoFrames. GpuVideoDevice::CreateVideoFramesFromGlTextures() will be
  // called.
  //
  // When GpuVideoDevice replied with a set of VideoFrames we'll give
  // that to VideoDecodeEngine and the cycle of video frame allocation is done.
  //
  // Note that this method is called when there's no video frames allocated or
  // they were all released.
  DCHECK(video_frame_map_.empty());

  // Save the parameters for allocation.
  pending_allocation_.reset(new PendingAllocation());
  pending_allocation_->n = n;
  pending_allocation_->width = width;
  pending_allocation_->height = height;
  pending_allocation_->format = format;
  pending_allocation_->frames = frames;
  pending_allocation_->task = task;
  SendAllocateVideoFrames(n, width, height, format);
}

void GpuVideoDecoder::ReleaseAllVideoFrames() {
  // This method will first call to GpuVideoDevice to release all the resource
  // associated with a VideoFrame.
  //
  // And then we'll call GpuVideoDevice::ReleaseVideoFrame() to remove the set
  // of Gl textures associated with the context.
  //
  // And finally we'll send IPC commands to IpcVideoDecoder to destroy all
  // GL textures generated.
  bool ret = gles2_decoder_->MakeCurrent();
  DCHECK(ret) << "Failed to switch context";

  for (VideoFrameMap::iterator i = video_frame_map_.begin();
       i != video_frame_map_.end(); ++i) {
    video_device_->ReleaseVideoFrame(i->second);
  }
  video_frame_map_.clear();
  SendReleaseAllVideoFrames();
}

void GpuVideoDecoder::UploadToVideoFrame(void* buffer,
                                         scoped_refptr<media::VideoFrame> frame,
                                         Task* task) {
  // This method is called by VideoDecodeEngine to upload a buffer to a
  // VideoFrame. We should just delegate this to GpuVideoDevice which contains
  // the actual implementation.
  bool ret = gles2_decoder_->MakeCurrent();
  DCHECK(ret) << "Failed to switch context";

  // Actually doing the upload on the main thread.
  ret = video_device_->UploadToVideoFrame(buffer, frame);
  DCHECK(ret) << "Failed to upload video content to a VideoFrame.";
  task->Run();
  delete task;
}

void GpuVideoDecoder::Destroy(Task* task) {
  //  TODO(hclam): I still need to think what I should do here.
}

void GpuVideoDecoder::SetVideoDecodeEngine(media::VideoDecodeEngine* engine) {
  decode_engine_.reset(engine);
}

void GpuVideoDecoder::SetGpuVideoDevice(GpuVideoDevice* device) {
  video_device_.reset(device);
}

GpuVideoDecoder::GpuVideoDecoder(
    MessageLoop* message_loop,
    int32 decoder_host_id,
    IPC::Message::Sender* sender,
    base::ProcessHandle handle,
    gpu::gles2::GLES2Decoder* decoder)
    : message_loop_(message_loop),
      decoder_host_id_(decoder_host_id),
      sender_(sender),
      renderer_handle_(handle),
      gles2_decoder_(decoder) {
  memset(&config_, 0, sizeof(config_));
  memset(&info_, 0, sizeof(info_));

  // TODO(jiesun): find a better way to determine which VideoDecodeEngine
  // to return on current platform.
#if defined(OS_WIN)
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kEnableAcceleratedDecoding)) {
    decode_engine_.reset(new media::MftH264DecodeEngine(true));
    video_device_.reset(new MftAngleVideoDevice());
  }
#else
  decode_engine_.reset(new FakeGlVideoDecodeEngine());
  video_device_.reset(new FakeGlVideoDevice());
#endif
}

void GpuVideoDecoder::OnInitialize(const GpuVideoDecoderInitParam& param) {
  // TODO(jiesun): codec id should come from |param|.
  config_.codec = media::kCodecH264;
  config_.width = param.width;
  config_.height = param.height;
  config_.opaque_context = NULL;
  decode_engine_->Initialize(message_loop_, this, this, config_);
}

void GpuVideoDecoder::OnUninitialize() {
  decode_engine_->Uninitialize();
}

void GpuVideoDecoder::OnFlush() {
  decode_engine_->Flush();
}

void GpuVideoDecoder::OnPreroll() {
  decode_engine_->Seek();
}

void GpuVideoDecoder::OnEmptyThisBuffer(
    const GpuVideoDecoderInputBufferParam& buffer) {
  DCHECK(input_transfer_buffer_->memory());

  uint8* src = static_cast<uint8*>(input_transfer_buffer_->memory());

  scoped_refptr<Buffer> input_buffer;
  uint8* dst = buffer.size ? new uint8[buffer.size] : NULL;
  input_buffer = new media::DataBuffer(dst, buffer.size);
  memcpy(dst, src, buffer.size);
  SendEmptyBufferACK();

  // Delegate the method call to VideoDecodeEngine.
  decode_engine_->ConsumeVideoSample(input_buffer);
}

void GpuVideoDecoder::OnProduceVideoFrame(int32 frame_id) {
  VideoFrameMap::iterator i = video_frame_map_.find(frame_id);
  if (i == video_frame_map_.end()) {
    NOTREACHED() << "Received a request of unknown frame ID.";
  }

  // Delegate the method call to VideoDecodeEngine.
  decode_engine_->ProduceVideoFrame(i->second);
}

void GpuVideoDecoder::OnVideoFrameAllocated(int32 frame_id,
                                            std::vector<uint32> textures) {
  bool ret = gles2_decoder_->MakeCurrent();
  DCHECK(ret) << "Failed to switch context";

  // This method is called in response to a video frame allocation request sent
  // to the Renderer process.
  // We should use the textures to generate a VideoFrame by using
  // GpuVideoDevice. The VideoFrame created is added to the internal map.
  // If we have generated enough VideoFrame, we call |allocation_callack_| to
  // complete the allocation process.
  for (size_t i = 0; i < textures.size(); ++i) {
    media::VideoFrame::GlTexture gl_texture;
    // Translate the client texture id to service texture id.
    ret = gles2_decoder_->GetServiceTextureId(textures[i], &gl_texture);
    DCHECK(ret) << "Cannot translate client texture ID to service ID";
    textures[i] = gl_texture;
  }

  // Use GpuVideoDevice to allocate VideoFrame objects.
  scoped_refptr<media::VideoFrame> frame;

  ret = video_device_->CreateVideoFrameFromGlTextures(
      pending_allocation_->width, pending_allocation_->height,
      pending_allocation_->format, textures, &frame);

  DCHECK(ret) << "Failed to allocation VideoFrame from GL textures)";
  pending_allocation_->frames->push_back(frame);
  video_frame_map_.insert(std::make_pair(frame_id, frame));

  if (video_frame_map_.size() == pending_allocation_->n) {
    pending_allocation_->task->Run();
    delete pending_allocation_->task;
    pending_allocation_.reset();
  }
}

void GpuVideoDecoder::SendInitializeDone(
    const GpuVideoDecoderInitDoneParam& param) {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_InitializeACK(decoder_host_id(), param))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_InitializeACK failed";
  }
}

void GpuVideoDecoder::SendUninitializeDone() {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_DestroyACK(decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_DestroyACK failed";
  }
}

void GpuVideoDecoder::SendFlushDone() {
  if (!sender_->Send(new GpuVideoDecoderHostMsg_FlushACK(decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_FlushACK failed";
  }
}

void GpuVideoDecoder::SendPrerollDone() {
  if (!sender_->Send(new GpuVideoDecoderHostMsg_PrerollDone(
          decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_PrerollDone failed";
  }
}

void GpuVideoDecoder::SendEmptyBufferDone() {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_EmptyThisBufferDone(decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBufferDone failed";
  }
}

void GpuVideoDecoder::SendEmptyBufferACK() {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_EmptyThisBufferACK(decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBufferACK failed";
  }
}

void GpuVideoDecoder::SendConsumeVideoFrame(
    int32 frame_id, int64 timestamp, int64 duration, int32 flags) {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_ConsumeVideoFrame(
              decoder_host_id(), frame_id, timestamp, duration, flags))) {
    LOG(ERROR) << "GpuVideoDecodeHostMsg_ConsumeVideoFrame failed.";
  }
}

void GpuVideoDecoder::SendAllocateVideoFrames(
    int n, size_t width, size_t height, media::VideoFrame::Format format) {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_AllocateVideoFrames(
              decoder_host_id(), n, width, height,
              static_cast<int32>(format)))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_AllocateVideoFrames failed";
  }
}

void GpuVideoDecoder::SendReleaseAllVideoFrames() {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_ReleaseAllVideoFrames(
              decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_ReleaseAllVideoFrames failed";
  }
}
<commit_msg>Remove the usage of MFT related objects so they don't get linked.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/gpu/gpu_video_decoder.h"

#include "base/command_line.h"
#include "chrome/common/child_thread.h"
#include "chrome/common/gpu_messages.h"
#include "chrome/gpu/gpu_channel.h"
#include "chrome/gpu/media/fake_gl_video_decode_engine.h"
#include "chrome/gpu/media/fake_gl_video_device.h"
#include "media/base/data_buffer.h"
#include "media/base/media_switches.h"
#include "media/base/video_frame.h"

#if defined(OS_WIN)
#include "chrome/gpu/media/mft_angle_video_device.h"
#include "media/video/mft_h264_decode_engine.h"
#include <d3d9.h>
#endif

void GpuVideoDecoder::OnChannelConnected(int32 peer_pid) {
}

void GpuVideoDecoder::OnChannelError() {
}

void GpuVideoDecoder::OnMessageReceived(const IPC::Message& msg) {
  IPC_BEGIN_MESSAGE_MAP(GpuVideoDecoder, msg)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Initialize,
                        OnInitialize)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Destroy,
                        OnUninitialize)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Flush,
                        OnFlush)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_Preroll,
                        OnPreroll)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_EmptyThisBuffer,
                        OnEmptyThisBuffer)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_ProduceVideoFrame,
                        OnProduceVideoFrame)
    IPC_MESSAGE_HANDLER(GpuVideoDecoderMsg_VideoFrameAllocated,
                        OnVideoFrameAllocated)
    IPC_MESSAGE_UNHANDLED_ERROR()
  IPC_END_MESSAGE_MAP()
}

bool GpuVideoDecoder::CreateInputTransferBuffer(
    uint32 size,
    base::SharedMemoryHandle* handle) {
  input_transfer_buffer_.reset(new base::SharedMemory);
  if (!input_transfer_buffer_.get())
    return false;

  if (!input_transfer_buffer_->Create(std::string(), false, false, size))
    return false;

  if (!input_transfer_buffer_->Map(size))
    return false;

  if (!input_transfer_buffer_->ShareToProcess(renderer_handle_, handle))
    return false;

  return true;
}

void GpuVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) {
  info_ = info;
  GpuVideoDecoderInitDoneParam param;
  param.success = false;
  param.input_buffer_handle = base::SharedMemory::NULLHandle();

  if (!info.success) {
    SendInitializeDone(param);
    return;
  }

  // TODO(jiesun): Check the assumption of input size < original size.
  param.input_buffer_size = config_.width * config_.height * 3 / 2;
  if (!CreateInputTransferBuffer(param.input_buffer_size,
                                 &param.input_buffer_handle)) {
    SendInitializeDone(param);
    return;
  }

  param.success = true;
  SendInitializeDone(param);
}

void GpuVideoDecoder::OnUninitializeComplete() {
  SendUninitializeDone();
}

void GpuVideoDecoder::OnFlushComplete() {
  SendFlushDone();
}

void GpuVideoDecoder::OnSeekComplete() {
  SendPrerollDone();
}

void GpuVideoDecoder::OnError() {
  NOTIMPLEMENTED();
}

void GpuVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) {
  NOTIMPLEMENTED();
}

void GpuVideoDecoder::ProduceVideoSample(scoped_refptr<Buffer> buffer) {
  SendEmptyBufferDone();
}

void GpuVideoDecoder::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) {
  if (frame->IsEndOfStream()) {
    SendConsumeVideoFrame(kGpuVideoInvalidFrameId, 0, 0, kGpuVideoEndOfStream);
    return;
  }

  int32 frame_id = kGpuVideoInvalidFrameId;
  for (VideoFrameMap::iterator i = video_frame_map_.begin();
       i != video_frame_map_.end(); ++i) {
    if (i->second == frame) {
      frame_id = i->first;
      break;
    }
  }
  DCHECK_NE(-1, frame_id) << "VideoFrame not recognized";

  SendConsumeVideoFrame(frame_id, frame->GetTimestamp().InMicroseconds(),
                        frame->GetDuration().InMicroseconds(), 0);
}

void* GpuVideoDecoder::GetDevice() {
  bool ret = gles2_decoder_->MakeCurrent();
  DCHECK(ret) << "Failed to switch context";

  // Simply delegate the method call to GpuVideoDevice.
  return video_device_->GetDevice();
}

void GpuVideoDecoder::AllocateVideoFrames(
    int n, size_t width, size_t height, media::VideoFrame::Format format,
    std::vector<scoped_refptr<media::VideoFrame> >* frames, Task* task) {
  // Since the communication between Renderer and GPU process is by GL textures.
  // We need to obtain a set of GL textures by sending IPC commands to the
  // Renderer process. The recipient of these commands will be IpcVideoDecoder.
  //
  // After IpcVideoDecoder replied with a set of textures. We'll assign these
  // textures to GpuVideoDevice. They will be used to generate platform
  // specific VideoFrames objects that are used by VideoDecodeEngine.
  //
  // After GL textures are assigned we'll proceed with allocation the
  // VideoFrames. GpuVideoDevice::CreateVideoFramesFromGlTextures() will be
  // called.
  //
  // When GpuVideoDevice replied with a set of VideoFrames we'll give
  // that to VideoDecodeEngine and the cycle of video frame allocation is done.
  //
  // Note that this method is called when there's no video frames allocated or
  // they were all released.
  DCHECK(video_frame_map_.empty());

  // Save the parameters for allocation.
  pending_allocation_.reset(new PendingAllocation());
  pending_allocation_->n = n;
  pending_allocation_->width = width;
  pending_allocation_->height = height;
  pending_allocation_->format = format;
  pending_allocation_->frames = frames;
  pending_allocation_->task = task;
  SendAllocateVideoFrames(n, width, height, format);
}

void GpuVideoDecoder::ReleaseAllVideoFrames() {
  // This method will first call to GpuVideoDevice to release all the resource
  // associated with a VideoFrame.
  //
  // And then we'll call GpuVideoDevice::ReleaseVideoFrame() to remove the set
  // of Gl textures associated with the context.
  //
  // And finally we'll send IPC commands to IpcVideoDecoder to destroy all
  // GL textures generated.
  bool ret = gles2_decoder_->MakeCurrent();
  DCHECK(ret) << "Failed to switch context";

  for (VideoFrameMap::iterator i = video_frame_map_.begin();
       i != video_frame_map_.end(); ++i) {
    video_device_->ReleaseVideoFrame(i->second);
  }
  video_frame_map_.clear();
  SendReleaseAllVideoFrames();
}

void GpuVideoDecoder::UploadToVideoFrame(void* buffer,
                                         scoped_refptr<media::VideoFrame> frame,
                                         Task* task) {
  // This method is called by VideoDecodeEngine to upload a buffer to a
  // VideoFrame. We should just delegate this to GpuVideoDevice which contains
  // the actual implementation.
  bool ret = gles2_decoder_->MakeCurrent();
  DCHECK(ret) << "Failed to switch context";

  // Actually doing the upload on the main thread.
  ret = video_device_->UploadToVideoFrame(buffer, frame);
  DCHECK(ret) << "Failed to upload video content to a VideoFrame.";
  task->Run();
  delete task;
}

void GpuVideoDecoder::Destroy(Task* task) {
  //  TODO(hclam): I still need to think what I should do here.
}

void GpuVideoDecoder::SetVideoDecodeEngine(media::VideoDecodeEngine* engine) {
  decode_engine_.reset(engine);
}

void GpuVideoDecoder::SetGpuVideoDevice(GpuVideoDevice* device) {
  video_device_.reset(device);
}

GpuVideoDecoder::GpuVideoDecoder(
    MessageLoop* message_loop,
    int32 decoder_host_id,
    IPC::Message::Sender* sender,
    base::ProcessHandle handle,
    gpu::gles2::GLES2Decoder* decoder)
    : message_loop_(message_loop),
      decoder_host_id_(decoder_host_id),
      sender_(sender),
      renderer_handle_(handle),
      gles2_decoder_(decoder) {
  memset(&config_, 0, sizeof(config_));
  memset(&info_, 0, sizeof(info_));

  // TODO(jiesun): find a better way to determine which VideoDecodeEngine
  // to return on current platform.
#if defined(OS_WIN)
  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
  if (command_line.HasSwitch(switches::kEnableAcceleratedDecoding)) {
    // The following code are removed so that we don't link them.
    // TODO(hclam): Enable the code once the crash is solved on XP.
    // decode_engine_.reset(new media::MftH264DecodeEngine(true));
    // video_device_.reset(new MftAngleVideoDevice());
  }
#else
  decode_engine_.reset(new FakeGlVideoDecodeEngine());
  video_device_.reset(new FakeGlVideoDevice());
#endif
}

void GpuVideoDecoder::OnInitialize(const GpuVideoDecoderInitParam& param) {
  // TODO(jiesun): codec id should come from |param|.
  config_.codec = media::kCodecH264;
  config_.width = param.width;
  config_.height = param.height;
  config_.opaque_context = NULL;
  decode_engine_->Initialize(message_loop_, this, this, config_);
}

void GpuVideoDecoder::OnUninitialize() {
  decode_engine_->Uninitialize();
}

void GpuVideoDecoder::OnFlush() {
  decode_engine_->Flush();
}

void GpuVideoDecoder::OnPreroll() {
  decode_engine_->Seek();
}

void GpuVideoDecoder::OnEmptyThisBuffer(
    const GpuVideoDecoderInputBufferParam& buffer) {
  DCHECK(input_transfer_buffer_->memory());

  uint8* src = static_cast<uint8*>(input_transfer_buffer_->memory());

  scoped_refptr<Buffer> input_buffer;
  uint8* dst = buffer.size ? new uint8[buffer.size] : NULL;
  input_buffer = new media::DataBuffer(dst, buffer.size);
  memcpy(dst, src, buffer.size);
  SendEmptyBufferACK();

  // Delegate the method call to VideoDecodeEngine.
  decode_engine_->ConsumeVideoSample(input_buffer);
}

void GpuVideoDecoder::OnProduceVideoFrame(int32 frame_id) {
  VideoFrameMap::iterator i = video_frame_map_.find(frame_id);
  if (i == video_frame_map_.end()) {
    NOTREACHED() << "Received a request of unknown frame ID.";
  }

  // Delegate the method call to VideoDecodeEngine.
  decode_engine_->ProduceVideoFrame(i->second);
}

void GpuVideoDecoder::OnVideoFrameAllocated(int32 frame_id,
                                            std::vector<uint32> textures) {
  bool ret = gles2_decoder_->MakeCurrent();
  DCHECK(ret) << "Failed to switch context";

  // This method is called in response to a video frame allocation request sent
  // to the Renderer process.
  // We should use the textures to generate a VideoFrame by using
  // GpuVideoDevice. The VideoFrame created is added to the internal map.
  // If we have generated enough VideoFrame, we call |allocation_callack_| to
  // complete the allocation process.
  for (size_t i = 0; i < textures.size(); ++i) {
    media::VideoFrame::GlTexture gl_texture;
    // Translate the client texture id to service texture id.
    ret = gles2_decoder_->GetServiceTextureId(textures[i], &gl_texture);
    DCHECK(ret) << "Cannot translate client texture ID to service ID";
    textures[i] = gl_texture;
  }

  // Use GpuVideoDevice to allocate VideoFrame objects.
  scoped_refptr<media::VideoFrame> frame;

  ret = video_device_->CreateVideoFrameFromGlTextures(
      pending_allocation_->width, pending_allocation_->height,
      pending_allocation_->format, textures, &frame);

  DCHECK(ret) << "Failed to allocation VideoFrame from GL textures)";
  pending_allocation_->frames->push_back(frame);
  video_frame_map_.insert(std::make_pair(frame_id, frame));

  if (video_frame_map_.size() == pending_allocation_->n) {
    pending_allocation_->task->Run();
    delete pending_allocation_->task;
    pending_allocation_.reset();
  }
}

void GpuVideoDecoder::SendInitializeDone(
    const GpuVideoDecoderInitDoneParam& param) {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_InitializeACK(decoder_host_id(), param))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_InitializeACK failed";
  }
}

void GpuVideoDecoder::SendUninitializeDone() {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_DestroyACK(decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_DestroyACK failed";
  }
}

void GpuVideoDecoder::SendFlushDone() {
  if (!sender_->Send(new GpuVideoDecoderHostMsg_FlushACK(decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_FlushACK failed";
  }
}

void GpuVideoDecoder::SendPrerollDone() {
  if (!sender_->Send(new GpuVideoDecoderHostMsg_PrerollDone(
          decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_PrerollDone failed";
  }
}

void GpuVideoDecoder::SendEmptyBufferDone() {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_EmptyThisBufferDone(decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBufferDone failed";
  }
}

void GpuVideoDecoder::SendEmptyBufferACK() {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_EmptyThisBufferACK(decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_EmptyThisBufferACK failed";
  }
}

void GpuVideoDecoder::SendConsumeVideoFrame(
    int32 frame_id, int64 timestamp, int64 duration, int32 flags) {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_ConsumeVideoFrame(
              decoder_host_id(), frame_id, timestamp, duration, flags))) {
    LOG(ERROR) << "GpuVideoDecodeHostMsg_ConsumeVideoFrame failed.";
  }
}

void GpuVideoDecoder::SendAllocateVideoFrames(
    int n, size_t width, size_t height, media::VideoFrame::Format format) {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_AllocateVideoFrames(
              decoder_host_id(), n, width, height,
              static_cast<int32>(format)))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_AllocateVideoFrames failed";
  }
}

void GpuVideoDecoder::SendReleaseAllVideoFrames() {
  if (!sender_->Send(
          new GpuVideoDecoderHostMsg_ReleaseAllVideoFrames(
              decoder_host_id()))) {
    LOG(ERROR) << "GpuVideoDecoderMsg_ReleaseAllVideoFrames failed";
  }
}
<|endoftext|>


<commit_before><commit_msg>Implement operator<<(std::ostream&, const uno::Any&)<commit_after><|endoftext|>


<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005 darkbits                        Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef GCN_ICON_HPP
#define GCN_ICON_HPP

#include "guichan/image.hpp"
#include "guichan/platform.hpp"
#include "guichan/widget.hpp"

namespace gcn
{
    /**
     * An Icon for displaying images.
     */
    class GCN_CORE_DECLSPEC Icon: public Widget
    {
    public:
        /**
         * Constructor.
         *
         * @param image an Image to display.
         */
        Icon(Image* image);

        // Inherited from Widget

        virtual void draw(Graphics* graphics);

        virtual void drawBorder(Graphics* graphics);

    private:
        Image* mImage;
    };
}

#endif // end GCN_ICON_HPP
<commit_msg>Image is now proteced.<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005 darkbits                        Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                     ^
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef GCN_ICON_HPP
#define GCN_ICON_HPP

#include "guichan/image.hpp"
#include "guichan/platform.hpp"
#include "guichan/widget.hpp"

namespace gcn
{
    /**
     * An Icon for displaying images.
     */
    class GCN_CORE_DECLSPEC Icon: public Widget
    {
    public:
        /**
         * Constructor.
         *
         * @param image an Image to display.
         */
        Icon(Image* image);

        // Inherited from Widget

        virtual void draw(Graphics* graphics);

        virtual void drawBorder(Graphics* graphics);

    protected:
        Image* mImage;
    };
}

#endif // end GCN_ICON_HPP
<|endoftext|>


<commit_before><commit_msg>Fix explicit<commit_after><|endoftext|>


<commit_before>#pragma once
#include <Eigen/Core>
#include <vector>
#include <memory>
#include <array>
#include "mtao/types.h"
#include <sstream>
#include <numeric>

namespace mtao { namespace geometry {
    template <typename T, int D>
        class KDTree;
    template <typename T, int D, int Axis>
        //class KDNode: public KDNodeBase<KDNode<T,D,Axis>> {
        class KDNode {
            public:
                using Vec = mtao::Vector<T,D>;
                using NodeType = KDNode<T,D,Axis>;
                constexpr static int ChildAxis = (Axis+1)%D;
                constexpr static int ParentAxis = (Axis-1+D)%D;
                using ChildNodeType = KDNode<T,D,ChildAxis>;
                using ParentNodeType = KDNode<T,D,ParentAxis>;
                //balanced construciton iterator, used for one constructor
                using BCIt = mtao::vector<size_t>::iterator;

                ~KDNode() = default;
                KDNode() = delete;
                KDNode(const KDNode&) = delete;
                KDNode(KDNode&&) = delete;
                KDNode& operator=(const KDNode&) = delete;
                KDNode& operator=(KDNode&&) = delete;
                KDNode(const KDTree<T,D>& tree, KDNode&& o): m_tree(tree), m_index(o.m_index) {
                    if(o.left()) {
                        left() = std::make_unique<ChildNodeType>(tree,std::move(*o.left()));
                    }
                    if(o.right()) {
                        right() = std::make_unique<ChildNodeType>(tree,std::move(*o.right()));
                    }
                }

                KDNode(const KDTree<T,D>& tree, int index): m_tree(tree), m_index(index) {}
                KDNode(const KDTree<T,D>& tree, const BCIt& begin, const BCIt& end): m_tree(tree) {
                    assert(std::distance(begin,end) > 0);

                    std::sort(begin,end,[&](size_t a, size_t b) {
                            return point(a)(Axis) < point(b)(Axis);
                            });
                    BCIt mid = begin + std::distance(begin,end)/2;
                    BCIt right_start = mid+1;
                    m_index = *mid;
                    if(std::distance(begin,mid) > 0) {
                        left() = std::make_unique<ChildNodeType>(m_tree,begin,mid);
                    }
                    if(std::distance(right_start,end) > 0) {
                        right() = std::make_unique<ChildNodeType>(m_tree,right_start,end);
                    }

                }
                auto&& point() const {
                    return point(m_index);
                }
                auto&& point(size_t idx) const {return m_tree.point(idx);}
                size_t index()const {return m_index;}

                template <typename Derived>
                    bool operator<(const Eigen::MatrixBase<Derived>& p) const {
                        //positive -> right
                        //negative -> left
                        return axis_dist(p) < 0;
                    }
                template <typename Derived>
                    T axis_dist(const Eigen::MatrixBase<Derived>& p) const {
                        return p(Axis) - point()(Axis);
                    }
                template <typename Derived>
                    size_t axis_choice(const Eigen::MatrixBase<Derived>& p) const {
                        return (*this < p)?0:1;
                    }

                template <typename Derived>
                    auto&& pick_child(const Eigen::MatrixBase<Derived>& p) {
                        return m_children[axis_choice(p)];
                    }
                template <typename Derived>
                    auto&& pick_child(const Eigen::MatrixBase<Derived>& p) const {
                        return m_children[axis_choice(p)];
                    }

                void insert(size_t idx) {
                    auto&& c = pick_child(point(idx));
                    if(c) {
                        c->insert(idx);
                    } else {
                        c = std::make_unique<ChildNodeType>(m_tree,idx);
                    }
                }

                template <typename Derived>
                   void nearest(const Eigen::MatrixBase<Derived>& p, size_t& nearest_index, T& nearest_dist) const {

                        T dist = (point() - p).norm();
                        if(dist < nearest_dist) {
                            nearest_index = index();
                            nearest_dist = dist;
                        }

                        auto comp_child = [&](const std::unique_ptr<ChildNodeType>& c) {
                            if(c) {
                                c->nearest(p,nearest_index,nearest_dist);
                            }
                        };
                        T ad = axis_dist(p);
                        bool in_nearband = nearest_dist >= std::abs(ad);

                        //[  node     point  child]
                        //[  node     child  point]
                        //[  point    node   child]
                        //axis nearest_dist is negative and considering going down right child
                        if(ad >= 0 || in_nearband) {
                            comp_child(right());
                        }
                        //[  point  child     node]
                        //[  child  point     node]
                        //[  child    node   point]
                        //axis nearest_dist is positive and considering going down left child
                        if(ad < 0 || in_nearband) {
                            comp_child(left());
                        }

                    }

                std::unique_ptr<ChildNodeType>& left() { return m_children[0]; }
                const std::unique_ptr<ChildNodeType>& left() const { return m_children[0]; }

                std::unique_ptr<ChildNodeType>& right() { return m_children[1]; }
                const std::unique_ptr<ChildNodeType>& right() const { return m_children[1]; }

                int max_depth() const {
                    int depth = 0;
                    if(left()) {
                        depth = std::max(left()->max_depth()+1,depth);
                    }
                    if(right()) {
                        depth = std::max(right()->max_depth()+1,depth);
                    }
                    return depth;
                }

                operator std::string() const {
                    std::stringstream ss;
                    ss << m_index << "[";
                    if(left()) {
                        ss << std::string(*left());
                    } else {
                        ss << ".";
                    }
                    ss << " | ";
                    if(right()) {
                        ss << std::string(*right());
                    } else {
                        ss << ".";
                    }
                    ss << "]";

                    return ss.str();
                }
            private:
                const KDTree<T,D>& m_tree;
                size_t m_index;
                std::array<std::unique_ptr<ChildNodeType>,2> m_children;
        };

    template <typename T, int D>
        class KDTree {
            public:
                using Vec = mtao::Vector<T,D>;
                constexpr static int Axis = 0;
                using NodeType = KDNode<T,D,0>;
                const mtao::vector<Vec>& points()const {return m_points;}
                auto&& point(size_t idx) const {return m_points[idx];}
                size_t size() const { return points().size(); }

                void rebalance() {
                    std::vector<size_t> P(m_points.size());
                    std::iota(P.begin(),P.end(),0);
                    m_node = std::make_unique<NodeType>(*this,P.begin(),P.end());
                }
                KDTree() = default;
                KDTree(const KDTree&) = delete;
                KDTree(KDTree&&) = delete;
                ~KDTree() = default;
                KDTree& operator=(const KDTree&) = delete;
                KDTree& operator=(KDTree&& o) {
                    m_points = std::move(o.m_points);
                    if(o.m_node) {
                        m_node = std::make_unique<NodeType>(*this,std::move(*o.m_node));
                    }
                    return *this;
                }
                KDTree(const mtao::vector<Vec>& points): m_points(points) {
                    rebalance();
                }
                size_t insert(const Vec& p) {
                    size_t newidx = m_points.size();
                    m_points.push_back(p);
                    if(!m_node) {
                        m_node = std::make_unique<NodeType>(*this, newidx);
                    } else {
                        m_node->insert(newidx);
                    }
                    return newidx;
                }
                size_t pruning_insertion(const Vec& p, T eps = T(1e-5)) {

                    if(m_node) {
                        size_t ni = nearest_index(p);
                        if((point(ni)-p).norm() < eps) {
                            return ni;
                        }
                    }
                    return insert(p);
                }
                template <typename Derived>
                    std::tuple<size_t,T> nearest(const typename Eigen::MatrixBase<Derived>& p) const {
                        size_t idx = 0;
                        T d = std::numeric_limits<T>::max();
                        assert(m_node);

                        m_node->nearest(p,idx,d);
                        return {idx,d};
                    }
                template <typename Derived>
                    size_t nearest_index(const typename Eigen::MatrixBase<Derived>& p) const {
                        return std::get<0>(nearest(p));
                    }
                template <typename Derived>
                    size_t nearest_distance(const typename Eigen::MatrixBase<Derived>& p) const {
                        return std::get<1>(nearest(p));
                    }
                template <typename Derived>
                    const Vec& nearest_point(const typename Eigen::MatrixBase<Derived>& p) const { return point(nearest_index(p)); }

                operator std::string() const { return *m_node; }

                int max_depth() const {
                    if(m_node) {
                        return m_node->max_depth() + 1;
                    }
                    return 0;
                }

            private:
                std::unique_ptr<NodeType> m_node;
                mtao::vector<Vec> m_points;

        };

}}

<commit_msg>minor optimzation to pruend insertion on kdtree<commit_after>#pragma once
#include <Eigen/Core>
#include <vector>
#include <memory>
#include <array>
#include "mtao/types.h"
#include <sstream>
#include <numeric>

namespace mtao { namespace geometry {
    template <typename T, int D>
        class KDTree;
    template <typename T, int D, int Axis>
        //class KDNode: public KDNodeBase<KDNode<T,D,Axis>> {
        class KDNode {
            public:
                using Vec = mtao::Vector<T,D>;
                using NodeType = KDNode<T,D,Axis>;
                constexpr static int ChildAxis = (Axis+1)%D;
                constexpr static int ParentAxis = (Axis-1+D)%D;
                using ChildNodeType = KDNode<T,D,ChildAxis>;
                using ParentNodeType = KDNode<T,D,ParentAxis>;
                //balanced construciton iterator, used for one constructor
                using BCIt = mtao::vector<size_t>::iterator;

                ~KDNode() = default;
                KDNode() = delete;
                KDNode(const KDNode&) = delete;
                KDNode(KDNode&&) = delete;
                KDNode& operator=(const KDNode&) = delete;
                KDNode& operator=(KDNode&&) = delete;
                KDNode(const KDTree<T,D>& tree, KDNode&& o): m_tree(tree), m_index(o.m_index) {
                    if(o.left()) {
                        left() = std::make_unique<ChildNodeType>(tree,std::move(*o.left()));
                    }
                    if(o.right()) {
                        right() = std::make_unique<ChildNodeType>(tree,std::move(*o.right()));
                    }
                }

                KDNode(const KDTree<T,D>& tree, int index): m_tree(tree), m_index(index) {}
                KDNode(const KDTree<T,D>& tree, const BCIt& begin, const BCIt& end): m_tree(tree) {
                    assert(std::distance(begin,end) > 0);

                    std::sort(begin,end,[&](size_t a, size_t b) {
                            return point(a)(Axis) < point(b)(Axis);
                            });
                    BCIt mid = begin + std::distance(begin,end)/2;
                    BCIt right_start = mid+1;
                    m_index = *mid;
                    if(std::distance(begin,mid) > 0) {
                        left() = std::make_unique<ChildNodeType>(m_tree,begin,mid);
                    }
                    if(std::distance(right_start,end) > 0) {
                        right() = std::make_unique<ChildNodeType>(m_tree,right_start,end);
                    }

                }
                auto&& point() const {
                    return point(m_index);
                }
                auto&& point(size_t idx) const {return m_tree.point(idx);}
                size_t index()const {return m_index;}

                template <typename Derived>
                    bool operator<(const Eigen::MatrixBase<Derived>& p) const {
                        //positive -> right
                        //negative -> left
                        return axis_dist(p) < 0;
                    }
                template <typename Derived>
                    T axis_dist(const Eigen::MatrixBase<Derived>& p) const {
                        return p(Axis) - point()(Axis);
                    }
                template <typename Derived>
                    size_t axis_choice(const Eigen::MatrixBase<Derived>& p) const {
                        return (*this < p)?0:1;
                    }

                template <typename Derived>
                    auto&& pick_child(const Eigen::MatrixBase<Derived>& p) {
                        return m_children[axis_choice(p)];
                    }
                template <typename Derived>
                    auto&& pick_child(const Eigen::MatrixBase<Derived>& p) const {
                        return m_children[axis_choice(p)];
                    }

                void insert(size_t idx) {
                    auto&& c = pick_child(point(idx));
                    if(c) {
                        c->insert(idx);
                    } else {
                        c = std::make_unique<ChildNodeType>(m_tree,idx);
                    }
                }

                template <typename Derived>
                   void nearest(const Eigen::MatrixBase<Derived>& p, size_t& nearest_index, T& nearest_dist) const {

                        T dist = (point() - p).norm();
                        if(dist < nearest_dist) {
                            nearest_index = index();
                            nearest_dist = dist;
                        }

                        auto comp_child = [&](const std::unique_ptr<ChildNodeType>& c) {
                            if(c) {
                                c->nearest(p,nearest_index,nearest_dist);
                            }
                        };
                        T ad = axis_dist(p);
                        bool in_nearband = nearest_dist >= std::abs(ad);

                        //[  node     point  child]
                        //[  node     child  point]
                        //[  point    node   child]
                        //axis nearest_dist is negative and considering going down right child
                        if(ad >= 0 || in_nearband) {
                            comp_child(right());
                        }
                        //[  point  child     node]
                        //[  child  point     node]
                        //[  child    node   point]
                        //axis nearest_dist is positive and considering going down left child
                        if(ad < 0 || in_nearband) {
                            comp_child(left());
                        }

                    }

                std::unique_ptr<ChildNodeType>& left() { return m_children[0]; }
                const std::unique_ptr<ChildNodeType>& left() const { return m_children[0]; }

                std::unique_ptr<ChildNodeType>& right() { return m_children[1]; }
                const std::unique_ptr<ChildNodeType>& right() const { return m_children[1]; }

                int max_depth() const {
                    int depth = 0;
                    if(left()) {
                        depth = std::max(left()->max_depth()+1,depth);
                    }
                    if(right()) {
                        depth = std::max(right()->max_depth()+1,depth);
                    }
                    return depth;
                }

                operator std::string() const {
                    std::stringstream ss;
                    ss << m_index << "[";
                    if(left()) {
                        ss << std::string(*left());
                    } else {
                        ss << ".";
                    }
                    ss << " | ";
                    if(right()) {
                        ss << std::string(*right());
                    } else {
                        ss << ".";
                    }
                    ss << "]";

                    return ss.str();
                }
            private:
                const KDTree<T,D>& m_tree;
                size_t m_index;
                std::array<std::unique_ptr<ChildNodeType>,2> m_children;
        };

    template <typename T, int D>
        class KDTree {
            public:
                using Vec = mtao::Vector<T,D>;
                constexpr static int Axis = 0;
                using NodeType = KDNode<T,D,0>;
                const mtao::vector<Vec>& points()const {return m_points;}
                auto&& point(size_t idx) const {return m_points[idx];}
                size_t size() const { return points().size(); }

                void rebalance() {
                    std::vector<size_t> P(m_points.size());
                    std::iota(P.begin(),P.end(),0);
                    m_node = std::make_unique<NodeType>(*this,P.begin(),P.end());
                }
                KDTree() = default;
                KDTree(const KDTree&) = delete;
                KDTree(KDTree&&) = delete;
                ~KDTree() = default;
                KDTree& operator=(const KDTree&) = delete;
                KDTree& operator=(KDTree&& o) {
                    m_points = std::move(o.m_points);
                    if(o.m_node) {
                        m_node = std::make_unique<NodeType>(*this,std::move(*o.m_node));
                    }
                    return *this;
                }
                KDTree(const mtao::vector<Vec>& points): m_points(points) {
                    rebalance();
                }
                size_t insert(const Vec& p) {
                    size_t newidx = m_points.size();
                    m_points.push_back(p);
                    if(!m_node) {
                        m_node = std::make_unique<NodeType>(*this, newidx);
                    } else {
                        m_node->insert(newidx);
                    }
                    return newidx;
                }
                size_t pruning_insertion(const Vec& p, T eps = T(1e-5)) {

                    if(m_node) {
                        size_t [ni,d] = nearest(p);
                        if(d < eps) {
                            return ni;
                        }
                    }
                    return insert(p);
                }
                template <typename Derived>
                    std::tuple<size_t,T> nearest(const typename Eigen::MatrixBase<Derived>& p) const {
                        size_t idx = 0;
                        T d = std::numeric_limits<T>::max();
                        assert(m_node);

                        m_node->nearest(p,idx,d);
                        return {idx,d};
                    }
                template <typename Derived>
                    size_t nearest_index(const typename Eigen::MatrixBase<Derived>& p) const {
                        return std::get<0>(nearest(p));
                    }
                template <typename Derived>
                    size_t nearest_distance(const typename Eigen::MatrixBase<Derived>& p) const {
                        return std::get<1>(nearest(p));
                    }
                template <typename Derived>
                    const Vec& nearest_point(const typename Eigen::MatrixBase<Derived>& p) const { return point(nearest_index(p)); }

                operator std::string() const { return *m_node; }

                int max_depth() const {
                    if(m_node) {
                        return m_node->max_depth() + 1;
                    }
                    return 0;
                }

            private:
                std::unique_ptr<NodeType> m_node;
                mtao::vector<Vec> m_points;

        };

}}

<|endoftext|>


<commit_before>#ifndef VSMC_INTERNAL_ASSERT_HPP
#define VSMC_INTERNAL_ASSERT_HPP

#include <cassert>
#include <cstdio>
#include <stdexcept>

#include <vsmc/internal/config.hpp>
#include <vsmc/internal/forward.hpp>

// Runtime assertion
#if VSMC_RUNTIME_ASSERT_AS_EXCEPTION
#define VSMC_RUNTIME_ASSERT(cond, msg)                                       \
{                                                                            \
    if (!(cond)) {                                                           \
        throw vsmc::RuntimeAssert(msg);                                      \
    };                                                                       \
}
#elif defined(NDEBUG) // VSMC_RUNTIME_ASSERT_AS_EXCEPTION
#define VSMC_RUNTIME_ASSERT(cond, msg)
#else
#define VSMC_RUNTIME_ASSERT(cond, msg)                                       \
{                                                                            \
    if (!(cond)) {                                                           \
        std::fprintf(stderr,                                                 \
                "vSMC runtime assertion failed; File: %s; Line: %d\n%s\n",   \
                __FILE__, __LINE__, msg);                                    \
    };                                                                       \
    assert(cond);                                                            \
}
#endif // VSMC_RUNTIME_ASSERT_AS_EXCEPTION

// Static assertion
#if VSMC_HAS_CXX11_STATIC_ASSERT
#define VSMC_STATIC_ASSERT(cond, msg) static_assert(cond, #msg)
#else // VSMC_HAS_CXX11_STATIC_ASSERT
#ifdef _MSC_VER
#define VSMC_STATIC_ASSERT(cond, msg) \
    {vsmc::StaticAssert<bool(cond)>::msg;}
#else // _MSC_VER
#define VSMC_STATIC_ASSERT(cond, msg) \
    if (vsmc::StaticAssert<bool(cond)>::msg) {};
#endif // _MSC_VER
#endif // VSMC_HAS_CXX11_STATIC_ASSERT

namespace vsmc {

class RuntimeAssert : public std::runtime_error
{
    public :

    RuntimeAssert (const std::string &msg) : std::runtime_error(msg) {}

    RuntimeAssert (const char *msg) : std::runtime_error(msg) {}
}; // class RuntimeAssert

template <bool> class StaticAssert {};

template <>
class StaticAssert<true>
{
    public :

    enum {
        USE_METHOD_resize_dim_WITH_A_FIXED_SIZE_StateBase_OBJECT,

        USE_StateCL_WITH_A_STATE_TYPE_OTHER_THAN_cl_float_AND_cl_double,
        USE_METHOD_resize_dim_WITH_A_FIXED_SIZE_StateCL_OBJECT,
        USE_InitializeCL_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL,
        USE_MoveCL_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL,
        USE_MonitorEvalCL_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL,
        USE_PathEvalCL_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL,

        USE_InitializeAdapter_WITHOUT_AN_INITIAILIZE_IMPLEMENTATION,
        USE_MoveAdapter_WITHOUT_A_MOVE_IMPLEMENTATION,
        USE_MonitorEvalAdapter_WITHOUT_A_MONITOR_EVAL_IMPLEMENTATION,
        USE_PathEvalAdapter_WITHOUT_A_PATH_EVAL_IMPLEMENTATION
    };
}; // class StaticAssert

} // namespace vsmc

#define VSMC_STATIC_ASSERT_STATE_TYPE(base, derived, user)                   \
    VSMC_STATIC_ASSERT((vsmc::traits::IsBaseOfState<base, derived>::value),  \
            USE_##user##_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_##base)

#define VSMC_STATIC_ASSERT_STATE_CL_VALUE_TYPE(type)                         \
    VSMC_STATIC_ASSERT((cxx11::is_same<type, cl_float>::value                \
             || cxx11::is_same<type, cl_double>::value),                     \
            USE_StateCL_WITH_A_STATE_TYPE_OTHER_THAN_cl_float_AND_cl_double)

#define VSMC_STATIC_ASSERT_STATE_CL_TYPE(derived, user)                      \
    VSMC_STATIC_ASSERT((vsmc::traits::IsBaseOfStateCL<derived>::value),      \
            USE_##user##_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL)

#define VSMC_STATIC_ASSERT_NO_IMPL(member)                                   \
    VSMC_STATIC_ASSERT((cxx11::is_same<T, NullType>::value),                 \
            NO_IMPLEMENTATION_OF_##member##_FOUND)

#define VSMC_RUNTIME_ASSERT_STATE_CL_BUILD(func)                             \
    VSMC_RUNTIME_ASSERT((build()),                                           \
            ("**StateCL::"#func"** can only be called after true "           \
             "**StateCL::build**"));

#define VSMC_RUNTIME_ASSERT_CONST_SINGLE_PARTICLE_VALID                      \
    VSMC_RUNTIME_ASSERT(particle_ptr_,                                       \
            ("A **ConstSingleParticle** object "                             \
             "is contructed with 0 **Particle** pointer"));                  \
    VSMC_RUNTIME_ASSERT((id_ >= 0 && id_ <= particle_ptr_->size()),          \
            ("A **ConstSignleParticle** object "                             \
             "is contructed with an out of range id"));

#define VSMC_RUNTIME_ASSERT_SINGLE_PARTICLE_VALID                            \
    VSMC_RUNTIME_ASSERT(particle_ptr_,                                       \
            ("A **SingleParticle** object "                                  \
             "is contructed with 0 **Particle** pointer"));                  \
    VSMC_RUNTIME_ASSERT((id_ >= 0 && id_ <= particle_ptr_->size()),          \
            ("A **SignleParticle** object "                                  \
             "is contructed with an out of range id"));

#define VSMC_RUNTIME_ASSERT_DERIVED_BASE(basename)                           \
    VSMC_RUNTIME_ASSERT((dynamic_cast<Derived *>(this)),                     \
            ("DERIVED FROM " #basename                                       \
            " WITH INCORRECT **Derived** TEMPLATE PARAMTER"));

#define VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(func)                           \
    VSMC_RUNTIME_ASSERT((setup()),                                           \
            ("**vsmc::Manager::"#func"** can only be called after true "   \
             "**vsmc::Manager::setup**"));

#define VSMC_RUNTIME_ASSERT_MKL_STAT_EVAL_EDIT_TASK(status)                  \
    VSMC_RUNTIME_ASSERT((status == VSL_STATUS_OK),                           \
            ("CALLING **vsldSSEditTask** failed"));

#endif // VSMC_INTERNAL_ASSERT_HPP
<commit_msg>add missing header<commit_after>#ifndef VSMC_INTERNAL_ASSERT_HPP
#define VSMC_INTERNAL_ASSERT_HPP

#include <cassert>
#include <cstdio>
#include <stdexcept>

#include <vsmc/internal/config.hpp>
#include <vsmc/internal/forward.hpp>
#include <vsmc/cxx11/type_traits.hpp>

// Runtime assertion
#if VSMC_RUNTIME_ASSERT_AS_EXCEPTION
#define VSMC_RUNTIME_ASSERT(cond, msg)                                       \
{                                                                            \
    if (!(cond)) {                                                           \
        throw vsmc::RuntimeAssert(msg);                                      \
    };                                                                       \
}
#elif defined(NDEBUG) // VSMC_RUNTIME_ASSERT_AS_EXCEPTION
#define VSMC_RUNTIME_ASSERT(cond, msg)
#else
#define VSMC_RUNTIME_ASSERT(cond, msg)                                       \
{                                                                            \
    if (!(cond)) {                                                           \
        std::fprintf(stderr,                                                 \
                "vSMC runtime assertion failed; File: %s; Line: %d\n%s\n",   \
                __FILE__, __LINE__, msg);                                    \
    };                                                                       \
    assert(cond);                                                            \
}
#endif // VSMC_RUNTIME_ASSERT_AS_EXCEPTION

// Static assertion
#if VSMC_HAS_CXX11_STATIC_ASSERT
#define VSMC_STATIC_ASSERT(cond, msg) static_assert(cond, #msg)
#else // VSMC_HAS_CXX11_STATIC_ASSERT
#ifdef _MSC_VER
#define VSMC_STATIC_ASSERT(cond, msg) \
    {vsmc::StaticAssert<bool(cond)>::msg;}
#else // _MSC_VER
#define VSMC_STATIC_ASSERT(cond, msg) \
    if (vsmc::StaticAssert<bool(cond)>::msg) {};
#endif // _MSC_VER
#endif // VSMC_HAS_CXX11_STATIC_ASSERT

namespace vsmc {

class RuntimeAssert : public std::runtime_error
{
    public :

    RuntimeAssert (const std::string &msg) : std::runtime_error(msg) {}

    RuntimeAssert (const char *msg) : std::runtime_error(msg) {}
}; // class RuntimeAssert

template <bool> class StaticAssert {};

template <>
class StaticAssert<true>
{
    public :

    enum {
        USE_METHOD_resize_dim_WITH_A_FIXED_SIZE_StateBase_OBJECT,

        USE_StateCL_WITH_A_STATE_TYPE_OTHER_THAN_cl_float_AND_cl_double,
        USE_METHOD_resize_dim_WITH_A_FIXED_SIZE_StateCL_OBJECT,
        USE_InitializeCL_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL,
        USE_MoveCL_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL,
        USE_MonitorEvalCL_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL,
        USE_PathEvalCL_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL,

        USE_InitializeAdapter_WITHOUT_AN_INITIAILIZE_IMPLEMENTATION,
        USE_MoveAdapter_WITHOUT_A_MOVE_IMPLEMENTATION,
        USE_MonitorEvalAdapter_WITHOUT_A_MONITOR_EVAL_IMPLEMENTATION,
        USE_PathEvalAdapter_WITHOUT_A_PATH_EVAL_IMPLEMENTATION
    };
}; // class StaticAssert

} // namespace vsmc

#define VSMC_STATIC_ASSERT_STATE_TYPE(base, derived, user)                   \
    VSMC_STATIC_ASSERT((vsmc::traits::IsBaseOfState<base, derived>::value),  \
            USE_##user##_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_##base)

#define VSMC_STATIC_ASSERT_STATE_CL_VALUE_TYPE(type)                         \
    VSMC_STATIC_ASSERT((cxx11::is_same<type, cl_float>::value                \
             || cxx11::is_same<type, cl_double>::value),                     \
            USE_StateCL_WITH_A_STATE_TYPE_OTHER_THAN_cl_float_AND_cl_double)

#define VSMC_STATIC_ASSERT_STATE_CL_TYPE(derived, user)                      \
    VSMC_STATIC_ASSERT((vsmc::traits::IsBaseOfStateCL<derived>::value),      \
            USE_##user##_WITH_A_STATE_TYPE_NOT_DERIVED_FROM_StateCL)

#define VSMC_STATIC_ASSERT_NO_IMPL(member)                                   \
    VSMC_STATIC_ASSERT((cxx11::is_same<T, NullType>::value),                 \
            NO_IMPLEMENTATION_OF_##member##_FOUND)

#define VSMC_RUNTIME_ASSERT_STATE_CL_BUILD(func)                             \
    VSMC_RUNTIME_ASSERT((build()),                                           \
            ("**StateCL::"#func"** can only be called after true "           \
             "**StateCL::build**"));

#define VSMC_RUNTIME_ASSERT_CONST_SINGLE_PARTICLE_VALID                      \
    VSMC_RUNTIME_ASSERT(particle_ptr_,                                       \
            ("A **ConstSingleParticle** object "                             \
             "is contructed with 0 **Particle** pointer"));                  \
    VSMC_RUNTIME_ASSERT((id_ >= 0 && id_ <= particle_ptr_->size()),          \
            ("A **ConstSignleParticle** object "                             \
             "is contructed with an out of range id"));

#define VSMC_RUNTIME_ASSERT_SINGLE_PARTICLE_VALID                            \
    VSMC_RUNTIME_ASSERT(particle_ptr_,                                       \
            ("A **SingleParticle** object "                                  \
             "is contructed with 0 **Particle** pointer"));                  \
    VSMC_RUNTIME_ASSERT((id_ >= 0 && id_ <= particle_ptr_->size()),          \
            ("A **SignleParticle** object "                                  \
             "is contructed with an out of range id"));

#define VSMC_RUNTIME_ASSERT_DERIVED_BASE(basename)                           \
    VSMC_RUNTIME_ASSERT((dynamic_cast<Derived *>(this)),                     \
            ("DERIVED FROM " #basename                                       \
            " WITH INCORRECT **Derived** TEMPLATE PARAMTER"));

#define VSMC_RUNTIME_ASSERT_CL_MANAGER_SETUP(func)                           \
    VSMC_RUNTIME_ASSERT((setup()),                                           \
            ("**vsmc::Manager::"#func"** can only be called after true "   \
             "**vsmc::Manager::setup**"));

#define VSMC_RUNTIME_ASSERT_MKL_STAT_EVAL_EDIT_TASK(status)                  \
    VSMC_RUNTIME_ASSERT((status == VSL_STATUS_OK),                           \
            ("CALLING **vsldSSEditTask** failed"));

#endif // VSMC_INTERNAL_ASSERT_HPP
<|endoftext|>


<commit_before>#pragma once

#include "zmsg_types.hpp"

namespace zmsg {

template<>
struct zmsg<mid_t::dust_check_start> {
public:
	ZMSG_PU()
};

struct bool_img {
	uint16_t width;
	uint16_t height;
	std::vector<bool> data;
public:
	ZMSG_PU(width, height, data);
};

template<>
struct zmsg<mid_t::dust_check_result> {
	bool_img xz;
	bool_img yz;
public:
	ZMSG_PU(xz, yz)
};

} /* msg */
<commit_msg>zmsg: dust_check_result : add member xz_ok/yz_ok<commit_after>#pragma once

#include "zmsg_types.hpp"

namespace zmsg {

template<>
struct zmsg<mid_t::dust_check_start> {
public:
	ZMSG_PU()
};

struct bool_img {
	uint16_t width;
	uint16_t height;
	std::vector<bool> data;
public:
	ZMSG_PU(width, height, data);
};

template<>
struct zmsg<mid_t::dust_check_result> {
	bool xz_ok;
	bool_img xz;
	bool yz_ok;
	bool_img yz;
public:
	ZMSG_PU(xz_ok, xz, yz_ok, yz)
};

} /* msg */
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <limits>
#include <stdexcept>

#include <boost/make_shared.hpp>

#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>

#include "IWORKMemoryStream.h"
#include "libetonyek_utils.h"

using libetonyek::EndOfStreamException;
using libetonyek::IWORKMemoryStream;
using libetonyek::RVNGInputStreamPtr_t;
using libetonyek::readSVar;
using libetonyek::readUVar;

using std::numeric_limits;

namespace test
{

namespace
{

RVNGInputStreamPtr_t makeStream(const char *const bytes, const size_t len)
{
  return boost::make_shared<IWORKMemoryStream>(reinterpret_cast<const unsigned char *>(bytes), len);
}

RVNGInputStreamPtr_t makeEmptyStream()
{
  const RVNGInputStreamPtr_t stream = makeStream("\0", 1);
  stream->seek(1, librevenge::RVNG_SEEK_SET);
  return stream;
}

}

class LibetonyekUtilsTest : public CPPUNIT_NS::TestFixture
{
public:
  virtual void setUp();
  virtual void tearDown();

private:
  CPPUNIT_TEST_SUITE(LibetonyekUtilsTest);
  CPPUNIT_TEST(testReadSVar);
  CPPUNIT_TEST(testReadUVar);
  CPPUNIT_TEST_SUITE_END();

private:
  void testReadSVar();
  void testReadUVar();
};

void LibetonyekUtilsTest::setUp()
{
}

void LibetonyekUtilsTest::tearDown()
{
}

void LibetonyekUtilsTest::testReadSVar()
{
  CPPUNIT_ASSERT_EQUAL(0L, readSVar(makeStream("\x0", 1)));
  CPPUNIT_ASSERT_EQUAL(-1L, readSVar(makeStream("\x1", 1)));
  CPPUNIT_ASSERT_EQUAL(1L, readSVar(makeStream("\x2", 1)));
  CPPUNIT_ASSERT_EQUAL(-2L, readSVar(makeStream("\x3", 1)));
  CPPUNIT_ASSERT_EQUAL(0x7fffffffL, readSVar(makeStream("\xfe\xff\xff\xff\xf", 5)));
  CPPUNIT_ASSERT_EQUAL(-0x80000000L, readSVar(makeStream("\xff\xff\xff\xff\xf", 5)));
  CPPUNIT_ASSERT_EQUAL(numeric_limits<int64_t>::max(), readSVar(makeStream("\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x1", 10)));
  CPPUNIT_ASSERT_EQUAL(numeric_limits<int64_t>::min(), readSVar(makeStream("\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1", 10)));
  CPPUNIT_ASSERT_THROW(readSVar(makeStream("\x80\x80\x80\x80\x80\x80\x80\x80\x80\x2", 10)), std::range_error);
  CPPUNIT_ASSERT_THROW(readSVar(makeStream("\x81\x80\x80\x80\x80\x80\x80\x80\x80\x2", 10)), std::range_error);
  CPPUNIT_ASSERT_THROW(readSVar(makeEmptyStream()), EndOfStreamException);
  CPPUNIT_ASSERT_THROW(readSVar(makeStream("\x80", 1)), EndOfStreamException);
  CPPUNIT_ASSERT_THROW(readSVar(makeStream("\xff\xff", 2)), EndOfStreamException);
}

void LibetonyekUtilsTest::testReadUVar()
{
  CPPUNIT_ASSERT_EQUAL(0UL, readUVar(makeStream("\x0", 1)));
  CPPUNIT_ASSERT_EQUAL(1UL, readUVar(makeStream("\x1", 1)));
  CPPUNIT_ASSERT_EQUAL(0x7fUL, readUVar(makeStream("\x7f", 1)));
  CPPUNIT_ASSERT_EQUAL(0x80UL, readUVar(makeStream("\x80\x1", 2)));
  CPPUNIT_ASSERT_EQUAL(0x81UL, readUVar(makeStream("\x81\x1", 2)));
  CPPUNIT_ASSERT_EQUAL(0x12345678UL, readUVar(makeStream("\xf8\xac\xd1\x91\x01", 5)));
  CPPUNIT_ASSERT_EQUAL(numeric_limits<uint64_t>::max(), readUVar(makeStream("\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1", 10)));
  CPPUNIT_ASSERT_THROW(readUVar(makeStream("\x80\x80\x80\x80\x80\x80\x80\x80\x80\x2", 10)), std::range_error);
  CPPUNIT_ASSERT_THROW(readUVar(makeEmptyStream()), EndOfStreamException);
  CPPUNIT_ASSERT_THROW(readUVar(makeStream("\x80", 1)), EndOfStreamException);
  CPPUNIT_ASSERT_THROW(readUVar(makeStream("\xff\xff", 2)), EndOfStreamException);
}

CPPUNIT_TEST_SUITE_REGISTRATION(LibetonyekUtilsTest);

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>fix build on OS X<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libetonyek project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <limits>
#include <stdexcept>

#include <boost/make_shared.hpp>

#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>

#include "IWORKMemoryStream.h"
#include "libetonyek_utils.h"

using libetonyek::EndOfStreamException;
using libetonyek::IWORKMemoryStream;
using libetonyek::RVNGInputStreamPtr_t;
using libetonyek::readSVar;
using libetonyek::readUVar;

using std::numeric_limits;

namespace test
{

namespace
{

RVNGInputStreamPtr_t makeStream(const char *const bytes, const size_t len)
{
  return boost::make_shared<IWORKMemoryStream>(reinterpret_cast<const unsigned char *>(bytes), len);
}

RVNGInputStreamPtr_t makeEmptyStream()
{
  const RVNGInputStreamPtr_t stream = makeStream("\0", 1);
  stream->seek(1, librevenge::RVNG_SEEK_SET);
  return stream;
}

}

class LibetonyekUtilsTest : public CPPUNIT_NS::TestFixture
{
public:
  virtual void setUp();
  virtual void tearDown();

private:
  CPPUNIT_TEST_SUITE(LibetonyekUtilsTest);
  CPPUNIT_TEST(testReadSVar);
  CPPUNIT_TEST(testReadUVar);
  CPPUNIT_TEST_SUITE_END();

private:
  void testReadSVar();
  void testReadUVar();
};

void LibetonyekUtilsTest::setUp()
{
}

void LibetonyekUtilsTest::tearDown()
{
}

void LibetonyekUtilsTest::testReadSVar()
{
  CPPUNIT_ASSERT_EQUAL(int64_t(0), readSVar(makeStream("\x0", 1)));
  CPPUNIT_ASSERT_EQUAL(int64_t(-1), readSVar(makeStream("\x1", 1)));
  CPPUNIT_ASSERT_EQUAL(int64_t(1), readSVar(makeStream("\x2", 1)));
  CPPUNIT_ASSERT_EQUAL(int64_t(-2), readSVar(makeStream("\x3", 1)));
  CPPUNIT_ASSERT_EQUAL(int64_t(0x7fffffffL), readSVar(makeStream("\xfe\xff\xff\xff\xf", 5)));
  CPPUNIT_ASSERT_EQUAL(int64_t(-0x80000000L), readSVar(makeStream("\xff\xff\xff\xff\xf", 5)));
  CPPUNIT_ASSERT_EQUAL(numeric_limits<int64_t>::max(), readSVar(makeStream("\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x1", 10)));
  CPPUNIT_ASSERT_EQUAL(numeric_limits<int64_t>::min(), readSVar(makeStream("\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1", 10)));
  CPPUNIT_ASSERT_THROW(readSVar(makeStream("\x80\x80\x80\x80\x80\x80\x80\x80\x80\x2", 10)), std::range_error);
  CPPUNIT_ASSERT_THROW(readSVar(makeStream("\x81\x80\x80\x80\x80\x80\x80\x80\x80\x2", 10)), std::range_error);
  CPPUNIT_ASSERT_THROW(readSVar(makeEmptyStream()), EndOfStreamException);
  CPPUNIT_ASSERT_THROW(readSVar(makeStream("\x80", 1)), EndOfStreamException);
  CPPUNIT_ASSERT_THROW(readSVar(makeStream("\xff\xff", 2)), EndOfStreamException);
}

void LibetonyekUtilsTest::testReadUVar()
{
  CPPUNIT_ASSERT_EQUAL(uint64_t(0), readUVar(makeStream("\x0", 1)));
  CPPUNIT_ASSERT_EQUAL(uint64_t(1), readUVar(makeStream("\x1", 1)));
  CPPUNIT_ASSERT_EQUAL(uint64_t(0x7f), readUVar(makeStream("\x7f", 1)));
  CPPUNIT_ASSERT_EQUAL(uint64_t(0x80), readUVar(makeStream("\x80\x1", 2)));
  CPPUNIT_ASSERT_EQUAL(uint64_t(0x81), readUVar(makeStream("\x81\x1", 2)));
  CPPUNIT_ASSERT_EQUAL(uint64_t(0x12345678UL), readUVar(makeStream("\xf8\xac\xd1\x91\x01", 5)));
  CPPUNIT_ASSERT_EQUAL(numeric_limits<uint64_t>::max(), readUVar(makeStream("\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1", 10)));
  CPPUNIT_ASSERT_THROW(readUVar(makeStream("\x80\x80\x80\x80\x80\x80\x80\x80\x80\x2", 10)), std::range_error);
  CPPUNIT_ASSERT_THROW(readUVar(makeEmptyStream()), EndOfStreamException);
  CPPUNIT_ASSERT_THROW(readUVar(makeStream("\x80", 1)), EndOfStreamException);
  CPPUNIT_ASSERT_THROW(readUVar(makeStream("\xff\xff", 2)), EndOfStreamException);
}

CPPUNIT_TEST_SUITE_REGISTRATION(LibetonyekUtilsTest);

}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>#include "unlimited.h"

#include "test/test_bitcoin.h"
#include "../consensus/consensus.h"

#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>

using namespace std;

// Defined in rpc_tests.cpp not bitcoin-cli.cpp
extern UniValue CallRPC(string strMethod);

BOOST_FIXTURE_TEST_SUITE(excessiveblock_test, TestingSetup)

BOOST_AUTO_TEST_CASE(rpc_excessive)
{
    BOOST_CHECK_NO_THROW(CallRPC("getexcessiveblock"));

    BOOST_CHECK_NO_THROW(CallRPC("getminingmaxblock"));

    BOOST_CHECK_THROW(CallRPC("setexcessiveblock not_uint"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("setexcessiveblock 1000000 not_uint"), boost::bad_lexical_cast);
    BOOST_CHECK_THROW(CallRPC("setexcessiveblock 1000000 -1"), boost::bad_lexical_cast);
    BOOST_CHECK_THROW(CallRPC("setexcessiveblock -1 0"), boost::bad_lexical_cast);

    BOOST_CHECK_THROW(CallRPC("setexcessiveblock 1000 1"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("setminingmaxblock 1000"));
    BOOST_CHECK_NO_THROW(CallRPC("setexcessiveblock 1000 1"));

    BOOST_CHECK_THROW(CallRPC("setexcessiveblock 1000 0 0"), runtime_error);

    BOOST_CHECK_THROW(CallRPC("setminingmaxblock"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock 100000"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock not_uint"),  boost::bad_lexical_cast);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock -1"),  boost::bad_lexical_cast);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock 0"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock 0 0"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("setminingmaxblock 1000"));
    BOOST_CHECK_NO_THROW(CallRPC("setminingmaxblock 101"));

}

BOOST_AUTO_TEST_CASE(buip005)
{
    string exceptedEB;
    string exceptedAD;
    excessiveBlockSize = 1000000;
    excessiveAcceptDepth = 9999999;
    exceptedEB = "EB1";
    exceptedAD = "AD9999999";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());
    BOOST_CHECK_MESSAGE(BUComments.back() == exceptedAD,
                        "AD ought to have been " << exceptedAD << " when excessiveBlockSize = " << excessiveAcceptDepth);
    excessiveBlockSize = 100000;
    excessiveAcceptDepth = 9999999 + 1;
    exceptedEB = "EB0.1";
    exceptedAD = "AD9999999";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());
    BOOST_CHECK_MESSAGE(BUComments.back() == exceptedAD,
                        "AD ought to have been " << exceptedAD << " when excessiveBlockSize = " << excessiveAcceptDepth);
    excessiveBlockSize = 10000;
    exceptedEB = "EB0";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());
    excessiveBlockSize = 150000;
    exceptedEB = "EB0.1";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been rounded to " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());
    excessiveBlockSize = 150000;
    exceptedEB = "EB0.1";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been rounded to " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());

    // set back to defaults
    excessiveBlockSize = 1000000;
    excessiveAcceptDepth = 4;
}

BOOST_AUTO_TEST_CASE(excessiveChecks)
{
  CBlock block;

  excessiveBlockSize = 16000000;  // Ignore excessive block size when checking sigops and block effort

  // Check sigops values

  // Maintain compatibility with the old sigops calculator for blocks <= 1MB
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE-1,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE-1,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS,100,100), "improper sigops");

  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE-1,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS+1,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS+1,100,100), "improper sigops");

  // Check sigops > 1MB.
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,1000000+1,(blockSigopsPerMb.value*2),100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,1000000+1,(blockSigopsPerMb.value*2)+1,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,(2*1000000),(blockSigopsPerMb.value*2)+1,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,(2*1000000)+1,(blockSigopsPerMb.value*2)+1,100,100), "improper sigops");

  // Check tx size values
  maxTxSize.value = DEFAULT_LARGEST_TRANSACTION;

  // Within a 1 MB block, a 1MB transaction is not excessive
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE,1,1,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE), "improper max tx");

  // With a > 1 MB block, use the maxTxSize to determine
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE+1,1,1,maxTxSize.value), "improper max tx");
  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE+1,1,1,maxTxSize.value+1), "improper max tx");

}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Added unit tests for emergent consesus validation functions.<commit_after>#include "unlimited.h"

#include "test/test_bitcoin.h"
#include "../consensus/consensus.h"

#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>

using namespace std;

// Defined in rpc_tests.cpp not bitcoin-cli.cpp
extern UniValue CallRPC(string strMethod);

BOOST_FIXTURE_TEST_SUITE(excessiveblock_test, TestingSetup)

BOOST_AUTO_TEST_CASE(rpc_excessive)
{
    BOOST_CHECK_NO_THROW(CallRPC("getexcessiveblock"));

    BOOST_CHECK_NO_THROW(CallRPC("getminingmaxblock"));

    BOOST_CHECK_THROW(CallRPC("setexcessiveblock not_uint"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("setexcessiveblock 1000000 not_uint"), boost::bad_lexical_cast);
    BOOST_CHECK_THROW(CallRPC("setexcessiveblock 1000000 -1"), boost::bad_lexical_cast);
    BOOST_CHECK_THROW(CallRPC("setexcessiveblock -1 0"), boost::bad_lexical_cast);

    BOOST_CHECK_THROW(CallRPC("setexcessiveblock 1000 1"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("setminingmaxblock 1000"));
    BOOST_CHECK_NO_THROW(CallRPC("setexcessiveblock 1000 1"));

    BOOST_CHECK_THROW(CallRPC("setexcessiveblock 1000 0 0"), runtime_error);

    BOOST_CHECK_THROW(CallRPC("setminingmaxblock"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock 100000"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock not_uint"),  boost::bad_lexical_cast);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock -1"),  boost::bad_lexical_cast);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock 0"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("setminingmaxblock 0 0"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("setminingmaxblock 1000"));
    BOOST_CHECK_NO_THROW(CallRPC("setminingmaxblock 101"));

}

BOOST_AUTO_TEST_CASE(buip005)
{
    string exceptedEB;
    string exceptedAD;
    excessiveBlockSize = 1000000;
    excessiveAcceptDepth = 9999999;
    exceptedEB = "EB1";
    exceptedAD = "AD9999999";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());
    BOOST_CHECK_MESSAGE(BUComments.back() == exceptedAD,
                        "AD ought to have been " << exceptedAD << " when excessiveBlockSize = " << excessiveAcceptDepth);
    excessiveBlockSize = 100000;
    excessiveAcceptDepth = 9999999 + 1;
    exceptedEB = "EB0.1";
    exceptedAD = "AD9999999";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());
    BOOST_CHECK_MESSAGE(BUComments.back() == exceptedAD,
                        "AD ought to have been " << exceptedAD << " when excessiveBlockSize = " << excessiveAcceptDepth);
    excessiveBlockSize = 10000;
    exceptedEB = "EB0";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());
    excessiveBlockSize = 150000;
    exceptedEB = "EB0.1";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been rounded to " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());
    excessiveBlockSize = 150000;
    exceptedEB = "EB0.1";
    settingsToUserAgentString();
    BOOST_CHECK_MESSAGE(BUComments.front() == exceptedEB,
                        "EB ought to have been rounded to " << exceptedEB << " when excessiveBlockSize = "
                        << excessiveBlockSize << " but was " << BUComments.front());

    // set back to defaults
    excessiveBlockSize = 1000000;
    excessiveAcceptDepth = 4;
}

BOOST_AUTO_TEST_CASE(excessiveChecks)
{
  CBlock block;

  excessiveBlockSize = 16000000;  // Ignore excessive block size when checking sigops and block effort

  // Check sigops values

  // Maintain compatibility with the old sigops calculator for blocks <= 1MB
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE-1,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE-1,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS,100,100), "improper sigops");

  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE-1,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS+1,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE,BLOCKSTREAM_CORE_MAX_BLOCK_SIGOPS+1,100,100), "improper sigops");

  // Check sigops > 1MB.
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,1000000+1,(blockSigopsPerMb.value*2),100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,1000000+1,(blockSigopsPerMb.value*2)+1,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,(2*1000000),(blockSigopsPerMb.value*2)+1,100,100), "improper sigops");
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,(2*1000000)+1,(blockSigopsPerMb.value*2)+1,100,100), "improper sigops");

  // Check tx size values
  maxTxSize.value = DEFAULT_LARGEST_TRANSACTION;

  // Within a 1 MB block, a 1MB transaction is not excessive
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE,1,1,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE), "improper max tx");

  // With a > 1 MB block, use the maxTxSize to determine
  BOOST_CHECK_MESSAGE(false == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE+1,1,1,maxTxSize.value), "improper max tx");
  BOOST_CHECK_MESSAGE(true == CheckExcessive(block,BLOCKSTREAM_CORE_MAX_BLOCK_SIZE+1,1,1,maxTxSize.value+1), "improper max tx");

}

BOOST_AUTO_TEST_CASE(check_validator_rule)
{
    BOOST_CHECK( MiningAndExcessiveBlockValidatorRule(1000000, 1000000));
    BOOST_CHECK( MiningAndExcessiveBlockValidatorRule(16000000, 1000000));
    BOOST_CHECK( MiningAndExcessiveBlockValidatorRule(1000001, 1000000));

    BOOST_CHECK( ! MiningAndExcessiveBlockValidatorRule(1000000, 1000001));
    BOOST_CHECK( ! MiningAndExcessiveBlockValidatorRule(1000000, 16000000));

    BOOST_CHECK( MiningAndExcessiveBlockValidatorRule(1357, 1357));
    BOOST_CHECK( MiningAndExcessiveBlockValidatorRule(161616, 2222));
    BOOST_CHECK( MiningAndExcessiveBlockValidatorRule(88889, 88888));

    BOOST_CHECK( ! MiningAndExcessiveBlockValidatorRule(929292, 929293));
    BOOST_CHECK( ! MiningAndExcessiveBlockValidatorRule(4, 234245));
}

BOOST_AUTO_TEST_CASE(check_excessive_validator)
{
    // fudge global variables....
    maxGeneratedBlock = 1000000;
    excessiveBlockSize = 888;

    unsigned int tmpExcessive = 1000000;
    std::string str;

    str = ExcessiveBlockValidator(tmpExcessive, NULL, true);
    BOOST_CHECK(str.empty());

    excessiveBlockSize = 888;
    str = ExcessiveBlockValidator(tmpExcessive, NULL, false);
    BOOST_CHECK(str.empty());

    str = ExcessiveBlockValidator(tmpExcessive, (unsigned int *) 42, true);
    BOOST_CHECK(str.empty());

    tmpExcessive = maxGeneratedBlock + 1;

    str = ExcessiveBlockValidator(tmpExcessive, NULL, true);
    BOOST_CHECK(str.empty());

    excessiveBlockSize = 888;
    str = ExcessiveBlockValidator(tmpExcessive, NULL, false);
    BOOST_CHECK(str.empty());

    str = ExcessiveBlockValidator(tmpExcessive, (unsigned int *) 42, true);
    BOOST_CHECK(str.empty());

    tmpExcessive = maxGeneratedBlock - 1;

    str = ExcessiveBlockValidator(tmpExcessive, NULL, true);
    BOOST_CHECK(! str.empty());

    str = ExcessiveBlockValidator(tmpExcessive, NULL, false);
    BOOST_CHECK(str.empty());

    str = ExcessiveBlockValidator(tmpExcessive, (unsigned int *) 42, true);
    BOOST_CHECK(! str.empty());
}

BOOST_AUTO_TEST_CASE(check_generated_block_validator)
{
    // fudge global variables....
    maxGeneratedBlock = 888;
    excessiveBlockSize = 1000000;

    uint64_t tmpMGB = 1000000;
    std::string str;

    str = MiningBlockSizeValidator(tmpMGB, NULL, true);
    BOOST_CHECK(str.empty());

    maxGeneratedBlock = 8888881;
    str = MiningBlockSizeValidator(tmpMGB, NULL, false);
    BOOST_CHECK(str.empty());

    str = MiningBlockSizeValidator(tmpMGB, (uint64_t *) 42, true);
    BOOST_CHECK(str.empty());

    tmpMGB = excessiveBlockSize - 1;

    str = MiningBlockSizeValidator(tmpMGB, NULL, true);
    BOOST_CHECK(str.empty());

    maxGeneratedBlock = 8888881;
    str = MiningBlockSizeValidator(tmpMGB, NULL, false);
    BOOST_CHECK(str.empty());

    str = MiningBlockSizeValidator(tmpMGB, (uint64_t *) 42, true);
    BOOST_CHECK(str.empty());

    tmpMGB = excessiveBlockSize + 1;

    str = MiningBlockSizeValidator(tmpMGB, NULL, true);
    BOOST_CHECK(! str.empty());

    str = MiningBlockSizeValidator(tmpMGB, NULL, false);
    BOOST_CHECK(str.empty());

    str = MiningBlockSizeValidator(tmpMGB, (uint64_t *) 42, true);
    BOOST_CHECK(! str.empty());
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "Mocks.hpp"

using namespace blackhole;

TEST(verbose_logger_t, Class) {
    enum level : std::uint64_t { debug, info, warn, error };
    verbose_logger_t<level> log;
    UNUSED(log);
}

TEST(verbose_logger_t, OpenRecordByDefault) {
    enum level : std::uint64_t { debug, info, warn, error };
    std::unique_ptr<mock::frontend_t> frontend;

    verbose_logger_t<level> log;
    log.add_frontend(std::move(frontend));
    log::record_t record = log.open_record(level::debug);
    EXPECT_TRUE(record.valid());
}

TEST(verbose_logger_t, OpenRecordForValidVerbosityLevel) {
    enum class level : std::uint64_t { debug, info, warn, error };
    std::unique_ptr<mock::frontend_t> frontend;

    verbose_logger_t<level> log;
    log.add_frontend(std::move(frontend));
    log.set_filter(keyword::severity<level>() >= level::info);
    EXPECT_FALSE(log.open_record(level::debug).valid());
    EXPECT_TRUE(log.open_record(level::info).valid());
    EXPECT_TRUE(log.open_record(level::warn).valid());
    EXPECT_TRUE(log.open_record(level::error).valid());
}

TEST(verbose_logger_t, Manual) {
    enum level : std::uint64_t { debug, info, warn, error };
    verbose_logger_t<level> log;

    //!@note: Factory starts here...
    auto formatter = std::make_unique<formatter::string_t>("[]: %(message)s [%(...L)s]");
    auto sink = std::make_unique<sink::file_t<>>("/dev/stdout");
    auto frontend = std::make_unique<frontend_t<formatter::string_t, sink::file_t<>>>(std::move(formatter), std::move(sink));
    //!@note ... till here.
    log.add_frontend(std::move(frontend));

    //!@note: Next lines can be hided via macro: LOG(log, debug, "Message %s", "Hell", { keyword::answer = 42, keyword::blah = "WAT?", keyword::make("urgent", 1) });
    log::record_t record = log.open_record(level::error);
    if (record.valid()) {
        record.attributes["message"] = { utils::format("Some message from: '%s'!", "Hell") };
        // Add another attributes.
        log.push(std::move(record));
    }
}

//!@todo: Make severity string mapper.
//!@todo: Specialization for `syslog_t` frontend. It's needed for providing loglevel to the `syslog_t`.
<commit_msg>One todo less.<commit_after>#include "Mocks.hpp"

using namespace blackhole;

TEST(verbose_logger_t, Class) {
    enum level : std::uint64_t { debug, info, warn, error };
    verbose_logger_t<level> log;
    UNUSED(log);
}

TEST(verbose_logger_t, OpenRecordByDefault) {
    enum level : std::uint64_t { debug, info, warn, error };
    std::unique_ptr<mock::frontend_t> frontend;

    verbose_logger_t<level> log;
    log.add_frontend(std::move(frontend));
    log::record_t record = log.open_record(level::debug);
    EXPECT_TRUE(record.valid());
}

TEST(verbose_logger_t, OpenRecordForValidVerbosityLevel) {
    enum class level : std::uint64_t { debug, info, warn, error };
    std::unique_ptr<mock::frontend_t> frontend;

    verbose_logger_t<level> log;
    log.add_frontend(std::move(frontend));
    log.set_filter(keyword::severity<level>() >= level::info);
    EXPECT_FALSE(log.open_record(level::debug).valid());
    EXPECT_TRUE(log.open_record(level::info).valid());
    EXPECT_TRUE(log.open_record(level::warn).valid());
    EXPECT_TRUE(log.open_record(level::error).valid());
}

TEST(verbose_logger_t, Manual) {
    enum level : std::uint64_t { debug, info, warn, error };
    verbose_logger_t<level> log;

    //!@note: Factory starts here...
    auto formatter = std::make_unique<formatter::string_t>("[]: %(message)s [%(...L)s]");
    auto sink = std::make_unique<sink::file_t<>>("/dev/stdout");
    auto frontend = std::make_unique<frontend_t<formatter::string_t, sink::file_t<>>>(std::move(formatter), std::move(sink));
    //!@note ... till here.
    log.add_frontend(std::move(frontend));

    //!@note: Next lines can be hided via macro: LOG(log, debug, "Message %s", "Hell", { keyword::answer = 42, keyword::blah = "WAT?", keyword::make("urgent", 1) });
    log::record_t record = log.open_record(level::error);
    if (record.valid()) {
        record.attributes["message"] = { utils::format("Some message from: '%s'!", "Hell") };
        // Add another attributes.
        log.push(std::move(record));
    }
}

//!@todo: Make severity string mapper.
<|endoftext|>