<commit_before>#include "stdio.h"
#include "xh_scanner.h"

#include <node.h>
#include <node_version.h>
#include <node_events.h>
#include <node_buffer.h>

using namespace v8;
using namespace node;

struct wchar_istream: public markup::instream
{
	markup::wchar* data;
   	int   pos;

       wchar_istream(markup::wchar* text) : data(text), pos(0) {
				// printf("Created stream of length :%i\n",data.len);
	}

       virtual markup::wchar get_char() {
		// markup::wchar result =  pos < data.len ? data.start[pos++] : 0;
		markup::wchar result =  data[pos];
		if (result != 0) {
			pos++;
		}
		return result;
	}

	~wchar_istream() {
		// delete[] data.start;
	}

};

/*
 * Do the binding stuff with V8
 */
class HTMLScanner: ObjectWrap
{
private:
  markup::scanner* scanner;
  markup::instream* si;
  int pendingToken;
  markup::wchar* html;

public:

  static Persistent<FunctionTemplate> s_ct;
  static void Initialize(Handle<Object> target)
  {
    HandleScope scope;

    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    s_ct = Persistent<FunctionTemplate>::New(t);
    s_ct->InstanceTemplate()->SetInternalFieldCount(1);
    s_ct->SetClassName(String::NewSymbol("Scanner"));

    NODE_SET_PROTOTYPE_METHOD(t, "next", Next);
    target->Set(String::NewSymbol("Scanner"),s_ct->GetFunction());
  }

  HTMLScanner(String &str) : pendingToken(-99)
  {
    html = new markup::wchar[str.Length()+1];
    str.Write(html);
    si = new wchar_istream(html);
    scanner = new markup::scanner(*si);

  }

  ~HTMLScanner()
  {
	delete scanner;
	delete si;
	delete[] html;
  }

  static Handle<Value> New(const Arguments& args)
  {
    HandleScope scope;
    Local<String> str;

    if (args.Length() >= 1 && args[0]->IsString())
    {
        str = args[0]->ToString();
        HTMLScanner* xhs = new HTMLScanner(**str);
        xhs->Wrap(args.This());
    }

    return args.This();
  }

  /*
   * This is the main method that is invoked
   */
  static Handle<Value> Next(const Arguments& args)
  {
    HandleScope scope;
    HTMLScanner* xhs = ObjectWrap::Unwrap<HTMLScanner>(args.This());
    markup::scanner* sc = xhs->scanner;

  bool found = false;
  Local<Object> result2 = Array::New();
  int t;

  while(! found)
  {

    // Check if there is still a pending token from last time this function was called.
    if (xhs->pendingToken > -2) {
	t = xhs->pendingToken;
	xhs->pendingToken = -99;
    } else {
	t = sc->get_token();
    }

    int counter = 0;
    found = true;

    switch(t)
    {
      case markup::scanner::TT_ERROR:
      case markup::scanner::TT_EOF:
	result2->Set(counter++, Integer::New(t) );
	break;

      case markup::scanner::TT_TAG_START:
	result2->Set(counter++, Integer::New(t) );
	sc->tagname.push_back(0); // Just make sure there is a 0.
	result2->Set(counter++,	String::New(&sc->tagname[0]));

	// Loop to get all the attributes
	t = sc->get_token();
	while (t == markup::scanner::TT_ATTR) {
		sc->attrname.push_back(0); // Just make sure there is a 0.
		result2->Set(counter++,	String::New(&sc->attrname[0]));
		sc->value2.push_back(0); // Just make sure there is a 0.
		result2->Set(counter++,	String::New(&sc->value2[0]));
		t = sc->get_token();
	}
	xhs->pendingToken = t;
        break;

      case markup::scanner::TT_TAG_END:
	result2->Set(counter++, Integer::New(t) );
	sc->tagname.push_back(0); // Just make sure there is a 0.
	result2->Set(counter++,	String::New(&sc->tagname[0]));
        break;

      case markup::scanner::TT_DOCTYPE_END:
      case markup::scanner::TT_WORD:
      case markup::scanner::TT_PI_END:
      case markup::scanner::TT_COMMENT_END:
      case markup::scanner::TT_CDATA_END:
	result2->Set(counter++, Integer::New(t) );
	sc->value2.push_back(0); // Just make sure there is a 0.
	result2->Set(counter++,	String::New(&sc->value2[0]));
     	break;

       default:
	found = false;

    }
  }

    return scope.Close(result2);

}
};

Persistent<FunctionTemplate> HTMLScanner::s_ct;
extern "C" void init(Handle<Object> target)
{
  HandleScope scope;
  HTMLScanner::Initialize(target);
}

<commit_msg>removed include<commit_after>#include "stdio.h"
#include "xh_scanner.h"

#include <node.h>
#include <node_version.h>
#include <node_buffer.h>

using namespace v8;
using namespace node;

struct wchar_istream: public markup::instream
{
	markup::wchar* data;
   	int   pos;

       wchar_istream(markup::wchar* text) : data(text), pos(0) {
				// printf("Created stream of length :%i\n",data.len);
	}

       virtual markup::wchar get_char() {
		// markup::wchar result =  pos < data.len ? data.start[pos++] : 0;
		markup::wchar result =  data[pos];
		if (result != 0) {
			pos++;
		}
		return result;
	}

	~wchar_istream() {
		// delete[] data.start;
	}

};

/*
 * Do the binding stuff with V8
 */
class HTMLScanner: ObjectWrap
{
private:
  markup::scanner* scanner;
  markup::instream* si;
  int pendingToken;
  markup::wchar* html;

public:

  static Persistent<FunctionTemplate> s_ct;
  static void Initialize(Handle<Object> target)
  {
    HandleScope scope;

    Local<FunctionTemplate> t = FunctionTemplate::New(New);

    s_ct = Persistent<FunctionTemplate>::New(t);
    s_ct->InstanceTemplate()->SetInternalFieldCount(1);
    s_ct->SetClassName(String::NewSymbol("Scanner"));

    NODE_SET_PROTOTYPE_METHOD(t, "next", Next);
    target->Set(String::NewSymbol("Scanner"),s_ct->GetFunction());
  }

  HTMLScanner(String &str) : pendingToken(-99)
  {
    html = new markup::wchar[str.Length()+1];
    str.Write(html);
    si = new wchar_istream(html);
    scanner = new markup::scanner(*si);

  }

  ~HTMLScanner()
  {
	delete scanner;
	delete si;
	delete[] html;
  }

  static Handle<Value> New(const Arguments& args)
  {
    HandleScope scope;
    Local<String> str;

    if (args.Length() >= 1 && args[0]->IsString())
    {
        str = args[0]->ToString();
        HTMLScanner* xhs = new HTMLScanner(**str);
        xhs->Wrap(args.This());
    }

    return args.This();
  }

  /*
   * This is the main method that is invoked
   */
  static Handle<Value> Next(const Arguments& args)
  {
    HandleScope scope;
    HTMLScanner* xhs = ObjectWrap::Unwrap<HTMLScanner>(args.This());
    markup::scanner* sc = xhs->scanner;

  bool found = false;
  Local<Object> result2 = Array::New();
  int t;

  while(! found)
  {

    // Check if there is still a pending token from last time this function was called.
    if (xhs->pendingToken > -2) {
	t = xhs->pendingToken;
	xhs->pendingToken = -99;
    } else {
	t = sc->get_token();
    }

    int counter = 0;
    found = true;

    switch(t)
    {
      case markup::scanner::TT_ERROR:
      case markup::scanner::TT_EOF:
	result2->Set(counter++, Integer::New(t) );
	break;

      case markup::scanner::TT_TAG_START:
	result2->Set(counter++, Integer::New(t) );
	sc->tagname.push_back(0); // Just make sure there is a 0.
	result2->Set(counter++,	String::New(&sc->tagname[0]));

	// Loop to get all the attributes
	t = sc->get_token();
	while (t == markup::scanner::TT_ATTR) {
		sc->attrname.push_back(0); // Just make sure there is a 0.
		result2->Set(counter++,	String::New(&sc->attrname[0]));
		sc->value2.push_back(0); // Just make sure there is a 0.
		result2->Set(counter++,	String::New(&sc->value2[0]));
		t = sc->get_token();
	}
	xhs->pendingToken = t;
        break;

      case markup::scanner::TT_TAG_END:
	result2->Set(counter++, Integer::New(t) );
	sc->tagname.push_back(0); // Just make sure there is a 0.
	result2->Set(counter++,	String::New(&sc->tagname[0]));
        break;

      case markup::scanner::TT_DOCTYPE_END:
      case markup::scanner::TT_WORD:
      case markup::scanner::TT_PI_END:
      case markup::scanner::TT_COMMENT_END:
      case markup::scanner::TT_CDATA_END:
	result2->Set(counter++, Integer::New(t) );
	sc->value2.push_back(0); // Just make sure there is a 0.
	result2->Set(counter++,	String::New(&sc->value2[0]));
     	break;

       default:
	found = false;

    }
  }

    return scope.Close(result2);

}
};

Persistent<FunctionTemplate> HTMLScanner::s_ct;
extern "C" void init(Handle<Object> target)
{
  HandleScope scope;
  HTMLScanner::Initialize(target);
}

<|endoftext|>


<commit_before>// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

//  VK tests
//
//  Copyright (C) 2014 LunarG, Inc.
//
//  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.

// Verify VK driver initialization

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#include <vulkan.h>
#include "gtest-1.7.0/include/gtest/gtest.h"
#include "vktestbinding.h"
#include "test_common.h"

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

class VkImageTest : public ::testing::Test {
public:
    void CreateImage(uint32_t w, uint32_t h);
    void DestroyImage();

    void CreateImageView(VkImageViewCreateInfo* pCreateInfo,
                         VkImageView* pView);
    void DestroyImageView(VkImageView imageView);
    VkDevice device() {return m_device->handle();}

protected:
    vk_testing::Device *m_device;
    VkApplicationInfo app_info;
    VkPhysicalDevice objs[16];
    uint32_t gpu_count;
    VkInstance inst;
    VkImage m_image;
    VkDeviceMemory m_image_mem;

    virtual void SetUp() {
        VkResult err;

        this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
        this->app_info.pNext = NULL;
        this->app_info.pAppName = "base";
        this->app_info.appVersion = 1;
        this->app_info.pEngineName = "unittest";
        this->app_info.engineVersion = 1;
        this->app_info.apiVersion = VK_API_VERSION;
        VkInstanceCreateInfo inst_info = {};
        inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        inst_info.pNext = NULL;
        inst_info.pAppInfo = &app_info;
        inst_info.pAllocCb = NULL;
        inst_info.layerCount = 0;
        inst_info.ppEnabledLayerNames = NULL;
        inst_info.extensionCount = 0;
        inst_info.ppEnabledExtensionNames = NULL;
        err = vkCreateInstance(&inst_info, &this->inst);
        ASSERT_VK_SUCCESS(err);
        err = vkEnumeratePhysicalDevices(this->inst, &this->gpu_count, NULL);
        ASSERT_VK_SUCCESS(err);
        ASSERT_LE(this->gpu_count, ARRAY_SIZE(objs)) << "Too many GPUs";
        err = vkEnumeratePhysicalDevices(this->inst, &this->gpu_count, objs);
        ASSERT_VK_SUCCESS(err);
        ASSERT_GE(this->gpu_count, 1) << "No GPU available";

        this->m_device = new vk_testing::Device(objs[0]);
        this->m_device->init();
    }

    virtual void TearDown() {
        delete this->m_device;
        vkDestroyInstance(this->inst);
    }
};

void VkImageTest::CreateImage(uint32_t w, uint32_t h)
{
    VkResult err;
    uint32_t mipCount;
    VkFormat fmt;
    VkFormatProperties image_fmt;

    mipCount = 0;

    uint32_t _w = w;
    uint32_t _h = h;
    while( ( _w > 0 ) || ( _h > 0 ) )
    {
        _w >>= 1;
        _h >>= 1;
        mipCount++;
    }

    fmt = VK_FORMAT_R8G8B8A8_UINT;
    // TODO: Pick known good format rather than just expect common format
    /*
     * XXX: What should happen if given NULL HANDLE for the pData argument?
     * We're not requesting VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS so there is
     * an expectation that pData is a valid pointer.
     * However, why include a returned size value? That implies that the
     * amount of data may vary and that doesn't work well for using a
     * fixed structure.
     */
    err = vkGetPhysicalDeviceFormatProperties(this->objs[0], fmt, &image_fmt);
    ASSERT_VK_SUCCESS(err);

    //    typedef struct VkImageCreateInfo_
    //    {
    //        VkStructureType                      sType;                      // Must be VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
    //        const void*                             pNext;                      // Pointer to next structure.
    //        VkImageType                          imageType;
    //        VkFormat                              format;
    //        VkExtent3D                            extent;
    //        uint32_t                                mipLevels;
    //        uint32_t                                arraySize;
    //        uint32_t                                samples;
    //        VkImageTiling                        tiling;
    //        VkFlags                               usage;                      // VkImageUsageFlags
    //        VkFlags                               flags;                      // VkImageCreateFlags
    //    } VkImageCreateInfo;

    VkImageCreateInfo imageCreateInfo = {};
    imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
    imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
    imageCreateInfo.format = fmt;
    imageCreateInfo.arraySize = 1;
    imageCreateInfo.extent.width = w;
    imageCreateInfo.extent.height = h;
    imageCreateInfo.extent.depth = 1;
    imageCreateInfo.mipLevels = mipCount;
    imageCreateInfo.samples = 1;
    if (image_fmt.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
        imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
    }
    else if (image_fmt.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
        imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
    }
    else {
        ASSERT_TRUE(false) << "Cannot find supported tiling format - Exiting";
    }

    // Image usage flags
    //        VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT                       = 0x00000008,
    //typedef enum VkImageUsageFlags_
    //{
    //    VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT                      = 0x00000001,   // Can be used as a source of transfer operations
    //    VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT                 = 0x00000002,   // Can be used as a destination of transfer operations
    //    VK_IMAGE_USAGE_SAMPLED_BIT                              = 0x00000004,   // Can be sampled from (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)
    //    VK_IMAGE_USAGE_STORAGE_BIT                              = 0x00000008,   // Can be used as storage image (STORAGE_IMAGE descriptor type)
    //    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT                     = 0x00000010,   // Can be used as framebuffer color attachment
    //    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT                        = 0x00000020,   // Can be used as framebuffer depth/stencil attachment
    //    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT                 = 0x00000040,   // Image data not needed outside of rendering
    //    } VkImageUsageFlags;
    imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
                            VK_IMAGE_USAGE_SAMPLED_BIT;

    //    VkResult VKAPI vkCreateImage(
    //        VkDevice                                  device,
    //        const VkImageCreateInfo*                pCreateInfo,
    //        VkImage*                                  pImage);
    err = vkCreateImage(device(), &imageCreateInfo, &m_image);
    ASSERT_VK_SUCCESS(err);

    VkMemoryRequirements mem_req;

    VkMemoryAllocInfo mem_info = {};
    mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
    mem_info.pNext = NULL;

    err = vkGetImageMemoryRequirements(device(), m_image, &mem_req);
    ASSERT_VK_SUCCESS(err);

    ASSERT_NE(0, mem_req.size) << "vkGetObjectMemoryRequirements (Image): Failed - expect images to require memory";
    mem_info.allocationSize = mem_req.size;
    mem_info.memoryTypeIndex = 0;

    err = m_device->phy().set_memory_type(mem_req.memoryTypeBits, &mem_info, 0);
    ASSERT_VK_SUCCESS(err);

    /* allocate memory */
    err = vkAllocMemory(device(), &mem_info, &m_image_mem);
    ASSERT_VK_SUCCESS(err);

    /* bind memory */
    err = vkBindImageMemory(device(), m_image, m_image_mem, 0);
    ASSERT_VK_SUCCESS(err);
}

void VkImageTest::DestroyImage()
{
    // All done with image object and memory, clean up
    vkDestroyImage(device(), m_image);
    vkFreeMemory(device(), m_image_mem);
}

void VkImageTest::CreateImageView(VkImageViewCreateInfo *pCreateInfo,
                                   VkImageView *pView)
{
    pCreateInfo->image = this->m_image;
    ASSERT_VK_SUCCESS(vkCreateImageView(device(), pCreateInfo, pView));
}

void VkImageTest::DestroyImageView(VkImageView imageView)
{
    vkDestroyImageView(device(), imageView);
}

TEST_F(VkImageTest, CreateImageViewTest) {
    VkFormat fmt;
    VkImageView imageView;

    fmt = VK_FORMAT_R8G8B8A8_UINT;

    CreateImage(512, 256);

    //    typedef struct VkImageViewCreateInfo_
    //    {
    //        VkStructureType                      sType;                  // Must be VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
    //        const void*                             pNext;                  // Pointer to next structure
    //        VkImage                               image;
    //        VkImageViewType                     viewType;
    //        VkFormat                              format;
    //        VkChannelMapping                     channels;
    //        VkImageSubresourceRange             subresourceRange;
    //        float                                   minLod;
    //    } VkImageViewCreateInfo;
    VkImageViewCreateInfo viewInfo = {};
    viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
    viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
    viewInfo.format = fmt;

    viewInfo.channels.r = VK_CHANNEL_SWIZZLE_R;
    viewInfo.channels.g = VK_CHANNEL_SWIZZLE_G;
    viewInfo.channels.b = VK_CHANNEL_SWIZZLE_B;
    viewInfo.channels.a = VK_CHANNEL_SWIZZLE_A;

    viewInfo.subresourceRange.baseArrayLayer = 0;
    viewInfo.subresourceRange.arraySize = 1;
    viewInfo.subresourceRange.baseMipLevel = 0;
    viewInfo.subresourceRange.mipLevels = 1;
    viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;

    //    VkResult VKAPI vkCreateImageView(
    //        VkDevice                                  device,
    //        const VkImageViewCreateInfo*           pCreateInfo,
    //        VkImageView*                             pView);

    CreateImageView(&viewInfo, &imageView);

    DestroyImageView(imageView);
    DestroyImage();
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    vk_testing::set_error_callback(test_error_callback);
    return RUN_ALL_TESTS();
}
<commit_msg>tests: cleanup valgrind errors<commit_after>// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

//  VK tests
//
//  Copyright (C) 2014 LunarG, Inc.
//
//  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.

// Verify VK driver initialization

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#include <vulkan.h>
#include "gtest-1.7.0/include/gtest/gtest.h"
#include "vktestbinding.h"
#include "test_common.h"

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))

class VkImageTest : public ::testing::Test {
public:
    void CreateImage(uint32_t w, uint32_t h);
    void DestroyImage();

    void CreateImageView(VkImageViewCreateInfo* pCreateInfo,
                         VkImageView* pView);
    void DestroyImageView(VkImageView imageView);
    VkDevice device() {return m_device->handle();}

protected:
    vk_testing::Device *m_device;
    VkApplicationInfo app_info;
    VkPhysicalDevice objs[16];
    uint32_t gpu_count;
    VkInstance inst;
    VkImage m_image;
    VkDeviceMemory m_image_mem;

    virtual void SetUp() {
        VkResult err;

        this->app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
        this->app_info.pNext = NULL;
        this->app_info.pAppName = "base";
        this->app_info.appVersion = 1;
        this->app_info.pEngineName = "unittest";
        this->app_info.engineVersion = 1;
        this->app_info.apiVersion = VK_API_VERSION;
        VkInstanceCreateInfo inst_info = {};
        inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        inst_info.pNext = NULL;
        inst_info.pAppInfo = &app_info;
        inst_info.pAllocCb = NULL;
        inst_info.layerCount = 0;
        inst_info.ppEnabledLayerNames = NULL;
        inst_info.extensionCount = 0;
        inst_info.ppEnabledExtensionNames = NULL;
        err = vkCreateInstance(&inst_info, &this->inst);
        ASSERT_VK_SUCCESS(err);
        err = vkEnumeratePhysicalDevices(this->inst, &this->gpu_count, NULL);
        ASSERT_VK_SUCCESS(err);
        ASSERT_LE(this->gpu_count, ARRAY_SIZE(objs)) << "Too many GPUs";
        err = vkEnumeratePhysicalDevices(this->inst, &this->gpu_count, objs);
        ASSERT_VK_SUCCESS(err);
        ASSERT_GE(this->gpu_count, 1) << "No GPU available";

        this->m_device = new vk_testing::Device(objs[0]);
        this->m_device->init();
    }

    virtual void TearDown() {
        delete this->m_device;
        vkDestroyInstance(this->inst);
    }
};

void VkImageTest::CreateImage(uint32_t w, uint32_t h)
{
    VkResult err;
    uint32_t mipCount;
    VkFormat fmt;
    VkFormatProperties image_fmt;

    mipCount = 0;

    uint32_t _w = w;
    uint32_t _h = h;
    while( ( _w > 0 ) || ( _h > 0 ) )
    {
        _w >>= 1;
        _h >>= 1;
        mipCount++;
    }

    fmt = VK_FORMAT_R8G8B8A8_UINT;
    // TODO: Pick known good format rather than just expect common format
    /*
     * XXX: What should happen if given NULL HANDLE for the pData argument?
     * We're not requesting VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS so there is
     * an expectation that pData is a valid pointer.
     * However, why include a returned size value? That implies that the
     * amount of data may vary and that doesn't work well for using a
     * fixed structure.
     */
    err = vkGetPhysicalDeviceFormatProperties(this->objs[0], fmt, &image_fmt);
    ASSERT_VK_SUCCESS(err);

    //    typedef struct VkImageCreateInfo_
    //    {
    //        VkStructureType                      sType;                      // Must be VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
    //        const void*                             pNext;                      // Pointer to next structure.
    //        VkImageType                          imageType;
    //        VkFormat                              format;
    //        VkExtent3D                            extent;
    //        uint32_t                                mipLevels;
    //        uint32_t                                arraySize;
    //        uint32_t                                samples;
    //        VkImageTiling                        tiling;
    //        VkFlags                               usage;                      // VkImageUsageFlags
    //        VkFlags                               flags;                      // VkImageCreateFlags
    //    } VkImageCreateInfo;

    VkImageCreateInfo imageCreateInfo = {};
    imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
    imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
    imageCreateInfo.format = fmt;
    imageCreateInfo.arraySize = 1;
    imageCreateInfo.extent.width = w;
    imageCreateInfo.extent.height = h;
    imageCreateInfo.extent.depth = 1;
    imageCreateInfo.mipLevels = mipCount;
    imageCreateInfo.samples = 1;
    if (image_fmt.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
        imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
    }
    else if (image_fmt.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
        imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
    }
    else {
        ASSERT_TRUE(false) << "Cannot find supported tiling format - Exiting";
    }

    // Image usage flags
    //        VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT                       = 0x00000008,
    //typedef enum VkImageUsageFlags_
    //{
    //    VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT                      = 0x00000001,   // Can be used as a source of transfer operations
    //    VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT                 = 0x00000002,   // Can be used as a destination of transfer operations
    //    VK_IMAGE_USAGE_SAMPLED_BIT                              = 0x00000004,   // Can be sampled from (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)
    //    VK_IMAGE_USAGE_STORAGE_BIT                              = 0x00000008,   // Can be used as storage image (STORAGE_IMAGE descriptor type)
    //    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT                     = 0x00000010,   // Can be used as framebuffer color attachment
    //    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT                        = 0x00000020,   // Can be used as framebuffer depth/stencil attachment
    //    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT                 = 0x00000040,   // Image data not needed outside of rendering
    //    } VkImageUsageFlags;
    imageCreateInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
                            VK_IMAGE_USAGE_SAMPLED_BIT;

    //    VkResult VKAPI vkCreateImage(
    //        VkDevice                                  device,
    //        const VkImageCreateInfo*                pCreateInfo,
    //        VkImage*                                  pImage);
    err = vkCreateImage(device(), &imageCreateInfo, &m_image);
    ASSERT_VK_SUCCESS(err);

    VkMemoryRequirements mem_req;

    VkMemoryAllocInfo mem_info = {};
    mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO;
    mem_info.pNext = NULL;

    err = vkGetImageMemoryRequirements(device(), m_image, &mem_req);
    ASSERT_VK_SUCCESS(err);

    ASSERT_NE(0, mem_req.size) << "vkGetObjectMemoryRequirements (Image): Failed - expect images to require memory";
    mem_info.allocationSize = mem_req.size;
    mem_info.memoryTypeIndex = 0;

    err = m_device->phy().set_memory_type(mem_req.memoryTypeBits, &mem_info, 0);
    ASSERT_VK_SUCCESS(err);

    /* allocate memory */
    err = vkAllocMemory(device(), &mem_info, &m_image_mem);
    ASSERT_VK_SUCCESS(err);

    /* bind memory */
    err = vkBindImageMemory(device(), m_image, m_image_mem, 0);
    ASSERT_VK_SUCCESS(err);
}

void VkImageTest::DestroyImage()
{
    // All done with image object and memory, clean up
    vkDestroyImage(device(), m_image);
    vkFreeMemory(device(), m_image_mem);
}

void VkImageTest::CreateImageView(VkImageViewCreateInfo *pCreateInfo,
                                   VkImageView *pView)
{
    VkResult err;
    pCreateInfo->image = this->m_image;
    err = vkCreateImageView(device(), pCreateInfo, pView);
    ASSERT_VK_SUCCESS(err);
}

void VkImageTest::DestroyImageView(VkImageView imageView)
{
    vkDestroyImageView(device(), imageView);
}

TEST_F(VkImageTest, CreateImageViewTest) {
    VkFormat fmt;
    VkImageView imageView;

    fmt = VK_FORMAT_R8G8B8A8_UINT;

    CreateImage(512, 256);

    //    typedef struct VkImageViewCreateInfo_
    //    {
    //        VkStructureType                      sType;                  // Must be VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
    //        const void*                             pNext;                  // Pointer to next structure
    //        VkImage                               image;
    //        VkImageViewType                     viewType;
    //        VkFormat                              format;
    //        VkChannelMapping                     channels;
    //        VkImageSubresourceRange             subresourceRange;
    //        float                                   minLod;
    //    } VkImageViewCreateInfo;
    VkImageViewCreateInfo viewInfo = {};
    viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
    viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
    viewInfo.format = fmt;

    viewInfo.channels.r = VK_CHANNEL_SWIZZLE_R;
    viewInfo.channels.g = VK_CHANNEL_SWIZZLE_G;
    viewInfo.channels.b = VK_CHANNEL_SWIZZLE_B;
    viewInfo.channels.a = VK_CHANNEL_SWIZZLE_A;

    viewInfo.subresourceRange.baseArrayLayer = 0;
    viewInfo.subresourceRange.arraySize = 1;
    viewInfo.subresourceRange.baseMipLevel = 0;
    viewInfo.subresourceRange.mipLevels = 1;
    viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;

    //    VkResult VKAPI vkCreateImageView(
    //        VkDevice                                  device,
    //        const VkImageViewCreateInfo*           pCreateInfo,
    //        VkImageView*                             pView);

    CreateImageView(&viewInfo, &imageView);

    DestroyImageView(imageView);
    DestroyImage();
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    vk_testing::set_error_callback(test_error_callback);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

// If you experience failures in debug mode (singular iterator used),
// then you probably have a problem with Boost.  See
// http://groups.google.com/group/boost-list/browse_thread/thread/5eecec53397d0c52/05b272fb9a9000c5:
//
//   The code can be fixed (although there may be other occurrences of
//   similar problems) by changing around line 220 on asio/detail/
//   hash_map.hpp from:
//        // Update number of buckets and initialise all buckets to empty.
//        buckets_.resize(num_buckets);
//        for (std::size_t i = 0; i < buckets_.size(); ++i)
//          buckets_[i].first = buckets_[i].last = end;
//   to:
//        // Update number of buckets and initialise all buckets to empty.
//        bucket_type bucket;
//        bucket.first = bucket.last = end;
//        buckets_.resize(num_buckets, bucket);
//

#include <libport/test.hh>
#include <libport/sysexits.hh>

using libport::test_suite;

#include <libport/asio.hh>
#include <libport/lexical-cast.hh>
#include <libport/thread.hh>
#include <libport/utime.hh>
#include <libport/unistd.h>

bool abort_ctor = false;

const char* msg = "coincoin\n";

// On OSX:
//   listen            connect        status
// "127.0.0.1"       "127.0.0.1"       PASS  IPv4
// "localhost"       "localhost"       PASS  IPv6
// ""                "localhost"       PASS  IPv6
// ""                "127.0.0.1"       FAIL
// ""                ""                PASS  IPv6
static const char* listen_host = "127.0.0.1";
static const char* connect_host = "127.0.0.1";

template<class T>
void
hold_for(T, libport::utime_t duration)
{
  usleep(duration);
  BOOST_TEST_MESSAGE("Done holding your T");
}

void
delayed_response(boost::shared_ptr<libport::UDPLink> l,
                 libport::utime_t duration)
{
  usleep(duration);
  l->reply("hop hop\n");
}

// Hack until we can kill listenig sockets.
static bool enable_delay = false;
void reply_delay(const void*, int,
                 boost::shared_ptr<libport::UDPLink> l,
                 libport::utime_t duration)
{
  libport::startThread(boost::bind(&delayed_response, l, duration));
}

void echo(const void* d, int s, boost::shared_ptr<libport::UDPLink> l)
{
  if (enable_delay)
    reply_delay(d, s, l, 500000);
  else
    l->reply(d, s);
}

/*-------------.
| TestSocket.  |
`-------------*/

class TestSocket: public libport::Socket
{
public:
  TestSocket()
    : nRead(0), echo(false), dump(false), destroyOnError(true)
  {
    BOOST_CHECK(!abort_ctor);
    nInstance++;
  }

  TestSocket(bool echo, bool dump)
    : nRead(0), echo(echo), dump(dump), destroyOnError(true)
  {
    BOOST_CHECK(!abort_ctor);
    nInstance++;
  }

  virtual ~TestSocket()
  {
    nInstance--;
    // BOOST_TEST_MESSAGE(this << " dying, in " << K_get()
    //                    << " lasterror=" << lastError.message());
    // aver(false);
  }

  size_t onRead(const void* data, size_t size)
  {
    nRead++;
    //BOOST_TEST_MESSAGE(this << " read " << size);
    if (echo)
      write(data, size);
    if (dump)
      received += std::string((const char*)data, size);
    return size;
  }

  void onError(boost::system::error_code erc)
  {
    lastError = erc;
    if (destroyOnError)
      destroy();
  }

  // Number of times read callback was called
  size_t nRead;
  // Echo back what is received.
  bool echo;
  // Store what is received in received.
  bool dump;
  // Destroy socket onError.
  bool destroyOnError;
  std::string received;
  boost::system::error_code lastError;
  static TestSocket* factory()
  {
    return lastInstance = new TestSocket();
  }
  static TestSocket* factoryEx(bool echo, bool dump)
  {
    return lastInstance = new TestSocket(echo, dump);
  }
  static size_t nInstance;
  // Last factory-created instance.
  static TestSocket* lastInstance;
};

size_t TestSocket::nInstance = 0u;
TestSocket* TestSocket::lastInstance = 0;

// Delay in microseconds used to sleep when something asynchronous
// is happening.
static const useconds_t delay = 200000;

static const int AVAIL_PORT = 7890;
static const std::string S_AVAIL_PORT = string_cast(AVAIL_PORT);

void test_one(bool proto)
{
  TestSocket* client = new TestSocket(false, true);
  boost::system::error_code err
    = client->connect(connect_host, S_AVAIL_PORT, proto);
  BOOST_REQUIRE_MESSAGE(!err, err.message());
  BOOST_CHECK_NO_THROW(client->send(msg));
  usleep(delay);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, proto ? 1u : 2u);
  BOOST_CHECK_EQUAL(client->received, msg);
  if (!proto)
    BOOST_CHECK_EQUAL(TestSocket::lastInstance->received,
                      msg);
  BOOST_CHECK_EQUAL(client->getRemotePort(), AVAIL_PORT);
  if (!proto)
    BOOST_CHECK_EQUAL(TestSocket::lastInstance->getLocalPort(),
                      AVAIL_PORT);
  if (!proto)
    BOOST_CHECK_EQUAL(TestSocket::lastInstance->getRemotePort(),
                      client->getLocalPort());
  // Close client-end. Should send error both ways and destroy all sockets.
  client->close();
  usleep(delay);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);
}

static
void
test()
{
  // Basic TCP
  BOOST_TEST_MESSAGE("##Safe destruction");
  boost::system::error_code err;
  TestSocket* s = new TestSocket(false, false);
  s->connect(connect_host, S_AVAIL_PORT, false);
  s->destroy();
  usleep(delay);
  libport::Socket* h = new libport::Socket();
  // Try listening on an IP that is not ours.
  BOOST_TEST_MESSAGE("Invalid IP in listen()");
  err = h->listen(boost::bind(&TestSocket::factoryEx, true, true),
                  "1.2.3.4", "1212", false);
  BOOST_CHECK(err);
  err = h->listen(boost::bind(&TestSocket::factoryEx, true, true),
                  listen_host, S_AVAIL_PORT, false);
  BOOST_CHECK_MESSAGE(!err, err.message());
  BOOST_CHECK_EQUAL(h->getLocalPort(), AVAIL_PORT);

  BOOST_TEST_MESSAGE("##One client");
  test_one(false);
  BOOST_CHECK_EQUAL(h->getLocalPort(), AVAIL_PORT);
  test_one(false);
  BOOST_CHECK_EQUAL(h->getLocalPort(), AVAIL_PORT);
  test_one(false);
  BOOST_TEST_MESSAGE("Socket on stack");
  {
    TestSocket s(false, true);
    err = s.connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(!err, err.message());
    s.send(msg);
    usleep(delay);
  }
  usleep(delay*2);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);

  test_one(false);
  BOOST_TEST_MESSAGE("##many clients");
  std::vector<TestSocket*> clients;
  for (int i=0; i<10; i++)
  {
    TestSocket* client = new TestSocket(false, true);
    err = client->connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(!err, err.message());
    client->send(msg);
    clients.push_back(client);
  }
  usleep(delay*3);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 20u);
  foreach(TestSocket* s, clients)
  {
    BOOST_CHECK_EQUAL(s->received, msg);
    s->close();
  }
  usleep(delay*3);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);

  BOOST_TEST_MESSAGE("##Failing connections");
  {
    TestSocket* client = new TestSocket();
    err = client->connect("auunsinsr.nosuch.hostaufisgiu.com.", "20000", false);
    BOOST_CHECK_MESSAGE(err, err.message());

    err = client->connect(connect_host, "nosuchport", false);
    BOOST_CHECK_MESSAGE(err, err.message());

    // Try to reuse that wasted socket.
    err = client->connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(!err, err.message());
    // Destroy without closing.
    client->destroy();
    usleep(delay);
    BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);
  }

  // Timeout
  BOOST_TEST_MESSAGE("##Timeout connect");
  {
    TestSocket* client = new TestSocket();
    libport::utime_t start = libport::utime();
    err = client->connect("1.1.1.1", "10000", false, 1000000);
    BOOST_CHECK_MESSAGE(err, err.message());
    libport::utime_t timeout = libport::utime() - start;
    // Give it a good margin.
    BOOST_CHECK_LT(timeout, 1400000);
    client->destroy();
  }

  BOOST_TEST_MESSAGE("##Destruction locking");
  {
    TestSocket* client = new TestSocket();
    err = client->connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(!err, err.message());
    usleep(delay);
    libport::startThread(
      boost::bind(&hold_for<libport::Destructible::DestructionLock>,
                  client->getDestructionLock(),
                  1000000));
    client->destroy();
    usleep(500000);
    // There can be 1 or 2 sockets at this point. Client must be still
    // alive because of the lock, but server might have died.
    BOOST_CHECK_MESSAGE(TestSocket::nInstance, TestSocket::nInstance);
    usleep(500000+delay);
    BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);
  }

  BOOST_TEST_MESSAGE("Destroy listener");
  {
    h->close();
    usleep(delay);
    TestSocket* client = new TestSocket();
    abort_ctor = true;
    err = client->connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(err, err.message());
    client->destroy();
    h->destroy();
    usleep(delay);
    abort_ctor = false;
  }

  BOOST_TEST_MESSAGE("##UDP");
  {
    libport::Socket::listenUDP(listen_host, S_AVAIL_PORT, &echo, err);
    BOOST_CHECK_MESSAGE(!err, err.message());
    test_one(true);
    usleep(delay);
    test_one(true);

    TestSocket* client = new TestSocket();
    err = client->connect("auunsinsr.nosuch.hostaufisgiu.com.", "20000", true);
    BOOST_CHECK_MESSAGE(err, err.message());

    err = client->connect(connect_host, "nosuchport", true);
    BOOST_CHECK_MESSAGE(err, err.message());

    // Try to reuse that wasted socket.
    err = client->connect(connect_host, S_AVAIL_PORT, true);
    BOOST_CHECK_MESSAGE(!err, err.message());
    // Destroy without closing.
    client->destroy();
    usleep(delay);
    BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);

    // Check one-write-one-packet semantic
    client = new TestSocket(false, true);
    err = client->connect(connect_host, S_AVAIL_PORT, true);
    BOOST_CHECK_MESSAGE(!err, err.message());
    client->send("coin");
    client->send("pan");
    usleep(delay*2);
    BOOST_CHECK_EQUAL(client->received, "coinpan");
    BOOST_CHECK_EQUAL(client->nRead, 2u);

    enable_delay = true;
    client = new TestSocket(false, true);
    err = client->connect(connect_host, S_AVAIL_PORT, true);
    BOOST_CHECK_MESSAGE(!err, err.message());
    client->send("coin");
    usleep(500000+delay);
    BOOST_CHECK_EQUAL(client->received, "hop hop\n");
  }
}

static void test_pipe()
{
  TestSocket* s1 = new TestSocket(false, true);
  TestSocket* s2 = new TestSocket(false, true);
  s1->destroyOnError = false;
  s2->destroyOnError = false;
  libport::makePipe(std::make_pair(s2, s1));

  // First element is reader, second is writer.
  s1->send("canard");
  usleep(delay*2);
  BOOST_CHECK_EQUAL("canard", s2->received);
  s1->send("coin");
  usleep(delay*2);
  BOOST_CHECK_EQUAL(s2->received, "canardcoin");
  usleep(delay);
  // FIXME: fix the bug that SEGV when a pipe socket is destroyed.
  s1->destroy();
  s2->destroy();
  usleep(delay*2);
}

test_suite*
init_test_suite()
{
  skip_if("Qemu");
  skip_if("Wine");
  test_suite* suite = BOOST_TEST_SUITE("libport::asio test suite");
  suite->add(BOOST_TEST_CASE(test));
  suite->add(BOOST_TEST_CASE(test_pipe));
  return suite;
}
<commit_msg>Libport.Asio: split large test case.<commit_after>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

// If you experience failures in debug mode (singular iterator used),
// then you probably have a problem with Boost.  See
// http://groups.google.com/group/boost-list/browse_thread/thread/5eecec53397d0c52/05b272fb9a9000c5:
//
//   The code can be fixed (although there may be other occurrences of
//   similar problems) by changing around line 220 on asio/detail/
//   hash_map.hpp from:
//        // Update number of buckets and initialise all buckets to empty.
//        buckets_.resize(num_buckets);
//        for (std::size_t i = 0; i < buckets_.size(); ++i)
//          buckets_[i].first = buckets_[i].last = end;
//   to:
//        // Update number of buckets and initialise all buckets to empty.
//        bucket_type bucket;
//        bucket.first = bucket.last = end;
//        buckets_.resize(num_buckets, bucket);
//

#include <libport/test.hh>
#include <libport/sysexits.hh>

using libport::test_suite;

#include <libport/asio.hh>
#include <libport/lexical-cast.hh>
#include <libport/thread.hh>
#include <libport/utime.hh>
#include <libport/unistd.h>

bool abort_ctor = false;

const char* msg = "coincoin\n";

// On OSX:
//   listen            connect        status
// "127.0.0.1"       "127.0.0.1"       PASS  IPv4
// "localhost"       "localhost"       PASS  IPv6
// ""                "localhost"       PASS  IPv6
// ""                "127.0.0.1"       FAIL
// ""                ""                PASS  IPv6
static const char* listen_host = "127.0.0.1";
static const char* connect_host = "127.0.0.1";

template<class T>
void
hold_for(T, libport::utime_t duration)
{
  usleep(duration);
  BOOST_TEST_MESSAGE("Done holding your T");
}

void
delayed_response(boost::shared_ptr<libport::UDPLink> l,
                 libport::utime_t duration)
{
  usleep(duration);
  l->reply("hop hop\n");
}

// Hack until we can kill listenig sockets.
static bool enable_delay = false;
void reply_delay(const void*, int,
                 boost::shared_ptr<libport::UDPLink> l,
                 libport::utime_t duration)
{
  libport::startThread(boost::bind(&delayed_response, l, duration));
}

void echo(const void* d, int s, boost::shared_ptr<libport::UDPLink> l)
{
  if (enable_delay)
    reply_delay(d, s, l, 500000);
  else
    l->reply(d, s);
}

/*-------------.
| TestSocket.  |
`-------------*/

class TestSocket: public libport::Socket
{
public:
  TestSocket()
    : nRead(0), echo(false), dump(false), destroyOnError(true)
  {
    BOOST_CHECK(!abort_ctor);
    nInstance++;
  }

  TestSocket(bool echo, bool dump)
    : nRead(0), echo(echo), dump(dump), destroyOnError(true)
  {
    BOOST_CHECK(!abort_ctor);
    nInstance++;
  }

  virtual ~TestSocket()
  {
    nInstance--;
    // BOOST_TEST_MESSAGE(this << " dying, in " << K_get()
    //                    << " lasterror=" << lastError.message());
    // aver(false);
  }

  size_t onRead(const void* data, size_t size)
  {
    nRead++;
    //BOOST_TEST_MESSAGE(this << " read " << size);
    if (echo)
      write(data, size);
    if (dump)
      received += std::string((const char*)data, size);
    return size;
  }

  void onError(boost::system::error_code erc)
  {
    lastError = erc;
    if (destroyOnError)
      destroy();
  }

  // Number of times read callback was called
  size_t nRead;
  // Echo back what is received.
  bool echo;
  // Store what is received in received.
  bool dump;
  // Destroy socket onError.
  bool destroyOnError;
  std::string received;
  boost::system::error_code lastError;
  static TestSocket* factory()
  {
    return lastInstance = new TestSocket();
  }
  static TestSocket* factoryEx(bool echo, bool dump)
  {
    return lastInstance = new TestSocket(echo, dump);
  }
  static size_t nInstance;
  // Last factory-created instance.
  static TestSocket* lastInstance;
};

size_t TestSocket::nInstance = 0u;
TestSocket* TestSocket::lastInstance = 0;

// Delay in microseconds used to sleep when something asynchronous
// is happening.
static const useconds_t delay = 200000;

static const int AVAIL_PORT = 7890;
static const std::string S_AVAIL_PORT = string_cast(AVAIL_PORT);

void test_one(bool proto)
{
  TestSocket* client = new TestSocket(false, true);
  boost::system::error_code err
    = client->connect(connect_host, S_AVAIL_PORT, proto);
  BOOST_REQUIRE_MESSAGE(!err, err.message());
  BOOST_CHECK_NO_THROW(client->send(msg));
  usleep(delay);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, proto ? 1u : 2u);
  BOOST_CHECK_EQUAL(client->received, msg);
  if (!proto)
    BOOST_CHECK_EQUAL(TestSocket::lastInstance->received,
                      msg);
  BOOST_CHECK_EQUAL(client->getRemotePort(), AVAIL_PORT);
  if (!proto)
    BOOST_CHECK_EQUAL(TestSocket::lastInstance->getLocalPort(),
                      AVAIL_PORT);
  if (!proto)
    BOOST_CHECK_EQUAL(TestSocket::lastInstance->getRemotePort(),
                      client->getLocalPort());
  // Close client-end. Should send error both ways and destroy all sockets.
  client->close();
  usleep(delay);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);
}

static
void
test_safe_destruction()
{
  BOOST_TEST_MESSAGE("##Safe destruction");
  TestSocket* s = new TestSocket(false, false);
  s->connect(connect_host, S_AVAIL_PORT, false);
  s->destroy();
  usleep(delay);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);
}

static
void
test()
{
  // Basic TCP
  boost::system::error_code err;
  libport::Socket* h = new libport::Socket();
  // Try listening on an IP that is not ours.
  BOOST_TEST_MESSAGE("Invalid IP in listen()");
  err = h->listen(boost::bind(&TestSocket::factoryEx, true, true),
                  "1.2.3.4", "1212", false);
  BOOST_CHECK(err);
  err = h->listen(boost::bind(&TestSocket::factoryEx, true, true),
                  listen_host, S_AVAIL_PORT, false);
  BOOST_CHECK_MESSAGE(!err, err.message());
  BOOST_CHECK_EQUAL(h->getLocalPort(), AVAIL_PORT);

  BOOST_TEST_MESSAGE("##One client");
  test_one(false);
  BOOST_CHECK_EQUAL(h->getLocalPort(), AVAIL_PORT);
  test_one(false);
  BOOST_CHECK_EQUAL(h->getLocalPort(), AVAIL_PORT);
  test_one(false);
  BOOST_TEST_MESSAGE("Socket on stack");
  {
    TestSocket s(false, true);
    err = s.connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(!err, err.message());
    s.send(msg);
    usleep(delay);
  }
  usleep(delay*2);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);

  test_one(false);
  BOOST_TEST_MESSAGE("##many clients");
  std::vector<TestSocket*> clients;
  for (int i=0; i<10; i++)
  {
    TestSocket* client = new TestSocket(false, true);
    err = client->connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(!err, err.message());
    client->send(msg);
    clients.push_back(client);
  }
  usleep(delay*3);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 20u);
  foreach(TestSocket* s, clients)
  {
    BOOST_CHECK_EQUAL(s->received, msg);
    s->close();
  }
  usleep(delay*3);
  BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);

  BOOST_TEST_MESSAGE("##Failing connections");
  {
    TestSocket* client = new TestSocket();
    err = client->connect("auunsinsr.nosuch.hostaufisgiu.com.", "20000", false);
    BOOST_CHECK_MESSAGE(err, err.message());

    err = client->connect(connect_host, "nosuchport", false);
    BOOST_CHECK_MESSAGE(err, err.message());

    // Try to reuse that wasted socket.
    err = client->connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(!err, err.message());
    // Destroy without closing.
    client->destroy();
    usleep(delay);
    BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);
  }

  // Timeout
  BOOST_TEST_MESSAGE("##Timeout connect");
  {
    TestSocket* client = new TestSocket();
    libport::utime_t start = libport::utime();
    err = client->connect("1.1.1.1", "10000", false, 1000000);
    BOOST_CHECK_MESSAGE(err, err.message());
    libport::utime_t timeout = libport::utime() - start;
    // Give it a good margin.
    BOOST_CHECK_LT(timeout, 1400000);
    client->destroy();
  }

  BOOST_TEST_MESSAGE("##Destruction locking");
  {
    TestSocket* client = new TestSocket();
    err = client->connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(!err, err.message());
    usleep(delay);
    libport::startThread(
      boost::bind(&hold_for<libport::Destructible::DestructionLock>,
                  client->getDestructionLock(),
                  1000000));
    client->destroy();
    usleep(500000);
    // There can be 1 or 2 sockets at this point. Client must be still
    // alive because of the lock, but server might have died.
    BOOST_CHECK_MESSAGE(TestSocket::nInstance, TestSocket::nInstance);
    usleep(500000+delay);
    BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);
  }

  BOOST_TEST_MESSAGE("Destroy listener");
  {
    h->close();
    usleep(delay);
    TestSocket* client = new TestSocket();
    abort_ctor = true;
    err = client->connect(connect_host, S_AVAIL_PORT, false);
    BOOST_CHECK_MESSAGE(err, err.message());
    client->destroy();
    h->destroy();
    usleep(delay);
    abort_ctor = false;
  }

  BOOST_TEST_MESSAGE("##UDP");
  {
    libport::Socket::listenUDP(listen_host, S_AVAIL_PORT, &echo, err);
    BOOST_CHECK_MESSAGE(!err, err.message());
    test_one(true);
    usleep(delay);
    test_one(true);

    TestSocket* client = new TestSocket();
    err = client->connect("auunsinsr.nosuch.hostaufisgiu.com.", "20000", true);
    BOOST_CHECK_MESSAGE(err, err.message());

    err = client->connect(connect_host, "nosuchport", true);
    BOOST_CHECK_MESSAGE(err, err.message());

    // Try to reuse that wasted socket.
    err = client->connect(connect_host, S_AVAIL_PORT, true);
    BOOST_CHECK_MESSAGE(!err, err.message());
    // Destroy without closing.
    client->destroy();
    usleep(delay);
    BOOST_CHECK_EQUAL(TestSocket::nInstance, 0u);

    // Check one-write-one-packet semantic
    client = new TestSocket(false, true);
    err = client->connect(connect_host, S_AVAIL_PORT, true);
    BOOST_CHECK_MESSAGE(!err, err.message());
    client->send("coin");
    client->send("pan");
    usleep(delay*2);
    BOOST_CHECK_EQUAL(client->received, "coinpan");
    BOOST_CHECK_EQUAL(client->nRead, 2u);

    enable_delay = true;
    client = new TestSocket(false, true);
    err = client->connect(connect_host, S_AVAIL_PORT, true);
    BOOST_CHECK_MESSAGE(!err, err.message());
    client->send("coin");
    usleep(500000+delay);
    BOOST_CHECK_EQUAL(client->received, "hop hop\n");
  }
}

static void test_pipe()
{
  TestSocket* s1 = new TestSocket(false, true);
  TestSocket* s2 = new TestSocket(false, true);
  s1->destroyOnError = false;
  s2->destroyOnError = false;
  libport::makePipe(std::make_pair(s2, s1));

  // First element is reader, second is writer.
  s1->send("canard");
  usleep(delay*2);
  BOOST_CHECK_EQUAL("canard", s2->received);
  s1->send("coin");
  usleep(delay*2);
  BOOST_CHECK_EQUAL(s2->received, "canardcoin");
  usleep(delay);
  // FIXME: fix the bug that SEGV when a pipe socket is destroyed.
  s1->destroy();
  s2->destroy();
  usleep(delay*2);
}

test_suite*
init_test_suite()
{
  skip_if("Qemu");
  skip_if("Wine");
  test_suite* suite = BOOST_TEST_SUITE("libport::asio test suite");
  suite->add(BOOST_TEST_CASE(test_safe_destruction));
  suite->add(BOOST_TEST_CASE(test));
  suite->add(BOOST_TEST_CASE(test_pipe));
  return suite;
}
<|endoftext|>


<commit_before>#include "glwidget.h"

#include <math.h>

#include <QKeyEvent>
#include <QTimer>
#include <QVector3D>
#include <QGLBuffer>
#include <QGLShader>
#include <QGLShaderProgram>

#include "color.h"
#include "emitter.h"

#include "camerashader.h"
#include "renderers/rend_vbo.h"

GLWidget::GLWidget(QWidget *parent) :
  QGLWidget(parent),
  _camera(NULL),
  _timer(),
  _qtimer(NULL),
  _vertShader(NULL),
  _fragShader(NULL),
  _shaderProgram(NULL),
  _renderer(NULL),
  _emitterCount(0),
  _emitters() {
  for(int i = 0; i < MAX_EMITTERS; i++) {
    _emitters[i] = NULL;
  }

  // Set the animation timer
  _qtimer = new QTimer(this);
  connect(_qtimer, SIGNAL(timeout()), this, SLOT(animate()));
  _qtimer->start();

  // Fire the internal timer
  _timer.start();
}

GLWidget::~GLWidget() {
  if(_qtimer) {
    delete _qtimer;
  }
  if(_axisVertexes) {
    _axisVertexes->destroy();
    delete _axisVertexes;
  }
  if(_axisColors) {
    _axisColors->destroy();
    delete _axisColors;
  }
}

QSize GLWidget::minimumSizeHint() const {
  return QSize(80, 80);
}

QSize GLWidget::sizeHint() const {
  return QSize(600, 600);
}

int GLWidget::getVertexCount() const {
  return _renderer->vertexCount();
}

int GLWidget::addEmitter(Emitter *emitter) {
  int index;
  for(index = 0; index < MAX_EMITTERS; index++) {
    if(!_emitters[index]) {
      break;
    }
  }

  if(index == MAX_EMITTERS) {
    return -1;
  }

  _emitters[index] = emitter;
  emitter->renderer(_renderer);

  return index;
}

void GLWidget::removeEmitter(int index) {
  if(_emitters[index]) {
    _emitters[index] = NULL;
  }
}

void GLWidget::animate() {
  _timer.update();

  float elapsed = _timer.elapsed();
  for(int i = 0; i < MAX_EMITTERS; i++) {
    if(_emitters[i]) {
      _emitters[i]->update(elapsed);
    }
  }

  updateGL();
}

void GLWidget::setPitch(int val) {
  _camera->pitch(val);
}

void GLWidget::setYaw(int val) {
  _camera->yaw(val);
}

void GLWidget::setRoll(int val) {
  _camera->roll(val);
}

void GLWidget::initializeGL() {
  glClearColor(.0, .0, .0, 1.0);
  glShadeModel(GL_FLAT);

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable( GL_BLEND );
  glBlendFunc( GL_SRC_ALPHA, GL_ONE );

  // Eye candy? :3
  glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
  glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );

  initShaders();

  createAxis();

  _camera = new CameraShader(_shaderProgram);
  _renderer = new Rend_VBO(MAX_VERTEXES, _shaderProgram);
}

void GLWidget::paintGL() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  _camera->apply();

  glPointSize(4.0);

  drawAxis();
  _renderer->clear();
  for(int i = 0; i < MAX_EMITTERS; i++) {
    if(_emitters[i]) {
      _emitters[i]->draw();
    }
  }
  _renderer->draw();
}

void GLWidget::resizeGL(int w, int h) {
  projection(w, h);
  glViewport(0, 0, w, h);
}

void GLWidget::initShaders() {
  _vertShader = new QGLShader(QGLShader::Vertex);
  _fragShader = new QGLShader(QGLShader::Fragment);

  if(!_vertShader->compileSourceFile(":/vshader.glsl")) {
    qWarning() << _vertShader->log();
  }

  if(!_fragShader->compileSourceFile(":/fshader.glsl")) {
    qWarning() << _fragShader->log();
  }

  _shaderProgram = new QGLShaderProgram();
  _shaderProgram->addShader(_vertShader);
  _shaderProgram->addShader(_fragShader);

  if(!_shaderProgram->link()) {
    qWarning() << _shaderProgram->log();
  }
  else {
    _shaderProgram->bind();
  }
}

void GLWidget::createAxis() {
  Vector3D v[6];
  Color c[6];

  v[0] = Vector3D(0, 0, 0);
  v[1] = Vector3D(1, 0, 0);
  c[0] = c[1] = Color(255, 0, 0);

  v[2] = Vector3D(0, 0, 0);
  v[3] = Vector3D(0, 1, 0);
  c[2] = c[3] = Color(0, 255, 0);

  v[4] = Vector3D(0, 0, 0);
  v[5] = Vector3D(0, 0, 1);
  c[4] = c[5] = Color(0, 0, 255);

  _axisVertexes = new QGLBuffer(QGLBuffer::VertexBuffer);
  _axisVertexes->create();
  _axisVertexes->bind();
  _axisVertexes->setUsagePattern(QGLBuffer::DynamicDraw);
  _axisVertexes->allocate(v, 6 * sizeof(Vector3D));

  _axisColors = new QGLBuffer(QGLBuffer::VertexBuffer);
  _axisColors->create();
  _axisColors->bind();
  _axisColors->setUsagePattern(QGLBuffer::DynamicDraw);
  _axisColors->allocate(c,  6 * sizeof(Color));
}

void GLWidget::drawAxis(float len) {
  _axisVertexes->bind();
  _shaderProgram->enableAttributeArray("vPosition");
  _shaderProgram->setAttributeBuffer("vPosition", GL_FLOAT, 0, 3, 0);

  _axisColors->bind();
  _shaderProgram->enableAttributeArray("vColor");
  _shaderProgram->setAttributeBuffer("vColor", GL_FLOAT, 0, 4, 0);

  glDrawArrays(GL_LINES, 0, 6);
}

void GLWidget::projection(int width, int height, float size) {
  QMatrix4x4 proj;
  proj.setToIdentity();
  proj.ortho(-size,size, -size,size, -size,size);

  _shaderProgram->setUniformValue("Projection", proj);
}
<commit_msg>Improved testbed<commit_after>#include "glwidget.h"

#include <math.h>

#include <QKeyEvent>
#include <QTimer>
#include <QVector3D>
#include <QGLBuffer>
#include <QGLShader>
#include <QGLShaderProgram>

#include "color.h"
#include "emitter.h"

#include "camerashader.h"
#include "renderers/rend_vbo.h"

GLWidget::GLWidget(QWidget *parent) :
  QGLWidget(parent),
  _camera(NULL),
  _timer(),
  _qtimer(NULL),
  _vertShader(NULL),
  _fragShader(NULL),
  _shaderProgram(NULL),
  _renderer(NULL),
  _emitterCount(0),
  _emitters() {
  for(int i = 0; i < MAX_EMITTERS; i++) {
    _emitters[i] = NULL;
  }

  // Set the animation timer
  _qtimer = new QTimer(this);
  connect(_qtimer, SIGNAL(timeout()), this, SLOT(animate()));
  _qtimer->start();

  // Fire the internal timer
  _timer.start();
}

GLWidget::~GLWidget() {
  if(_qtimer) {
    delete _qtimer;
  }

  if(_shaderProgram) {
    delete _shaderProgram;
  }

  if(_vertShader) {
    delete _vertShader;
  }

  if(_fragShader) {
    delete _fragShader;
  }

  if(_axisVertexes) {
    _axisVertexes->destroy();
    delete _axisVertexes;
  }

  if(_axisColors) {
    _axisColors->destroy();
    delete _axisColors;
  }
}

QSize GLWidget::minimumSizeHint() const {
  return QSize(80, 80);
}

QSize GLWidget::sizeHint() const {
  return QSize(600, 600);
}

int GLWidget::getVertexCount() const {
  return _renderer->vertexCount();
}

int GLWidget::addEmitter(Emitter *emitter) {
  int index;
  for(index = 0; index < MAX_EMITTERS; index++) {
    if(!_emitters[index]) {
      break;
    }
  }

  if(index == MAX_EMITTERS) {
    return -1;
  }

  _emitters[index] = emitter;
  emitter->renderer(_renderer);

  return index;
}

void GLWidget::removeEmitter(int index) {
  if(_emitters[index]) {
    _emitters[index] = NULL;
  }
}

void GLWidget::animate() {
  _timer.update();

  float elapsed = _timer.elapsed();
  for(int i = 0; i < MAX_EMITTERS; i++) {
    if(_emitters[i]) {
      _emitters[i]->update(elapsed);
    }
  }

  updateGL();
}

void GLWidget::setPitch(int val) {
  _camera->pitch(val);
}

void GLWidget::setYaw(int val) {
  _camera->yaw(val);
}

void GLWidget::setRoll(int val) {
  _camera->roll(val);
}

void GLWidget::initializeGL() {
  glClearColor(.0, .0, .0, 1.0);
  glShadeModel(GL_FLAT);

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable( GL_BLEND );
  glBlendFunc( GL_SRC_ALPHA, GL_ONE );

  // Eye candy? :3
  glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
  glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );

  initShaders();

  createAxis();

  _camera = new CameraShader(_shaderProgram);
  _renderer = new Rend_VBO(MAX_VERTEXES, _shaderProgram);
}

void GLWidget::paintGL() {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  _camera->apply();

  glPointSize(4.0);

  drawAxis();
  _renderer->clear();
  for(int i = 0; i < MAX_EMITTERS; i++) {
    if(_emitters[i]) {
      _emitters[i]->draw();
    }
  }
  _renderer->draw();
}

void GLWidget::resizeGL(int w, int h) {
  projection(w, h);
  glViewport(0, 0, w, h);
}

void GLWidget::initShaders() {
  _vertShader = new QGLShader(QGLShader::Vertex);
  _fragShader = new QGLShader(QGLShader::Fragment);

  if(!_vertShader->compileSourceFile(":/vshader.glsl")) {
    qWarning() << _vertShader->log();
  }

  if(!_fragShader->compileSourceFile(":/fshader.glsl")) {
    qWarning() << _fragShader->log();
  }

  _shaderProgram = new QGLShaderProgram();
  _shaderProgram->addShader(_vertShader);
  _shaderProgram->addShader(_fragShader);

  if(!_shaderProgram->link()) {
    qWarning() << _shaderProgram->log();
  }
  else {
    _shaderProgram->bind();
  }
}

void GLWidget::createAxis() {
  Vector3D v[6];
  Color c[6];

  v[0] = Vector3D(0, 0, 0);
  v[1] = Vector3D(1, 0, 0);
  c[0] = c[1] = Color(255, 0, 0);

  v[2] = Vector3D(0, 0, 0);
  v[3] = Vector3D(0, 1, 0);
  c[2] = c[3] = Color(0, 255, 0);

  v[4] = Vector3D(0, 0, 0);
  v[5] = Vector3D(0, 0, 1);
  c[4] = c[5] = Color(0, 0, 255);

  _axisVertexes = new QGLBuffer(QGLBuffer::VertexBuffer);
  _axisVertexes->create();
  _axisVertexes->bind();
  _axisVertexes->setUsagePattern(QGLBuffer::DynamicDraw);
  _axisVertexes->allocate(v, 6 * sizeof(Vector3D));

  _axisColors = new QGLBuffer(QGLBuffer::VertexBuffer);
  _axisColors->create();
  _axisColors->bind();
  _axisColors->setUsagePattern(QGLBuffer::DynamicDraw);
  _axisColors->allocate(c,  6 * sizeof(Color));
}

void GLWidget::drawAxis(float len) {
  _axisVertexes->bind();
  _shaderProgram->enableAttributeArray("vPosition");
  _shaderProgram->setAttributeBuffer("vPosition", GL_FLOAT, 0, 3, 0);

  _axisColors->bind();
  _shaderProgram->enableAttributeArray("vColor");
  _shaderProgram->setAttributeBuffer("vColor", GL_FLOAT, 0, 4, 0);

  glDrawArrays(GL_LINES, 0, 6);
}

void GLWidget::projection(int width, int height, float size) {
  QMatrix4x4 proj;
  proj.setToIdentity();
  proj.ortho(-size,size, -size,size, -size,size);

  _shaderProgram->setUniformValue("Projection", proj);
}
<|endoftext|>


<commit_before>/**
 * imagepanel.cpp - simple panel for wxImage
 * I refer http://wiki.wxwidgets.org/An_image_panel
 *
 * Copyright (C) 2011-2015 Hiroyuki Nagata
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Contributor:
 *	Hiroyuki Nagata <newserver002@gmail.com>
 */
#include "imagepanel.hpp"
#include "xrossboardimageviewer.hpp"
#include "enums.hpp"

BEGIN_EVENT_TABLE(wxImagePanel, wxScrolledWindow)

// some useful events
/*
  EVT_MOTION(wxImagePanel::mouseMoved)
  EVT_LEFT_DOWN(wxImagePanel::mouseDown)
  EVT_LEFT_UP(wxImagePanel::mouseReleased)
  EVT_RIGHT_DOWN(wxImagePanel::rightClick)
  EVT_LEAVE_WINDOW(wxImagePanel::mouseLeftWindow)
  EVT_KEY_DOWN(wxImagePanel::keyPressed)
  EVT_KEY_UP(wxImagePanel::keyReleased)
  EVT_MOUSEWHEEL(wxImagePanel::mouseWheelMoved)
*/
// catch paint events
EVT_PAINT(wxImagePanel::PaintEvent)

END_EVENT_TABLE()

/**
 * Default constructor
 */
wxImagePanel::wxImagePanel(wxWindow* parent, std::unique_ptr<DownloadImageResult>& result, const wxBitmapType type)
: wxScrolledWindow(parent, ID_ImagePanel)
{
     // load the file... ideally add a check to see if loading was successful
     image.LoadFile(result->imagePath, type);

     // copy file information (better copy way is ?)
     this->imageInfo.imagePath = wxString(result->imagePath);
     this->imageInfo.imageURL  = wxString(result->imageURL);
     this->imageInfo.ext       = wxString(result->ext);
     this->imageInfo.fileName  = wxString(result->fileName);
     this->imageInfo.result    = result->result;
     this->originalHeight      = image.GetHeight();
     this->originalWidth       = image.GetWidth();
     this->magnification       = 1.0;
     this->m_type              = type;

     // set scrollbars
     this->SetScrollbars(1, 1, image.GetHeight(), image.GetWidth());
}
/**
 * Copy constructor
 */
wxImagePanel::wxImagePanel(const wxImagePanel& rhs) {}

/**
 * Assignment operator
 */
wxImagePanel& wxImagePanel::operator=(const wxImagePanel& rhs)
{
     if (this != &rhs) {
	  // TODO: implement copy
     }
     return *this;
}
/*
 * Called by the system of by wxWidgets when the panel needs
 * to be redrawn. You can also trigger this call by
 * calling Refresh()/Update().
 */
void wxImagePanel::PaintEvent(wxPaintEvent & evt)
{
     // depending on your system you may need to look at double-buffered dcs
     wxPaintDC dc(this);
     Render(dc);
}
/*
 * Alternatively, you can use a clientDC to paint on the panel
 * at any time. Using this generally does not free you from
 * catching paint events, since it is possible that e.g. the window
 * manager throws away your drawing when the window comes to the
 * background, and expects you will redraw it when the window comes
 * back (by sending a paint event).
 */
void wxImagePanel::PaintNow()
{
     // depending on your system you may need to look at double-buffered dcs
     wxClientDC dc(this);
     Render(dc);
}
/*
 * Here we do the actual rendering. I put it in a separate
 * method so that it can work no matter what type of DC
 * (e.g. wxPaintDC or wxClientDC) is used.
 */
void wxImagePanel::Render(wxDC&  dc)
{
     dc.Clear();
     const wxPoint p = this->GetViewStart();
     dc.DrawBitmap( image, -p.x, -p.y, false );
}
/**
 * 画像のファイルパスを返す
 */
wxString wxImagePanel::GetFilePath()
{
     return imageInfo.imagePath;
}
/**
 * 画像のダウンロード先を返す
 */
wxString wxImagePanel::GetImageURL()
{
     return imageInfo.imageURL;
}
/**
 * 画像を90度回転させる
 * @param bool clockwise true:時計回り false:反時計回り
 */
void wxImagePanel::Rotate90(bool clockwise)
{
     wxImage copy = this->image.ConvertToImage();
     image  = wxBitmap(copy.Rotate90(clockwise));
     PaintNow();
}
/**
 * 画像をリサイズする
 * @param bool toBig true:大きく false:小さく
 */
void wxImagePanel::Resize(bool toBig)
{
     if (this->originalHeight <= 0 || this->originalWidth <= 0)
     {
	  return;
     }

     if ( 0.1 <= this->magnification && this->magnification <= 2.0 )
     {
	  if (toBig && magnification == 2.0)
	  {
	       return;
	  }
	  else if (toBig)
	  {
	       // 大きくする
	       this->magnification += 0.1;
	  }
	  else if (!toBig && magnification == 0.1)
	  {
	       return;
	  }
	  else
	  {
	       // 小さくする
	       this->magnification -= 0.1;
	  }

	  bool ret = image.LoadFile(imageInfo.imagePath, m_type);
	  if (!ret)
	  {
	       wxMessageBox(wxT("リサイズ実行時に画像ファイルが見つかりませんでした"));
	       return;
	  }

	  wxImage copy = image.ConvertToImage();
	  const int x = originalWidth*magnification;
	  const int y = originalHeight*magnification;

	  image = wxBitmap(copy.Rescale(x, y, wxIMAGE_QUALITY_HIGH));
	  PaintNow();
     }
}
/**
 * 画像を元のサイズに戻す
 */
void wxImagePanel::Reset()
{
     if (originalHeight <= 0 || originalWidth <= 0)
     {
	  return;
     }

     bool ret = image.LoadFile(imageInfo.imagePath, m_type);
     if (!ret)
     {
	  wxMessageBox(wxT("リサイズ実行時に画像ファイルが見つかりませんでした"));
	  return;
     }

     wxImage copy = image.ConvertToImage();
     image  = wxBitmap(copy.Rescale(originalWidth, originalHeight, wxIMAGE_QUALITY_HIGH));
     this->magnification = 1.0;
     PaintNow();
}

double wxImagePanel::GetMagnification()
{
     return this->magnification;
}

void wxImagePanel::SetMagnification(double magnification)
{
     this->magnification = magnification;
}

<commit_msg>Fix for wx-2.8 style<commit_after>/**
 * imagepanel.cpp - simple panel for wxImage
 * I refer http://wiki.wxwidgets.org/An_image_panel
 *
 * Copyright (C) 2011-2015 Hiroyuki Nagata
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Contributor:
 *	Hiroyuki Nagata <newserver002@gmail.com>
 */
#include "imagepanel.hpp"
#include "xrossboardimageviewer.hpp"
#include "enums.hpp"

BEGIN_EVENT_TABLE(wxImagePanel, wxScrolledWindow)

// some useful events
/*
  EVT_MOTION(wxImagePanel::mouseMoved)
  EVT_LEFT_DOWN(wxImagePanel::mouseDown)
  EVT_LEFT_UP(wxImagePanel::mouseReleased)
  EVT_RIGHT_DOWN(wxImagePanel::rightClick)
  EVT_LEAVE_WINDOW(wxImagePanel::mouseLeftWindow)
  EVT_KEY_DOWN(wxImagePanel::keyPressed)
  EVT_KEY_UP(wxImagePanel::keyReleased)
  EVT_MOUSEWHEEL(wxImagePanel::mouseWheelMoved)
*/
// catch paint events
EVT_PAINT(wxImagePanel::PaintEvent)

END_EVENT_TABLE()

/**
 * Default constructor
 */
wxImagePanel::wxImagePanel(wxWindow* parent, std::unique_ptr<DownloadImageResult>& result, const wxBitmapType type)
: wxScrolledWindow(parent, ID_ImagePanel)
{
     // load the file... ideally add a check to see if loading was successful
     image.LoadFile(result->imagePath, type);

     // copy file information (better copy way is ?)
     this->imageInfo.imagePath = wxString(result->imagePath);
     this->imageInfo.imageURL  = wxString(result->imageURL);
     this->imageInfo.ext       = wxString(result->ext);
     this->imageInfo.fileName  = wxString(result->fileName);
     this->imageInfo.result    = result->result;
     this->originalHeight      = image.GetHeight();
     this->originalWidth       = image.GetWidth();
     this->magnification       = 1.0;
     this->m_type              = type;

     // set scrollbars
     this->SetScrollbars(1, 1, image.GetHeight(), image.GetWidth());
}
/**
 * Copy constructor
 */
wxImagePanel::wxImagePanel(const wxImagePanel& rhs) {}

/**
 * Assignment operator
 */
wxImagePanel& wxImagePanel::operator=(const wxImagePanel& rhs)
{
     if (this != &rhs) {
	  // TODO: implement copy
     }
     return *this;
}
/*
 * Called by the system of by wxWidgets when the panel needs
 * to be redrawn. You can also trigger this call by
 * calling Refresh()/Update().
 */
void wxImagePanel::PaintEvent(wxPaintEvent & evt)
{
     // depending on your system you may need to look at double-buffered dcs
     wxPaintDC dc(this);
     Render(dc);
}
/*
 * Alternatively, you can use a clientDC to paint on the panel
 * at any time. Using this generally does not free you from
 * catching paint events, since it is possible that e.g. the window
 * manager throws away your drawing when the window comes to the
 * background, and expects you will redraw it when the window comes
 * back (by sending a paint event).
 */
void wxImagePanel::PaintNow()
{
     // depending on your system you may need to look at double-buffered dcs
     wxClientDC dc(this);
     Render(dc);
}
/*
 * Here we do the actual rendering. I put it in a separate
 * method so that it can work no matter what type of DC
 * (e.g. wxPaintDC or wxClientDC) is used.
 */
void wxImagePanel::Render(wxDC&  dc)
{
     dc.Clear();
     wxPoint p;
     this->GetViewStart(&p.x, &p.y);
     dc.DrawBitmap( image, -p.x, -p.y, false );
}
/**
 * 画像のファイルパスを返す
 */
wxString wxImagePanel::GetFilePath()
{
     return imageInfo.imagePath;
}
/**
 * 画像のダウンロード先を返す
 */
wxString wxImagePanel::GetImageURL()
{
     return imageInfo.imageURL;
}
/**
 * 画像を90度回転させる
 * @param bool clockwise true:時計回り false:反時計回り
 */
void wxImagePanel::Rotate90(bool clockwise)
{
     wxImage copy = this->image.ConvertToImage();
     image  = wxBitmap(copy.Rotate90(clockwise));
     PaintNow();
}
/**
 * 画像をリサイズする
 * @param bool toBig true:大きく false:小さく
 */
void wxImagePanel::Resize(bool toBig)
{
     if (this->originalHeight <= 0 || this->originalWidth <= 0)
     {
	  return;
     }

     if ( 0.1 <= this->magnification && this->magnification <= 2.0 )
     {
	  if (toBig && magnification == 2.0)
	  {
	       return;
	  }
	  else if (toBig)
	  {
	       // 大きくする
	       this->magnification += 0.1;
	  }
	  else if (!toBig && magnification == 0.1)
	  {
	       return;
	  }
	  else
	  {
	       // 小さくする
	       this->magnification -= 0.1;
	  }

	  bool ret = image.LoadFile(imageInfo.imagePath, m_type);
	  if (!ret)
	  {
	       wxMessageBox(wxT("リサイズ実行時に画像ファイルが見つかりませんでした"));
	       return;
	  }

	  wxImage copy = image.ConvertToImage();
	  const int x = originalWidth*magnification;
	  const int y = originalHeight*magnification;

	  image = wxBitmap(copy.Rescale(x, y, wxIMAGE_QUALITY_HIGH));
	  PaintNow();
     }
}
/**
 * 画像を元のサイズに戻す
 */
void wxImagePanel::Reset()
{
     if (originalHeight <= 0 || originalWidth <= 0)
     {
	  return;
     }

     bool ret = image.LoadFile(imageInfo.imagePath, m_type);
     if (!ret)
     {
	  wxMessageBox(wxT("リサイズ実行時に画像ファイルが見つかりませんでした"));
	  return;
     }

     wxImage copy = image.ConvertToImage();
     image  = wxBitmap(copy.Rescale(originalWidth, originalHeight, wxIMAGE_QUALITY_HIGH));
     this->magnification = 1.0;
     PaintNow();
}

double wxImagePanel::GetMagnification()
{
     return this->magnification;
}

void wxImagePanel::SetMagnification(double magnification)
{
     this->magnification = magnification;
}

<|endoftext|>


<commit_before><commit_msg>add micro support<commit_after><|endoftext|>


<commit_before>#include "catch.hpp"

#include "orrery.hpp"

using namespace groho;

TEST_CASE("Load orrery", "[ORRERY]")
{
    Kernels kernels = { { {}, "groho-test-data/de432s.bsp" },
                        { { 809, 899 }, "groho-test-data/nep086.bsp" } };
    J2000_s begin   = GregorianDate{ 2000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 2010, 1, 1, 0 };

    Orrery::StatusCode status;
    auto bodies = load_orrery_objects(begin, end, kernels, status);

    REQUIRE(status == Orrery::StatusCode::OK);
    REQUIRE(bodies.size() == 17);
    REQUIRE(bodies[1].ephemeris->target_code == 10);
    REQUIRE(bodies[1].parent_idx == 0);
    REQUIRE(bodies[11].ephemeris->target_code == 299);
    REQUIRE(bodies[11].parent_idx == 2);
    REQUIRE(bodies[15].ephemeris->target_code == 399);
    REQUIRE(bodies[15].parent_idx == 8);

    auto orrery = Orrery(begin, end, kernels);
}

TEST_CASE("Missing kernel file", "[ORRERY]")
{
    Kernels kernels = { { { 909, 999 }, "groho-test-data/non-existent.bsp" } };
    J2000_s begin   = GregorianDate{ 2000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 2010, 1, 1, 0 };

    auto orrery = Orrery(begin, end, kernels);
    REQUIRE(orrery.status() == Orrery::StatusCode::WARNING);
}

TEST_CASE("Load orrery with date problems", "[ORRERY]")
{
    Kernels kernels = { { {}, "groho-test-data/de432s.bsp" },
                        { { 809, 899 }, "groho-test-data/nep086.bsp" } };
    J2000_s begin   = GregorianDate{ 1000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 1010, 1, 1, 0 };

    auto orrery = Orrery(begin, end, kernels);
    REQUIRE(orrery.status() == Orrery::StatusCode::ERROR);
}

TEST_CASE("Load orrery with center problems", "[ORRERY]")
{
    Kernels kernels = { { { 809, 899 }, "groho-test-data/nep086.bsp" } };
    J2000_s begin   = GregorianDate{ 2000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 2010, 1, 1, 0 };

    auto orrery = Orrery(begin, end, kernels);
    REQUIRE(orrery.status() == Orrery::StatusCode::ERROR);
}

TEST_CASE("Load orrery with missing bodies", "[ORRERY]")
{
    Kernels kernels = { { { 909, 999 }, "groho-test-data/nep086.bsp" } };
    J2000_s begin   = GregorianDate{ 2000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 2010, 1, 1, 0 };

    auto orrery = Orrery(begin, end, kernels);
    REQUIRE(orrery.status() == Orrery::StatusCode::WARNING);
}
<commit_msg>Make orrery test stable to tree order<commit_after>#include "catch.hpp"

#include "orrery.hpp"

using namespace groho;

TEST_CASE("Load orrery", "[ORRERY]")
{
    Kernels kernels = { { {}, "groho-test-data/de432s.bsp" },
                        { { 809, 899 }, "groho-test-data/nep086.bsp" } };
    J2000_s begin   = GregorianDate{ 2000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 2010, 1, 1, 0 };

    Orrery::StatusCode status;
    auto bodies = load_orrery_objects(begin, end, kernels, status);

    REQUIRE(status == Orrery::StatusCode::OK);
    REQUIRE(bodies.size() == 17);

    for (size_t i = 1; i < bodies.size(); i++) {
        REQUIRE(bodies[i].parent_idx < i); // The ordering property we need
    }

    for (size_t i = 1; i < bodies.size(); i++) {
        if (bodies[i].ephemeris->target_code == 299) {
            size_t venus_bc = bodies[i].parent_idx;
            REQUIRE(bodies[venus_bc].ephemeris->target_code == 2);
            REQUIRE(bodies[venus_bc].parent_idx == 0);
            break;
        }
    }

    auto orrery = Orrery(begin, end, kernels);
}

TEST_CASE("Missing kernel file", "[ORRERY]")
{
    Kernels kernels = { { { 909, 999 }, "groho-test-data/non-existent.bsp" } };
    J2000_s begin   = GregorianDate{ 2000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 2010, 1, 1, 0 };

    auto orrery = Orrery(begin, end, kernels);
    REQUIRE(orrery.status() == Orrery::StatusCode::WARNING);
}

TEST_CASE("Load orrery with date problems", "[ORRERY]")
{
    Kernels kernels = { { {}, "groho-test-data/de432s.bsp" },
                        { { 809, 899 }, "groho-test-data/nep086.bsp" } };
    J2000_s begin   = GregorianDate{ 1000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 1010, 1, 1, 0 };

    auto orrery = Orrery(begin, end, kernels);
    REQUIRE(orrery.status() == Orrery::StatusCode::ERROR);
}

TEST_CASE("Load orrery with center problems", "[ORRERY]")
{
    Kernels kernels = { { { 809, 899 }, "groho-test-data/nep086.bsp" } };
    J2000_s begin   = GregorianDate{ 2000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 2010, 1, 1, 0 };

    auto orrery = Orrery(begin, end, kernels);
    REQUIRE(orrery.status() == Orrery::StatusCode::ERROR);
}

TEST_CASE("Load orrery with missing bodies", "[ORRERY]")
{
    Kernels kernels = { { { 909, 999 }, "groho-test-data/nep086.bsp" } };
    J2000_s begin   = GregorianDate{ 2000, 1, 1, 0 };
    J2000_s end     = GregorianDate{ 2010, 1, 1, 0 };

    auto orrery = Orrery(begin, end, kernels);
    REQUIRE(orrery.status() == Orrery::StatusCode::WARNING);
}
<|endoftext|>


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

#pragma once

#include <algorithm>
#include <random>

namespace tests::random {

static std::random_device rd;
static std::default_random_engine gen(rd());

template<typename T>
T get_int() {
    std::uniform_int_distribution<T> dist;
    return dist(gen);
}

template<typename T>
T get_int(T max) {
    std::uniform_int_distribution<T> dist(0, max);
    return dist(gen);
}

template<typename T>
T get_int(T min, T max) {
    std::uniform_int_distribution<T> dist(min, max);
    return dist(gen);
}

bool get_bool() {
    static std::bernoulli_distribution dist;
    return dist(gen);
}

bytes get_bytes(size_t n) {
    bytes b(bytes::initialized_later(), n);
    boost::generate(b, [] { return get_int<bytes::value_type>(); });
    return b;
}

bytes get_bytes() {
    return get_bytes(get_int<unsigned>(128 * 1024));
}

}
<commit_msg>tests/random-utils: add missing include<commit_after>/*
 * Copyright (C) 2018 ScyllaDB
 */
/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <algorithm>
#include <random>

#include <boost/range/algorithm/generate.hpp>

namespace tests::random {

static std::random_device rd;
static std::default_random_engine gen(rd());

template<typename T>
T get_int() {
    std::uniform_int_distribution<T> dist;
    return dist(gen);
}

template<typename T>
T get_int(T max) {
    std::uniform_int_distribution<T> dist(0, max);
    return dist(gen);
}

template<typename T>
T get_int(T min, T max) {
    std::uniform_int_distribution<T> dist(min, max);
    return dist(gen);
}

bool get_bool() {
    static std::bernoulli_distribution dist;
    return dist(gen);
}

bytes get_bytes(size_t n) {
    bytes b(bytes::initialized_later(), n);
    boost::generate(b, [] { return get_int<bytes::value_type>(); });
    return b;
}

bytes get_bytes() {
    return get_bytes(get_int<unsigned>(128 * 1024));
}

}
<|endoftext|>


<commit_before><commit_msg>TosLang: Fixing include under GCC<commit_after><|endoftext|>


<commit_before>/*
 * testCounter.cpp
 *
 *      Author: Peter Johansson
 */
#ifdef _MOCK_

#include "gtest/gtest.h"
#include "../src/CalvinDone/CalvinMini.h"
#include "../src/CalvinDone/actors.h"

class testCounter : public ::testing::Test {
protected:
	virtual void SetUp() {}
	virtual void TearDown() {}
};

TEST(testCounter, testReceiveCounter)
{
    CalvinMini mini;
    String str = "{\"to_rt_uuid\": \"calvin-miniscule\", \"from_rt_uuid\": \"422828ae-02c1-4d2f-9837-43a32fb6decb\""
                 ", \"state\": {\"prev_connections\": {\"actor_name\": \"test3:src\", \"inports\": {}, \"actor_id\": \"6bc4b467-a2d2-4254-ad84-bf918231c68e\""
                 ", \"outports\": {\"f4822772-bca4-465c-8109-a1e7a960e304\": [[\"422828ae-02c1-4d2f-9837-43a32fb6decb\", \"98f7f8ad-f4d3-44ae-9228-728a54c2fee3\"]]}}"
                 ", \"actor_type\": \"std.Counter\", \"actor_state\": {\"count\": 117, \"name\": \"test3:src\", \"inports\": {}, \"_managed\": [\"count\", \"id\", \"name\"]"
                 ", \"outports\": {\"integer\": {\"fanout\": 1, \"name\": \"integer\", \"fifo\": {\"write_pos\": 117, \"readers\": [\"98f7f8ad-f4d3-44ae-9228-728a54c2fee3\"]"
                 ", \"fifo\": [{\"data\": 113, \"type\": \"Token\"}, {\"data\": 114, \"type\": \"Token\"}, {\"data\": 115, \"type\": \"Token\"}"
                 ", {\"data\": 116, \"type\": \"Token\"}, {\"data\": 117, \"type\": \"Token\"}], \"N\": 5, \"tentative_read_pos\": {\"98f7f8ad-f4d3-44ae-9228-728a54c2fee3\": 113}"
                 ", \"read_pos\": {\"98f7f8ad-f4d3-44ae-9228-7228a54c2fee3\": 113}}, \"id\": \"f4822772-bca4-465c-8109-a1e7a960e304\"}}"
                 ", \"id\": \"6bc4b467-a2d2-4254-ad84-bf918231c68e\"}}, \"cmd\": \"ACTOR_NEW\", \"msg_uuid\": \"fd71b46d-0e44-4298-9bb3-61aa0420bc45\"}";

    StaticJsonBuffer<4096> jsonBuffer;
    JsonObject &msg = jsonBuffer.parseObject(str.c_str());
    JsonObject &reply = jsonBuffer.createObject();
    JsonObject &request = jsonBuffer.createObject();

    // Test what number arduino should start counting from
    JsonObject &fifoObject = msg["state"]["actor_state"]["outports"]["integer"]["fifo"];
    JsonArray &fifoArray = fifoObject.get("fifo");
    JsonObject &count = fifoArray.get(0);
    EXPECT_EQ(113,(uint32_t)count.get("data"));

    int8_t size = mini.handleMsg(msg, reply, request, 0);
    JsonObject &actor_state = msg["state"]["actor_state"];

    // Test if number of outgoing messages is 2
    EXPECT_EQ(size,2);

    // Test if actor_type Counter is triggered
    EXPECT_STREQ("std.Counter", msg["state"]["actor_type"]);

    // Test if actor_state contains key count
    // which should be true when actor is Counter
    EXPECT_TRUE(actor_state.containsKey("count"));

    // Test if PORT_CONNECT is returned cmd
    // which it should be after an actor migrate
    EXPECT_STREQ("PORT_CONNECT", request["cmd"]);
}

TEST(testCounter, testCounterACK)
{
    CalvinMini mini;
    String str = "{\"to_rt_uuid\": \"calvin-arduino\", \"from_rt_uuid\": \"babc045f-5da1-4eb1-a08e-95e6a272cfde\""
                 ", \"cmd\": \"TUNNEL_DATA\", \"value\": {\"sequencenbr\": 0, \"peer_port_id\": \"50017184-4e7f-4f76-8c39-9e1f35f59b46\""
                 ", \"cmd\": \"TOKEN_REPLY\", \"port_id\": \"be1fbbb2-9fb3-4bac-bb94-0e601f2df6df\", \"value\": \"ACK\"}, \"tunnel_id\": \"fake-tunnel\"}";

    StaticJsonBuffer<4096> jsonBuffer;
    JsonObject &msg = jsonBuffer.parseObject(str.c_str());
    JsonObject &reply = jsonBuffer.createObject();
    JsonObject &request = jsonBuffer.createObject();

    int8_t size = mini.handleMsg(msg, reply, request, 0);

    // Test if number of outgoing messages is 1
    EXPECT_EQ(size, 1);
}

TEST(testCounter,testCounting)
{
	CalvinMini mini;
	actor testActor;
	fifo testFifo;
	initFifo(&testFifo);
	testActor.inportsFifo[0] = testFifo;
	fifoPop(&testActor.inportsFifo[0]);
	testActor.count = 0;
	EXPECT_EQ(0,testActor.count);
	EXPECT_EQ(0,actorCount(&testActor));
	EXPECT_EQ(1,testActor.count);
	fifoPop(&testActor.inportsFifo[0]);
	testActor.count = 0;
	for(int i = 0; i < 1000; i++){
		actorCount(&testActor);
		EXPECT_EQ(i+1,fifoPop(&testActor.inportsFifo[0]));
	}
	EXPECT_EQ(1000,testActor.count);

}

#endif
<commit_msg>Added tests for ACK and NACK in testCounter<commit_after>/*
 * testCounter.cpp
 *
 *      Author: Peter Johansson
 */
#ifdef _MOCK_

#include "gtest/gtest.h"
#include "../src/CalvinDone/CalvinMini.h"
#include "../src/CalvinDone/actors.h"

class testCounter : public ::testing::Test {
protected:
	virtual void SetUp() {}
	virtual void TearDown() {}
};

TEST(testCounter, testReceiveCounter)
{
    CalvinMini mini;
    String str = "{\"to_rt_uuid\": \"calvin-miniscule\", \"from_rt_uuid\": \"422828ae-02c1-4d2f-9837-43a32fb6decb\""
                 ", \"state\": {\"prev_connections\": {\"actor_name\": \"test3:src\", \"inports\": {}, \"actor_id\": \"6bc4b467-a2d2-4254-ad84-bf918231c68e\""
                 ", \"outports\": {\"f4822772-bca4-465c-8109-a1e7a960e304\": [[\"422828ae-02c1-4d2f-9837-43a32fb6decb\", \"98f7f8ad-f4d3-44ae-9228-728a54c2fee3\"]]}}"
                 ", \"actor_type\": \"std.Counter\", \"actor_state\": {\"count\": 117, \"name\": \"test3:src\", \"inports\": {}, \"_managed\": [\"count\", \"id\", \"name\"]"
                 ", \"outports\": {\"integer\": {\"fanout\": 1, \"name\": \"integer\", \"fifo\": {\"write_pos\": 117, \"readers\": [\"98f7f8ad-f4d3-44ae-9228-728a54c2fee3\"]"
                 ", \"fifo\": [{\"data\": 113, \"type\": \"Token\"}, {\"data\": 114, \"type\": \"Token\"}, {\"data\": 115, \"type\": \"Token\"}"
                 ", {\"data\": 116, \"type\": \"Token\"}, {\"data\": 117, \"type\": \"Token\"}], \"N\": 5, \"tentative_read_pos\": {\"98f7f8ad-f4d3-44ae-9228-728a54c2fee3\": 113}"
                 ", \"read_pos\": {\"98f7f8ad-f4d3-44ae-9228-7228a54c2fee3\": 113}}, \"id\": \"f4822772-bca4-465c-8109-a1e7a960e304\"}}"
                 ", \"id\": \"6bc4b467-a2d2-4254-ad84-bf918231c68e\"}}, \"cmd\": \"ACTOR_NEW\", \"msg_uuid\": \"fd71b46d-0e44-4298-9bb3-61aa0420bc45\"}";

    StaticJsonBuffer<4096> jsonBuffer;
    JsonObject &msg = jsonBuffer.parseObject(str.c_str());
    JsonObject &reply = jsonBuffer.createObject();
    JsonObject &request = jsonBuffer.createObject();

    // Test what number arduino should start counting from
    JsonObject &fifoObject = msg["state"]["actor_state"]["outports"]["integer"]["fifo"];
    JsonArray &fifoArray = fifoObject.get("fifo");
    JsonObject &count = fifoArray.get(0);
    EXPECT_EQ(113,(uint32_t)count.get("data"));

    int8_t size = mini.handleMsg(msg, reply, request, 0);
    JsonObject &actor_state = msg["state"]["actor_state"];

    // Test if number of outgoing messages is 2
    EXPECT_EQ(size,2);

    // Test if actor_type Counter is triggered
    EXPECT_STREQ("std.Counter", msg["state"]["actor_type"]);

    // Test if actor_state contains key count
    // which should be true when actor is Counter
    EXPECT_TRUE(actor_state.containsKey("count"));

    // Test if PORT_CONNECT is returned cmd
    // which it should be after an actor migrate
    EXPECT_STREQ("PORT_CONNECT", request["cmd"]);
}

TEST(testCounter, testCounterACK)
{
    CalvinMini mini;
    String str = "{\"to_rt_uuid\": \"calvin-arduino\", \"from_rt_uuid\": \"babc045f-5da1-4eb1-a08e-95e6a272cfde\""
                 ", \"cmd\": \"TUNNEL_DATA\", \"value\": {\"sequencenbr\": 0, \"peer_port_id\": \"50017184-4e7f-4f76-8c39-9e1f35f59b46\""
                 ", \"cmd\": \"TOKEN_REPLY\", \"port_id\": \"be1fbbb2-9fb3-4bac-bb94-0e601f2df6df\", \"value\": \"ACK\"}, \"tunnel_id\": \"fake-tunnel\"}";

    StaticJsonBuffer<4096> jsonBuffer;
    JsonObject &msg = jsonBuffer.parseObject(str.c_str());
    JsonObject &reply = jsonBuffer.createObject();
    JsonObject &request = jsonBuffer.createObject();

    int8_t size = mini.handleMsg(msg, reply, request, 0);

    // Test if number of outgoing messages is 1
    EXPECT_EQ(size, 1);

    JsonObject &value = reply.get("value");
    int sequencenbr = value.get("sequencenbr");

    // Test if sequencenbr is updated from 0 to 1 when ACK from base
    EXPECT_EQ(1, sequencenbr);
}

TEST(testCounter, testCounterNACK)
{
    CalvinMini mini;
    String str = "{\"to_rt_uuid\": \"calvin-arduino\", \"from_rt_uuid\": \"babc045f-5da1-4eb1-a08e-95e6a272cfde\""
                 ", \"cmd\": \"TUNNEL_DATA\", \"value\": {\"sequencenbr\": 0, \"peer_port_id\": \"50017184-4e7f-4f76-8c39-9e1f35f59b46\""
                 ", \"cmd\": \"TOKEN_REPLY\", \"port_id\": \"be1fbbb2-9fb3-4bac-bb94-0e601f2df6df\", \"value\": \"NACK\"}, \"tunnel_id\": \"fake-tunnel\"}";

    StaticJsonBuffer<4096> jsonBuffer;
    JsonObject &msg = jsonBuffer.parseObject(str.c_str());
    JsonObject &reply = jsonBuffer.createObject();
    JsonObject &request = jsonBuffer.createObject();

    int8_t size = mini.handleMsg(msg, reply, request, 0);

    // Test if number of outgoing messages is 1
    EXPECT_EQ(size, 1);

    JsonObject &value = reply.get("value");
    int sequencenbr = value.get("sequencenbr");

    // Test if sequencenbr is unchanged from 0 when NACK from base
    EXPECT_EQ(0, sequencenbr);
}

TEST(testCounter,testCounting)
{
	CalvinMini mini;
	actor testActor;
	fifo testFifo;
	initFifo(&testFifo);
	testActor.inportsFifo[0] = testFifo;
	fifoPop(&testActor.inportsFifo[0]);
	testActor.count = 0;
	EXPECT_EQ(0,testActor.count);
	EXPECT_EQ(0,actorCount(&testActor));
	EXPECT_EQ(1,testActor.count);
	fifoPop(&testActor.inportsFifo[0]);
	testActor.count = 0;
	for(int i = 0; i < 1000; i++){
		actorCount(&testActor);
		EXPECT_EQ(i+1,fifoPop(&testActor.inportsFifo[0]));
	}
	EXPECT_EQ(1000,testActor.count);

}

#endif
<|endoftext|>