<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2019 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "d3d11_test.h"

struct Binding_Hazards : D3D11GraphicsTest
{
  static constexpr const char *Description = "Test of D3D11 hazard tracking write/read bindings";

  std::string compute = R"EOSHADER(

Texture2D<uint> texin : register(t0);
Buffer<uint> bufin : register(t1);
RWTexture2D<uint> texout1 : register(u0);
RWBuffer<uint> bufout1 : register(u1);
RWTexture2D<uint> texout2 : register(u2);
RWBuffer<uint> bufout2 : register(u3);

[numthreads(1,1,1)]
void main()
{
	texout1[uint2(3,4)] = bufin[3];
	texout2[uint2(4,4)] = texin[uint2(3,3)];
	bufout1[4] = bufin[4];
	bufout2[3] = texin[uint2(4,4)];
}

)EOSHADER";

  int main(int argc, char **argv)
  {
    // so that running individually we get errors
    debugDevice = true;

    // initialise, create window, create device, etc
    if(!Init(argc, argv))
      return 3;

    ID3D11ComputeShaderPtr cs = CreateCS(Compile(compute, "main", "cs_5_0"));

    ID3D11Texture2DPtr tex0 = MakeTexture(DXGI_FORMAT_R32_UINT, 8, 8).UAV().RTV();
    ID3D11UnorderedAccessViewPtr uav0 = MakeUAV(tex0);
    ID3D11RenderTargetViewPtr rtv0 = MakeRTV(tex0);

    ID3D11Texture2DPtr tex1 = MakeTexture(DXGI_FORMAT_R32_UINT, 8, 8).UAV().RTV();
    ID3D11UnorderedAccessViewPtr uav1 = MakeUAV(tex1);
    ID3D11RenderTargetViewPtr rtv1 = MakeRTV(tex1);

    ID3D11BufferPtr buf1 = MakeBuffer().Size(65536).SRV().UAV();
    ID3D11BufferPtr buf2 = MakeBuffer().Size(65536).SRV();
    ID3D11ShaderResourceViewPtr buf1SRV = MakeSRV(buf1).Format(DXGI_FORMAT_R32_UINT);
    ID3D11UnorderedAccessViewPtr buf1UAV = MakeUAV(buf1).Format(DXGI_FORMAT_R32_UINT);

    while(Running())
    {
      ctx->ClearState();

      ctx->CSSetShader(cs, NULL, 0);

      ID3D11ShaderResourceViewPtr tempSRV =
          MakeSRV(buf2).Format(DXGI_FORMAT_R32_UINT).NumElements(128);

      ctx->CSSetShaderResources(1, 1, &tempSRV.GetInterfacePtr());

      ULONG refcount = tempSRV->Release();

      ID3D11ShaderResourceView *srvs[2] = {NULL, tempSRV.GetInterfacePtr()};

      ctx->CSSetShaderResources(1, 2, srvs);

      refcount = tempSRV->AddRef();
      refcount = tempSRV->Release();

      ctx->CSSetShaderResources(3, 2, srvs);

      refcount = tempSRV->AddRef();
      refcount = tempSRV->Release();

      ctx->CSSetUnorderedAccessViews(0, 1, &uav0.GetInterfacePtr(), NULL);
      ctx->CSSetUnorderedAccessViews(2, 1, &uav1.GetInterfacePtr(), NULL);

      // try to bind the buffer to two slots, find it gets unbound
      ctx->CSSetUnorderedAccessViews(1, 1, &buf1UAV.GetInterfacePtr(), NULL);
      ctx->CSSetUnorderedAccessViews(3, 1, &buf1UAV.GetInterfacePtr(), NULL);

      ID3D11UnorderedAccessView *getCSUAVs[4] = {};
      ID3D11RenderTargetView *getOMRTV = NULL;
      ID3D11RenderTargetView *getOMRTVs[2] = {};
      ID3D11UnorderedAccessView *getOMUAV = NULL;

      // Dispatch each time so we can also check state in UI
      ctx->Dispatch(1, 1, 1);
      ctx->CSGetUnorderedAccessViews(0, 4, getCSUAVs);

      TEST_ASSERT(getCSUAVs[0] == uav0, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[1] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[2] == uav1, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[3] == buf1UAV, "Unexpected binding");

      // this should unbind uav0 because it's re-bound as rtv0, then unbind uav1 because it's
      // rebound on another UAV slot
      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv0.GetInterfacePtr(), NULL, 1, 1,
                                                     &uav1.GetInterfacePtr(), NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);
      ctx->CSGetUnorderedAccessViews(0, 4, getCSUAVs);

      TEST_ASSERT(getOMRTV == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == uav1, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[0] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[1] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[2] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[3] == buf1UAV, "Unexpected binding");

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
                                                     NULL, NULL, 1, 0, NULL, NULL);

      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);

      TEST_ASSERT(getOMRTV == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == NULL, "Unexpected binding");

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv0.GetInterfacePtr(), NULL, 1, 1,
                                                     &uav1.GetInterfacePtr(), NULL);

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
                                                     &rtv1.GetInterfacePtr(), NULL, 1, 0, NULL, NULL);

      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);

      TEST_ASSERT(getOMRTV == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == NULL, "Unexpected binding");

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv0.GetInterfacePtr(), NULL, 1, 1,
                                                     &uav1.GetInterfacePtr(), NULL);

      ID3D11RenderTargetView *empty = NULL;
      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &empty, NULL, 1,
                                                     D3D11_KEEP_UNORDERED_ACCESS_VIEWS, NULL, NULL);

      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);

      TEST_ASSERT(getOMRTV == empty, "Unexpected binding");
      TEST_ASSERT(getOMUAV == uav1, "Unexpected binding");

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv0.GetInterfacePtr(), NULL, 1, 1,
                                                     &uav1.GetInterfacePtr(), NULL);

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(
          1, &empty, NULL, 1, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, &uav0.GetInterfacePtr(), NULL);

      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);

      TEST_ASSERT(getOMRTV == empty, "Unexpected binding");
      TEST_ASSERT(getOMUAV == uav1, "Unexpected binding");

      // finally this should unbind both OM views, and rebind back on the CS
      ctx->CSSetUnorderedAccessViews(0, 1, &uav0.GetInterfacePtr(), NULL);
      ctx->CSSetUnorderedAccessViews(2, 1, &uav1.GetInterfacePtr(), NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);
      ctx->CSGetUnorderedAccessViews(0, 4, getCSUAVs);

      TEST_ASSERT(getOMRTV == NULL, "Unexpected binding");
      TEST_ASSERT(getOMUAV == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[0] == uav0, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[1] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[2] == uav1, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[3] == buf1UAV, "Unexpected binding");

      ctx->ClearState();

      ctx->CSSetShader(cs, NULL, 0);

      ID3D11RenderTargetView *RTVs[] = {
          rtv0, rtv0,
      };

      // can't bind the same RTV to two slots
      ctx->OMSetRenderTargets(2, RTVs, NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(2, getOMRTVs, NULL, 2, 1, &getOMUAV);
      TEST_ASSERT(getOMRTVs[0] == NULL, "Unexpected binding");
      TEST_ASSERT(getOMRTVs[1] == NULL, "Unexpected binding");
      TEST_ASSERT(getOMUAV == NULL, "Unexpected binding");

      RTVs[0] = rtv1;
      RTVs[1] = rtv0;

      // this bind is fine, no overlapping state
      ctx->OMSetRenderTargetsAndUnorderedAccessViews(2, RTVs, NULL, 2, 1,
                                                     &buf1UAV.GetInterfacePtr(), NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(2, getOMRTVs, NULL, 2, 1, &getOMUAV);
      TEST_ASSERT(getOMRTVs[0] == rtv1, "Unexpected binding");
      TEST_ASSERT(getOMRTVs[1] == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == buf1UAV, "Unexpected binding");

      RTVs[0] = rtv0;
      RTVs[1] = rtv1;

      // this bind is discarded, because rtv0 overlaps uav0.
      ctx->OMSetRenderTargetsAndUnorderedAccessViews(2, RTVs, NULL, 2, 1, &uav0.GetInterfacePtr(),
                                                     NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(2, getOMRTVs, NULL, 2, 1, &getOMUAV);
      TEST_ASSERT(getOMRTVs[0] == rtv1, "Unexpected binding");
      TEST_ASSERT(getOMRTVs[1] == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == buf1UAV, "Unexpected binding");

      Present();
    }

    return 0;
  }
};

REGISTER_TEST(Binding_Hazards);<commit_msg>Fix D3D11_Binding_Hazards test<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2019 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "d3d11_test.h"

struct Binding_Hazards : D3D11GraphicsTest
{
  static constexpr const char *Description = "Test of D3D11 hazard tracking write/read bindings";

  std::string compute = R"EOSHADER(

Texture2D<uint> texin : register(t0);
Buffer<uint> bufin : register(t1);
RWTexture2D<uint> texout1 : register(u0);
RWBuffer<uint> bufout1 : register(u1);
RWTexture2D<uint> texout2 : register(u2);
RWBuffer<uint> bufout2 : register(u3);

[numthreads(1,1,1)]
void main()
{
	texout1[uint2(3,4)] = bufin[3];
	texout2[uint2(4,4)] = texin[uint2(3,3)];
	bufout1[4] = bufin[4];
	bufout2[3] = texin[uint2(4,4)];
}

)EOSHADER";

  int main(int argc, char **argv)
  {
    // so that running individually we get errors
    debugDevice = true;

    // initialise, create window, create device, etc
    if(!Init(argc, argv))
      return 3;

    ID3D11ComputeShaderPtr cs = CreateCS(Compile(compute, "main", "cs_5_0"));

    ID3D11Texture2DPtr tex0 = MakeTexture(DXGI_FORMAT_R32_UINT, 8, 8).UAV().RTV();
    ID3D11UnorderedAccessViewPtr uav0 = MakeUAV(tex0);
    ID3D11RenderTargetViewPtr rtv0 = MakeRTV(tex0);

    ID3D11Texture2DPtr tex1 = MakeTexture(DXGI_FORMAT_R32_UINT, 8, 8).UAV().RTV();
    ID3D11UnorderedAccessViewPtr uav1 = MakeUAV(tex1);
    ID3D11RenderTargetViewPtr rtv1 = MakeRTV(tex1);

    ID3D11BufferPtr buf1 = MakeBuffer().Size(65536).SRV().UAV();
    ID3D11BufferPtr buf2 = MakeBuffer().Size(65536).SRV();
    ID3D11ShaderResourceViewPtr buf1SRV = MakeSRV(buf1).Format(DXGI_FORMAT_R32_UINT);
    ID3D11UnorderedAccessViewPtr buf1UAV = MakeUAV(buf1).Format(DXGI_FORMAT_R32_UINT);

    while(Running())
    {
      ctx->ClearState();

      ctx->CSSetShader(cs, NULL, 0);

      ID3D11ShaderResourceViewPtr tempSRV =
          MakeSRV(buf2).Format(DXGI_FORMAT_R32_UINT).NumElements(128);

      ctx->CSSetShaderResources(1, 1, &tempSRV.GetInterfacePtr());

      tempSRV->AddRef();
      ULONG refcount = tempSRV->Release();

      ID3D11ShaderResourceView *srvs[2] = {NULL, tempSRV.GetInterfacePtr()};

      ctx->CSSetShaderResources(1, 2, srvs);

      refcount = tempSRV->AddRef();
      refcount = tempSRV->Release();

      ctx->CSSetShaderResources(3, 2, srvs);

      refcount = tempSRV->AddRef();
      refcount = tempSRV->Release();

      ctx->CSSetUnorderedAccessViews(0, 1, &uav0.GetInterfacePtr(), NULL);
      ctx->CSSetUnorderedAccessViews(2, 1, &uav1.GetInterfacePtr(), NULL);

      // try to bind the buffer to two slots, find it gets unbound
      ctx->CSSetUnorderedAccessViews(1, 1, &buf1UAV.GetInterfacePtr(), NULL);
      ctx->CSSetUnorderedAccessViews(3, 1, &buf1UAV.GetInterfacePtr(), NULL);

      ID3D11UnorderedAccessView *getCSUAVs[4] = {};
      ID3D11RenderTargetView *getOMRTV = NULL;
      ID3D11RenderTargetView *getOMRTVs[2] = {};
      ID3D11UnorderedAccessView *getOMUAV = NULL;

      // Dispatch each time so we can also check state in UI
      ctx->Dispatch(1, 1, 1);
      ctx->CSGetUnorderedAccessViews(0, 4, getCSUAVs);

      TEST_ASSERT(getCSUAVs[0] == uav0, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[1] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[2] == uav1, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[3] == buf1UAV, "Unexpected binding");

      // this should unbind uav0 because it's re-bound as rtv0, then unbind uav1 because it's
      // rebound on another UAV slot
      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv0.GetInterfacePtr(), NULL, 1, 1,
                                                     &uav1.GetInterfacePtr(), NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);
      ctx->CSGetUnorderedAccessViews(0, 4, getCSUAVs);

      TEST_ASSERT(getOMRTV == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == uav1, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[0] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[1] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[2] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[3] == buf1UAV, "Unexpected binding");

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
                                                     NULL, NULL, 1, 0, NULL, NULL);

      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);

      TEST_ASSERT(getOMRTV == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == NULL, "Unexpected binding");

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv0.GetInterfacePtr(), NULL, 1, 1,
                                                     &uav1.GetInterfacePtr(), NULL);

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
                                                     &rtv1.GetInterfacePtr(), NULL, 1, 0, NULL, NULL);

      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);

      TEST_ASSERT(getOMRTV == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == NULL, "Unexpected binding");

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv0.GetInterfacePtr(), NULL, 1, 1,
                                                     &uav1.GetInterfacePtr(), NULL);

      ID3D11RenderTargetView *empty = NULL;
      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &empty, NULL, 1,
                                                     D3D11_KEEP_UNORDERED_ACCESS_VIEWS, NULL, NULL);

      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);

      TEST_ASSERT(getOMRTV == empty, "Unexpected binding");
      TEST_ASSERT(getOMUAV == uav1, "Unexpected binding");

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv0.GetInterfacePtr(), NULL, 1, 1,
                                                     &uav1.GetInterfacePtr(), NULL);

      ctx->OMSetRenderTargetsAndUnorderedAccessViews(
          1, &empty, NULL, 1, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, &uav0.GetInterfacePtr(), NULL);

      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);

      TEST_ASSERT(getOMRTV == empty, "Unexpected binding");
      TEST_ASSERT(getOMUAV == uav1, "Unexpected binding");

      // finally this should unbind both OM views, and rebind back on the CS
      ctx->CSSetUnorderedAccessViews(0, 1, &uav0.GetInterfacePtr(), NULL);
      ctx->CSSetUnorderedAccessViews(2, 1, &uav1.GetInterfacePtr(), NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(1, &getOMRTV, NULL, 1, 1, &getOMUAV);
      ctx->CSGetUnorderedAccessViews(0, 4, getCSUAVs);

      TEST_ASSERT(getOMRTV == NULL, "Unexpected binding");
      TEST_ASSERT(getOMUAV == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[0] == uav0, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[1] == NULL, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[2] == uav1, "Unexpected binding");
      TEST_ASSERT(getCSUAVs[3] == buf1UAV, "Unexpected binding");

      ctx->ClearState();

      ctx->CSSetShader(cs, NULL, 0);

      ID3D11RenderTargetView *RTVs[] = {
          rtv0, rtv0,
      };

      // can't bind the same RTV to two slots
      ctx->OMSetRenderTargets(2, RTVs, NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(2, getOMRTVs, NULL, 2, 1, &getOMUAV);
      TEST_ASSERT(getOMRTVs[0] == NULL, "Unexpected binding");
      TEST_ASSERT(getOMRTVs[1] == NULL, "Unexpected binding");
      TEST_ASSERT(getOMUAV == NULL, "Unexpected binding");

      RTVs[0] = rtv1;
      RTVs[1] = rtv0;

      // this bind is fine, no overlapping state
      ctx->OMSetRenderTargetsAndUnorderedAccessViews(2, RTVs, NULL, 2, 1,
                                                     &buf1UAV.GetInterfacePtr(), NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(2, getOMRTVs, NULL, 2, 1, &getOMUAV);
      TEST_ASSERT(getOMRTVs[0] == rtv1, "Unexpected binding");
      TEST_ASSERT(getOMRTVs[1] == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == buf1UAV, "Unexpected binding");

      RTVs[0] = rtv0;
      RTVs[1] = rtv1;

      // this bind is discarded, because rtv0 overlaps uav0.
      ctx->OMSetRenderTargetsAndUnorderedAccessViews(2, RTVs, NULL, 2, 1, &uav0.GetInterfacePtr(),
                                                     NULL);

      ctx->Dispatch(1, 1, 1);
      ctx->OMGetRenderTargetsAndUnorderedAccessViews(2, getOMRTVs, NULL, 2, 1, &getOMUAV);
      TEST_ASSERT(getOMRTVs[0] == rtv1, "Unexpected binding");
      TEST_ASSERT(getOMRTVs[1] == rtv0, "Unexpected binding");
      TEST_ASSERT(getOMUAV == buf1UAV, "Unexpected binding");

      Present();
    }

    return 0;
  }
};

REGISTER_TEST(Binding_Hazards);<|endoftext|>


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

#include "app/app_switches.h"
#include "base/command_line.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/gpu_process_host_ui_shim.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/common/child_process_logging.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/gpu_info.h"
#include "chrome/common/gpu_messages.h"
#include "chrome/common/render_messages.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_switches.h"

#if defined(OS_LINUX)
#include "gfx/gtk_native_view_id_manager.h"
#endif

namespace {

// Tasks used by this file
class RouteOnUIThreadTask : public Task {
 public:
  explicit RouteOnUIThreadTask(const IPC::Message& msg) : msg_(msg) {
  }

 private:
  void Run() {
    GpuProcessHostUIShim::Get()->OnMessageReceived(msg_);
  }
  IPC::Message msg_;
};

// Global GpuProcessHost instance.
// We can not use Singleton<GpuProcessHost> because that gets
// terminated on the wrong thread (main thread). We need the
// GpuProcessHost to be terminated on the same thread on which it is
// initialized, the IO thread.
static GpuProcessHost* sole_instance_ = NULL;

}  // anonymous namespace

GpuProcessHost::GpuProcessHost()
    : BrowserChildProcessHost(GPU_PROCESS, NULL),
      initialized_(false),
      initialized_successfully_(false) {
  DCHECK_EQ(sole_instance_, static_cast<GpuProcessHost*>(NULL));
}

GpuProcessHost::~GpuProcessHost() {
  while (!queued_synchronization_replies_.empty()) {
    delete queued_synchronization_replies_.front().reply;
    queued_synchronization_replies_.pop();
  }
  DCHECK_EQ(sole_instance_, this);
  sole_instance_ = NULL;
}

bool GpuProcessHost::EnsureInitialized() {
  if (!initialized_) {
    initialized_ = true;
    initialized_successfully_ = Init();
  }
  return initialized_successfully_;
}

bool GpuProcessHost::Init() {
  if (!CreateChannel())
    return false;

  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
  CommandLine::StringType gpu_launcher =
      browser_command_line.GetSwitchValueNative(switches::kGpuLauncher);

  FilePath exe_path = ChildProcessHost::GetChildPath(gpu_launcher.empty());
  if (exe_path.empty())
    return false;

  CommandLine* cmd_line = new CommandLine(exe_path);
  cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
  cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());

  // Propagate relevant command line switches.
  static const char* const kSwitchNames[] = {
    switches::kUseGL,
    switches::kDisableGpuVsync,
    switches::kDisableLogging,
    switches::kEnableLogging,
    switches::kGpuStartupDialog,
    switches::kLoggingLevel,
  };
  cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
                             arraysize(kSwitchNames));

  // If specified, prepend a launcher program to the command line.
  if (!gpu_launcher.empty())
    cmd_line->PrependWrapper(gpu_launcher);

  Launch(
#if defined(OS_WIN)
      FilePath(),
#elif defined(OS_POSIX)
      false,  // Never use the zygote (GPU plugin can't be sandboxed).
      base::environment_vector(),
#endif
      cmd_line);

  return true;
}

// static
GpuProcessHost* GpuProcessHost::Get() {
  if (sole_instance_ == NULL)
    sole_instance_ = new GpuProcessHost();
  return sole_instance_;
}

// static
void GpuProcessHost::SendAboutGpuCrash() {
  Get()->Send(new GpuMsg_Crash());
}

// static
void GpuProcessHost::SendAboutGpuHang() {
  Get()->Send(new GpuMsg_Hang());
}

bool GpuProcessHost::Send(IPC::Message* msg) {
  if (!EnsureInitialized())
    return false;

  return BrowserChildProcessHost::Send(msg);
}

void GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
  if (message.routing_id() == MSG_ROUTING_CONTROL) {
    OnControlMessageReceived(message);
  } else {
    // Need to transfer this message to the UI thread and the
    // GpuProcessHostUIShim for dispatching via its message router.
    ChromeThread::PostTask(ChromeThread::UI,
                           FROM_HERE,
                           new RouteOnUIThreadTask(message));
  }
}

void GpuProcessHost::EstablishGpuChannel(int renderer_id,
                                         ResourceMessageFilter* filter) {
  if (Send(new GpuMsg_EstablishChannel(renderer_id))) {
    sent_requests_.push(ChannelRequest(filter));
  } else {
    ReplyToRenderer(IPC::ChannelHandle(), GPUInfo(), filter);
  }
}

void GpuProcessHost::Synchronize(IPC::Message* reply,
                                 ResourceMessageFilter* filter) {
  queued_synchronization_replies_.push(SynchronizationRequest(reply, filter));
  Send(new GpuMsg_Synchronize());
}

GPUInfo GpuProcessHost::gpu_info() const {
  return gpu_info_;
}

void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) {
  IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message)
    IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished)
    IPC_MESSAGE_HANDLER(GpuHostMsg_SynchronizeReply, OnSynchronizeReply)
    IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected,
                        OnGraphicsInfoCollected)
#if defined(OS_LINUX)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_GetViewXID, OnGetViewXID)
#elif defined(OS_MACOSX)
    IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceSetIOSurface,
                        OnAcceleratedSurfaceSetIOSurface)
    IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
                        OnAcceleratedSurfaceBuffersSwapped)
#endif
    IPC_MESSAGE_UNHANDLED_ERROR()
  IPC_END_MESSAGE_MAP()
}

void GpuProcessHost::OnChannelEstablished(
    const IPC::ChannelHandle& channel_handle,
    const GPUInfo& gpu_info) {
  const ChannelRequest& request = sent_requests_.front();
  ReplyToRenderer(channel_handle, gpu_info, request.filter);
  sent_requests_.pop();
  gpu_info_ = gpu_info;
  child_process_logging::SetGpuInfo(gpu_info);
}

void GpuProcessHost::OnSynchronizeReply() {
  const SynchronizationRequest& request =
      queued_synchronization_replies_.front();
  request.filter->Send(request.reply);
  queued_synchronization_replies_.pop();
}

void GpuProcessHost::OnGraphicsInfoCollected(const GPUInfo& gpu_info) {
  gpu_info_ = gpu_info;
}

#if defined(OS_LINUX)

namespace {

void SendDelayedReply(IPC::Message* reply_msg) {
  GpuProcessHost::Get()->Send(reply_msg);
}

void GetViewXIDDispatcher(gfx::NativeViewId id, IPC::Message* reply_msg) {
  unsigned long xid;

  GtkNativeViewManager* manager = Singleton<GtkNativeViewManager>::get();
  if (!manager->GetPermanentXIDForId(&xid, id)) {
    DLOG(ERROR) << "Can't find XID for view id " << id;
    xid = 0;
  }

  GpuHostMsg_GetViewXID::WriteReplyParams(reply_msg, xid);

  // Have to reply from IO thread.
  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableFunction(&SendDelayedReply, reply_msg));
}

}

void GpuProcessHost::OnGetViewXID(gfx::NativeViewId id,
                                  IPC::Message *reply_msg) {
  // Have to request a permanent overlay from UI thread.
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      NewRunnableFunction(&GetViewXIDDispatcher, id, reply_msg));
}

#elif defined(OS_MACOSX)

namespace {

class SetIOSurfaceDispatcher : public Task {
 public:
  SetIOSurfaceDispatcher(
      const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params)
      : params_(params) {
  }

  void Run() {
    RenderViewHost* host = RenderViewHost::FromID(params_.renderer_id,
                                                  params_.render_view_id);
    if (!host)
      return;
    RenderWidgetHostView* view = host->view();
    if (!view)
      return;
    view->AcceleratedSurfaceSetIOSurface(params_.window,
                                         params_.width,
                                         params_.height,
                                         params_.identifier);
  }

 private:
  GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params_;

  DISALLOW_COPY_AND_ASSIGN(SetIOSurfaceDispatcher);
};

}  // namespace

void GpuProcessHost::OnAcceleratedSurfaceSetIOSurface(
    const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params) {
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      new SetIOSurfaceDispatcher(params));
}

namespace {

class BuffersSwappedDispatcher : public Task {
 public:
  BuffersSwappedDispatcher(
      int32 renderer_id, int32 render_view_id, gfx::PluginWindowHandle window)
      : renderer_id_(renderer_id),
        render_view_id_(render_view_id),
        window_(window) {
  }

  void Run() {
    RenderViewHost* host = RenderViewHost::FromID(renderer_id_,
                                                  render_view_id_);
    if (!host)
      return;
    RenderWidgetHostView* view = host->view();
    if (!view)
      return;
    view->AcceleratedSurfaceBuffersSwapped(window_);
  }

 private:
  int32 renderer_id_;
  int32 render_view_id_;
  gfx::PluginWindowHandle window_;

  DISALLOW_COPY_AND_ASSIGN(BuffersSwappedDispatcher);
};

}  // namespace

void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
    int32 renderer_id,
    int32 render_view_id,
    gfx::PluginWindowHandle window) {
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      new BuffersSwappedDispatcher(renderer_id, render_view_id, window));
}
#endif

void GpuProcessHost::ReplyToRenderer(
    const IPC::ChannelHandle& channel,
    const GPUInfo& gpu_info,
    ResourceMessageFilter* filter) {
  ViewMsg_GpuChannelEstablished* message =
      new ViewMsg_GpuChannelEstablished(channel, gpu_info);
  // If the renderer process is performing synchronous initialization,
  // it needs to handle this message before receiving the reply for
  // the synchronous ViewHostMsg_SynchronizeGpu message.
  message->set_unblock(true);
  filter->Send(message);
}

URLRequestContext* GpuProcessHost::GetRequestContext(
    uint32 request_id,
    const ViewHostMsg_Resource_Request& request_data) {
  return NULL;
}

bool GpuProcessHost::CanShutdown() {
  return true;
}
<commit_msg>Pass --enable-accelerated-decoding to the GPU process<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/browser/gpu_process_host.h"

#include "app/app_switches.h"
#include "base/command_line.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/gpu_process_host_ui_shim.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/common/child_process_logging.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/gpu_info.h"
#include "chrome/common/gpu_messages.h"
#include "chrome/common/render_messages.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_switches.h"
#include "media/base/media_switches.h"

#if defined(OS_LINUX)
#include "gfx/gtk_native_view_id_manager.h"
#endif

namespace {

// Tasks used by this file
class RouteOnUIThreadTask : public Task {
 public:
  explicit RouteOnUIThreadTask(const IPC::Message& msg) : msg_(msg) {
  }

 private:
  void Run() {
    GpuProcessHostUIShim::Get()->OnMessageReceived(msg_);
  }
  IPC::Message msg_;
};

// Global GpuProcessHost instance.
// We can not use Singleton<GpuProcessHost> because that gets
// terminated on the wrong thread (main thread). We need the
// GpuProcessHost to be terminated on the same thread on which it is
// initialized, the IO thread.
static GpuProcessHost* sole_instance_ = NULL;

}  // anonymous namespace

GpuProcessHost::GpuProcessHost()
    : BrowserChildProcessHost(GPU_PROCESS, NULL),
      initialized_(false),
      initialized_successfully_(false) {
  DCHECK_EQ(sole_instance_, static_cast<GpuProcessHost*>(NULL));
}

GpuProcessHost::~GpuProcessHost() {
  while (!queued_synchronization_replies_.empty()) {
    delete queued_synchronization_replies_.front().reply;
    queued_synchronization_replies_.pop();
  }
  DCHECK_EQ(sole_instance_, this);
  sole_instance_ = NULL;
}

bool GpuProcessHost::EnsureInitialized() {
  if (!initialized_) {
    initialized_ = true;
    initialized_successfully_ = Init();
  }
  return initialized_successfully_;
}

bool GpuProcessHost::Init() {
  if (!CreateChannel())
    return false;

  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
  CommandLine::StringType gpu_launcher =
      browser_command_line.GetSwitchValueNative(switches::kGpuLauncher);

  FilePath exe_path = ChildProcessHost::GetChildPath(gpu_launcher.empty());
  if (exe_path.empty())
    return false;

  CommandLine* cmd_line = new CommandLine(exe_path);
  cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
  cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());

  // Propagate relevant command line switches.
  static const char* const kSwitchNames[] = {
    switches::kUseGL,
    switches::kDisableGpuVsync,
    switches::kDisableLogging,
    switches::kEnableAcceleratedDecoding,
    switches::kEnableLogging,
    switches::kGpuStartupDialog,
    switches::kLoggingLevel,
  };
  cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
                             arraysize(kSwitchNames));

  // If specified, prepend a launcher program to the command line.
  if (!gpu_launcher.empty())
    cmd_line->PrependWrapper(gpu_launcher);

  Launch(
#if defined(OS_WIN)
      FilePath(),
#elif defined(OS_POSIX)
      false,  // Never use the zygote (GPU plugin can't be sandboxed).
      base::environment_vector(),
#endif
      cmd_line);

  return true;
}

// static
GpuProcessHost* GpuProcessHost::Get() {
  if (sole_instance_ == NULL)
    sole_instance_ = new GpuProcessHost();
  return sole_instance_;
}

// static
void GpuProcessHost::SendAboutGpuCrash() {
  Get()->Send(new GpuMsg_Crash());
}

// static
void GpuProcessHost::SendAboutGpuHang() {
  Get()->Send(new GpuMsg_Hang());
}

bool GpuProcessHost::Send(IPC::Message* msg) {
  if (!EnsureInitialized())
    return false;

  return BrowserChildProcessHost::Send(msg);
}

void GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
  if (message.routing_id() == MSG_ROUTING_CONTROL) {
    OnControlMessageReceived(message);
  } else {
    // Need to transfer this message to the UI thread and the
    // GpuProcessHostUIShim for dispatching via its message router.
    ChromeThread::PostTask(ChromeThread::UI,
                           FROM_HERE,
                           new RouteOnUIThreadTask(message));
  }
}

void GpuProcessHost::EstablishGpuChannel(int renderer_id,
                                         ResourceMessageFilter* filter) {
  if (Send(new GpuMsg_EstablishChannel(renderer_id))) {
    sent_requests_.push(ChannelRequest(filter));
  } else {
    ReplyToRenderer(IPC::ChannelHandle(), GPUInfo(), filter);
  }
}

void GpuProcessHost::Synchronize(IPC::Message* reply,
                                 ResourceMessageFilter* filter) {
  queued_synchronization_replies_.push(SynchronizationRequest(reply, filter));
  Send(new GpuMsg_Synchronize());
}

GPUInfo GpuProcessHost::gpu_info() const {
  return gpu_info_;
}

void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) {
  IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message)
    IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished)
    IPC_MESSAGE_HANDLER(GpuHostMsg_SynchronizeReply, OnSynchronizeReply)
    IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected,
                        OnGraphicsInfoCollected)
#if defined(OS_LINUX)
    IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_GetViewXID, OnGetViewXID)
#elif defined(OS_MACOSX)
    IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceSetIOSurface,
                        OnAcceleratedSurfaceSetIOSurface)
    IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
                        OnAcceleratedSurfaceBuffersSwapped)
#endif
    IPC_MESSAGE_UNHANDLED_ERROR()
  IPC_END_MESSAGE_MAP()
}

void GpuProcessHost::OnChannelEstablished(
    const IPC::ChannelHandle& channel_handle,
    const GPUInfo& gpu_info) {
  const ChannelRequest& request = sent_requests_.front();
  ReplyToRenderer(channel_handle, gpu_info, request.filter);
  sent_requests_.pop();
  gpu_info_ = gpu_info;
  child_process_logging::SetGpuInfo(gpu_info);
}

void GpuProcessHost::OnSynchronizeReply() {
  const SynchronizationRequest& request =
      queued_synchronization_replies_.front();
  request.filter->Send(request.reply);
  queued_synchronization_replies_.pop();
}

void GpuProcessHost::OnGraphicsInfoCollected(const GPUInfo& gpu_info) {
  gpu_info_ = gpu_info;
}

#if defined(OS_LINUX)

namespace {

void SendDelayedReply(IPC::Message* reply_msg) {
  GpuProcessHost::Get()->Send(reply_msg);
}

void GetViewXIDDispatcher(gfx::NativeViewId id, IPC::Message* reply_msg) {
  unsigned long xid;

  GtkNativeViewManager* manager = Singleton<GtkNativeViewManager>::get();
  if (!manager->GetPermanentXIDForId(&xid, id)) {
    DLOG(ERROR) << "Can't find XID for view id " << id;
    xid = 0;
  }

  GpuHostMsg_GetViewXID::WriteReplyParams(reply_msg, xid);

  // Have to reply from IO thread.
  ChromeThread::PostTask(
      ChromeThread::IO, FROM_HERE,
      NewRunnableFunction(&SendDelayedReply, reply_msg));
}

}

void GpuProcessHost::OnGetViewXID(gfx::NativeViewId id,
                                  IPC::Message *reply_msg) {
  // Have to request a permanent overlay from UI thread.
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      NewRunnableFunction(&GetViewXIDDispatcher, id, reply_msg));
}

#elif defined(OS_MACOSX)

namespace {

class SetIOSurfaceDispatcher : public Task {
 public:
  SetIOSurfaceDispatcher(
      const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params)
      : params_(params) {
  }

  void Run() {
    RenderViewHost* host = RenderViewHost::FromID(params_.renderer_id,
                                                  params_.render_view_id);
    if (!host)
      return;
    RenderWidgetHostView* view = host->view();
    if (!view)
      return;
    view->AcceleratedSurfaceSetIOSurface(params_.window,
                                         params_.width,
                                         params_.height,
                                         params_.identifier);
  }

 private:
  GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params params_;

  DISALLOW_COPY_AND_ASSIGN(SetIOSurfaceDispatcher);
};

}  // namespace

void GpuProcessHost::OnAcceleratedSurfaceSetIOSurface(
    const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params) {
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      new SetIOSurfaceDispatcher(params));
}

namespace {

class BuffersSwappedDispatcher : public Task {
 public:
  BuffersSwappedDispatcher(
      int32 renderer_id, int32 render_view_id, gfx::PluginWindowHandle window)
      : renderer_id_(renderer_id),
        render_view_id_(render_view_id),
        window_(window) {
  }

  void Run() {
    RenderViewHost* host = RenderViewHost::FromID(renderer_id_,
                                                  render_view_id_);
    if (!host)
      return;
    RenderWidgetHostView* view = host->view();
    if (!view)
      return;
    view->AcceleratedSurfaceBuffersSwapped(window_);
  }

 private:
  int32 renderer_id_;
  int32 render_view_id_;
  gfx::PluginWindowHandle window_;

  DISALLOW_COPY_AND_ASSIGN(BuffersSwappedDispatcher);
};

}  // namespace

void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
    int32 renderer_id,
    int32 render_view_id,
    gfx::PluginWindowHandle window) {
  ChromeThread::PostTask(
      ChromeThread::UI, FROM_HERE,
      new BuffersSwappedDispatcher(renderer_id, render_view_id, window));
}
#endif

void GpuProcessHost::ReplyToRenderer(
    const IPC::ChannelHandle& channel,
    const GPUInfo& gpu_info,
    ResourceMessageFilter* filter) {
  ViewMsg_GpuChannelEstablished* message =
      new ViewMsg_GpuChannelEstablished(channel, gpu_info);
  // If the renderer process is performing synchronous initialization,
  // it needs to handle this message before receiving the reply for
  // the synchronous ViewHostMsg_SynchronizeGpu message.
  message->set_unblock(true);
  filter->Send(message);
}

URLRequestContext* GpuProcessHost::GetRequestContext(
    uint32 request_id,
    const ViewHostMsg_Resource_Request& request_data) {
  return NULL;
}

bool GpuProcessHost::CanShutdown() {
  return true;
}
<|endoftext|>


<commit_before>#include <BALL/PLUGIN/pluginManager.h>
#include <BALL/PLUGIN/BALLPlugin.h>
#include <BALL/PLUGIN/pluginHandler.h>

#include <QtCore/QPluginLoader>
#include <QtCore/QDir>
#include <QtCore/QReadLocker>
#include <QtCore/QWriteLocker>
#include <BALL/COMMON/logStream.h>

#if defined(BALL_OS_WINDOWS)
# define PLUGIN_MASK "plugin*.dll"
#elif defined(BALL_OS_DARWIN)
# define PLUGIN_MASK "plugin*.dylib"
#else
# define PLUGIN_MASK "plugin*.so"
#endif

namespace BALL
{
	const char* PluginManager::BETWEEN_PLUGINDIR_SEPERATOR  = "?";
	boost::shared_ptr<PluginManager> PluginManager::manager_;

	QMutex PluginManager::mutex_;

	PluginManager::PluginManager()
	{
	}

	PluginManager::~PluginManager()
	{
		unloadAllPlugins();
	}

	PluginManager& PluginManager::instance()
	{
		//Make the PluginManager creation thread safe
		if (!manager_)
		{
			//Another thread could have taken over control right now
			//so lock a mutex to ensure the PluginManager is created only once.
			mutex_.lock();
			//Check that the manager has not been created by a concurring thread
			if(!manager_)
			{
				manager_ = boost::shared_ptr<PluginManager>(new PluginManager());
			}
			mutex_.unlock();
		}

		return *manager_;
	}

	bool PluginManager::addPluginDirectory(const QString& dir)
	{
		std::map<QString, vector<BALLPlugin*> >::iterator to_load_it = loaded_plugin_dirs_.find(dir);
		if (to_load_it == loaded_plugin_dirs_.end())
		{
			vector<BALLPlugin*> loaded_plugins;
			QDir plugin_dir(dir, PLUGIN_MASK, QDir::Name | QDir::IgnoreCase, QDir::Files);

			if(!plugin_dir.exists())
			{
				return false;
			}

			// collect the loaded plugins in this dir
			foreach(QString it, plugin_dir.entryList())
			{
				BALLPlugin* new_plugin = loadPlugin(plugin_dir.absoluteFilePath(it));
				if (new_plugin)
				{
					loaded_plugins.push_back(new_plugin);
				}
			}

			// and store the entry
			loaded_plugin_dirs_[dir]=loaded_plugins;

			return true;
		}

		return false;
	}

	bool PluginManager::unloadDirectoryPlugins_(PluginDirMap::iterator it)
	{
		if(it == loaded_plugin_dirs_.end()) {
			return false;
		}

		vector<BALLPlugin*>::iterator to_unload = it->second.begin();
		for (; to_unload != it->second.end(); ++to_unload)
		{
			unloadPlugin((*to_unload)->getName());
		}

		// and the directory itself
		loaded_plugin_dirs_.erase(it);

		return true;
	}

	bool PluginManager::removePluginDirectory(const QString& dir)
	{
		std::map<QString, vector<BALLPlugin*> >::iterator to_unload_it = loaded_plugin_dirs_.find(dir);

		return unloadDirectoryPlugins_(to_unload_it);
	}

	vector<QString> PluginManager::getPluginDirectories() const
	{
		vector<QString> result;

		std::map<QString, vector<BALLPlugin*> >::const_iterator it = loaded_plugin_dirs_.begin();
		for (; it!=loaded_plugin_dirs_.end(); ++it)
			result.push_back(it->first);

		return result;
	}

	BALLPlugin* PluginManager::loadPlugin(const QString& plugin_name)
	{
		BALLPlugin* plugin = 0;
		QPluginLoader* loader = new QPluginLoader(plugin_name);

		Log.info() << "Trying to load plugin: " << plugin_name.toStdString() << std::endl;
		if (loader->load())
		{
			plugin = qobject_cast<BALLPlugin*>(loader->instance());
		}
		else
		{
			Log.info() << "Error:" << loader->errorString().toStdString() << std::endl;
		}

		if (plugin)
		{
			QHash<QString, QPluginLoader*>::iterator it = loaders_.find(plugin->getName());

			if(it != loaders_.end()) {
				Log.info() << "Plugin was already loaded." << std::endl;
				delete loader;
				return qobject_cast<BALLPlugin*>(*it);
			}

			Log.info() << "Loaded plugin " << plugin_name.toStdString() << "." << std::endl;
			loader_mutex_.lockForWrite();
			loaders_.insert(plugin->getName(), loader);
			loader_mutex_.unlock();

			if(autoactivate_plugins_.contains(plugin->getName())) {
				startPlugin(plugin);
				plugin->activate();
			}
		}

		return plugin;
	}

	bool PluginManager::unloadPlugin(const QString& plugin)
	{
		QWriteLocker locker(&loader_mutex_);
		QHash<QString, QPluginLoader*>::iterator it = loaders_.find(plugin);

		if (it != loaders_.end())
		{
			//Shutdown the plugin
			stopPlugin(qobject_cast<BALLPlugin*>(it.value()->instance()));

			// NOTE: unloading crashes BALLView, for some reason!
			//       it is not really crucial to unload the plugins, but we should have
			//       a look at this anyhow
			//Delete the loader
//			it.value()->unload();
//			delete it.value();

			loaders_.erase(it);

			return true;
		}

		return false;
	}

	void PluginManager::unloadAllPlugins()
	{
		loader_mutex_.lockForWrite();
		QHash<QString, QPluginLoader*>::iterator it = loaders_.begin();
		for (; it != loaders_.end(); ++it)
		{
			//Shutdown the plugin
			stopPlugin(qobject_cast<BALLPlugin*>(it.value()->instance()));
			//Delete the loader
			it.value()->unload();
			delete it.value();
		}
		loaders_.clear();
		loader_mutex_.unlock();
	}

	QObject* PluginManager::getPluginInstance(const QString& plugin)
	{
		QReadLocker locker(&loader_mutex_);
		QHash<QString, QPluginLoader*>::iterator it = loaders_.find(plugin);

		if(it != loaders_.end())
		{
			return (it.value()->instance());
		}

		return NULL;
	}

	QObject* PluginManager::getPluginInstance(int pos)
	{
		QReadLocker locker(&loader_mutex_);
		if(pos < 0 || pos >= getPluginCount())
		{
			return NULL;
		}

		QHash<QString, QPluginLoader*>::const_iterator it = loaders_.begin();
		for(int i = 0; i < pos; ++i, ++it) {}

		return it.value()->instance();
	}

	void PluginManager::registerHandler(const boost::shared_ptr<PluginHandler>& h)
	{
		handler_mutex_.lockForWrite();
		shared_handlers_.push_back(h);
		handlers_.push_back(h.get());
		handler_mutex_.unlock();
	}

	void PluginManager::registerHandler(PluginHandler* h)
	{
		handler_mutex_.lockForWrite();
		handlers_.push_back(h);
		handler_mutex_.unlock();
	}

	bool PluginManager::unregisterHandler(PluginHandler* h)
	{
		// First remove the handler from the list of PluginHandlers
		handler_mutex_.lockForRead();
		std::list<PluginHandler*>::iterator ht = std::find(handlers_.begin(), handlers_.end(), h);
		handler_mutex_.unlock();

		if(ht == handlers_.end())
		{
			return true;
		}

		handler_mutex_.lockForWrite();
		handlers_.erase(ht);
		handler_mutex_.unlock();

		// Now stop all plugins that are run by this handler
		QWriteLocker locker(&loader_mutex_);

		QHash<QString, QPluginLoader*>::iterator it = loaders_.begin();
		while(it != loaders_.end())
		{
			if (!it.value()->isLoaded())
			{
				++it;
				continue;
			}

			BALLPlugin* plugin = qobject_cast<BALLPlugin*>(it.value()->instance());

			if(!plugin || !h->isRunning(plugin))
			{
				++it;
				continue;
			}

			if(!h->stopPlugin(plugin) || !stopPlugin(plugin))
			{
				return false;
			}

			//Delete the loader
			it.value()->unload();
			delete it.value();

			it = loaders_.erase(it);
		}

		return true;
	}

	bool PluginManager::startPlugin(int plugin)
	{
		return startPlugin(qobject_cast<BALLPlugin*>(getPluginInstance(plugin)));
	}

	bool PluginManager::startPlugin(const QString& plugin)
	{
		return startPlugin(qobject_cast<BALLPlugin*>(getPluginInstance(plugin)));
	}

	bool PluginManager::startPlugin(BALLPlugin* plugin)
	{
		if (!plugin)
		{
			return true;
		}

		bool started = false;
		handler_mutex_.lockForRead();
		std::list<PluginHandler*>::iterator it = handlers_.begin();
		for (; it != handlers_.end(); ++it)
		{
			if ((*it)->canHandle(plugin))
			{
				started = (*it)->startPlugin(plugin) && !started;
			}
		}
		handler_mutex_.unlock();

		return started;
	}

	bool PluginManager::stopPlugin(int plugin)
	{
		return stopPlugin(qobject_cast<BALLPlugin*>(getPluginInstance(plugin)));
	}

	bool PluginManager::stopPlugin(const QString& plugin)
	{
		return stopPlugin(qobject_cast<BALLPlugin*>(getPluginInstance(plugin)));
	}

	bool PluginManager::stopPlugin(BALLPlugin* plugin)
	{
		if (!plugin)
		{
			return true;
		}

		bool all_stopped = true;
		handler_mutex_.lockForRead();
		std::list<PluginHandler*>::iterator it = handlers_.begin();
		for (; it != handlers_.end(); ++it)
		{
			if ((*it)->isRunning(plugin))
			{
				all_stopped = (*it)->stopPlugin(plugin) && all_stopped;
			}
		}
		handler_mutex_.unlock();

		return all_stopped;
	}

	int PluginManager::getPluginCount() const
	{
		QReadLocker locker(&loader_mutex_);
		return loaders_.size();
	}

	bool PluginManager::getPluginDirectories(String& value) const
	{
		if (!loaded_plugin_dirs_.empty())
		{
			std::map<QString, vector<BALLPlugin*> >::const_iterator it = loaded_plugin_dirs_.begin();

			if ( it != loaded_plugin_dirs_.end())
			{

				value += it->first.toLatin1().toPercentEncoding().data();

				for (++it; it != loaded_plugin_dirs_.end(); ++it)
				{
					value += BETWEEN_PLUGINDIR_SEPERATOR;
					value += it->first.toLatin1().toPercentEncoding().data();
				}
			}
		}
		return true;
	}

	bool PluginManager::setPluginDirectories(const String& value)
	{
		std::vector<String> plugin_directories;

		String tmp(QByteArray::fromPercentEncoding(QByteArray(value.c_str())).data());
		tmp.split(plugin_directories, BETWEEN_PLUGINDIR_SEPERATOR, 0);

		for (size_t i = 0; i < plugin_directories.size(); ++i)
		{
			addPluginDirectory(plugin_directories[i].c_str());
		}

		return true;
	}

	QString PluginManager::getAutoActivatePlugins() const
	{
		return autoactivate_plugins_.join(";");
	}

	bool PluginManager::setAutoActivatePlugins(const QString& value)
	{
		autoactivate_plugins_ = value.split(";", QString::SkipEmptyParts);

		return true;
	}

	void PluginManager::autoActivatePlugin(const QString& str)
	{
		if(!autoactivate_plugins_.contains(str)) {
			autoactivate_plugins_.append(str);
		}
	}

	void PluginManager::doNotAutoActivatePlugin(const QString& str)
	{
		autoactivate_plugins_.removeOne(str);
	}
}
<commit_msg>[VIEW] Fix: Incorrect return value in PluginManager::startPlugin In the case of multiple handlers for any given plugin, the return value would have been false most of the time, regardless of the handlers' actual success.<commit_after>#include <BALL/PLUGIN/pluginManager.h>
#include <BALL/PLUGIN/BALLPlugin.h>
#include <BALL/PLUGIN/pluginHandler.h>

#include <QtCore/QPluginLoader>
#include <QtCore/QDir>
#include <QtCore/QReadLocker>
#include <QtCore/QWriteLocker>
#include <BALL/COMMON/logStream.h>

#if defined(BALL_OS_WINDOWS)
# define PLUGIN_MASK "plugin*.dll"
#elif defined(BALL_OS_DARWIN)
# define PLUGIN_MASK "plugin*.dylib"
#else
# define PLUGIN_MASK "plugin*.so"
#endif

namespace BALL
{
	const char* PluginManager::BETWEEN_PLUGINDIR_SEPERATOR  = "?";
	boost::shared_ptr<PluginManager> PluginManager::manager_;

	QMutex PluginManager::mutex_;

	PluginManager::PluginManager()
	{
	}

	PluginManager::~PluginManager()
	{
		unloadAllPlugins();
	}

	PluginManager& PluginManager::instance()
	{
		//Make the PluginManager creation thread safe
		if (!manager_)
		{
			//Another thread could have taken over control right now
			//so lock a mutex to ensure the PluginManager is created only once.
			mutex_.lock();
			//Check that the manager has not been created by a concurring thread
			if(!manager_)
			{
				manager_ = boost::shared_ptr<PluginManager>(new PluginManager());
			}
			mutex_.unlock();
		}

		return *manager_;
	}

	bool PluginManager::addPluginDirectory(const QString& dir)
	{
		std::map<QString, vector<BALLPlugin*> >::iterator to_load_it = loaded_plugin_dirs_.find(dir);
		if (to_load_it == loaded_plugin_dirs_.end())
		{
			vector<BALLPlugin*> loaded_plugins;
			QDir plugin_dir(dir, PLUGIN_MASK, QDir::Name | QDir::IgnoreCase, QDir::Files);

			if(!plugin_dir.exists())
			{
				return false;
			}

			// collect the loaded plugins in this dir
			foreach(QString it, plugin_dir.entryList())
			{
				BALLPlugin* new_plugin = loadPlugin(plugin_dir.absoluteFilePath(it));
				if (new_plugin)
				{
					loaded_plugins.push_back(new_plugin);
				}
			}

			// and store the entry
			loaded_plugin_dirs_[dir]=loaded_plugins;

			return true;
		}

		return false;
	}

	bool PluginManager::unloadDirectoryPlugins_(PluginDirMap::iterator it)
	{
		if(it == loaded_plugin_dirs_.end()) {
			return false;
		}

		vector<BALLPlugin*>::iterator to_unload = it->second.begin();
		for (; to_unload != it->second.end(); ++to_unload)
		{
			unloadPlugin((*to_unload)->getName());
		}

		// and the directory itself
		loaded_plugin_dirs_.erase(it);

		return true;
	}

	bool PluginManager::removePluginDirectory(const QString& dir)
	{
		std::map<QString, vector<BALLPlugin*> >::iterator to_unload_it = loaded_plugin_dirs_.find(dir);

		return unloadDirectoryPlugins_(to_unload_it);
	}

	vector<QString> PluginManager::getPluginDirectories() const
	{
		vector<QString> result;

		std::map<QString, vector<BALLPlugin*> >::const_iterator it = loaded_plugin_dirs_.begin();
		for (; it!=loaded_plugin_dirs_.end(); ++it)
			result.push_back(it->first);

		return result;
	}

	BALLPlugin* PluginManager::loadPlugin(const QString& plugin_name)
	{
		BALLPlugin* plugin = 0;
		QPluginLoader* loader = new QPluginLoader(plugin_name);

		Log.info() << "Trying to load plugin: " << plugin_name.toStdString() << std::endl;
		if (loader->load())
		{
			plugin = qobject_cast<BALLPlugin*>(loader->instance());
		}
		else
		{
			Log.info() << "Error:" << loader->errorString().toStdString() << std::endl;
		}

		if (plugin)
		{
			QHash<QString, QPluginLoader*>::iterator it = loaders_.find(plugin->getName());

			if(it != loaders_.end()) {
				Log.info() << "Plugin was already loaded." << std::endl;
				delete loader;
				return qobject_cast<BALLPlugin*>(*it);
			}

			Log.info() << "Loaded plugin " << plugin_name.toStdString() << "." << std::endl;
			loader_mutex_.lockForWrite();
			loaders_.insert(plugin->getName(), loader);
			loader_mutex_.unlock();

			if(autoactivate_plugins_.contains(plugin->getName())) {
				startPlugin(plugin);
				plugin->activate();
			}
		}

		return plugin;
	}

	bool PluginManager::unloadPlugin(const QString& plugin)
	{
		QWriteLocker locker(&loader_mutex_);
		QHash<QString, QPluginLoader*>::iterator it = loaders_.find(plugin);

		if (it != loaders_.end())
		{
			//Shutdown the plugin
			stopPlugin(qobject_cast<BALLPlugin*>(it.value()->instance()));

			// NOTE: unloading crashes BALLView, for some reason!
			//       it is not really crucial to unload the plugins, but we should have
			//       a look at this anyhow
			//Delete the loader
//			it.value()->unload();
//			delete it.value();

			loaders_.erase(it);

			return true;
		}

		return false;
	}

	void PluginManager::unloadAllPlugins()
	{
		loader_mutex_.lockForWrite();
		QHash<QString, QPluginLoader*>::iterator it = loaders_.begin();
		for (; it != loaders_.end(); ++it)
		{
			//Shutdown the plugin
			stopPlugin(qobject_cast<BALLPlugin*>(it.value()->instance()));
			//Delete the loader
			it.value()->unload();
			delete it.value();
		}
		loaders_.clear();
		loader_mutex_.unlock();
	}

	QObject* PluginManager::getPluginInstance(const QString& plugin)
	{
		QReadLocker locker(&loader_mutex_);
		QHash<QString, QPluginLoader*>::iterator it = loaders_.find(plugin);

		if(it != loaders_.end())
		{
			return (it.value()->instance());
		}

		return NULL;
	}

	QObject* PluginManager::getPluginInstance(int pos)
	{
		QReadLocker locker(&loader_mutex_);
		if(pos < 0 || pos >= getPluginCount())
		{
			return NULL;
		}

		QHash<QString, QPluginLoader*>::const_iterator it = loaders_.begin();
		for(int i = 0; i < pos; ++i, ++it) {}

		return it.value()->instance();
	}

	void PluginManager::registerHandler(const boost::shared_ptr<PluginHandler>& h)
	{
		handler_mutex_.lockForWrite();
		shared_handlers_.push_back(h);
		handlers_.push_back(h.get());
		handler_mutex_.unlock();
	}

	void PluginManager::registerHandler(PluginHandler* h)
	{
		handler_mutex_.lockForWrite();
		handlers_.push_back(h);
		handler_mutex_.unlock();
	}

	bool PluginManager::unregisterHandler(PluginHandler* h)
	{
		// First remove the handler from the list of PluginHandlers
		handler_mutex_.lockForRead();
		std::list<PluginHandler*>::iterator ht = std::find(handlers_.begin(), handlers_.end(), h);
		handler_mutex_.unlock();

		if(ht == handlers_.end())
		{
			return true;
		}

		handler_mutex_.lockForWrite();
		handlers_.erase(ht);
		handler_mutex_.unlock();

		// Now stop all plugins that are run by this handler
		QWriteLocker locker(&loader_mutex_);

		QHash<QString, QPluginLoader*>::iterator it = loaders_.begin();
		while(it != loaders_.end())
		{
			if (!it.value()->isLoaded())
			{
				++it;
				continue;
			}

			BALLPlugin* plugin = qobject_cast<BALLPlugin*>(it.value()->instance());

			if(!plugin || !h->isRunning(plugin))
			{
				++it;
				continue;
			}

			if(!h->stopPlugin(plugin) || !stopPlugin(plugin))
			{
				return false;
			}

			//Delete the loader
			it.value()->unload();
			delete it.value();

			it = loaders_.erase(it);
		}

		return true;
	}

	bool PluginManager::startPlugin(int plugin)
	{
		return startPlugin(qobject_cast<BALLPlugin*>(getPluginInstance(plugin)));
	}

	bool PluginManager::startPlugin(const QString& plugin)
	{
		return startPlugin(qobject_cast<BALLPlugin*>(getPluginInstance(plugin)));
	}

	bool PluginManager::startPlugin(BALLPlugin* plugin)
	{
		if (!plugin)
		{
			return true;
		}

		bool started = false;
		handler_mutex_.lockForRead();
		std::list<PluginHandler*>::iterator it = handlers_.begin();
		for (; it != handlers_.end(); ++it)
		{
			if ((*it)->canHandle(plugin))
			{
				started |= (*it)->startPlugin(plugin);
			}
		}
		handler_mutex_.unlock();

		return started;
	}

	bool PluginManager::stopPlugin(int plugin)
	{
		return stopPlugin(qobject_cast<BALLPlugin*>(getPluginInstance(plugin)));
	}

	bool PluginManager::stopPlugin(const QString& plugin)
	{
		return stopPlugin(qobject_cast<BALLPlugin*>(getPluginInstance(plugin)));
	}

	bool PluginManager::stopPlugin(BALLPlugin* plugin)
	{
		if (!plugin)
		{
			return true;
		}

		bool all_stopped = true;
		handler_mutex_.lockForRead();
		std::list<PluginHandler*>::iterator it = handlers_.begin();
		for (; it != handlers_.end(); ++it)
		{
			if ((*it)->isRunning(plugin))
			{
				all_stopped = (*it)->stopPlugin(plugin) && all_stopped;
			}
		}
		handler_mutex_.unlock();

		return all_stopped;
	}

	int PluginManager::getPluginCount() const
	{
		QReadLocker locker(&loader_mutex_);
		return loaders_.size();
	}

	bool PluginManager::getPluginDirectories(String& value) const
	{
		if (!loaded_plugin_dirs_.empty())
		{
			std::map<QString, vector<BALLPlugin*> >::const_iterator it = loaded_plugin_dirs_.begin();

			if ( it != loaded_plugin_dirs_.end())
			{

				value += it->first.toLatin1().toPercentEncoding().data();

				for (++it; it != loaded_plugin_dirs_.end(); ++it)
				{
					value += BETWEEN_PLUGINDIR_SEPERATOR;
					value += it->first.toLatin1().toPercentEncoding().data();
				}
			}
		}
		return true;
	}

	bool PluginManager::setPluginDirectories(const String& value)
	{
		std::vector<String> plugin_directories;

		String tmp(QByteArray::fromPercentEncoding(QByteArray(value.c_str())).data());
		tmp.split(plugin_directories, BETWEEN_PLUGINDIR_SEPERATOR, 0);

		for (size_t i = 0; i < plugin_directories.size(); ++i)
		{
			addPluginDirectory(plugin_directories[i].c_str());
		}

		return true;
	}

	QString PluginManager::getAutoActivatePlugins() const
	{
		return autoactivate_plugins_.join(";");
	}

	bool PluginManager::setAutoActivatePlugins(const QString& value)
	{
		autoactivate_plugins_ = value.split(";", QString::SkipEmptyParts);

		return true;
	}

	void PluginManager::autoActivatePlugin(const QString& str)
	{
		if(!autoactivate_plugins_.contains(str)) {
			autoactivate_plugins_.append(str);
		}
	}

	void PluginManager::doNotAutoActivatePlugin(const QString& str)
	{
		autoactivate_plugins_.removeOne(str);
	}
}
<|endoftext|>


<commit_before>// $Id: ShiftModel_test.C,v 1.4 2000/09/22 11:21:20 amoll Exp $
#include <BALL/CONCEPT/classTest.h>

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

#include <BALL/NMR/shiftModel.h>

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

START_TEST(ShiftModel, "$Id: ShiftModel_test.C,v 1.4 2000/09/22 11:21:20 amoll Exp $")

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

using namespace BALL;

ShiftModel* sm = 0;
CHECK(ShiftModel::ShiftModel() throw())
  sm = new ShiftModel;
	TEST_NOT_EQUAL(sm, 0)
RESULT

CHECK(ShiftModel::~ShiftModel() throw())
  delete sm;
RESULT

CHECK(ShiftModel::isValid() const  throw())
  ShiftModel sm;
	TEST_EQUAL(sm.isValid(), false)
RESULT

CHECK(ShiftModel::isRegistered(const String& name) const  throw())
  ShiftModel sm;
	TEST_EQUAL(sm.isRegistered("UNNAMED MODULE X"), false)
	TEST_EQUAL(sm.isRegistered(""), false)
	TEST_EQUAL(sm.isRegistered("JohnsonBovey"), true)
	TEST_EQUAL(sm.isRegistered("HaighMallion"), true)
	TEST_EQUAL(sm.isRegistered("JohnsonBovey"), true)
	TEST_EQUAL(sm.isRegistered("Anisotropy"), true)
	TEST_EQUAL(sm.isRegistered("RandomCoil"), true)
	TEST_EQUAL(sm.isRegistered("ElectricField"), true)
RESULT

CHECK(ShiftModel::getParameters() throw())
  ShiftModel sm;
	TEST_NOT_EQUAL(&sm.getParameters(), 0)
	TEST_EQUAL(sm.getParameters().isValid(), false)
RESULT

CHECK(ShiftModel::setFilename(const String& filename) throw(Exception::FileNotFound))
	ShiftModel sm;
	TEST_EXCEPTION(Exception::FileNotFound, sm.setFilename("XXXXXX"))
	TEST_EQUAL(sm.isValid(), false)
	TEST_EQUAL(sm.getParameters().isValid(), false)
	sm.setFilename("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.isValid(), true)
	TEST_EQUAL(sm.getParameters().isValid(), true)
RESULT

CHECK(ShiftModel::getFilename() const  throw())
	ShiftModel sm;
	TEST_EXCEPTION(Exception::FileNotFound, sm.setFilename("XXXXXX"))
	TEST_EQUAL(sm.isValid(), false)
	TEST_EQUAL(sm.getFilename(), "XXXXXX")
	sm.setFilename("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.isValid(), true)
	TEST_EQUAL(sm.getFilename(), "data/ShiftModel_test.ini")
RESULT

CHECK(ShiftModel::getModuleList() throw())
	ShiftModel sm;
	TEST_EQUAL(sm.getModuleList().size(), 0)

	sm.setFilename("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.getModuleList().size(), 2)
RESULT

CHECK(ShiftModel::registerModule(const String& name, CreateMethod method) throw(Exception::NullPointer))
	ShiftModel sm;
	using namespace RTTI;
	ShiftModel::CreateMethod m = getNew<ShiftModule>;
	TEST_EQUAL(sm.isRegistered("TEST"), false)
	sm.registerModule("TEST", m);
	TEST_EQUAL(sm.isRegistered("TEST"), true)
	TEST_EQUAL(sm.isRegistered("TEST2"), false)
	TEST_EXCEPTION(Exception::NullPointer, sm.registerModule("TEST2", 0))
	TEST_EQUAL(sm.isRegistered("TEST2"), false)
RESULT

CHECK(ShiftModel::unregisterModule(const String& name) throw())
	ShiftModel sm;
	using namespace RTTI;
	ShiftModel::CreateMethod m = getNew<ShiftModule>;
	TEST_EQUAL(sm.isRegistered("TEST"), false)
	sm.registerModule("TEST", m);
	TEST_EQUAL(sm.isRegistered("TEST"), true)
	sm.unregisterModule("TEST");
	TEST_EQUAL(sm.isRegistered("TEST"), false)
	sm.unregisterModule("TEST");
	TEST_EQUAL(sm.isRegistered("TEST"), false)
RESULT

CHECK(ShiftModel::ShiftModel(const String& filename) throw())
  ShiftModel sm("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.isValid(), true)
	ShiftModel::ModuleList mod_list = sm.getModuleList();
	TEST_EQUAL(mod_list.size(), 2)
	if (mod_list.size() > 0)
	{
		TEST_EQUAL((*mod_list.begin())->getName(), "JB_ring_current")
	}
RESULT

CHECK(ShiftModel::clear() throw())
  ShiftModel sm("data/ShiftModel_test.ini");
	sm.clear();
	TEST_EQUAL(sm.isValid(), false)
	TEST_EQUAL(sm.getFilename(), "")
	TEST_EQUAL(sm.getModuleList().size(), 0)
RESULT

const ShiftModel smx("data/ShiftModel_test.ini");

CHECK(ShiftModel::ShiftModel(const ShiftModel& model) throw())
	ShiftModel sm(smx);
	TEST_EQUAL(sm.isValid(), true)
	ShiftModel::ModuleList mod_list = sm.getModuleList();
	TEST_EQUAL(mod_list.size(), 2)
	if (mod_list.size() > 0)
	{
		TEST_EQUAL((*mod_list.begin())->getName(), "JB_ring_current")
	}
RESULT

CHECK(ShiftModel::ShiftModel& operator = (const ShiftModel& model) throw())
	ShiftModel sm = smx;
	TEST_EQUAL(sm.isValid(), true)
	ShiftModel::ModuleList mod_list = sm.getModuleList();
	TEST_EQUAL(mod_list.size(), 2)
	if (mod_list.size() > 0)
	{
		TEST_EQUAL((*mod_list.begin())->getName(), "JB_ring_current")
	}
RESULT

CHECK(ShiftModel::ShiftModel& operator = (const String& filename) throw())
	ShiftModel sm = String("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.isValid(), true)
	ShiftModel::ModuleList mod_list = sm.getModuleList();
	TEST_EQUAL(mod_list.size(), 2)
	if (mod_list.size() > 0)
	{
		TEST_EQUAL((*mod_list.begin())->getName(), "JB_ring_current")
	}
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>cosmetic changes<commit_after>// $Id: ShiftModel_test.C,v 1.5 2000/09/22 12:17:08 amoll Exp $
#include <BALL/CONCEPT/classTest.h>

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

#include <BALL/NMR/shiftModel.h>

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

START_TEST(ShiftModel, "$Id: ShiftModel_test.C,v 1.5 2000/09/22 12:17:08 amoll Exp $")

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

using namespace BALL;

ShiftModel* sm = 0;
CHECK(ShiftModel::ShiftModel() throw())
  sm = new ShiftModel;
	TEST_NOT_EQUAL(sm, 0)
RESULT

CHECK(ShiftModel::~ShiftModel() throw())
  delete sm;
RESULT

CHECK(ShiftModel::isValid() const  throw())
  ShiftModel sm;
	TEST_EQUAL(sm.isValid(), false)
RESULT

CHECK(ShiftModel::isRegistered(const String& name) const  throw())
  ShiftModel sm;
	TEST_EQUAL(sm.isRegistered("UNNAMED MODULE X"), false)
	TEST_EQUAL(sm.isRegistered(""), false)
	TEST_EQUAL(sm.isRegistered("JohnsonBovey"), true)
	TEST_EQUAL(sm.isRegistered("HaighMallion"), true)
	TEST_EQUAL(sm.isRegistered("JohnsonBovey"), true)
	TEST_EQUAL(sm.isRegistered("Anisotropy"), true)
	TEST_EQUAL(sm.isRegistered("RandomCoil"), true)
	TEST_EQUAL(sm.isRegistered("ElectricField"), true)
RESULT

CHECK(ShiftModel::getParameters() throw())
  ShiftModel sm;
	TEST_NOT_EQUAL(&sm.getParameters(), 0)
	TEST_EQUAL(sm.getParameters().isValid(), false)
RESULT

CHECK(ShiftModel::setFilename(const String& filename) throw(Exception::FileNotFound))
	ShiftModel sm;
	TEST_EXCEPTION(Exception::FileNotFound, sm.setFilename("XXXXXX"))
	TEST_EQUAL(sm.isValid(), false)
	TEST_EQUAL(sm.getParameters().isValid(), false)
	sm.setFilename("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.isValid(), true)
	TEST_EQUAL(sm.getParameters().isValid(), true)
RESULT

CHECK(ShiftModel::getFilename() const  throw())
	ShiftModel sm;
	TEST_EXCEPTION(Exception::FileNotFound, sm.setFilename("XXXXXX"))
	TEST_EQUAL(sm.isValid(), false)
	TEST_EQUAL(sm.getFilename(), "XXXXXX")
	sm.setFilename("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.isValid(), true)
	TEST_EQUAL(sm.getFilename(), "data/ShiftModel_test.ini")
RESULT

CHECK(ShiftModel::getModuleList() throw())
	ShiftModel sm;
	TEST_EQUAL(sm.getModuleList().size(), 0)

	sm.setFilename("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.getModuleList().size(), 2)
RESULT

CHECK(ShiftModel::registerModule(const String& name, CreateMethod method) throw(Exception::NullPointer))
	ShiftModel sm;
	using namespace RTTI;
	ShiftModel::CreateMethod m = getNew<ShiftModule>;
	TEST_EQUAL(sm.isRegistered("TEST"), false)
	sm.registerModule("TEST", m);
	TEST_EQUAL(sm.isRegistered("TEST"), true)
	TEST_EQUAL(sm.isRegistered("TEST2"), false)
	TEST_EXCEPTION(Exception::NullPointer, sm.registerModule("TEST2", 0))
	TEST_EQUAL(sm.isRegistered("TEST2"), false)
RESULT

CHECK(ShiftModel::unregisterModule(const String& name) throw())
	ShiftModel sm;
	using namespace RTTI;
	ShiftModel::CreateMethod m = getNew<ShiftModule>;
	TEST_EQUAL(sm.isRegistered("TEST"), false)
	sm.registerModule("TEST", m);
	TEST_EQUAL(sm.isRegistered("TEST"), true)
	sm.unregisterModule("TEST");
	TEST_EQUAL(sm.isRegistered("TEST"), false)
	sm.unregisterModule("TEST");
	TEST_EQUAL(sm.isRegistered("TEST"), false)
RESULT

CHECK(ShiftModel::ShiftModel(const String& filename) throw())
  ShiftModel sm("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.isValid(), true)
	ShiftModel::ModuleList mod_list = sm.getModuleList();
	TEST_EQUAL(mod_list.size(), 2)
	if (mod_list.size() > 0)
	{
		TEST_EQUAL((*mod_list.begin())->getName(), "JB_ring_current")
	}
RESULT

CHECK(ShiftModel::clear() throw())
  ShiftModel sm("data/ShiftModel_test.ini");
	sm.clear();
	TEST_EQUAL(sm.isValid(), false)
	TEST_EQUAL(sm.getFilename(), "")
	TEST_EQUAL(sm.getModuleList().size(), 0)
RESULT

const ShiftModel smx("data/ShiftModel_test.ini");

CHECK(ShiftModel::ShiftModel(const ShiftModel& model) throw())
	ShiftModel sm(smx);
	TEST_EQUAL(sm.isValid(), true)
	ShiftModel::ModuleList mod_list = sm.getModuleList();
	TEST_EQUAL(mod_list.size(), 2)
	if (mod_list.size() > 0)
	{
		TEST_EQUAL((*mod_list.begin())->getName(), "JB_ring_current")
	}
RESULT

CHECK(ShiftModel::ShiftModel& operator = (const ShiftModel& model) throw())
	ShiftModel sm = smx;
	TEST_EQUAL(sm.isValid(), true)
	ShiftModel::ModuleList mod_list = sm.getModuleList();
	TEST_EQUAL(mod_list.size(), 2)
	if (mod_list.size() > 0)
	{
		TEST_EQUAL((*mod_list.begin())->getName(), "JB_ring_current")
	}
RESULT

CHECK(ShiftModel::ShiftModel& operator = (const String& filename) throw())
	ShiftModel sm = String("data/ShiftModel_test.ini");
	TEST_EQUAL(sm.isValid(), true)
	ShiftModel::ModuleList mod_list = sm.getModuleList();
	TEST_EQUAL(mod_list.size(), 2)
	if (mod_list.size() > 0)
	{
		TEST_EQUAL((*mod_list.begin())->getName(), "JB_ring_current")
	}
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>


<commit_before>//===--------------------- LLDBAssert.cpp ------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Utility/LLDBAssert.h"

#include "llvm/Support/Format.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
using namespace lldb_private;

void lldb_private::lldb_assert(bool expression, const char *expr_text,
                               const char *func, const char *file,
                               unsigned int line) {
  if (LLVM_LIKELY(expression))
    return;

  errs() << format("Assertion failed: (%s), function %s, file %s, line %u\n",
                   expr_text, func, file, line);
  errs() << "backtrace leading to the failure:\n";
  llvm::sys::PrintStackTrace(errs());
  errs() << "please file a bug report against lldb reporting this failure "
            "log, and as many details as possible\n";
}
<commit_msg>lldb_assert: abort when assertions are enabled.<commit_after>//===--------------------- LLDBAssert.cpp ------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Utility/LLDBAssert.h"

#include "llvm/Support/Format.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;
using namespace lldb_private;

void lldb_private::lldb_assert(bool expression, const char *expr_text,
                               const char *func, const char *file,
                               unsigned int line) {
  if (LLVM_LIKELY(expression))
    return;

  // In a Debug configuration lldb_assert() behaves like assert().
  assert(false && "lldb_assert failed");

  // In a Release configuration it will print a warning and encourage the user
  // to file a bug report, similar to LLVM’s crash handler, and then return
  // execution.
  errs() << format("Assertion failed: (%s), function %s, file %s, line %u\n",
                   expr_text, func, file, line);
  errs() << "backtrace leading to the failure:\n";
  llvm::sys::PrintStackTrace(errs());
  errs() << "please file a bug report against lldb reporting this failure "
            "log, and as many details as possible\n";
}
<|endoftext|>


<commit_before>// Copyright 2014 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 <stdint.h>
#include <windows.h>

#include <algorithm>
#include <vector>

#include "base/base_paths.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/win/pe_image.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

class ELFImportsTest : public testing::Test {
 protected:
  static bool ImportsCallback(const base::win::PEImage &image,
                              LPCSTR module,
                              PIMAGE_THUNK_DATA name_table,
                              PIMAGE_THUNK_DATA iat,
                              PVOID cookie) {
    std::vector<std::string>* import_list =
        reinterpret_cast<std::vector<std::string>*>(cookie);
    import_list->push_back(module);
    return true;
  }

  void GetImports(const base::FilePath& module_path,
                  std::vector<std::string>* imports) {
    ASSERT_TRUE(imports != NULL);

    base::MemoryMappedFile module_mmap;

    ASSERT_TRUE(module_mmap.Initialize(module_path));
    base::win::PEImageAsData pe_image_data(
        reinterpret_cast<HMODULE>(const_cast<uint8*>(module_mmap.data())));
    pe_image_data.EnumImportChunks(ELFImportsTest::ImportsCallback, imports);
  }
};

TEST_F(ELFImportsTest, ChromeElfSanityCheck) {
  std::vector<std::string> elf_imports;

  base::FilePath dll;
  ASSERT_TRUE(PathService::Get(base::DIR_EXE, &dll));
  dll = dll.Append(L"chrome_elf.dll");
  GetImports(dll, &elf_imports);

  // Check that ELF has imports.
  ASSERT_LT(0u, elf_imports.size());

  std::vector<std::string>::iterator it(elf_imports.begin());

  static const char* const kValidFilePatterns[] = {
      "KERNEL32.dll",
      "MSVC*",
#if defined(ADDRESS_SANITIZER)
      "syzyasan_rtl.dll",
#endif
      "ADVAPI32.dll"};

  // Make sure all of ELF's imports are in the valid imports list.
  for (; it != elf_imports.end(); it++) {
    bool match = false;
    for (int i = 0; i < arraysize(kValidFilePatterns); ++i) {
      if (MatchPattern(*it, kValidFilePatterns[i]))
        match = true;
    }
    ASSERT_TRUE(match) << "Illegal import in chrome_elf.dll.";
  }
}

#if defined(ARCH_CPU_64_BITS)
#define MAYBE_ChromeExeSanityCheck DISABLED_ChromeExeSanityCheck
#else
#define MAYBE_ChromeExeSanityCheck ChromeExeSanityCheck
#endif
// Fails on 64-bit Windows, see http://crbug.com/335173.
TEST_F(ELFImportsTest, MAYBE_ChromeExeSanityCheck) {
  std::vector<std::string> exe_imports;

  base::FilePath exe;
  ASSERT_TRUE(PathService::Get(base::DIR_EXE, &exe));
  exe = exe.Append(L"chrome.exe");
  GetImports(exe, &exe_imports);

  // Check that chrome.exe has imports.
  ASSERT_LT(0u, exe_imports.size());

  // Chrome.exe's first import must be ELF.
  EXPECT_EQ("chrome_elf.dll", exe_imports[0]) <<
      "Illegal import order in chrome.exe";
}

}  // namespace
<commit_msg>Add logs to chrome_elf_unittests to ensure the correct target is built.<commit_after>// Copyright 2014 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 <stdint.h>
#include <windows.h>

#include <algorithm>
#include <vector>

#include "base/base_paths.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/win/pe_image.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

class ELFImportsTest : public testing::Test {
 protected:
  static bool ImportsCallback(const base::win::PEImage &image,
                              LPCSTR module,
                              PIMAGE_THUNK_DATA name_table,
                              PIMAGE_THUNK_DATA iat,
                              PVOID cookie) {
    std::vector<std::string>* import_list =
        reinterpret_cast<std::vector<std::string>*>(cookie);
    import_list->push_back(module);
    return true;
  }

  void GetImports(const base::FilePath& module_path,
                  std::vector<std::string>* imports) {
    ASSERT_TRUE(imports != NULL);

    base::MemoryMappedFile module_mmap;

    ASSERT_TRUE(module_mmap.Initialize(module_path));
    base::win::PEImageAsData pe_image_data(
        reinterpret_cast<HMODULE>(const_cast<uint8*>(module_mmap.data())));
    pe_image_data.EnumImportChunks(ELFImportsTest::ImportsCallback, imports);
  }
};

TEST_F(ELFImportsTest, ChromeElfSanityCheck) {
  std::vector<std::string> elf_imports;

  base::FilePath dll;
  ASSERT_TRUE(PathService::Get(base::DIR_EXE, &dll));
  dll = dll.Append(L"chrome_elf.dll");
  GetImports(dll, &elf_imports);

  // Check that ELF has imports.
  ASSERT_LT(0u, elf_imports.size()) << "Ensure the chrome_elf_unittests "
    "target was built, instead of chrome_elf_unittests.exe";

  std::vector<std::string>::iterator it(elf_imports.begin());

  static const char* const kValidFilePatterns[] = {
      "KERNEL32.dll",
      "MSVC*",
#if defined(ADDRESS_SANITIZER)
      "syzyasan_rtl.dll",
#endif
      "ADVAPI32.dll"};

  // Make sure all of ELF's imports are in the valid imports list.
  for (; it != elf_imports.end(); it++) {
    bool match = false;
    for (int i = 0; i < arraysize(kValidFilePatterns); ++i) {
      if (MatchPattern(*it, kValidFilePatterns[i]))
        match = true;
    }
    ASSERT_TRUE(match) << "Illegal import in chrome_elf.dll.";
  }
}

#if defined(ARCH_CPU_64_BITS)
#define MAYBE_ChromeExeSanityCheck DISABLED_ChromeExeSanityCheck
#else
#define MAYBE_ChromeExeSanityCheck ChromeExeSanityCheck
#endif
// Fails on 64-bit Windows, see http://crbug.com/335173.
TEST_F(ELFImportsTest, MAYBE_ChromeExeSanityCheck) {
  std::vector<std::string> exe_imports;

  base::FilePath exe;
  ASSERT_TRUE(PathService::Get(base::DIR_EXE, &exe));
  exe = exe.Append(L"chrome.exe");
  GetImports(exe, &exe_imports);

  // Check that chrome.exe has imports.
  ASSERT_LT(0u, exe_imports.size()) << "Ensure the chrome_elf_unittests "
    "target was built, instead of chrome_elf_unittests.exe";

  // Chrome.exe's first import must be ELF.
  EXPECT_EQ("chrome_elf.dll", exe_imports[0]) <<
      "Illegal import order in chrome.exe (ensure the chrome_elf_unittest "
      "target was built, instead of just chrome_elf_unittests.exe)";
}

}  // namespace
<|endoftext|>


<commit_before>#include "raptor_api.h"
#include "type/pb_converter.h"
#include "boost/date_time/posix_time/posix_time.hpp"
namespace navitia { namespace routing { namespace raptor {

std::string iso_string(const nt::Data & d, int date, int hour){
    boost::posix_time::ptime date_time(d.meta.production_date.begin() + boost::gregorian::days(date));
    date_time += boost::posix_time::seconds(hour);
    return boost::posix_time::to_iso_string(date_time);
}

pbnavitia::Response make_pathes(const std::vector<navitia::routing::Path> &paths, const nt::Data & d) {
    pbnavitia::Response pb_response;
    pb_response.set_requested_api(pbnavitia::PLANNER);

    for(Path path : paths) {
        pbnavitia::Journey * pb_journey = pb_response.mutable_planner()->add_journey();
        pb_journey->set_duration(path.duration);
        pb_journey->set_nb_transfers(path.nb_changes);
        for(PathItem & item : path.items){
            pbnavitia::Section * pb_section = pb_journey->add_section();
            pb_section->set_arrival_date_time(iso_string(d, item.arrival.date(), item.arrival.hour()));
            pb_section->set_departure_date_time(iso_string(d, item.departure.date(), item.departure.hour()));
            if(item.type == public_transport)
                pb_section->set_type(pbnavitia::PUBLIC_TRANSPORT);
            else
                pb_section->set_type(pbnavitia::TRANSFER);
            if(item.type == public_transport && item.vj_idx != type::invalid_idx){
                const type::VehicleJourney & vj = d.pt_data.vehicle_journeys[item.vj_idx];
                const type::Route & route = d.pt_data.routes[vj.route_idx];
                const type::Line & line = d.pt_data.lines[route.line_idx];
                fill_pb_object(line.idx, d, pb_section->mutable_line());
            }
            for(navitia::type::idx_t stop_point : item.stop_points){
                fill_pb_object(stop_point, d, pb_section->add_stop_point());
            }
            if(item.stop_points.size() >= 2) {
                pbnavitia::PlaceMark * origin_place_mark = pb_section->mutable_origin();
                origin_place_mark->set_type(pbnavitia::STOPAREA);
                fill_pb_object(d.pt_data.stop_points[item.stop_points.front()].stop_area_idx, d, origin_place_mark->mutable_stop_area());
                pbnavitia::PlaceMark * destination_place_mark = pb_section->mutable_destination();
                destination_place_mark->set_type(pbnavitia::STOPAREA);
                fill_pb_object(d.pt_data.stop_points[item.stop_points.back()].stop_area_idx, d, destination_place_mark->mutable_stop_area());
            }

        }
    }

    return pb_response;
}

std::vector<std::pair<type::idx_t, double> > get_stop_points(const type::EntryPoint &ep, const type::Data & data, streetnetwork::StreetNetworkWorker & worker){
    std::vector<std::pair<type::idx_t, double> > result;

    switch(ep.type) {
    case navitia::type::Type_e::eStopArea:
    {
        auto it = data.pt_data.stop_area_map.find(ep.external_code);
        if(it!= data.pt_data.stop_area_map.end()) {
            for(auto spidx : data.pt_data.stop_areas[it->second].stop_point_list) {
                result.push_back(std::make_pair(spidx, 0));
            }
        }
    } break;
    case type::Type_e::eStopPoint: {
        auto it = data.pt_data.stop_point_map.find(ep.external_code);
        if(it != data.pt_data.stop_point_map.end()){
            result.push_back(std::make_pair(data.pt_data.stop_points[it->second].idx, 0));
        }
    } break;
    case type::Type_e::eCoord: {
        result = worker.find_nearest(ep.coordinates, data.pt_data.stop_point_proximity_list, 300);
    } break;
    default: break;
    }
    return result;
}

vector_idxretour to_idxretour(std::vector<std::pair<type::idx_t, double> > elements, int hour, int day){
    vector_idxretour result;
    for(auto item : elements) {
        int temps = hour + (item.second / 80);
        int jour;
        if(temps > 86400) {
            temps = temps % 86400;
            jour = day + 1;
        } else {
            jour = day;
        }
        result.push_back(std::make_pair(item.first, type_retour(navitia::type::invalid_idx, DateTime(jour, temps), 0, (item.second / 80))));
    }
    return result;
}

pbnavitia::Response make_response(RAPTOR &raptor, const type::EntryPoint &origin, const type::EntryPoint &destination, const boost::posix_time::ptime &datetime, bool clockwise, streetnetwork::StreetNetworkWorker & worker) {
    pbnavitia::Response response;

    if(!raptor.data.meta.production_date.contains(datetime.date())) {
        response.set_error("Date not in the production period");
        return response;
    }

    auto departures = get_stop_points(origin, raptor.data, worker);
    if(departures.size() == 0){
        response.set_error("Departure point not found");
        return response;
    }

    auto destinations = get_stop_points(destination, raptor.data, worker);
    if(destinations.size() == 0){
        response.set_error("Destination point not found");
        return response;
    }

    std::vector<Path> result;

    int day = (datetime.date() - raptor.data.meta.production_date.begin()).days();
    int time = datetime.time_of_day().total_seconds();

    if(clockwise)
        result = raptor.compute_all(to_idxretour(departures, time, day), to_idxretour(destinations, time, day));
    else
        result = raptor.compute_reverse_all(to_idxretour(departures, time, day), to_idxretour(destinations, time, day));

    return make_pathes(result, raptor.data);
}

pbnavitia::Response make_response(RAPTOR &raptor, const type::EntryPoint &origin, const type::EntryPoint &destination, const std::vector<std::string> &datetimes_str, bool clockwise, streetnetwork::StreetNetworkWorker & worker) {
    pbnavitia::Response response;

    std::vector<boost::posix_time::ptime> datetimes;
    for(std::string datetime: datetimes_str){
        try {
            boost::posix_time::ptime ptime;
            ptime = boost::posix_time::from_iso_string(datetime);
            if(!raptor.data.meta.production_date.contains(ptime.date())) {
                response.set_error("Date not in the production period");
                return response;
            }
            datetimes.push_back(ptime);
        } catch(...){
            response.set_error("Impossible to parse date " + datetime);
            return response;
        }
    }

    auto departures = get_stop_points(origin, raptor.data, worker);
    if(departures.size() == 0){
        response.set_error("Departure point not found");
        return response;
    }

    auto destinations = get_stop_points(destination, raptor.data, worker);
    if(destinations.size() == 0){
        response.set_error("Destination point not found");
        return response;
    }

    std::vector<Path> result;
    for(boost::posix_time::ptime datetime : datetimes){
        std::vector<Path> tmp;
        int day = (datetime.date() - raptor.data.meta.production_date.begin()).days();
        int time = datetime.time_of_day().total_seconds();

        if(clockwise)
            tmp = raptor.compute_all(to_idxretour(departures, time, day), to_idxretour(destinations, time, day));
        else
            tmp = raptor.compute_reverse_all(to_idxretour(departures, time, day), to_idxretour(destinations, time, day));
        if(tmp.size() > 0)
            result.push_back(tmp.front());
        else
            result.push_back(Path());
    }
    return make_pathes(result, raptor.data);
}

}}}
<commit_msg>RaptorAPI : meilleur retour des messages d'erreur<commit_after>#include "raptor_api.h"
#include "type/pb_converter.h"
#include "boost/date_time/posix_time/posix_time.hpp"
namespace navitia { namespace routing { namespace raptor {

std::string iso_string(const nt::Data & d, int date, int hour){
    boost::posix_time::ptime date_time(d.meta.production_date.begin() + boost::gregorian::days(date));
    date_time += boost::posix_time::seconds(hour);
    return boost::posix_time::to_iso_string(date_time);
}

pbnavitia::Response make_pathes(const std::vector<navitia::routing::Path> &paths, const nt::Data & d) {
    pbnavitia::Response pb_response;
    pb_response.set_requested_api(pbnavitia::PLANNER);

    pbnavitia::Planner * planner = pb_response.mutable_planner();
    planner->set_response_type(pbnavitia::ITINERARY_FOUND);
    for(Path path : paths) {
        pbnavitia::Journey * pb_journey = planner->add_journey();
        pb_journey->set_duration(path.duration);
        pb_journey->set_nb_transfers(path.nb_changes);
        for(PathItem & item : path.items){
            pbnavitia::Section * pb_section = pb_journey->add_section();
            pb_section->set_arrival_date_time(iso_string(d, item.arrival.date(), item.arrival.hour()));
            pb_section->set_departure_date_time(iso_string(d, item.departure.date(), item.departure.hour()));
            if(item.type == public_transport)
                pb_section->set_type(pbnavitia::PUBLIC_TRANSPORT);
            else
                pb_section->set_type(pbnavitia::TRANSFER);
            if(item.type == public_transport && item.vj_idx != type::invalid_idx){
                const type::VehicleJourney & vj = d.pt_data.vehicle_journeys[item.vj_idx];
                const type::Route & route = d.pt_data.routes[vj.route_idx];
                const type::Line & line = d.pt_data.lines[route.line_idx];
                fill_pb_object(line.idx, d, pb_section->mutable_line());
            }
            for(navitia::type::idx_t stop_point : item.stop_points){
                fill_pb_object(stop_point, d, pb_section->add_stop_point());
            }
            if(item.stop_points.size() >= 2) {
                pbnavitia::PlaceMark * origin_place_mark = pb_section->mutable_origin();
                origin_place_mark->set_type(pbnavitia::STOPAREA);
                fill_pb_object(d.pt_data.stop_points[item.stop_points.front()].stop_area_idx, d, origin_place_mark->mutable_stop_area());
                pbnavitia::PlaceMark * destination_place_mark = pb_section->mutable_destination();
                destination_place_mark->set_type(pbnavitia::STOPAREA);
                fill_pb_object(d.pt_data.stop_points[item.stop_points.back()].stop_area_idx, d, destination_place_mark->mutable_stop_area());
            }

        }
    }

    return pb_response;
}

std::vector<std::pair<type::idx_t, double> > get_stop_points(const type::EntryPoint &ep, const type::Data & data, streetnetwork::StreetNetworkWorker & worker){
    std::vector<std::pair<type::idx_t, double> > result;

    switch(ep.type) {
    case navitia::type::Type_e::eStopArea:
    {
        auto it = data.pt_data.stop_area_map.find(ep.external_code);
        if(it!= data.pt_data.stop_area_map.end()) {
            for(auto spidx : data.pt_data.stop_areas[it->second].stop_point_list) {
                result.push_back(std::make_pair(spidx, 0));
            }
        }
    } break;
    case type::Type_e::eStopPoint: {
        auto it = data.pt_data.stop_point_map.find(ep.external_code);
        if(it != data.pt_data.stop_point_map.end()){
            result.push_back(std::make_pair(data.pt_data.stop_points[it->second].idx, 0));
        }
    } break;
    case type::Type_e::eCoord: {
        result = worker.find_nearest(ep.coordinates, data.pt_data.stop_point_proximity_list, 300);
    } break;
    default: break;
    }
    return result;
}

vector_idxretour to_idxretour(std::vector<std::pair<type::idx_t, double> > elements, int hour, int day){
    vector_idxretour result;
    for(auto item : elements) {
        int temps = hour + (item.second / 80);
        int jour;
        if(temps > 86400) {
            temps = temps % 86400;
            jour = day + 1;
        } else {
            jour = day;
        }
        result.push_back(std::make_pair(item.first, type_retour(navitia::type::invalid_idx, DateTime(jour, temps), 0, (item.second / 80))));
    }
    return result;
}

pbnavitia::Response make_response(RAPTOR &raptor, const type::EntryPoint &origin, const type::EntryPoint &destination, const boost::posix_time::ptime &datetime, bool clockwise, streetnetwork::StreetNetworkWorker & worker) {
    pbnavitia::Response response;
    response.set_requested_api(pbnavitia::PLANNER);

    if(!raptor.data.meta.production_date.contains(datetime.date())) {
        response.mutable_planner()->set_response_type(pbnavitia::DATE_OUT_OF_BOUNDS);
        return response;
    }

    auto departures = get_stop_points(origin, raptor.data, worker);
    auto destinations = get_stop_points(destination, raptor.data, worker);
    if(departures.size() == 0 && destinations.size() == 0){
        response.mutable_planner()->set_response_type(pbnavitia::NO_DEPARTURE_NOR_DESTINATION_POINT);
        return response;
    }

    if(departures.size() == 0){
        response.mutable_planner()->set_response_type(pbnavitia::NO_DEPARTURE_NOR_DESTINATION_POINT);
        return response;
    }

    if(destinations.size() == 0){
        response.mutable_planner()->set_response_type(pbnavitia::NO_DEPARTURE_POINT);
        return response;
    }

    std::vector<Path> result;

    int day = (datetime.date() - raptor.data.meta.production_date.begin()).days();
    int time = datetime.time_of_day().total_seconds();

    if(clockwise)
        result = raptor.compute_all(to_idxretour(departures, time, day), to_idxretour(destinations, time, day));
    else
        result = raptor.compute_reverse_all(to_idxretour(departures, time, day), to_idxretour(destinations, time, day));

    if(result.size() == 0){
        response.mutable_planner()->set_response_type(pbnavitia::NO_SOLUTION);
        return response;
    }

    return make_pathes(result, raptor.data);
}

pbnavitia::Response make_response(RAPTOR &raptor, const type::EntryPoint &origin, const type::EntryPoint &destination, const std::vector<std::string> &datetimes_str, bool clockwise, streetnetwork::StreetNetworkWorker & worker) {
    pbnavitia::Response response;
    response.set_requested_api(pbnavitia::PLANNER);

    std::vector<boost::posix_time::ptime> datetimes;
    for(std::string datetime: datetimes_str){
        try {
            boost::posix_time::ptime ptime;
            ptime = boost::posix_time::from_iso_string(datetime);
            if(!raptor.data.meta.production_date.contains(ptime.date())) {
                response.mutable_planner()->set_response_type(pbnavitia::DATE_OUT_OF_BOUNDS);
                response.set_info("Example of invalid date: " + datetime);
                return response;
            }
            datetimes.push_back(ptime);
        } catch(...){
            response.set_error("Impossible to parse date " + datetime);
            return response;
        }
    }

    auto departures = get_stop_points(origin, raptor.data, worker);
    auto destinations = get_stop_points(destination, raptor.data, worker);
    if(departures.size() == 0 && destinations.size() == 0){
        response.mutable_planner()->set_response_type(pbnavitia::NO_DEPARTURE_NOR_DESTINATION_POINT);
        return response;
    }

    if(departures.size() == 0){
        response.mutable_planner()->set_response_type(pbnavitia::NO_DEPARTURE_NOR_DESTINATION_POINT);
        return response;
    }

    if(destinations.size() == 0){
        response.mutable_planner()->set_response_type(pbnavitia::NO_DEPARTURE_POINT);
        return response;
    }

    std::vector<Path> result;
    for(boost::posix_time::ptime datetime : datetimes){
        std::vector<Path> tmp;
        int day = (datetime.date() - raptor.data.meta.production_date.begin()).days();
        int time = datetime.time_of_day().total_seconds();

        if(clockwise)
            tmp = raptor.compute_all(to_idxretour(departures, time, day), to_idxretour(destinations, time, day));
        else
            tmp = raptor.compute_reverse_all(to_idxretour(departures, time, day), to_idxretour(destinations, time, day));
        if(tmp.size() > 0)
            result.push_back(tmp.front());
        else
            result.push_back(Path());
    }
    return make_pathes(result, raptor.data);
}

}}}
<|endoftext|>