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

#include "test_serialise_list.h"

#include "../src/serialise_list.h"
#include "utils.h"

inline int testing(const std::vector<std::string>& strs) {
	auto serialised = StringList::serialise(strs.begin(), strs.end());

	int cont = 0;

	StringList s(serialised);
	if (s.size() != strs.size()) {
		L_ERR(nullptr, "StringList is not working. Size: %zu Expected: %zu", s.size(), strs.size());
		++cont;
	}

	std::vector<std::string> res;
	StringList::unserialise(serialised, std::back_inserter(res));
	if (res.size() != strs.size()) {
		L_ERR(nullptr, "StringList::unserialise is not working. Size: %zu Expected: %zu", res.size(), strs.size());
		++cont;
	}

	auto it_s = s.begin();
	auto it_r = res.begin();
	for (const auto& elem : strs) {
		if (*it_s != elem || *it_r != elem) {
			L_ERR(nullptr, "StringList is not working. Result: [%s, %s] Expected: %s", it_s->c_str(), it_r->c_str(), elem.c_str());
			++cont;
		}
		++it_s;
		++it_r;
	}

	return cont;
}

inline int testing(const std::vector<Cartesian>& ptos) {
	auto serialised = CartesianList::serialise(ptos.begin(), ptos.end());

	int cont = 0;

	CartesianList s(serialised);
	if (s.size() != ptos.size()) {
		L_ERR(nullptr, "CartesianList is not working. Size: %zu Expected: %zu", s.size(), ptos.size());
		++cont;
	}

	std::vector<Cartesian> res;
	CartesianList::unserialise(serialised, std::back_inserter(res));
	if (res.size() != ptos.size()) {
		L_ERR(nullptr, "CartesianList::unserialise is not working. Size: %zu Expected: %zu", res.size(), ptos.size());
		++cont;
	}

	auto it_s = s.begin();
	auto it_r = res.begin();
	for (const auto& elem : ptos) {
		if (*it_s != elem || *it_r != elem) {
			L_ERR(nullptr, "CartesianList is not working. Result: [%s, %s] Expected: %s", it_s->to_string().c_str(), it_r->to_string().c_str(), elem.to_string().c_str());
			++cont;
		}
		++it_s;
		++it_r;
	}

	return cont;
}

inline int testing(const std::vector<range_t>& ranges) {
	auto serialised = RangeList::serialise(ranges.begin(), ranges.end());

	int cont = 0;

	RangeList s(serialised);
	if (s.size() != ranges.size()) {
		L_ERR(nullptr, "RangeList is not working. Size: %zu Expected: %zu", s.size(), ranges.size());
		++cont;
	}

	std::vector<range_t> res;
	RangeList::unserialise(serialised, std::back_inserter(res));
	if (res.size() != ranges.size()) {
		L_ERR(nullptr, "RangeList::unserialise is not working. Size: %zu Expected: %zu", res.size(), ranges.size());
		++cont;
	}

	auto it_s = s.begin();
	auto it_r = res.begin();
	for (const auto& elem : ranges) {
		if (*it_s != elem || *it_r != elem) {
			L_ERR(nullptr, "RangeList is not working. Result: [%s, %s] Expected: %s", it_s->to_string().c_str(), it_r->to_string().c_str(), elem.to_string().c_str());
			++cont;
		}
		++it_s;
		++it_r;
	}

	return cont;
}

int test_StringList() {
	std::vector<std::string> strs;

	int cont = testing(strs);

	strs.emplace_back("a");
	cont += testing(strs);

	strs.emplace_back("b");
	strs.emplace_back("c");
	strs.emplace_back("d");
	strs.emplace_back("e");
	strs.emplace_back("f");
	strs.emplace_back("g");
	strs.emplace_back("h");
	strs.emplace_back("i");
	strs.emplace_back("j");
	cont += testing(strs);

	RETURN(cont);
}

int test_CartesianList() {
	std::vector<Cartesian> ptos;

	int cont = testing(ptos);

	ptos.emplace_back(-1, 0, 0);
	cont += testing(ptos);

	ptos.emplace_back(0.267261, 0.534522, 0.801784);
	ptos.emplace_back(0.455842, 0.569803, 0.683763);
	ptos.emplace_back(0.502571, 0.574367, 0.646162);
	ptos.emplace_back(0.523424, 0.575766, 0.628109);
	ptos.emplace_back(-0.267261, 0.534522, 0.801784);
	ptos.emplace_back(0.455842, -0.569803, 0.683763);
	ptos.emplace_back(0.502571, 0.574367, -0.646162);
	ptos.emplace_back(-0.523424, -0.575766, -0.628109);
	cont += testing(ptos);

	RETURN(cont);
}

int test_RangeList() {
	std::vector<range_t> ranges;

	int cont = testing(ranges);

	ranges.emplace_back(1, 10);
	cont += testing(ranges);

	ranges.emplace_back(20, 30);
	ranges.emplace_back(40, 50);
	ranges.emplace_back(60, 70);
	ranges.emplace_back(80, 90);
	ranges.emplace_back(100, 110);
	ranges.emplace_back(120, 130);
	ranges.emplace_back(140, 150);
	cont += testing(ranges);

	RETURN(cont);
}
<commit_msg>Serialise::range works for HTM with level 25<commit_after>/*
 * Copyright (C) 2017 deipi.com LLC and contributors. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "test_serialise_list.h"

#include "../src/serialise_list.h"
#include "utils.h"

inline int testing(const std::vector<std::string>& strs) {
	auto serialised = StringList::serialise(strs.begin(), strs.end());

	int cont = 0;

	StringList s(serialised);
	if (s.size() != strs.size()) {
		L_ERR(nullptr, "StringList is not working. Size: %zu Expected: %zu", s.size(), strs.size());
		++cont;
	}

	std::vector<std::string> res;
	StringList::unserialise(serialised, std::back_inserter(res));
	if (res.size() != strs.size()) {
		L_ERR(nullptr, "StringList::unserialise is not working. Size: %zu Expected: %zu", res.size(), strs.size());
		++cont;
	}

	auto it_s = s.begin();
	auto it_r = res.begin();
	for (const auto& elem : strs) {
		if (*it_s != elem || *it_r != elem) {
			L_ERR(nullptr, "StringList is not working. Result: [%s, %s] Expected: %s", it_s->c_str(), it_r->c_str(), elem.c_str());
			++cont;
		}
		++it_s;
		++it_r;
	}

	return cont;
}

inline int testing(const std::vector<Cartesian>& ptos) {
	auto serialised = CartesianList::serialise(ptos.begin(), ptos.end());

	int cont = 0;

	CartesianList s(serialised);
	if (s.size() != ptos.size()) {
		L_ERR(nullptr, "CartesianList is not working. Size: %zu Expected: %zu", s.size(), ptos.size());
		++cont;
	}

	std::vector<Cartesian> res;
	CartesianList::unserialise(serialised, std::back_inserter(res));
	if (res.size() != ptos.size()) {
		L_ERR(nullptr, "CartesianList::unserialise is not working. Size: %zu Expected: %zu", res.size(), ptos.size());
		++cont;
	}

	auto it_s = s.begin();
	auto it_r = res.begin();
	for (const auto& elem : ptos) {
		if (*it_s != elem || *it_r != elem) {
			L_ERR(nullptr, "CartesianList is not working. Result: [%s, %s] Expected: %s", it_s->to_string().c_str(), it_r->to_string().c_str(), elem.to_string().c_str());
			++cont;
		}
		++it_s;
		++it_r;
	}

	return cont;
}

inline int testing(const std::vector<range_t>& ranges) {
	auto serialised = RangeList::serialise(ranges.begin(), ranges.end());

	int cont = 0;

	RangeList s(serialised);
	if (s.size() != ranges.size()) {
		L_ERR(nullptr, "RangeList is not working. Size: %zu Expected: %zu", s.size(), ranges.size());
		++cont;
	}

	std::vector<range_t> res;
	RangeList::unserialise(serialised, std::back_inserter(res));
	if (res.size() != ranges.size()) {
		L_ERR(nullptr, "RangeList::unserialise is not working. Size: %zu Expected: %zu", res.size(), ranges.size());
		++cont;
	}

	auto it_s = s.begin();
	auto it_r = res.begin();
	for (const auto& elem : ranges) {
		if (*it_s != elem || *it_r != elem) {
			L_ERR(nullptr, "RangeList is not working. Result: [%s, %s] Expected: %s", it_s->to_string().c_str(), it_r->to_string().c_str(), elem.to_string().c_str());
			++cont;
		}
		++it_s;
		++it_r;
	}

	return cont;
}

int test_StringList() {
	std::vector<std::string> strs;

	int cont = testing(strs);

	strs.emplace_back("a");
	cont += testing(strs);

	strs.emplace_back("b");
	strs.emplace_back("c");
	strs.emplace_back("d");
	strs.emplace_back("e");
	strs.emplace_back("f");
	strs.emplace_back("g");
	strs.emplace_back("h");
	strs.emplace_back("i");
	strs.emplace_back("j");
	cont += testing(strs);

	RETURN(cont);
}

int test_CartesianList() {
	std::vector<Cartesian> ptos;

	int cont = testing(ptos);

	ptos.emplace_back(-1, 0, 0);
	cont += testing(ptos);

	ptos.emplace_back(0.267261, 0.534522, 0.801784);
	ptos.emplace_back(0.455842, 0.569803, 0.683763);
	ptos.emplace_back(0.502571, 0.574367, 0.646162);
	ptos.emplace_back(0.523424, 0.575766, 0.628109);
	ptos.emplace_back(-0.267261, 0.534522, 0.801784);
	ptos.emplace_back(0.455842, -0.569803, 0.683763);
	ptos.emplace_back(0.502571, 0.574367, -0.646162);
	ptos.emplace_back(-0.523424, -0.575766, -0.628109);
	cont += testing(ptos);

	RETURN(cont);
}

int test_RangeList() {
	std::vector<range_t> ranges;

	int cont = testing(ranges);

	// Small level range.
	ranges.emplace_back(14363263991021568, 14363298350759935);
	cont += testing(ranges);

	ranges.emplace_back(14363315530629120, 14363332710498303);
	ranges.emplace_back(14363367070236672, 14363384250105855);
	ranges.emplace_back(14363401429975040, 14363418609844223);
	ranges.emplace_back(14363607588405248, 14363624768274431);
	ranges.emplace_back(14363641948143616, 14363676307881983);
	ranges.emplace_back(14363745027358720, 14363813746835455);
	ranges.emplace_back(14363899646181376, 14363916826050559);
	ranges.emplace_back(14363968365658112, 14364019905265663);
	cont += testing(ranges);

	RETURN(cont);
}
<|endoftext|>


<commit_before>#include "sipclienttransaction.h"

#include "siptransactionuser.h"

#include <QDebug>

// 2 seconds for a SIP reply
const unsigned int TIMEOUT = 2000;
// 1 minute for the user to react
const unsigned int INVITE_TIMEOUT = 60000;

SIPClientTransaction::SIPClientTransaction():
  ongoingTransactionType_(SIP_UNKNOWN_REQUEST),
  connected_(false),
  sessionID_(0),
  state_(INACTIVE),
  pendingRequest_(SIP_UNKNOWN_REQUEST),
  transactionUser_(NULL)
{}

void SIPClientTransaction::init(SIPTransactionUser* tu, uint32_t sessionID)
{
  Q_ASSERT(sessionID != 0);
  Q_ASSERT(tu);
  transactionUser_ = tu;
  sessionID_ = sessionID;
  requestTimer_.setSingleShot(true);
  connect(&requestTimer_, SIGNAL(timeout()), this, SLOT(requestTimeOut()));
}

//processes incoming response
bool SIPClientTransaction::processResponse(SIPResponse &response)
{
  Q_ASSERT(sessionID_ != 0);
  Q_ASSERT(transactionUser_ != NULL);

  qDebug() << "Client starts processing response";
  if(!sessionID_ || transactionUser_ == NULL)
  {
    qWarning() << "WARNING: SIP Client Transaction not initialized.";
    return true;
  }

  int responseCode = response.type;

  if(responseCode >= 300 && responseCode <= 399)
  {
    // TODO: 8.1.3.4 Processing 3xx Responses in RFC 3261
    qDebug() << "Got a redirection response Code. Not implemented!";
    return false;
  }

  if(responseCode >= 400 && responseCode <= 499)
  {
    // TODO: 8.1.3.5 Processing 4xx Responses in RFC 3261
    qDebug() << "Got a Client Failure Response Code. Not implemented!";

    // TODO: if the response is 481 or 408, terminate dialog
    return false;
  }

  if(responseCode >= 500 && responseCode <= 599)
  {
    qDebug() << "Got a Server Failure Response Code. Not implemented!";
    return false;
  }

  if(ongoingTransactionType_ == INVITE)
  {
    if(responseCode >= 600 && responseCode <= 699)
    {
      qDebug() << "Got a Global Failure Response Code for INVITE";
      transactionUser_->callRejected(sessionID_);
      return false;
    }
    else
    {
      switch (response.type) {
      case SIP_RINGING:
        transactionUser_->callRinging(sessionID_);
        break;
      case SIP_OK:
        // the sdp has been check by transaction layer before this.
        requestSender(ACK);
        transactionUser_->callNegotiated(sessionID_);
        break;
      default:
        break;
      }
    }
  }
  if(responseCode >= 200)
  {
    ongoingTransactionType_ = SIP_UNKNOWN_REQUEST;
  }

  return true;
}

bool SIPClientTransaction::startCall()
{
  qDebug() << "Starting a call and sending an INVITE in session";
  Q_ASSERT(sessionID_ != 0);
  if(!sessionID_)
  {
    qWarning() << "WARNING: SIP Client Transaction not initialized";
    return false;
  }

  if(state_ == INACTIVE)
  {
    requestSender(INVITE);
  }
  else
  {
    qWarning() << "WARNING: Trying to start a call, when it is already running or negotiating:" << state_;
    return false;
  }

  return true;
}

void SIPClientTransaction::endCall()
{
  if(state_ != RUNNNING)
  {
    qDebug() << "WARNING: Trying to end a non-active call!";
    return;
  }

  requestSender(BYE);
}

void SIPClientTransaction::registerToServer()
{
  requestSender(REGISTER);
}

void SIPClientTransaction::connectionReady(bool ready)
{
  connected_ = ready;
  if(pendingRequest_ != SIP_UNKNOWN_REQUEST)
  {
    requestSender(pendingRequest_);
    pendingRequest_ = SIP_UNKNOWN_REQUEST;
  }
}

void SIPClientTransaction::getRequestMessageInfo(RequestType type,
                                                 std::shared_ptr<SIPMessageInfo>& outMessage)
{
  outMessage = std::shared_ptr<SIPMessageInfo> (new SIPMessageInfo);

  if(type == ACK)
  {
    outMessage->transactionRequest = INVITE;
  }
  else if(type == CANCEL)
  {
    outMessage->transactionRequest = ongoingTransactionType_;
  }
  else
  {
    outMessage->transactionRequest = type;
  }

  outMessage->dialog = NULL;
  outMessage->maxForwards = 71;
  outMessage->version = "2.0";
  outMessage->cSeq = 0; // invalid, should be set in dialog
}

void SIPClientTransaction::requestSender(RequestType type)
{
  if(!connected_)
  {
    qDebug() << "Added a pending request:" << type;
    pendingRequest_ = type;
  }
  else
  {
    qDebug() << "Client starts sending a request:" << type;
    ongoingTransactionType_ = type;
    emit sendRequest(sessionID_, type);

    if(type != INVITE)
    {
      qDebug() << "Request timeout set to: " << TIMEOUT;
      requestTimer_.start(TIMEOUT);
    }
    else
    {
      qDebug() << "INVITE timeout set to: " << INVITE_TIMEOUT;
      requestTimer_.start(INVITE_TIMEOUT);
    }
  }
}

void SIPClientTransaction::requestTimeOut()
{
  qDebug() << "No response. Request timed out";

  if(ongoingTransactionType_ == INVITE)
  {
    sendRequest(sessionID_, BYE);
    // TODO tell user we have failed
  }

  requestSender(CANCEL);
  transactionUser_->callRejected(sessionID_);
  ongoingTransactionType_ = SIP_UNKNOWN_REQUEST;
}
<commit_msg>Fixed bunch of issues with timeout triggering too soon or needlessly.<commit_after>#include "sipclienttransaction.h"

#include "siptransactionuser.h"

#include <QDebug>

// 2 seconds for a SIP reply
const unsigned int TIMEOUT = 2000;
// 1 minute for the user to react
const unsigned int INVITE_TIMEOUT = 60000;

SIPClientTransaction::SIPClientTransaction():
  ongoingTransactionType_(SIP_UNKNOWN_REQUEST),
  connected_(false),
  sessionID_(0),
  state_(INACTIVE),
  pendingRequest_(SIP_UNKNOWN_REQUEST),
  transactionUser_(NULL)
{}

void SIPClientTransaction::init(SIPTransactionUser* tu, uint32_t sessionID)
{
  Q_ASSERT(sessionID != 0);
  Q_ASSERT(tu);
  transactionUser_ = tu;
  sessionID_ = sessionID;
  requestTimer_.setSingleShot(true);
  connect(&requestTimer_, SIGNAL(timeout()), this, SLOT(requestTimeOut()));
}

//processes incoming response
bool SIPClientTransaction::processResponse(SIPResponse &response)
{
  Q_ASSERT(sessionID_ != 0);
  Q_ASSERT(transactionUser_ != NULL);

  qDebug() << "Client starts processing response";
  if(!sessionID_ || transactionUser_ == NULL)
  {
    qWarning() << "WARNING: SIP Client Transaction not initialized.";
    return true;
  }

  int responseCode = response.type;

  if(responseCode >= 100 && responseCode <= 199)
  {
    qDebug() << "Got provisional response. Restarting timer.";
    if(response.message->transactionRequest == INVITE)
    {
      requestTimer_.start(INVITE_TIMEOUT);
    }
    else
    {
      requestTimer_.start(TIMEOUT);
    }
  }
  else
  {
    qDebug() << "Got response. Stopping timout.";
    requestTimer_.stop();
  }

  if(responseCode >= 300 && responseCode <= 399)
  {
    // TODO: 8.1.3.4 Processing 3xx Responses in RFC 3261
    qDebug() << "Got a redirection response Code. Not implemented!";
    return false;
  }

  if(responseCode >= 400 && responseCode <= 499)
  {
    // TODO: 8.1.3.5 Processing 4xx Responses in RFC 3261
    qDebug() << "Got a Client Failure Response Code. Not implemented!";

    // TODO: if the response is 481 or 408, terminate dialog
    return false;
  }

  if(responseCode >= 500 && responseCode <= 599)
  {
    qDebug() << "Got a Server Failure Response Code. Not implemented!";
    return false;
  }

  if(ongoingTransactionType_ == INVITE)
  {
    if(responseCode >= 600 && responseCode <= 699)
    {
      qDebug() << "Got a Global Failure Response Code for INVITE";
      transactionUser_->callRejected(sessionID_);
      return false;
    }
    else
    {
      switch (response.type) {
      case SIP_RINGING:
        transactionUser_->callRinging(sessionID_);
        break;
      case SIP_OK:
        // the sdp has been check by transaction layer before this.
        requestSender(ACK);
        transactionUser_->callNegotiated(sessionID_);
        break;
      default:
        break;
      }
    }
  }
  if(responseCode >= 200)
  {
    ongoingTransactionType_ = SIP_UNKNOWN_REQUEST;
  }

  return true;
}

bool SIPClientTransaction::startCall()
{
  qDebug() << "Starting a call and sending an INVITE in session";
  Q_ASSERT(sessionID_ != 0);
  if(!sessionID_)
  {
    qWarning() << "WARNING: SIP Client Transaction not initialized";
    return false;
  }

  if(state_ == INACTIVE)
  {
    requestSender(INVITE);
  }
  else
  {
    qWarning() << "WARNING: Trying to start a call, when it is already running or negotiating:" << state_;
    return false;
  }

  return true;
}

void SIPClientTransaction::endCall()
{
  if(state_ != RUNNNING)
  {
    qDebug() << "WARNING: Trying to end a non-active call!";
    return;
  }

  requestSender(BYE);
}

void SIPClientTransaction::registerToServer()
{
  requestSender(REGISTER);
}

void SIPClientTransaction::connectionReady(bool ready)
{
  connected_ = ready;
  if(pendingRequest_ != SIP_UNKNOWN_REQUEST)
  {
    requestSender(pendingRequest_);
    pendingRequest_ = SIP_UNKNOWN_REQUEST;
  }
}

void SIPClientTransaction::getRequestMessageInfo(RequestType type,
                                                 std::shared_ptr<SIPMessageInfo>& outMessage)
{
  outMessage = std::shared_ptr<SIPMessageInfo> (new SIPMessageInfo);

  if(type == ACK)
  {
    outMessage->transactionRequest = INVITE;
  }
  else if(type == CANCEL)
  {
    outMessage->transactionRequest = ongoingTransactionType_;
  }
  else
  {
    outMessage->transactionRequest = type;
  }

  outMessage->dialog = NULL;
  outMessage->maxForwards = 71;
  outMessage->version = "2.0";
  outMessage->cSeq = 0; // invalid, should be set in dialog
}

void SIPClientTransaction::requestSender(RequestType type)
{
  if(!connected_)
  {
    qDebug() << "Added a pending request:" << type;
    pendingRequest_ = type;
  }
  else
  {
    qDebug() << "Client starts sending a request:" << type;
    ongoingTransactionType_ = type;
    emit sendRequest(sessionID_, type);

    if(type != INVITE && type != CANCEL && type != ACK)
    {
      qDebug() << "Request timeout set to: " << TIMEOUT;
      requestTimer_.start(TIMEOUT);
    }
    else if(type == INVITE)
    {
      qDebug() << "INVITE timeout set to: " << INVITE_TIMEOUT;
      requestTimer_.start(INVITE_TIMEOUT);
    }
    else
    {
      requestTimer_.stop();
    }
  }
}

void SIPClientTransaction::requestTimeOut()
{
  qDebug() << "No response. Request timed out";

  if(ongoingTransactionType_ == INVITE)
  {
    sendRequest(sessionID_, BYE);
    // TODO tell user we have failed
  }

  requestSender(CANCEL);
  requestTimer_.stop();
  transactionUser_->callRejected(sessionID_);
  ongoingTransactionType_ = SIP_UNKNOWN_REQUEST;
}
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
 * Copyright (c) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Compressed texture tests.
 *//*--------------------------------------------------------------------*/

#include "vktTextureCompressedFormatTests.hpp"

#include "deString.h"
#include "deStringUtil.hpp"
#include "tcuCompressedTexture.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "vkImageUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktTextureTestUtil.hpp"
#include <string>
#include <vector>

namespace vkt
{
namespace texture
{
namespace
{

using namespace vk;
using namespace glu::TextureTestUtil;
using namespace texture::util;

using std::string;
using std::vector;
using tcu::Sampler;
using tcu::TestLog;

struct Compressed2DTestParameters : public Texture2DTestCaseParameters
{
};

class Compressed2DTestInstance : public TestInstance
{
public:
	typedef Compressed2DTestParameters	ParameterType;

										Compressed2DTestInstance	(Context&				context,
																	 const ParameterType&	testParameters);
	tcu::TestStatus						iterate						(void);

private:
										Compressed2DTestInstance	(const Compressed2DTestInstance& other);
	Compressed2DTestInstance&			operator=					(const Compressed2DTestInstance& other);

	const ParameterType&				m_testParameters;
	const tcu::CompressedTexFormat		m_compressedFormat;
	TestTexture2DSp						m_texture;
	TextureRenderer						m_renderer;
};

Compressed2DTestInstance::Compressed2DTestInstance (Context&				context,
													const ParameterType&	testParameters)
	: TestInstance			(context)
	, m_testParameters		(testParameters)
	, m_compressedFormat	(mapVkCompressedFormat(testParameters.format))
	, m_texture				(TestTexture2DSp(new pipeline::TestTexture2D(m_compressedFormat, testParameters.width, testParameters.height)))
	, m_renderer			(context, testParameters.sampleCount, testParameters.width, testParameters.height)
{
	m_renderer.add2DTexture(m_texture);
}

tcu::TestStatus Compressed2DTestInstance::iterate (void)
{
	tcu::TestLog&					log				= m_context.getTestContext().getLog();
	const pipeline::TestTexture2D&	texture			= m_renderer.get2DTexture(0);
	const tcu::TextureFormat		textureFormat	= texture.getTextureFormat();
	const tcu::TextureFormatInfo	formatInfo		= tcu::getTextureFormatInfo(textureFormat);

	ReferenceParams					sampleParams	(TEXTURETYPE_2D);
	tcu::Surface					rendered		(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
	vector<float>					texCoord;

	// Setup params for reference.
	sampleParams.sampler			= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
	sampleParams.samplerType		= SAMPLERTYPE_FLOAT;
	sampleParams.lodMode			= LODMODE_EXACT;
	sampleParams.colorBias			= formatInfo.lookupBias;
	sampleParams.colorScale			= formatInfo.lookupScale;

	log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;

	// Compute texture coordinates.
	computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));

	m_renderer.renderQuad(rendered, 0, &texCoord[0], sampleParams);

	// Compute reference.
	const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
	const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
	tcu::Surface			referenceFrame	(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
	sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat), m_texture->getTexture(), &texCoord[0], sampleParams);

	// Compare and log.
	const bool isOk = compareImages(log, referenceFrame, rendered, pixelFormat.getColorThreshold() + tcu::RGBA(1, 1, 1, 1));

	return isOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Image verification failed");
}

void populateTextureCompressedFormatTests (tcu::TestCaseGroup* compressedTextureTests)
{
	tcu::TestContext&	testCtx	= compressedTextureTests->getTestContext();

	// ETC2 and EAC compressed formats.
	const struct {
		const VkFormat	format;
	} etc2Formats[] =
	{
		{ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK		},
		{ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK		},
		{ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK	},
		{ VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK	},
		{ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK	},
		{ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK	},

		{ VK_FORMAT_EAC_R11_UNORM_BLOCK			},
		{ VK_FORMAT_EAC_R11_SNORM_BLOCK			},
		{ VK_FORMAT_EAC_R11G11_UNORM_BLOCK		},
		{ VK_FORMAT_EAC_R11G11_SNORM_BLOCK		},
	};

	const struct {
		const int	width;
		const int	height;
		const char*	name;
	} sizes[] =
	{
		{ 128, 64, "pot"  },
		{ 51,  65, "npot" },
	};

	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(etc2Formats); formatNdx++)
	{
		const string	formatStr	= de::toString(getFormatStr(etc2Formats[formatNdx].format));
		const string	nameBase	= de::toLower(formatStr.substr(10));

		Compressed2DTestParameters	testParameters;
		testParameters.format		= etc2Formats[formatNdx].format;
		testParameters.width		= sizes[sizeNdx].width;
		testParameters.height		= sizes[sizeNdx].height;
		testParameters.programs.push_back(PROGRAM_2D_FLOAT);

		compressedTextureTests->addChild(new TextureTestCase<Compressed2DTestInstance>(testCtx, (nameBase + "_2d_" + sizes[sizeNdx].name).c_str(), (formatStr + ", TEXTURETYPE_2D").c_str(), testParameters));
	}
}

} // anonymous

tcu::TestCaseGroup* createTextureCompressedFormatTests (tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "compressed", "Texture compressed format tests.", populateTextureCompressedFormatTests);
}

} // texture
} // vkt
<commit_msg>Properly initialize minFilter/magFilter when setting up test cases<commit_after>/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
 * Copyright (c) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Compressed texture tests.
 *//*--------------------------------------------------------------------*/

#include "vktTextureCompressedFormatTests.hpp"

#include "deString.h"
#include "deStringUtil.hpp"
#include "tcuCompressedTexture.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "vkImageUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktTextureTestUtil.hpp"
#include <string>
#include <vector>

namespace vkt
{
namespace texture
{
namespace
{

using namespace vk;
using namespace glu::TextureTestUtil;
using namespace texture::util;

using std::string;
using std::vector;
using tcu::Sampler;
using tcu::TestLog;

struct Compressed2DTestParameters : public Texture2DTestCaseParameters
{
};

class Compressed2DTestInstance : public TestInstance
{
public:
	typedef Compressed2DTestParameters	ParameterType;

										Compressed2DTestInstance	(Context&				context,
																	 const ParameterType&	testParameters);
	tcu::TestStatus						iterate						(void);

private:
										Compressed2DTestInstance	(const Compressed2DTestInstance& other);
	Compressed2DTestInstance&			operator=					(const Compressed2DTestInstance& other);

	const ParameterType&				m_testParameters;
	const tcu::CompressedTexFormat		m_compressedFormat;
	TestTexture2DSp						m_texture;
	TextureRenderer						m_renderer;
};

Compressed2DTestInstance::Compressed2DTestInstance (Context&				context,
													const ParameterType&	testParameters)
	: TestInstance			(context)
	, m_testParameters		(testParameters)
	, m_compressedFormat	(mapVkCompressedFormat(testParameters.format))
	, m_texture				(TestTexture2DSp(new pipeline::TestTexture2D(m_compressedFormat, testParameters.width, testParameters.height)))
	, m_renderer			(context, testParameters.sampleCount, testParameters.width, testParameters.height)
{
	m_renderer.add2DTexture(m_texture);
}

tcu::TestStatus Compressed2DTestInstance::iterate (void)
{
	tcu::TestLog&					log				= m_context.getTestContext().getLog();
	const pipeline::TestTexture2D&	texture			= m_renderer.get2DTexture(0);
	const tcu::TextureFormat		textureFormat	= texture.getTextureFormat();
	const tcu::TextureFormatInfo	formatInfo		= tcu::getTextureFormatInfo(textureFormat);

	ReferenceParams					sampleParams	(TEXTURETYPE_2D);
	tcu::Surface					rendered		(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
	vector<float>					texCoord;

	// Setup params for reference.
	sampleParams.sampler			= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
	sampleParams.samplerType		= SAMPLERTYPE_FLOAT;
	sampleParams.lodMode			= LODMODE_EXACT;
	sampleParams.colorBias			= formatInfo.lookupBias;
	sampleParams.colorScale			= formatInfo.lookupScale;

	log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;

	// Compute texture coordinates.
	computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));

	m_renderer.renderQuad(rendered, 0, &texCoord[0], sampleParams);

	// Compute reference.
	const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
	const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
	tcu::Surface			referenceFrame	(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
	sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat), m_texture->getTexture(), &texCoord[0], sampleParams);

	// Compare and log.
	const bool isOk = compareImages(log, referenceFrame, rendered, pixelFormat.getColorThreshold() + tcu::RGBA(1, 1, 1, 1));

	return isOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Image verification failed");
}

void populateTextureCompressedFormatTests (tcu::TestCaseGroup* compressedTextureTests)
{
	tcu::TestContext&	testCtx	= compressedTextureTests->getTestContext();

	// ETC2 and EAC compressed formats.
	const struct {
		const VkFormat	format;
	} etc2Formats[] =
	{
		{ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK		},
		{ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK		},
		{ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK	},
		{ VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK	},
		{ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK	},
		{ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK	},

		{ VK_FORMAT_EAC_R11_UNORM_BLOCK			},
		{ VK_FORMAT_EAC_R11_SNORM_BLOCK			},
		{ VK_FORMAT_EAC_R11G11_UNORM_BLOCK		},
		{ VK_FORMAT_EAC_R11G11_SNORM_BLOCK		},
	};

	const struct {
		const int	width;
		const int	height;
		const char*	name;
	} sizes[] =
	{
		{ 128, 64, "pot"  },
		{ 51,  65, "npot" },
	};

	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(etc2Formats); formatNdx++)
	{
		const string	formatStr	= de::toString(getFormatStr(etc2Formats[formatNdx].format));
		const string	nameBase	= de::toLower(formatStr.substr(10));

		Compressed2DTestParameters	testParameters;
		testParameters.format		= etc2Formats[formatNdx].format;
		testParameters.width		= sizes[sizeNdx].width;
		testParameters.height		= sizes[sizeNdx].height;
		testParameters.minFilter	= tcu::Sampler::NEAREST;
		testParameters.magFilter	= tcu::Sampler::NEAREST;
		testParameters.programs.push_back(PROGRAM_2D_FLOAT);

		compressedTextureTests->addChild(new TextureTestCase<Compressed2DTestInstance>(testCtx, (nameBase + "_2d_" + sizes[sizeNdx].name).c_str(), (formatStr + ", TEXTURETYPE_2D").c_str(), testParameters));
	}
}

} // anonymous

tcu::TestCaseGroup* createTextureCompressedFormatTests (tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "compressed", "Texture compressed format tests.", populateTextureCompressedFormatTests);
}

} // texture
} // vkt
<|endoftext|>


<commit_before>static void
show_type(Vec<CreationSet *> &t, FILE *fp) {
  fprintf(fp, "( ");
  forv_CreationSet(cs, t) if (cs) {
    if (cs->sym->name)
      fprintf(fp, "%s ", cs->sym->name);
    else if (cs->sym->constant)
      fprintf(fp, "\"%s\" ", cs->sym->constant);
    else
      fprintf(fp, "%d ", cs->sym->id);
  }
  fprintf(fp, ") ");
}

static void
show_sym(Sym *s, FILE *fp) {
  if (s->is_pattern) {
    fprintf(fp, "( ");
    forv_Sym(ss, s->has) {
      if (ss != s->has.v[0])
	fprintf(fp, ", ");
      show_sym(ss, fp);
    }
    fprintf(fp, ") ");
  } else if (s->name)
    fprintf(fp, "%s ", s->name);
  else if (s->constant)
    fprintf(fp, "\"%s\" ", s->constant);
  if (s->type && s->type->name)
    fprintf(fp, "= %s", s->type->name);
  else if (s->must_implement &&
	   s->must_implement == s->must_specialize)
    fprintf(fp, ": %s", s->must_implement->name);
  else if (s->must_implement)
    fprintf(fp, "< %s", s->must_implement->name);
  else if (s->must_specialize)
    fprintf(fp, "@ %s", s->must_specialize->name);
}

static void
show_fun(Fun *f, FILE *fp) {
  fprintf(fp, "%s:%d: ", f->filename(), f->line());
  forv_Sym(s, f->sym->has)
    show_sym(s, fp);
}

void
fa_print_backward(AVar *v, FILE *fp) {
  Vec<AVar *> done, todo;
  todo.add(v);
  done.set_add(v);
  for (int i = 0; i < todo.n; i++) {
    v = todo.v[i];
    if (v->var) {
      if (v->var->sym) {
	if (v->var->sym->name)
	  fprintf(fp, "%s %d\n", v->var->sym->name, v->var->sym->id);
	else
	  fprintf(fp, "%d\n", v->var->sym->id);
      } else
	fprintf(fp, "VAR %p\n", v->var);
    } else
      fprintf(fp, "AVAR %p\n", v);
    show_type(*v->out, fp); fprintf(fp, "\n");
    forv_AVar(vv, v->backward) if (vv) {
      if (!done.set_in(vv)) {
	todo.add(vv);
	done.set_add(vv);
      }
    }
  }
}

void
fa_dump_var_types(AVar *av, FILE *fp, int verbose = verbose_level) {
  Var *v = av->var;
  if (verbose < 2 && (!v->sym->name || v->sym->is_symbol))
    return;
  if (!v->sym->in)
    fprintf(fp, "::");
  else if (v->sym->in->name)
    fprintf(fp, "%s::", v->sym->in->name);
  else
    fprintf(fp, "%d::", v->sym->in->id);
  if (v->sym->name)
    fprintf(fp, "%s(%d) ", v->sym->name, v->sym->id);
  else
    fprintf(fp, "(%d) ", v->sym->id);
  if (v->sym->constant)
    fprintf(fp, "\"%s\" ", v->sym->constant);
  else {
    fprintf(fp, "\"");
    print(fp, v->sym->imm, v->sym->type);
    fprintf(fp, "\" ");
  }
  show_type(*av->out, fp);
  fprintf(fp, "\n");
}

void
fa_dump_types(FA *fa, FILE *fp) {
  Vec<Var *> gvars;
  forv_Fun(f, fa->funs) {
    forv_EntrySet(es, f->ess) {
      if (f->sym->name)
	fprintf(fp, "function %s (%d) ", f->sym->name, f->sym->id);
      else
	fprintf(fp, "function %d ", f->sym->id);
      fprintf(fp, "entry set with %d edges\n", es->edges.count());
      Vec<Var *> vars;
      f->collect_Vars(vars);
      forv_Var(v, vars) {
	if (v->sym->global_scope) {
	  gvars.set_add(v);
	  continue;
	}
	fa_dump_var_types(make_AVar(v, es), fp);
      }
    }
  }
  gvars.set_to_vec();
  fprintf(fp, "globals\n");
  forv_Var(v, gvars)
    if (!v->sym->is_constant && !v->sym->is_symbol)
      fa_dump_var_types(unique_AVar(v, GLOBAL_CONTOUR), fp);
}

static void
show_illegal_type(FILE *fp, ATypeViolation *v) {
  AVar *av = v->av;
  if (av->var->sym->name)
    fprintf(stderr, "'%s' ", av->var->sym->name);
  else if (verbose_level)
    fprintf(stderr, "expr:%d ", av->var->sym->id);
  else
    fprintf(stderr, "expression ");
  if (verbose_level) {
    fprintf(stderr, "id:%d ", av->var->sym->id);
    if (av->out->n) {
      fprintf(stderr, ": ");
      show_type(*av->out, fp);
    }
  }
  fprintf(stderr, "illegal: ");
  show_type(*v->type, fp);
  fprintf(stderr, "\n");
}

static void
show_call_tree(FILE *fp, PNode *p, EntrySet *es, int depth = 0) {
  depth++;
  if (depth > print_call_depth || !p->code)
    return;
  if (depth > 1 && p->code->filename()) {
    for (int x = 0; x < depth; x++)
      fprintf(stderr, " ");
    fprintf(stderr, "called from %s:%d\n", p->code->filename(), p->code->line());
  }
  AEdge **last = es->edges.last();
  for (AEdge **x = es->edges.first(); x < last; x++) if (*x)
    show_call_tree(fp, (*x)->pnode, (*x)->from, depth);
}

static void
show_call_tree(FILE *fp, AVar *av) {
  EntrySet *es = (EntrySet*)av->contour;
  AEdge **last = es->edges.last();
  for (AEdge **x = es->edges.first(); x < last; x++) if (*x)
    show_call_tree(fp, (*x)->pnode, (*x)->from, 1);
}

static int
compar_tv_pos(const void *aa, const void *bb) {
  ATypeViolation *a = (*(ATypeViolation**)aa);
  ATypeViolation *b = (*(ATypeViolation**)bb);
  AST *aast = a->send ? a->send->var->def->code->ast : 0;
  if (!aast) aast = a->av->var->sym->ast;
  AST *bast = b->send ? b->send->var->def->code->ast : 0;
  if (!bast) bast = b->av->var->sym->ast;
  if (!aast || !bast) {
    if (bast) return -1;
    if (aast) return 1;
    return 0;
  }
  if (!aast->pathname() || !bast->pathname()) {
    if (bast->pathname()) return -1;
    if (aast->pathname()) return 1;
  } else {
    int x = strcmp(aast->pathname(), bast->pathname());
    if (x) return x;
  }
  int i = aast->line();
  int j = bast->line();
  return (i > j) ? 1 : ((i < j) ? -1 : 0);
}

static void
show_violations(FA *fa, FILE *fp) {
  Vec<ATypeViolation *> vv;
  forv_ATypeViolation(v, type_violations) if (v)
    vv.add(v);
  qsort(vv.v, vv.n, sizeof(vv.v[0]), compar_tv_pos);
  forv_ATypeViolation(v, vv) if (v) {
    if (!verbose_level && !v->av->var->sym->name)
      continue;
    if (v->send)
      fprintf(stderr, "%s:%d: ", v->send->var->def->code->filename(),
	      v->send->var->def->code->line());
    else if (v->av->var->sym->ast)
      fprintf(stderr, "%s:%d: ", v->av->var->sym->filename(),
	      v->av->var->sym->line());
    else
      fprintf(stderr, "error: ");
    switch (v->kind) {
      default: assert(0);
      case ATypeViolation_PRIMITIVE_ARGUMENT:
	fprintf(stderr, "illegal primitive argument type ");
	show_illegal_type(fp, v);
	break;
      case ATypeViolation_SEND_ARGUMENT:
	if (v->av->var->sym->is_symbol &&
	    v->send->var->def->rvals.v[0] == v->av->var)
	  fprintf(stderr, "unresolved call '%s'\n", v->av->var->sym->name);
	else {
	  fprintf(stderr, "illegal call argument type ");
	  show_illegal_type(fp, v);
	}
	break;
      case ATypeViolation_DISPATCH_AMBIGUITY:
	fprintf(stderr, "ambiguous call '%s'\n", v->av->var->sym->name);
	fprintf(stderr, "  candidate functions:\n");
	forv_Fun(f, *v->funs) {
	  fprintf(stderr, "    ");
	  show_fun(f, stderr);
	  fprintf(stderr, "\n");
	}
	break;
      case ATypeViolation_MEMBER:
	if (v->av->out->n == 1)
	  fprintf(stderr, "unresolved member '%s'", v->av->out->v[0]->sym->name);
	else {
	  fprintf(stderr, "unresolved member\n");
	  forv_CreationSet(selector, *v->av->out)
	    fprintf(stderr, "  selector '%s'\n", selector->sym->name);
	}
	if (v->type->n == 1)
	  fprintf(stderr, "  class '%s'\n", v->type->v[0]->sym->name ? v->type->v[0]->sym->name :
		  "<anonymous>");
	else {
	  fprintf(stderr, "  classes\n");
	  forv_CreationSet(cs, *v->type)
	    fprintf(stderr, "  class '%s'\n", cs->sym->name);
	}
	break;
      case ATypeViolation_MATCH:
	if (v->type->n == 1)
	  fprintf(stderr, "near '%s' unmatched type '%s'\n",
		  v->av->var->sym->name ? v->av->var->sym->name : "<anonymous>",
		  v->type->v[0]->sym->name);
	else {
	  fprintf(stderr, "near '%s' unmatched type\n");
	  forv_CreationSet(cs, *v->type)
	    fprintf(stderr, "  type '%s'\n", cs->sym->name);
	}
	break;
      case ATypeViolation_NOTYPE:
	if (v->av->var->sym->name)
	  fprintf(stderr, "'%s' ", v->av->var->sym->name);
	else
	  fprintf(stderr, "expression ");
	fprintf(stderr, "has no type\n");
	break;
    }
    if (v->send)
      show_call_tree(fp, v->send->var->def, (EntrySet*)v->send->contour);
    else if (v->av->contour_is_entry_set)
      show_call_tree(fp, v->av);
  }
}

static char *fn(char *s) {
  if (!s)
    return "<none>";
  char *filename = strrchr(s, '/');
  if (filename)
    return filename + 1;
  return s;
}

void
log_var_types(Var *v, Fun *f) {
  if (!v->sym->name || v->sym->is_symbol)
    return;
  if (!v->sym->in)
    log(LOG_TEST_FA, "::");
  else if (v->sym->in->name)
    log(LOG_TEST_FA, "%s::", v->sym->in->name);
  else
    log(LOG_TEST_FA, "%d::", v->sym->in->id);
  if (v->sym->name)
    log(LOG_TEST_FA, "%s(%s:%d) ", v->sym->name, fn(v->sym->filename()), v->sym->line());
  else
    log(LOG_TEST_FA, "(%s:%d) ", fn(v->sym->filename()), v->sym->line());
  Vec<CreationSet *> css;
  for (int i = 0; i < v->avars.n; i++) if (v->avars.v[i].key) {
    AVar *av = v->avars.v[i].value;
    if (!f || f->ess.in(((EntrySet*)av->contour)))
      css.set_union(*av->out);
  }
  assert(css.n);
  log(LOG_TEST_FA, "( ");
  Vec<Sym *> syms;
  forv_CreationSet(cs, css) if (cs)
    syms.set_add(cs->sym);
  syms.set_to_vec();
  qsort(syms.v, syms.n, sizeof(syms.v[0]), compar_syms);
  forv_Sym(s, syms) {
    if (s->name)
      log(LOG_TEST_FA, "%s ", s->name);
    else if (s->constant)
      log(LOG_TEST_FA, "\"%s\" ", s->constant);
    log(LOG_TEST_FA, "(%s:%d) ", fn(s->filename()), s->line());
  }
  log(LOG_TEST_FA, ")\n");
}

<commit_msg>SEGV in debug output of some constants<commit_after>static void
show_type(Vec<CreationSet *> &t, FILE *fp) {
  fprintf(fp, "( ");
  forv_CreationSet(cs, t) if (cs) {
    if (cs->sym->name)
      fprintf(fp, "%s ", cs->sym->name);
    else if (cs->sym->constant)
      fprintf(fp, "\"%s\" ", cs->sym->constant);
    else
      fprintf(fp, "%d ", cs->sym->id);
  }
  fprintf(fp, ") ");
}

static void
show_sym(Sym *s, FILE *fp) {
  if (s->is_pattern) {
    fprintf(fp, "( ");
    forv_Sym(ss, s->has) {
      if (ss != s->has.v[0])
	fprintf(fp, ", ");
      show_sym(ss, fp);
    }
    fprintf(fp, ") ");
  } else if (s->name)
    fprintf(fp, "%s ", s->name);
  else if (s->constant)
    fprintf(fp, "\"%s\" ", s->constant);
  if (s->type && s->type->name)
    fprintf(fp, "= %s", s->type->name);
  else if (s->must_implement &&
	   s->must_implement == s->must_specialize)
    fprintf(fp, ": %s", s->must_implement->name);
  else if (s->must_implement)
    fprintf(fp, "< %s", s->must_implement->name);
  else if (s->must_specialize)
    fprintf(fp, "@ %s", s->must_specialize->name);
}

static void
show_fun(Fun *f, FILE *fp) {
  fprintf(fp, "%s:%d: ", f->filename(), f->line());
  forv_Sym(s, f->sym->has)
    show_sym(s, fp);
}

void
fa_print_backward(AVar *v, FILE *fp) {
  Vec<AVar *> done, todo;
  todo.add(v);
  done.set_add(v);
  for (int i = 0; i < todo.n; i++) {
    v = todo.v[i];
    if (v->var) {
      if (v->var->sym) {
	if (v->var->sym->name)
	  fprintf(fp, "%s %d\n", v->var->sym->name, v->var->sym->id);
	else
	  fprintf(fp, "%d\n", v->var->sym->id);
      } else
	fprintf(fp, "VAR %p\n", v->var);
    } else
      fprintf(fp, "AVAR %p\n", v);
    show_type(*v->out, fp); fprintf(fp, "\n");
    forv_AVar(vv, v->backward) if (vv) {
      if (!done.set_in(vv)) {
	todo.add(vv);
	done.set_add(vv);
      }
    }
  }
}

void
fa_dump_var_types(AVar *av, FILE *fp, int verbose = verbose_level) {
  Var *v = av->var;
  if (verbose < 2 && (!v->sym->name || v->sym->is_symbol))
    return;
  if (!v->sym->in)
    fprintf(fp, "::");
  else if (v->sym->in->name)
    fprintf(fp, "%s::", v->sym->in->name);
  else
    fprintf(fp, "%d::", v->sym->in->id);
  if (v->sym->name)
    fprintf(fp, "%s(%d) ", v->sym->name, v->sym->id);
  else
    fprintf(fp, "(%d) ", v->sym->id);
  if (v->sym->is_constant) {
    if (v->sym->constant)
      fprintf(fp, "\"%s\" ", v->sym->constant);
    else {
      fprintf(fp, "\"");
      print(fp, v->sym->imm, v->sym->type);
      fprintf(fp, "\" ");
    }
  }
  show_type(*av->out, fp);
  fprintf(fp, "\n");
}

void
fa_dump_types(FA *fa, FILE *fp) {
  Vec<Var *> gvars;
  forv_Fun(f, fa->funs) {
    forv_EntrySet(es, f->ess) {
      if (f->sym->name)
	fprintf(fp, "function %s (%d) ", f->sym->name, f->sym->id);
      else
	fprintf(fp, "function %d ", f->sym->id);
      fprintf(fp, "entry set with %d edges\n", es->edges.count());
      Vec<Var *> vars;
      f->collect_Vars(vars);
      forv_Var(v, vars) {
	if (v->sym->global_scope) {
	  gvars.set_add(v);
	  continue;
	}
	fa_dump_var_types(make_AVar(v, es), fp);
      }
    }
  }
  gvars.set_to_vec();
  fprintf(fp, "globals\n");
  forv_Var(v, gvars)
    if (!v->sym->is_constant && !v->sym->is_symbol)
      fa_dump_var_types(unique_AVar(v, GLOBAL_CONTOUR), fp);
}

static void
show_illegal_type(FILE *fp, ATypeViolation *v) {
  AVar *av = v->av;
  if (av->var->sym->name)
    fprintf(stderr, "'%s' ", av->var->sym->name);
  else if (verbose_level)
    fprintf(stderr, "expr:%d ", av->var->sym->id);
  else
    fprintf(stderr, "expression ");
  if (verbose_level) {
    fprintf(stderr, "id:%d ", av->var->sym->id);
    if (av->out->n) {
      fprintf(stderr, ": ");
      show_type(*av->out, fp);
    }
  }
  fprintf(stderr, "illegal: ");
  show_type(*v->type, fp);
  fprintf(stderr, "\n");
}

static void
show_call_tree(FILE *fp, PNode *p, EntrySet *es, int depth = 0) {
  depth++;
  if (depth > print_call_depth || !p->code)
    return;
  if (depth > 1 && p->code->filename()) {
    for (int x = 0; x < depth; x++)
      fprintf(stderr, " ");
    fprintf(stderr, "called from %s:%d\n", p->code->filename(), p->code->line());
  }
  AEdge **last = es->edges.last();
  for (AEdge **x = es->edges.first(); x < last; x++) if (*x)
    show_call_tree(fp, (*x)->pnode, (*x)->from, depth);
}

static void
show_call_tree(FILE *fp, AVar *av) {
  EntrySet *es = (EntrySet*)av->contour;
  AEdge **last = es->edges.last();
  for (AEdge **x = es->edges.first(); x < last; x++) if (*x)
    show_call_tree(fp, (*x)->pnode, (*x)->from, 1);
}

static int
compar_tv_pos(const void *aa, const void *bb) {
  ATypeViolation *a = (*(ATypeViolation**)aa);
  ATypeViolation *b = (*(ATypeViolation**)bb);
  AST *aast = a->send ? a->send->var->def->code->ast : 0;
  if (!aast) aast = a->av->var->sym->ast;
  AST *bast = b->send ? b->send->var->def->code->ast : 0;
  if (!bast) bast = b->av->var->sym->ast;
  if (!aast || !bast) {
    if (bast) return -1;
    if (aast) return 1;
    return 0;
  }
  if (!aast->pathname() || !bast->pathname()) {
    if (bast->pathname()) return -1;
    if (aast->pathname()) return 1;
  } else {
    int x = strcmp(aast->pathname(), bast->pathname());
    if (x) return x;
  }
  int i = aast->line();
  int j = bast->line();
  return (i > j) ? 1 : ((i < j) ? -1 : 0);
}

static void
show_violations(FA *fa, FILE *fp) {
  Vec<ATypeViolation *> vv;
  forv_ATypeViolation(v, type_violations) if (v)
    vv.add(v);
  qsort(vv.v, vv.n, sizeof(vv.v[0]), compar_tv_pos);
  forv_ATypeViolation(v, vv) if (v) {
    if (!verbose_level && !v->av->var->sym->name)
      continue;
    if (v->send)
      fprintf(stderr, "%s:%d: ", v->send->var->def->code->filename(),
	      v->send->var->def->code->line());
    else if (v->av->var->sym->ast)
      fprintf(stderr, "%s:%d: ", v->av->var->sym->filename(),
	      v->av->var->sym->line());
    else
      fprintf(stderr, "error: ");
    switch (v->kind) {
      default: assert(0);
      case ATypeViolation_PRIMITIVE_ARGUMENT:
	fprintf(stderr, "illegal primitive argument type ");
	show_illegal_type(fp, v);
	break;
      case ATypeViolation_SEND_ARGUMENT:
	if (v->av->var->sym->is_symbol &&
	    v->send->var->def->rvals.v[0] == v->av->var)
	  fprintf(stderr, "unresolved call '%s'\n", v->av->var->sym->name);
	else {
	  fprintf(stderr, "illegal call argument type ");
	  show_illegal_type(fp, v);
	}
	break;
      case ATypeViolation_DISPATCH_AMBIGUITY:
	fprintf(stderr, "ambiguous call '%s'\n", v->av->var->sym->name);
	fprintf(stderr, "  candidate functions:\n");
	forv_Fun(f, *v->funs) {
	  fprintf(stderr, "    ");
	  show_fun(f, stderr);
	  fprintf(stderr, "\n");
	}
	break;
      case ATypeViolation_MEMBER:
	if (v->av->out->n == 1)
	  fprintf(stderr, "unresolved member '%s'", v->av->out->v[0]->sym->name);
	else {
	  fprintf(stderr, "unresolved member\n");
	  forv_CreationSet(selector, *v->av->out)
	    fprintf(stderr, "  selector '%s'\n", selector->sym->name);
	}
	if (v->type->n == 1)
	  fprintf(stderr, "  class '%s'\n", v->type->v[0]->sym->name ? v->type->v[0]->sym->name :
		  "<anonymous>");
	else {
	  fprintf(stderr, "  classes\n");
	  forv_CreationSet(cs, *v->type)
	    fprintf(stderr, "  class '%s'\n", cs->sym->name);
	}
	break;
      case ATypeViolation_MATCH:
	if (v->type->n == 1)
	  fprintf(stderr, "near '%s' unmatched type '%s'\n",
		  v->av->var->sym->name ? v->av->var->sym->name : "<anonymous>",
		  v->type->v[0]->sym->name);
	else {
	  fprintf(stderr, "near '%s' unmatched type\n");
	  forv_CreationSet(cs, *v->type)
	    fprintf(stderr, "  type '%s'\n", cs->sym->name);
	}
	break;
      case ATypeViolation_NOTYPE:
	if (v->av->var->sym->name)
	  fprintf(stderr, "'%s' ", v->av->var->sym->name);
	else
	  fprintf(stderr, "expression ");
	fprintf(stderr, "has no type\n");
	break;
    }
    if (v->send)
      show_call_tree(fp, v->send->var->def, (EntrySet*)v->send->contour);
    else if (v->av->contour_is_entry_set)
      show_call_tree(fp, v->av);
  }
}

static char *fn(char *s) {
  if (!s)
    return "<none>";
  char *filename = strrchr(s, '/');
  if (filename)
    return filename + 1;
  return s;
}

void
log_var_types(Var *v, Fun *f) {
  if (!v->sym->name || v->sym->is_symbol)
    return;
  if (!v->sym->in)
    log(LOG_TEST_FA, "::");
  else if (v->sym->in->name)
    log(LOG_TEST_FA, "%s::", v->sym->in->name);
  else
    log(LOG_TEST_FA, "%d::", v->sym->in->id);
  if (v->sym->name)
    log(LOG_TEST_FA, "%s(%s:%d) ", v->sym->name, fn(v->sym->filename()), v->sym->line());
  else
    log(LOG_TEST_FA, "(%s:%d) ", fn(v->sym->filename()), v->sym->line());
  Vec<CreationSet *> css;
  for (int i = 0; i < v->avars.n; i++) if (v->avars.v[i].key) {
    AVar *av = v->avars.v[i].value;
    if (!f || f->ess.in(((EntrySet*)av->contour)))
      css.set_union(*av->out);
  }
  assert(css.n);
  log(LOG_TEST_FA, "( ");
  Vec<Sym *> syms;
  forv_CreationSet(cs, css) if (cs)
    syms.set_add(cs->sym);
  syms.set_to_vec();
  qsort(syms.v, syms.n, sizeof(syms.v[0]), compar_syms);
  forv_Sym(s, syms) {
    if (s->name)
      log(LOG_TEST_FA, "%s ", s->name);
    else if (s->constant)
      log(LOG_TEST_FA, "\"%s\" ", s->constant);
    log(LOG_TEST_FA, "(%s:%d) ", fn(s->filename()), s->line());
  }
  log(LOG_TEST_FA, ")\n");
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#include "core/do_with.hh"
#include "cql_test_env.hh"
#include "cql3/query_processor.hh"
#include "cql3/query_options.hh"
#include "core/distributed.hh"
#include "core/shared_ptr.hh"
#include "utils/UUID_gen.hh"
#include "message/messaging_service.hh"
#include "service/storage_service.hh"

class in_memory_cql_env : public cql_test_env {
public:
    static auto constexpr ks_name = "ks";
private:
    ::shared_ptr<distributed<database>> _db;
    ::shared_ptr<distributed<cql3::query_processor>> _qp;
    ::shared_ptr<distributed<service::storage_proxy>> _proxy;
private:
    struct core_local_state {
        service::client_state client_state;

        core_local_state()
            : client_state(service::client_state::for_internal_calls()) {
            client_state.set_keyspace(ks_name);
        }

        future<> stop() {
            return make_ready_future<>();
        }
    };
    distributed<core_local_state> _core_local;
private:
    auto make_query_state() {
        return ::make_shared<service::query_state>(_core_local.local().client_state);
    }
public:
    in_memory_cql_env(
        ::shared_ptr<distributed<database>> db,
        ::shared_ptr<distributed<cql3::query_processor>> qp,
        ::shared_ptr<distributed<service::storage_proxy>> proxy)
            : _db(db)
            , _qp(qp)
            , _proxy(proxy)
    { }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_cql(const sstring& text) override {
        auto qs = make_query_state();
        return _qp->local().process(text, *qs, cql3::query_options::DEFAULT).finally([qs] {});
    }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_cql(
        const sstring& text,
        std::unique_ptr<cql3::query_options> qo) override
    {
        auto qs = make_query_state();
        auto& lqo = *qo;
        return _qp->local().process(text, *qs, lqo).finally([qs, qo = std::move(qo)] {});
    }

    virtual future<bytes> prepare(sstring query) override {
        return _qp->invoke_on_all([query, this] (auto& local_qp) {
            auto qs = this->make_query_state();
            return local_qp.prepare(query, *qs).finally([qs] {}).discard_result();
        }).then([query, this] {
            return _qp->local().compute_id(query, ks_name);
        });
    }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_prepared(
        bytes id,
        std::vector<bytes_opt> values) override
    {
        auto prepared = _qp->local().get_prepared(id);
        assert(bool(prepared));
        auto stmt = prepared->statement;
        assert(stmt->get_bound_terms() == values.size());

        int32_t protocol_version = 3;
        auto options = ::make_shared<cql3::query_options>(db::consistency_level::ONE, std::experimental::nullopt, std::move(values), false,
                                                          cql3::query_options::specific_options::DEFAULT, protocol_version, serialization_format::use_32_bit());
        options->prepare(prepared->bound_names);

        auto qs = make_query_state();
        return _qp->local().process_statement(stmt, *qs, *options)
            .finally([options, qs] {});
    }

    virtual future<> create_table(std::function<schema(const sstring&)> schema_maker) override {
        auto id = utils::UUID_gen::get_time_UUID();
        return _db->invoke_on_all([schema_maker, id, this] (database& db) {
            auto cf_schema = make_lw_shared(schema_maker(ks_name));
            cf_schema->set_id(id);
            auto& ks = db.find_keyspace(ks_name);
            auto cfg = ks.make_column_family_config(*cf_schema);
            db.add_column_family(std::move(cf_schema), std::move(cfg));
        });
    }

    virtual future<> require_keyspace_exists(const sstring& ks_name) override {
        auto& db = _db->local();
        assert(db.has_keyspace(ks_name));
        return make_ready_future<>();
    }

    virtual future<> require_table_exists(const sstring& ks_name, const sstring& table_name) override {
        auto& db = _db->local();
        assert(db.has_schema(ks_name, table_name));
        return make_ready_future<>();
    }

    virtual future<> require_column_has_value(const sstring& table_name,
                                      std::vector<boost::any> pk,
                                      std::vector<boost::any> ck,
                                      const sstring& column_name,
                                      boost::any expected) override {
        auto& db = _db->local();
        auto& cf = db.find_column_family(ks_name, table_name);
        auto schema = cf.schema();
        auto pkey = partition_key::from_deeply_exploded(*schema, pk);
        auto dk = dht::global_partitioner().decorate_key(*schema, pkey);
        auto shard = db.shard_of(dk._token);
        return _db->invoke_on(shard, [pkey = std::move(pkey),
                                      ck = std::move(ck),
                                      ks_name = std::move(ks_name),
                                      column_name = std::move(column_name),
                                      expected = std::move(expected),
                                      table_name = std::move(table_name)] (database& db) mutable {
          auto& cf = db.find_column_family(ks_name, table_name);
          auto schema = cf.schema();
          return cf.find_partition_slow(pkey).then([schema, ck, column_name, expected] (column_family::const_mutation_partition_ptr p) {
            assert(p != nullptr);
            auto row = p->find_row(clustering_key::from_deeply_exploded(*schema, ck));
            assert(row != nullptr);
            auto col_def = schema->get_column_definition(utf8_type->decompose(column_name));
            assert(col_def != nullptr);
            const atomic_cell_or_collection* cell = row->find_cell(col_def->id);
            if (!cell) {
                assert(((void)"column not set", 0));
            }
            bytes actual;
            if (!col_def->type->is_multi_cell()) {
                auto c = cell->as_atomic_cell();
                assert(c.is_live());
                actual = { c.value().begin(), c.value().end() };
            } else {
                auto c = cell->as_collection_mutation();
                auto type = dynamic_pointer_cast<const collection_type_impl>(col_def->type);
                actual = type->to_value(type->deserialize_mutation_form(c),
                                        serialization_format::internal());
            }
            assert(col_def->type->equal(actual, col_def->type->decompose(expected)));
          });
        });
    }

    virtual database& local_db() override {
        return _db->local();
    }

    future<> start() {
        return _core_local.start().then([this] () {
            auto query = sprint("create keyspace %s with replication = { 'class' : 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor' : 1 };", sstring{ks_name});
            return execute_cql(query).discard_result().then([] {
                return make_ready_future<>();
            });
        });
    }

    virtual future<> stop() override {
        return _core_local.stop().then([this] {
            return _qp->stop().then([this] {
                return _proxy->stop().then([this] {
                    return _db->stop().then([] {
                        return locator::i_endpoint_snitch::stop_snitch();
                    });
                });
            });
        });
    }
};

future<> init_once() {
    static bool done = false;
    if (!done) {
        done = true;
        return service::init_storage_service().then([] {
                return net::init_messaging_service("127.0.0.1", db::config::seed_provider_type()).then([] {
                });
        });
    } else {
        return make_ready_future();
    }
}

future<::shared_ptr<cql_test_env>> make_env_for_test() {
    return init_once().then([] {
        using namespace locator;
        return i_endpoint_snitch::create_snitch("org.apache.cassandra.locator.SimpleSnitch").then([] {
            auto db = ::make_shared<distributed<database>>();
            auto cfg = make_lw_shared<db::config>();
            cfg->data_file_directories() = {};
            return db->start(std::move(*cfg)).then([db] {
                auto proxy = ::make_shared<distributed<service::storage_proxy>>();
                auto qp = ::make_shared<distributed<cql3::query_processor>>();
                return proxy->start(std::ref(*db)).then([qp, db, proxy] {
                    return qp->start(std::ref(*proxy), std::ref(*db)).then([db, proxy, qp] {
                        auto env = ::make_shared<in_memory_cql_env>(db, qp, proxy);
                        return env->start().then([env] () -> ::shared_ptr<cql_test_env> {
                            return env;
                        });
                    });
                });
            });
        });
    });
}

future<> do_with_cql_env(std::function<future<>(cql_test_env&)> func) {
    return make_env_for_test().then([func = std::move(func)] (auto e) mutable {
        return do_with(std::move(func), [e] (auto& f) {
            return f(*e);
        }).finally([e] {
            return e->stop().finally([e] {});
        });
    });
}
<commit_msg>cql_test_env: Start the global snitch before storage service<commit_after>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#include "core/do_with.hh"
#include "cql_test_env.hh"
#include "cql3/query_processor.hh"
#include "cql3/query_options.hh"
#include "core/distributed.hh"
#include "core/shared_ptr.hh"
#include "utils/UUID_gen.hh"
#include "message/messaging_service.hh"
#include "service/storage_service.hh"

class in_memory_cql_env : public cql_test_env {
public:
    static auto constexpr ks_name = "ks";
private:
    ::shared_ptr<distributed<database>> _db;
    ::shared_ptr<distributed<cql3::query_processor>> _qp;
    ::shared_ptr<distributed<service::storage_proxy>> _proxy;
private:
    struct core_local_state {
        service::client_state client_state;

        core_local_state()
            : client_state(service::client_state::for_internal_calls()) {
            client_state.set_keyspace(ks_name);
        }

        future<> stop() {
            return make_ready_future<>();
        }
    };
    distributed<core_local_state> _core_local;
private:
    auto make_query_state() {
        return ::make_shared<service::query_state>(_core_local.local().client_state);
    }
public:
    in_memory_cql_env(
        ::shared_ptr<distributed<database>> db,
        ::shared_ptr<distributed<cql3::query_processor>> qp,
        ::shared_ptr<distributed<service::storage_proxy>> proxy)
            : _db(db)
            , _qp(qp)
            , _proxy(proxy)
    { }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_cql(const sstring& text) override {
        auto qs = make_query_state();
        return _qp->local().process(text, *qs, cql3::query_options::DEFAULT).finally([qs] {});
    }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_cql(
        const sstring& text,
        std::unique_ptr<cql3::query_options> qo) override
    {
        auto qs = make_query_state();
        auto& lqo = *qo;
        return _qp->local().process(text, *qs, lqo).finally([qs, qo = std::move(qo)] {});
    }

    virtual future<bytes> prepare(sstring query) override {
        return _qp->invoke_on_all([query, this] (auto& local_qp) {
            auto qs = this->make_query_state();
            return local_qp.prepare(query, *qs).finally([qs] {}).discard_result();
        }).then([query, this] {
            return _qp->local().compute_id(query, ks_name);
        });
    }

    virtual future<::shared_ptr<transport::messages::result_message>> execute_prepared(
        bytes id,
        std::vector<bytes_opt> values) override
    {
        auto prepared = _qp->local().get_prepared(id);
        assert(bool(prepared));
        auto stmt = prepared->statement;
        assert(stmt->get_bound_terms() == values.size());

        int32_t protocol_version = 3;
        auto options = ::make_shared<cql3::query_options>(db::consistency_level::ONE, std::experimental::nullopt, std::move(values), false,
                                                          cql3::query_options::specific_options::DEFAULT, protocol_version, serialization_format::use_32_bit());
        options->prepare(prepared->bound_names);

        auto qs = make_query_state();
        return _qp->local().process_statement(stmt, *qs, *options)
            .finally([options, qs] {});
    }

    virtual future<> create_table(std::function<schema(const sstring&)> schema_maker) override {
        auto id = utils::UUID_gen::get_time_UUID();
        return _db->invoke_on_all([schema_maker, id, this] (database& db) {
            auto cf_schema = make_lw_shared(schema_maker(ks_name));
            cf_schema->set_id(id);
            auto& ks = db.find_keyspace(ks_name);
            auto cfg = ks.make_column_family_config(*cf_schema);
            db.add_column_family(std::move(cf_schema), std::move(cfg));
        });
    }

    virtual future<> require_keyspace_exists(const sstring& ks_name) override {
        auto& db = _db->local();
        assert(db.has_keyspace(ks_name));
        return make_ready_future<>();
    }

    virtual future<> require_table_exists(const sstring& ks_name, const sstring& table_name) override {
        auto& db = _db->local();
        assert(db.has_schema(ks_name, table_name));
        return make_ready_future<>();
    }

    virtual future<> require_column_has_value(const sstring& table_name,
                                      std::vector<boost::any> pk,
                                      std::vector<boost::any> ck,
                                      const sstring& column_name,
                                      boost::any expected) override {
        auto& db = _db->local();
        auto& cf = db.find_column_family(ks_name, table_name);
        auto schema = cf.schema();
        auto pkey = partition_key::from_deeply_exploded(*schema, pk);
        auto dk = dht::global_partitioner().decorate_key(*schema, pkey);
        auto shard = db.shard_of(dk._token);
        return _db->invoke_on(shard, [pkey = std::move(pkey),
                                      ck = std::move(ck),
                                      ks_name = std::move(ks_name),
                                      column_name = std::move(column_name),
                                      expected = std::move(expected),
                                      table_name = std::move(table_name)] (database& db) mutable {
          auto& cf = db.find_column_family(ks_name, table_name);
          auto schema = cf.schema();
          return cf.find_partition_slow(pkey).then([schema, ck, column_name, expected] (column_family::const_mutation_partition_ptr p) {
            assert(p != nullptr);
            auto row = p->find_row(clustering_key::from_deeply_exploded(*schema, ck));
            assert(row != nullptr);
            auto col_def = schema->get_column_definition(utf8_type->decompose(column_name));
            assert(col_def != nullptr);
            const atomic_cell_or_collection* cell = row->find_cell(col_def->id);
            if (!cell) {
                assert(((void)"column not set", 0));
            }
            bytes actual;
            if (!col_def->type->is_multi_cell()) {
                auto c = cell->as_atomic_cell();
                assert(c.is_live());
                actual = { c.value().begin(), c.value().end() };
            } else {
                auto c = cell->as_collection_mutation();
                auto type = dynamic_pointer_cast<const collection_type_impl>(col_def->type);
                actual = type->to_value(type->deserialize_mutation_form(c),
                                        serialization_format::internal());
            }
            assert(col_def->type->equal(actual, col_def->type->decompose(expected)));
          });
        });
    }

    virtual database& local_db() override {
        return _db->local();
    }

    future<> start() {
        return _core_local.start().then([this] () {
            auto query = sprint("create keyspace %s with replication = { 'class' : 'org.apache.cassandra.locator.SimpleStrategy', 'replication_factor' : 1 };", sstring{ks_name});
            return execute_cql(query).discard_result().then([] {
                return make_ready_future<>();
            });
        });
    }

    virtual future<> stop() override {
        return _core_local.stop().then([this] {
            return _qp->stop().then([this] {
                return _proxy->stop().then([this] {
                    return _db->stop().then([] {
                        return locator::i_endpoint_snitch::stop_snitch();
                    });
                });
            });
        });
    }
};

future<> init_once() {
    static bool done = false;
    if (!done) {
        done = true;
        return service::init_storage_service().then([] {
                return net::init_messaging_service("127.0.0.1", db::config::seed_provider_type()).then([] {
                });
        });
    } else {
        return make_ready_future();
    }
}

future<::shared_ptr<cql_test_env>> make_env_for_test() {
    return locator::i_endpoint_snitch::create_snitch("SimpleSnitch").then([] {
        return init_once().then([] {
            auto db = ::make_shared<distributed<database>>();
            auto cfg = make_lw_shared<db::config>();
            cfg->data_file_directories() = {};
            return db->start(std::move(*cfg)).then([db] {
                auto proxy = ::make_shared<distributed<service::storage_proxy>>();
                auto qp = ::make_shared<distributed<cql3::query_processor>>();
                return proxy->start(std::ref(*db)).then([qp, db, proxy] {
                    return qp->start(std::ref(*proxy), std::ref(*db)).then([db, proxy, qp] {
                        auto env = ::make_shared<in_memory_cql_env>(db, qp, proxy);
                        return env->start().then([env] () -> ::shared_ptr<cql_test_env> {
                            return env;
                        });
                    });
                });
            });
        });
    });
}

future<> do_with_cql_env(std::function<future<>(cql_test_env&)> func) {
    return make_env_for_test().then([func = std::move(func)] (auto e) mutable {
        return do_with(std::move(func), [e] (auto& f) {
            return f(*e);
        }).finally([e] {
            return e->stop().finally([e] {});
        });
    });
}
<|endoftext|>


<commit_before>//===--- TypeSerialization.cpp - Serialization of Decls ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Ted Kremenek and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This files defines methods that implement bitcode serialization for Types.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Type.h"
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"

using namespace clang;

void QualType::Emit(llvm::Serializer& S) const {
  S.EmitPtr(getAsOpaquePtr());
  S.EmitInt(getQualifiers());
}

void QualType::Read(llvm::Deserializer& D) {
  D.ReadPtr(ThePtr);
  ThePtr |= D.ReadInt();
}

/*  FIXME: Either remove this method or complete it.

void Type::Emit(llvm::Serializer& S) {
  switch (getTypeClass()) {
    default:
      assert (false && "Serialization for type class not implemented.");
      break;

    case Type::Builtin:
      cast<BuiltinType>(this)->Emit(S);
      break;
  }
}
 */

void Type::EmitTypeInternal(llvm::Serializer& S) const {
  S.Emit(CanonicalType);
}

void Type::ReadTypeInternal(llvm::Deserializer& D) {
  D.Read(CanonicalType);
}

void ComplexType::Emit(llvm::Serializer& S) const {
  EmitTypeInternal(S);
  S.Emit(ElementType);
}

ComplexType* ComplexType::Materialize(llvm::Deserializer& D) {
  ComplexType* T = new ComplexType(QualType(),QualType());
  T->ReadTypeInternal(D);
  D.Read(T->ElementType);
  return T;
}

void PointerType::Emit(llvm::Serializer& S) const {
  EmitTypeInternal(S);
  S.Emit(PointeeType);
}

PointerType* PointerType::Materialize(llvm::Deserializer& D) {
  PointerType* T = new PointerType(QualType(),QualType());
  T->ReadTypeInternal(D);
  D.Read(T->PointeeType);
  return T;
}

void ReferenceType::Emit(llvm::Serializer& S) const {
  EmitTypeInternal(S);
  S.Emit(ReferenceeType);
}

ReferenceType* ReferenceType::Materialize(llvm::Deserializer& D) {
  ReferenceType* T = new ReferenceType(QualType(),QualType());
  T->ReadTypeInternal(D);
  D.Read(T->ReferenceeType);
  return T;
}

void ArrayType::EmitArrayTypeInternal(llvm::Serializer& S) const {
  EmitTypeInternal(S);
  S.Emit(ElementType);
  S.EmitInt(SizeModifier);
  S.EmitInt(IndexTypeQuals);
}

void ArrayType::ReadArrayTypeInternal(llvm::Deserializer& D) {
  ReadTypeInternal(D);
  D.Read(ElementType);
  SizeModifier = static_cast<ArraySizeModifier>(D.ReadInt());
  IndexTypeQuals = D.ReadInt();
}

void ConstantArrayType::Emit(llvm::Serializer& S) const {
#if 0
  // FIXME: APInt serialization
  S.Emit(Size);
#endif
  EmitArrayTypeInternal(S);
}

ConstantArrayType* ConstantArrayType::Materialize(llvm::Deserializer& D) {
#if 0
  llvm::APInt x = S.ReadVal<llvm::APInt>(D);

  // "Default" construct the array.
  ConstantArrayType* T =
    new ConstantArrayType(QualType(), QualType(), x, ArrayType::Normal, 0);

  // Deserialize the internal values.
  T->ReadArrayTypeInternal(D);

  return T;
#else
  return NULL;
#endif

}
<commit_msg>Completed serialization of ConstantArrayTypes (now that APInt serialization is in place).<commit_after>//===--- TypeSerialization.cpp - Serialization of Decls ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Ted Kremenek and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This files defines methods that implement bitcode serialization for Types.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Type.h"
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"

using namespace clang;

void QualType::Emit(llvm::Serializer& S) const {
  S.EmitPtr(getAsOpaquePtr());
  S.EmitInt(getQualifiers());
}

void QualType::Read(llvm::Deserializer& D) {
  D.ReadPtr(ThePtr);
  ThePtr |= D.ReadInt();
}

/*  FIXME: Either remove this method or complete it.

void Type::Emit(llvm::Serializer& S) {
  switch (getTypeClass()) {
    default:
      assert (false && "Serialization for type class not implemented.");
      break;

    case Type::Builtin:
      cast<BuiltinType>(this)->Emit(S);
      break;
  }
}
 */

void Type::EmitTypeInternal(llvm::Serializer& S) const {
  S.Emit(CanonicalType);
}

void Type::ReadTypeInternal(llvm::Deserializer& D) {
  D.Read(CanonicalType);
}

void ComplexType::Emit(llvm::Serializer& S) const {
  EmitTypeInternal(S);
  S.Emit(ElementType);
}

ComplexType* ComplexType::Materialize(llvm::Deserializer& D) {
  ComplexType* T = new ComplexType(QualType(),QualType());
  T->ReadTypeInternal(D);
  D.Read(T->ElementType);
  return T;
}

void PointerType::Emit(llvm::Serializer& S) const {
  EmitTypeInternal(S);
  S.Emit(PointeeType);
}

PointerType* PointerType::Materialize(llvm::Deserializer& D) {
  PointerType* T = new PointerType(QualType(),QualType());
  T->ReadTypeInternal(D);
  D.Read(T->PointeeType);
  return T;
}

void ReferenceType::Emit(llvm::Serializer& S) const {
  EmitTypeInternal(S);
  S.Emit(ReferenceeType);
}

ReferenceType* ReferenceType::Materialize(llvm::Deserializer& D) {
  ReferenceType* T = new ReferenceType(QualType(),QualType());
  T->ReadTypeInternal(D);
  D.Read(T->ReferenceeType);
  return T;
}

void ArrayType::EmitArrayTypeInternal(llvm::Serializer& S) const {
  EmitTypeInternal(S);
  S.Emit(ElementType);
  S.EmitInt(SizeModifier);
  S.EmitInt(IndexTypeQuals);
}

void ArrayType::ReadArrayTypeInternal(llvm::Deserializer& D) {
  ReadTypeInternal(D);
  D.Read(ElementType);
  SizeModifier = static_cast<ArraySizeModifier>(D.ReadInt());
  IndexTypeQuals = D.ReadInt();
}

void ConstantArrayType::Emit(llvm::Serializer& S) const {
  EmitArrayTypeInternal(S);
  S.Emit(Size);
}

ConstantArrayType* ConstantArrayType::Materialize(llvm::Deserializer& D) {
  // "Default" construct the array.
  ConstantArrayType* T =
    new ConstantArrayType(QualType(), QualType(), llvm::APInt(),
                          ArrayType::Normal, 0);

  // Deserialize the internal values.
  T->ReadArrayTypeInternal(D);
  D.Read(T->Size);

  return T;
}
<|endoftext|>


<commit_before>// Blink.cpp : Defines the entry point for the console application.
//

#include "ConnectionService.h"
#include "TreehopperUsb.h"
#include <string>
#include <vector>
#include <iostream>

using namespace Treehopper;

int main()
{
	auto service = ConnectionService::instance();
    TreehopperUsb& board = service.getFirstDevice();

	board.connect();

    board.pins[2].makeAnalogInput();

    for(int i=0;i<20;i++)
	{
		board.led(!board.led());
		//board.pins[1].toggleOutput();
        cout << board.pins[2].adcValue() << endl;
        this_thread::sleep_for(chrono::milliseconds(100));
	}
	board.disconnect();

    while(true)
    {
        std:this_thread::sleep_for(chrono::seconds(5));
    }

    return 0;
}

<commit_msg>Don't hang after blink is finished<commit_after>// Blink.cpp : Defines the entry point for the console application.
//

#include "ConnectionService.h"
#include "TreehopperUsb.h"
#include <string>
#include <vector>
#include <iostream>

using namespace Treehopper;

int main()
{
	auto service = ConnectionService::instance();
    TreehopperUsb& board = service.getFirstDevice();

	board.connect();

    board.pins[2].makeAnalogInput();

    for(int i=0;i<20;i++)
	{
		board.led(!board.led());
		//board.pins[1].toggleOutput();
        cout << board.pins[2].adcValue() << endl;
        this_thread::sleep_for(chrono::milliseconds(100));
	}
	board.disconnect();

    return 0;
}

<|endoftext|>


<commit_before>/*
 * Mediator
 * Author: reimen
 * Data: Oct.15.2014
 *
 */
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
class Colleague;
class Mediator;
class ConcreteMediator;

class Mediator
{
protected:
  Colleague* _colleague;
public:
  virtual ~Mediator() {}
  virtual void createColleague() = 0;
  virtual void colleagueChanged() = 0;
};

class Colleague
{
protected:
  Mediator* _mediator;
public:
  virtual ~Colleague() {}
  virtual void setMediator(Mediator* mediator) = 0;
  virtual void controlColleague() = 0;
};

class ConcreteColleague : public Colleague
{
private:

public:
  ConcreteColleague() {}
  virtual ~ConcreteColleague() {}
  void setMediator(Mediator* mediator)
  {
    _mediator = mediator;
  }
  void controlColleague()
  {
    cout << "Hello This is Colleague" << endl;
    if(_mediator != NULL)
    {
      _mediator -> colleagueChanged();
    }
    else
    {
      cout << "There is no mediator" << endl;
    }
  }
};

class ConcreteMediator : Mediator
{
public:
  virtual ~ConcreteMediator() { delete _colleague; }
  void createColleague()
  {
    if(_colleague == NULL)
    {
      _colleague = new ConcreteColleague;
      _colleague -> setMediator(this);
    }

  }
  void colleagueChanged()
  {
    cout << "Hello I am mediator!!" << endl;
  }
  void zap()
  {
    if(_colleague != NULL)
    {
      _colleague->controlColleague();
    }
    else
    {
      cout << "No colleague" << endl;
    }
  }
};

int main()
{
  ConcreteMediator mediator;
  mediator.createColleague();
  mediator.zap();
  return EXIT_SUCCESS;
}
<commit_msg>Add Comments to Mediator.cpp<commit_after>/*
 * Mediator
 * Author: reimen
 * Date: Oct.15.2014
 * Define an object that encapsulates how a set of objects interact.
 * Mediator promotes loose coupling by keeping objects from
 * referring to each other explicitly, and it lets you vary their
 * interaction independently.
 */
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
class Colleague;
class Mediator;
class ConcreteMediator;

class Mediator
{
protected:
  Colleague* _colleague;
public:
  virtual ~Mediator() {}
  virtual void createColleague() = 0;
  virtual void colleagueChanged() = 0;
};

class Colleague
{
protected:
  Mediator* _mediator;
public:
  virtual ~Colleague() {}
  virtual void setMediator(Mediator* mediator) = 0;
  virtual void controlColleague() = 0;
};

class ConcreteColleague : public Colleague
{
private:

public:
  ConcreteColleague() {}
  virtual ~ConcreteColleague() {}
  void setMediator(Mediator* mediator)
  {
    _mediator = mediator;
  }
  void controlColleague()
  {
    cout << "Hello This is Colleague" << endl;
    if(_mediator != NULL)
      {
        _mediator -> colleagueChanged();
      }
    else
      {
        cout << "There is no mediator" << endl;
      }
  }
};

class ConcreteMediator : Mediator
{
public:
  virtual ~ConcreteMediator()
  {
    delete _colleague;
  }
  void createColleague()
  {
    if(_colleague == NULL)
      {
        _colleague = new ConcreteColleague;
        _colleague -> setMediator(this);
      }

  }
  void colleagueChanged()
  {
    cout << "Hello I am mediator!!" << endl;
  }
  void zap()
  {
    if(_colleague != NULL)
      {
        _colleague->controlColleague();
      }
    else
      {
        cout << "No colleague" << endl;
      }
  }
};

int main()
{
  ConcreteMediator mediator;
  mediator.createColleague();
  mediator.zap();
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <string>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>

#include "gtest/gtest.h"

// redefine class, private & protected to get access to
// private and protected members of rbtree & rbnode.
#define class struct
#define private public
#define protected public

#include "../rbtree.hpp"
#include "../rbnode.hpp"

#undef class
#undef private
#undef protected

using namespace std;

// Redirect the cout to a string
struct cout_redirect {
  cout_redirect(std::streambuf* new_buffer)
    : old( std::cout.rdbuf(new_buffer))
  {
  }

  ~cout_redirect() {
    std::cout.rdbuf(old);
  }

private:
  std::streambuf* old;
};

class rbtree_tests : public ::testing::Test {
public:
    // red black trees
    rbtree* rbt;

    rbtree_tests() {
        rbt = new rbtree();
    }

    ~rbtree_tests() {
        delete rbt;
    }
};

TEST_F(rbtree_tests, test_empty) {
    EXPECT_TRUE(rbt->root == nullptr) << "root should be null";
}

TEST_F(rbtree_tests, test_rbtree_invalid) {
    rbt->root = new rbnode(56, rbcolor::red);
    EXPECT_FALSE(rbt->is_valid_rbtree()) << "tree with red root is invalid";
}

TEST_F(rbtree_tests, test_rbtree_valid_1) {
    // build a red black tree.
    auto root = new rbnode(45, rbcolor::black);

    auto r1 = new rbnode(25);
    r1->parent = root;

    auto r2 = new rbnode(60);
    r2->parent = root;

    root->left = r1;
    root->right = r2;

    rbt->root = root;
    EXPECT_TRUE(rbt->is_valid_rbtree());
}

TEST_F(rbtree_tests, test_rbtree_valid_2) {
    auto root = new rbnode(10, rbcolor::black);
    auto n7 = new rbnode(7, rbcolor::black, root);
    auto n19 = new rbnode(19, rbcolor::red, root);
    auto n13 = new rbnode(13, rbcolor::black, n19);
    auto n23 = new rbnode(23, rbcolor::black, n19);

    root->left = n7;
    root->right = n19;
    n19->left = n13;
    n19->right = n23;

    rbt->root = root;
    EXPECT_TRUE(rbt->is_valid_rbtree());
}

TEST_F(rbtree_tests, test_rbtree_insert) {

}

TEST_F(rbtree_tests, test_rbtree_remove) {

}

TEST_F(rbtree_tests, test_rbtree_remove_all) {

}
<commit_msg>added test cases for rb insert, rotate<commit_after>#include <string>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

#include "gtest/gtest.h"

// redefine class, private & protected to get access to
// private and protected members of rbtree & rbnode.
#define class struct
#define private public
#define protected public

#include "../rbtree.hpp"
#include "../rbnode.hpp"

#undef class
#undef private
#undef protected

using namespace std;

// Redirect the cout to a string
struct cout_redirect {
  cout_redirect(std::streambuf* new_buffer)
    : old( std::cout.rdbuf(new_buffer))
  {
  }

  ~cout_redirect() {
    std::cout.rdbuf(old);
  }

private:
  std::streambuf* old;
};

class rbtree_tests : public ::testing::Test {
public:
    // red black trees
    rbtree* rbt;

    rbtree_tests() {
        rbt = new rbtree();
    }

    ~rbtree_tests() {
        delete rbt;
    }
};

TEST_F(rbtree_tests, test_empty) {
    EXPECT_TRUE(rbt->root == nullptr) << "root should be null!";
}

TEST_F(rbtree_tests, test_rbtree_invalid_1) {
    rbt->root = new rbnode(56, rbcolor::red);
    EXPECT_FALSE(rbt->is_valid_rbtree()) << "tree with red root should be invalid!";
}

TEST_F(rbtree_tests, test_rbtree_invalid_2) {
    auto root = new rbnode(7, rbcolor::black);
    auto n3 = new rbnode(3, rbcolor::red, root);
    auto n18 = new rbnode(18, rbcolor::black, root);
    auto n1 = new rbnode(1, rbcolor::black, n3);
    auto n45 = new rbnode(45, rbcolor::black, n18);
    auto n2 = new rbnode(2, rbcolor::black, n1);

    root->left = n3;
    root->right = n18;
    n18->right = n45;
    n3->left = n1;
    n1->right = n2;

    rbt->root = root;
    EXPECT_FALSE(rbt->is_valid_rbtree());
}

TEST_F(rbtree_tests, test_rbtree_valid_1) {
    // build a red black tree.
    auto root = new rbnode(45, rbcolor::black);

    auto r1 = new rbnode(25);
    r1->parent = root;

    auto r2 = new rbnode(60);
    r2->parent = root;

    root->left = r1;
    root->right = r2;

    rbt->root = root;
    EXPECT_TRUE(rbt->is_valid_rbtree());
}

TEST_F(rbtree_tests, test_rbtree_valid_2) {
    auto root = new rbnode(10, rbcolor::black);
    auto n7 = new rbnode(7, rbcolor::black, root);
    auto n19 = new rbnode(19, rbcolor::red, root);
    auto n13 = new rbnode(13, rbcolor::black, n19);
    auto n23 = new rbnode(23, rbcolor::black, n19);

    root->left = n7;
    root->right = n19;
    n19->left = n13;
    n19->right = n23;

    rbt->root = root;
    EXPECT_TRUE(rbt->is_valid_rbtree());
}

TEST_F(rbtree_tests, test_rbtree_insert) {
    // generated using visualization tool: https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
    vector<string> expected = {
        "0(black)\n",
        "0(black)\n1(red)\n",
        "0(red)\n1(black)\n2(red)\n",
        "0(black)\n1(black)\n2(black)\n3(red)\n",
        "0(black)\n1(black)\n2(red)\n3(black)\n4(red)\n",
        "0(black)\n1(black)\n2(black)\n3(red)\n4(black)\n5(red)\n",
        "0(black)\n1(black)\n2(black)\n3(red)\n4(red)\n5(black)\n6(red)\n",
        "0(black)\n1(red)\n2(black)\n3(black)\n4(black)\n5(red)\n6(black)\n7(red)\n",
        "0(black)\n1(red)\n2(black)\n3(black)\n4(black)\n5(red)\n6(red)\n7(black)\n8(red)\n",
        "0(black)\n1(black)\n2(black)\n3(black)\n4(black)\n5(black)\n6(black)\n7(red)\n8(black)\n9(red)\n"
    };

    for (int i = 0; i < expected.size(); i++) {
        auto n = i+1;
        rbt->insert(i);

        stringstream buffer; {
            cout_redirect activate(buffer.rdbuf());
            rbt->inorder();
        }
        string got = buffer.str();

        EXPECT_TRUE(expected[i] == got) << "insert of " << i << " is incorrect!";

        // max heigth of rb tree <= 2 * log(n+1)
        EXPECT_TRUE(rbt->depth() < 2 * ceil(log2(n+1))) << "depth of rb tree is incorrect!";

    }
}

TEST_F(rbtree_tests, test_rbtree_remove) {

}

TEST_F(rbtree_tests, test_rbtree_remove_all) {
    rbt->remove_all(rbt->root);
    EXPECT_TRUE(rbt->root == nullptr);
    EXPECT_TRUE(rbt->depth() == 0) << "depth of empty rb tree should be zero!";
}

TEST_F(rbtree_tests, test_left_rotate) {
    /*
          x                                          y
         / \          left rotate around x          / \
        a   y       ------------------------>      x   c
           / \                                    / \
          b   c                                  a   b
     */

    auto x = new rbnode(50, rbcolor::black);
    auto y = new rbnode(60, rbcolor::red, x);
    auto a = new rbnode(25, rbcolor::black, x);
    auto b = new rbnode(55, rbcolor::black, y);
    auto c = new rbnode(70, rbcolor::black, y);

    x->left = a;
    x->right = y;
    y->right = c;
    y->left  = b;

    rbt->root = x;
    rbt->left_rotate(x);

    stringstream buffer; {
        cout_redirect activate(buffer.rdbuf());
        rbt->inorder();
    }

    string expected = "25(black)\n50(black)\n55(black)\n60(red)\n70(black)\n";
    string got = buffer.str();

    EXPECT_TRUE(expected == got) << "left rotation is incorrect!";
    EXPECT_TRUE(rbt->depth() == 3) << "left rotation is of incorrect depth!";
}

TEST_F(rbtree_tests, test_right_rotate) {
    /*
             y                                        x
            / \        right rotate around y         / \
           x   c     ----------------------->       a   y
          / \                                          / \
         a   b                                        b   c

     */

    auto y = new rbnode(50, rbcolor::black);
    auto x = new rbnode(25, rbcolor::red, y);
    auto a = new rbnode(10, rbcolor::black, x);
    auto b = new rbnode(30, rbcolor::black, x);
    auto c = new rbnode(60, rbcolor::black);

    x->left = a;
    x->right = b;
    y->right = c;
    y->left  = x;

    rbt->root = y;
    rbt->right_rotate(y);

    stringstream buffer; {
        cout_redirect activate(buffer.rdbuf());
        rbt->inorder();
    }

    string expected = "10(black)\n25(red)\n30(black)\n50(black)\n60(black)\n";
    string got = buffer.str();

    EXPECT_TRUE(expected == got) << "right rotation is incorrect.";
    EXPECT_TRUE(rbt->depth() == 3) << "right rotation is of incorrect depth";
}
<|endoftext|>


<commit_before>using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;

//
// Les informations gnrales relatives  un assembly dpendent de
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
// associes  un assembly.
//
[assembly:AssemblyTitleAttribute(L"ClrPhlib")];
[assembly:AssemblyDescriptionAttribute(L"")];
[assembly:AssemblyConfigurationAttribute(L"")];
[assembly:AssemblyCompanyAttribute(L"")];
[assembly:AssemblyProductAttribute(L"ClrPhlib")];
[assembly:AssemblyCopyrightAttribute(L"Copyright (c)  2017")];
[assembly:AssemblyTrademarkAttribute(L"")];
[assembly:AssemblyCultureAttribute(L"")];

//
// Les informations de version pour un assembly se composent des quatre valeurs suivantes:
//
//      Version principale
//      Version secondaire
//      Numro de build
//      Rvision
//
// Vous pouvez spcifier toutes les valeurs ou indiquer les numros de rvision et de build par dfaut
// en utilisant '*', comme indiqu ci-dessous:

[assembly:AssemblyVersionAttribute("1.9.*")];

[assembly:ComVisible(false)];

[assembly:CLSCompliantAttribute(true)];<commit_msg>Save encoding of AssemblyInfo.cpp to UTF-8 because of the diacritics of comment may cause compile error (we treat compile warning as error).<commit_after>using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;

//
// Les informations générales relatives à un assembly dépendent de
// l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
// associées à un assembly.
//
[assembly:AssemblyTitleAttribute(L"ClrPhlib")];
[assembly:AssemblyDescriptionAttribute(L"")];
[assembly:AssemblyConfigurationAttribute(L"")];
[assembly:AssemblyCompanyAttribute(L"")];
[assembly:AssemblyProductAttribute(L"ClrPhlib")];
[assembly:AssemblyCopyrightAttribute(L"Copyright (c)  2017")];
[assembly:AssemblyTrademarkAttribute(L"")];
[assembly:AssemblyCultureAttribute(L"")];

//
// Les informations de version pour un assembly se composent des quatre valeurs suivantes :
//
//      Version principale
//      Version secondaire
//      Numéro de build
//      Révision
//
// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de révision et de build par défaut
// en utilisant '*', comme indiqué ci-dessous :

[assembly:AssemblyVersionAttribute("1.9.*")];

[assembly:ComVisible(false)];

[assembly:CLSCompliantAttribute(true)];<|endoftext|>