<commit_before>/*
The MIT License (MIT)

Copyright (c) 2013-2019 Winlin

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 <srs_utest_protostack.hpp>

#include <srs_utest_protocol.hpp>

#include <srs_kernel_error.hpp>
#include <srs_core_autofree.hpp>
#include <srs_protocol_utility.hpp>
#include <srs_rtmp_msg_array.hpp>
#include <srs_rtmp_stack.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_app_st.hpp>
#include <srs_protocol_amf0.hpp>
#include <srs_rtmp_stack.hpp>
#include <srs_service_http_conn.hpp>
#include <srs_kernel_buffer.hpp>

using namespace std;

class MockPacket : public SrsPacket
{
public:
    int size;
public:
    MockPacket() {
        size = 0;
    }
    virtual ~MockPacket() {
    }
protected:
    virtual int get_size() {
        return size;
    }
};

class MockPacket2 : public MockPacket
{
public:
    char* payload;
public:
    MockPacket2() {
        payload = NULL;
    }
    virtual ~MockPacket2() {
        srs_freep(payload);
    }
    virtual srs_error_t encode(int& size, char*& payload) {
        size = this->size;
        payload = this->payload;
        this->payload = NULL;
        return srs_success;
    }
};

VOID TEST(ProtoStackTest, PacketEncode)
{
    srs_error_t err;

    int size;
    char* payload;

    if (true) {
        MockPacket pkt;
        pkt.size = 1024;

        HELPER_EXPECT_FAILED(pkt.encode(size, payload));
    }

    if (true) {
        MockPacket pkt;
        pkt.size = 1024;

        SrsBuffer b;
        HELPER_EXPECT_FAILED(pkt.decode(&b));
    }

    if (true) {
        SrsPacket pkt;
        EXPECT_EQ(0, pkt.get_prefer_cid());
        EXPECT_EQ(0, pkt.get_message_type());
        EXPECT_EQ(0, pkt.get_size());
    }

    if (true) {
        MockPacket pkt;
        pkt.size = 1024;

        EXPECT_EQ(1024, pkt.get_size());
    }
}

VOID TEST(ProtoStackTest, ManualFlush)
{
    srs_error_t err;

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        // Default is auto response.
        HELPER_EXPECT_SUCCESS(p.response_acknowledgement_message());
        EXPECT_EQ(12+4, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        p.set_auto_response(true);
        HELPER_EXPECT_SUCCESS(p.response_acknowledgement_message());
        EXPECT_EQ(12+4, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        // When not auto response, need to flush it manually.
        p.set_auto_response(false);
        HELPER_EXPECT_SUCCESS(p.response_acknowledgement_message());
        EXPECT_EQ(0, io.out_buffer.length());

        HELPER_EXPECT_SUCCESS(p.manual_response_flush());
        EXPECT_EQ(12+4, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        HELPER_EXPECT_SUCCESS(p.response_ping_message(1024));
        EXPECT_EQ(12+6, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        // When not auto response, need to flush it manually.
        p.set_auto_response(false);
        HELPER_EXPECT_SUCCESS(p.response_ping_message(1024));
        EXPECT_EQ(0, io.out_buffer.length());

        HELPER_EXPECT_SUCCESS(p.manual_response_flush());
        EXPECT_EQ(12+6, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        // When not auto response, need to flush it manually.
        p.set_auto_response(false);
        HELPER_EXPECT_SUCCESS(p.response_ping_message(1024));
        EXPECT_EQ(0, io.out_buffer.length());

        // If not flushed, the packets will be destroyed.
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        p.set_recv_buffer(0);
        p.set_recv_buffer(131072 * 10);

        p.set_merge_read(true, NULL);
        p.set_merge_read(false, NULL);
    }
}

VOID TEST(ProtoStackTest, SendPacketsError)
{
    srs_error_t err;

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        MockPacket* pkt = new MockPacket();
        pkt->size = 1024;
        HELPER_EXPECT_FAILED(p.send_and_free_packet(pkt, 1));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        SrsPacket* pkt = new SrsPacket();
        HELPER_EXPECT_SUCCESS(p.send_and_free_packet(pkt, 1));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        MockPacket2* pkt = new MockPacket2();
        pkt->size = 1024;
        HELPER_EXPECT_SUCCESS(p.send_and_free_packet(pkt, 1));
    }
}

VOID TEST(ProtoStackTest, SendHugePacket)
{
    srs_error_t err;

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        MockPacket2* pkt = new MockPacket2();
        pkt->size = 1024;
        pkt->payload = new char[1024];
        HELPER_EXPECT_SUCCESS(p.send_and_free_packet(pkt, 1));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        MockPacket2* pkt = new MockPacket2();
        pkt->size = 16;
        pkt->payload = new char[16];

        io.out_err = srs_error_new(1, "fail");
        HELPER_EXPECT_FAILED(p.send_and_free_packet(pkt, 1));
    }
}

VOID TEST(ProtoStackTest, SendZeroMessages)
{
    srs_error_t err;
    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);
        HELPER_EXPECT_SUCCESS(p.send_and_free_message(NULL, 0));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);
        SrsSharedPtrMessage* msg = new SrsSharedPtrMessage();
        HELPER_EXPECT_SUCCESS(p.send_and_free_message(msg, 1));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);
        SrsSharedPtrMessage* msgs[1024];
        for (int i = 0; i < 1024; i++) {
            msgs[i] = new SrsSharedPtrMessage();
        }
        HELPER_EXPECT_SUCCESS(p.send_and_free_messages(msgs, 1024, 0));
    }
}

VOID TEST(ProtoStackTest, HugeMessages)
{
    srs_error_t err;
    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        SrsCommonMessage pkt;
        pkt.header.initialize_audio(200, 1000, 1);
        pkt.create_payload(256);
        pkt.size = 256;

        SrsSharedPtrMessage* msg = new SrsSharedPtrMessage();
        msg->create(&pkt);

        HELPER_EXPECT_SUCCESS(p.send_and_free_message(msg, 1));
        EXPECT_EQ(269, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        SrsCommonMessage pkt;
        pkt.header.initialize_audio(200, 1000, 1);
        pkt.create_payload(256);
        pkt.size = 256;

        SrsSharedPtrMessage* msg = new SrsSharedPtrMessage();
        msg->create(&pkt);
        SrsAutoFree(SrsSharedPtrMessage, msg);

        SrsSharedPtrMessage* msgs[1024];
        for (int i = 0; i < 1024; i++) {
            msgs[i] = msg->copy();
        }

        HELPER_EXPECT_SUCCESS(p.send_and_free_messages(msgs, 1024, 1));
        EXPECT_EQ(269*1024, io.out_buffer.length());
    }
}

VOID TEST(ProtoStackTest, DecodeMessages)
{
    srs_error_t err;

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // AMF0 message with 1B should fail.
        SrsCommonMessage msg;
        msg.header.initialize_amf0_script(1, 1);
        msg.create_payload(1);
        msg.size = 1;

        SrsPacket* pkt;
        HELPER_EXPECT_FAILED(p.decode_message(&msg, &pkt));
    }
}

<commit_msg>Cover protocol stack RTMP. 3.0.63<commit_after>/*
The MIT License (MIT)

Copyright (c) 2013-2019 Winlin

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 <srs_utest_protostack.hpp>

#include <srs_utest_protocol.hpp>

#include <srs_kernel_error.hpp>
#include <srs_core_autofree.hpp>
#include <srs_protocol_utility.hpp>
#include <srs_rtmp_msg_array.hpp>
#include <srs_rtmp_stack.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_app_st.hpp>
#include <srs_protocol_amf0.hpp>
#include <srs_rtmp_stack.hpp>
#include <srs_service_http_conn.hpp>
#include <srs_kernel_buffer.hpp>

using namespace std;

class MockPacket : public SrsPacket
{
public:
    int size;
public:
    MockPacket() {
        size = 0;
    }
    virtual ~MockPacket() {
    }
protected:
    virtual int get_size() {
        return size;
    }
};

class MockPacket2 : public MockPacket
{
public:
    char* payload;
public:
    MockPacket2() {
        payload = NULL;
    }
    virtual ~MockPacket2() {
        srs_freep(payload);
    }
    virtual srs_error_t encode(int& size, char*& payload) {
        size = this->size;
        payload = this->payload;
        this->payload = NULL;
        return srs_success;
    }
};

VOID TEST(ProtoStackTest, PacketEncode)
{
    srs_error_t err;

    int size;
    char* payload;

    if (true) {
        MockPacket pkt;
        pkt.size = 1024;

        HELPER_EXPECT_FAILED(pkt.encode(size, payload));
    }

    if (true) {
        MockPacket pkt;
        pkt.size = 1024;

        SrsBuffer b;
        HELPER_EXPECT_FAILED(pkt.decode(&b));
    }

    if (true) {
        SrsPacket pkt;
        EXPECT_EQ(0, pkt.get_prefer_cid());
        EXPECT_EQ(0, pkt.get_message_type());
        EXPECT_EQ(0, pkt.get_size());
    }

    if (true) {
        MockPacket pkt;
        pkt.size = 1024;

        EXPECT_EQ(1024, pkt.get_size());
    }
}

VOID TEST(ProtoStackTest, ManualFlush)
{
    srs_error_t err;

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        // Default is auto response.
        HELPER_EXPECT_SUCCESS(p.response_acknowledgement_message());
        EXPECT_EQ(12+4, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        p.set_auto_response(true);
        HELPER_EXPECT_SUCCESS(p.response_acknowledgement_message());
        EXPECT_EQ(12+4, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        // When not auto response, need to flush it manually.
        p.set_auto_response(false);
        HELPER_EXPECT_SUCCESS(p.response_acknowledgement_message());
        EXPECT_EQ(0, io.out_buffer.length());

        HELPER_EXPECT_SUCCESS(p.manual_response_flush());
        EXPECT_EQ(12+4, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        HELPER_EXPECT_SUCCESS(p.response_ping_message(1024));
        EXPECT_EQ(12+6, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        // When not auto response, need to flush it manually.
        p.set_auto_response(false);
        HELPER_EXPECT_SUCCESS(p.response_ping_message(1024));
        EXPECT_EQ(0, io.out_buffer.length());

        HELPER_EXPECT_SUCCESS(p.manual_response_flush());
        EXPECT_EQ(12+6, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // Always response ACK message.
        HELPER_EXPECT_SUCCESS(p.set_in_window_ack_size(1));

        // When not auto response, need to flush it manually.
        p.set_auto_response(false);
        HELPER_EXPECT_SUCCESS(p.response_ping_message(1024));
        EXPECT_EQ(0, io.out_buffer.length());

        // If not flushed, the packets will be destroyed.
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        p.set_recv_buffer(0);
        p.set_recv_buffer(131072 * 10);

        p.set_merge_read(true, NULL);
        p.set_merge_read(false, NULL);
    }
}

VOID TEST(ProtoStackTest, SendPacketsError)
{
    srs_error_t err;

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        MockPacket* pkt = new MockPacket();
        pkt->size = 1024;
        HELPER_EXPECT_FAILED(p.send_and_free_packet(pkt, 1));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        SrsPacket* pkt = new SrsPacket();
        HELPER_EXPECT_SUCCESS(p.send_and_free_packet(pkt, 1));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        MockPacket2* pkt = new MockPacket2();
        pkt->size = 1024;
        HELPER_EXPECT_SUCCESS(p.send_and_free_packet(pkt, 1));
    }
}

VOID TEST(ProtoStackTest, SendHugePacket)
{
    srs_error_t err;

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        MockPacket2* pkt = new MockPacket2();
        pkt->size = 1024;
        pkt->payload = new char[1024];
        HELPER_EXPECT_SUCCESS(p.send_and_free_packet(pkt, 1));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        MockPacket2* pkt = new MockPacket2();
        pkt->size = 16;
        pkt->payload = new char[16];

        io.out_err = srs_error_new(1, "fail");
        HELPER_EXPECT_FAILED(p.send_and_free_packet(pkt, 1));
    }
}

VOID TEST(ProtoStackTest, SendZeroMessages)
{
    srs_error_t err;
    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);
        HELPER_EXPECT_SUCCESS(p.send_and_free_message(NULL, 0));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);
        SrsSharedPtrMessage* msg = new SrsSharedPtrMessage();
        HELPER_EXPECT_SUCCESS(p.send_and_free_message(msg, 1));
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);
        SrsSharedPtrMessage* msgs[1024];
        for (int i = 0; i < 1024; i++) {
            msgs[i] = new SrsSharedPtrMessage();
        }
        HELPER_EXPECT_SUCCESS(p.send_and_free_messages(msgs, 1024, 0));
    }
}

VOID TEST(ProtoStackTest, HugeMessages)
{
    srs_error_t err;
    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        SrsCommonMessage pkt;
        pkt.header.initialize_audio(200, 1000, 1);
        pkt.create_payload(256);
        pkt.size = 256;

        SrsSharedPtrMessage* msg = new SrsSharedPtrMessage();
        msg->create(&pkt);

        HELPER_EXPECT_SUCCESS(p.send_and_free_message(msg, 1));
        EXPECT_EQ(269, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        SrsCommonMessage pkt;
        pkt.header.initialize_audio(200, 1000, 1);
        pkt.create_payload(256);
        pkt.size = 256;

        SrsSharedPtrMessage* msg = new SrsSharedPtrMessage();
        msg->create(&pkt);
        SrsAutoFree(SrsSharedPtrMessage, msg);

        SrsSharedPtrMessage* msgs[1024];
        for (int i = 0; i < 1024; i++) {
            msgs[i] = msg->copy();
        }

        HELPER_EXPECT_SUCCESS(p.send_and_free_messages(msgs, 1024, 1));
        EXPECT_EQ(269*1024, io.out_buffer.length());
    }

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        SrsCommonMessage pkt;
        pkt.header.initialize_audio(200, 1000, 1);
        pkt.create_payload(256);
        pkt.size = 256;

        SrsSharedPtrMessage* msg = new SrsSharedPtrMessage();
        msg->create(&pkt);
        SrsAutoFree(SrsSharedPtrMessage, msg);

        SrsSharedPtrMessage* msgs[10240];
        for (int i = 0; i < 10240; i++) {
            msgs[i] = msg->copy();
        }

        HELPER_EXPECT_SUCCESS(p.send_and_free_messages(msgs, 10240, 1));
        EXPECT_EQ(269*10240, io.out_buffer.length());
    }
}

VOID TEST(ProtoStackTest, DecodeMessages)
{
    srs_error_t err;

    if (true) {
        MockBufferIO io;
        SrsProtocol p(&io);

        // AMF0 message with 1B should fail.
        SrsCommonMessage msg;
        msg.header.initialize_amf0_script(1, 1);
        msg.create_payload(1);
        msg.size = 1;

        SrsPacket* pkt;
        HELPER_EXPECT_FAILED(p.decode_message(&msg, &pkt));
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2013 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 "ui/keyboard/keyboard_controller_proxy.h"

#include "base/command_line.h"
#include "base/values.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/bindings_policy.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/keyboard/keyboard_constants.h"
#include "ui/keyboard/keyboard_switches.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/wm/core/shadow.h"

namespace {

// The WebContentsDelegate for the keyboard.
// The delegate deletes itself when the keyboard is destroyed.
class KeyboardContentsDelegate : public content::WebContentsDelegate,
                                 public content::WebContentsObserver {
 public:
  KeyboardContentsDelegate(keyboard::KeyboardControllerProxy* proxy)
      : proxy_(proxy) {}
  virtual ~KeyboardContentsDelegate() {}

 private:
  // Overridden from content::WebContentsDelegate:
  virtual content::WebContents* OpenURLFromTab(
      content::WebContents* source,
      const content::OpenURLParams& params) OVERRIDE {
    source->GetController().LoadURL(
        params.url, params.referrer, params.transition, params.extra_headers);
    Observe(source);
    return source;
  }

  virtual bool IsPopupOrPanel(
      const content::WebContents* source) const OVERRIDE {
    return true;
  }

  virtual void MoveContents(content::WebContents* source,
                            const gfx::Rect& pos) OVERRIDE {
    aura::Window* keyboard = proxy_->GetKeyboardWindow();
    // keyboard window must have been added to keyboard container window at this
    // point. Otherwise, wrong keyboard bounds is used and may cause problem as
    // described in crbug.com/367788.
    DCHECK(keyboard->parent());
    gfx::Rect bounds = keyboard->bounds();
    int new_height = pos.height();
    bounds.set_y(bounds.y() + bounds.height() - new_height);
    bounds.set_height(new_height);
    keyboard->SetBounds(bounds);
  }

  // Overridden from content::WebContentsDelegate:
  virtual void RequestMediaAccessPermission(content::WebContents* web_contents,
      const content::MediaStreamRequest& request,
      const content::MediaResponseCallback& callback) OVERRIDE {
    proxy_->RequestAudioInput(web_contents, request, callback);
  }

  // Overridden from content::WebContentsObserver:
  virtual void WebContentsDestroyed() OVERRIDE {
    delete this;
  }

  keyboard::KeyboardControllerProxy* proxy_;

  DISALLOW_COPY_AND_ASSIGN(KeyboardContentsDelegate);
};

}  // namespace

namespace keyboard {

KeyboardControllerProxy::KeyboardControllerProxy()
    : default_url_(kKeyboardURL) {
}

KeyboardControllerProxy::~KeyboardControllerProxy() {
}

const GURL& KeyboardControllerProxy::GetVirtualKeyboardUrl() {
  if (keyboard::IsInputViewEnabled()) {
    const GURL& override_url = GetOverrideContentUrl();
    return override_url.is_valid() ? override_url : default_url_;
  } else {
    return default_url_;
  }
}

void KeyboardControllerProxy::LoadContents(const GURL& url) {
  if (keyboard_contents_) {
    content::OpenURLParams params(
        url,
        content::Referrer(),
        SINGLETON_TAB,
        content::PAGE_TRANSITION_AUTO_TOPLEVEL,
        false);
    keyboard_contents_->OpenURL(params);
  }
}

aura::Window* KeyboardControllerProxy::GetKeyboardWindow() {
  if (!keyboard_contents_) {
    content::BrowserContext* context = GetBrowserContext();
    keyboard_contents_.reset(content::WebContents::Create(
        content::WebContents::CreateParams(context,
            content::SiteInstance::CreateForURL(context,
                                                GetVirtualKeyboardUrl()))));
    keyboard_contents_->SetDelegate(new KeyboardContentsDelegate(this));
    SetupWebContents(keyboard_contents_.get());
    LoadContents(GetVirtualKeyboardUrl());
    keyboard_contents_->GetNativeView()->AddObserver(this);
  }

  return keyboard_contents_->GetNativeView();
}

bool KeyboardControllerProxy::HasKeyboardWindow() const {
  return keyboard_contents_;
}

void KeyboardControllerProxy::ShowKeyboardContainer(aura::Window* container) {
  GetKeyboardWindow()->Show();
  container->Show();
}

void KeyboardControllerProxy::HideKeyboardContainer(aura::Window* container) {
  container->Hide();
  GetKeyboardWindow()->Hide();
}

void KeyboardControllerProxy::SetUpdateInputType(ui::TextInputType type) {
}

void KeyboardControllerProxy::EnsureCaretInWorkArea() {
  if (GetInputMethod()->GetTextInputClient()) {
    aura::Window* keyboard_window = GetKeyboardWindow();
    aura::Window* root_window = keyboard_window->GetRootWindow();
    gfx::Rect available_bounds = root_window->bounds();
    gfx::Rect keyboard_bounds = keyboard_window->bounds();
    available_bounds.set_height(available_bounds.height() -
        keyboard_bounds.height());
    GetInputMethod()->GetTextInputClient()->EnsureCaretInRect(available_bounds);
  }
}

void KeyboardControllerProxy::LoadSystemKeyboard() {
  DCHECK(keyboard_contents_);
  if (keyboard_contents_->GetURL() != default_url_) {
    // TODO(bshe): The height of system virtual keyboard and IME virtual
    // keyboard may different. The height needs to be restored too.
    LoadContents(default_url_);
  }
}

void KeyboardControllerProxy::ReloadKeyboardIfNeeded() {
  DCHECK(keyboard_contents_);
  if (keyboard_contents_->GetURL() != GetVirtualKeyboardUrl()) {
    LoadContents(GetVirtualKeyboardUrl());
  }
}

void KeyboardControllerProxy::SetupWebContents(content::WebContents* contents) {
}

void KeyboardControllerProxy::OnWindowBoundsChanged(
    aura::Window* window,
    const gfx::Rect& old_bounds,
    const gfx::Rect& new_bounds) {
  if (!shadow_) {
    shadow_.reset(new wm::Shadow());
    shadow_->Init(wm::Shadow::STYLE_ACTIVE);
    shadow_->layer()->SetVisible(true);
    DCHECK(keyboard_contents_->GetNativeView()->parent());
    keyboard_contents_->GetNativeView()->parent()->layer()->Add(
        shadow_->layer());
  }

  shadow_->SetContentBounds(new_bounds);
}

void KeyboardControllerProxy::OnWindowDestroyed(aura::Window* window) {
  window->RemoveObserver(this);
}

}  // namespace keyboard
<commit_msg>Set keyboard height to 0 before show a keyboard in a different extension<commit_after>// Copyright (c) 2013 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 "ui/keyboard/keyboard_controller_proxy.h"

#include "base/command_line.h"
#include "base/values.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/bindings_policy.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/keyboard/keyboard_constants.h"
#include "ui/keyboard/keyboard_switches.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/wm/core/shadow.h"

namespace {

// The WebContentsDelegate for the keyboard.
// The delegate deletes itself when the keyboard is destroyed.
class KeyboardContentsDelegate : public content::WebContentsDelegate,
                                 public content::WebContentsObserver {
 public:
  KeyboardContentsDelegate(keyboard::KeyboardControllerProxy* proxy)
      : proxy_(proxy) {}
  virtual ~KeyboardContentsDelegate() {}

 private:
  // Overridden from content::WebContentsDelegate:
  virtual content::WebContents* OpenURLFromTab(
      content::WebContents* source,
      const content::OpenURLParams& params) OVERRIDE {
    source->GetController().LoadURL(
        params.url, params.referrer, params.transition, params.extra_headers);
    Observe(source);
    return source;
  }

  virtual bool IsPopupOrPanel(
      const content::WebContents* source) const OVERRIDE {
    return true;
  }

  virtual void MoveContents(content::WebContents* source,
                            const gfx::Rect& pos) OVERRIDE {
    aura::Window* keyboard = proxy_->GetKeyboardWindow();
    // keyboard window must have been added to keyboard container window at this
    // point. Otherwise, wrong keyboard bounds is used and may cause problem as
    // described in crbug.com/367788.
    DCHECK(keyboard->parent());
    gfx::Rect bounds = keyboard->bounds();
    int new_height = pos.height();
    bounds.set_y(bounds.y() + bounds.height() - new_height);
    bounds.set_height(new_height);
    keyboard->SetBounds(bounds);
  }

  // Overridden from content::WebContentsDelegate:
  virtual void RequestMediaAccessPermission(content::WebContents* web_contents,
      const content::MediaStreamRequest& request,
      const content::MediaResponseCallback& callback) OVERRIDE {
    proxy_->RequestAudioInput(web_contents, request, callback);
  }

  // Overridden from content::WebContentsObserver:
  virtual void WebContentsDestroyed() OVERRIDE {
    delete this;
  }

  keyboard::KeyboardControllerProxy* proxy_;

  DISALLOW_COPY_AND_ASSIGN(KeyboardContentsDelegate);
};

}  // namespace

namespace keyboard {

KeyboardControllerProxy::KeyboardControllerProxy()
    : default_url_(kKeyboardURL) {
}

KeyboardControllerProxy::~KeyboardControllerProxy() {
}

const GURL& KeyboardControllerProxy::GetVirtualKeyboardUrl() {
  if (keyboard::IsInputViewEnabled()) {
    const GURL& override_url = GetOverrideContentUrl();
    return override_url.is_valid() ? override_url : default_url_;
  } else {
    return default_url_;
  }
}

void KeyboardControllerProxy::LoadContents(const GURL& url) {
  if (keyboard_contents_) {
    content::OpenURLParams params(
        url,
        content::Referrer(),
        SINGLETON_TAB,
        content::PAGE_TRANSITION_AUTO_TOPLEVEL,
        false);
    keyboard_contents_->OpenURL(params);
  }
}

aura::Window* KeyboardControllerProxy::GetKeyboardWindow() {
  if (!keyboard_contents_) {
    content::BrowserContext* context = GetBrowserContext();
    keyboard_contents_.reset(content::WebContents::Create(
        content::WebContents::CreateParams(context,
            content::SiteInstance::CreateForURL(context,
                                                GetVirtualKeyboardUrl()))));
    keyboard_contents_->SetDelegate(new KeyboardContentsDelegate(this));
    SetupWebContents(keyboard_contents_.get());
    LoadContents(GetVirtualKeyboardUrl());
    keyboard_contents_->GetNativeView()->AddObserver(this);
  }

  return keyboard_contents_->GetNativeView();
}

bool KeyboardControllerProxy::HasKeyboardWindow() const {
  return keyboard_contents_;
}

void KeyboardControllerProxy::ShowKeyboardContainer(aura::Window* container) {
  GetKeyboardWindow()->Show();
  container->Show();
}

void KeyboardControllerProxy::HideKeyboardContainer(aura::Window* container) {
  container->Hide();
  GetKeyboardWindow()->Hide();
}

void KeyboardControllerProxy::SetUpdateInputType(ui::TextInputType type) {
}

void KeyboardControllerProxy::EnsureCaretInWorkArea() {
  if (GetInputMethod()->GetTextInputClient()) {
    aura::Window* keyboard_window = GetKeyboardWindow();
    aura::Window* root_window = keyboard_window->GetRootWindow();
    gfx::Rect available_bounds = root_window->bounds();
    gfx::Rect keyboard_bounds = keyboard_window->bounds();
    available_bounds.set_height(available_bounds.height() -
        keyboard_bounds.height());
    GetInputMethod()->GetTextInputClient()->EnsureCaretInRect(available_bounds);
  }
}

void KeyboardControllerProxy::LoadSystemKeyboard() {
  DCHECK(keyboard_contents_);
  if (keyboard_contents_->GetURL() != default_url_) {
    // TODO(bshe): The height of system virtual keyboard and IME virtual
    // keyboard may different. The height needs to be restored too.
    LoadContents(default_url_);
  }
}

void KeyboardControllerProxy::ReloadKeyboardIfNeeded() {
  DCHECK(keyboard_contents_);
  if (keyboard_contents_->GetURL() != GetVirtualKeyboardUrl()) {
    if (keyboard_contents_->GetURL().GetOrigin() !=
        GetVirtualKeyboardUrl().GetOrigin()) {
      // Sets keyboard window height to 0 before navigate to a keyboard in a
      // different extension. This keeps the UX the same as Android.
      gfx::Rect bounds = GetKeyboardWindow()->bounds();
      bounds.set_y(bounds.y() + bounds.height());
      bounds.set_height(0);
      GetKeyboardWindow()->SetBounds(bounds);
    }
    LoadContents(GetVirtualKeyboardUrl());
  }
}

void KeyboardControllerProxy::SetupWebContents(content::WebContents* contents) {
}

void KeyboardControllerProxy::OnWindowBoundsChanged(
    aura::Window* window,
    const gfx::Rect& old_bounds,
    const gfx::Rect& new_bounds) {
  if (!shadow_) {
    shadow_.reset(new wm::Shadow());
    shadow_->Init(wm::Shadow::STYLE_ACTIVE);
    shadow_->layer()->SetVisible(true);
    DCHECK(keyboard_contents_->GetNativeView()->parent());
    keyboard_contents_->GetNativeView()->parent()->layer()->Add(
        shadow_->layer());
  }

  shadow_->SetContentBounds(new_bounds);
}

void KeyboardControllerProxy::OnWindowDestroyed(aura::Window* window) {
  window->RemoveObserver(this);
}

}  // namespace keyboard
<|endoftext|>


<commit_before>#include <silicium/fast_variant.hpp>
#include <boost/container/string.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/test/unit_test.hpp>

namespace Si
{
#ifdef _MSC_VER
	//boost::container::string is broken in Boost 1.55 with Visual C++ 2013.
	//std::string is not nothrow_default_constructible, but that does not matter because VC++ 2013 cannot detect that anyway.
	typedef std::string noexcept_string;
#else
	typedef boost::container::string noexcept_string;
#endif

	BOOST_AUTO_TEST_CASE(fast_variant_single)
	{
		fast_variant<int> v;
		BOOST_CHECK_EQUAL(0, v.which());
		BOOST_CHECK_EQUAL(boost::make_optional(0), try_get<int>(v));
	}

	BOOST_AUTO_TEST_CASE(fast_variant_assignment_same)
	{
		typedef fast_variant<int, noexcept_string> variant;
		variant v(1), w(2);
		BOOST_CHECK_EQUAL(boost::make_optional(1), try_get<int>(v));
		BOOST_CHECK_EQUAL(boost::make_optional(2), try_get<int>(w));
		v = w;
		BOOST_CHECK_EQUAL(boost::make_optional(2), try_get<int>(v));
		BOOST_CHECK_EQUAL(boost::make_optional(2), try_get<int>(w));
	}

	BOOST_AUTO_TEST_CASE(fast_variant_assignment_different)
	{
		fast_variant<int, noexcept_string> v, w(noexcept_string("S"));
		BOOST_CHECK_EQUAL(boost::make_optional(0), try_get<int>(v));
		BOOST_CHECK_EQUAL(boost::make_optional(noexcept_string("S")), try_get<noexcept_string>(w));
		v = w;
		BOOST_CHECK_EQUAL(boost::make_optional(noexcept_string("S")), try_get<noexcept_string>(v));
		BOOST_CHECK_EQUAL(boost::make_optional(noexcept_string("S")), try_get<noexcept_string>(w));
	}

	struct is_int_visitor : boost::static_visitor<bool>
	{
		bool operator()(int) const
		{
			return true;
		}

		bool operator()(noexcept_string const &) const
		{
			return false;
		}
	};

	BOOST_AUTO_TEST_CASE(fast_variant_apply_visitor)
	{
		{
			fast_variant<int, noexcept_string> int_;
			is_int_visitor v;
			bool is_int = apply_visitor(v, int_);
			BOOST_CHECK(is_int);
		}

		{
			fast_variant<int, noexcept_string> str(noexcept_string{});
			is_int_visitor v;
			bool is_int = apply_visitor(v, str);
			BOOST_CHECK(!is_int);
		}
	}

	BOOST_AUTO_TEST_CASE(fast_variant_nesting)
	{
		fast_variant<fast_variant<int>, noexcept_string> f;
		f = noexcept_string("S");
		BOOST_CHECK_EQUAL(boost::make_optional(noexcept_string("S")), try_get<noexcept_string>(f));

		f = fast_variant<int>(2);
		BOOST_CHECK_EQUAL(boost::make_optional(fast_variant<int>(2)), try_get<fast_variant<int>>(f));
	}

	BOOST_AUTO_TEST_CASE(fast_variant_construct_const)
	{
		noexcept_string const s("S");
		fast_variant<fast_variant<int>, noexcept_string> f{s};
	}

	BOOST_AUTO_TEST_CASE(fast_variant_assign_const)
	{
		fast_variant<fast_variant<int>, noexcept_string> f;
		noexcept_string const s("S");
		f = s;
	}

	BOOST_AUTO_TEST_CASE(fast_variant_less)
	{
		fast_variant<int, noexcept_string> f(1), g(2), h(noexcept_string("a")), i(noexcept_string("b"));
		BOOST_CHECK_LT(f, g);
		BOOST_CHECK_LT(f, h);
		BOOST_CHECK_LT(f, i);
		BOOST_CHECK_LT(h, i);
	}
}
<commit_msg>begin to write tests for the new fast_variant<commit_after>#include <silicium/fast_variant.hpp>
#include <reactive/config.hpp>
#include <boost/container/string.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/type_traits/aligned_storage.hpp>

namespace Si
{
#ifdef _MSC_VER
	//boost::container::string is broken in Boost 1.55 with Visual C++ 2013.
	//std::string is not nothrow_default_constructible, but that does not matter because VC++ 2013 cannot detect that anyway.
	typedef std::string noexcept_string;
#else
	typedef boost::container::string noexcept_string;
#endif

	BOOST_AUTO_TEST_CASE(fast_variant_single)
	{
		fast_variant<int> v;
		BOOST_CHECK_EQUAL(0, v.which());
		BOOST_CHECK_EQUAL(boost::make_optional(0), try_get<int>(v));
	}

	BOOST_AUTO_TEST_CASE(fast_variant_assignment_same)
	{
		typedef fast_variant<int, noexcept_string> variant;
		variant v(1), w(2);
		BOOST_CHECK_EQUAL(boost::make_optional(1), try_get<int>(v));
		BOOST_CHECK_EQUAL(boost::make_optional(2), try_get<int>(w));
		v = w;
		BOOST_CHECK_EQUAL(boost::make_optional(2), try_get<int>(v));
		BOOST_CHECK_EQUAL(boost::make_optional(2), try_get<int>(w));
	}

	BOOST_AUTO_TEST_CASE(fast_variant_assignment_different)
	{
		fast_variant<int, noexcept_string> v, w(noexcept_string("S"));
		BOOST_CHECK_EQUAL(boost::make_optional(0), try_get<int>(v));
		BOOST_CHECK_EQUAL(boost::make_optional(noexcept_string("S")), try_get<noexcept_string>(w));
		v = w;
		BOOST_CHECK_EQUAL(boost::make_optional(noexcept_string("S")), try_get<noexcept_string>(v));
		BOOST_CHECK_EQUAL(boost::make_optional(noexcept_string("S")), try_get<noexcept_string>(w));
	}

	struct is_int_visitor : boost::static_visitor<bool>
	{
		bool operator()(int) const
		{
			return true;
		}

		bool operator()(noexcept_string const &) const
		{
			return false;
		}
	};

	BOOST_AUTO_TEST_CASE(fast_variant_apply_visitor)
	{
		{
			fast_variant<int, noexcept_string> int_;
			is_int_visitor v;
			bool is_int = apply_visitor(v, int_);
			BOOST_CHECK(is_int);
		}

		{
			fast_variant<int, noexcept_string> str(noexcept_string{});
			is_int_visitor v;
			bool is_int = apply_visitor(v, str);
			BOOST_CHECK(!is_int);
		}
	}

	BOOST_AUTO_TEST_CASE(fast_variant_nesting)
	{
		fast_variant<fast_variant<int>, noexcept_string> f;
		f = noexcept_string("S");
		BOOST_CHECK_EQUAL(boost::make_optional(noexcept_string("S")), try_get<noexcept_string>(f));

		f = fast_variant<int>(2);
		BOOST_CHECK_EQUAL(boost::make_optional(fast_variant<int>(2)), try_get<fast_variant<int>>(f));
	}

	BOOST_AUTO_TEST_CASE(fast_variant_construct_const)
	{
		noexcept_string const s("S");
		fast_variant<fast_variant<int>, noexcept_string> f{s};
	}

	BOOST_AUTO_TEST_CASE(fast_variant_assign_const)
	{
		fast_variant<fast_variant<int>, noexcept_string> f;
		noexcept_string const s("S");
		f = s;
	}

	BOOST_AUTO_TEST_CASE(fast_variant_less)
	{
		fast_variant<int, noexcept_string> f(1), g(2), h(noexcept_string("a")), i(noexcept_string("b"));
		BOOST_CHECK_LT(f, g);
		BOOST_CHECK_LT(f, h);
		BOOST_CHECK_LT(f, i);
		BOOST_CHECK_LT(h, i);
	}

	namespace detail
	{
		template <class ...T>
		struct union_;

		template <class First, class ...T>
		struct union_<First, T...>
		{
			union
			{
				First head;
				union_<T...> tail;
			}
			content;
		};

		template <>
		struct union_<>
		{
		};

		template <bool IsCopyable, class ...T>
		struct fast_variant_base;

		template <class ...T>
		struct fast_variant_base<false, T...>
		{
			using which_type = std::size_t;

			fast_variant_base() BOOST_NOEXCEPT
			{
				//TODO
			}

			~fast_variant_base() BOOST_NOEXCEPT
			{
				//TODO
			}

			fast_variant_base(fast_variant_base &&other) BOOST_NOEXCEPT
			{
				throw std::logic_error("to do");
			}

			fast_variant_base &operator = (fast_variant_base &&other) BOOST_NOEXCEPT
			{
				throw std::logic_error("to do");
			}

			template <
				class U,
				class CleanU = typename std::decay<U>::type,
				class NoFastVariant = typename std::enable_if<
					boost::mpl::not_<
						std::is_same<
							CleanU,
							fast_variant<T...>
						>
					>::value,
					void
				>::type>
			fast_variant_base(U &&value)
			{
				throw std::logic_error("to do");
			}

			which_type which() const BOOST_NOEXCEPT
			{
				return which_;
			}

			template <class Visitor>
			auto apply_visitor(Visitor &&visitor) -> typename std::decay<Visitor>::type::result_type;

			template <class Visitor>
			auto apply_visitor(Visitor &&visitor) const -> typename std::decay<Visitor>::type::result_type;

		protected:

			which_type which_;
			typename boost::aligned_storage<sizeof(union_<T...>)>::type storage;
		};

		template <class ...T>
		struct fast_variant_base<true, T...> : fast_variant_base<false, T...>
		{
			using base = fast_variant_base<false, T...>;

			fast_variant_base() BOOST_NOEXCEPT
			{
			}

			template <
				class U,
				class CleanU = typename std::decay<U>::type,
				class NoFastVariant = typename std::enable_if<
					boost::mpl::not_<
						std::is_same<
							CleanU,
							fast_variant<T...>
						>
					>::value,
					void
				>::type>
			fast_variant_base(U &&value)
				: base(std::forward<U>(value))
			{
			}

			fast_variant_base(fast_variant_base const &other)
			{
				throw std::logic_error("to do");
			}

			fast_variant_base &operator = (fast_variant_base const &other)
			{
				throw std::logic_error("to do");
			}
		};

		template <class ...T>
		struct are_noexcept_movable;

		template <class First, class ...T>
		struct are_noexcept_movable<First, T...>
			: boost::mpl::and_<
				boost::mpl::and_<
					std::is_nothrow_move_constructible<First>,
					std::is_nothrow_move_assignable<First>
				>,
				are_noexcept_movable<T...>
			>::type
		{
		};

		template <>
		struct are_noexcept_movable<> : std::true_type
		{
		};

		template <class ...T>
		struct are_copyable;

		template <class First, class ...T>
		struct are_copyable<First, T...>
			: boost::mpl::and_<
				boost::mpl::and_<
					std::is_copy_constructible<First>,
					std::is_copy_assignable<First>
				>,
				are_copyable<T...>
			>::type
		{
		};

		template <>
		struct are_copyable<> : std::true_type
		{
		};

		BOOST_STATIC_ASSERT(are_copyable<>::value);
		BOOST_STATIC_ASSERT(are_copyable<int>::value);
		BOOST_STATIC_ASSERT(are_copyable<int, float>::value);
		BOOST_STATIC_ASSERT(!are_copyable<int, std::unique_ptr<int>>::value);

		template <class ...T>
		using select_fast_variant_base = fast_variant_base<are_copyable<T...>::value, T...>;
	}

	template <class ...T>
	struct fast_variant2 : detail::select_fast_variant_base<T...>
	{
		BOOST_STATIC_ASSERT_MSG(detail::are_noexcept_movable<T...>::value, "All contained types must be nothrow/noexcept-movable");

		using base = detail::select_fast_variant_base<T...>;

		using base::base;

		fast_variant2()
		{
		}
	};

	template <class ...T>
	bool operator == (fast_variant2<T...> const &left, fast_variant2<T...> const &right)
	{
		if (left.which() != right.which())
		{
			return false;
		}
		throw std::logic_error("to do");
	}

	template <class ...T>
	bool operator != (fast_variant2<T...> const &left, fast_variant2<T...> const &right)
	{
		return !(left == right);
	}

	BOOST_AUTO_TEST_CASE(fast_variant2_copyable_default)
	{
		using variant = fast_variant2<int>;
		variant v;
	}

	BOOST_AUTO_TEST_CASE(fast_variant2_non_copyable_default)
	{
		using variant = fast_variant2<std::unique_ptr<int>>;
		variant v;
	}

	BOOST_AUTO_TEST_CASE(fast_variant2_copyable_operator_copy)
	{
		using variant = fast_variant2<int>;
		variant v;
		variant w(2);
		BOOST_CHECK(v != w);
		v = w;
		BOOST_CHECK(v == w);
	}

	BOOST_AUTO_TEST_CASE(fast_variant2_copyable_construct_copy)
	{
		using variant = fast_variant2<int>;
		variant v;
		variant w(v);
		BOOST_CHECK(v == w);
	}

	BOOST_AUTO_TEST_CASE(fast_variant_non_copyable_operator_move)
	{
		using variant = fast_variant2<std::unique_ptr<int>>;
		variant v;
		variant w(rx::make_unique<int>(2));
		BOOST_CHECK(v != w);
		v = std::move(w);
		BOOST_CHECK(v != w);
	}

	BOOST_AUTO_TEST_CASE(fast_variant_non_copyable_construct_move)
	{
		using variant = fast_variant2<std::unique_ptr<int>>;
		variant v(rx::make_unique<int>(2));
		variant w(std::move(v));
		BOOST_CHECK(v != w);
	}
}
<|endoftext|>


<commit_before>#include <mlopen.h>
#include "test.hpp"
#include <vector>
#include <array>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <memory>
#include <utility>
#include <iostream>
#include <cmath>
#include <mlopen/tensor.hpp>
#include <mlopen/convolution.hpp>
#include <mlopen/returns.hpp>
#include <mlopen/each_args.hpp>
#include <limits>
#include <thread>

#include "network_data.hpp"

template<class F>
struct protect_fn
{
    F f;
    protect_fn(F x) : f(std::move(x))
    {}

    template<class... Ts>
    auto operator()(Ts&&... xs) const MLOPEN_RETURNS
    (f(std::forward<Ts>(xs)...));
};

template<class F>
protect_fn<F> protect(F f)
{
    return {std::move(f)};
}

template<class F>
void par_for(std::size_t n, F f)
{
    const auto threadsize = std::thread::hardware_concurrency();
    if (n < threadsize)
    {
        for(std::size_t i=0;i<n;i++) f(i);
    }
    else
    {
        std::vector<std::thread> threads(threadsize);
        const std::size_t grainsize = std::ceil(static_cast<double>(n) / threads.size());

        std::size_t work = 0;
        std::generate(threads.begin(), threads.end(), [&]
        {
            std::size_t start = work;
            std::size_t last = std::min(n, work+grainsize);
            assert((last - start) <= grainsize);
            assert((last - start) > 0);
            auto result = std::thread([&f, start, last]
            {
                for(std::size_t i=start;i<last;i++)
                {
                    f(i);
                }
            });
            work += grainsize;
            return result;
        });
        // TODO: Should be in destructor
        for(auto&& t:threads)
        {
            if (t.joinable()) t.join();
        }
    }
}

// Multidimensional for loop
struct ford_impl
{
    template<class F, class T>
    void operator()(F f, T x) const
    {
        for(T i=0;i<x;i++) f(i);
    }

    template<class F, class T, class... Ts>
    void operator()(F f, T x, Ts... xs) const
    {
#if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 9)
        // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55914
        // This reverses the order of evaluation
        (*this)([&](Ts... is)
        {
            (*this)(std::bind(protect(f), std::placeholders::_1, is...), x);
        }, xs...);
#else
        (*this)([&](T i)
        {
            (*this)([&](Ts... is)
            {
                f(i, is...);
            }, xs...);
        }, x);
#endif

    }
};

template<class... Ts>
auto ford(Ts... xs) MLOPEN_RETURNS
(
    std::bind(ford_impl{}, std::placeholders::_1, xs...)
);

struct par_ford_impl
{
    template<class F, class... Ts>
    void operator()(F f, Ts... xs) const
    {
        using array_type = std::array<std::size_t, sizeof...(Ts)>;
        array_type lens = {{static_cast<std::size_t>(xs)...}};
        array_type strides;
        strides.fill(1);
        std::partial_sum(lens.rbegin(), lens.rend()-1, strides.rbegin()+1, std::multiplies<std::size_t>());
        auto size = std::accumulate(lens.begin(), lens.end(), 1, std::multiplies<std::size_t>());
        par_for(size, [&](std::size_t i)
        {
            array_type indices;
            std::transform(strides.begin(), strides.end(), lens.begin(), indices.begin(), [&](size_t stride, size_t len)
            {
                return (i / stride) % len;
            });
            mlopen::unpack(f, indices);
        });
    }
};

template<class... Ts>
auto par_ford(Ts... xs) MLOPEN_RETURNS
(
    std::bind(par_ford_impl{}, std::placeholders::_1, xs...)
);

template<class T>
struct tensor
{
    mlopen::TensorDescriptor desc;
    std::vector<T> data;

    tensor(int n, int c, int h, int w)
    : desc(mlopenFloat, {n,c,h,w}), data(n*c*h*w)
    {}

    tensor(mlopen::TensorDescriptor rhs)
    : desc(std::move(rhs))
    {
        data.resize(desc.GetElementSize());
    }

    template<class G>
    tensor& generate(G g) &
    {
        this->generate_impl(g);
        return *this;
    }

    template<class G>
    tensor&& generate(G g) &&
    {
        this->generate_impl(g);
        return std::move(*this);
    }

    template<class G>
    void generate_impl(G g)
    {
        auto iterator = data.begin();
        this->for_each([&](int i, int j, int k, int m)
        {
            assert(iterator < data.end());
            *iterator = g(i, j, k, m);
            ++iterator;
        });
    }

    template<class F>
    void for_each(F f) const
    {
        int n, c, h, w;
        std::tie(n, c, h, w) = mlopen::tie4(desc.GetLengths());
        ford(n, c, h, w)(std::move(f));
    }

    template<class F>
    void par_for_each(F f) const
    {
        int n, c, h, w;
        std::tie(n, c, h, w) = mlopen::tie4(desc.GetLengths());
        par_ford(n, c, h, w)(std::move(f));
    }

    T& operator()(int n, int c, int h, int w)
    {
        assert(this->desc.GetIndex(n, c, h, w) < data.size());
        return this->data[this->desc.GetIndex(n, c, h, w)];
    }

    const T& operator()(int n, int c, int h, int w) const
    {
        assert(this->desc.GetIndex(n, c, h, w) < data.size());
        return this->data[this->desc.GetIndex(n, c, h, w)];
    }
};

struct tensor_generate
{
    template<class Tensor, class G>
    Tensor&& operator()(Tensor&& t, G g) const
    {
        return std::forward<Tensor>(t.generate(g));
    }
};

template<class T>
tensor<T> get_output_tensor(const mlopen::ConvolutionDescriptor& filter, const tensor<T>& input, const tensor<T>& weights)
{
    return tensor<T>{filter.GetForwardOutputTensor(input.desc, weights.desc)};
}

template<class T>
std::vector<T> forward_conv(const tensor<T>& input, const tensor<T>& weights, const mlopen::ConvolutionDescriptor& filter, int bias = 0)
{
    auto out = get_output_tensor(filter, input, weights);

    int in_n, in_c, in_h, in_w;
    std::tie(in_n, in_c, in_h, in_w) = mlopen::tie4(input.desc.GetLengths());

    int wei_h, wei_w;
    std::tie(std::ignore, std::ignore, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());

    out.par_for_each([&](int o, int w, int i, int j)
    {
        int in_off_h = i * filter.v;
        int in_off_w = j * filter.u;

        T acc = bias;
        ford(in_c, wei_h, wei_w)([&](int k, int x, int y)
        {
            int in_x = in_off_h - filter.pad_h + x;
            int in_y = in_off_w - filter.pad_w + y;
            if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                acc += input(o, k, in_x, in_y) * weights(w, k, x, y);
            }
        });
        out(o, w, i, j) = acc;
    });
    return out.data;
}

template<class T>
std::vector<T> forward_conv(mlopen::Handle& handle, const tensor<T>& input, const tensor<T>& weights, const mlopen::ConvolutionDescriptor& filter, int /* bias */ = 0)
{
    auto out = get_output_tensor(filter, input, weights);

    auto in_dev = handle.Write(input.data);
    auto wei_dev = handle.Write(weights.data);
    auto out_dev = handle.Create<T>(out.data.size());

    int ret_algo_count;
    mlopenConvAlgoPerf_t perf;

    int alpha = 1, beta = 1;

    filter.FindConvFwdAlgorithm(handle,
        input.desc,
        in_dev.get(),
        weights.desc,
        wei_dev.get(),
        out.desc,
        out_dev.get(),
        1,
        &ret_algo_count,
        &perf,
        mlopenConvolutionFastest,
        NULL,
        10,
        0); // MD: Not performing exhaustiveSearch by default for now

    filter.ConvolutionForward(handle,
        &alpha,
        input.desc,
        in_dev.get(),
        weights.desc,
        wei_dev.get(),
        mlopenConvolutionFwdAlgoDirect,
        &beta,
        out.desc,
        out_dev.get(),
        NULL,
        0);

    out.data = handle.Read<T>(out_dev, out.data.size());
    return out.data;
}

struct float_equal_fn
{
    template<class T>
    bool operator()(T x, T y) const
    {
        return std::fabs(x - y) < std::max(std::numeric_limits<T>::epsilon() * std::max(x, y), std::numeric_limits<T>::epsilon());
    }
};

template<class R1, class R2>
bool float_equal_range(R1&& r1, R2&& r2)
{
    return std::distance(r1.begin(), r1.end()) == std::distance(r2.begin(), r2.end()) &&
        std::equal(r1.begin(), r1.end(), r2.begin(), float_equal_fn{});
}

template<class R1, class R2, class Op>
float accumulate_difference(R1&& r1, R2&& r2, Op op)
{
    return std::inner_product(r1.begin(), r1.end(), r2.begin(), 0.0, op,
        [](float x, float y) { return std::fabs(x - y); }
    );
}

template<class T>
void verify_forward_conv(mlopen::Handle& handle, const tensor<T>& input, const tensor<T>& weights, const mlopen::ConvolutionDescriptor& filter, int bias = 0)
{
    auto out_cpu = forward_conv(input, weights, filter, bias);
    auto out_gpu = forward_conv(handle, input, weights, filter, bias);
    int size = std::distance(out_cpu.begin(), out_cpu.end());
    CHECK(std::distance(out_cpu.begin(), out_cpu.end()) == std::distance(out_gpu.begin(), out_gpu.end()));
    if (!float_equal_range(out_cpu, out_gpu))
    {
        std::cout << "FAILED: " << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
        std::cout << "Weights tensor: " << weights.desc.ToString() << std::endl;

        std::cout
            << "Average difference: "
            << (accumulate_difference(out_cpu, out_gpu, std::plus<float>()) / size)
            << std::endl;
        std::cout
            << "Max difference: "
            << (accumulate_difference(out_cpu, out_gpu, [](float x, float y) { return std::max(x, y); }))
            << std::endl;
    }
    // CHECK(out_cpu == out_gpu);
}

struct cross_args_apply
{
    template<class F, class T, class... Ts>
    void operator()(F f, T&& x, Ts&&... xs) const
    {
        mlopen::each_args(std::bind(f, std::forward<T>(x), std::placeholders::_1), std::forward<Ts>(xs)...);
    }
};

template<class F, class... Ts>
void cross_args(F f, Ts&&... xs)
{
    mlopen::each_args(
        std::bind(cross_args_apply{}, protect(std::move(f)), std::placeholders::_1, std::forward<Ts>(xs)...),
    std::forward<Ts>(xs)...);
}

template<class T>
struct verify_both
{
    template<class G1, class G2>
    void operator()(mlopen::Handle& handle, G1 g1, G2 g2) const
    {
        visit_network<T>([&](mlopen::TensorDescriptor input_desc, mlopen::TensorDescriptor weights_desc)
        {
            auto input = tensor<T>{std::move(input_desc)}.generate(g1);
            auto weights = tensor<T>{std::move(weights_desc)}.generate(g2);
            mlopen::ConvolutionDescriptor filter{1, 1};

            verify_forward_conv(handle, input, weights, filter);
        });
    }
};

template<class T, class... Gs>
void verify_all(mlopen::Handle& handle, Gs... gs)
{
    cross_args(
        std::bind(verify_both<T>{}, std::ref(handle), std::placeholders::_1, std::placeholders::_2),
        gs...);
}

template<class T, class G>
void verify_one(mlopen::Handle& handle, G g)
{
    auto input = tensor<T>{16, 32, 8, 8}.generate(g);
    auto weights = tensor<T>{64, 32, 5, 5}.generate(g);
    mlopen::ConvolutionDescriptor filter{1, 1};
    verify_forward_conv(handle, input, weights, filter);
}

int main() {
    mlopen::Handle handle;
    auto g0 = [](int, int, int, int) { return 0; };
    auto g1 = [](int, int, int, int) { return 1; };
    auto g_id = [](int, int, int h, int w) { return h == w ? 1 : 0; };
    auto g = [](int n, int c, int h, int w)
    {
        double x = (547*n+701*c+877*h+1049*w+173)%1223;
        return x/691.0;
    };
    (void)g0;
    (void)g1;
    (void)g_id;
    (void)g;
#if MLOPEN_TEST_ALL
    printf("verify_all\n");
    verify_all<float>(handle, g0,g1, g_id, g);
#else
    printf("verify_one\n");
    verify_one<float>(handle, g);
#endif
}
<commit_msg>Simplify multidimensional for loop to make it consistent across platforms<commit_after>#include <mlopen.h>
#include "test.hpp"
#include <vector>
#include <array>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <memory>
#include <utility>
#include <iostream>
#include <cmath>
#include <mlopen/tensor.hpp>
#include <mlopen/convolution.hpp>
#include <mlopen/returns.hpp>
#include <mlopen/each_args.hpp>
#include <limits>
#include <thread>

#include "network_data.hpp"

template<class F>
struct protect_fn
{
    F f;
    protect_fn(F x) : f(std::move(x))
    {}

    template<class... Ts>
    auto operator()(Ts&&... xs) const MLOPEN_RETURNS
    (f(std::forward<Ts>(xs)...));
};

template<class F>
protect_fn<F> protect(F f)
{
    return {std::move(f)};
}

template<class F>
void par_for(std::size_t n, F f)
{
    const auto threadsize = std::thread::hardware_concurrency();
    if (n < threadsize)
    {
        for(std::size_t i=0;i<n;i++) f(i);
    }
    else
    {
        std::vector<std::thread> threads(threadsize);
        const std::size_t grainsize = std::ceil(static_cast<double>(n) / threads.size());

        std::size_t work = 0;
        std::generate(threads.begin(), threads.end(), [&]
        {
            std::size_t start = work;
            std::size_t last = std::min(n, work+grainsize);
            assert((last - start) <= grainsize);
            assert((last - start) > 0);
            auto result = std::thread([&f, start, last]
            {
                for(std::size_t i=start;i<last;i++)
                {
                    f(i);
                }
            });
            work += grainsize;
            return result;
        });
        // TODO: Should be in destructor
        for(auto&& t:threads)
        {
            if (t.joinable()) t.join();
        }
    }
}

// Multidimensional for loop
struct ford_impl
{
    template<class F>
    void operator()(F f) const
    {
        f();
    }

    template<class F, class T, class... Ts>
    void operator()(F f, T x, Ts... xs) const
    {
        // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55914
        for(T i=0;i<x;i++)
        {
            (*this)([&](Ts... is)
            {
                f(i, is...);
            }, xs...);
        }
    }
};

template<class... Ts>
auto ford(Ts... xs) MLOPEN_RETURNS
(
    std::bind(ford_impl{}, std::placeholders::_1, xs...)
);

struct par_ford_impl
{
    template<class F, class... Ts>
    void operator()(F f, Ts... xs) const
    {
        using array_type = std::array<std::size_t, sizeof...(Ts)>;
        array_type lens = {{static_cast<std::size_t>(xs)...}};
        array_type strides;
        strides.fill(1);
        std::partial_sum(lens.rbegin(), lens.rend()-1, strides.rbegin()+1, std::multiplies<std::size_t>());
        auto size = std::accumulate(lens.begin(), lens.end(), 1, std::multiplies<std::size_t>());
        par_for(size, [&](std::size_t i)
        {
            array_type indices;
            std::transform(strides.begin(), strides.end(), lens.begin(), indices.begin(), [&](size_t stride, size_t len)
            {
                return (i / stride) % len;
            });
            mlopen::unpack(f, indices);
        });
    }
};

template<class... Ts>
auto par_ford(Ts... xs) MLOPEN_RETURNS
(
    std::bind(par_ford_impl{}, std::placeholders::_1, xs...)
);

template<class T>
struct tensor
{
    mlopen::TensorDescriptor desc;
    std::vector<T> data;

    tensor(int n, int c, int h, int w)
    : desc(mlopenFloat, {n,c,h,w}), data(n*c*h*w)
    {}

    tensor(mlopen::TensorDescriptor rhs)
    : desc(std::move(rhs))
    {
        data.resize(desc.GetElementSize());
    }

    template<class G>
    tensor& generate(G g) &
    {
        this->generate_impl(g);
        return *this;
    }

    template<class G>
    tensor&& generate(G g) &&
    {
        this->generate_impl(g);
        return std::move(*this);
    }

    template<class G>
    void generate_impl(G g)
    {
        auto iterator = data.begin();
        this->for_each([&](int i, int j, int k, int m)
        {
            assert(iterator < data.end());
            *iterator = g(i, j, k, m);
            ++iterator;
        });
    }

    template<class F>
    void for_each(F f) const
    {
        int n, c, h, w;
        std::tie(n, c, h, w) = mlopen::tie4(desc.GetLengths());
        ford(n, c, h, w)(std::move(f));
    }

    template<class F>
    void par_for_each(F f) const
    {
        int n, c, h, w;
        std::tie(n, c, h, w) = mlopen::tie4(desc.GetLengths());
        par_ford(n, c, h, w)(std::move(f));
    }

    T& operator()(int n, int c, int h, int w)
    {
        assert(this->desc.GetIndex(n, c, h, w) < data.size());
        return this->data[this->desc.GetIndex(n, c, h, w)];
    }

    const T& operator()(int n, int c, int h, int w) const
    {
        assert(this->desc.GetIndex(n, c, h, w) < data.size());
        return this->data[this->desc.GetIndex(n, c, h, w)];
    }
};

struct tensor_generate
{
    template<class Tensor, class G>
    Tensor&& operator()(Tensor&& t, G g) const
    {
        return std::forward<Tensor>(t.generate(g));
    }
};

template<class T>
tensor<T> get_output_tensor(const mlopen::ConvolutionDescriptor& filter, const tensor<T>& input, const tensor<T>& weights)
{
    return tensor<T>{filter.GetForwardOutputTensor(input.desc, weights.desc)};
}

template<class T>
std::vector<T> forward_conv(const tensor<T>& input, const tensor<T>& weights, const mlopen::ConvolutionDescriptor& filter, int bias = 0)
{
    auto out = get_output_tensor(filter, input, weights);

    int in_n, in_c, in_h, in_w;
    std::tie(in_n, in_c, in_h, in_w) = mlopen::tie4(input.desc.GetLengths());

    int wei_h, wei_w;
    std::tie(std::ignore, std::ignore, wei_h, wei_w) = mlopen::tie4(weights.desc.GetLengths());

    out.par_for_each([&](int o, int w, int i, int j)
    {
        const int in_off_h = i * filter.v;
        const int in_off_w = j * filter.u;

        T acc = bias;
        ford(in_c, wei_h, wei_w)([&](int k, int x, int y)
        {
            const int in_x = in_off_h - filter.pad_h + x;
            const int in_y = in_off_w - filter.pad_w + y;
            if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                acc += input(o, k, in_x, in_y) * weights(w, k, x, y);
            }
        });
        out(o, w, i, j) = acc;
    });
    return out.data;
}

template<class T>
std::vector<T> forward_conv(mlopen::Handle& handle, const tensor<T>& input, const tensor<T>& weights, const mlopen::ConvolutionDescriptor& filter, int /* bias */ = 0)
{
    auto out = get_output_tensor(filter, input, weights);

    auto in_dev = handle.Write(input.data);
    auto wei_dev = handle.Write(weights.data);
    auto out_dev = handle.Create<T>(out.data.size());

    int ret_algo_count;
    mlopenConvAlgoPerf_t perf;

    int alpha = 1, beta = 1;

    filter.FindConvFwdAlgorithm(handle,
        input.desc,
        in_dev.get(),
        weights.desc,
        wei_dev.get(),
        out.desc,
        out_dev.get(),
        1,
        &ret_algo_count,
        &perf,
        mlopenConvolutionFastest,
        NULL,
        10,
        0); // MD: Not performing exhaustiveSearch by default for now

    filter.ConvolutionForward(handle,
        &alpha,
        input.desc,
        in_dev.get(),
        weights.desc,
        wei_dev.get(),
        mlopenConvolutionFwdAlgoDirect,
        &beta,
        out.desc,
        out_dev.get(),
        NULL,
        0);

    out.data = handle.Read<T>(out_dev, out.data.size());
    return out.data;
}

struct float_equal_fn
{
    template<class T>
    bool operator()(T x, T y) const
    {
        return std::fabs(x - y) < std::max(std::numeric_limits<T>::epsilon() * std::max(x, y), std::numeric_limits<T>::epsilon());
    }
};

template<class R1, class R2>
bool float_equal_range(R1&& r1, R2&& r2)
{
    return std::distance(r1.begin(), r1.end()) == std::distance(r2.begin(), r2.end()) &&
        std::equal(r1.begin(), r1.end(), r2.begin(), float_equal_fn{});
}

template<class R1, class R2, class Op>
float accumulate_difference(R1&& r1, R2&& r2, Op op)
{
    return std::inner_product(r1.begin(), r1.end(), r2.begin(), 0.0, op,
        [](float x, float y) { return std::fabs(x - y); }
    );
}

template<class T>
void verify_forward_conv(mlopen::Handle& handle, const tensor<T>& input, const tensor<T>& weights, const mlopen::ConvolutionDescriptor& filter, int bias = 0)
{
    auto out_cpu = forward_conv(input, weights, filter, bias);
    auto out_gpu = forward_conv(handle, input, weights, filter, bias);
    int size = std::distance(out_cpu.begin(), out_cpu.end());
    CHECK(std::distance(out_cpu.begin(), out_cpu.end()) == std::distance(out_gpu.begin(), out_gpu.end()));
    if (!float_equal_range(out_cpu, out_gpu))
    {
        std::cout << "FAILED: " << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
        std::cout << "Weights tensor: " << weights.desc.ToString() << std::endl;

        std::cout
            << "Average difference: "
            << (accumulate_difference(out_cpu, out_gpu, std::plus<float>()) / size)
            << std::endl;
        std::cout
            << "Max difference: "
            << (accumulate_difference(out_cpu, out_gpu, [](float x, float y) { return std::max(x, y); }))
            << std::endl;
    }
    // CHECK(out_cpu == out_gpu);
}

struct cross_args_apply
{
    template<class F, class T, class... Ts>
    void operator()(F f, T&& x, Ts&&... xs) const
    {
        mlopen::each_args(std::bind(f, std::forward<T>(x), std::placeholders::_1), std::forward<Ts>(xs)...);
    }
};

template<class F, class... Ts>
void cross_args(F f, Ts&&... xs)
{
    mlopen::each_args(
        std::bind(cross_args_apply{}, protect(std::move(f)), std::placeholders::_1, std::forward<Ts>(xs)...),
    std::forward<Ts>(xs)...);
}

template<class T>
struct verify_both
{
    template<class G1, class G2>
    void operator()(mlopen::Handle& handle, G1 g1, G2 g2) const
    {
        visit_network<T>([&](mlopen::TensorDescriptor input_desc, mlopen::TensorDescriptor weights_desc)
        {
            auto input = tensor<T>{std::move(input_desc)}.generate(g1);
            auto weights = tensor<T>{std::move(weights_desc)}.generate(g2);
            mlopen::ConvolutionDescriptor filter{1, 1};

            verify_forward_conv(handle, input, weights, filter);
        });
    }
};

template<class T, class... Gs>
void verify_all(mlopen::Handle& handle, Gs... gs)
{
    cross_args(
        std::bind(verify_both<T>{}, std::ref(handle), std::placeholders::_1, std::placeholders::_2),
        gs...);
}

template<class T, class G>
void verify_one(mlopen::Handle& handle, G g)
{
    auto input = tensor<T>{16, 32, 8, 8}.generate(g);
    auto weights = tensor<T>{64, 32, 5, 5}.generate(g);
    mlopen::ConvolutionDescriptor filter{1, 1};
    verify_forward_conv(handle, input, weights, filter);
}

int main() {
    mlopen::Handle handle;
    auto g0 = [](int, int, int, int) { return 0; };
    auto g1 = [](int, int, int, int) { return 1; };
    auto g_id = [](int, int, int h, int w) { return h == w ? 1 : 0; };
    auto g = [](int n, int c, int h, int w)
    {
        double x = (547*n+701*c+877*h+1049*w+173)%1223;
        return x/691.0;
    };
    (void)g0;
    (void)g1;
    (void)g_id;
    (void)g;
#if MLOPEN_TEST_ALL
    printf("verify_all\n");
    verify_all<float>(handle, g0,g1, g_id, g);
#else
    printf("verify_one\n");
    verify_one<float>(handle, g);
#endif
}
<|endoftext|>


<commit_before>///
/// @file  generate_phi.cpp
/// @brief Test that generate_phi(x, a) and phi(x, a)
///        results are identical
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount.hpp>
#include <generate.hpp>
#include <generate_phi.hpp>
#include <PiTable.hpp>

#include <stdint.h>
#include <iostream>
#include <random>
#include <vector>

using namespace std;
using namespace primecount;

int main()
{
  for (int i = 0; i < 100; i++)
  {
    random_device rd;
    mt19937 gen(rd());
    uniform_int_distribution<int64_t> dist(0, 1000000);

    int64_t x = dist(gen);
    int64_t y = isqrt(x) + 1000;

    PiTable pi(y);
    int64_t a = pi[y];

    auto primes = generate_primes<int64_t>(y);
    auto phi_vect = generate_phi(x, a, primes, pi);

    for (int64_t i = 1; i < phi_vect.size(); i++)
    {
      int64_t phi1 = phi_vect[i];
      int64_t phi2 = phi(x, i - 1);

      if (phi1 != phi2)
      {
        cerr << "Error: generate_phi(x, i - 1) = " << phi1 << endl;
        cerr << "Correct: phi(x, i - 1) = " << phi2 << endl;
        cerr << "x = " << x << endl;
        cerr << "i - 1 = " << i - 1 << endl;
        cerr << "a = " << a << endl;
        exit(1);
      }
    }
  }

  cout << endl;
  cout << "All tests passed successfully!" << endl;

  return 0;
}
<commit_msg>Silence MSVC warning<commit_after>///
/// @file  generate_phi.cpp
/// @brief Test that generate_phi(x, a) and phi(x, a)
///        results are identical
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount.hpp>
#include <generate.hpp>
#include <generate_phi.hpp>
#include <PiTable.hpp>

#include <stdint.h>
#include <iostream>
#include <random>
#include <vector>

using namespace std;
using namespace primecount;

int main()
{
  for (int j = 0; j < 100; j++)
  {
    random_device rd;
    mt19937 gen(rd());
    uniform_int_distribution<int64_t> dist(0, 1000000);

    int64_t x = dist(gen);
    int64_t y = isqrt(x) + 1000;

    PiTable pi(y);
    int64_t a = pi[y];

    auto primes = generate_primes<int64_t>(y);
    auto phi_vect = generate_phi(x, a, primes, pi);

    for (size_t i = 1; i < phi_vect.size(); i++)
    {
      int64_t phi1 = phi_vect[i];
      int64_t phi2 = phi(x, i - 1);

      if (phi1 != phi2)
      {
        cerr << "Error: generate_phi(x, i - 1) = " << phi1 << endl;
        cerr << "Correct: phi(x, i - 1) = " << phi2 << endl;
        cerr << "x = " << x << endl;
        cerr << "i - 1 = " << i - 1 << endl;
        cerr << "a = " << a << endl;
        exit(1);
      }
    }
  }

  cout << endl;
  cout << "All tests passed successfully!" << endl;

  return 0;
}
<|endoftext|>


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

#include "message.h"
#include <testpp/test.h>

TESTPP( test_message_constructor )
{
	message_c msg;

	assertpp( msg.argc() ) == 0;
}

<commit_msg>added a message test to verify that args are added correctly<commit_after>/**
 * Copyright 2008 Matthew Graham
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "message.h"
#include <testpp/test.h>

TESTPP( test_message_constructor )
{
	message_c msg;

	assertpp( msg.argc() ) == 0;
}

TESTPP( test_message_add_arg )
{
	message_c msg;

	msg.add_arg( "hello" );
	msg.add_arg( "world!" );
	msg.add_arg( "hello world!" );

	assertpp( msg.argc() ) == 3;
	assertpp( msg.argv( 0 ) ) == "hello";
	assertpp( msg.argv( 1 ) ) == "world!";
	assertpp( msg.argv( 2 ) ) == "hello world!";
}

<|endoftext|>


<commit_before>#include <miopen/miopen.h>
#include "test.hpp"
#include <array>
#include <iterator>
#include <memory>
#include <utility>
#include <iostream>
#include <miopen/tensor.hpp>
#include <miopen/pooling.hpp>
#include <limits>

// #include "network_data.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"
#include "driver.hpp"
#include "get_handle.hpp"

template<class T>
tensor<T> get_output_tensor(const miopen::PoolingDescriptor& filter, const tensor<T>& input)
{
    return tensor<T>{filter.GetForwardOutputTensor(input.desc)};
}

template<class T>
struct pooling_operators
{
    miopen::PoolingDescriptor filter;
    pooling_operators(miopen::PoolingDescriptor f)
    : filter(f)
    {}

    T start() const
    {
        if (filter.GetMode() == miopenPoolingMax) return std::numeric_limits<T>::lowest();
        else return 0.0;
    }

    T operator()(T x, T y) const
    {
        if (filter.GetMode() == miopenPoolingMax) return std::max(x, y);
        else return x+y;
    }

    T final(T x, T y)
    {
        if (filter.GetMode() == miopenPoolingMax) return x;
        else return x / y;
    }
};

struct verify_forward_pooling
{
    template<class T>
    tensor<T> cpu(const tensor<T>& input, const miopen::PoolingDescriptor& filter, std::vector<uint8_t>&)
    {
        auto out = get_output_tensor(filter, input);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tie4(input.desc.GetLengths());

        int u, v, pad_h, pad_w, window_h, window_w;
        std::tie(u, v) = miopen::tie2(filter.GetStrides());
        std::tie(pad_h, pad_w) = miopen::tie2(filter.GetPads());
        std::tie(window_h, window_w) = miopen::tie2(filter.GetLengths());

        auto op = pooling_operators<T>{filter};

        out.par_for_each([&](int o, int w, int i, int j)
        {
            const int start_x = i * v - pad_h;
            const int start_y = j * u - pad_w;

            const int hend = std::min(start_x + window_h, in_h + pad_h);
            const int wend = std::min(start_y + window_w, in_w + pad_w);

            const int pool_size = (hend - start_x) * (wend - start_y);

            T acc = op.start();
            ford(window_h, window_w)([&](int x, int y)
            {
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                    acc = op(acc, input(o, w, in_x, in_y));
                }
            });
            out(o, w, i, j) = op.final(acc, pool_size);
        });
        return out;
    }

    template<class T>
    tensor<T> gpu(const tensor<T>& input, const miopen::PoolingDescriptor& filter, std::vector<uint8_t>& indices)
    {
        auto&& handle = get_handle();
        auto out = get_output_tensor(filter, input);
        indices.resize(out.data.size(), 0);

        auto in_dev = handle.Write(input.data);
        auto out_dev = handle.Create<T>(out.data.size());
        auto workspace_dev = handle.Write(indices);

        int alpha = 1, beta = 1;
        filter.Forward(
            handle,
            &alpha,
            input.desc,
            in_dev.get(),
            &beta,
            out.desc,
            out_dev.get(),
            true,
            workspace_dev.get(),
            indices.size() * sizeof(uint8_t)
        );

        indices = handle.Read<uint8_t>(workspace_dev, indices.size());
        out.data = handle.Read<T>(out_dev, out.data.size());
        return out;
    }

    template<class T>
    void fail(float, const tensor<T>& input, const miopen::PoolingDescriptor& filter, const std::vector<uint8_t>&)
    {
        std::cout << "Forward pooling: ";
        if (filter.GetMode() == miopenPoolingAverage) std::cout << "Average";
        else std::cout << "Max";
        std::cout << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
        std::cout << "Output tensor: " << filter.GetForwardOutputTensor(input.desc).ToString() << std::endl;
    }

};

struct verify_backward_pooling
{
    template<class T>
    tensor<T> cpu(const tensor<T>& input, const tensor<T>& dout, const tensor<T>& out, const miopen::PoolingDescriptor& filter, const std::vector<uint8_t>& indices)
    {
        auto dinput = input;
        CHECK(dout.desc == out.desc);
        std::fill(dinput.begin(), dinput.end(), 0.0);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tie4(dinput.desc.GetLengths());

        int u, v, pad_h, pad_w, window_h, window_w;
        std::tie(u, v) = miopen::tie2(filter.GetStrides());
        std::tie(pad_h, pad_w) = miopen::tie2(filter.GetPads());
        std::tie(window_h, window_w) = miopen::tie2(filter.GetLengths());

        int out_n, out_c, out_h, out_w;
        std::tie(out_n, out_c, out_h, out_w) = miopen::tie4(out.desc.GetLengths());

        par_ford(out_n, out_c)([&](int o, int w)
        {
            if (filter.GetMode() == miopenPoolingMax)
            {
                ford(out_h, out_w)([&](int i, int j)
                {
                    auto idx = indices.at(dout.desc.GetIndex(o, w, i, j));
                    auto idx_h = idx / in_w;
                    auto idx_w = idx % in_w;
                    CHECK(miopen::float_equal(input(o, w, idx_h, idx_w), out(o, w, i, j)));
                    dinput(o, w, idx_h, idx_w) += dout(o, w, i, j);
                });
            }
            else
            {
                ford(out_h, out_w, window_h, window_w)([&](int i, int j, int x, int y)
                {
                    const int start_x = i * v - pad_h;
                    const int start_y = j * u - pad_w;

                    const int hend = std::min(start_x + window_h, in_h + pad_h);
                    const int wend = std::min(start_y + window_w, in_w + pad_w);

                    const int pool_size = (hend - start_x) * (wend - start_y);

                    const int in_x = start_x + x;
                    const int in_y = start_y + y;
                    if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                        dinput(o, w, in_x, in_y) += dout(o, w, i, j) / pool_size;
                    }
                });
            }
        });
        return dinput;
    }

    template<class T>
    tensor<T> gpu(const tensor<T>& input, const tensor<T>& dout, const tensor<T>& out, const miopen::PoolingDescriptor& filter, const std::vector<uint8_t>& indices)
    {
        auto&& handle = get_handle();
        auto dinput = input;

        auto in_dev = handle.Write(input.data);
        auto dout_dev = handle.Write(dout.data);
        auto out_dev = handle.Write(out.data);
        auto din_dev = handle.Create<T>(dinput.data.size());

        // std::vector<char> workspace(filter.GetWorkSpaceSize(out.desc));
        // auto workspace_dev = handle.Write(workspace);
        auto workspace_dev = handle.Write(indices);

        int alpha = 1, beta = 1;
        filter.Backward(
            handle,
            &alpha,
            // y
            out.desc,
            out_dev.get(),
            // dy
            dout.desc,
            dout_dev.get(),
            // x
            input.desc,
            in_dev.get(),
            &beta,
            // dx
            dinput.desc,
            din_dev.get(),
            workspace_dev.get()
        );

        dinput.data = handle.Read<T>(din_dev, dinput.data.size());
        return dinput;
    }

    template<class T>
    void fail(float, const tensor<T>& input, const tensor<T>&, const tensor<T>& out, const miopen::PoolingDescriptor& filter, const std::vector<uint8_t>&)
    {
        std::cout << "Backward pooling: ";
        if (filter.GetMode() == miopenPoolingAverage) std::cout << "Average";
        else std::cout << "Max";
        std::cout << std::endl;
        std::cout << "Output tensor: " << out.desc.ToString() << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
    }

};

template<class T>
struct pooling_driver : test_driver
{
    tensor<T> input;

    pooling_driver()
    {
        add(input, "input", get_input_tensor());
    }
    void run()
    {
		int window_h, window_w;
		std::tie(window_h, window_w) = miopen::tie2(filter.GetLengths());
        if ((window_h * window_w) >= std::numeric_limits<uint8_t>::max()) return;

        for(auto m:{miopenPoolingMax, miopenPoolingAverage})
        {
            for(auto filter:{
                miopen::PoolingDescriptor{m, {2, 2}, {2, 2}, {0, 0}},
                miopen::PoolingDescriptor{m, {2, 2}, {1, 1}, {0, 0}},
                miopen::PoolingDescriptor{m, {2, 2}, {1, 1}, {1, 1}},
                miopen::PoolingDescriptor{m, {3, 3}, {2, 2}, {0, 0}},
                miopen::PoolingDescriptor{m, {3, 3}, {1, 1}, {1, 1}}
            })
            {
                std::vector<uint8_t> indices{};
                auto out = verify(verify_forward_pooling{}, input, filter, indices);
                auto dout = out.first;
                dout.generate([&](int n, int c, int h, int w)
                {
                    T x = out.first(n, c, h, w);
                    double y = (877*n+547*c+701*h+1049*w+static_cast<int>(769*x))%2503;
                    return ((x*y)/1301.0);
                });
                verify(verify_backward_pooling{}, input, dout, out.first, filter, indices);
            }
        }
    }
};

int main(int argc, const char *argv[])
{
    test_drive<pooling_driver<float>>(argc, argv);
}
<commit_msg>Fix pooling tests<commit_after>#include <miopen/miopen.h>
#include "test.hpp"
#include <array>
#include <iterator>
#include <memory>
#include <utility>
#include <iostream>
#include <miopen/tensor.hpp>
#include <miopen/pooling.hpp>
#include <limits>

// #include "network_data.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"
#include "driver.hpp"
#include "get_handle.hpp"

template<class T>
tensor<T> get_output_tensor(const miopen::PoolingDescriptor& filter, const tensor<T>& input)
{
    return tensor<T>{filter.GetForwardOutputTensor(input.desc)};
}

template<class T>
struct pooling_operators
{
    miopen::PoolingDescriptor filter;
    pooling_operators(miopen::PoolingDescriptor f)
    : filter(f)
    {}

    T start() const
    {
        if (filter.GetMode() == miopenPoolingMax) return std::numeric_limits<T>::lowest();
        else return 0.0;
    }

    T operator()(T x, T y) const
    {
        if (filter.GetMode() == miopenPoolingMax) return std::max(x, y);
        else return x+y;
    }

    T final(T x, T y)
    {
        if (filter.GetMode() == miopenPoolingMax) return x;
        else return x / y;
    }
};

struct verify_forward_pooling
{
    template<class T>
    tensor<T> cpu(const tensor<T>& input, const miopen::PoolingDescriptor& filter, std::vector<uint8_t>&)
    {
        auto out = get_output_tensor(filter, input);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tie4(input.desc.GetLengths());

        int u, v, pad_h, pad_w, window_h, window_w;
        std::tie(u, v) = miopen::tie2(filter.GetStrides());
        std::tie(pad_h, pad_w) = miopen::tie2(filter.GetPads());
        std::tie(window_h, window_w) = miopen::tie2(filter.GetLengths());

        auto op = pooling_operators<T>{filter};

        out.par_for_each([&](int o, int w, int i, int j)
        {
            const int start_x = i * v - pad_h;
            const int start_y = j * u - pad_w;

            const int hend = std::min(start_x + window_h, in_h + pad_h);
            const int wend = std::min(start_y + window_w, in_w + pad_w);

            const int pool_size = (hend - start_x) * (wend - start_y);

            T acc = op.start();
            ford(window_h, window_w)([&](int x, int y)
            {
                const int in_x = start_x + x;
                const int in_y = start_y + y;
                if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                    acc = op(acc, input(o, w, in_x, in_y));
                }
            });
            out(o, w, i, j) = op.final(acc, pool_size);
        });
        return out;
    }

    template<class T>
    tensor<T> gpu(const tensor<T>& input, const miopen::PoolingDescriptor& filter, std::vector<uint8_t>& indices)
    {
        auto&& handle = get_handle();
        auto out = get_output_tensor(filter, input);
        indices.resize(out.data.size(), 0);

        auto in_dev = handle.Write(input.data);
        auto out_dev = handle.Create<T>(out.data.size());
        auto workspace_dev = handle.Write(indices);

        int alpha = 1, beta = 1;
        filter.Forward(
            handle,
            &alpha,
            input.desc,
            in_dev.get(),
            &beta,
            out.desc,
            out_dev.get(),
            true,
            workspace_dev.get(),
            indices.size() * sizeof(uint8_t)
        );

        indices = handle.Read<uint8_t>(workspace_dev, indices.size());
        out.data = handle.Read<T>(out_dev, out.data.size());
        return out;
    }

    template<class T>
    void fail(float, const tensor<T>& input, const miopen::PoolingDescriptor& filter, const std::vector<uint8_t>&)
    {
        std::cout << "Forward pooling: ";
        if (filter.GetMode() == miopenPoolingAverage) std::cout << "Average";
        else std::cout << "Max";
        std::cout << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
        std::cout << "Output tensor: " << filter.GetForwardOutputTensor(input.desc).ToString() << std::endl;
    }

};

struct verify_backward_pooling
{
    template<class T>
    tensor<T> cpu(const tensor<T>& input, const tensor<T>& dout, const tensor<T>& out, const miopen::PoolingDescriptor& filter, const std::vector<uint8_t>& indices)
    {
        auto dinput = input;
        CHECK(dout.desc == out.desc);
        std::fill(dinput.begin(), dinput.end(), 0.0);

        int in_h, in_w;
        std::tie(std::ignore, std::ignore, in_h, in_w) = miopen::tie4(dinput.desc.GetLengths());

        int u, v, pad_h, pad_w, window_h, window_w;
        std::tie(u, v) = miopen::tie2(filter.GetStrides());
        std::tie(pad_h, pad_w) = miopen::tie2(filter.GetPads());
        std::tie(window_h, window_w) = miopen::tie2(filter.GetLengths());

        int out_n, out_c, out_h, out_w;
        std::tie(out_n, out_c, out_h, out_w) = miopen::tie4(out.desc.GetLengths());

        par_ford(out_n, out_c)([&](int o, int w)
        {
            if (filter.GetMode() == miopenPoolingMax)
            {
                ford(out_h, out_w)([&](int i, int j)
                {
                    auto idx = indices.at(dout.desc.GetIndex(o, w, i, j));
                    auto idx_h = idx / window_w;
                    auto idx_w = idx % window_w;
					auto in_y = i * v - pad_h + idx_h;
					auto in_x = j * u - pad_w + idx_w;
					if (in_y >= 0 && in_x >= 0 && in_y < in_h && in_x < in_w) {
						CHECK(miopen::float_equal(input(o, w, in_y, in_x), out(o, w, i, j)));
						dinput(o, w, in_y, in_x) += dout(o, w, i, j);
					}
                });
            }
            else
            {
                ford(out_h, out_w, window_h, window_w)([&](int i, int j, int x, int y)
                {
                    const int start_x = i * v - pad_h;
                    const int start_y = j * u - pad_w;

                    const int hend = std::min(start_x + window_h, in_h + pad_h);
                    const int wend = std::min(start_y + window_w, in_w + pad_w);

                    const int pool_size = (hend - start_x) * (wend - start_y);

                    const int in_x = start_x + x;
                    const int in_y = start_y + y;
                    if(in_x >= 0 && in_x < in_h && in_y >= 0 && in_y < in_w) {
                        dinput(o, w, in_x, in_y) += dout(o, w, i, j) / pool_size;
                    }
                });
            }
        });
        return dinput;
    }

    template<class T>
    tensor<T> gpu(const tensor<T>& input, const tensor<T>& dout, const tensor<T>& out, const miopen::PoolingDescriptor& filter, const std::vector<uint8_t>& indices)
    {
        auto&& handle = get_handle();
        auto dinput = input;

        auto in_dev = handle.Write(input.data);
        auto dout_dev = handle.Write(dout.data);
        auto out_dev = handle.Write(out.data);
        auto din_dev = handle.Create<T>(dinput.data.size());

        // std::vector<char> workspace(filter.GetWorkSpaceSize(out.desc));
        // auto workspace_dev = handle.Write(workspace);
        auto workspace_dev = handle.Write(indices);

        int alpha = 1, beta = 1;
        filter.Backward(
            handle,
            &alpha,
            // y
            out.desc,
            out_dev.get(),
            // dy
            dout.desc,
            dout_dev.get(),
            // x
            input.desc,
            in_dev.get(),
            &beta,
            // dx
            dinput.desc,
            din_dev.get(),
            workspace_dev.get()
        );

        dinput.data = handle.Read<T>(din_dev, dinput.data.size());
        return dinput;
    }

    template<class T>
    void fail(float, const tensor<T>& input, const tensor<T>&, const tensor<T>& out, const miopen::PoolingDescriptor& filter, const std::vector<uint8_t>&)
    {
        std::cout << "Backward pooling: ";
        if (filter.GetMode() == miopenPoolingAverage) std::cout << "Average";
        else std::cout << "Max";
        std::cout << std::endl;
        std::cout << "Output tensor: " << out.desc.ToString() << std::endl;
        std::cout << "Input tensor: " << input.desc.ToString() << std::endl;
    }

};

template<class T>
struct pooling_driver : test_driver
{
    tensor<T> input;

    pooling_driver()
    {
        add(input, "input", get_input_tensor());
    }
    void run()
    {
        for(auto m:{miopenPoolingMax, miopenPoolingAverage})
        {
            for(auto filter:{
                miopen::PoolingDescriptor{m, {2, 2}, {2, 2}, {0, 0}},
                miopen::PoolingDescriptor{m, {2, 2}, {1, 1}, {0, 0}},
                miopen::PoolingDescriptor{m, {2, 2}, {1, 1}, {1, 1}},
                miopen::PoolingDescriptor{m, {3, 3}, {2, 2}, {0, 0}},
                miopen::PoolingDescriptor{m, {3, 3}, {1, 1}, {1, 1}}
            })
            {
                std::vector<uint8_t> indices{};
                auto out = verify(verify_forward_pooling{}, input, filter, indices);
                auto dout = out.first;
                dout.generate([&](int n, int c, int h, int w)
                {
                    T x = out.first(n, c, h, w);
                    double y = (877*n+547*c+701*h+1049*w+static_cast<int>(769*x))%2503;
                    return ((x*y)/1301.0);
                });
                verify(verify_backward_pooling{}, input, dout, out.first, filter, indices);
            }
        }
    }
};

int main(int argc, const char *argv[])
{
    test_drive<pooling_driver<float>>(argc, argv);
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

/*
 * SpeciesInitialValueLostFocusCommand.cpp
 *
 *  Created on: 19 Sep 2014
 *      Author: dada
 */

#include "qtUtilities.h"

#include "model/CMetab.h"
#include "UI/CQSpeciesDetail.h"
#include "model/CCompartment.h"

#include "UndoSpeciesData.h"

#include "SpeciesInitialValueLostFocusCommand.h"

SpeciesInitialValueLostFocusCommand::SpeciesInitialValueLostFocusCommand(
  CQSpeciesDetail *pSpecieDetail)
  : CCopasiUndoCommand("Species", SPECIES_TYPE_CHANGE, "Change")
  , mpSpecieDetail(pSpecieDetail)
  , mpSpeciesData(new UndoSpeciesData(mpSpecieDetail->mpMetab))
  , mFirstTime(true)
{

  std::string sName = mpSpecieDetail->mpMetab->getObjectName();
  setText(QString(": Species Initial Value Change for %1").arg(FROM_UTF8(sName)));
  setName(mpSpeciesData->getName());

  std::ostringstream strs;
  strs << mpSpecieDetail->mInitialConcentration;
  std::string str = strs.str();
  setNewValue(str);
  strs.clear();
  strs << mpSpecieDetail->mpMetab->getInitialConcentration();
  str = strs.str();
  setOldValue(str);
  setProperty("Initial Value");
}
void SpeciesInitialValueLostFocusCommand::redo()
{
  if (mFirstTime)
    {
      mpSpecieDetail->speciesInitialValueLostFocus();
      mFirstTime = false;
    }
  else
    {
      mpSpecieDetail->speciesInitialValueLostFocus(mpSpeciesData);
    }
}
void SpeciesInitialValueLostFocusCommand::undo()
{
  mpSpecieDetail->speciesInitialValueLostFocus(mpSpeciesData);
  setAction("Undone change");
}

SpeciesInitialValueLostFocusCommand::~SpeciesInitialValueLostFocusCommand()
{
  pdelete(mpSpeciesData);
}
<commit_msg>- issue 2241: old value was not properly stored on species initial value change<commit_after>// Copyright (C) 2015 - 2016 by Pedro Mendes, Virginia Tech Intellectual
// Properties, Inc., University of Heidelberg, and The University
// of Manchester.
// All rights reserved.

/*
 * SpeciesInitialValueLostFocusCommand.cpp
 *
 *  Created on: 19 Sep 2014
 *      Author: dada
 */

#include "qtUtilities.h"

#include "model/CMetab.h"
#include "UI/CQSpeciesDetail.h"
#include "model/CCompartment.h"

#include "UndoSpeciesData.h"

#include "SpeciesInitialValueLostFocusCommand.h"

SpeciesInitialValueLostFocusCommand::SpeciesInitialValueLostFocusCommand(
  CQSpeciesDetail *pSpecieDetail)
  : CCopasiUndoCommand("Species", SPECIES_TYPE_CHANGE, "Change")
  , mpSpecieDetail(pSpecieDetail)
  , mpSpeciesData(new UndoSpeciesData(mpSpecieDetail->mpMetab))
  , mFirstTime(true)
{

  std::string sName = mpSpecieDetail->mpMetab->getObjectName();
  setText(QString(": Species Initial Value Change for %1").arg(FROM_UTF8(sName)));
  setName(mpSpeciesData->getName());

  setNewValue(TO_UTF8(mpSpecieDetail->mpEditInitialValue->text()));
  std::ostringstream strs;
  strs << mpSpecieDetail->mInitialConcentration;
  std::string str = strs.str();
  setOldValue(str);
  setProperty("Initial Value");
}
void SpeciesInitialValueLostFocusCommand::redo()
{
  if (mFirstTime)
    {
      mpSpecieDetail->speciesInitialValueLostFocus();
      mFirstTime = false;
    }
  else
    {
      mpSpecieDetail->speciesInitialValueLostFocus(mpSpeciesData);
    }
}
void SpeciesInitialValueLostFocusCommand::undo()
{
  mpSpecieDetail->speciesInitialValueLostFocus(mpSpeciesData);
  setAction("Undone change");
}

SpeciesInitialValueLostFocusCommand::~SpeciesInitialValueLostFocusCommand()
{
  pdelete(mpSpeciesData);
}
<|endoftext|>


<commit_before>#include "Test.h"

using namespace ::testing;

#define EVIL_EOF (-0xE0F)

extern "C" FILE* test_fopen(const char* filename,
                            const char* mode);
extern "C" int test_fwrite(const void *data,
                           size_t size,
                           size_t nmemb,
                           FILE *f);
extern "C" int test_fclose(FILE *f);

class FcloseTest : public evil::Test {};

TEST_F(FcloseTest, null) {
    evil::UBChecker ub{1};
    EXPECT_EQ(EVIL_EOF, test_fclose(nullptr));
}

TEST_F(FcloseTest, failing_close) {
    EXPECT_CALL(_syscalls, _isatty(_))
        .WillOnce(Return(1));
    EXPECT_CALL(_syscalls, _access(_, _))
        .WillOnce(Return(0));
    EXPECT_CALL(_syscalls, _open(_, _, _))
        .WillOnce(Return(3));

    FILE *f = test_fopen("", "r");
    EXPECT_NE(nullptr, f);

    EXPECT_CALL(_syscalls, _close(3))
        .WillOnce(Return(-1));

    EXPECT_EQ(EVIL_EOF, test_fclose(f));
}

TEST_F(FcloseTest, failing_flush) {
    char heap[4096];
    EXPECT_CALL(_syscalls, _isatty(_))
        .WillOnce(Return(0));
    EXPECT_CALL(_syscalls, _sbrk(_))
        .WillOnce(Return(heap));
    EXPECT_CALL(_syscalls, _open(_, _, _))
        .WillOnce(Return(3));

    FILE *f = test_fopen("", "w");
    test_fwrite("a", 1, 1, f);

    EXPECT_CALL(_syscalls, _write(_, _, _))
        .WillOnce(Return(-1));
    EXPECT_CALL(_syscalls, _close(3))
        .WillOnce(Return(0));

    EXPECT_EQ(EVIL_EOF, test_fclose(f));
}
<commit_msg>Remove more redundant expects<commit_after>#include "Test.h"

using namespace ::testing;

#define EVIL_EOF (-0xE0F)

extern "C" FILE* test_fopen(const char* filename,
                            const char* mode);
extern "C" int test_fwrite(const void *data,
                           size_t size,
                           size_t nmemb,
                           FILE *f);
extern "C" int test_fclose(FILE *f);

class FcloseTest : public evil::Test {};

TEST_F(FcloseTest, null) {
    evil::UBChecker ub{1};
    EXPECT_EQ(EVIL_EOF, test_fclose(nullptr));
}

TEST_F(FcloseTest, failing_close) {
    EXPECT_CALL(_syscalls, _isatty(_))
        .WillOnce(Return(1));
    EXPECT_CALL(_syscalls, _access(_, _))
        .WillOnce(Return(0));
    EXPECT_CALL(_syscalls, _open(_, _, _))
        .WillOnce(Return(3));

    FILE *f = test_fopen("", "r");
    EXPECT_NE(nullptr, f);

    EXPECT_CALL(_syscalls, _close(3))
        .WillOnce(Return(-1));

    EXPECT_EQ(EVIL_EOF, test_fclose(f));
}

TEST_F(FcloseTest, failing_flush) {
    EXPECT_CALL(_syscalls, _isatty(_))
        .WillOnce(Return(0));
    EXPECT_CALL(_syscalls, _open(_, _, _))
        .WillOnce(Return(3));

    FILE *f = test_fopen("", "w");
    test_fwrite("a", 1, 1, f);

    EXPECT_CALL(_syscalls, _write(_, _, _))
        .WillOnce(Return(-1));
    EXPECT_CALL(_syscalls, _close(3))
        .WillOnce(Return(0));

    EXPECT_EQ(EVIL_EOF, test_fclose(f));
}
<|endoftext|>