text:
#include <iostream>

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string/join.hpp>

#include "server/server_setting.hpp"

using namespace boost;

namespace pgl {

	bool server_setting::load_from_setting_file(const std::filesystem::path& file_path) {
		if (!exists(file_path)) {
			std::cerr << "Failed to load a server setting file (" << file_path << ")." << std::endl;
			return false;
		}

		property_tree::ptree ptree;
		read_json(file_path.string(), ptree);
		enable_session_key_check = ptree.get("enable_session_key_check", enable_session_key_check);
		time_out_seconds = ptree.get("time_out_seconds", time_out_seconds);
		connection_check_time_out_seconds = ptree.get("connection_check_time_out_seconds",
			connection_check_time_out_seconds);
		const auto ip_version_str = ptree.get("ip_version", std::string(nameof::nameof_enum(ip_version)));
		try { ip_version = string_to_ip_version(ip_version_str); }
		catch (const std::out_of_range&) { std::cerr << ip_version_str << " is invalid for ip_version." << std::endl; }
		port = ptree.get("port", port);
		max_connection_per_thread = ptree.get("max_connection_per_thread", max_connection_per_thread);
		thread = ptree.get("thread", thread);
		max_room_per_room_group = ptree.get("max_room_per_room_group", max_room_per_room_group);

		const auto room_group_list_ptree = ptree.get_child_optional("room_group_list");
		if (room_group_list_ptree) {
			room_group_list.clear();
			room_group_list.reserve(room_group_list_ptree->size());
			for (auto&& child : *room_group_list_ptree) {
				room_group_list.push_back(child.second.get_value<std::string>());
			}
		}

		max_player_per_room = ptree.get("max_player_per_room", max_player_per_room);

		enable_console_log = ptree.get("enable_console_log", enable_console_log);
		const auto console_log_level_str = ptree.get("console_log_level",
			std::string(nameof::nameof_enum(console_log_level)));
		try { console_log_level = string_to_log_level(console_log_level_str); }
		catch (const std::out_of_range&) {
			std::cerr << console_log_level_str << " is invalid for log_level." << std::endl;
		}
		enable_file_log = ptree.get("enable_file_log", enable_file_log);
		const auto file_log_level_str = ptree.get("file_log_level", std::string(nameof::nameof_enum(file_log_level)));
		try { file_log_level = string_to_log_level(file_log_level_str); }
		catch (const std::out_of_range&) {
			std::cerr << file_log_level_str << " is invalid for log_level." << std::endl;
		}
		file_log_path = ptree.get("file_log_path", file_log_path);

		return true;
	}

	void server_setting::output_to_log() const {
		log(log_level::info, "================Server Setting================");
		log(log_level::info, NAMEOF(enable_session_key_check), ": ", enable_session_key_check);
		log(log_level::info, NAMEOF(time_out_seconds), ": ", time_out_seconds);
		log(log_level::info, NAMEOF(connection_check_time_out_seconds), ": ", connection_check_time_out_seconds);
		log(log_level::info, NAMEOF(ip_version), ": ", ip_version);
		log(log_level::info, NAMEOF(port), ": ", port);
		log(log_level::info, NAMEOF(max_connection_per_thread), ": ", max_connection_per_thread);
		log(log_level::info, NAMEOF(thread), ": ", thread);
		log(log_level::info, NAMEOF(max_room_per_room_group), ": ", max_room_per_room_group);
		log(log_level::info, NAMEOF(room_group_list), ": ", room_group_list.size(), "(", join(room_group_list, ","),
			")");
		log(log_level::info, NAMEOF(max_player_per_room), ": ", max_player_per_room);
		log(log_level::info, NAMEOF(enable_console_log), ": ", enable_console_log);
		log(log_level::info, NAMEOF(console_log_level), ": ", console_log_level);
		log(log_level::info, NAMEOF(enable_file_log), ": ", enable_file_log);
		log(log_level::info, NAMEOF(file_log_level), ": ", file_log_level);
		log(log_level::info, NAMEOF(file_log_path), ": ", file_log_path);
		log(log_level::info, "==============================================");
	}
}

max_stars_repo_name: InstytutXR/PlanetaMatchMaker

max_issues_repo_name: InstytutXR/PlanetaMatchMaker

max_forks_repo_name: InstytutXR/PlanetaMatchMaker


text:
/*=============================================================================
    Copyright (c) 2001-2014 Joel de Guzman

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#if !defined(BOOST_SPIRIT_X3_CHAR_FEBRUARY_02_2007_0921AM)
#define BOOST_SPIRIT_X3_CHAR_FEBRUARY_02_2007_0921AM

#include <boost/spirit/home/x3/char/char.hpp>
#include <boost/spirit/home/x3/char/char_class.hpp>
#include <boost/spirit/home/x3/char/char_parser.hpp>
#include <boost/spirit/home/x3/char/char_set.hpp>
#include <boost/spirit/home/x3/char/negated_char_parser.hpp>

#if defined(BOOST_SPIRIT_X3_UNICODE)
#include <boost/spirit/home/x3/char/unicode.hpp>
#endif

#endif

ext: hpp

max_stars_repo_name: henrywarhurst/matrix

max_issues_repo_name: henrywarhurst/matrix

max_forks_repo_name: henrywarhurst/matrix


text:
/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you 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 <gtest/gtest.h>
#include <boost/date_time.hpp>
#include <boost/algorithm/string.hpp>
#include <cetty/handler/codec/http/Cookie.h>
#include <cetty/handler/codec/http/CookieDecoder.h>
#include <cetty/handler/codec/http/HttpHeaderDateFormat.h>

using namespace boost::posix_time;
using namespace cetty::handler::codec::http;

TEST(CookieDecoderTest, testDecodingSingleCookieV0) {
    std::string cookieString = "myCookie=myValue;expires=XXX;path=/apathsomewhere;domain=.adomainsomewhere;secure;";

    ptime time = microsec_clock::universal_time() + milliseconds(50000);
    boost::replace_all(cookieString, "XXX", HttpHeaderDateFormat::defaultFormat.format(time));

    std::vector<Cookie> cookies;
    CookieDecoder::decode(cookieString, &cookies);

    ASSERT_EQ(1, cookies.size());
    const Cookie& cookie = cookies.front();

    ASSERT_TRUE(!cookie.getName().empty());
    ASSERT_STREQ("myValue", cookie.getValue().c_str());

    ASSERT_TRUE(cookie.getComment().empty());
    ASSERT_TRUE(cookie.getCommentUrl().empty());
    ASSERT_STREQ(".adomainsomewhere", cookie.getDomain().c_str());
    ASSERT_FALSE(cookie.isDiscard());

    bool fail = true;

    for (int i = 40; i <= 60; i ++) {
        if (cookie.getMaxAge() == i) {
            fail = false;
            break;
        }
    }

    if (fail) {
        FAIL("expected: 50, actual: " + cookie.getMaxAge());
    }

    ASSERT_STREQ("/apathsomewhere", cookie.getPath().c_str());
    ASSERT_TRUE(cookie.getPorts().empty());
    ASSERT_TRUE(cookie.isSecure());
    ASSERT_EQ(0, cookie.getVersion());
}

TEST(CookieDecoderTest, testDecodingSingleCookieV0ExtraParamsIgnored) {
    String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=0;commentURL=http://aurl.com;port=\"80,8080\";discard;";
    Set<Cookie> cookies = CookieDecoder.decode(cookieString);
    assertEquals(1, cookies.size());
    Cookie cookie = cookies.iterator().next();
    assertNotNull(cookie);
    assertEquals("myValue", cookie.getValue());
    assertNull(cookie.getComment());
    assertNull(cookie.getCommentUrl());
    assertEquals(".adomainsomewhere", cookie.getDomain());
    assertFalse(cookie.isDiscard());
    assertEquals(50, cookie.getMaxAge());
    assertEquals("/apathsomewhere", cookie.getPath());
    assertTrue(cookie.getPorts().isEmpty());
    assertTrue(cookie.isSecure());
    assertEquals(0, cookie.getVersion());
}

TEST(CookieDecoderTest,testDecodingSingleCookieV1) {
    String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=1;";
    Set<Cookie> cookies = CookieDecoder.decode(cookieString);
    assertEquals(1, cookies.size());
    Cookie cookie = cookies.iterator().next();
    assertEquals("myValue", cookie.getValue());
    assertNotNull(cookie);
    assertEquals("this is a comment", cookie.getComment());
    assertNull(cookie.getCommentUrl());
    assertEquals(".adomainsomewhere", cookie.getDomain());
    assertFalse(cookie.isDiscard());
    assertEquals(50, cookie.getMaxAge());
    assertEquals("/apathsomewhere", cookie.getPath());
    assertTrue(cookie.getPorts().isEmpty());
    assertTrue(cookie.isSecure());
    assertEquals(1, cookie.getVersion());
}

TEST(CookieDecoderTest, testDecodingSingleCookieV1ExtraParamsIgnored) {
    String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=1;commentURL=http://aurl.com;port='80,8080';discard;";
    Set<Cookie> cookies = CookieDecoder.decode(cookieString);
    assertEquals(1, cookies.size());
    Cookie cookie = cookies.iterator().next();
    assertNotNull(cookie);
    assertEquals("myValue", cookie.getValue());
    assertEquals("this is a comment", cookie.getComment());
    assertNull(cookie.getCommentUrl());
    assertEquals(".adomainsomewhere", cookie.getDomain());
    assertFalse(cookie.isDiscard());
    assertEquals(50, cookie.getMaxAge());
    assertEquals("/apathsomewhere", cookie.getPath());
    assertTrue(cookie.getPorts().isEmpty());
    assertTrue(cookie.isSecure());
    assertEquals(1, cookie.getVersion());
}

TEST(CookieDecoderTest,testDecodingSingleCookieV2) {
    String cookieString = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=2;commentURL=http://aurl.com;port=\"80,8080\";discard;";
    Set<Cookie> cookies = CookieDecoder.decode(cookieString);
    assertEquals(1, cookies.size());
    Cookie cookie = cookies.iterator().next();
    assertNotNull(cookie);
    assertEquals("myValue", cookie.getValue());
    assertEquals("this is a comment", cookie.getComment());
    assertEquals("http://aurl.com", cookie.getCommentUrl());
    assertEquals(".adomainsomewhere", cookie.getDomain());
    assertTrue(cookie.isDiscard());
    assertEquals(50, cookie.getMaxAge());
    assertEquals("/apathsomewhere", cookie.getPath());
    assertEquals(2, cookie.getPorts().size());
    assertTrue(cookie.getPorts().contains(80));
    assertTrue(cookie.getPorts().contains(8080));
    assertTrue(cookie.isSecure());
    assertEquals(2, cookie.getVersion());
}

TEST(CookieDecoderTest, testDecodingMultipleCookies) {
    String c1 = "myCookie=myValue;max-age=50;path=/apathsomewhere;domain=.adomainsomewhere;secure;comment=this is a comment;version=2;commentURL=\"http://aurl.com\";port='80,8080';discard;";
    String c2 = "myCookie2=myValue2;max-age=0;path=/anotherpathsomewhere;domain=.anotherdomainsomewhere;comment=this is another comment;version=2;commentURL=http://anotherurl.com;";
    String c3 = "myCookie3=myValue3;max-age=0;version=2;";

    Set<Cookie> cookies = CookieDecoder.decode(c1 + c2 + c3);
    assertEquals(3, cookies.size());
    Iterator<Cookie> it = cookies.iterator();
    Cookie cookie = it.next();
    assertNotNull(cookie);
    assertEquals("myValue", cookie.getValue());
    assertEquals("this is a comment", cookie.getComment());
    assertEquals("http://aurl.com", cookie.getCommentUrl());
    assertEquals(".adomainsomewhere", cookie.getDomain());
    assertTrue(cookie.isDiscard());
    assertEquals(50, cookie.getMaxAge());
    assertEquals("/apathsomewhere", cookie.getPath());
    assertEquals(2, cookie.getPorts().size());
    assertTrue(cookie.getPorts().contains(80));
    assertTrue(cookie.getPorts().contains(8080));
    assertTrue(cookie.isSecure());
    assertEquals(2, cookie.getVersion());
    cookie = it.next();
    assertNotNull(cookie);
    assertEquals("myValue2", cookie.getValue());
    assertEquals("this is another comment", cookie.getComment());
    assertEquals("http://anotherurl.com", cookie.getCommentUrl());
    assertEquals(".anotherdomainsomewhere", cookie.getDomain());
    assertFalse(cookie.isDiscard());
    assertEquals(0, cookie.getMaxAge());
    assertEquals("/anotherpathsomewhere", cookie.getPath());
    assertTrue(cookie.getPorts().isEmpty());
    assertFalse(cookie.isSecure());
    assertEquals(2, cookie.getVersion());
    cookie = it.next();
    assertNotNull(cookie);
    assertEquals("myValue3", cookie.getValue());
    assertNull(cookie.getComment());
    assertNull(cookie.getCommentUrl());
    assertNull(cookie.getDomain());
    assertFalse(cookie.isDiscard());
    assertEquals(0, cookie.getMaxAge());
    assertNull(cookie.getPath());
    assertTrue(cookie.getPorts().isEmpty());
    assertFalse(cookie.isSecure());
    assertEquals(2, cookie.getVersion());
}

TEST(CookieDecoderTest, testDecodingClientSideCookies) {
    String source = "$Version=\"1\"; " +
                    "Part_Number=\"Riding_Rocket_0023\"; $Path=\"/acme/ammo\"; " +
                    "Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"";

    Set<Cookie> cookies = CookieDecoder.decode(source);
    Iterator<Cookie> it = cookies.iterator();
    Cookie c;

    c = it.next();
    assertEquals(1, c.getVersion());
    assertEquals("Part_Number", c.getName());
    assertEquals("Rocket_Launcher_0001", c.getValue());
    assertEquals("/acme", c.getPath());
    assertNull(c.getComment());
    assertNull(c.getCommentUrl());
    assertNull(c.getDomain());
    assertTrue(c.getPorts().isEmpty());
    assertEquals(Long.MIN_VALUE, c.getMaxAge());

    c = it.next();
    assertEquals(1, c.getVersion());
    assertEquals("Part_Number", c.getName());
    assertEquals("Riding_Rocket_0023", c.getValue());
    assertEquals("/acme/ammo", c.getPath());
    assertNull(c.getComment());
    assertNull(c.getCommentUrl());
    assertNull(c.getDomain());
    assertTrue(c.getPorts().isEmpty());
    assertEquals(Long.MIN_VALUE, c.getMaxAge());

    assertFalse(it.hasNext());
}

TEST(CookieDecoderTest, testDecodingCommaSeparatedClientSideCookies) {
    String source =
        "$Version=\"1\"; session_id=\"1234\", " +
        "$Version=\"1\"; session_id=\"1111\"; $Domain=\".cracker.edu\"";

    Set<Cookie> cookies = CookieDecoder.decode(source);
    Iterator<Cookie> it = cookies.iterator();
    Cookie c;

    assertTrue(it.hasNext());
    c = it.next();
    assertEquals(1, c.getVersion());
    assertEquals("session_id", c.getName());
    assertEquals("1234", c.getValue());
    assertNull(c.getPath());
    assertNull(c.getComment());
    assertNull(c.getCommentUrl());
    assertNull(c.getDomain());
    assertTrue(c.getPorts().isEmpty());
    assertEquals(Long.MIN_VALUE, c.getMaxAge());

    assertTrue(it.hasNext());
    c = it.next();
    assertEquals(1, c.getVersion());
    assertEquals("session_id", c.getName());
    assertEquals("1111", c.getValue());
    assertEquals(".cracker.edu", c.getDomain());
    assertNull(c.getPath());
    assertNull(c.getComment());
    assertNull(c.getCommentUrl());
    assertTrue(c.getPorts().isEmpty());
    assertEquals(Long.MIN_VALUE, c.getMaxAge());

    assertFalse(it.hasNext());
}

TEST(CookieDecoderTest, testDecodingQuotedCookie) {
    String source =
        "a=\"\"," +
        "b=\"1\"," +
        "c=\"\\\"1\\\"2\\\"\"," +
        "d=\"1\\\"2\\\"3\"," +
        "e=\"\\\"\\\"\"," +
        "f=\"1\\\"\\\"2\"," +
        "g=\"\\\\\"," +
        "h=\"';,\\x\"";

    Set<Cookie> cookies = CookieDecoder.decode(source);
    Iterator<Cookie> it = cookies.iterator();
    Cookie c;

    c = it.next();
    assertEquals("a", c.getName());
    assertEquals("", c.getValue());

    c = it.next();
    assertEquals("b", c.getName());
    assertEquals("1", c.getValue());

    c = it.next();
    assertEquals("c", c.getName());
    assertEquals("\"1\"2\"", c.getValue());

    c = it.next();
    assertEquals("d", c.getName());
    assertEquals("1\"2\"3", c.getValue());

    c = it.next();
    assertEquals("e", c.getName());
    assertEquals("\"\"", c.getValue());

    c = it.next();
    assertEquals("f", c.getName());
    assertEquals("1\"\"2", c.getValue());

    c = it.next();
    assertEquals("g", c.getName());
    assertEquals("\\", c.getValue());

    c = it.next();
    assertEquals("h", c.getName());
    assertEquals("';,\\x", c.getValue());

    assertFalse(it.hasNext());
}

TEST(CookieDecoderTest, testDecodingGoogleAnalyticsCookie) {
    String source =
        "ARPT=LWUKQPSWRTUN04CKKJI; " +
        "kw-2E343B92-B097-442c-BFA5-BE371E0325A2=unfinished furniture; " +
        "__utma=48461872.1094088325.1258140131.1258140131.1258140131.1; " +
        "__utmb=48461872.13.10.1258140131; __utmc=48461872; " +
        "__utmz=48461872.1258140131.1.1.utmcsr=overstock.com|utmccn=(referral)|utmcmd=referral|utmcct=/Home-Garden/Furniture/Clearance,/clearance,/32/dept.html";
    Set<Cookie> cookies = CookieDecoder.decode(source);
    Iterator<Cookie> it = cookies.iterator();
    Cookie c;

    c = it.next();
    assertEquals("__utma", c.getName());
    assertEquals("48461872.1094088325.1258140131.1258140131.1258140131.1", c.getValue());

    c = it.next();
    assertEquals("__utmb", c.getName());
    assertEquals("48461872.13.10.1258140131", c.getValue());

    c = it.next();
    assertEquals("__utmc", c.getName());
    assertEquals("48461872", c.getValue());

    c = it.next();
    assertEquals("__utmz", c.getName());
    assertEquals("48461872.1258140131.1.1.utmcsr=overstock.com|utmccn=(referral)|utmcmd=referral|utmcct=/Home-Garden/Furniture/Clearance,/clearance,/32/dept.html", c.getValue());

    c = it.next();
    assertEquals("ARPT", c.getName());
    assertEquals("LWUKQPSWRTUN04CKKJI", c.getValue());

    c = it.next();
    assertEquals("kw-2E343B92-B097-442c-BFA5-BE371E0325A2", c.getName());
    assertEquals("unfinished furniture", c.getValue());

    assertFalse(it.hasNext());
}

TEST(CookieDecoderTest, testDecodingLongDates) {
    Calendar cookieDate = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    cookieDate.set(9999, Calendar.DECEMBER, 31, 23, 59, 59);
    long expectedMaxAge = (cookieDate.getTimeInMillis() - System.currentTimeMillis()) / 1000;

    String source = "Format=EU; expires=Fri, 31-Dec-9999 23:59:59 GMT; path=/";

    Set<Cookie> cookies = CookieDecoder.decode(source);

    Cookie c = cookies.iterator().next();
    assertTrue(Math.abs(expectedMaxAge - c.getMaxAge()) < 2);
}

TEST(CookieDecoderTest, testDecodingValueWithComma) {
    String source = "UserCookie=timeZoneName=(GMT+04:00) Moscow, St. Petersburg, Volgograd&promocode=&region=BE;" +
                    " expires=Sat, 01-Dec-2012 10:53:31 GMT; path=/";

    Set<Cookie> cookies = CookieDecoder.decode(source);

    Cookie c = cookies.iterator().next();
    assertEquals("timeZoneName=(GMT+04:00) Moscow, St. Petersburg, Volgograd&promocode=&region=BE", c.getValue());
}

TEST(CookieDecoderTest, testDecodingWeirdNames1) {
    String src = "path=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com";
    Set<Cookie> cookies = CookieDecoder.decode(src);
    Cookie c = cookies.iterator().next();
    assertEquals("path", c.getName());
    assertEquals("", c.getValue());
    assertEquals("/", c.getPath());
}

TEST(CookieDecoderTest, testDecodingWeirdNames2) {
    String src = "HTTPOnly=";
    Set<Cookie> cookies = CookieDecoder.decode(src);
    Cookie c = cookies.iterator().next();
    assertEquals("HTTPOnly", c.getName());
    assertEquals("", c.getValue());
}

TEST(CookieDecoderTest, testDecodingValuesWithCommasAndEquals) {
    String src = "A=v=1&lg=en-US,it-IT,it&intl=it&np=1;T=z=E";
    Set<Cookie> cookies = CookieDecoder.decode(src);
    Iterator<Cookie> i = cookies.iterator();
    Cookie c = i.next();
    assertEquals("A", c.getName());
    assertEquals("v=1&lg=en-US,it-IT,it&intl=it&np=1", c.getValue());
    c = i.next();
    assertEquals("T", c.getName());
    assertEquals("z=E", c.getValue());
}

TEST(CookieDecoderTest, testDecodingLongValue) {
    std::string longValue =
        "b!!!$Q!!$ha!!<NC=MN(F!!%#4!!<NC=MN(F!!2!d!!!!#=IvZB!!2,F!!!!'=KqtH!!2-9!!!!"
        "'=IvZM!!3f:!!!!$=HbQW!!3g'!!!!%=J^wI!!3g-!!!!%=J^wI!!3g1!!!!$=HbQW!!3g2!!!!"
        "$=HbQW!!3g5!!!!%=J^wI!!3g9!!!!$=HbQW!!3gT!!!!$=HbQW!!3gX!!!!#=J^wI!!3gY!!!!"
        "#=J^wI!!3gh!!!!$=HbQW!!3gj!!!!$=HbQW!!3gr!!!!$=HbQW!!3gx!!!!#=J^wI!!3h!!!!!"
        "$=HbQW!!3h$!!!!#=J^wI!!3h'!!!!$=HbQW!!3h,!!!!$=HbQW!!3h0!!!!%=J^wI!!3h1!!!!"
        "#=J^wI!!3h2!!!!$=HbQW!!3h4!!!!$=HbQW!!3h7!!!!$=HbQW!!3h8!!!!%=J^wI!!3h:!!!!"
        "#=J^wI!!3h@!!!!%=J^wI!!3hB!!!!$=HbQW!!3hC!!!!$=HbQW!!3hL!!!!$=HbQW!!3hQ!!!!"
        "$=HbQW!!3hS!!!!%=J^wI!!3hU!!!!$=HbQW!!3h[!!!!$=HbQW!!3h^!!!!$=HbQW!!3hd!!!!"
        "%=J^wI!!3he!!!!%=J^wI!!3hf!!!!%=J^wI!!3hg!!!!$=HbQW!!3hh!!!!%=J^wI!!3hi!!!!"
        "%=J^wI!!3hv!!!!$=HbQW!!3i/!!!!#=J^wI!!3i2!!!!#=J^wI!!3i3!!!!%=J^wI!!3i4!!!!"
        "$=HbQW!!3i7!!!!$=HbQW!!3i8!!!!$=HbQW!!3i9!!!!%=J^wI!!3i=!!!!#=J^wI!!3i>!!!!"
        "%=J^wI!!3iD!!!!$=HbQW!!3iF!!!!#=J^wI!!3iH!!!!%=J^wI!!3iM!!!!%=J^wI!!3iS!!!!"
        "#=J^wI!!3iU!!!!%=J^wI!!3iZ!!!!#=J^wI!!3i]!!!!%=J^wI!!3ig!!!!%=J^wI!!3ij!!!!"
        "%=J^wI!!3ik!!!!#=J^wI!!3il!!!!$=HbQW!!3in!!!!%=J^wI!!3ip!!!!$=HbQW!!3iq!!!!"
        "$=HbQW!!3it!!!!%=J^wI!!3ix!!!!#=J^wI!!3j!!!!!$=HbQW!!3j%!!!!$=HbQW!!3j'!!!!"
        "%=J^wI!!3j(!!!!%=J^wI!!9mJ!!!!'=KqtH!!=SE!!<NC=MN(F!!?VS!!<NC=MN(F!!Zw`!!!!"
        "%=KqtH!!j+C!!<NC=MN(F!!j+M!!<NC=MN(F!!j+a!!<NC=MN(F!!j,.!!<NC=MN(F!!n>M!!!!"
        "'=KqtH!!s1X!!!!$=MMyc!!s1_!!!!#=MN#O!!ypn!!!!'=KqtH!!ypr!!!!'=KqtH!#%h!!!!!"
        "%=KqtH!#%o!!!!!'=KqtH!#)H6!!<NC=MN(F!#*%'!!!!%=KqtH!#+k(!!!!'=KqtH!#-E!!!!!"
        "'=KqtH!#1)w!!!!'=KqtH!#1)y!!!!'=KqtH!#1*M!!!!#=KqtH!#1*p!!!!'=KqtH!#14Q!!<N"
        "C=MN(F!#14S!!<NC=MN(F!#16I!!<NC=MN(F!#16N!!<NC=MN(F!#16X!!<NC=MN(F!#16k!!<N"
        "C=MN(F!#17@!!<NC=MN(F!#17A!!<NC=MN(F!#1Cq!!!!'=KqtH!#7),!!!!#=KqtH!#7)b!!!!"
        "#=KqtH!#7Ww!!!!'=KqtH!#?cQ!!!!'=KqtH!#His!!!!'=KqtH!#Jrh!!!!'=KqtH!#O@M!!<N"
        "C=MN(F!#O@O!!<NC=MN(F!#OC6!!<NC=MN(F!#Os.!!!!#=KqtH!#YOW!!!!#=H/Li!#Zat!!!!"
        "'=KqtH!#ZbI!!!!%=KqtH!#Zbc!!!!'=KqtH!#Zbs!!!!%=KqtH!#Zby!!!!'=KqtH!#Zce!!!!"
        "'=KqtH!#Zdc!!!!%=KqtH!#Zea!!!!'=KqtH!#ZhI!!!!#=KqtH!#ZiD!!!!'=KqtH!#Zis!!!!"
        "'=KqtH!#Zj0!!!!#=KqtH!#Zj1!!!!'=KqtH!#Zj[!!!!'=KqtH!#Zj]!!!!'=KqtH!#Zj^!!!!"
        "'=KqtH!#Zjb!!!!'=KqtH!#Zk!!!!!'=KqtH!#Zk6!!!!#=KqtH!#Zk9!!!!%=KqtH!#Zk<!!!!"
        "'=KqtH!#Zl>!!!!'=KqtH!#]9R!!!!$=H/Lt!#]I6!!!!#=KqtH!#]Z#!!!!%=KqtH!#^*N!!!!"
        "#=KqtH!#^:m!!!!#=KqtH!#_*_!!!!%=J^wI!#`-7!!!!#=KqtH!#`T>!!!!'=KqtH!#`T?!!!!"
        "'=KqtH!#`TA!!!!'=KqtH!#`TB!!!!'=KqtH!#`TG!!!!'=KqtH!#`TP!!!!#=KqtH!#`U,!!!!"
        "'=KqtH!#`U/!!!!'=KqtH!#`U0!!!!#=KqtH!#`U9!!!!'=KqtH!#aEQ!!!!%=KqtH!#b<)!!!!"
        "'=KqtH!#c9-!!!!%=KqtH!#dxC!!!!%=KqtH!#dxE!!!!%=KqtH!#ev$!!!!'=KqtH!#fBi!!!!"
        "#=KqtH!#fBj!!!!'=KqtH!#fG)!!!!'=KqtH!#fG+!!!!'=KqtH!#g<d!!!!'=KqtH!#g<e!!!!"
        "'=KqtH!#g=J!!!!'=KqtH!#gat!!!!#=KqtH!#s`D!!!!#=J_#p!#sg?!!!!#=J_#p!#t<a!!!!"
        "#=KqtH!#t<c!!!!#=KqtH!#trY!!!!$=JiYj!#vA$!!!!'=KqtH!#xs_!!!!'=KqtH!$$rO!!!!"
        "#=KqtH!$$rP!!!!#=KqtH!$(!%!!!!'=KqtH!$)]o!!!!%=KqtH!$,@)!!!!'=KqtH!$,k]!!!!"
        "'=KqtH!$1]+!!!!%=KqtH!$3IO!!!!%=KqtH!$3J#!!!!'=KqtH!$3J.!!!!'=KqtH!$3J:!!!!"
        "#=KqtH!$3JH!!!!#=KqtH!$3JI!!!!#=KqtH!$3JK!!!!%=KqtH!$3JL!!!!'=KqtH!$3JS!!!!"
        "'=KqtH!$8+M!!!!#=KqtH!$99d!!!!%=KqtH!$:Lw!!!!#=LK+x!$:N@!!!!#=KqtG!$:NC!!!!"
        "#=KqtG!$:hW!!!!'=KqtH!$:i[!!!!'=KqtH!$:ih!!!!'=KqtH!$:it!!!!'=KqtH!$:kO!!!!"
        "'=KqtH!$>*B!!!!'=KqtH!$>hD!!!!+=J^x0!$?lW!!!!'=KqtH!$?ll!!!!'=KqtH!$?lm!!!!"
        "%=KqtH!$?mi!!!!'=KqtH!$?mx!!!!'=KqtH!$D7]!!!!#=J_#p!$D@T!!!!#=J_#p!$V<g!!!!"
        "'=KqtH";

    std::vector<Cookie> cookies;

    std::string str("bh=\"");
    str += longValue;
    str += "\";";
    CookieDecoder::decode(str, &cookies);

    ASSERT_EQ(1, cookies.size());
    const Cookie& c = cookies.front();

    ASSERT_STREQ("bh", c.getName().c_str());
    ASSERT_STREQ(longValue.c_str(), c.getValue().c_str());
}

ext: cpp


text:
#ifndef CHILDREN_HANDLER_HPP_INCLUDED
#define CHILDREN_HANDLER_HPP_INCLUDED

/**
 * Spawn children processes, and associate an object with each child PID.
 *
 * Use boost asio and a signal handler to manage the lifetime of the children
 * and properly wait() for them.
 *
 * Instantiate a communication channel with nanomsg IPC (man nn_ipc)
 */

#include <slave/child_game.hpp>

#include <boost/asio.hpp>

#include <unistd.h>

#include <memory>
#include <map>

class Slave;

class ChildrenHandler
{
public:
  ChildrenHandler(Slave*);
  ~ChildrenHandler() = default;
  void start_subprocess(const uint64_t game_id);
  std::size_t size() const;

private:
  Slave* slave;
  void install_signal_handler();
  void on_child_exit();
  boost::asio::signal_set signal_set;

  std::map<pid_t, std::unique_ptr<ChildGame>> children;

  ChildrenHandler(const ChildrenHandler&) = delete;
  ChildrenHandler(ChildrenHandler&&) = delete;
  ChildrenHandler& operator=(const ChildrenHandler&) = delete;
  ChildrenHandler& operator=(ChildrenHandler&&) = delete;
};

#endif /* CHILDREN_HANDLER_HPP_INCLUDED */

max_stars_repo_name: louiz/batajelo

max_issues_repo_name: louiz/batajelo

max_forks_repo_name: louiz/batajelo


text:
#include <boost/asio/compose.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/use_future.hpp>
#include <boost/asio/write.hpp>
#include <functional>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>

// The return type of the initiating function is deduced from the combination of
// CompletionToken type and the completion handle's signature. When the
// completion token is a simple callback, the return type is void. However, when
// the completion token is boost::asio::yield_context (use for stackful
// coroutines) the return type would be also be void, as there is no non-error
// argument to the completion handler. When the completion token is
// boost::asio::use_future it would be std::future<void>.
template <typename T, typename CompletionToken>
auto async_write_message(boost::asio::ip::tcp::socket &socket, const T &message,
                         std::size_t repeat_count, CompletionToken &&token) {
  // Encoded the message and copy it into an allocated buffer. The buffer
  // will be maintained for the lifetime of the asynchornous operation.
  std::ostringstream os;
  os << message;
  std::unique_ptr<std::string> encoded_message =
      std::make_unique<std::string>(os.str());

  // Create a steady_timer to be used for the delay between messages.
  std::unique_ptr<boost::asio::steady_timer> delay_timer =
      std::make_unique<boost::asio::steady_timer>(socket.get_executor());

  // To manage the cycle between the multiple underlying asynchronous
  // operations, our implemention is a state machine.
  enum struct state {
    starting,
    waiting,
    writing,
  };

  // The boost::asio::async_compose function takes:
  //
  // - our asynchronous operatioon implementation,
  // - the completion token,
  // - the completion handler signature, and
  // - any I/O objects (or executors) used by the operation
  //
  // If then wraps our implementation, which is implemented here as a
  // state machine in a lambda, in an intermediate completion handler that
  // meets the requirements of a confornubg asynchronous operation. This
  // includes tracking outstanding work against the I/O executors
  // associated with the operation (in this example, this is the socket's
  // executor).
  //
  // The first argument to our lanbda is a reference to the enclosing
  // intermediate completion handler. This intermediate completion handler
  // is provided for us by the boost::asio::async_compose function, and
  // takes care of all the details required to implement a conforming
  // asynchronous operation. When calling an underlying asynchronous
  // operation, we pass it this enclosing intermediate completion handler
  // as the completino token.
  //
  // All arguments to our lambda after the first must be defaulted to
  // allow the state machine to be started, as well as to allow the
  // completion handler to match the completion signature of both the
  // async_write and steady_timer::async_wait operations.
  return boost::asio::async_compose<CompletionToken,
                                    void(boost::system::error_code)>(
      [
          // The implementation holds a referene to the socket as it is
          // used for multiple async_write operations.
          &socket,

          // The allocated buffer for the encoding message. The
          // std::unique_ptr smart pointer is move-only, and as a
          // consequence our lambda implementation is also move-only.
          encoded_message = std::move(encoded_message),

          // The repeat count remaining.
          repeat_count,

          // A steady timer used for introducing a delay.
          delay_timer = std::move(delay_timer),

          // To manage the cycle between the multiple underlying
          // asynchronous operation, our implementation is a state
          // machine.
          state = state::starting](auto &self,
                                   const boost::system::error_code &err = {},
                                   std::size_t = 0) mutable {
        if (!err) {
          switch (state) {
          case state::starting:
          case state::writing:
            if (repeat_count > 0) {
              --repeat_count;
              state = state::waiting;
              delay_timer->expires_after(std::chrono::seconds(1));
              delay_timer->async_wait(std::move(self));
              return; // Composed operation not yet complete.
            }
            break; // Composed operation complete, continue below.
          case state::waiting:
            state = state::writing;
            boost::asio::async_write(
                socket, boost::asio::buffer(*encoded_message), std::move(self));
            return; // Composed operation not yet complete.
          }
        }
        // This point is reached only on completion of the entire composed
        // operation.

        // deallocate the encoded message and delay timer before calling
        // the used-supplied completion handler .
        encoded_message.reset();
        delay_timer.reset();

        // Call the user-supplied handler with the result of the
        // operation.
        self.complete(err);
      },
      token, socket);
}

void test_callback() {
  boost::asio::io_context io_context;
  boost::asio::ip::tcp::acceptor acceptor(io_context,
                                          {boost::asio::ip::tcp::v4(), 1234});
  boost::asio::ip::tcp::socket socket = acceptor.accept();

  // Test our asynchronous operation using a lambda as a callback.
  async_write_message(socket, "Testing callback\n", 5,
                      [](const boost::system::error_code &err) {
                        if (!err) {
                          std::cout << "Message sent" << std::endl;
                        } else {
                          std::cout << "Error: " << err.message() << std::endl;
                        }
                      });
  io_context.run();
}

void test_future() {
  boost::asio::io_context io_context;
  boost::asio::ip::tcp::acceptor acceptor(io_context,
                                          {boost::asio::ip::tcp::v4(), 1234});
  boost::asio::ip::tcp::socket socket = acceptor.accept();

  // Test our asynchronous operation using the use_future completion token.
  // This token causes the operation's initiating function to return a future,
  // which may be used to synchronously wait for the result of operation.
  std::future<void> f = async_write_message(socket, "Testing future\n", 5,
                                            boost::asio::use_future);
  io_context.run();
  try {
    f.get();
    std::cout << "Message sent" << std::endl;
  } catch (const std::exception &e) {
    std::cout << "Error: " << e.what() << std::endl;
  }
}

int main() {
  test_callback();
  test_future();
  return 0;
}

max_stars_repo_name: mnrn/game-memo

max_issues_repo_name: mnrn/game-memo

max_forks_repo_name: mnrn/game-memo


text: #include <boost/fusion/sequence/intrinsic/segments.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include <TestSupport.h>
#include <Core/SpawningKit/Handshake/Prepare.h>
#include <Core/SpawningKit/Handshake/Perform.h>
#include <LoggingKit/Context.h>
#include <SystemTools/UserDatabase.h>
#include <boost/bind/bind.hpp>
#include <cstdio>
#include <IOTools/IOUtils.h>

using namespace std;
using namespace Passenger;
using namespace Passenger::SpawningKit;

namespace tut {
	struct Core_SpawningKit_HandshakePerformTest: public TestBase {
		WrapperRegistry::Registry wrapperRegistry;
		SpawningKit::Context::Schema schema;
		SpawningKit::Context context;
		SpawningKit::Config config;
		boost::shared_ptr<HandshakeSession> session;
		pid_t pid;
		Pipe stdoutAndErr;
		HandshakePerform::DebugSupport *debugSupport;
		AtomicInt counter;
		FileDescriptor server;

		Core_SpawningKit_HandshakePerformTest()
			: context(schema),
			  pid(getpid()),
			  debugSupport(NULL)
		{
			wrapperRegistry.finalize();
			context.resourceLocator = resourceLocator;
			context.wrapperRegistry = &wrapperRegistry;
			context.integrationMode = "standalone";
			context.spawnDir = getSystemTempDir();

			config.appGroupName = "appgroup";
			config.appRoot = "/tmp/myapp";
			config.startCommand = "echo hi";
			config.startupFile = "/tmp/myapp/app.py";
			config.appType = "wsgi";
			config.spawnMethod = "direct";
			config.bindAddress = "127.0.0.1";
			config.user = lookupSystemUsernameByUid(getuid());
			config.group = lookupSystemGroupnameByGid(getgid());
			config.internStrings();
		}

		~Core_SpawningKit_HandshakePerformTest() {
			Json::Value config;
			vector<ConfigKit::Error> errors;
			LoggingKit::ConfigChangeRequest req;
			config["level"] = DEFAULT_LOG_LEVEL_NAME;
			config["app_output_log_level"] = DEFAULT_APP_OUTPUT_LOG_LEVEL_NAME;

			if (LoggingKit::context->prepareConfigChange(config, errors, req)) {
				LoggingKit::context->commitConfigChange(req);
			} else {
				P_BUG("Error configuring LoggingKit: " << ConfigKit::toString(errors));
			}
		}

		void init(JourneyType type) {
			vector<StaticString> errors;
			ensure("Config is valid", config.validate(errors));

			context.finalize();

			session = boost::make_shared<HandshakeSession>(context, config, type);

			session->journey.setStepInProgress(SPAWNING_KIT_PREPARATION);
			HandshakePrepare(*session).execute().finalize();

			session->journey.setStepInProgress(SPAWNING_KIT_HANDSHAKE_PERFORM);
			session->journey.setStepInProgress(SUBPROCESS_BEFORE_FIRST_EXEC);
		}

		void execute() {
			HandshakePerform performer(*session, pid, FileDescriptor(), stdoutAndErr.first);
			performer.debugSupport = debugSupport;
			performer.execute();
			counter++;
		}

		static Json::Value createGoodPropertiesJson() {
			Json::Value socket, doc;
			socket["address"] = "tcp://127.0.0.1:3000";
			socket["protocol"] = "http";
			socket["concurrency"] = 1;
			socket["accept_http_requests"] = true;
			doc["sockets"].append(socket);
			return doc;
		}

		void signalFinish() {
			writeFile(session->responseDir + "/finish", "1");
		}

		void signalFinishWithError() {
			writeFile(session->responseDir + "/finish", "0");
		}
	};

	struct FreePortDebugSupport: public HandshakePerform::DebugSupport {
		Core_SpawningKit_HandshakePerformTest *test;
		HandshakeSession *session;
		AtomicInt expectedStartPort;

		virtual void beginWaitUntilSpawningFinished() {
			expectedStartPort = session->expectedStartPort;
			test->counter++;
		}
	};

	struct CrashingDebugSupport: public HandshakePerform::DebugSupport {
		virtual void beginWaitUntilSpawningFinished() {
			throw RuntimeException("oh no!");
		}
	};

	DEFINE_TEST_GROUP_WITH_LIMIT(Core_SpawningKit_HandshakePerformTest, 80);

	/***** General logic *****/

	TEST_METHOD(1) {
		set_test_name("If the app is generic, it finishes when the app is pingable");

		FreePortDebugSupport debugSupport;
		this->debugSupport = &debugSupport;
		config.genericApp = true;
		init(SPAWN_DIRECTLY);
		debugSupport.test = this;
		debugSupport.session = session.get();
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::execute, this));

		EVENTUALLY(1,
			result = counter == 1;
		);

		server.assign(createTcpServer("127.0.0.1", debugSupport.expectedStartPort.get()),
			NULL, 0);

		EVENTUALLY(1,
			result = counter == 2;
		);
	}

	TEST_METHOD(2) {
		set_test_name("If findFreePort is true, it finishes when the app is pingable");

		FreePortDebugSupport debugSupport;
		this->debugSupport = &debugSupport;
		config.findFreePort = true;
		init(SPAWN_DIRECTLY);
		debugSupport.test = this;
		debugSupport.session = session.get();
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::execute, this));

		EVENTUALLY(1,
			result = counter == 1;
		);

		server.assign(createTcpServer("127.0.0.1", debugSupport.expectedStartPort.get()),
			NULL, 0);

		EVENTUALLY(1,
			result = counter == 2;
		);
	}

	TEST_METHOD(3) {
		set_test_name("It finishes when the app has sent the finish signal");

		init(SPAWN_DIRECTLY);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::execute, this));

		SHOULD_NEVER_HAPPEN(100,
			result = counter > 0;
		);

		createFile(session->responseDir + "/properties.json",
			createGoodPropertiesJson().toStyledString());
		signalFinish();

		EVENTUALLY(1,
			result = counter == 1;
		);
	}

	TEST_METHOD(10) {
		set_test_name("It raises an error if the process exits prematurely");

		init(SPAWN_DIRECTLY);
		pid = fork();
		if (pid == 0) {
			// Exit child
			_exit(1);
		}

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(StaticString(e.what()),
				"The application process exited prematurely.");
		}
	}

	TEST_METHOD(11) {
		set_test_name("It raises an error if the procedure took too long");

		config.startTimeoutMsec = 50;
		init(SPAWN_DIRECTLY);
		pid = fork();
		if (pid == 0) {
			// Exit child
			usleep(1000000);
			_exit(1);
		}

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(StaticString(e.what()),
				"A timeout occurred while spawning an application process.");
		}
	}

	TEST_METHOD(15) {
		set_test_name("In the event of an error, it sets the SPAWNING_KIT_HANDSHAKE_PERFORM step to the errored state");

		CrashingDebugSupport debugSupport;
		this->debugSupport = &debugSupport;
		init(SPAWN_DIRECTLY);

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &) {
			ensure_equals(session->journey.getFirstFailedStep(), SPAWNING_KIT_HANDSHAKE_PERFORM);
		}
	}

	TEST_METHOD(16) {
		set_test_name("In the event of an error, the exception contains journey state information from the response directory");

		CrashingDebugSupport debugSupport;
		this->debugSupport = &debugSupport;
		init(SPAWN_DIRECTLY);

		createFile(session->responseDir + "/steps/subprocess_listen/state", "STEP_ERRORED");

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &) {
			ensure_equals(session->journey.getStepInfo(SUBPROCESS_LISTEN).state,
				STEP_ERRORED);
		}
	}

	TEST_METHOD(17) {
		set_test_name("In the event of an error, the exception contains subprocess stdout and stderr data");

		Pipe p = createPipe(__FILE__, __LINE__);
		CrashingDebugSupport debugSupport;
		init(SPAWN_DIRECTLY);
		HandshakePerform performer(*session, pid, FileDescriptor(), p.first);
		performer.debugSupport = &debugSupport;

		Json::Value config;
		vector<ConfigKit::Error> errors;
		LoggingKit::ConfigChangeRequest req;
		config["app_output_log_level"] = "debug";
		if (LoggingKit::context->prepareConfigChange(config, errors, req)) {
			LoggingKit::context->commitConfigChange(req);
		} else {
			P_BUG("Error configuring LoggingKit: " << ConfigKit::toString(errors));
		}

		writeExact(p.second, "hi\n");

		try {
			performer.execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(e.getStdoutAndErrData(), "hi\n");
		}
	}

	TEST_METHOD(18) {
		set_test_name("In the event of an error caused by the subprocess, the exception contains messages from"
			" the subprocess as dumped in the response directory");

		init(SPAWN_DIRECTLY);
		pid = fork();
		if (pid == 0) {
			// Exit child
			_exit(1);
		}

		createFile(session->responseDir + "/error/summary", "the summary");
		createFile(session->responseDir + "/error/problem_description.txt", "the <problem>");
		createFile(session->responseDir + "/error/advanced_problem_details", "the advanced problem details");
		createFile(session->responseDir + "/error/solution_description.html", "the solution");

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(e.getSummary(), "the summary");
			ensure_equals(e.getProblemDescriptionHTML(), "the <problem>");
			ensure_equals(e.getAdvancedProblemDetails(), "the advanced problem details");
			ensure_equals(e.getSolutionDescriptionHTML(), "the solution");
		}
	}

	TEST_METHOD(19) {
		set_test_name("In the event of success, it loads the journey state information from the response directory");

		init(SPAWN_DIRECTLY);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::execute, this));

		createFile(session->responseDir + "/properties.json",
			createGoodPropertiesJson().toStyledString());
		createFile(session->responseDir + "/steps/subprocess_listen/state",
			"STEP_PERFORMED");
		signalFinish();

		EVENTUALLY(5,
			result = counter == 1;
		);

		ensure_equals(session->journey.getStepInfo(SUBPROCESS_LISTEN).state, STEP_PERFORMED);
	}

	TEST_METHOD(20) {
		// Limited test of whether the code mitigates symlink attacks.
		set_test_name("It does not read from symlinks");

		init(SPAWN_DIRECTLY);

		createFile(session->responseDir + "/properties-real.json",
			createGoodPropertiesJson().toStyledString());
		symlink("properties-real.json",
			(session->responseDir + "/properties.json").c_str());
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinish,
			this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure(containsSubstring(e.getSummary(),
				"Cannot open 'properties.json'"));
		}
	}

	/***** Success response handling *****/

	TEST_METHOD(30) {
		set_test_name("The result object contains basic information such as FDs and time");

		init(SPAWN_DIRECTLY);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::execute, this));

		createFile(session->responseDir + "/properties.json",
			createGoodPropertiesJson().toStyledString());
		createFile(session->responseDir + "/steps/subprocess_listen/state",
			"STEP_PERFORMED");
		signalFinish();

		EVENTUALLY(5,
			result = counter == 1;
		);

		ensure_equals(session->result.pid, pid);
		ensure(session->result.spawnStartTime != 0);
		ensure(session->result.spawnEndTime >= session->result.spawnStartTime);
		ensure(session->result.spawnStartTimeMonotonic != 0);
		ensure(session->result.spawnEndTimeMonotonic >= session->result.spawnStartTimeMonotonic);
	}

	TEST_METHOD(31) {
		set_test_name("The result object contains sockets specified in properties.json");

		init(SPAWN_DIRECTLY);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::execute, this));

		createFile(session->responseDir + "/properties.json",
			createGoodPropertiesJson().toStyledString());
		createFile(session->responseDir + "/steps/subprocess_listen/state",
			"STEP_PERFORMED");
		signalFinish();

		EVENTUALLY(5,
			result = counter == 1;
		);

		ensure_equals(session->result.sockets.size(), 1u);
		ensure_equals(session->result.sockets[0].address, "tcp://127.0.0.1:3000");
		ensure_equals(session->result.sockets[0].protocol, "http");
		ensure_equals(session->result.sockets[0].concurrency, 1);
		ensure(session->result.sockets[0].acceptHttpRequests);
	}

	TEST_METHOD(32) {
		set_test_name("If the app is generic, it automatically registers the free port as a request-handling socket");

		FreePortDebugSupport debugSupport;
		this->debugSupport = &debugSupport;
		config.genericApp = true;
		init(SPAWN_DIRECTLY);
		debugSupport.test = this;
		debugSupport.session = session.get();
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::execute, this));

		EVENTUALLY(1,
			result = counter == 1;
		);
		server.assign(createTcpServer("127.0.0.1", debugSupport.expectedStartPort.get()),
			NULL, 0);
		EVENTUALLY(1,
			result = counter == 2;
		);

		ensure_equals(session->result.sockets.size(), 1u);
		ensure_equals(session->result.sockets[0].address, "tcp://127.0.0.1:" + toString(session->expectedStartPort));
		ensure_equals(session->result.sockets[0].protocol, "http");
		ensure_equals(session->result.sockets[0].concurrency, -1);
		ensure(session->result.sockets[0].acceptHttpRequests);
	}

	TEST_METHOD(33) {
		set_test_name("If findFreePort is true, it automatically registers the free port as a request-handling socket");

		FreePortDebugSupport debugSupport;
		this->debugSupport = &debugSupport;
		config.findFreePort = true;
		init(SPAWN_DIRECTLY);
		debugSupport.test = this;
		debugSupport.session = session.get();
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::execute, this));

		EVENTUALLY(1,
			result = counter == 1;
		);
		server.assign(createTcpServer("127.0.0.1", debugSupport.expectedStartPort.get()),
			NULL, 0);
		EVENTUALLY(1,
			result = counter == 2;
		);

		ensure_equals(session->result.sockets.size(), 1u);
		ensure_equals(session->result.sockets[0].address, "tcp://127.0.0.1:" + toString(session->expectedStartPort));
		ensure_equals(session->result.sockets[0].protocol, "http");
		ensure_equals(session->result.sockets[0].concurrency, -1);
		ensure(session->result.sockets[0].acceptHttpRequests);
	}

	TEST_METHOD(34) {
		set_test_name("It raises an error if we expected the subprocess to create a properties.json,"
			" but the file does not conform to the required format");

		init(SPAWN_DIRECTLY);
		createFile(session->responseDir + "/properties.json", "{ \"sockets\": {} }");
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinish, this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure(containsSubstring(e.getSummary(), "'sockets' must be an array"));
		}
	}

	TEST_METHOD(35) {
		set_test_name("It raises an error if we expected the subprocess to specify at"
			" least one request-handling socket in properties.json, yet the file does"
			" not specify any");

		Json::Value socket, doc;
		socket["address"] = "tcp://127.0.0.1:3000";
		socket["protocol"] = "http";
		socket["concurrency"] = 1;
		doc["sockets"].append(socket);

		init(SPAWN_DIRECTLY);
		createFile(session->responseDir + "/properties.json", doc.toStyledString());
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinish, this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure(containsSubstring(e.getSummary(),
				"the application did not report any sockets to receive requests on"));
		}
	}

	TEST_METHOD(36) {
		set_test_name("It raises an error if we expected the subprocess to specify at"
			" least one request-handling socket in properties.json, yet properties.json"
			" does not exist");

		init(SPAWN_DIRECTLY);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinish, this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure(containsSubstring(e.getSummary(), "sockets are not supplied"));
		}
	}

	TEST_METHOD(37) {
		set_test_name("It raises an error if we expected the subprocess to specify at"
			" least one preloader command socket in properties.json, yet the file does"
			" not specify any");

		Json::Value socket, doc;
		socket["address"] = "tcp://127.0.0.1:3000";
		socket["protocol"] = "http";
		socket["concurrency"] = 1;
		doc["sockets"].append(socket);

		init(START_PRELOADER);
		createFile(session->responseDir + "/properties.json", doc.toStyledString());
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinish, this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure(containsSubstring(e.getSummary(),
				"the application did not report any sockets to receive preloader commands on"));
		}
	}

	TEST_METHOD(38) {
		set_test_name("It raises an error if we expected the subprocess to specify at"
			" least one preloader command socket in properties.json, yet properties.json"
			" does not exist");

		init(START_PRELOADER);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinish, this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure(containsSubstring(e.getSummary(),
				"sockets are not supplied"));
		}
	}

	TEST_METHOD(39) {
		set_test_name("It raises an error if properties.json specifies a Unix domain socket"
			" that is not located in the apps.s subdir of the instance directory");

		TempDir tmpDir("tmp.instance");

		context.instanceDir = absolutizePath("tmp.instance");
		init(SPAWN_DIRECTLY);
		Json::Value doc = createGoodPropertiesJson();
		doc["sockets"][0]["address"] = "unix:/foo";
		createFile(session->responseDir + "/properties.json", doc.toStyledString());
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinish, this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure(containsSubstring(e.getSummary(),
				"must be an absolute path to a file in"));
		}
	}

	TEST_METHOD(40) {
		set_test_name("It raises an error if properties.json specifies a Unix domain socket"
			" that is not owned by the app");

		if (geteuid() != 0) {
			return;
		}

		TempDir tmpDir("tmp.instance");
		mkdir("tmp.instance/apps.s", 0700);
		string socketPath = absolutizePath("tmp.instance/apps.s/foo.sock");

		init(SPAWN_DIRECTLY);
		Json::Value doc = createGoodPropertiesJson();
		doc["sockets"][0]["address"] = "unix:" + socketPath;
		createFile(session->responseDir + "/properties.json", doc.toStyledString());
		safelyClose(createUnixServer(socketPath));
		chown(socketPath.c_str(), 1, 1);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinish, this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure("(1)", containsSubstring(e.getSummary(), "must be owned by user"));
		}
	}

	/***** Error response handling *****/

	TEST_METHOD(50) {
		set_test_name("It raises an error if the application responded with an error");

		init(SPAWN_DIRECTLY);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinishWithError,
			this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(e.getSummary(), "The web application aborted with an error during startup.");
		}
	}

	TEST_METHOD(51) {
		set_test_name("The exception contains error messages provided by the application");

		init(SPAWN_DIRECTLY);
		writeFile(session->workDir->getPath() + "/response/error/summary",
			"the summary");
		writeFile(session->workDir->getPath() + "/response/error/problem_description.html",
			"the problem description");
		writeFile(session->workDir->getPath() + "/response/error/solution_description.html",
			"the solution description");
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinishWithError,
			this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(e.getSummary(), "the summary");
			ensure_equals(e.getProblemDescriptionHTML(), "the problem description");
			ensure_equals(e.getSolutionDescriptionHTML(), "the solution description");
		}
	}

	TEST_METHOD(52) {
		set_test_name("The exception describes which steps in the journey had failed");

		init(SPAWN_DIRECTLY);
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinishWithError,
			this));

		try {
			execute();
		} catch (const SpawnException &e) {
			ensure_equals(e.getJourney().getFirstFailedStep(), SUBPROCESS_BEFORE_FIRST_EXEC);
		}
	}

	TEST_METHOD(53) {
		set_test_name("The exception contains the subprocess' output");

		Json::Value config;
		vector<ConfigKit::Error> errors;
		LoggingKit::ConfigChangeRequest req;
		config["app_output_log_level"] = "debug";
		if (LoggingKit::context->prepareConfigChange(config, errors, req)) {
			LoggingKit::context->commitConfigChange(req);
		} else {
			P_BUG("Error configuring LoggingKit: " << ConfigKit::toString(errors));
		}

		init(SPAWN_DIRECTLY);
		stdoutAndErr = createPipe(__FILE__, __LINE__);
		writeExact(stdoutAndErr.second, "oh no");
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinishWithError,
			this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(e.getStdoutAndErrData(), "oh no");
		}
	}

	TEST_METHOD(54) {
		set_test_name("The exception contains the subprocess' environment variables dump");

		init(SPAWN_DIRECTLY);
		writeFile(session->workDir->getPath() + "/envdump/envvars",
			"the env dump");
		TempThread thr(boost::bind(&Core_SpawningKit_HandshakePerformTest::signalFinishWithError,
			this));

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals(e.getSubprocessEnvvars(), "the env dump");
		}
	}

	TEST_METHOD(55) {
		set_test_name("If the subprocess fails without setting a specific"
			" journey step to the ERRORED state,"
			" and there is a subprocess journey step in the IN_PROGRESS state,"
			" then we set that latter step to the ERRORED state");

		init(SPAWN_DIRECTLY);
		pid = fork();
		if (pid == 0) {
			// Exit child
			_exit(1);
		}

		createFile(session->responseDir
			+ "/steps/subprocess_before_first_exec/state",
			"STEP_PERFORMED");
		createFile(session->responseDir
			+ "/steps/subprocess_before_first_exec/duration",
			"1");
		createFile(session->responseDir
			+ "/steps/subprocess_spawn_env_setupper_before_shell/state",
			"STEP_IN_PROGRESS");

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals("SPAWNING_KIT_HANDSHAKE_PERFORM is in the IN_PROGRESS state",
				e.getJourney().getStepInfo(SPAWNING_KIT_HANDSHAKE_PERFORM).state,
				STEP_IN_PROGRESS);

			ensure_equals("SUBPROCESS_BEFORE_FIRST_EXEC is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_BEFORE_FIRST_EXEC).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL is in the ERRORED state",
				e.getJourney().getStepInfo(SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL).state,
				STEP_ERRORED);
			ensure_equals("SUBPROCESS_OS_SHELL is in the NOT_STARTED state",
				e.getJourney().getStepInfo(SUBPROCESS_OS_SHELL).state,
				STEP_NOT_STARTED);
			ensure_equals("SUBPROCESS_SPAWN_ENV_SETUPPER_AFTER_SHELL is in the NOT_STARTED state",
				e.getJourney().getStepInfo(SUBPROCESS_SPAWN_ENV_SETUPPER_AFTER_SHELL).state,
				STEP_NOT_STARTED);
		}
	}

	TEST_METHOD(56) {
		set_test_name("If the subprocess fails without setting a specific"
			" journey step to the ERRORED state,"
			" and there is no subprocess journey step in the IN_PROGRESS state,"
			" and no subprocess journey steps are in the PERFORMED state,"
			" then we set the first subprocess journey step to the ERRORED state");

		init(SPAWN_DIRECTLY);
		pid = fork();
		if (pid == 0) {
			// Exit child
			_exit(1);
		}

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals("SPAWNING_KIT_HANDSHAKE_PERFORM is in the IN_PROGRESS state",
				e.getJourney().getStepInfo(SPAWNING_KIT_HANDSHAKE_PERFORM).state,
				STEP_IN_PROGRESS);

			ensure_equals("SUBPROCESS_BEFORE_FIRST_EXEC is in the ERRORED state",
				e.getJourney().getStepInfo(SUBPROCESS_BEFORE_FIRST_EXEC).state,
				STEP_ERRORED);
			ensure_equals("SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL is in the NOT_STARTED state",
				e.getJourney().getStepInfo(SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL).state,
				STEP_NOT_STARTED);
		}
	}

	TEST_METHOD(57) {
		set_test_name("If the subprocess fails without setting a specific"
			" journey step to the ERRORED state,"
			" and there is no subprocess journey step in the IN_PROGRESS state,"
			" and some but not all subprocess journey steps are in the PERFORMED state,"
			" then we set the step that comes right after the last PERFORMED step,"
			" to the ERRORED state");

		init(SPAWN_DIRECTLY);
		pid = fork();
		if (pid == 0) {
			// Exit child
			_exit(1);
		}

		createFile(session->responseDir
			+ "/steps/subprocess_before_first_exec/state",
			"STEP_PERFORMED");
		createFile(session->responseDir
			+ "/steps/subprocess_before_first_exec/duration",
			"1");

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals("SPAWNING_KIT_HANDSHAKE_PERFORM is in the IN_PROGRESS state",
				e.getJourney().getStepInfo(SPAWNING_KIT_HANDSHAKE_PERFORM).state,
				STEP_IN_PROGRESS);

			ensure_equals("SUBPROCESS_BEFORE_FIRST_EXEC is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_BEFORE_FIRST_EXEC).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL is in the ERRORED state",
				e.getJourney().getStepInfo(SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL).state,
				STEP_ERRORED);
			ensure_equals("SUBPROCESS_OS_SHELL is in the NOT_STARTED state",
				e.getJourney().getStepInfo(SUBPROCESS_OS_SHELL).state,
				STEP_NOT_STARTED);
			ensure_equals("SUBPROCESS_SPAWN_ENV_SETUPPER_AFTER_SHELL is in the NOT_STARTED state",
				e.getJourney().getStepInfo(SUBPROCESS_SPAWN_ENV_SETUPPER_AFTER_SHELL).state,
				STEP_NOT_STARTED);
		}
	}

	TEST_METHOD(58) {
		set_test_name("If the subprocess fails without setting a specific"
			" journey step to the ERRORED state,"
			" and there is no subprocess journey step in the IN_PROGRESS state,"
			" and all subprocess journey steps are in the PERFORMED state,"
			" then we set the last subprocess step to the ERRORED state");

		init(SPAWN_DIRECTLY);
		pid = fork();
		if (pid == 0) {
			// Exit child
			_exit(1);
		}

		JourneyStep firstStep = getFirstSubprocessJourneyStep();
		JourneyStep lastStep = getLastSubprocessJourneyStep();
		JourneyStep step;

		for (step = firstStep; step < lastStep; step = JourneyStep((int) step + 1)) {
			if (!session->journey.hasStep(step)) {
				continue;
			}

			createFile(session->responseDir
				+ "/steps/" + journeyStepToStringLowerCase(step) + "/state",
				"STEP_PERFORMED");
			createFile(session->responseDir
				+ "/steps/" + journeyStepToStringLowerCase(step) + "/duration",
				"1");
		}

		try {
			execute();
			fail("SpawnException expected");
		} catch (const SpawnException &e) {
			ensure_equals("SPAWNING_KIT_HANDSHAKE_PERFORM is in the IN_PROGRESS state",
				e.getJourney().getStepInfo(SPAWNING_KIT_HANDSHAKE_PERFORM).state,
				STEP_IN_PROGRESS);

			ensure_equals("SUBPROCESS_BEFORE_FIRST_EXEC is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_BEFORE_FIRST_EXEC).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_SPAWN_ENV_SETUPPER_BEFORE_SHELL).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_OS_SHELL is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_OS_SHELL).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_SPAWN_ENV_SETUPPER_AFTER_SHELL is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_SPAWN_ENV_SETUPPER_AFTER_SHELL).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_APP_LOAD_OR_EXEC is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_APP_LOAD_OR_EXEC).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_APP_LOAD_OR_EXEC is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_APP_LOAD_OR_EXEC).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_LISTEN is in the PERFORMED state",
				e.getJourney().getStepInfo(SUBPROCESS_LISTEN).state,
				STEP_PERFORMED);
			ensure_equals("SUBPROCESS_FINISH is in the ERRORED state",
				e.getJourney().getStepInfo(SUBPROCESS_FINISH).state,
				STEP_ERRORED);
		}
	}
}


text:
////////////////////////////////////////////////////////////////////////////////
// Name:      macros.cpp
// Purpose:   Implementation of class wex::macros
// Author:    Anton van Wezenbeek
// Copyright: (c) 2021-2022 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <boost/algorithm/string.hpp>
#include <wex/common/util.h>
#include <wex/core/app.h>
#include <wex/core/config.h>
#include <wex/core/core.h>
#include <wex/core/log.h>
#include <wex/core/path.h>
#include <wex/core/type-to-value.h>
#include <wex/factory/lexer-props.h>
#include <wex/ui/frame.h>
#include <wex/vi/macros.h>

#include <algorithm>
#include <numeric>

wex::macros::macros()
  : m_mode(this)
{
}

bool wex::macros::erase()
{
  if (m_macros.erase(m_mode.get_macro()) == 0)
  {
    log("erase macro") << m_mode.get_macro();
    return false;
  }

  return true;
}

const std::vector<std::string> wex::macros::find(const std::string& macro) const
{
  if (const auto& it = m_macros.find(macro); it != m_macros.end())
  {
    return it->second;
  }
  else
  {
    if (const auto& it = m_variables.find(macro); it != m_variables.end())
    {
      return {it->second.get_value()};
    }
    else
    {
      return {};
    }
  }
}

const std::vector<std::string> wex::macros::get() const
{
  std::vector<std::string> v;

  for (const auto& it : m_macros)
  {
    if (it.first.size() > 1)
    {
      v.emplace_back(it.first);
    }
  }

  std::transform(
    m_variables.begin(),
    m_variables.end(),
    std::back_inserter(v),
    [](const auto& i)
    {
      return i.first;
    });

  std::sort(v.begin(), v.end());

  return v;
}

const wex::path wex::macros::path() const
{
  return wex::path(config::dir(), "wex-macros.xml");
}

const wex::macros::keys_map_t& wex::macros::get_keys_map(key_t type) const
{
  switch (type)
  {
    case KEY_ALT:
      return m_map_alt_keys;
    case KEY_CONTROL:
      return m_map_control_keys;
    default:
      return m_map_keys;
  }
}

const std::vector<std::string>
wex::macros::get_macro_commands(const std::string& macro) const
{
  const auto& it = m_macros.find(macro);
  return (it != m_macros.end()) ? it->second : std::vector<std::string>();
}

const std::string wex::macros::get_register(char name) const
{
  switch (name)
  {
    case '*':
    case '\"':
      return clipboard_get();

    default:
    {
      const auto& it = m_macros.find(std::string(1, name));
      return it != m_macros.end() ? std::accumulate(
                                      it->second.begin(),
                                      it->second.end(),
                                      std::string()) :
                                    std::string();
    }
  }
}

const std::vector<std::string> wex::macros::get_registers() const
{
  std::vector<std::string> r;
  lexer_props              l;

  for (const auto& it : m_macros)
  {
    if (it.first.size() == 1)
    {
      r.emplace_back(l.make_key(
        it.first,
        boost::algorithm::trim_copy(
          std::accumulate(it.second.begin(), it.second.end(), std::string()))));
    }
  }

  if (const auto& clipboard(boost::algorithm::trim_copy(clipboard_get()));
      !clipboard.empty())
  {
    r.emplace_back(l.make_key("*", clipboard));
  }

  return r;
}

bool wex::macros::is_recorded(const std::string& macro) const
{
  return !find(macro).empty();
}

bool wex::macros::is_recorded_macro(const std::string& macro) const
{
  return m_macros.find(macro) != m_macros.end();
}

bool wex::macros::load_document()
{
  if (!path().file_exists())
  {
    return false;
  }

  if (const auto result = m_doc.load_file(
        path().string().c_str(),
        pugi::parse_default | pugi::parse_comments);
      !result)
  {
    xml_error(path(), &result);
    return false;
  }

  m_is_modified = false;

  m_abbreviations.clear();
  m_macros.clear();
  m_map.clear();
  m_map_alt_keys.clear();
  m_map_control_keys.clear();
  m_map_keys.clear();
  m_variables.clear();

  for (const auto& child : m_doc.document_element().children())
  {
    if (strcmp(child.name(), "abbreviation") == 0)
    {
      parse_node<std::string, strings_map_t>(
        child,
        "abbreviation",
        m_abbreviations);
    }
    else if (strcmp(child.name(), "macro") == 0)
    {
      parse_node_macro(child);
    }
    else if (strcmp(child.name(), "map") == 0)
    {
      parse_node<std::string, strings_map_t>(child, "map", m_map);
    }
    else if (strcmp(child.name(), "map-alt") == 0)
    {
      parse_node<int, keys_map_t>(child, "map-alt", m_map_alt_keys);
    }
    else if (strcmp(child.name(), "map-control") == 0)
    {
      parse_node<int, keys_map_t>(child, "map-control", m_map_control_keys);
    }
    else if (strcmp(child.name(), "map-key") == 0)
    {
      parse_node<int, keys_map_t>(child, "map-key", m_map_keys);
    }
    else if (strcmp(child.name(), "variable") == 0)
    {
      parse_node_variable(child);
    }
  }

  log::trace("macros info")
    << "abbreviations:" << m_abbreviations.size() << "maps:" << m_map.size()
    << "macros:" << m_macros.size() << "variables:" << m_variables.size();

  m_is_loaded = true;

  return true;
}

template <typename S, typename T>
void wex::macros::parse_node(
  const pugi::xml_node& node,
  const std::string&    container_name,
  T&                    container)
{
  const std::string name(node.attribute("name").value());

  if (const S& value = type_to_value<S>(name).get();
      container.find(value) != container.end())
  {
    log("duplicate " + container_name)
      << name << "current:" << container[value]
      << "update:" << node.text().get() << node;
  }
  else
  {
    container.insert({value, std::string(node.text().get())});
  }
}

void wex::macros::parse_node_macro(const pugi::xml_node& node)
{
  const std::string name(node.attribute("name").value());

  if (const auto& it = m_macros.find(name); it != m_macros.end())
  {
    log("duplicate macro") << name << node << it->second.front();
  }
  else
  {
    std::vector<std::string> v;

    std::transform(
      node.children().begin(),
      node.children().end(),
      std::back_inserter(v),
      [](const auto& t)
      {
        return t.text().get();
      });

    m_macros.insert({node.attribute("name").value(), v});
  }
}

void wex::macros::parse_node_variable(const pugi::xml_node& node)
{
  if (const variable variable(node); variable.get_name().empty())
  {
    log("empty variable") << node;
  }
  else if (const auto& it = m_variables.find(variable.get_name());
           it != m_variables.end())
  {
    log("duplicate variable") << variable.get_name() << node;
  }
  else
  {
    m_variables.insert({variable.get_name(), variable});
  }
}

bool wex::macros::record(const std::string& text, bool new_command)
{
  if (auto* f = (dynamic_cast<frame*>(wxTheApp->GetTopWindow())); f != nullptr)
  {
    f->record(text);
  }

  if (!m_mode.is_recording() || m_mode.is_playback() || text.empty())
  {
    return false;
  }

  if (m_mode.get_macro().empty())
  {
    log("macro record while macro empty") << text;
    return false;
  }

  if (new_command)
  {
    m_macros[m_mode.get_macro()].emplace_back(text == " " ? "l" : text);
  }
  else
  {
    if (m_macros[m_mode.get_macro()].empty())
    {
      std::string s;
      m_macros[m_mode.get_macro()].emplace_back(s);
    }

    m_macros[m_mode.get_macro()].back() += text;
  }

  if (const auto& it = m_macros.find(m_mode.get_macro()); it != m_macros.end())
  {
    log::trace("macro recorded")
      << m_mode.get_macro() << "->"
      << std::accumulate(it->second.begin(), it->second.end(), std::string());
  }

  return true;
}

bool wex::macros::save_document(bool only_if_modified)
{
  if (
    !m_is_loaded || !path().file_exists() ||
    (!m_is_modified && only_if_modified))
  {
    return false;
  }

  const bool ok = m_doc.save_file(path().string().c_str(), "  ");

  if (ok)
  {
    m_is_modified = false;
  }

  return ok;
}

bool wex::macros::save_macro(const std::string& macro)
{
  try
  {
    if (const auto& v(find(macro)); !v.empty())
    {
      if (const auto& node = m_doc.document_element().select_node(
            std::string("//macro[@name='" + macro + "']").c_str());
          node && node.node())
      {
        m_doc.document_element().remove_child(node.node());
      }

      auto node_macro = m_doc.document_element().append_child("macro");
      node_macro.append_attribute("name") = macro.c_str();

      for (const auto& it : v)
      {
        node_macro.append_child("command").text().set(it.c_str());
      }

      m_is_modified = true;

      return save_document();
    }
  }
  catch (pugi::xpath_exception& e)
  {
    log(e) << macro;
  }

  return false;
}

template <typename S, typename T>
void wex::macros::set(
  T&                 container,
  const std::string& xpath,
  const std::string& name,
  const std::string& value)
{
  try
  {
    if (const auto& node = m_doc.document_element().select_node(
          std::string("//" + xpath + "[@name='" + name + "']").c_str());
        node && node.node())
    {
      m_doc.document_element().remove_child(node.node());
    }

    if (value.empty())
    {
      container.erase(type_to_value<S>(name).get());
    }
    else
    {
      auto child = m_doc.document_element().append_child(xpath.c_str());
      child.append_attribute("name") = name.c_str();
      child.text().set(value.c_str());

      container[type_to_value<S>(name).get()] = value;
    }

    m_is_modified = true;
  }
  catch (pugi::xpath_exception& e)
  {
    log(e) << name;
  }
}

void wex::macros::set_abbreviation(
  const std::string& name,
  const std::string& value)
{
  set<std::string, strings_map_t>(m_abbreviations, "abbreviation", name, value);
}

void wex::macros::set_key_map(
  const std::string& name,
  const std::string& value,
  macros::key_t      type)
{
  switch (type)
  {
    case KEY_ALT:
      set<int, keys_map_t>(m_map_alt_keys, "map-alt", name, value);
      break;

    case KEY_CONTROL:
      set<int, keys_map_t>(m_map_control_keys, "map-control", name, value);
      break;

    case KEY_NORMAL:
      set<int, keys_map_t>(m_map_keys, "map-key", name, value);
      break;
  }
}

void wex::macros::set_map(const std::string& name, const std::string& value)
{
  set<std::string, strings_map_t>(m_map, "map", name, value);
}

bool wex::macros::set_register(char name, const std::string& value)
{
  if (
    !isalnum(name) && !isdigit(name) && name != '%' && name != '_' &&
    name != '*' && name != '.')
  {
    return false;
  }

  if (name == '*')
  {
    clipboard_add(value);
    return true;
  }

  std::vector<std::string> v;

  // The black hole register, everything written to it is discarded.
  if (name != '_')
  {
    if (isupper(name))
    {
      v.emplace_back(get_register(tolower(name)) + value);
    }
    else
    {
      v.emplace_back(value);
    }
  }

  m_macros[std::string(1, static_cast<char>(tolower(name)))] = v;
  save_macro(std::string(1, static_cast<char>(tolower(name))));

  return true;
}

bool wex::macros::starts_with(const std::string_view& text)
{
  if (text.empty() || isdigit(text[0]))
  {
    return false;
  }

  return (
    std::any_of(
      m_macros.begin(),
      m_macros.end(),
      [text](const auto& p)
      {
        return p.first.substr(0, text.size()) == text;
      }) ||
    std::any_of(
      m_variables.begin(),
      m_variables.end(),
      [text](const auto& p)
      {
        return p.first.substr(0, text.size()) == text;
      }));
}

max_stars_repo_name: antonvw/wxExtension

max_issues_repo_name: antonvw/wxExtension

max_forks_repo_name: antonvw/wxExtension


text:
/**
 * Swaggy Jenkins
 * Jenkins API clients generated from Swagger / Open API specification
 *
 * OpenAPI spec version: 1.1.1
 * Contact: blah@cliffano.com
 *
 * NOTE: This class is auto generated by OpenAPI-Generator 3.2.1-SNAPSHOT.
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

#include "Hudson.h"

#include <string>
#include <sstream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;

namespace org {
namespace openapitools {
namespace server {
namespace model {

Hudson::Hudson()
{
    m__class = "";
    m_Mode = "";
    m_NodeDescription = "";
    m_NodeName = "";
    m_NumExecutors = 0;
    m_Description = "";
    m_QuietingDown = false;
    m_SlaveAgentPort = 0;
    m_UseCrumbs = false;
    m_UseSecurity = false;

}

Hudson::~Hudson()
{
}

std::string Hudson::toJsonString()
{
	std::stringstream ss;
	ptree pt;
	pt.put("_class", m__class);
	pt.put("Mode", m_Mode);
	pt.put("NodeDescription", m_NodeDescription);
	pt.put("NodeName", m_NodeName);
	pt.put("NumExecutors", m_NumExecutors);
	pt.put("Description", m_Description);
	pt.put("QuietingDown", m_QuietingDown);
	pt.put("SlaveAgentPort", m_SlaveAgentPort);
	pt.put("UseCrumbs", m_UseCrumbs);
	pt.put("UseSecurity", m_UseSecurity);
	write_json(ss, pt, false);
	return ss.str();
}

void Hudson::fromJsonString(std::string const& jsonString)
{
	std::stringstream ss(jsonString);
	ptree pt;
	read_json(ss,pt);
	m__class = pt.get("_class", "");
	m_Mode = pt.get("Mode", "");
	m_NodeDescription = pt.get("NodeDescription", "");
	m_NodeName = pt.get("NodeName", "");
	m_NumExecutors = pt.get("NumExecutors", 0);
	m_Description = pt.get("Description", "");
	m_QuietingDown = pt.get("QuietingDown", false);
	m_SlaveAgentPort = pt.get("SlaveAgentPort", 0);
	m_UseCrumbs = pt.get("UseCrumbs", false);
	m_UseSecurity = pt.get("UseSecurity", false);
}

std::string Hudson::getClass() const
{
    return m__class;
}
void Hudson::setClass(std::string value)
{
    m__class = value;
}
std::vector<std::shared_ptr<HudsonassignedLabels>> Hudson::getAssignedLabels() const
{
    return m_AssignedLabels;
}
void Hudson::setAssignedLabels(std::vector<std::shared_ptr<HudsonassignedLabels>> value)
{
    m_AssignedLabels = value;
}
std::string Hudson::getMode() const
{
    return m_Mode;
}
void Hudson::setMode(std::string value)
{
    m_Mode = value;
}
std::string Hudson::getNodeDescription() const
{
    return m_NodeDescription;
}
void Hudson::setNodeDescription(std::string value)
{
    m_NodeDescription = value;
}
std::string Hudson::getNodeName() const
{
    return m_NodeName;
}
void Hudson::setNodeName(std::string value)
{
    m_NodeName = value;
}
int32_t Hudson::getNumExecutors() const
{
    return m_NumExecutors;
}
void Hudson::setNumExecutors(int32_t value)
{
    m_NumExecutors = value;
}
std::string Hudson::getDescription() const
{
    return m_Description;
}
void Hudson::setDescription(std::string value)
{
    m_Description = value;
}
std::vector<std::shared_ptr<FreeStyleProject>> Hudson::getJobs() const
{
    return m_Jobs;
}
void Hudson::setJobs(std::vector<std::shared_ptr<FreeStyleProject>> value)
{
    m_Jobs = value;
}
std::shared_ptr<AllView> Hudson::getPrimaryView() const
{
    return m_PrimaryView;
}
void Hudson::setPrimaryView(std::shared_ptr<AllView> value)
{
    m_PrimaryView = value;
}
bool Hudson::isQuietingDown() const
{
    return m_QuietingDown;
}
void Hudson::setQuietingDown(bool value)
{
    m_QuietingDown = value;
}
int32_t Hudson::getSlaveAgentPort() const
{
    return m_SlaveAgentPort;
}
void Hudson::setSlaveAgentPort(int32_t value)
{
    m_SlaveAgentPort = value;
}
std::shared_ptr<UnlabeledLoadStatistics> Hudson::getUnlabeledLoad() const
{
    return m_UnlabeledLoad;
}
void Hudson::setUnlabeledLoad(std::shared_ptr<UnlabeledLoadStatistics> value)
{
    m_UnlabeledLoad = value;
}
bool Hudson::isUseCrumbs() const
{
    return m_UseCrumbs;
}
void Hudson::setUseCrumbs(bool value)
{
    m_UseCrumbs = value;
}
bool Hudson::isUseSecurity() const
{
    return m_UseSecurity;
}
void Hudson::setUseSecurity(bool value)
{
    m_UseSecurity = value;
}
std::vector<std::shared_ptr<AllView>> Hudson::getViews() const
{
    return m_Views;
}
void Hudson::setViews(std::vector<std::shared_ptr<AllView>> value)
{
    m_Views = value;
}

}
}
}
}

max_stars_repo_name: PankTrue/swaggy-jenkins

max_issues_repo_name: PankTrue/swaggy-jenkins

max_forks_repo_name: PankTrue/swaggy-jenkins


text:
#ifndef CTS_CMD_REGISTRY_HPP_
#define CTS_CMD_REGISTRY_HPP_
//============================================================================
// Name        :
// Author      : Avi
// Revision    : $Revision: #5 $
//
// Copyright 2009- ECMWF.
// This software is licensed under the terms of the Apache Licence version 2.0
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
// In applying this licence, ECMWF does not waive the privileges and immunities
// granted to it by virtue of its status as an intergovernmental organisation
// nor does it submit to any jurisdiction.
//
// Description : Registration of all the client to server commands
//               This allows us to parse the arg associated with
//               commands in this category. The idea being to keep
//               new commands functionality in one place.
//               Any new client to server commands that are created
//               must be added to this class.
//============================================================================

#include <boost/program_options.hpp>
#include <vector>
#include "Cmd.hpp"

class AbstractClientEnv;

class CtsCmdRegistry {
public:
   CtsCmdRegistry(const CtsCmdRegistry&) = delete;
   const CtsCmdRegistry& operator=(const CtsCmdRegistry&) = delete;

   explicit CtsCmdRegistry(bool addGroupCmd = true );

	/// These option describe the arguments for each of the commands
	/// They also can be presented to the user via --help option.
	void addAllOptions(boost::program_options::options_description& desc) const;
	void addCmdOptions(boost::program_options::options_description& desc) const;

	/// Parse arguments given in 'vm' and use that to create a command
	/// that will be sent to the server. Will throw std::runtime_error for errors
	/// Returns true if command line argument specified via 'vm', matches one of the
	/// registered command.
	/// *** This allows us to distinguish between where we match with a registered
	/// *** command, but do *NOT* set Cmd_ptr, ie since its a client specific command
	/// *** i.e there is no need to send it to the server
	bool parse( Cmd_ptr& cmd,
				   boost::program_options::variables_map& vm,
				   AbstractClientEnv* clientEnv ) const;

private:
	std::vector<Cmd_ptr > vec_;

	void addHelpOption(boost::program_options::options_description& desc) const;
};

#endif

max_stars_repo_name: mpartio/ecflow

max_issues_repo_name: mpartio/ecflow

max_forks_repo_name: mpartio/ecflow


text:
#ifndef __ICP_HPP__
#define __ICP_HPP__

#include <Eigen/Geometry>
#include <vector>
#include <cvx/util/geometry/kdtree.hpp>

// simple ICP point-to-point alignment class

class ICPAligner {
public:

    using point_list_t = cvx::util::PointList3f ;

    struct Parameters {
        float inlier_distance_threshold_ ;
        float inlier_threshold_update_factor_ ;
        uint max_iterations_ ;
        uint min_inliers_ ;
        float epsilon_ ;     // difference in squared distance error to stop iterations

        Parameters():
            inlier_distance_threshold_(0.05),
            max_iterations_(10),
            epsilon_(1.0e-10),
            min_inliers_(3),
            inlier_threshold_update_factor_(3)
        {}

    } ;

    ICPAligner(const Parameters &params): params_(params) {}
    ICPAligner() {}

    // Point cloud alignment with ICP. Variable target is the static cloud and src is the moving cloud. Variable pose should be initialized
    // with the initial transform

    float align(const point_list_t &target, const point_list_t &src, Eigen::Isometry3f &pose, uint &n_inliers) {
        cvx::util::KDTree3 tree(target) ;
        return align(tree, target, src, pose, n_inliers) ;
    }

    // usefull when one needs to do several alignments to the same model
    float align(cvx::util::KDTree3 &stree, const point_list_t &target, const point_list_t &src, Eigen::Isometry3f &pose,
                uint &n_inliers) ;

private:

    Parameters params_ ;
};

#endif

max_stars_repo_name: malasiot/crf

max_issues_repo_name: malasiot/crf

max_forks_repo_name: malasiot/crf


text:
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// test_shared_ptr.cpp

// (C) Copyright 2002 Robert Ramey- http://www.rrsd.com - David Tonge  .
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//  See http://www.boost.org for updates, documentation, and revision history.

#include <cstddef> // NULL
#include <cstdio> // remove
#include <fstream>

#include <boost/config.hpp>
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std{
    using ::remove;
}
#endif

#include <serialization/nvp.hpp>
#include <serialization/export.hpp>
#include <serialization/shared_ptr.hpp>
#include <serialization/weak_ptr.hpp>

#include <I3Test.h>

namespace{
// This is a simple class.  It contains a counter of the number
// of objects of this class which have been instantiated.
class A{
private:
    friend class icecube::serialization::access;
    int x;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar & I3_SERIALIZATION_NVP(x);
    }
    A(A const & rhs);
    A& operator=(A const& rhs);
public:
    static int count;
    bool operator==(const A& rhs) const {
        return x == rhs.x;
    }
    A(){++count;}    // default constructor
    A(int x):x(x){++count;}
    virtual ~A(){--count;}   // destructor
};

int A::count = 0;
}

I3_SERIALIZATION_SHARED_PTR(A)

namespace{
// B is a subclass of A
class B : public A
{
private:
    friend class icecube::serialization::access;
    int y;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar & I3_SERIALIZATION_BASE_OBJECT_NVP(A);
        ar & I3_SERIALIZATION_NVP(y);
    }
public:
    static int count;
    B(){};
    B(int x):A(x){};
    virtual ~B() {};
};
}

// B needs to be exported because its serialized via a base class pointer
I3_CLASS_EXPORT(B)
I3_SERIALIZATION_SHARED_PTR(B)

namespace{
// test a non-polymorphic class
class C
{
private:
    friend class icecube::serialization::access;
    int z;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar & I3_SERIALIZATION_NVP(z);
    }
public:
    static int count;
    bool operator==(const C& rhs) const {
        return z == rhs.z;
    }
    C() :
        z(++count)    // default constructor
    {}
    virtual ~C(){--count;}   // destructor
};

int C::count = 0;
}

I3_CLASS_EXPORT(C)
I3_SERIALIZATION_SHARED_PTR(C)

template<typename TS /*test settings*/, class SP>
void save(const char* testfile, const SP& spa)
{
    typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
    typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
    oa << I3_SERIALIZATION_NVP(spa);
}

template<typename TS /*test settings*/, class SP>
void load(const char* testfile, SP& spa)
{
    typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
    typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
    ia >> I3_SERIALIZATION_NVP(spa);
}

// trivial test
template<typename TS /*test settings*/, class SP>
void save_and_load(SP& spa)
{
    auto testfile = I3Test::testfile("shared_ptr_save_and_load");
    save<TS>(testfile.c_str(), spa);
    SP spa1;
    load<TS>(testfile.c_str(), spa1);

    ENSURE(
        (spa.get() == NULL && spa1.get() == NULL)
        || *spa == *spa1
        );
    std::remove(testfile.c_str());
}

template<typename TS /*test settings*/, class SP>
void save2(
    const char* testfile,
    const SP& first,
    const SP& second
){
    typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
    typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
    oa << I3_SERIALIZATION_NVP(first);
    oa << I3_SERIALIZATION_NVP(second);
}

template<typename TS /*test settings*/, class SP>
void load2(
    const char* testfile,
    SP& first,
    SP& second)
{
    typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
    typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
    ia >> I3_SERIALIZATION_NVP(first);
    ia >> I3_SERIALIZATION_NVP(second);
}

// Run tests by serializing two shared_ptrs into an archive,
// clearing them (deleting the objects) and then reloading the
// objects back from an archive.
template<typename TS /*test settings*/, class SP>
void save_and_load2(SP & first, SP & second)
{
    auto testfile = I3Test::testfile("shared_ptr_save_and_load2");

    save2<TS>(testfile.c_str(), first, second);

    // Clear the pointers, thereby destroying the objects they contain
    first.reset();
    second.reset();

    load2<TS>(testfile.c_str(), first, second);

    ENSURE(first == second);
    std::remove(testfile.c_str());
}

template<typename TS /*test settings*/, class SP, class WP>
void save3(
    const char* testfile,
    SP& first,
    SP& second,
    WP& third
){
    typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
    typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
    oa << I3_SERIALIZATION_NVP(third);
    oa << I3_SERIALIZATION_NVP(first);
    oa << I3_SERIALIZATION_NVP(second);
}

template<typename TS /*test settings*/, class SP, class WP>
void load3(
    const char* testfile,
    SP& first,
    SP& second,
    WP& third
){
    typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
    typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
    // note that we serialize the weak pointer first
    ia >> I3_SERIALIZATION_NVP(third);
    // in order to test that a temporarily solitary weak pointer
    // correctly restored.
    ia >> I3_SERIALIZATION_NVP(first);
    ia >> I3_SERIALIZATION_NVP(second);
}

template<typename TS /*test settings*/, class SP, class WP>
void save_and_load3(
    SP& first,
    SP& second,
    WP& third
){
    auto testfile = I3Test::testfile("shared_ptr_save_and_load3");

    save3<TS>(testfile.c_str(), first, second, third);

    // Clear the pointers, thereby destroying the objects they contain
    first.reset();
    second.reset();
    third.reset();

    load3<TS>(testfile.c_str(), first, second, third);

    ENSURE(first == second);
    ENSURE(first == third.lock());
    std::remove(testfile.c_str());
}

template<typename TS /*test settings*/, class SP>
void save4(const char* testfile, const SP& spc)
{
    typename TS::test_ostream os(testfile, TS::TEST_STREAM_FLAGS);
    typename TS::test_oarchive oa(os, TS::TEST_ARCHIVE_FLAGS);
    oa << I3_SERIALIZATION_NVP(spc);
}

template<typename TS /*test settings*/, class SP>
void load4(const char* testfile, SP& spc)
{
    typename TS::test_istream is(testfile, TS::TEST_STREAM_FLAGS);
    typename TS::test_iarchive ia(is, TS::TEST_ARCHIVE_FLAGS);
    ia >> I3_SERIALIZATION_NVP(spc);
}

// trivial test
template<typename TS /*test settings*/, class SP>
void save_and_load4(SP & spc)
{
    auto testfile = I3Test::testfile("shared_ptr_save_and_load4");
    save4<TS>(testfile.c_str(), spc);
    SP spc1;
    load4<TS>(testfile.c_str(), spc1);

    ENSURE(
        (spc.get() == NULL && spc1.get() == NULL)
        || *spc == *spc1
    );
    std::remove(testfile.c_str());
}

// This does the tests
template<typename TS /*test settings*/, template<class T> class SPT , template<class T> class WPT >
void test(){
    {
        SPT<A> spa;
        // These are our shared_ptrs
        spa = SPT<A>(new A);
        SPT<A> spa1 = spa;
        spa1 = spa;
    }
    {
        // These are our shared_ptrs
        SPT<A> spa;

        // trivial test 1
        save_and_load<TS>(spa);

        //trivival test 2
        spa = SPT<A>(new A(5));
        save_and_load<TS>(spa);

        // Try to save and load pointers to As
        spa = SPT<A>(new A(17));
        SPT<A> spa1 = spa;
        save_and_load2<TS>(spa, spa1);

        // Try to save and load pointers to Bs
        spa = SPT<A>(new B(-12));
        spa1 = spa;
        save_and_load2<TS>(spa, spa1);

        // test a weak pointer
        spa = SPT<A>(new A(2));
        spa1 = spa;
        WPT<A> wp = spa;
        save_and_load3<TS>(spa, spa1, wp);

        // obj of type B gets destroyed
        // as smart_ptr goes out of scope
    }
    ENSURE(A::count == 0);
    {
        // Try to save and load pointers to Cs
        SPT<C> spc;
        spc = SPT<C>(new C);
        save_and_load4<TS>(spc);
    }
    ENSURE(C::count == 0);
}

TEST_GROUP(shared_ptr)

#define TEST_SET(name) \
TEST(name ## _boost_shared_ptr){ \
    test<test_settings, boost::shared_ptr, boost::weak_ptr>(); \
} \
TEST(name ## _std_shared_ptr){ \
    test<test_settings, std::shared_ptr, std::weak_ptr>(); \
}

#define I3_ARCHIVE_TEST binary_archive.hpp
#include "select_archive.hpp"
TEST_SET(binary_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST text_archive.hpp
#include "select_archive.hpp"
TEST_SET(text_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST xml_archive.hpp
#include "select_archive.hpp"
TEST_SET(xml_archive)

#undef I3_ARCHIVE_TEST
#define I3_ARCHIVE_TEST portable_binary_archive.hpp
#include "select_archive.hpp"
TEST_SET(portable_binary_archive)


text:
// This file automatically generated by create_export_module.py
#define NO_IMPORT_ARRAY

#include <NumpyEigenConverter.hpp>

#include <boost/cstdint.hpp>

void import_3_2_double() { NumpyEigenConverter<Eigen::Matrix<double, 3, 2> >::register_converter(); }

max_stars_repo_name: chengfzy/kalibr

max_issues_repo_name: chengfzy/kalibr

max_forks_repo_name: chengfzy/kalibr


text:
/*
 * Software License Agreement (Apache License)
 *
 * Copyright (c) 2018, Southwest Research Institute
 *
 * 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 <descartes_planner/dense_planner.h>
#include <boost/make_shared.hpp>

namespace descartes_planner
{
using namespace descartes_core;
DensePlanner::DensePlanner() : planning_graph_(), error_code_(descartes_core::PlannerError::UNINITIALIZED)
{
  error_map_ = { { PlannerError::OK, "OK" },
                 { PlannerError::EMPTY_PATH, "No path plan has been generated" },
                 { PlannerError::INVALID_ID, "ID is nil or isn't part of the path" },
                 { PlannerError::IK_NOT_AVAILABLE, "One or more ik solutions could not be found" },
                 { PlannerError::UNINITIALIZED, "Planner has not been initialized with a robot model" },
                 { PlannerError::INCOMPLETE_PATH, "Input trajectory and output path point cound differ" } };
}

DensePlanner::~DensePlanner()
{
}

bool DensePlanner::initialize(descartes_core::RobotModelConstPtr model)
{
  planning_graph_ =
      boost::shared_ptr<descartes_planner::PlanningGraph>(new descartes_planner::PlanningGraph(std::move(model)));
  error_code_ = descartes_core::PlannerErrors::EMPTY_PATH;
  return true;
}

bool DensePlanner::initialize(descartes_core::RobotModelConstPtr model,
                              descartes_planner::CostFunction cost_function_callback)
{
  planning_graph_ = boost::shared_ptr<descartes_planner::PlanningGraph>(
      new descartes_planner::PlanningGraph(std::move(model), cost_function_callback));
  error_code_ = descartes_core::PlannerErrors::EMPTY_PATH;
  return true;
}

bool DensePlanner::setConfig(const descartes_core::PlannerConfig& config)
{
  config_ = config;
  config_.clear();
  return true;
}

void DensePlanner::getConfig(descartes_core::PlannerConfig& config) const
{
  config = config_;
}

descartes_core::TrajectoryPt::ID DensePlanner::getPrevious(const descartes_core::TrajectoryPt::ID& ref_id)
{
  descartes_core::TrajectoryPt::ID id;
  auto predicate = [&ref_id](descartes_core::TrajectoryPtPtr p)
  {
    return ref_id == p->getID();
  };

  auto pos = std::find_if(path_.begin()++, path_.end(), predicate);
  if (pos == path_.end())
  {
    id = descartes_core::TrajectoryID::make_nil();
  }
  else
  {
    pos--;
    id = (*pos)->getID();
  }

  return id;
}

bool DensePlanner::updatePath()
{
  double c;
  std::list<descartes_trajectory::JointTrajectoryPt> list;
  if (planning_graph_->getShortestPath(c, list))
  {
    error_code_ = descartes_core::PlannerErrors::OK;
    for (auto&& p : list)
    {
      path_.push_back(boost::make_shared<descartes_trajectory::JointTrajectoryPt>(std::move(p)));
    }
    return true;
  }
  else
  {
    error_code_ = descartes_core::PlannerErrors::UKNOWN;
    return false;
  }
}

descartes_core::TrajectoryPt::ID DensePlanner::getNext(const descartes_core::TrajectoryPt::ID& ref_id)
{
  descartes_core::TrajectoryPt::ID id;
  auto predicate = [&ref_id](descartes_core::TrajectoryPtPtr p)
  {
    return ref_id == p->getID();
  };

  auto pos = std::find_if(path_.begin(), path_.end() - 2, predicate);
  if (pos == path_.end())
  {
    id = descartes_core::TrajectoryID::make_nil();
  }
  else
  {
    pos++;
    id = (*pos)->getID();
  }
  return id;
}

descartes_core::TrajectoryPtPtr DensePlanner::get(const descartes_core::TrajectoryPt::ID& ref_id)
{
  descartes_core::TrajectoryPtPtr p;
  auto predicate = [&ref_id](descartes_core::TrajectoryPtPtr p)
  {
    return ref_id == p->getID();
  };

  auto pos = std::find_if(path_.begin(), path_.end() - 2, predicate);
  if (pos == path_.end())
  {
    p.reset();
  }
  else
  {
    p = *pos;
  }
  return p;
}

bool DensePlanner::planPath(const std::vector<descartes_core::TrajectoryPtPtr>& traj)
{
  if (error_code_ == descartes_core::PlannerError::UNINITIALIZED)
  {
    ROS_ERROR_STREAM("Planner has not been initialized");
    return false;
  }

  path_.clear();
  error_code_ = descartes_core::PlannerError::EMPTY_PATH;

  if (planning_graph_->insertGraph(traj))
  {
    updatePath();
  }
  else
  {
    error_code_ = descartes_core::PlannerError::IK_NOT_AVAILABLE;
  }

  return descartes_core::PlannerError::OK == error_code_;
}

bool DensePlanner::getPath(std::vector<descartes_core::TrajectoryPtPtr>& path) const
{
  if (path_.empty())
    return false;

  path.assign(path_.begin(), path_.end());
  return error_code_ == descartes_core::PlannerError::OK;
}

bool DensePlanner::addAfter(const descartes_core::TrajectoryPt::ID& ref_id, descartes_core::TrajectoryPtPtr tp)
{
  if (path_.empty())
  {
    return false;
  }

  descartes_core::TrajectoryPt::ID next_id = getNext(ref_id);
  if (!next_id.is_nil())
  {
    if (planning_graph_->addTrajectory(tp, ref_id, next_id))
    {
      if (updatePath())
      {
        error_code_ = descartes_core::PlannerError::OK;
      }
      else
      {
        return false;
      }
    }
    else
    {
      error_code_ = descartes_core::PlannerErrors::IK_NOT_AVAILABLE;
      return false;
    }
  }
  else
  {
    error_code_ = descartes_core::PlannerError::INVALID_ID;
    return false;
  }

  return true;
}

bool DensePlanner::addBefore(const descartes_core::TrajectoryPt::ID& ref_id, descartes_core::TrajectoryPtPtr tp)
{
  if (path_.empty())
  {
    return false;
  }

  descartes_core::TrajectoryPt::ID prev_id = getPrevious(ref_id);
  if (!prev_id.is_nil())
  {
    if (planning_graph_->addTrajectory(tp, prev_id, ref_id))
    {
      if (updatePath())
      {
        error_code_ = descartes_core::PlannerError::OK;
      }
      else
      {
        return false;
      }
    }
    else
    {
      error_code_ = descartes_core::PlannerErrors::IK_NOT_AVAILABLE;
      return false;
    }
  }
  else
  {
    error_code_ = descartes_core::PlannerError::INVALID_ID;
    return false;
  }

  return true;
}

bool DensePlanner::remove(const descartes_core::TrajectoryPt::ID& ref_id)
{
  if (path_.empty())
  {
    return false;
  }

  descartes_core::TrajectoryPtPtr tp = get(ref_id);
  if (tp)
  {
    tp->setID(ref_id);
    if (planning_graph_->removeTrajectory(tp->getID())) // TODO: Clean up this extra copy & lookup
    {
      if (updatePath()) // TODO: Should we force an update here? What if the user wants to remove several points?
      {
        error_code_ = descartes_core::PlannerError::OK;
      }
      else
      {
        return false;
      }
    }
    else
    {
      error_code_ = descartes_core::PlannerErrors::IK_NOT_AVAILABLE;
      return false;
    }
  }
  else
  {
    error_code_ = descartes_core::PlannerError::INVALID_ID;
    return false;
  }

  return true;
}

bool DensePlanner::modify(const descartes_core::TrajectoryPt::ID& ref_id, descartes_core::TrajectoryPtPtr tp)
{
  if (path_.empty())
  {
    return false;
  }

  if (!ref_id.is_nil())
  {
    tp->setID(ref_id);
    if (planning_graph_->modifyTrajectory(tp))
    {
      if (updatePath())
      {
        error_code_ = descartes_core::PlannerError::OK;
      }
      else
      {
        return false;
      }
    }
    else
    {
      error_code_ = descartes_core::PlannerErrors::IK_NOT_AVAILABLE;
      return false;
    }
  }
  else
  {
    error_code_ = descartes_core::PlannerError::INVALID_ID;
    return false;
  }

  return true;
}

int DensePlanner::getErrorCode() const
{
  return error_code_;
}

bool DensePlanner::getErrorMessage(int error_code, std::string& msg) const
{
  std::map<int, std::string>::const_iterator it = error_map_.find(error_code);

  if (it != error_map_.cend())
  {
    msg = it->second;
  }
  else
  {
    return false;
  }
  return true;
}

} /* namespace descartes_core */

max_stars_repo_name: jrgnicho/descartes

max_issues_repo_name: jrgnicho/descartes

max_forks_repo_name: jrgnicho/descartes