<commit_before>#include "editor.h"

Editor::Editor()
{
    // Allocate memory
    this->characterValues = new std::unordered_map<std::string, QString>;
    this->inventory = new int[Items::NUM_INVENTORY_SLOTS];
    this->itemSettings = new ItemSettings[Items::NUM_INVENTORY_SLOTS];
    this->combatChips = new int[Items::NUM_COMBAT_CHIP_SLOTS];

    // Determine the username
    QString username = qgetenv("USER");
    if (username.isEmpty())
        username = qgetenv("USERNAME");

    // The location of the save file is different on Windows and Mac
    this->_playerDataLocation = Strings::playerDataPrefix + username.toStdString() + Strings::playerDataSuffix;
    this->_tmpDataLocation = Strings::playerDataPrefix + username.toStdString() + Strings::tmpDataSuffix;

    // Open a stream and load contents into memory
    std::ifstream playerDataStream(this->_playerDataLocation);
    if (playerDataStream.fail()) std::abort(); // TODO: Implement more graceful exception handling.
    this->_playerData = new std::string((std::istreambuf_iterator<char>(playerDataStream)),
                                       std::istreambuf_iterator<char>());

    // The space is semi-important, treasure it always
    *this->_playerData = " " + *this->_playerData;
    playerDataStream.close();
}

Editor::~Editor()
{
    delete this->characterValues;
    delete[] this->inventory;
    delete[] this->combatChips;
    delete[] this->itemSettings;
    delete this->_playerData;
}

std::string Editor::loadValue(std::string specifier)
{
    /* Returns the value assigned to specifier. */
    // Find the value by determining the string between start and end (Ex:  0hp : <value> : System.Int32;
    std::string startDelimiter = " " + specifier + Strings::paddedSeperator;
    std::string endDelimiter = Strings::paddedSeperator;

    // Find the location of key in playerData
    std::size_t first = this->_playerData->find(startDelimiter);
    first += startDelimiter.length(); // Move to the position just before value
    std::size_t last = this->_playerData->find(endDelimiter, first);

    return this->_playerData->substr(first, last-first);
}

void Editor::replaceValue(std::string specifier, std::string oldValue, std::string newValue)
{
    /* Replaces oldValue with newValue in this->playerData. */
    std::string oldString = " " + specifier + Strings::paddedSeperator + oldValue; // String to be replaced
    std::string newString = " " + specifier + Strings::paddedSeperator + newValue; // String to be inserted

    // Find the location at which to replace
    std::size_t position = this->_playerData->find(oldString);

    // Erase oldString at position from playerData
    this->_playerData->erase(position, oldString.length());

    // Insert newString into playerData at position
    this->_playerData->insert(position, newString);
}

void Editor::save()
{
    /* This function is called when the user clicks on Save Character. First it outputs
     * its Editor's playerData member to a temporary file.  If this was successful, it overwrites
     * the original PlayerPrefs.txt with the temporary file. */

    // First, output the edited playerData into tmpDataLocation
    std::ofstream saveStream(this->_tmpDataLocation);
    saveStream << this->_playerData->substr(1, this->_playerData->size() - 1);  // Ignore the extra space at the beginning
    if (saveStream.fail()) std::abort();
    saveStream.close();

    // Next, overwrite the original playerData and replace it with the new playerData
    std::remove(this->_playerDataLocation.c_str());
    std::rename(this->_tmpDataLocation.c_str(), (const char*) this->_playerDataLocation.c_str());
}

QString* Editor::loadCharacterNames()
{
    /* This function searches playerData.txt for all character names and adds seperators to
     * the "Load Player" section in the menu bar of w. Type can either be System.String or
     * System.Int32. */
    std::string characterName;
    std::string specifier;
    QString* characterNames = new QString[this->MAX_CHARACTERS];

    /* In PlayerData.txt, character names are specified by their number, ranging from
     * 0 to MAX_CHARACTERS, followed by "name" (e.g. "0name : Smurfalicious"). */
    for (int i = 0; i < this->MAX_CHARACTERS; i++)
    {
        // Load the name and store it in characterNames
        specifier = std::to_string(i) + Strings::nameSpecifier;
        characterName = this->loadValue(specifier);
        characterNames[i] = QString::fromStdString(characterName);
    }

    return characterNames;
}

void Editor::loadCharacterValues()
{
    /* Loads the settings and stats of the character specified by ID. */
    std::string val;

    // Load and store the name and experience
    (*this->characterValues)[Strings::nameSpecifier] = QString::fromStdString(this->loadValue(this->currentID + Strings::nameSpecifier));
    (*this->characterValues)[Strings::characterExperienceSpecifier] = QString::fromStdString(this->loadValue(this->currentID + Strings::characterExperienceSpecifier));

    // Load comboBoxes
    for (int i = 0; i < Strings::CHARACTER_TAB_NUM_COMBOBOXES; i++)
    {
        val = this->loadValue(this->currentID + Strings::cComboBoxSpecifiers[i]);
        (*this->characterValues)[Strings::cComboBoxSpecifiers[i]] = QString::fromStdString(val);
    }

    // Load spinBoxes
    for (int i = 0; i < Strings::CHARACTER_TAB_NUM_SPINBOXES; i++)
        (*this->characterValues)[Strings::cSpinBoxSpecifiers[i]] = QString::fromStdString(this->loadValue(this->currentID + Strings::cSpinBoxSpecifiers[i]));
}

void Editor::loadCharacterItemBrowser()
{
    /* Loads the combat chips and inventory of the character specified by ID*/
    ItemSettings setting;
    std::string specifierPrefix;

    // Load the inventory of the character specified by ID into this->inventory */
    for (int i = 0; i < Items::NUM_INVENTORY_SLOTS; i++)
        this->inventory[i] = std::stoi(this->loadValue(this->currentID + std::to_string(i) + Strings::idSpecifier));

    // Load in item settings
    for (int i = 0; i < Items::NUM_INVENTORY_SLOTS; i++)
    {
        specifierPrefix = this->currentID + std::to_string(i);
        setting.exp = this->loadValue(specifierPrefix + Strings::itemExperienceSpecifier);
        setting.quantity = this->loadValue(specifierPrefix + Strings::itemQuantitySpecifier);
        setting.rarity = this->loadValue(specifierPrefix + Strings::itemRaritySpecifier);
        this->itemSettings[i] = setting;
    }

    // Load the combat chips of the character specified by ID into this->combatChips */
    for (int i = 0; i < Items::NUM_COMBAT_CHIP_SLOTS; i++)
        this->combatChips[i] = std::stoi(this->loadValue(this->currentID + Strings::combatChipSpecifier + std::to_string(i)));
}

int *Editor::equippedStats()
{
    int* equippedStats = new int[Items::NUM_STATS];
    Items::Equippable currentEquippable;
    int itemLevel;
    int itemRarityBonus;

    // Initialize everything to 0
    for (int i = 0; i < Items::NUM_STATS; i++)
        equippedStats[i] = 0;

    // Loop through the inventory and update equipped stats!
    for (int i = Items::EQUIPPED_BEGIN; i < Items::EQUIPPED_END; i++)
    {
        // Load in values associated with current equippable index
        currentEquippable = Items::equippables.find(this->inventory[i])->second;
        itemLevel = this->calculateItemLevelFromExperience(std::stoi(this->itemSettings[i].exp));
        itemRarityBonus = std::stoi(this->itemSettings[i].rarity) * Items::itemRarityBonusMultiplier;

        // Stat Bonus = Item Stat * Item Level + Item Rarity * 3 (iff Item Stat != 0)
        equippedStats[Items::vitalityIndex] += (currentEquippable.vitality) ? currentEquippable.vitality * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::dexterityIndex] += (currentEquippable.dexterity) ? currentEquippable.dexterity * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::magicIndex] += (currentEquippable.magic) ? currentEquippable.magic * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::strengthIndex] += (currentEquippable.strength) ? currentEquippable.strength * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::techIndex] += (currentEquippable.tech) ? currentEquippable.tech * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::faithIndex] += (currentEquippable.faith) ? currentEquippable.faith * itemLevel + itemRarityBonus : 0;
    }

    return equippedStats;
}

int Editor::calculateItemLevelFromExperience(int exp)
{
    // Takes exp and returns the associated item level
    if      (exp >= Items::itemLevel10exp) return 10;
    else if (exp >= Items::itemLevel9exp) return 9;
    else if (exp >= Items::itemLevel8exp) return 8;
    else if (exp >= Items::itemLevel7exp) return 7;
    else if (exp >= Items::itemLevel6exp) return 6;
    else if (exp >= Items::itemLevel5exp) return 5;
    else if (exp >= Items::itemLevel4exp) return 4;
    else if (exp >= Items::itemLevel3exp) return 3;
    else if (exp >= Items::itemLevel2exp) return 2;

    // Default to returning one
    return 1;
}

int Editor::calculateItemExperienceFromLevel(int level)
{
    // Use Roguelands formula to convert newLevel to exp
    switch (level)
    {
    case 2:  return Items::itemLevel2exp;
    case 3:  return Items::itemLevel3exp;
    case 4:  return Items::itemLevel4exp;
    case 5:  return Items::itemLevel5exp;
    case 6:  return Items::itemLevel6exp;
    case 7:  return Items::itemLevel7exp;
    case 8:  return Items::itemLevel8exp;
    case 9:  return Items::itemLevel9exp;
    case 10: return Items::itemLevel10exp;
    default: return Items::itemLevel1exp;
    }
}
<commit_msg>Fix bug where loadValue would incorrectly return values that did not exist<commit_after>#include "editor.h"

Editor::Editor()
{
    // Allocate memory
    this->characterValues = new std::unordered_map<std::string, QString>;
    this->inventory = new int[Items::NUM_INVENTORY_SLOTS];
    this->itemSettings = new ItemSettings[Items::NUM_INVENTORY_SLOTS];
    this->combatChips = new int[Items::NUM_COMBAT_CHIP_SLOTS];

    // Determine the username
    QString username = qgetenv("USER");
    if (username.isEmpty())
        username = qgetenv("USERNAME");

    // The location of the save file is different on Windows and Mac
    this->_playerDataLocation = Strings::playerDataPrefix + username.toStdString() + Strings::playerDataSuffix;
    this->_tmpDataLocation = Strings::playerDataPrefix + username.toStdString() + Strings::tmpDataSuffix;

    // Open a stream and load contents into memory
    std::ifstream playerDataStream(this->_playerDataLocation);
    if (playerDataStream.fail()) std::abort(); // TODO: Implement more graceful exception handling.
    this->_playerData = new std::string((std::istreambuf_iterator<char>(playerDataStream)),
                                       std::istreambuf_iterator<char>());

    // The space is semi-important, treasure it always
    *this->_playerData = " " + *this->_playerData;
    playerDataStream.close();
}

Editor::~Editor()
{
    delete this->characterValues;
    delete[] this->inventory;
    delete[] this->combatChips;
    delete[] this->itemSettings;
    delete this->_playerData;
}

std::string Editor::loadValue(std::string specifier)
{
    /* Returns the value assigned to specifier. */
    // Find the value by determining the string between start and end (Ex:  0hp : <value> : System.Int32;
    std::string startDelimiter = " " + specifier + Strings::paddedSeperator;
    std::string endDelimiter = Strings::paddedSeperator;

    // Find the location of key in playerData
    std::size_t first = this->_playerData->find(startDelimiter);
    if (first == this->_playerData->npos) return ""; // Break if not found
    first += startDelimiter.length(); // Move to the position just before value
    std::size_t last = this->_playerData->find(endDelimiter, first);

    return this->_playerData->substr(first, last-first);
}

void Editor::replaceValue(std::string specifier, std::string oldValue, std::string newValue)
{
    /* Replaces oldValue with newValue in this->playerData. */
    std::string oldString = " " + specifier + Strings::paddedSeperator + oldValue; // String to be replaced
    std::string newString = " " + specifier + Strings::paddedSeperator + newValue; // String to be inserted

    // Find the location at which to replace
    std::size_t position = this->_playerData->find(oldString);

    // Erase oldString at position from playerData
    this->_playerData->erase(position, oldString.length());

    // Insert newString into playerData at position
    this->_playerData->insert(position, newString);
}

void Editor::save()
{
    /* This function is called when the user clicks on Save Character. First it outputs
     * its Editor's playerData member to a temporary file.  If this was successful, it overwrites
     * the original PlayerPrefs.txt with the temporary file. */

    // First, output the edited playerData into tmpDataLocation
    std::ofstream saveStream(this->_tmpDataLocation);
    saveStream << this->_playerData->substr(1, this->_playerData->size() - 1);  // Ignore the extra space at the beginning
    if (saveStream.fail()) std::abort();
    saveStream.close();

    // Next, overwrite the original playerData and replace it with the new playerData
    std::remove(this->_playerDataLocation.c_str());
    std::rename(this->_tmpDataLocation.c_str(), (const char*) this->_playerDataLocation.c_str());
}

QString* Editor::loadCharacterNames()
{
    /* This function searches playerData.txt for all character names and adds seperators to
     * the "Load Player" section in the menu bar of w. Type can either be System.String or
     * System.Int32. */
    std::string characterName;
    std::string specifier;
    QString* characterNames = new QString[this->MAX_CHARACTERS];

    /* In PlayerData.txt, character names are specified by their number, ranging from
     * 0 to MAX_CHARACTERS, followed by "name" (e.g. "0name : Smurfalicious"). */
    for (int i = 0; i < this->MAX_CHARACTERS; i++)
    {
        // Load the name and store it in characterNames
        specifier = std::to_string(i) + Strings::nameSpecifier;
        characterName = this->loadValue(specifier);
        characterNames[i] = QString::fromStdString(characterName);
    }

    return characterNames;
}

void Editor::loadCharacterValues()
{
    /* Loads the settings and stats of the character specified by ID. */
    std::string val;

    // Load and store the name and experience
    (*this->characterValues)[Strings::nameSpecifier] = QString::fromStdString(this->loadValue(this->currentID + Strings::nameSpecifier));
    (*this->characterValues)[Strings::characterExperienceSpecifier] = QString::fromStdString(this->loadValue(this->currentID + Strings::characterExperienceSpecifier));

    // Load comboBoxes
    for (int i = 0; i < Strings::CHARACTER_TAB_NUM_COMBOBOXES; i++)
    {
        val = this->loadValue(this->currentID + Strings::cComboBoxSpecifiers[i]);
        (*this->characterValues)[Strings::cComboBoxSpecifiers[i]] = QString::fromStdString(val);
    }

    // Load spinBoxes
    for (int i = 0; i < Strings::CHARACTER_TAB_NUM_SPINBOXES; i++)
        (*this->characterValues)[Strings::cSpinBoxSpecifiers[i]] = QString::fromStdString(this->loadValue(this->currentID + Strings::cSpinBoxSpecifiers[i]));
}

void Editor::loadCharacterItemBrowser()
{
    /* Loads the combat chips and inventory of the character specified by ID*/
    ItemSettings setting;
    std::string specifierPrefix;

    // Load the inventory of the character specified by ID into this->inventory */
    for (int i = 0; i < Items::NUM_INVENTORY_SLOTS; i++)
        this->inventory[i] = std::stoi(this->loadValue(this->currentID + std::to_string(i) + Strings::idSpecifier));

    // Load in item settings
    for (int i = 0; i < Items::NUM_INVENTORY_SLOTS; i++)
    {
        specifierPrefix = this->currentID + std::to_string(i);
        setting.exp = this->loadValue(specifierPrefix + Strings::itemExperienceSpecifier);
        setting.quantity = this->loadValue(specifierPrefix + Strings::itemQuantitySpecifier);
        setting.rarity = this->loadValue(specifierPrefix + Strings::itemRaritySpecifier);
        this->itemSettings[i] = setting;
    }

    // Load the combat chips of the character specified by ID into this->combatChips */
    for (int i = 0; i < Items::NUM_COMBAT_CHIP_SLOTS; i++)
        this->combatChips[i] = std::stoi(this->loadValue(this->currentID + Strings::combatChipSpecifier + std::to_string(i)));
}

int *Editor::equippedStats()
{
    int* equippedStats = new int[Items::NUM_STATS];
    Items::Equippable currentEquippable;
    int itemLevel;
    int itemRarityBonus;

    // Initialize everything to 0
    for (int i = 0; i < Items::NUM_STATS; i++)
        equippedStats[i] = 0;

    // Loop through the inventory and update equipped stats!
    for (int i = Items::EQUIPPED_BEGIN; i < Items::EQUIPPED_END; i++)
    {
        // Load in values associated with current equippable index
        currentEquippable = Items::equippables.find(this->inventory[i])->second;
        itemLevel = this->calculateItemLevelFromExperience(std::stoi(this->itemSettings[i].exp));
        itemRarityBonus = std::stoi(this->itemSettings[i].rarity) * Items::itemRarityBonusMultiplier;

        // Stat Bonus = Item Stat * Item Level + Item Rarity * 3 (iff Item Stat != 0)
        equippedStats[Items::vitalityIndex] += (currentEquippable.vitality) ? currentEquippable.vitality * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::dexterityIndex] += (currentEquippable.dexterity) ? currentEquippable.dexterity * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::magicIndex] += (currentEquippable.magic) ? currentEquippable.magic * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::strengthIndex] += (currentEquippable.strength) ? currentEquippable.strength * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::techIndex] += (currentEquippable.tech) ? currentEquippable.tech * itemLevel + itemRarityBonus : 0;
        equippedStats[Items::faithIndex] += (currentEquippable.faith) ? currentEquippable.faith * itemLevel + itemRarityBonus : 0;
    }

    return equippedStats;
}

int Editor::calculateItemLevelFromExperience(int exp)
{
    // Takes exp and returns the associated item level
    if      (exp >= Items::itemLevel10exp) return 10;
    else if (exp >= Items::itemLevel9exp) return 9;
    else if (exp >= Items::itemLevel8exp) return 8;
    else if (exp >= Items::itemLevel7exp) return 7;
    else if (exp >= Items::itemLevel6exp) return 6;
    else if (exp >= Items::itemLevel5exp) return 5;
    else if (exp >= Items::itemLevel4exp) return 4;
    else if (exp >= Items::itemLevel3exp) return 3;
    else if (exp >= Items::itemLevel2exp) return 2;

    // Default to returning one
    return 1;
}

int Editor::calculateItemExperienceFromLevel(int level)
{
    // Use Roguelands formula to convert newLevel to exp
    switch (level)
    {
    case 2:  return Items::itemLevel2exp;
    case 3:  return Items::itemLevel3exp;
    case 4:  return Items::itemLevel4exp;
    case 5:  return Items::itemLevel5exp;
    case 6:  return Items::itemLevel6exp;
    case 7:  return Items::itemLevel7exp;
    case 8:  return Items::itemLevel8exp;
    case 9:  return Items::itemLevel9exp;
    case 10: return Items::itemLevel10exp;
    default: return Items::itemLevel1exp;
    }
}
<|endoftext|>


<commit_before>/*
 *  Phusion Passenger - https://www.phusionpassenger.com/
 *  Copyright (c) 2011-2017 Phusion Holding B.V.
 *
 *  "Passenger", "Phusion Passenger" and "Union Station" are registered
 *  trademarks of Phusion Holding B.V.
 *
 *  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 <Core/ApplicationPool/Group.h>

/*************************************************************************
 *
 * Session management functions for ApplicationPool2::Group
 *
 *************************************************************************/

namespace Passenger {
namespace ApplicationPool2 {

using namespace std;
using namespace boost;

/****************************
 *
 * Public methods
 *
 ****************************/

unsigned int
Group::getProcessCount() const {
	return enabledCount + disablingCount + disabledCount;
}

/**
 * Returns whether the lower bound of the group-specific process limits
 * have been satisfied. Note that even if the result is false, the pool limits
 * may not allow spawning, so you should check `pool->atFullCapacity()` too.
 */
bool
Group::processLowerLimitsSatisfied() const {
	return capacityUsed() >= options.minProcesses;
}

/**
 * Returns whether the upper bound of the group-specific process limits have
 * been reached, or surpassed. Does not check whether pool limits have been
 * reached. Use `pool->atFullCapacity()` to check for that.
 */
bool
Group::processUpperLimitsReached() const {
	return options.maxProcesses != 0 && capacityUsed() >= options.maxProcesses;
}

/**
 * Returns whether all enabled processes are totally busy. If so, another
 * process should be spawned, if allowed by the process limits.
 * Returns false if there are no enabled processes.
 */
bool
Group::allEnabledProcessesAreTotallyBusy() const {
	return nEnabledProcessesTotallyBusy == enabledCount;
}

/**
 * Returns the number of processes in this group that should be part of the
 * ApplicationPool process limits calculations.
 */
unsigned int
Group::capacityUsed() const {
	return enabledCount + disablingCount + disabledCount + processesBeingSpawned;
}

/**
 * Checks whether this group is waiting for capacity on the pool to
 * become available before it can continue processing requests.
 */
bool
Group::isWaitingForCapacity() const {
	return enabledProcesses.empty()
		&& processesBeingSpawned == 0
		&& !m_restarting
		&& !getWaitlist.empty();
}

bool
Group::garbageCollectable(unsigned long long now) const {
	/* if (now == 0) {
		now = SystemTime::getUsec();
	}
	return busyness() == 0
		&& getWaitlist.empty()
		&& disabledProcesses.empty()
		&& options.getMaxPreloaderIdleTime() != 0
		&& now - spawner->lastUsed() >
			(unsigned long long) options.getMaxPreloaderIdleTime() * 1000000; */
	return false;
}

void
Group::inspectXml(std::ostream &stream, bool includeSecrets) const {
	ProcessList::const_iterator it;

	stream << "<name>" << escapeForXml(info.name) << "</name>";
	stream << "<component_name>" << escapeForXml(info.name) << "</component_name>";
	stream << "<app_root>" << escapeForXml(options.appRoot) << "</app_root>";
	stream << "<app_type>" << escapeForXml(options.appType) << "</app_type>";
	stream << "<environment>" << escapeForXml(options.environment) << "</environment>";
	stream << "<uuid>" << toString(uuid) << "</uuid>";
	stream << "<enabled_process_count>" << enabledCount << "</enabled_process_count>";
	stream << "<disabling_process_count>" << disablingCount << "</disabling_process_count>";
	stream << "<disabled_process_count>" << disabledCount << "</disabled_process_count>";
	stream << "<capacity_used>" << capacityUsed() << "</capacity_used>";
	stream << "<get_wait_list_size>" << getWaitlist.size() << "</get_wait_list_size>";
	stream << "<disable_wait_list_size>" << disableWaitlist.size() << "</disable_wait_list_size>";
	stream << "<processes_being_spawned>" << processesBeingSpawned << "</processes_being_spawned>";
	if (m_spawning) {
		stream << "<spawning/>";
	}
	if (restarting()) {
		stream << "<restarting/>";
	}
	if (includeSecrets) {
		stream << "<secret>" << escapeForXml(getApiKey().toStaticString()) << "</secret>";
		stream << "<api_key>" << escapeForXml(getApiKey().toStaticString()) << "</api_key>";
	}
	LifeStatus lifeStatus = (LifeStatus) this->lifeStatus.load(boost::memory_order_relaxed);
	switch (lifeStatus) {
	case ALIVE:
		stream << "<life_status>ALIVE</life_status>";
		break;
	case SHUTTING_DOWN:
		stream << "<life_status>SHUTTING_DOWN</life_status>";
		break;
	case SHUT_DOWN:
		stream << "<life_status>SHUT_DOWN</life_status>";
		break;
	default:
		P_BUG("Unknown 'lifeStatus' state " << lifeStatus);
	}

	SpawningKit::UserSwitchingInfo usInfo(SpawningKit::prepareUserSwitching(options));
	stream << "<user>" << escapeForXml(usInfo.username) << "</user>";
	stream << "<uid>" << usInfo.uid << "</uid>";
	stream << "<group>" << escapeForXml(usInfo.groupname) << "</group>";
	stream << "<gid>" << usInfo.gid << "</gid>";

	stream << "<options>";
	options.toXml(stream, getResourceLocator());
	stream << "</options>";

	stream << "<processes>";

	for (it = enabledProcesses.begin(); it != enabledProcesses.end(); it++) {
		stream << "<process>";
		(*it)->inspectXml(stream, includeSecrets);
		stream << "</process>";
	}
	for (it = disablingProcesses.begin(); it != disablingProcesses.end(); it++) {
		stream << "<process>";
		(*it)->inspectXml(stream, includeSecrets);
		stream << "</process>";
	}
	for (it = disabledProcesses.begin(); it != disabledProcesses.end(); it++) {
		stream << "<process>";
		(*it)->inspectXml(stream, includeSecrets);
		stream << "</process>";
	}
	for (it = detachedProcesses.begin(); it != detachedProcesses.end(); it++) {
		stream << "<process>";
		(*it)->inspectXml(stream, includeSecrets);
		stream << "</process>";
	}

	stream << "</processes>";
}

} // namespace ApplicationPool2
} // namespace Passenger
<commit_msg>Group::allEnabledProcessesAreTotallyBusy should return false if there are no enabled processes.<commit_after>/*
 *  Phusion Passenger - https://www.phusionpassenger.com/
 *  Copyright (c) 2011-2017 Phusion Holding B.V.
 *
 *  "Passenger", "Phusion Passenger" and "Union Station" are registered
 *  trademarks of Phusion Holding B.V.
 *
 *  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 <Core/ApplicationPool/Group.h>

/*************************************************************************
 *
 * Session management functions for ApplicationPool2::Group
 *
 *************************************************************************/

namespace Passenger {
namespace ApplicationPool2 {

using namespace std;
using namespace boost;

/****************************
 *
 * Public methods
 *
 ****************************/

unsigned int
Group::getProcessCount() const {
	return enabledCount + disablingCount + disabledCount;
}

/**
 * Returns whether the lower bound of the group-specific process limits
 * have been satisfied. Note that even if the result is false, the pool limits
 * may not allow spawning, so you should check `pool->atFullCapacity()` too.
 */
bool
Group::processLowerLimitsSatisfied() const {
	return capacityUsed() >= options.minProcesses;
}

/**
 * Returns whether the upper bound of the group-specific process limits have
 * been reached, or surpassed. Does not check whether pool limits have been
 * reached. Use `pool->atFullCapacity()` to check for that.
 */
bool
Group::processUpperLimitsReached() const {
	return options.maxProcesses != 0 && capacityUsed() >= options.maxProcesses;
}

/**
 * Returns whether all enabled processes are totally busy. If so, another
 * process should be spawned, if allowed by the process limits.
 * Returns false if there are no enabled processes.
 */
bool
Group::allEnabledProcessesAreTotallyBusy() const {
	return nEnabledProcessesTotallyBusy == enabledCount && enabledCount > 0;
}

/**
 * Returns the number of processes in this group that should be part of the
 * ApplicationPool process limits calculations.
 */
unsigned int
Group::capacityUsed() const {
	return enabledCount + disablingCount + disabledCount + processesBeingSpawned;
}

/**
 * Checks whether this group is waiting for capacity on the pool to
 * become available before it can continue processing requests.
 */
bool
Group::isWaitingForCapacity() const {
	return enabledProcesses.empty()
		&& processesBeingSpawned == 0
		&& !m_restarting
		&& !getWaitlist.empty();
}

bool
Group::garbageCollectable(unsigned long long now) const {
	/* if (now == 0) {
		now = SystemTime::getUsec();
	}
	return busyness() == 0
		&& getWaitlist.empty()
		&& disabledProcesses.empty()
		&& options.getMaxPreloaderIdleTime() != 0
		&& now - spawner->lastUsed() >
			(unsigned long long) options.getMaxPreloaderIdleTime() * 1000000; */
	return false;
}

void
Group::inspectXml(std::ostream &stream, bool includeSecrets) const {
	ProcessList::const_iterator it;

	stream << "<name>" << escapeForXml(info.name) << "</name>";
	stream << "<component_name>" << escapeForXml(info.name) << "</component_name>";
	stream << "<app_root>" << escapeForXml(options.appRoot) << "</app_root>";
	stream << "<app_type>" << escapeForXml(options.appType) << "</app_type>";
	stream << "<environment>" << escapeForXml(options.environment) << "</environment>";
	stream << "<uuid>" << toString(uuid) << "</uuid>";
	stream << "<enabled_process_count>" << enabledCount << "</enabled_process_count>";
	stream << "<disabling_process_count>" << disablingCount << "</disabling_process_count>";
	stream << "<disabled_process_count>" << disabledCount << "</disabled_process_count>";
	stream << "<capacity_used>" << capacityUsed() << "</capacity_used>";
	stream << "<get_wait_list_size>" << getWaitlist.size() << "</get_wait_list_size>";
	stream << "<disable_wait_list_size>" << disableWaitlist.size() << "</disable_wait_list_size>";
	stream << "<processes_being_spawned>" << processesBeingSpawned << "</processes_being_spawned>";
	if (m_spawning) {
		stream << "<spawning/>";
	}
	if (restarting()) {
		stream << "<restarting/>";
	}
	if (includeSecrets) {
		stream << "<secret>" << escapeForXml(getApiKey().toStaticString()) << "</secret>";
		stream << "<api_key>" << escapeForXml(getApiKey().toStaticString()) << "</api_key>";
	}
	LifeStatus lifeStatus = (LifeStatus) this->lifeStatus.load(boost::memory_order_relaxed);
	switch (lifeStatus) {
	case ALIVE:
		stream << "<life_status>ALIVE</life_status>";
		break;
	case SHUTTING_DOWN:
		stream << "<life_status>SHUTTING_DOWN</life_status>";
		break;
	case SHUT_DOWN:
		stream << "<life_status>SHUT_DOWN</life_status>";
		break;
	default:
		P_BUG("Unknown 'lifeStatus' state " << lifeStatus);
	}

	SpawningKit::UserSwitchingInfo usInfo(SpawningKit::prepareUserSwitching(options));
	stream << "<user>" << escapeForXml(usInfo.username) << "</user>";
	stream << "<uid>" << usInfo.uid << "</uid>";
	stream << "<group>" << escapeForXml(usInfo.groupname) << "</group>";
	stream << "<gid>" << usInfo.gid << "</gid>";

	stream << "<options>";
	options.toXml(stream, getResourceLocator());
	stream << "</options>";

	stream << "<processes>";

	for (it = enabledProcesses.begin(); it != enabledProcesses.end(); it++) {
		stream << "<process>";
		(*it)->inspectXml(stream, includeSecrets);
		stream << "</process>";
	}
	for (it = disablingProcesses.begin(); it != disablingProcesses.end(); it++) {
		stream << "<process>";
		(*it)->inspectXml(stream, includeSecrets);
		stream << "</process>";
	}
	for (it = disabledProcesses.begin(); it != disabledProcesses.end(); it++) {
		stream << "<process>";
		(*it)->inspectXml(stream, includeSecrets);
		stream << "</process>";
	}
	for (it = detachedProcesses.begin(); it != detachedProcesses.end(); it++) {
		stream << "<process>";
		(*it)->inspectXml(stream, includeSecrets);
		stream << "</process>";
	}

	stream << "</processes>";
}

} // namespace ApplicationPool2
} // namespace Passenger
<|endoftext|>


<commit_before>#include "Test.h"
#include "System/Common.h"
#include "System/Time.h"
#include "System/ThreadPool.h"
#include "System/Events/Callable.h"

TEST_DEFINE(TestStorageRandomGetSetDelete);

static bool             crash = false;

static void CrashFunc()
{
    char*   null;

    MSleep((unsigned)(1000.0 / RandomInt(1, 100) - 7) * 1000);

    if (crash)
    {
        null = NULL;
        null[0] = 0;
    }
}

TEST_DEFINE(TestCrashStorage)
{
    int         ret;
    ThreadPool* thread;

    crash = true;
    thread = ThreadPool::Create(1);
    thread->Start();
    thread->Execute(CFunc(CrashFunc));

    while (true)
    {
        ret = TestStorageRandomGetSetDelete();
        if (ret != TEST_SUCCESS)
            return ret;
    }

    crash = false;
    return TEST_SUCCESS;
}

<commit_msg>Improved crash random.<commit_after>#include "Test.h"
#include "System/Common.h"
#include "System/Time.h"
#include "System/ThreadPool.h"
#include "System/Events/Callable.h"

TEST_DEFINE(TestStorageRandomGetSetDelete);

static bool             crash = false;

static void CrashFunc()
{
    char*   null;

    MSleep((unsigned)(1000.0 / RandomInt(1, 100)) * 1000);

    if (crash)
    {
        null = NULL;
        null[0] = 0;
    }
}

TEST_DEFINE(TestCrashStorage)
{
    int         ret;
    ThreadPool* thread;

    crash = true;
    thread = ThreadPool::Create(1);
    thread->Start();
    thread->Execute(CFunc(CrashFunc));

    while (true)
    {
        ret = TestStorageRandomGetSetDelete();
        if (ret != TEST_SUCCESS)
            return ret;
    }

    crash = false;
    return TEST_SUCCESS;
}

<|endoftext|>


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

#include <SynthesizedBeams.hpp>
#include <ArgumentList.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <gtest/gtest.h>

const std::string wrongFileName = "does_not_exist";
const unsigned int padding = 128;
std::string path;

int main(int argc, char * argv[])
{
    testing::InitGoogleTest(&argc, argv);
    isa::utils::ArgumentList arguments(argc, argv);
    try
    {
        path = arguments.getSwitchArgument<std::string>("-path");
    }
    catch ( std::exception & err )
    {
        std::cerr << std::endl;
        std::cerr << "Required command line parameters:" << std::endl;
        std::cerr << "\t-path <string> // The path of the test input files" << std::endl;
        std::cerr << std::endl;
        return -1;
    }
    return RUN_ALL_TESTS();
}

TEST(BeamMapping, GenerateSingle)
{
    AstroData::Observation observation;
    std::vector<unsigned int> mapping;
    observation.setNrBeams(12);
    observation.setNrSynthesizedBeams(71);
    observation.setFrequencyRange(1, 1536, 0.0f, 0.0f);
    AstroData::generateBeamMapping(observation, mapping, padding);
    for ( unsigned int sBeam = 0; sBeam < observation.getNrSynthesizedBeams(); sBeam++ )
    {
        for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ )
        {
            EXPECT_EQ(mapping[(sBeam * observation.getNrChannels(padding / sizeof(unsigned int))) + channel], sBeam % observation.getNrBeams());
        }
    }
}

TEST(BeamMapping, GenerateSubband)
{
    AstroData::Observation observation;
    std::vector<unsigned int> mapping;
    observation.setNrBeams(12);
    observation.setNrSynthesizedBeams(71);
    observation.setFrequencyRange(32, 1536, 0.0f, 0.0f);
    AstroData::generateBeamMapping(observation, mapping, padding, true);
    for ( unsigned int sBeam = 0; sBeam < observation.getNrSynthesizedBeams(); sBeam++ )
    {
        for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ )
        {
            EXPECT_EQ(mapping[(sBeam * observation.getNrSubbands(padding / sizeof(unsigned int))) + subband], sBeam % observation.getNrBeams());
        }
    }
}

TEST(BeamMapping, ReadSubband)
{
    AstroData::Observation observation;
    std::vector<unsigned int> mapping;
    observation.setNrBeams(12);
    observation.setNrSynthesizedBeams(71);
    observation.setFrequencyRange(32, 1536, 0.0f, 0.0f);
    AstroData::readBeamMapping(observation, path + "/sb_table.conf", mapping, padding, true);
    EXPECT_EQ(mapping[0], 4);
    EXPECT_EQ(mapping[31], 11);
    EXPECT_EQ(mapping[(18 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 8], 3);
    EXPECT_EQ(mapping[(18 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 18], 4);
    EXPECT_EQ(mapping[(18 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 19], 4);
    EXPECT_EQ(mapping[(18 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 27], 5);
    for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ )
    {
        EXPECT_EQ(mapping[(35 * observation.getNrSubbands(padding / sizeof(unsigned int))) + subband], 0);
    }
    EXPECT_EQ(mapping[(70 * observation.getNrSubbands(padding / sizeof(unsigned int)))], 8);
    EXPECT_EQ(mapping[(70 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 31], 1);
}
<commit_msg>Memory allocation.<commit_after>// Copyright 2019 Netherlands eScience Center and Netherlands Institute for Radio Astronomy (ASTRON)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <SynthesizedBeams.hpp>
#include <ArgumentList.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <gtest/gtest.h>

const std::string wrongFileName = "does_not_exist";
const unsigned int padding = 128;
std::string path;

int main(int argc, char * argv[])
{
    testing::InitGoogleTest(&argc, argv);
    isa::utils::ArgumentList arguments(argc, argv);
    try
    {
        path = arguments.getSwitchArgument<std::string>("-path");
    }
    catch ( std::exception & err )
    {
        std::cerr << std::endl;
        std::cerr << "Required command line parameters:" << std::endl;
        std::cerr << "\t-path <string> // The path of the test input files" << std::endl;
        std::cerr << std::endl;
        return -1;
    }
    return RUN_ALL_TESTS();
}

TEST(BeamMapping, GenerateSingle)
{
    AstroData::Observation observation;
    std::vector<unsigned int> mapping;
    observation.setNrBeams(12);
    observation.setNrSynthesizedBeams(71);
    observation.setFrequencyRange(1, 1536, 0.0f, 0.0f);
    mapping.resize(observation.getNrSynthesizedBeams() * observation.getNrChannels(padding));
    AstroData::generateBeamMapping(observation, mapping, padding);
    for ( unsigned int sBeam = 0; sBeam < observation.getNrSynthesizedBeams(); sBeam++ )
    {
        for ( unsigned int channel = 0; channel < observation.getNrChannels(); channel++ )
        {
            EXPECT_EQ(mapping[(sBeam * observation.getNrChannels(padding / sizeof(unsigned int))) + channel], sBeam % observation.getNrBeams());
        }
    }
}

TEST(BeamMapping, GenerateSubband)
{
    AstroData::Observation observation;
    std::vector<unsigned int> mapping;
    observation.setNrBeams(12);
    observation.setNrSynthesizedBeams(71);
    observation.setFrequencyRange(32, 1536, 0.0f, 0.0f);
    mapping.resize(observation.getNrSynthesizedBeams() * observation.getNrSubbands(padding));
    AstroData::generateBeamMapping(observation, mapping, padding, true);
    for ( unsigned int sBeam = 0; sBeam < observation.getNrSynthesizedBeams(); sBeam++ )
    {
        for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ )
        {
            EXPECT_EQ(mapping[(sBeam * observation.getNrSubbands(padding / sizeof(unsigned int))) + subband], sBeam % observation.getNrBeams());
        }
    }
}

TEST(BeamMapping, ReadSubband)
{
    AstroData::Observation observation;
    std::vector<unsigned int> mapping;
    observation.setNrBeams(12);
    observation.setNrSynthesizedBeams(71);
    observation.setFrequencyRange(32, 1536, 0.0f, 0.0f);
    mapping.resize(observation.getNrSynthesizedBeams() * observation.getNrSubbands(padding));
    AstroData::readBeamMapping(observation, path + "/sb_table.conf", mapping, padding, true);
    EXPECT_EQ(mapping[0], 4);
    EXPECT_EQ(mapping[31], 11);
    EXPECT_EQ(mapping[(18 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 8], 3);
    EXPECT_EQ(mapping[(18 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 18], 4);
    EXPECT_EQ(mapping[(18 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 19], 4);
    EXPECT_EQ(mapping[(18 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 27], 5);
    for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ )
    {
        EXPECT_EQ(mapping[(35 * observation.getNrSubbands(padding / sizeof(unsigned int))) + subband], 0);
    }
    EXPECT_EQ(mapping[(70 * observation.getNrSubbands(padding / sizeof(unsigned int)))], 8);
    EXPECT_EQ(mapping[(70 * observation.getNrSubbands(padding / sizeof(unsigned int))) + 31], 1);
}
<|endoftext|>


<commit_before>#include "StateMachine.h"
#include "Timing.h"
#include "Logger.h"
#include "render/Text.h"
#include "Graphics.h"
#include "Quirks.h"
#include "ResourceManager.h"
#include "Status.h"
#include "map/Map.h"
#include "map/StateMap.h"
#include "piaf/Archive.h"
#include "utility/misc.h"

using namespace WalrusRPG;
using WalrusRPG::PIAF::Archive;
using WalrusRPG::Graphics::Texture;
using namespace WalrusRPG::Graphics;

int main(int argc, char *argv[])
{
    UNUSED(argc);
    Logger::log("WalrusRPG Init");
    Status::init();
    Graphics::init();
    Timing::init();
    Quirks::init(argv[0]);
    ResourceManager::init();
    Text::init();
    Logger::log("WalrusRPG ready. Rock'n'roll, baby!");
    {
        // Keep the ManagedArchive in its own variable, to avoid unloading it.
        ManagedArchive m("data/wip_data.wrf");
        Archive *arc = ManagedArchive("");
        Texture tex(arc->get("ov.png"));
        WalrusRPG::PIAF::File f1 = arc->get("l1.bin");
        WalrusRPG::PIAF::File f2 = arc->get("l2.bin");

        const uint8_t *l1 = f1.get();
        const uint8_t *l2 = f2.get();

        // TODO better map reading.
        uint16_t *dungeonTest = new uint16_t[f1.file_size / 2 + 1];
        uint16_t *dungeonTest2 = new uint16_t[f1.file_size / 2 + 1];

        for (unsigned i = 0; i < f1.file_size / 2; i++)
        {
            dungeonTest[i] = read_big_endian_value<uint16_t>(&l1[i * 2]);
            dungeonTest2[i] = read_big_endian_value<uint16_t>(&l2[i * 2]);
        }

        Map map(20, 20, dungeonTest, dungeonTest2, tex);
        tinystl::vector<Frame> stripe21;
        tinystl::vector<Frame> stripe22;
        stripe21.push_back({21, 23});
        stripe21.push_back({22, 31});
        stripe22.push_back({22, 37});
        stripe22.push_back({21, 41});
        map.anim.add_animation(21, {stripe21, true, 0});
        map.anim.add_animation(22, {stripe22, true, 0});
        StateMachine::init();
        StateMachine::push(new States::StateMap(0, 0, map));
        StateMachine::run();
        delete[] dungeonTest;
        delete[] dungeonTest2;
    }

    Logger::log("WalrusRPG Deinit");
    StateMachine::deinit();
    ResourceManager::deinit();
    Quirks::deinit();
    Timing::deinit();
    Graphics::deinit();
    Status::deinit();
    Logger::log("WalrusRPG Exit");

    return 0;
}
<commit_msg>*facepalm*<commit_after>#include "StateMachine.h"
#include "Timing.h"
#include "Logger.h"
#include "render/Text.h"
#include "Graphics.h"
#include "Quirks.h"
#include "ResourceManager.h"
#include "Status.h"
#include "map/Map.h"
#include "map/StateMap.h"
#include "piaf/Archive.h"
#include "utility/misc.h"

using namespace WalrusRPG;
using WalrusRPG::PIAF::Archive;
using WalrusRPG::Graphics::Texture;
using namespace WalrusRPG::Graphics;

int main(int argc, char *argv[])
{
    UNUSED(argc);
    Logger::log("WalrusRPG Init");
    Status::init();
    Graphics::init();
    Timing::init();
    Quirks::init(argv[0]);
    ResourceManager::init();
    Text::init();
    Logger::log("WalrusRPG ready. Rock'n'roll, baby!");
    {
        // Keep the ManagedArchive in its own variable, to avoid unloading it.
        ManagedArchive m("data/wip_data.wrf");
        Archive *arc = m;
        Texture tex(arc->get("ov.png"));
        WalrusRPG::PIAF::File f1 = arc->get("l1.bin");
        WalrusRPG::PIAF::File f2 = arc->get("l2.bin");

        const uint8_t *l1 = f1.get();
        const uint8_t *l2 = f2.get();

        // TODO better map reading.
        uint16_t *dungeonTest = new uint16_t[f1.file_size / 2 + 1];
        uint16_t *dungeonTest2 = new uint16_t[f1.file_size / 2 + 1];

        for (unsigned i = 0; i < f1.file_size / 2; i++)
        {
            dungeonTest[i] = read_big_endian_value<uint16_t>(&l1[i * 2]);
            dungeonTest2[i] = read_big_endian_value<uint16_t>(&l2[i * 2]);
        }

        Map map(20, 20, dungeonTest, dungeonTest2, tex);
        tinystl::vector<Frame> stripe21;
        tinystl::vector<Frame> stripe22;
        stripe21.push_back({21, 23});
        stripe21.push_back({22, 31});
        stripe22.push_back({22, 37});
        stripe22.push_back({21, 41});
        map.anim.add_animation(21, {stripe21, true, 0});
        map.anim.add_animation(22, {stripe22, true, 0});
        StateMachine::init();
        StateMachine::push(new States::StateMap(0, 0, map));
        StateMachine::run();
        delete[] dungeonTest;
        delete[] dungeonTest2;
    }

    Logger::log("WalrusRPG Deinit");
    StateMachine::deinit();
    ResourceManager::deinit();
    Quirks::deinit();
    Timing::deinit();
    Graphics::deinit();
    Status::deinit();
    Logger::log("WalrusRPG Exit");

    return 0;
}
<|endoftext|>


<commit_before>/*
 *  This file is part of Poedit (http://www.poedit.net)
 *
 *  Copyright (C) 2003 Christophe Hermier
 *
 *  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.
 *
 *  $Id$
 *
 *  Catalog export into HTML file
 *
 */

#include <wx/intl.h>
#include <wx/colour.h>
#include <wx/utils.h>
#include <wx/textfile.h>

#include "catalog.h"

// colours used in the list:
// (FIXME: this is duplicated with code in edframe.cpp, get rid of this
// duplication, preferably by making the colours customizable and stored
// in wxConfig)

#define g_darkColourFactor 0.95
#define DARKEN_COLOUR(r,g,b) (wxColour(int((r)*g_darkColourFactor),\
                                       int((g)*g_darkColourFactor),\
                                       int((b)*g_darkColourFactor)))
#define LIST_COLOURS(r,g,b) { wxColour(r,g,b), DARKEN_COLOUR(r,g,b) }
static wxColour
    g_ItemColourNormal[2] =       LIST_COLOURS(0xFF,0xFF,0xFF), // white
    g_ItemColourUntranslated[2] = LIST_COLOURS(0xA5,0xEA,0xEF), // blue
    g_ItemColourFuzzy[2] =        LIST_COLOURS(0xF4,0xF1,0xC1); // yellow

bool Catalog::ExportToHTML(const wxString& filename)
{
	size_t i;
	wxTextFile f;

	if ( wxFileExists(filename) )
	{
		wxRemoveFile ( filename);
	}

	if (!f.Create(filename))
	{
		return false;
	}

	// TODO use some kind of HTML template system to allow different styles

	wxString line;

	// HTML HEADER
    f.AddLine(_T("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"));
    f.AddLine(_T(""));

    f.AddLine(_T(""));
	line.Printf(_T("<title> %s - %s / %s - Poedit Export </title>"),
                m_header.Project.c_str(),
                m_header.Language.c_str(),
                m_header.Country.c_str());
    f.AddLine(line);
    f.AddLine(_T("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" ) );
    f.AddLine(_T(""));
    f.AddLine(_T(""));

	line.Printf(_T("
 %s : %s / %s
"),
               m_header.Project.c_str(),
               m_header.Language.c_str(),
               m_header.Country.c_str());
    f.AddLine(line);

	// po file header information :

	// String here are duplicates from the ones in setting.xrc
	// TODO find a way if possible to synchronize them

	f.AddLine(_T("
"));

	line.Printf(_T("
%s
"),
                _("Project info"));
	f.AddLine(line);
	wxString line_format = _T("
%s	%s
");
	line.Printf(line_format,
                _("Project name and version:"),
                m_header.Project.c_str());
	f.AddLine(line);
	line.Printf(line_format, _("Language:"),
                m_header.Language.c_str());
	f.AddLine(line);
	line.Printf(line_format, _("Country:"),
                m_header.Country.c_str());
	f.AddLine(line);
    line.Printf(line_format, _("Team:"),
                m_header.Team.c_str());
	f.AddLine(line);
	line.Printf(_T("
%s	%s
"),
                _("Team's email address:"),
                m_header.TeamEmail.c_str(), m_header.TeamEmail.c_str());
	f.AddLine(line);
	line.Printf(line_format, _("Charset:"),
                m_header.Charset.c_str());
	f.AddLine(line);

	f.AddLine( _T("
") );
	// statistics

    int all = 0;
	int fuzzy = 0;
	int untranslated = 0;
    int broken = 0;
    GetStatistics(&all, &fuzzy, &broken, &untranslated);
	line.Printf(
            _("%i strings (%i fuzzy, %i bad tokens, %i not translated)"),
            all, fuzzy, broken, untranslated);
	f.AddLine(line);

	// data printed in a table :
	f.AddLine(_T("
"));

	f.AddLine(_T("
"));
	f.AddLine(_T(""));
	f.AddLine(_("Original string"));
	f.AddLine(_T("	"));
	f.AddLine(_T(""));
	f.AddLine(_("Translation"));
	f.AddLine(_T("	"));
	f.AddLine(_T("	"));
	f.AddLine(_T(""));
	f.AddLine(_("Notes"));
	f.AddLine(_T("	"));
	f.AddLine(_T("
"));

	for (i = 0; i < GetCount(); i++)
    {
        const CatalogItem& data = m_items[i];

		wxColour bgcolor = g_ItemColourNormal[i % 2];
		wxString original_string = data.GetString();

		wxString translation = data.GetTranslation();
		if (translation.empty())
		{
			translation = _T(" ");
			bgcolor = g_ItemColourUntranslated[i % 2];
		}

		wxString flags;

		if (data.IsAutomatic())
		{
			flags += _("Automatic translation");
			flags += _T("
");
		}
		if (data.IsFuzzy())
		{
			bgcolor = g_ItemColourFuzzy[i % 2];
			flags += _("Fuzzy translation");
			flags += _T("
");
		}
		if (flags.empty())
		{
			flags = _T(" ");
		}

		wxString tr;
		tr.Printf(_T("
"),
                  bgcolor.Red(), bgcolor.Green(), bgcolor.Blue());
        f.AddLine(tr);

        f.AddLine(_T(""));
		f.AddLine(original_string);
        f.AddLine(_T("	"));
        f.AddLine(_T(""));
		f.AddLine(translation);
        f.AddLine(_T("	"));
        f.AddLine(_T(""));
        f.AddLine(_T(""));
		f.AddLine(flags);
        f.AddLine(_T(""));
        f.AddLine(_T("	"));
        f.AddLine(_T("
"));
    }

	f.AddLine(_T("
"));
	f.AddLine(_T(""));
	f.AddLine(_T(""));

	bool written = f.Write(wxTextFileType_None, wxConvUTF8);

	f.Close();

    return written;
}
<commit_msg>use same statistics string in PoeditFrame and HTML export<commit_after>/*
 *  This file is part of Poedit (http://www.poedit.net)
 *
 *  Copyright (C) 2003 Christophe Hermier
 *
 *  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.
 *
 *  $Id$
 *
 *  Catalog export into HTML file
 *
 */

#include <wx/intl.h>
#include <wx/colour.h>
#include <wx/utils.h>
#include <wx/textfile.h>

#include "catalog.h"

// colours used in the list:
// (FIXME: this is duplicated with code in edframe.cpp, get rid of this
// duplication, preferably by making the colours customizable and stored
// in wxConfig)

#define g_darkColourFactor 0.95
#define DARKEN_COLOUR(r,g,b) (wxColour(int((r)*g_darkColourFactor),\
                                       int((g)*g_darkColourFactor),\
                                       int((b)*g_darkColourFactor)))
#define LIST_COLOURS(r,g,b) { wxColour(r,g,b), DARKEN_COLOUR(r,g,b) }
static wxColour
    g_ItemColourNormal[2] =       LIST_COLOURS(0xFF,0xFF,0xFF), // white
    g_ItemColourUntranslated[2] = LIST_COLOURS(0xA5,0xEA,0xEF), // blue
    g_ItemColourFuzzy[2] =        LIST_COLOURS(0xF4,0xF1,0xC1); // yellow

bool Catalog::ExportToHTML(const wxString& filename)
{
	size_t i;
	wxTextFile f;

	if ( wxFileExists(filename) )
	{
		wxRemoveFile ( filename);
	}

	if (!f.Create(filename))
	{
		return false;
	}

	// TODO use some kind of HTML template system to allow different styles

	wxString line;

	// HTML HEADER
    f.AddLine(_T("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"));
    f.AddLine(_T(""));

    f.AddLine(_T(""));
	line.Printf(_T("<title> %s - %s / %s - Poedit Export </title>"),
                m_header.Project.c_str(),
                m_header.Language.c_str(),
                m_header.Country.c_str());
    f.AddLine(line);
    f.AddLine(_T("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" ) );
    f.AddLine(_T(""));
    f.AddLine(_T(""));

	line.Printf(_T("
 %s : %s / %s
"),
               m_header.Project.c_str(),
               m_header.Language.c_str(),
               m_header.Country.c_str());
    f.AddLine(line);

	// po file header information :

	// String here are duplicates from the ones in setting.xrc
	// TODO find a way if possible to synchronize them

	f.AddLine(_T("
"));

	line.Printf(_T("
%s
"),
                _("Project info"));
	f.AddLine(line);
	wxString line_format = _T("
%s	%s
");
	line.Printf(line_format,
                _("Project name and version:"),
                m_header.Project.c_str());
	f.AddLine(line);
	line.Printf(line_format, _("Language:"),
                m_header.Language.c_str());
	f.AddLine(line);
	line.Printf(line_format, _("Country:"),
                m_header.Country.c_str());
	f.AddLine(line);
    line.Printf(line_format, _("Team:"),
                m_header.Team.c_str());
	f.AddLine(line);
	line.Printf(_T("
%s	%s
"),
                _("Team's email address:"),
                m_header.TeamEmail.c_str(), m_header.TeamEmail.c_str());
	f.AddLine(line);
	line.Printf(line_format, _("Charset:"),
                m_header.Charset.c_str());
	f.AddLine(line);

	f.AddLine( _T("
") );
	// statistics

    int all = 0;
	int fuzzy = 0;
	int untranslated = 0;
    int badtokens = 0;
    GetStatistics(&all, &fuzzy, &badtokens, &untranslated);

    int percent = (all == 0 ) ? 0 :
                  (100 * (all-fuzzy-badtokens-untranslated) / all);
    line.Printf(_("%i %% translated, %i strings (%i fuzzy, %i bad tokens, %i not translated)"),
               percent, all, fuzzy, badtokens, untranslated);

	f.AddLine(line);

	// data printed in a table :
	f.AddLine(_T("
"));

	f.AddLine(_T("
"));
	f.AddLine(_T(""));
	f.AddLine(_("Original string"));
	f.AddLine(_T("	"));
	f.AddLine(_T(""));
	f.AddLine(_("Translation"));
	f.AddLine(_T("	"));
	f.AddLine(_T("	"));
	f.AddLine(_T(""));
	f.AddLine(_("Notes"));
	f.AddLine(_T("	"));
	f.AddLine(_T("
"));

	for (i = 0; i < GetCount(); i++)
    {
        const CatalogItem& data = m_items[i];

		wxColour bgcolor = g_ItemColourNormal[i % 2];
		wxString original_string = data.GetString();

		wxString translation = data.GetTranslation();
		if (translation.empty())
		{
			translation = _T(" ");
			bgcolor = g_ItemColourUntranslated[i % 2];
		}

		wxString flags;

		if (data.IsAutomatic())
		{
			flags += _("Automatic translation");
			flags += _T("
");
		}
		if (data.IsFuzzy())
		{
			bgcolor = g_ItemColourFuzzy[i % 2];
			flags += _("Fuzzy translation");
			flags += _T("
");
		}
		if (flags.empty())
		{
			flags = _T(" ");
		}

		wxString tr;
		tr.Printf(_T("
"),
                  bgcolor.Red(), bgcolor.Green(), bgcolor.Blue());
        f.AddLine(tr);

        f.AddLine(_T(""));
		f.AddLine(original_string);
        f.AddLine(_T("	"));
        f.AddLine(_T(""));
		f.AddLine(translation);
        f.AddLine(_T("	"));
        f.AddLine(_T(""));
        f.AddLine(_T(""));
		f.AddLine(flags);
        f.AddLine(_T(""));
        f.AddLine(_T("	"));
        f.AddLine(_T("
"));
    }

	f.AddLine(_T("
"));
	f.AddLine(_T(""));
	f.AddLine(_T(""));

	bool written = f.Write(wxTextFileType_None, wxConvUTF8);

	f.Close();

    return written;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * libVLC backend for the Phonon library                                     *
 *                                                                           *
 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
 * Copyright (C) 2009-2010 vlc-phonon AUTHORS                                *
 *                                                                           *
 * This program is free software; you can redistribute it and/or             *
 * modify it under the terms of the GNU Lesser General Public                *
 * License as published by the Free Software Foundation; either              *
 * version 2.1 of the License, or (at your option) any later version.        *
 *                                                                           *
 * This program is distributed in the hope that it will be useful,           *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this package; if not, write to the Free Software       *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "vlcvideowidget.h"

#include <QtGui/QResizeEvent>
#include <QtCore/QDebug>

namespace Phonon
{
namespace VLC {

VLCVideoWidget::VLCVideoWidget(QWidget *p_parent) : WidgetNoPaintEvent(p_parent)
{
    // Set background color
    setBackgroundColor(Qt::black);
}

VLCVideoWidget::~VLCVideoWidget()
{
}

void VLCVideoWidget::resizeEvent(QResizeEvent *p_event)
{
    qDebug() << "resizeEvent" << p_event->size();
}

void VLCVideoWidget::setAspectRatio(double f_aspect_ratio)
{
}

void VLCVideoWidget::setScaleAndCropMode(bool b_scale_and_crop)
{
}

/**
 * Sets an approximate video size to provide a size hint. It will be set
 * to the original size of the video.
 */
void VLCVideoWidget::setVideoSize(const QSize & size)
{
    videoSize = size;
}

QSize VLCVideoWidget::sizeHint() const
{
    if (!videoSize.isEmpty())
        return videoSize;
    return QSize(640, 480);
}

}
} // Namespace Phonon::VLC
<commit_msg>update videowidget's geometry and the widget itself when the video size changes<commit_after>/*****************************************************************************
 * libVLC backend for the Phonon library                                     *
 *                                                                           *
 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
 * Copyright (C) 2009-2010 vlc-phonon AUTHORS                                *
 *                                                                           *
 * This program is free software; you can redistribute it and/or             *
 * modify it under the terms of the GNU Lesser General Public                *
 * License as published by the Free Software Foundation; either              *
 * version 2.1 of the License, or (at your option) any later version.        *
 *                                                                           *
 * This program is distributed in the hope that it will be useful,           *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this package; if not, write to the Free Software       *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "vlcvideowidget.h"

#include <QtGui/QResizeEvent>
#include <QtCore/QDebug>

namespace Phonon
{
namespace VLC {

VLCVideoWidget::VLCVideoWidget(QWidget *p_parent) : WidgetNoPaintEvent(p_parent)
{
    // Set background color
    setBackgroundColor(Qt::black);
}

VLCVideoWidget::~VLCVideoWidget()
{
}

void VLCVideoWidget::resizeEvent(QResizeEvent *p_event)
{
    qDebug() << "resizeEvent" << p_event->size();
}

void VLCVideoWidget::setAspectRatio(double f_aspect_ratio)
{
}

void VLCVideoWidget::setScaleAndCropMode(bool b_scale_and_crop)
{
}

/**
 * Sets an approximate video size to provide a size hint. It will be set
 * to the original size of the video.
 */
void VLCVideoWidget::setVideoSize(const QSize & size)
{
    videoSize = size;
    updateGeometry();
    update();
}

QSize VLCVideoWidget::sizeHint() const
{
    if (!videoSize.isEmpty())
        return videoSize;
    return QSize(640, 480);
}

}
} // Namespace Phonon::VLC
<|endoftext|>


<commit_before>#include <boost/asio/io_service.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <atomic>
#include <system_error>
#include <thread>
#include <utility>

#include "connection_pool.hpp"
#include "length_framed_connection.hpp"
#include "testing_util.hpp"
#include "test_length_framed_server.hpp"
#include "thread_pool.hpp"

namespace riak {
namespace testing {
namespace {
constexpr auto allow_errors = response::allow_errors_yes;

TEST(ConnectionPoolTest, SequencedMessages) {
  InSequence sequence;
  mock_server server;
  thread_pool threads{4};
  std::unique_ptr<connection_pool<length_framed_connection>> pool{
      new connection_pool<length_framed_connection>{
          threads.io_service(), "localhost", server.port(), 2, 4096, 1000}};

  send_and_expect(*pool, "okay1", 300, errc_success, "okay1_reply", [&] {
  send_and_expect(*pool, "okay2", 300, errc_success, "okay2_reply", [&] {
  send_and_expect(*pool, "timeout1", 60, std::errc::timed_out, "");
  }); });

  EXPECT_CALL(server, on_receive(Eq(asio_success), Eq("okay1")))
      .WillOnce(Return(response{30, "okay1_reply"}));
  EXPECT_CALL(server, on_receive(Eq(asio_success), Eq("okay2")))
      .WillOnce(Return(response{50, "okay2_reply"}));
  EXPECT_CALL(server, on_receive(Eq(asio_success), Eq("timeout1")))
      .WillOnce(Return(response{70, "timeout1_reply", allow_errors}));
  server.expect_eof_and_close();

  // A single connection should be neccessary, since the messages are sent only
  // when the previous ones are received.
  server.run(1);
}

TEST(ConnectionPoolTest, ManyMessages) {
  for (uint32_t num_connections = 1; num_connections < 17;
       num_connections += 3) {
    mock_server server;
    thread_pool threads{4};
    std::atomic<uint32_t> msgs_received{0};
    constexpr uint32_t msgs_to_send = 1000;

    std::unique_ptr<connection_pool<length_framed_connection>> pool{
        new connection_pool<length_framed_connection>{
            threads.io_service(), "localhost", server.port(), num_connections,
            4096, 1000}};

    // Expect 'msgs_to_send' messages (in any order) and reply to 'msg' with
    // 'msg_reply'.
    for (uint32_t i = 0; i < msgs_to_send; ++i) {
      EXPECT_CALL(server, on_receive(Eq(asio_success), _))
          .WillOnce(Invoke([&, i](asio_error, std::string request) {
            return response{request + "_reply"};
          }))
          .RetiresOnSaturation();
    }
    server.expect_eof_and_close();  // The client will close the connection.
    std::thread server_thread{[&] { server.run(num_connections, 20000); }};

    // Send 'okay1', 'okay2' ... from two different threads at the same time
    // and kill the connection pool when all message replies have been received.
    auto stop_when_done = [&] {
      if (++msgs_received == msgs_to_send) {
        pool.reset();
        threads.io_service().stop();
      }
    };

    std::thread first_half{[&] {
      for (auto i = 0; i < msgs_to_send / 2; ++i) {
        send_and_expect(*pool, "okay" + std::to_string(i), 10000, errc_success,
                        "okay" + std::to_string(i) + "_reply", stop_when_done);
      }
    }};

    std::thread second_half{[&] {
      for (auto i = msgs_to_send / 2; i < msgs_to_send; ++i) {
        send_and_expect(*pool, "okay" + std::to_string(i), 10000, errc_success,
                        "okay" + std::to_string(i) + "_reply", stop_when_done);
      }
    }};

    first_half.join();
    second_half.join();
    server_thread.join();

    // Compute the variance of the reply counts of each connection and ensure
    // it is less than 10% -- a fair load balancing.
    size_t i_connection = 0;
    double variance = 0.0;
    double mean = static_cast<double>(msgs_to_send) / num_connections;
    std::stringstream counts_string_builder;
    for (auto count : server.reply_counts()) {
      EXPECT_LT(0, count);
      counts_string_builder << count << " ";
      variance += (count - mean) * (count - mean) / num_connections;
      ++i_connection;
    }
    EXPECT_LE(sqrt(variance), msgs_to_send / 100)
        << "FLAKY: This test checks for the variance of a load balancer, "
           "it is statistically possible that the test fails on a normal run. "
           "The counts are: " << counts_string_builder.str();
  }
}

TEST(ConnectionPoolTest, ConnectionRefused) {
  for (int i_run = 0; i_run < 100; ++i_run) {
    constexpr uint32_t msgs_to_send = 20;
    std::atomic<uint32_t> msgs_to_receive{msgs_to_send};
    thread_pool threads{4};
    std::unique_ptr<connection_pool<length_framed_connection>> pool{
        new connection_pool<length_framed_connection>{
            threads.io_service(), "localhost", random_port(), 3, 4096, 1000}};

    for (size_t i_msg = 0; i_msg < msgs_to_send; ++i_msg) {
      send_and_expect(*pool, "a", 1000, std::errc::connection_refused, "", [&] {
        if (--msgs_to_receive == 0) {
          pool.reset();
          threads.io_service().stop();
        }
      });
    }
    threads.io_service().run();
  }
}

}  // namespace
}  // namespace testing
}  // namespace riak
<commit_msg>increased timeouts for running tests in Jenkins<commit_after>#include <boost/asio/io_service.hpp>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <atomic>
#include <system_error>
#include <thread>
#include <utility>

#include "connection_pool.hpp"
#include "length_framed_connection.hpp"
#include "testing_util.hpp"
#include "test_length_framed_server.hpp"
#include "thread_pool.hpp"

namespace riak {
namespace testing {
namespace {
constexpr auto allow_errors = response::allow_errors_yes;

TEST(ConnectionPoolTest, SequencedMessages) {
  InSequence sequence;
  mock_server server;
  thread_pool threads{4};
  std::unique_ptr<connection_pool<length_framed_connection>> pool{
      new connection_pool<length_framed_connection>{
          threads.io_service(), "localhost", server.port(), 2, 4096, 1000}};

  send_and_expect(*pool, "okay1", 300, errc_success, "okay1_reply", [&] {
  send_and_expect(*pool, "okay2", 300, errc_success, "okay2_reply", [&] {
  send_and_expect(*pool, "timeout1", 60, std::errc::timed_out, "");
  }); });

  EXPECT_CALL(server, on_receive(Eq(asio_success), Eq("okay1")))
      .WillOnce(Return(response{30, "okay1_reply"}));
  EXPECT_CALL(server, on_receive(Eq(asio_success), Eq("okay2")))
      .WillOnce(Return(response{50, "okay2_reply"}));
  EXPECT_CALL(server, on_receive(Eq(asio_success), Eq("timeout1")))
      .WillOnce(Return(response{70, "timeout1_reply", allow_errors}));
  server.expect_eof_and_close();

  // A single connection should be neccessary, since the messages are sent only
  // when the previous ones are received.
  server.run(1);
}

TEST(ConnectionPoolTest, ManyMessages) {
  for (uint32_t num_connections = 1; num_connections < 17;
       num_connections += 3) {
    mock_server server;
    thread_pool threads{4};
    std::atomic<uint32_t> msgs_received{0};
    constexpr uint32_t msgs_to_send = 1000;

    std::unique_ptr<connection_pool<length_framed_connection>> pool{
        new connection_pool<length_framed_connection>{
            threads.io_service(), "localhost", server.port(), num_connections,
            4096, 1000}};

    // Expect 'msgs_to_send' messages (in any order) and reply to 'msg' with
    // 'msg_reply'.
    for (uint32_t i = 0; i < msgs_to_send; ++i) {
      EXPECT_CALL(server, on_receive(Eq(asio_success), _))
          .WillOnce(Invoke([&, i](asio_error, std::string request) {
            return response{request + "_reply"};
          }))
          .RetiresOnSaturation();
    }
    server.expect_eof_and_close();  // The client will close the connection.
    std::thread server_thread{[&] { server.run(num_connections, 20000); }};

    // Send 'okay1', 'okay2' ... from two different threads at the same time
    // and kill the connection pool when all message replies have been received.
    auto stop_when_done = [&] {
      if (++msgs_received == msgs_to_send) {
        pool.reset();
        threads.io_service().stop();
      }
    };

    std::thread first_half{[&] {
      for (auto i = 0; i < msgs_to_send / 2; ++i) {
        send_and_expect(*pool, "okay" + std::to_string(i), 20000, errc_success,
                        "okay" + std::to_string(i) + "_reply", stop_when_done);
      }
    }};

    std::thread second_half{[&] {
      for (auto i = msgs_to_send / 2; i < msgs_to_send; ++i) {
        send_and_expect(*pool, "okay" + std::to_string(i), 20000, errc_success,
                        "okay" + std::to_string(i) + "_reply", stop_when_done);
      }
    }};

    first_half.join();
    second_half.join();
    server_thread.join();

    // Compute the variance of the reply counts of each connection and ensure
    // it is less than 10% -- a fair load balancing.
    size_t i_connection = 0;
    double variance = 0.0;
    double mean = static_cast<double>(msgs_to_send) / num_connections;
    std::stringstream counts_string_builder;
    for (auto count : server.reply_counts()) {
      EXPECT_LT(0, count);
      counts_string_builder << count << " ";
      variance += (count - mean) * (count - mean) / num_connections;
      ++i_connection;
    }
    EXPECT_LE(sqrt(variance), msgs_to_send / 100)
        << "FLAKY: This test checks for the variance of a load balancer, "
           "it is statistically possible that the test fails on a normal run. "
           "The counts are: " << counts_string_builder.str();
  }
}

TEST(ConnectionPoolTest, ConnectionRefused) {
  for (int i_run = 0; i_run < 100; ++i_run) {
    constexpr uint32_t msgs_to_send = 20;
    std::atomic<uint32_t> msgs_to_receive{msgs_to_send};
    thread_pool threads{4};
    std::unique_ptr<connection_pool<length_framed_connection>> pool{
        new connection_pool<length_framed_connection>{
            threads.io_service(), "localhost", random_port(), 3, 4096, 1000}};

    for (size_t i_msg = 0; i_msg < msgs_to_send; ++i_msg) {
      send_and_expect(*pool, "a", 5000, std::errc::connection_refused, "", [&] {
        if (--msgs_to_receive == 0) {
          pool.reset();
          threads.io_service().stop();
        }
      });
    }
    threads.io_service().run();
  }
}

}  // namespace
}  // namespace testing
}  // namespace riak
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 The LitecoinZ developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifdef WIN32
#define CURL_STATICLIB
#endif

#include "fetchparams.h"
#include "ui_interface.h"
#include "util.h"

#include <stdio.h>
#include <curl/curl.h>
#include <curl/easy.h>
#include <openssl/sha.h>

#include <sstream>
#include <string>

#include <boost/filesystem.hpp>

bool LTZ_VerifyParams(std::string file, std::string sha256expected)
{
    std::string msg = "Verifying " + file + "...";
    LogPrintf("%s\n", msg.c_str());

    FILE *fp = fopen(file.c_str(), "rb");
    if(!fp) {
        msg = "Can not open " + file + "!";
        LogPrintf("%s\n", msg.c_str());
    }

    unsigned char buffer[BUFSIZ];
    unsigned char hash[SHA256_DIGEST_LENGTH];

    int len = 0;
    int bytesRead = 0;

    boost::filesystem::path p(file);
    std::string initMsg = "Verifying " + p.filename().string() + "...";
    uiInterface.InitMessage(_(initMsg.c_str()));

    SHA256_CTX ctx;
    SHA256_Init(&ctx);

    while((bytesRead = fread(buffer, 1, BUFSIZ, fp)))
    {
        SHA256_Update(&ctx, buffer, bytesRead);
    }
    SHA256_Final(hash, &ctx);

    fclose(fp);

    std::ostringstream oss;
    for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
        oss << strprintf("%02x", hash[i]);

    LogPrintf("SHA256SUM: %s\n", oss.str());

    if (!(sha256expected.compare(oss.str()) == 0))
    {
        msg = "Deleting corrupted file " + file + "!";
        LogPrintf("%s\n", msg.c_str());
        initMsg = "Deleting corrupted file " + p.filename().string() + "!";
        uiInterface.InitMessage(_(initMsg.c_str()));
        boost::filesystem::remove(file.c_str());
        return false;
    }

    return true;
}

bool LTZ_FetchParams(std::string url, std::string file)
{
    CURL *curl;
    FILE *fp;
    CURLcode res;

    std::string msg = "Downloading " + url + "...";
    LogPrintf("%s\n", msg.c_str());

    boost::filesystem::path p(file);
    std::string initMsg = "Downloading " + p.filename().string() + "...";

    uiInterface.InitMessage(_(initMsg.c_str()));

    curl = curl_easy_init();
    if (curl)
    {
        fp = fopen(file.c_str(), "wb");
        if (fp)
        {
            curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
            curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
            curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);

            CURLcode res = curl_easy_perform(curl);
            fclose(fp);

            std::ostringstream oss;
            oss << "CURL Return code: " << curl_easy_strerror(res) << std::endl;
            LogPrintf("%s", oss.str());

            if (res != CURLE_OK)
                return false;
        }
    }
    curl_easy_cleanup(curl);

    return true;
}
<commit_msg>Display download percentage while downloading params files<commit_after>// Copyright (c) 2017-2018 The LitecoinZ developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifdef WIN32
#define CURL_STATICLIB
#endif

#include "fetchparams.h"
#include "ui_interface.h"
#include "util.h"

#include <stdio.h>
#include <curl/curl.h>
#include <openssl/sha.h>

#include <sstream>
#include <string>

#include <boost/filesystem.hpp>

std::string filename = "";

void printInfo(std::string msg)
{
    std::string info = msg + " " + filename + "...";
    LogPrintf("%s\n", info.c_str());
    uiInterface.InitMessage(_(info.c_str()));
}

bool LTZ_VerifyParams(std::string file, std::string sha256expected)
{
    printInfo("Verifying");

    FILE *fp = fopen(file.c_str(), "rb");
    if(!fp) {
        std::string msg = "Can not open " + file + "!";
        LogPrintf("%s\n", msg.c_str());
    }

    unsigned char buffer[BUFSIZ];
    unsigned char hash[SHA256_DIGEST_LENGTH];

    int len = 0;
    int bytesRead = 0;

    SHA256_CTX ctx;
    SHA256_Init(&ctx);

    while((bytesRead = fread(buffer, 1, BUFSIZ, fp)))
    {
        SHA256_Update(&ctx, buffer, bytesRead);
    }
    SHA256_Final(hash, &ctx);

    fclose(fp);

    std::ostringstream oss;
    for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
        oss << strprintf("%02x", hash[i]);

    LogPrintf("SHA256SUM: %s\n", oss.str());

    if (!(sha256expected.compare(oss.str()) == 0))
    {
        printInfo("Deleting corrupted file");
        boost::filesystem::remove(file.c_str());
        return false;
    }

    return true;
}

static int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
    int perc = 0;
    if ((double)dlnow > 0)
        perc = (double)dlnow * 100 / (double)dltotal;

    std::string initMsg = "Downloading " + filename + " (" + std::to_string(perc) + "%)...";
    uiInterface.InitMessage(_(initMsg.c_str()));

    return 0;
}

bool LTZ_FetchParams(std::string url, std::string file)
{
    CURL *curl;
    CURLcode res = CURLE_OK;

    FILE *fp;

    std::string msg = "Downloading " + url + "...";
    LogPrintf("%s\n", msg.c_str());

    boost::filesystem::path p(file);
    filename = p.filename().string();

    curl = curl_easy_init();
    if (curl)
    {
        fp = fopen(file.c_str(), "wb");
        if (fp)
        {
            curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
            curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
            curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);

            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
            curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);

            res = curl_easy_perform(curl);
            fclose(fp);

            std::ostringstream oss;
            oss << "CURL Return code: " << curl_easy_strerror(res) << std::endl;
            LogPrintf("%s", oss.str());

            if (res != CURLE_OK)
                return false;
        }
    }
    curl_easy_cleanup(curl);

    return true;
}
<|endoftext|>


<commit_before>/*
** Author(s):
**  - Herve Cuche <hcuche@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <iostream>
#include <string>

#include <boost/program_options.hpp>

#include <qi/os.hpp>
#include "qiservicetest.hpp"

namespace po = boost::program_options;

int main(int argc, char *argv[])
{
  // declare the program options
  po::options_description desc("Usage:\n  qi-service masterAddress [options]\nOptions");
  desc.add_options()
      ("help", "Print this help.")
      ("master-address",
       po::value<std::string>()->default_value(std::string("127.0.0.1:5555")),
       "The master address");

  // allow master address to be specified as the first arg
  po::positional_options_description pos;
  pos.add("master-address", 1);

  // parse and store
  po::variables_map vm;
  try
  {
    po::store(po::command_line_parser(argc, argv).
              options(desc).positional(pos).run(), vm);
    po::notify(vm);

    if (vm.count("help"))
    {
      std::cout << desc << "\n";
      return 0;
    }

    if (vm.count("master-address") == 1)
    {
      qi::Session       session;
      qi::ServiceTest       st;

      st.start("127.0.0.1:9571");
      std::cout << "ready." << std::endl;

      qi::EndpointInfo e;
      e.ip = "127.0.0.1";
      e.port = 9571;
      e.type = "tcp";

      std::string masterAddress = vm["master-address"].as<std::string>();

      session.setName("serviceTest");
      session.setDestination("qi.master");
      session.connect(masterAddress);
      session.waitForConnected();
      session.registerEndpoint(e);

      while (1)
        qi::os::sleep(1);

      session.unregisterEndpoint(e);
    }
    else
    {
      std::cout << desc << "\n";
    }
  }
  catch (const boost::program_options::error&)
  {
    std::cout << desc << "\n";
  }

  return 0;
}
<commit_msg>qiservicetest: use new qi::Object<commit_after>/*
** Author(s):
**  - Herve Cuche <hcuche@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <iostream>
#include <string>

#include <boost/program_options.hpp>

#include <qi/os.hpp>
#include <qimessaging/session.hpp>
#include <qimessaging/server.hpp>
#include <qimessaging/object.hpp>

//#include "qiservicetest.hpp"

std::string reply(const std::string &msg) {
  return msg + "bim";
}

namespace po = boost::program_options;

int main(int argc, char *argv[])
{
  // declare the program options
  po::options_description desc("Usage:\n  qi-service masterAddress [options]\nOptions");
  desc.add_options()
      ("help", "Print this help.")
      ("master-address",
       po::value<std::string>()->default_value(std::string("127.0.0.1:5555")),
       "The master address");

  // allow master address to be specified as the first arg
  po::positional_options_description pos;
  pos.add("master-address", 1);

  // parse and store
  po::variables_map vm;
  try
  {
    po::store(po::command_line_parser(argc, argv).
              options(desc).positional(pos).run(), vm);
    po::notify(vm);

    if (vm.count("help"))
    {
      std::cout << desc << "\n";
      return 0;
    }

    if (vm.count("master-address") == 1)
    {
      qi::Session       session;
      qi::Object        obj;
      qi::Server        srv;
      obj.advertiseMethod("reply", &reply);

      srv.advertiseService("serviceTest", &obj);
      srv.start("127.0.0.1", 9571, session._nthd);

      //qi::ServiceTest       st;

      //st.start("127.0.0.1:9571");
      std::cout << "ready." << std::endl;

      qi::EndpointInfo e;
      e.ip = "127.0.0.1";
      e.port = 9571;
      e.type = "tcp";

      std::string masterAddress = vm["master-address"].as<std::string>();

      session.setName("serviceTest");
      session.setDestination("qi.master");
      session.connect(masterAddress);
      session.waitForConnected();
      session.registerEndpoint(e);

      while (1)
        qi::os::sleep(1);

      session.unregisterEndpoint(e);
    }
    else
    {
      std::cout << desc << "\n";
    }
  }
  catch (const boost::program_options::error&)
  {
    std::cout << desc << "\n";
  }

  return 0;
}
<|endoftext|>