<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#if !defined( STANDALONE )
#include "condor_common.h"
#include "condor_config.h"
#include "condor_classad.h"
#else
#include <ctype.h>
#include "classad_package.h"
using namespace classad;
#endif

enum Commands {
	_NO_CMD_,

	CLEAR_TOPLEVEL,
	DEEP_INSERT_ATTRIBUTE,
	DEEP_DELETE_ATTRIBUTE,
	EVALUATE,
	EVALUATE_WITH_SIGNIFICANCE,
	FLATTEN,
	HELP,
	INSERT_ATTRIBUTE,
	NEW_TOPLEVEL,
	OUTPUT_TOPLEVEL,
#if !defined( STANDALONE )
	PARAM,
#endif
	QUIT,
	REMOVE_ATTRIBUTE,
	SET_MATCH_TOPLEVEL,

	_LAST_COMMAND_
};

char CommandWords[][32] = {
	"",

	"clear_toplevel",
	"deep_insert",
	"deep_delete",
	"evaluate",
	"sigeval",
	"flatten",
	"help",
	"insert_attribute",
	"new_toplevel",
	"output_toplevel",
#if !defined( STANDALONE )
	"param",
#endif
	"quit",
	"delete_attribute",
	"set_match_toplevel",

	""
};

void help( void );
int  findCommand( char* );

int
main( void )
{
	ClassAd 		*ad, *adptr;
	char 			cmdString[128],buffer1[20480],buffer2[20480],buffer3[20480];
#if !defined( STANDALONE )
	char			*paramStr, *attrName;
#endif
	ExprTree		*expr=NULL, *fexpr=NULL;
	int 			command;
	Value			value;
	ClassAdParser	parser;
	ClassAdUnParser	unparser;
	string			output;
	FormatOptions	pp;

		// set formatter options
	pp.SetClassAdIndentation( true , 4 );
	pp.SetListIndentation( true , 4 );

#if !defined( STANDALONE )
	config( 0 );
#endif

	ad = new ClassAd();

	printf( "'h' for help\n# " );
	while( 1 ) {
		scanf( "%s", cmdString );
		command = findCommand( cmdString );
		switch( command ) {
			case CLEAR_TOPLEVEL:
				ad->Clear();
				fgets( buffer1, 2048, stdin );
				break;

			case DEEP_INSERT_ATTRIBUTE:
				if( scanf( "%s", buffer1 ) != 1 ) {	// expr
					printf( "Error reading primary expression\n" );
					break;
				}
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				if( scanf( "%s", buffer2 ) != 1 ) {
					printf( "Error reading attribute name\n" );
					break;
				}
				fgets( buffer3, 2048, stdin );
				if( !parser.ParseExpression( buffer3, fexpr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer3 );
					break;
				}
				expr->SetParentScope( ad );
				if( !ad->EvaluateExpr( expr, value ) ) {
					printf( "Error evaluating expression: %s\n", buffer1 );
					delete expr;
					delete fexpr;
					expr = NULL;
					fexpr = NULL;
					break;
				}
				if( !value.IsClassAdValue( adptr ) ) {
					printf( "Error:  Primary expression was not a classad\n" );
					delete expr;
					expr = NULL;
					delete fexpr;
					fexpr = NULL;
					break;
				}
				if( !adptr->Insert( buffer2, fexpr ) ) {
					printf( "Error Inserting expression: %s\n", buffer3 );
					delete fexpr;
					delete expr;
					fexpr = NULL;
					expr = NULL;
				}
				delete expr;
				adptr = NULL;
				expr  = NULL;
				break;

			case DEEP_DELETE_ATTRIBUTE:
				if( scanf( "%s", buffer1 ) != 1 ) { // expr
					printf( "Error reading primary expression\n" );
					break;
				}
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				fgets( buffer2, 2048, stdin ); // name
				expr->SetParentScope( ad );
				if( !ad->EvaluateExpr( expr, value ) ) {
					printf( "Error evaluating expression: %s\n", buffer1 );
					delete expr;
					break;
				}
				if( !value.IsClassAdValue( adptr ) ) {
					printf( "Error:  Primary expression was not a classad\n" );
					delete expr;
					expr = NULL;
					break;
				}
				if( !adptr->Remove( buffer2 ) ) {
					printf( "Warning:  Attribute %s not found\n", buffer2 );
				}
				delete expr;
				expr = NULL;
				break;

			case EVALUATE:
				fgets( buffer1, 2048, stdin );
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				expr->SetParentScope( ad );
				if( !ad->EvaluateExpr( expr, value ) ) {
					printf( "Error evaluating expression: %s\n", buffer1 );
					delete expr;
					expr = NULL;
					break;
				}
				output = "";
				unparser.Unparse( output, value );
				printf( "%s\n", output.c_str( ) );
				delete expr;
				expr = NULL;
				break;

			case EVALUATE_WITH_SIGNIFICANCE:
				fgets( buffer1, 2048, stdin );
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				expr->SetParentScope( ad );
				if( !ad->EvaluateExpr( expr, value, fexpr ) ) {
					printf( "Error evaluating expression: %s\n", buffer1 );
					delete expr;
					delete fexpr;
					expr = NULL;
					fexpr = NULL;
					break;
				}
				output = "";
				unparser.Unparse( output, value );
				printf( "%s\n", output.c_str( ) );
				output = "";
				unparser.Unparse( output, fexpr );
				printf( "%s\n", output.c_str( ) );
				delete expr;
				expr = NULL;
				delete fexpr;
				fexpr = NULL;
				break;

			case FLATTEN:
				fgets( buffer1, 2048, stdin );
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				expr->SetParentScope( ad );
				if( ad->Flatten( expr, value, fexpr ) ) {
					if( fexpr ) {
						output = "";
						unparser.Unparse( output, fexpr );
						printf( "%s\n", output.c_str( ) );
						delete fexpr;
						fexpr = NULL;
					} else {
						output = "";
						unparser.Unparse( output, value );
						printf( "%s\n", output.c_str( ) );
					}
				} else {
					printf( "Error flattening expression\n" );
				}
				delete expr;
				expr = NULL;
				break;

			case HELP:
				help();
				fgets( buffer1, 2048, stdin );
				break;

			case INSERT_ATTRIBUTE:
				if( scanf( "%s", buffer1 ) != 1 ) {
					printf( "Error reading attribute name\n" );
					break;
				}
				fgets( buffer2, 2048, stdin );
				if( !parser.ParseExpression( buffer2, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer2 );
					break;
				}
				if( !ad->Insert( buffer1, expr ) ) {
					printf( "Error Inserting expression\n" );
				}
				expr = NULL;
				break;

			case NEW_TOPLEVEL:
				ad->Clear();
				fgets( buffer1, 2048, stdin );
				if( !( ad = parser.ParseClassAd( buffer1, true ) ) ) {
					printf( "Error parsing classad\n" );
				}
				break;

			case OUTPUT_TOPLEVEL:
				output = "";
				unparser.Unparse( output, ad );
				printf( "%s\n", output.c_str( ) );
				fgets( buffer1, 2048, stdin );
				break;

#if !defined( STANDALONE )
			case PARAM:
				fgets( buffer1, 2048, stdin );
				attrName = strtok( buffer1, " \t\n" );
				if( !( paramStr = param( attrName ) ) ) {
					printf( "Did not find %s in config file\n", buffer1 );
					break;
				}
				if( !parser.ParseExpression( paramStr, expr, true ) ) {
					printf( "Error parsing expression: %s\n", paramStr );
					free( paramStr );
					break;
				}
				if( !ad->Insert( attrName, expr ) ) {
					printf( "Error Inserting: %s = %s\n", buffer1, paramStr );
				}
				free( paramStr );
				expr = NULL;
				break;
#endif

			case QUIT:
				printf( "Done\n\n" );
				exit( 0 );

			case REMOVE_ATTRIBUTE:
				if( scanf( "%s", buffer1 ) != 1 ) {
					printf( "Error reading attribute name\n" );
					break;
				}
				if( !ad->Remove( buffer1 ) ) {
					printf( "Error removing attribute %s\n", buffer1 );
				}
				fgets( buffer1, 2048, stdin );
				break;

			case SET_MATCH_TOPLEVEL:
				delete ad;
				if( !( ad = MatchClassAd::MakeMatchClassAd( NULL, NULL ) ) ){
					printf( "Error making classad\n" );
				}
				fgets( buffer1, 2048, stdin );
				break;

			default:
				fflush( stdin );
		}

		printf( "\n# " );
	}

	exit( 0 );
}

// Print help information for the hapless user
void
help( void )
{
	printf( "\nCommands are:\n" );
	printf( "clear_toplevel\n\tClear toplevel ad\n\n" );
	printf( "deep_insert <expr1> <name> <expr2>\n\tInsert (<name>,<expr2>) into"
		" classad <expr1>. (No inter-token spaces\n\tallowed in <expr1>.)\n\n");
	printf( "deep_delete <expr> <name>\n\tDelete <name> from classad "
		"<expr>. (No inter-token spaces allowed\n\tin <expr>.\n\n" );
	printf( "evaluate <expr>\n\tEvaluate <expr> (in toplevel ad)\n\n" );
	printf( "sigeval <expr>\n\tEvaluate <expr> (in toplevel) and "
		"identify significant\n\tsubexpressions\n\n" );
	printf( "flatten <expr>\n\tFlatten <expr> (in toplevel ad)\n\n" );
	printf( "help\n\tHelp --- this screen\n\n" );
	printf( "insert_attribute <name> <expr>\n\tInsert attribute (<name>,<expr>)"
		"into toplevel\n\n" );
	printf( "new_toplevel <classad>\n\tEnter new toplevel ad\n\n" );
	printf( "output_toplevel\n\tOutput toplevel ad\n\n" );
#if !defined( STANDALONE )
	printf("param <name>\n\tParam from config file and insert in toplevel\n\n");
#endif
	printf( "quit\n\tQuit\n\n" );
	printf( "delete_attribute <name>\n\tDelete attribute <name> from "
		"toplevel\n\n" );
	printf( "set_condor_toplevel\n\tSetup a toplevel ad for matching\n\n" );
	printf( "\nA command may be specified by an unambiguous prefix\n\n" );
}

int
findCommand( char *cmdStr )
{
	int cmd = 0, len = strlen( cmdStr );

	for( int i = 0 ; i < len ; i++ ) {
		cmdStr[i] = tolower( cmdStr[i] );
	}

	for( int i = _NO_CMD_+1 ; i < _LAST_COMMAND_ ; i++ ) {
		if( strncmp( cmdStr, CommandWords[i], len ) == 0 ) {
			if( cmd == 0 ) {
				cmd = i;
			} else if( cmd > 0 ) {
				cmd = -1;
			}
		}
	}

	if( cmd > 0 ) return cmd;

	if( cmd == 0 ) {
		printf( "\nUnknown command %s\n", cmdStr );
		return -1;
	}

	printf( "\nAmbiguous command %s; matches\n", cmdStr );
	for( int i = _NO_CMD_+1 ; i < _LAST_COMMAND_ ; i++ ) {
		if( strncmp( cmdStr, CommandWords[i], len ) == 0 ) {
			printf( "\t%s\n", CommandWords[i] );
		}
	}
	return -1;
}
<commit_msg>Dumped obsolete FormatOptions; using PrettyPrint object instead<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#if !defined( STANDALONE )
#include "condor_common.h"
#include "condor_config.h"
#include "condor_classad.h"
#else
#include <ctype.h>
#include "classad_package.h"
using namespace classad;
#endif

enum Commands {
	_NO_CMD_,

	CLEAR_TOPLEVEL,
	DEEP_INSERT_ATTRIBUTE,
	DEEP_DELETE_ATTRIBUTE,
	EVALUATE,
	EVALUATE_WITH_SIGNIFICANCE,
	FLATTEN,
	HELP,
	INSERT_ATTRIBUTE,
	NEW_TOPLEVEL,
	OUTPUT_TOPLEVEL,
#if !defined( STANDALONE )
	PARAM,
#endif
	QUIT,
	REMOVE_ATTRIBUTE,
	SET_MATCH_TOPLEVEL,

	_LAST_COMMAND_
};

char CommandWords[][32] = {
	"",

	"clear_toplevel",
	"deep_insert",
	"deep_delete",
	"evaluate",
	"sigeval",
	"flatten",
	"help",
	"insert_attribute",
	"new_toplevel",
	"output_toplevel",
#if !defined( STANDALONE )
	"param",
#endif
	"quit",
	"delete_attribute",
	"set_match_toplevel",

	""
};

void help( void );
int  findCommand( char* );

int
main( void )
{
	ClassAd 		*ad, *adptr;
	char 			cmdString[128],buffer1[20480],buffer2[20480],buffer3[20480];
#if !defined( STANDALONE )
	char			*paramStr, *attrName;
#endif
	ExprTree		*expr=NULL, *fexpr=NULL;
	int 			command;
	Value			value;
	ClassAdParser	parser;
	PrettyPrint		unparser;
	string			output;

#if !defined( STANDALONE )
	config( 0 );
#endif

	ad = new ClassAd();

	printf( "'h' for help\n# " );
	while( 1 ) {
		scanf( "%s", cmdString );
		command = findCommand( cmdString );
		switch( command ) {
			case CLEAR_TOPLEVEL:
				ad->Clear();
				fgets( buffer1, 2048, stdin );
				break;

			case DEEP_INSERT_ATTRIBUTE:
				if( scanf( "%s", buffer1 ) != 1 ) {	// expr
					printf( "Error reading primary expression\n" );
					break;
				}
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				if( scanf( "%s", buffer2 ) != 1 ) {
					printf( "Error reading attribute name\n" );
					break;
				}
				fgets( buffer3, 2048, stdin );
				if( !parser.ParseExpression( buffer3, fexpr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer3 );
					break;
				}
				expr->SetParentScope( ad );
				if( !ad->EvaluateExpr( expr, value ) ) {
					printf( "Error evaluating expression: %s\n", buffer1 );
					delete expr;
					delete fexpr;
					expr = NULL;
					fexpr = NULL;
					break;
				}
				if( !value.IsClassAdValue( adptr ) ) {
					printf( "Error:  Primary expression was not a classad\n" );
					delete expr;
					expr = NULL;
					delete fexpr;
					fexpr = NULL;
					break;
				}
				if( !adptr->Insert( buffer2, fexpr ) ) {
					printf( "Error Inserting expression: %s\n", buffer3 );
					delete fexpr;
					delete expr;
					fexpr = NULL;
					expr = NULL;
				}
				delete expr;
				adptr = NULL;
				expr  = NULL;
				break;

			case DEEP_DELETE_ATTRIBUTE:
				if( scanf( "%s", buffer1 ) != 1 ) { // expr
					printf( "Error reading primary expression\n" );
					break;
				}
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				fgets( buffer2, 2048, stdin ); // name
				expr->SetParentScope( ad );
				if( !ad->EvaluateExpr( expr, value ) ) {
					printf( "Error evaluating expression: %s\n", buffer1 );
					delete expr;
					break;
				}
				if( !value.IsClassAdValue( adptr ) ) {
					printf( "Error:  Primary expression was not a classad\n" );
					delete expr;
					expr = NULL;
					break;
				}
				if( !adptr->Remove( buffer2 ) ) {
					printf( "Warning:  Attribute %s not found\n", buffer2 );
				}
				delete expr;
				expr = NULL;
				break;

			case EVALUATE:
				fgets( buffer1, 2048, stdin );
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				expr->SetParentScope( ad );
				if( !ad->EvaluateExpr( expr, value ) ) {
					printf( "Error evaluating expression: %s\n", buffer1 );
					delete expr;
					expr = NULL;
					break;
				}
				output = "";
				unparser.Unparse( output, value );
				printf( "%s\n", output.c_str( ) );
				delete expr;
				expr = NULL;
				break;

			case EVALUATE_WITH_SIGNIFICANCE:
				fgets( buffer1, 2048, stdin );
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				expr->SetParentScope( ad );
				if( !ad->EvaluateExpr( expr, value, fexpr ) ) {
					printf( "Error evaluating expression: %s\n", buffer1 );
					delete expr;
					delete fexpr;
					expr = NULL;
					fexpr = NULL;
					break;
				}
				output = "";
				unparser.Unparse( output, value );
				printf( "%s\n", output.c_str( ) );
				output = "";
				unparser.Unparse( output, fexpr );
				printf( "%s\n", output.c_str( ) );
				delete expr;
				expr = NULL;
				delete fexpr;
				fexpr = NULL;
				break;

			case FLATTEN:
				fgets( buffer1, 2048, stdin );
				if( !parser.ParseExpression( buffer1, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer1 );
					break;
				}
				expr->SetParentScope( ad );
				if( ad->Flatten( expr, value, fexpr ) ) {
					if( fexpr ) {
						output = "";
						unparser.Unparse( output, fexpr );
						printf( "%s\n", output.c_str( ) );
						delete fexpr;
						fexpr = NULL;
					} else {
						output = "";
						unparser.Unparse( output, value );
						printf( "%s\n", output.c_str( ) );
					}
				} else {
					printf( "Error flattening expression\n" );
				}
				delete expr;
				expr = NULL;
				break;

			case HELP:
				help();
				fgets( buffer1, 2048, stdin );
				break;

			case INSERT_ATTRIBUTE:
				if( scanf( "%s", buffer1 ) != 1 ) {
					printf( "Error reading attribute name\n" );
					break;
				}
				fgets( buffer2, 2048, stdin );
				if( !parser.ParseExpression( buffer2, expr, true ) ) {
					printf( "Error parsing expression: %s\n", buffer2 );
					break;
				}
				if( !ad->Insert( buffer1, expr ) ) {
					printf( "Error Inserting expression\n" );
				}
				expr = NULL;
				break;

			case NEW_TOPLEVEL:
				ad->Clear();
				fgets( buffer1, 2048, stdin );
				if( !( ad = parser.ParseClassAd( buffer1, true ) ) ) {
					printf( "Error parsing classad\n" );
				}
				break;

			case OUTPUT_TOPLEVEL:
				output = "";
				unparser.Unparse( output, ad );
				printf( "%s\n", output.c_str( ) );
				fgets( buffer1, 2048, stdin );
				break;

#if !defined( STANDALONE )
			case PARAM:
				fgets( buffer1, 2048, stdin );
				attrName = strtok( buffer1, " \t\n" );
				if( !( paramStr = param( attrName ) ) ) {
					printf( "Did not find %s in config file\n", buffer1 );
					break;
				}
				if( !parser.ParseExpression( paramStr, expr, true ) ) {
					printf( "Error parsing expression: %s\n", paramStr );
					free( paramStr );
					break;
				}
				if( !ad->Insert( attrName, expr ) ) {
					printf( "Error Inserting: %s = %s\n", buffer1, paramStr );
				}
				free( paramStr );
				expr = NULL;
				break;
#endif

			case QUIT:
				printf( "Done\n\n" );
				exit( 0 );

			case REMOVE_ATTRIBUTE:
				if( scanf( "%s", buffer1 ) != 1 ) {
					printf( "Error reading attribute name\n" );
					break;
				}
				if( !ad->Remove( buffer1 ) ) {
					printf( "Error removing attribute %s\n", buffer1 );
				}
				fgets( buffer1, 2048, stdin );
				break;

			case SET_MATCH_TOPLEVEL:
				delete ad;
				if( !( ad = MatchClassAd::MakeMatchClassAd( NULL, NULL ) ) ){
					printf( "Error making classad\n" );
				}
				fgets( buffer1, 2048, stdin );
				break;

			default:
				fflush( stdin );
		}

		printf( "\n# " );
	}

	exit( 0 );
}

// Print help information for the hapless user
void
help( void )
{
	printf( "\nCommands are:\n" );
	printf( "clear_toplevel\n\tClear toplevel ad\n\n" );
	printf( "deep_insert <expr1> <name> <expr2>\n\tInsert (<name>,<expr2>) into"
		" classad <expr1>. (No inter-token spaces\n\tallowed in <expr1>.)\n\n");
	printf( "deep_delete <expr> <name>\n\tDelete <name> from classad "
		"<expr>. (No inter-token spaces allowed\n\tin <expr>.\n\n" );
	printf( "evaluate <expr>\n\tEvaluate <expr> (in toplevel ad)\n\n" );
	printf( "sigeval <expr>\n\tEvaluate <expr> (in toplevel) and "
		"identify significant\n\tsubexpressions\n\n" );
	printf( "flatten <expr>\n\tFlatten <expr> (in toplevel ad)\n\n" );
	printf( "help\n\tHelp --- this screen\n\n" );
	printf( "insert_attribute <name> <expr>\n\tInsert attribute (<name>,<expr>)"
		"into toplevel\n\n" );
	printf( "new_toplevel <classad>\n\tEnter new toplevel ad\n\n" );
	printf( "output_toplevel\n\tOutput toplevel ad\n\n" );
#if !defined( STANDALONE )
	printf("param <name>\n\tParam from config file and insert in toplevel\n\n");
#endif
	printf( "quit\n\tQuit\n\n" );
	printf( "delete_attribute <name>\n\tDelete attribute <name> from "
		"toplevel\n\n" );
	printf( "set_condor_toplevel\n\tSetup a toplevel ad for matching\n\n" );
	printf( "\nA command may be specified by an unambiguous prefix\n\n" );
}

int
findCommand( char *cmdStr )
{
	int cmd = 0, len = strlen( cmdStr );

	for( int i = 0 ; i < len ; i++ ) {
		cmdStr[i] = tolower( cmdStr[i] );
	}

	for( int i = _NO_CMD_+1 ; i < _LAST_COMMAND_ ; i++ ) {
		if( strncmp( cmdStr, CommandWords[i], len ) == 0 ) {
			if( cmd == 0 ) {
				cmd = i;
			} else if( cmd > 0 ) {
				cmd = -1;
			}
		}
	}

	if( cmd > 0 ) return cmd;

	if( cmd == 0 ) {
		printf( "\nUnknown command %s\n", cmdStr );
		return -1;
	}

	printf( "\nAmbiguous command %s; matches\n", cmdStr );
	for( int i = _NO_CMD_+1 ; i < _LAST_COMMAND_ ; i++ ) {
		if( strncmp( cmdStr, CommandWords[i], len ) == 0 ) {
			printf( "\t%s\n", CommandWords[i] );
		}
	}
	return -1;
}
<|endoftext|>


<commit_before>#include "CFunctions.h"
#include "include/ILuaModuleManager.h"
#include "extra/CLuaArguments.h"

#include <pathfind/Graph.h>
#include "Module.h"
#include "Utils.h"

#ifndef _WIN32
	#include <sys/stat.h>
#endif

int CFunctions::LoadPathGraph(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TSTRING)
	{
		pModuleManager->ErrorPrintf("Bad argument @ loadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Build graph path
	char buf[300];
	if (!pModuleManager->GetResourceFilePath(luaVM, lua_tostring(luaVM, 1), buf, sizeof(buf)))
	{
		pModuleManager->ErrorPrintf("File does not exist @ loadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Check if path is valid
	std::string path{ buf };
	if (path.find("..") != std::string::npos)
	{
		pModuleManager->ErrorPrintf("Bad path @ loadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Load graph
	GraphId graphId = g_Module->LoadGraph(path);
	lua_pushnumber(luaVM, graphId);

	return 1;
}

int CFunctions::UnloadPathGraph(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TNUMBER) {
		pModuleManager->ErrorPrintf("Bad argument @ unloadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Check if graph has been loaded
	GraphId graphId = (GraphId)lua_tonumber(luaVM, 1);
	if (g_Module->GetGraph(graphId) == nullptr) {
		pModuleManager->ErrorPrintf("Bad graph @ unloadPathGraph, cannot unload\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	g_Module->UnloadGraph(graphId);
	lua_pushboolean(luaVM, true);
	return 1;
}

int CFunctions::FindShortestPathBetween(lua_State* luaVM)
{
	// bool findShortestPathBetween(int graphId, float startX, float startY, float startZ, float endX, float endY, float endZ, function callback)
	if (lua_type(luaVM, 1) != LUA_TNUMBER || lua_type(luaVM, 2) != LUA_TNUMBER || lua_type(luaVM, 3) != LUA_TNUMBER || lua_type(luaVM, 4) != LUA_TNUMBER ||
		lua_type(luaVM, 5) != LUA_TNUMBER || lua_type(luaVM, 6) != LUA_TNUMBER || lua_type(luaVM, 7) != LUA_TNUMBER ||
		lua_type(luaVM, 8) != LUA_TFUNCTION)
	{
		pModuleManager->ErrorPrintf("Bad argument @ findShortestPathBetween\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Check if graph has been loaded
	GraphId graphId = (GraphId)lua_tonumber(luaVM, 1);
	if (g_Module->GetGraph(graphId) == nullptr)
	{
		pModuleManager->ErrorPrintf("No graph loaded @ findShortestPathBetween\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Make vectors from Lua primitives
	Vector3 from((float)lua_tonumber(luaVM, 1), (float)lua_tonumber(luaVM, 2), (float)lua_tonumber(luaVM, 3));
	Vector3 to((float)lua_tonumber(luaVM, 4), (float)lua_tonumber(luaVM, 5), (float)lua_tonumber(luaVM, 6));

	// Save reference of the Lua callback function
	// See: http://lua-users.org/lists/lua-l/2008-12/msg00193.html
	lua_pushvalue(luaVM, -1);
	int funcRef = luaL_ref(luaVM, LUA_REGISTRYINDEX);

	g_Module->GetJobManager().PushTask([from, to, graphId]() {

		// Prepare information we need to pass to A*
		pathfind::AStar algorithm(g_Module->GetGraph(graphId), from, to);

		// Run A*
		return algorithm.CalculateShortestPath();

	}, [luaVM = lua_getmainstate(luaVM), funcRef](const pathfind::AStarResult& result) {

		// Validate LuaVM (use ResourceStart/-Stop to manage valid lua states)
		if (!g_Module->HasLuaVM(luaVM))
			return;

		// Push stored reference to callback function to the stack
		lua_rawgeti(luaVM, LUA_REGISTRYINDEX, funcRef);

		// Push arguments to the stack
		lua_newtable(luaVM);
		std::size_t index = 0;

		for (pathfind::GraphNode* node : result)
		{
			// Set table index
			lua_pushnumber(luaVM, ++index);

			// Create a table containing the vector components
			lua_newtable(luaVM);

			lua_pushnumber(luaVM, 1);
			lua_pushnumber(luaVM, node->position.GetX());
			lua_settable(luaVM, -3);

			lua_pushnumber(luaVM, 2);
			lua_pushnumber(luaVM, node->position.GetY());
			lua_settable(luaVM, -3);

			lua_pushnumber(luaVM, 3);
			lua_pushnumber(luaVM, node->position.GetZ());
			lua_settable(luaVM, -3);

			// Add vector table to result table
			lua_settable(luaVM, -3);
		}

		// Finally, call the function
		int err = lua_pcall(luaVM, 1, 0, 0);
		if (err != 0)
			pModuleManager->ErrorPrintf("%s\n", lua_tostring(luaVM, -1));

	});

	lua_pushboolean(luaVM, true);
	return 1;
}

int CFunctions::IsGraphLoaded(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TNUMBER) {
		pModuleManager->ErrorPrintf("Bad argument @ unloadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	GraphId graphId = (GraphId) lua_tonumber(luaVM, 1);
	lua_pushboolean(luaVM, g_Module->GetGraph(graphId) != nullptr);
	return 1;
}

int CFunctions::FindNodeAt(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TNUMBER || lua_type(luaVM, 2) != LUA_TNUMBER || lua_type(luaVM, 3) != LUA_TNUMBER || lua_type(luaVM, 4) != LUA_TNUMBER)
	{
		pModuleManager->ErrorPrintf("Bad argument @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	GraphId graphId = (GraphId)lua_tonumber(luaVM, 1);
	if (g_Module->GetGraph(graphId) == nullptr) {
		pModuleManager->ErrorPrintf("Bad graph @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	Vector3 position((float)lua_tonumber(luaVM, 2), (float)lua_tonumber(luaVM, 3), (float)lua_tonumber(luaVM, 4));
	pathfind::GraphNode* node = g_Module->GetGraph(graphId)->FindClosestNodeTo(position);
	if (!node) {
		lua_pushboolean(luaVM, false);
		return 1;
	}

	lua_pushnumber(luaVM, node->id);
	lua_pushnumber(luaVM, node->position.GetX());
	lua_pushnumber(luaVM, node->position.GetY());
	lua_pushnumber(luaVM, node->position.GetZ());

	return 4;
}

int CFunctions::GetNodeNeighbors(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TNUMBER || lua_type(luaVM, 2) != LUA_TNUMBER || lua_type(luaVM, 3) != LUA_TNUMBER)
	{
		pModuleManager->ErrorPrintf("Bad argument @ getNodeNeighbors\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	pathfind::Graph* graph = g_Module->GetGraph((GraphId)lua_tonumber(luaVM, 1));
	if (graph == nullptr) {
		pModuleManager->ErrorPrintf("Bad graph @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	int nodeId = (int)lua_tonumber(luaVM, 2);
	if (nodeId < 0) {
		pModuleManager->ErrorPrintf("Invalid NodeId @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	pathfind::GraphNode* node = graph->GetNode(static_cast<unsigned int>(nodeId));
	if (node == nullptr) {
		pModuleManager->ErrorPrintf("Invalid NodeId @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	int depth = (int)lua_tonumber(luaVM, 3);
	if (depth > Utils::MAX_NODE_DEPTH) {
		pModuleManager->ErrorPrintf("Depth to high, would take to long @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	lua_newtable(luaVM);
	Utils::GetNodeNeighbors(luaVM, node, depth);

	return 1;
}<commit_msg>Fixed #2 (using math.huge as position crashes the server)<commit_after>#include "CFunctions.h"
#include "include/ILuaModuleManager.h"
#include "extra/CLuaArguments.h"

#include <pathfind/Graph.h>
#include "Module.h"
#include "Utils.h"

#ifndef _WIN32
	#include <sys/stat.h>
#endif

int CFunctions::LoadPathGraph(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TSTRING)
	{
		pModuleManager->ErrorPrintf("Bad argument @ loadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Build graph path
	char buf[300];
	if (!pModuleManager->GetResourceFilePath(luaVM, lua_tostring(luaVM, 1), buf, sizeof(buf)))
	{
		pModuleManager->ErrorPrintf("File does not exist @ loadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Check if path is valid
	std::string path{ buf };
	if (path.find("..") != std::string::npos)
	{
		pModuleManager->ErrorPrintf("Bad path @ loadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Load graph
	GraphId graphId = g_Module->LoadGraph(path);
	lua_pushnumber(luaVM, graphId);

	return 1;
}

int CFunctions::UnloadPathGraph(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TNUMBER) {
		pModuleManager->ErrorPrintf("Bad argument @ unloadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Check if graph has been loaded
	GraphId graphId = (GraphId)lua_tonumber(luaVM, 1);
	if (g_Module->GetGraph(graphId) == nullptr) {
		pModuleManager->ErrorPrintf("Bad graph @ unloadPathGraph, cannot unload\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	g_Module->UnloadGraph(graphId);
	lua_pushboolean(luaVM, true);
	return 1;
}

int CFunctions::FindShortestPathBetween(lua_State* luaVM)
{
	// bool findShortestPathBetween(int graphId, float startX, float startY, float startZ, float endX, float endY, float endZ, function callback)
	if (lua_type(luaVM, 1) != LUA_TNUMBER || lua_type(luaVM, 2) != LUA_TNUMBER || lua_type(luaVM, 3) != LUA_TNUMBER || lua_type(luaVM, 4) != LUA_TNUMBER ||
		lua_type(luaVM, 5) != LUA_TNUMBER || lua_type(luaVM, 6) != LUA_TNUMBER || lua_type(luaVM, 7) != LUA_TNUMBER ||
		lua_type(luaVM, 8) != LUA_TFUNCTION)
	{
		pModuleManager->ErrorPrintf("Bad argument @ findShortestPathBetween\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Check if graph has been loaded
	GraphId graphId = (GraphId)lua_tonumber(luaVM, 1);
	if (g_Module->GetGraph(graphId) == nullptr)
	{
		pModuleManager->ErrorPrintf("No graph loaded @ findShortestPathBetween\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Check if the positions are valid
	float fromX = (float)lua_tonumber(luaVM, 2), fromY = (float)lua_tonumber(luaVM, 3), fromZ = (float)lua_tonumber(luaVM, 4);
	float toX = (float)lua_tonumber(luaVM, 5), toY = (float)lua_tonumber(luaVM, 6), toZ = (float)lua_tonumber(luaVM, 7);
	if (isinf(fromX) || isinf(fromY) || isinf(fromZ) || isinf(toX) || isinf(toY) || isinf(toZ)) {
		pModuleManager->ErrorPrintf("Bad argument @ findShortestPathBetween\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	// Make vectors from Lua primitives
	Vector3 from(fromX, fromY, fromZ);
	Vector3 to(toX, toY, toZ);

	// Save reference of the Lua callback function
	// See: http://lua-users.org/lists/lua-l/2008-12/msg00193.html
	lua_pushvalue(luaVM, -1);
	int funcRef = luaL_ref(luaVM, LUA_REGISTRYINDEX);

	g_Module->GetJobManager().PushTask([from, to, graphId]() {

		// Prepare information we need to pass to A*
		pathfind::AStar algorithm(g_Module->GetGraph(graphId), from, to);

		// Run A*
		return algorithm.CalculateShortestPath();

	}, [luaVM = lua_getmainstate(luaVM), funcRef](const pathfind::AStarResult& result) {

		// Validate LuaVM (use ResourceStart/-Stop to manage valid lua states)
		if (!g_Module->HasLuaVM(luaVM))
			return;

		// Push stored reference to callback function to the stack
		lua_rawgeti(luaVM, LUA_REGISTRYINDEX, funcRef);

		// Push arguments to the stack
		lua_newtable(luaVM);
		std::size_t index = 0;

		for (pathfind::GraphNode* node : result)
		{
			// Set table index
			lua_pushnumber(luaVM, ++index);

			// Create a table containing the vector components
			lua_newtable(luaVM);

			lua_pushnumber(luaVM, 1);
			lua_pushnumber(luaVM, node->position.GetX());
			lua_settable(luaVM, -3);

			lua_pushnumber(luaVM, 2);
			lua_pushnumber(luaVM, node->position.GetY());
			lua_settable(luaVM, -3);

			lua_pushnumber(luaVM, 3);
			lua_pushnumber(luaVM, node->position.GetZ());
			lua_settable(luaVM, -3);

			// Add vector table to result table
			lua_settable(luaVM, -3);
		}

		// Finally, call the function
		int err = lua_pcall(luaVM, 1, 0, 0);
		if (err != 0)
			pModuleManager->ErrorPrintf("%s\n", lua_tostring(luaVM, -1));

	});

	lua_pushboolean(luaVM, true);
	return 1;
}

int CFunctions::IsGraphLoaded(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TNUMBER) {
		pModuleManager->ErrorPrintf("Bad argument @ unloadPathGraph\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	GraphId graphId = (GraphId) lua_tonumber(luaVM, 1);
	lua_pushboolean(luaVM, g_Module->GetGraph(graphId) != nullptr);
	return 1;
}

int CFunctions::FindNodeAt(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TNUMBER || lua_type(luaVM, 2) != LUA_TNUMBER || lua_type(luaVM, 3) != LUA_TNUMBER || lua_type(luaVM, 4) != LUA_TNUMBER)
	{
		pModuleManager->ErrorPrintf("Bad argument @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	GraphId graphId = (GraphId)lua_tonumber(luaVM, 1);
	if (g_Module->GetGraph(graphId) == nullptr) {
		pModuleManager->ErrorPrintf("Bad graph @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	float fromX = (float)lua_tonumber(luaVM, 2), fromY = (float)lua_tonumber(luaVM, 3), fromZ = (float)lua_tonumber(luaVM, 4);
	if (isinf(fromX) || isinf(fromY) || isinf(fromZ)) {
		pModuleManager->ErrorPrintf("Bad argument @ findShortestPathBetween\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	Vector3 position(fromX, fromY, fromZ);
	pathfind::GraphNode* node = g_Module->GetGraph(graphId)->FindClosestNodeTo(position);
	if (!node) {
		lua_pushboolean(luaVM, false);
		return 1;
	}

	lua_pushnumber(luaVM, node->id);
	lua_pushnumber(luaVM, node->position.GetX());
	lua_pushnumber(luaVM, node->position.GetY());
	lua_pushnumber(luaVM, node->position.GetZ());

	return 4;
}

int CFunctions::GetNodeNeighbors(lua_State* luaVM)
{
	if (lua_type(luaVM, 1) != LUA_TNUMBER || lua_type(luaVM, 2) != LUA_TNUMBER || lua_type(luaVM, 3) != LUA_TNUMBER)
	{
		pModuleManager->ErrorPrintf("Bad argument @ getNodeNeighbors\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	pathfind::Graph* graph = g_Module->GetGraph((GraphId)lua_tonumber(luaVM, 1));
	if (graph == nullptr) {
		pModuleManager->ErrorPrintf("Bad graph @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	int nodeId = (int)lua_tonumber(luaVM, 2);
	if (nodeId < 0) {
		pModuleManager->ErrorPrintf("Invalid NodeId @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	pathfind::GraphNode* node = graph->GetNode(static_cast<unsigned int>(nodeId));
	if (node == nullptr) {
		pModuleManager->ErrorPrintf("Invalid NodeId @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	int depth = (int)lua_tonumber(luaVM, 3);
	if (depth > Utils::MAX_NODE_DEPTH) {
		pModuleManager->ErrorPrintf("Depth to high, would take to long @ findNodeAt\n");
		lua_pushboolean(luaVM, false);
		return 1;
	}

	lua_newtable(luaVM);
	Utils::GetNodeNeighbors(luaVM, node, depth);

	return 1;
}<|endoftext|>


<commit_before>#include "condor_common.h"

#include <algorithm>
#include "ranger.h"

///// ranger insert/erase/find implementation /////

ranger::iterator ranger::insert(ranger::range r)
{
    // lower_bound here will coalesce an adjacent disjoint range;
    // can use upper_bound instead to avoid this and leave them fractured
    iterator it_start = forest.lower_bound(r._start);
    iterator it = it_start;
    while (it != forest.end() && it->_start <= r._end)  // '<' for no coalesce
        ++it;

    iterator it_end = it;
    if (it_start == it_end)
        return forest.insert(it_end, r);

    if (it_start->contains(r))
        return it_start;

    iterator it_back = --it;
    range rr_new = { std::min(it_start->_start, r._start),
                     std::max(it_back->_end, r._end) };

    // avoid erase+insert if only expanding a range
    if (it_start == it_back) {
        it_start->_start = rr_new._start;
        it_start->_end = rr_new._end;
        return it_start;
    }

    iterator hint = forest.erase(it_start, it_end);

    return forest.insert(hint, rr_new);
}

static
bool shrink_single_edge(const ranger::range &rm, const ranger::range &at)
{
    bool erase_start = rm._start <= at._start;
    bool erase_back  = at._end   <= rm._end;
    if (erase_start ^ erase_back) {
        if (erase_start)
            at._start = rm._end;
        else
            at._end = rm._start;
        return true;
    }
    return false;
}

ranger::iterator ranger::erase(ranger::range r)
{
    iterator it_start = forest.upper_bound(r._start);
    iterator it = it_start;
    while (it != forest.end() && it->_start < r._end)
        ++it;

    iterator it_end = it;
    if (it_start == it_end)
        return it_start;

    iterator it_back = --it;

    // avoid erase+insert if only shrinking an edge of a range
    if (it_start == it_back && shrink_single_edge(r, *it_start))
        return it_start;

    range rr_start = *it_start;
    range rr_back  = *it_back;

    iterator hint = forest.erase(it_start, it_end);
    if (rr_start._start < r._start)
        hint = forest.insert(hint, {rr_start._start, r._start});

    if (r._end < rr_back._end)
        hint = forest.insert(hint, {r._end, rr_back._end});

    return hint;
}

std::pair<ranger::iterator, bool>
ranger::find(value_type x) const
{
    iterator it = forest.upper_bound(x);
    return {it, it != forest.end() && it->_start <= x};
}

bool ranger::contains(value_type x) const
{
    return find(x).second;
}

ranger::ranger(const std::initializer_list<ranger::range> &il)
{
    for (const range &rr : il)
        insert(rr);
}

///// ranger::elements::iterator implementation /////

/* This allows:
 *
 *      for (int i : myranger.get_elements())
 *          process_int(i);
 *
 *
 * Instead of the still-straightforward:
 *
 *      for (auto &rr : myranger)
 *          for (int i : rr)
 *              process_int(i);
 */

void ranger::elements::iterator::mk_valid()
{
    if (!rit_valid) {
        rit = sit->begin();
        rit_valid = true;
    }
}

ranger::value_type ranger::elements::iterator::operator*()
{
    mk_valid();
    return *rit;
}

ranger::elements::iterator &ranger::elements::iterator::operator++()
{
    mk_valid();
    if (++rit == sit->end()) {
        ++sit;
        rit_valid = false;
    }
    return *this;
}

ranger::elements::iterator &ranger::elements::iterator::operator--()
{
    mk_valid();
    if (rit == sit->begin()) {
        --sit;
        rit = sit->end();
        --rit;
    }
    return *this;
}

bool ranger::elements::iterator::operator==(iterator &it)
{
    if (sit != it.sit)
        return false;
    if (!rit_valid && !it.rit_valid)
        return true;
    // at this point neither sit nor it.sit points to the end() of its set,
    // thus it's OK to call mk_valid() on each, which may dereference *sit
    mk_valid();
    it.mk_valid();
    return rit == it.rit;
}

bool ranger::elements::iterator::operator!=(iterator &it)
{
    return !(*this == it);
}

///// ranger persist/load implementation /////

#include <stdlib.h> // strtol
#include <stdio.h>  // sprintf
#include <string>

/*  persist / load ranger objects
 *
 *  The serialized format is one or more sub-ranges, separated by semicolons,
 *  where each sub-range is either N-M (for inclusive N..M) or N for a single
 *  integer.  Eg, "2", "5-10", "4;7;10-20;44;50-60"
 */

static
void persist_range_single(std::string &s, const ranger::range &rr)
{
    char buf[64];
    int n;
    if (rr._start == rr._end - 1)
        n = sprintf(buf, "%d;", rr._start);
    else
        n = sprintf(buf, "%d-%d;", rr._start, rr._end - 1);
    s.append(buf, n);
}

void persist(std::string &s, const ranger &r)
{
    s.clear();
    if (r.empty())
        return;

    for (auto &rr : r)
        persist_range_single(s, rr);

    s.erase(s.size() - 1);
}

void persist_range(std::string &s, const ranger &r, const ranger::range &rr)
{
    s.clear();
    if (r.empty())
        return;

    auto rit = r.find(rr._start).first;
    for (; rit != r.end() && rit->_start < rr._end; ++rit) {
        ranger::range rr_new = { std::max(rit->_start, rr._start),
                                 std::min(rit->_end,   rr._end) };
        persist_range_single(s, rr_new);
    }

    s.erase(s.size() - 1);
}

void persist_slice(std::string &s, const ranger &r, int start, int back)
{
    persist_range(s, r, {start, back+1});
}

// return 0 on success, (-1 - (position in string)) on parse failure
int load(ranger &r, const char *s)
{
    const char *sstart = s;
    while (*s) {
        char *sp;
        int start = strtol(s, &sp, 10);
        int back;
        if (s == sp)
            // no int parsed is ok as long as we're at the end
            return *s ? -1 - int(s - sstart) : 0;
        s = sp;
        if (*sp == '-') {
            s++;
            back = strtol(s, &sp, 10);
            if (s == sp)
                // a number should have followed '-'
                return -1 - int(s - sstart);
            s = sp;
        } else {
            back = start;
        }
        if (*s == ';')
            s++;
        else if (*s)
            // expected either ';' or end of string
            return -1 - int(s - sstart);
        r.insert({start, back + 1});
    }
    return 0;
}

<commit_msg>advance hint if inserting to the left of an erasure gap<commit_after>#include "condor_common.h"

#include <algorithm>
#include "ranger.h"

///// ranger insert/erase/find implementation /////

ranger::iterator ranger::insert(ranger::range r)
{
    // lower_bound here will coalesce an adjacent disjoint range;
    // can use upper_bound instead to avoid this and leave them fractured
    iterator it_start = forest.lower_bound(r._start);
    iterator it = it_start;
    while (it != forest.end() && it->_start <= r._end)  // '<' for no coalesce
        ++it;

    iterator it_end = it;
    if (it_start == it_end)
        return forest.insert(it_end, r);

    if (it_start->contains(r))
        return it_start;

    iterator it_back = --it;
    range rr_new = { std::min(it_start->_start, r._start),
                     std::max(it_back->_end, r._end) };

    // avoid erase+insert if only expanding a range
    if (it_start == it_back) {
        it_start->_start = rr_new._start;
        it_start->_end = rr_new._end;
        return it_start;
    }

    iterator hint = forest.erase(it_start, it_end);

    return forest.insert(hint, rr_new);
}

static
bool shrink_single_edge(const ranger::range &rm, const ranger::range &at)
{
    bool erase_start = rm._start <= at._start;
    bool erase_back  = at._end   <= rm._end;
    if (erase_start ^ erase_back) {
        if (erase_start)
            at._start = rm._end;
        else
            at._end = rm._start;
        return true;
    }
    return false;
}

ranger::iterator ranger::erase(ranger::range r)
{
    iterator it_start = forest.upper_bound(r._start);
    iterator it = it_start;
    while (it != forest.end() && it->_start < r._end)
        ++it;

    iterator it_end = it;
    if (it_start == it_end)
        return it_start;

    iterator it_back = --it;

    // avoid erase+insert if only shrinking an edge of a range
    if (it_start == it_back && shrink_single_edge(r, *it_start))
        return it_start;

    range rr_start = *it_start;
    range rr_back  = *it_back;

    iterator hint = forest.erase(it_start, it_end);
    if (rr_start._start < r._start) {
        hint = forest.insert(hint, {rr_start._start, r._start});
        ++hint;  // advance to erasure gap
    }

    if (r._end < rr_back._end)
        hint = forest.insert(hint, {r._end, rr_back._end});

    return hint;
}

std::pair<ranger::iterator, bool>
ranger::find(value_type x) const
{
    iterator it = forest.upper_bound(x);
    return {it, it != forest.end() && it->_start <= x};
}

bool ranger::contains(value_type x) const
{
    return find(x).second;
}

ranger::ranger(const std::initializer_list<ranger::range> &il)
{
    for (const range &rr : il)
        insert(rr);
}

///// ranger::elements::iterator implementation /////

/* This allows:
 *
 *      for (int i : myranger.get_elements())
 *          process_int(i);
 *
 *
 * Instead of the still-straightforward:
 *
 *      for (auto &rr : myranger)
 *          for (int i : rr)
 *              process_int(i);
 */

void ranger::elements::iterator::mk_valid()
{
    if (!rit_valid) {
        rit = sit->begin();
        rit_valid = true;
    }
}

ranger::value_type ranger::elements::iterator::operator*()
{
    mk_valid();
    return *rit;
}

ranger::elements::iterator &ranger::elements::iterator::operator++()
{
    mk_valid();
    if (++rit == sit->end()) {
        ++sit;
        rit_valid = false;
    }
    return *this;
}

ranger::elements::iterator &ranger::elements::iterator::operator--()
{
    mk_valid();
    if (rit == sit->begin()) {
        --sit;
        rit = sit->end();
        --rit;
    }
    return *this;
}

bool ranger::elements::iterator::operator==(iterator &it)
{
    if (sit != it.sit)
        return false;
    if (!rit_valid && !it.rit_valid)
        return true;
    // at this point neither sit nor it.sit points to the end() of its set,
    // thus it's OK to call mk_valid() on each, which may dereference *sit
    mk_valid();
    it.mk_valid();
    return rit == it.rit;
}

bool ranger::elements::iterator::operator!=(iterator &it)
{
    return !(*this == it);
}

///// ranger persist/load implementation /////

#include <stdlib.h> // strtol
#include <stdio.h>  // sprintf
#include <string>

/*  persist / load ranger objects
 *
 *  The serialized format is one or more sub-ranges, separated by semicolons,
 *  where each sub-range is either N-M (for inclusive N..M) or N for a single
 *  integer.  Eg, "2", "5-10", "4;7;10-20;44;50-60"
 */

static
void persist_range_single(std::string &s, const ranger::range &rr)
{
    char buf[64];
    int n;
    if (rr._start == rr._end - 1)
        n = sprintf(buf, "%d;", rr._start);
    else
        n = sprintf(buf, "%d-%d;", rr._start, rr._end - 1);
    s.append(buf, n);
}

void persist(std::string &s, const ranger &r)
{
    s.clear();
    if (r.empty())
        return;

    for (auto &rr : r)
        persist_range_single(s, rr);

    s.erase(s.size() - 1);
}

void persist_range(std::string &s, const ranger &r, const ranger::range &rr)
{
    s.clear();
    if (r.empty())
        return;

    auto rit = r.find(rr._start).first;
    for (; rit != r.end() && rit->_start < rr._end; ++rit) {
        ranger::range rr_new = { std::max(rit->_start, rr._start),
                                 std::min(rit->_end,   rr._end) };
        persist_range_single(s, rr_new);
    }

    s.erase(s.size() - 1);
}

void persist_slice(std::string &s, const ranger &r, int start, int back)
{
    persist_range(s, r, {start, back+1});
}

// return 0 on success, (-1 - (position in string)) on parse failure
int load(ranger &r, const char *s)
{
    const char *sstart = s;
    while (*s) {
        char *sp;
        int start = strtol(s, &sp, 10);
        int back;
        if (s == sp)
            // no int parsed is ok as long as we're at the end
            return *s ? -1 - int(s - sstart) : 0;
        s = sp;
        if (*sp == '-') {
            s++;
            back = strtol(s, &sp, 10);
            if (s == sp)
                // a number should have followed '-'
                return -1 - int(s - sstart);
            s = sp;
        } else {
            back = start;
        }
        if (*s == ';')
            s++;
        else if (*s)
            // expected either ';' or end of string
            return -1 - int(s - sstart);
        r.insert({start, back + 1});
    }
    return 0;
}

<|endoftext|>


<commit_before>#include "GUI-SFML.hpp"
#include <iostream>

int main()
{
    sf::RenderWindow window{ sf::VideoMode{ 1280, 720 }, "GUI-SFML Example Orientation" };
    // Some widgets need a Font to work properly, so we load one
    sf::Font font;
    if (!font.loadFromFile("../../assets/fonts/LiberationSans-Regular.ttf"))
    {
        std::cout << "Error by loading Font" << std::endl;
    }
    // Create an instance of GUIEnvironment which handle the drawing, updating and
    // events of the widgets which are added to it
    // It needs the window as a parameter
    gsf::GUIEnvironment environment{ window };

    // Create a Vertical layout. The "create" method create a unique_ptr with the
    // given parameters.
    // The width and height of the layout is automatic calculated and depends
    // of its child widgets
    gsf::VerticalLayout::Ptr layout{ gsf::VerticalLayout::create() };
    layout->setPosition(300.f, 300.f);
    // Make background gray
    layout->setBackgroundColor(sf::Color{ 192, 192, 192 });

    // Create some TextWidgets
    gsf::TextWidget::Ptr text1{ gsf::TextWidget::create("Text One", font) };
    gsf::TextWidget::Ptr text2{ gsf::TextWidget::create("Text Two", font) };
    gsf::TextWidget::Ptr text3{ gsf::TextWidget::create("Text Three", font) };
    // Add TextWidgets to the Layout
    layout->attachChild(std::move(text1));
    layout->attachChild(std::move(text2));
    layout->attachChild(std::move(text3));

    // Add Layout to environment
    environment.addWidget(std::move(layout));

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {

            if (event.type == sf::Event::Closed)
            {
                window.close();
            }
            environment.handleEvent(event);
        }
        //environment.update(dt);

        window.clear(sf::Color::White);
        window.draw(environment);
        window.display();
    }

}
<commit_msg>Clean up<commit_after>#include "GUI-SFML.hpp"
#include <iostream>

int main()
{
    sf::RenderWindow window{ sf::VideoMode{ 1280, 720 }, "GUI-SFML Example Orientation" };
    // Some widgets need a Font to work properly, so we load one
    sf::Font font;
    if (!font.loadFromFile("../../assets/fonts/LiberationSans-Regular.ttf"))
    {
        std::cout << "Error by loading Font" << std::endl;
    }
    // Create an instance of GUIEnvironment which handle the drawing, updating and
    // events of the widgets which are added to it
    // It needs the window as a parameter
    gsf::GUIEnvironment environment{ window };

    // Create a Vertical layout. The "create" method create a unique_ptr with the
    // given parameters.
    // The height of the layout is automatic calculated and depends
    // of its child widgets.
    gsf::VerticalLayout::Ptr layout{ gsf::VerticalLayout::create(200.f, 0.f) };
    layout->setPosition(0.f, 0.f);
    // Make background gray
    layout->setBackgroundColor(sf::Color{ 192, 192, 192 });

    // Create some TextWidgets
    gsf::TextWidget::Ptr text1{ gsf::TextWidget::create("Text One", font) };
    gsf::TextWidget::Ptr text2{ gsf::TextWidget::create("Text Two", font) };
    gsf::TextWidget::Ptr text3{ gsf::TextWidget::create("Text Three", font) };
    // Add TextWidgets to the Layout
    layout->attachChild(std::move(text1));
    layout->attachChild(std::move(text2));
    layout->attachChild(std::move(text3));

    // Add Layout to environment
    environment.addWidget(std::move(layout));

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {

            if (event.type == sf::Event::Closed)
            {
                window.close();
            }
            environment.handleEvent(event);
        }
        //environment.update(dt);

        window.clear(sf::Color::White);
        window.draw(environment);
        window.display();
    }
}
<|endoftext|>


<commit_before>/*
    testbedprotocol.cpp - Kopete Testbed Protocol

    Copyright (c) 2003      by Will Stephenson		 <will@stevello.free-online.co.u>
    Kopete    (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/
#include <kgenericfactory.h>

#include "kopeteaccountmanager.h"

#include "testbedaccount.h"
#include "testbedcontact.h"
#include "testbedprotocol.h"
#include "testbedaddcontactpage.h"
#include "testbededitaccountwidget.h"

typedef KGenericFactory<TestbedProtocol> TestbedProtocolFactory;
K_EXPORT_COMPONENT_FACTORY( kopete_testbed, TestbedProtocolFactory( "kopete_testbed" )  );

TestbedProtocol *TestbedProtocol::s_protocol = 0L;

TestbedProtocol::TestbedProtocol( QObject* parent, const char *name, const QStringList &/*args*/ )
	: KopeteProtocol( TestbedProtocolFactory::instance(), parent, name ),
	  testbedOnline(  KopeteOnlineStatus::Online, 25, this, 0,  QString::null,  i18n( "Go O&nline" ),   i18n( "Online" ) ),
	  testbedAway(  KopeteOnlineStatus::Away, 25, this, 1, "msn_away",  i18n( "Go &Away" ),   i18n( "Away" ) ),
	  testbedOffline(  KopeteOnlineStatus::Offline, 25, this, 2,  QString::null,  i18n( "Go O&ffline" ),   i18n( "Offline" ) )

{
	kdDebug( 14210 ) << k_funcinfo << endl;

	s_protocol = this;
}

TestbedProtocol::~TestbedProtocol()
{
}

void TestbedProtocol::deserializeContact( KopeteMetaContact *metaContact, const QMap<QString, QString> &serializedData,
	const QMap<QString, QString> &/* addressBookData */)
{
	QString contactId = serializedData[ "contactId" ];
	QString accountId = serializedData[ "accountId" ];
	QString displayName = serializedData[ "displayName" ];
	QString type = serializedData[ "contactType" ];

	TestbedContact::TestbedContactType tbcType;
	if ( type == QString::fromLatin1( "echo" ) )
		tbcType = TestbedContact::Echo;
	if ( type == QString::fromLatin1( "null" ) )
		tbcType = TestbedContact::Null;
	else
		tbcType = TestbedContact::Null;

	QDict<KopeteAccount> accounts = KopeteAccountManager::manager()->accounts( this );

	KopeteAccount *account = accounts[ accountId ];
	if ( !account )
	{
		kdDebug(14210) << "Account doesn't exist, skipping" << endl;
		return;
	}

	new TestbedContact(account, contactId, tbcType, displayName, metaContact, KopeteContact::OmitFromKABC );
}

AddContactPage * TestbedProtocol::createAddContactWidget( QWidget *parent, KopeteAccount *account )
{
	kdDebug(14210) << "Creating Add Contact Page" << endl;
	return new TestbedAddContactPage( parent );
}

EditAccountWidget * TestbedProtocol::createEditAccountWidget( KopeteAccount *account, QWidget *parent )
{
	kdDebug(14210) << "Creating Edit Account Page" << endl;
	return new TestbedEditAccountWidget( parent, account );
}

KopeteAccount *TestbedProtocol::createNewAccount( const QString &accountId )
{
	return new TestbedAccount( this, accountId );
}

TestbedProtocol *TestbedProtocol::protocol()
{
	return s_protocol;
}

<commit_msg>compile<commit_after>/*
    testbedprotocol.cpp - Kopete Testbed Protocol

    Copyright (c) 2003      by Will Stephenson		 <will@stevello.free-online.co.u>
    Kopete    (c) 2002-2003 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/
#include <kgenericfactory.h>

#include "kopeteaccountmanager.h"

#include "testbedaccount.h"
#include "testbedcontact.h"
#include "testbedprotocol.h"
#include "testbedaddcontactpage.h"
#include "testbededitaccountwidget.h"

typedef KGenericFactory<TestbedProtocol> TestbedProtocolFactory;
K_EXPORT_COMPONENT_FACTORY( kopete_testbed, TestbedProtocolFactory( "kopete_testbed" )  )

TestbedProtocol *TestbedProtocol::s_protocol = 0L;

TestbedProtocol::TestbedProtocol( QObject* parent, const char *name, const QStringList &/*args*/ )
	: KopeteProtocol( TestbedProtocolFactory::instance(), parent, name ),
	  testbedOnline(  KopeteOnlineStatus::Online, 25, this, 0,  QString::null,  i18n( "Go O&nline" ),   i18n( "Online" ) ),
	  testbedAway(  KopeteOnlineStatus::Away, 25, this, 1, "msn_away",  i18n( "Go &Away" ),   i18n( "Away" ) ),
	  testbedOffline(  KopeteOnlineStatus::Offline, 25, this, 2,  QString::null,  i18n( "Go O&ffline" ),   i18n( "Offline" ) )

{
	kdDebug( 14210 ) << k_funcinfo << endl;

	s_protocol = this;
}

TestbedProtocol::~TestbedProtocol()
{
}

void TestbedProtocol::deserializeContact( KopeteMetaContact *metaContact, const QMap<QString, QString> &serializedData,
	const QMap<QString, QString> &/* addressBookData */)
{
	QString contactId = serializedData[ "contactId" ];
	QString accountId = serializedData[ "accountId" ];
	QString displayName = serializedData[ "displayName" ];
	QString type = serializedData[ "contactType" ];

	TestbedContact::TestbedContactType tbcType;
	if ( type == QString::fromLatin1( "echo" ) )
		tbcType = TestbedContact::Echo;
	if ( type == QString::fromLatin1( "null" ) )
		tbcType = TestbedContact::Null;
	else
		tbcType = TestbedContact::Null;

	QDict<KopeteAccount> accounts = KopeteAccountManager::manager()->accounts( this );

	KopeteAccount *account = accounts[ accountId ];
	if ( !account )
	{
		kdDebug(14210) << "Account doesn't exist, skipping" << endl;
		return;
	}

	new TestbedContact(account, contactId, tbcType, displayName, metaContact, KopeteContact::OmitFromKABC );
}

AddContactPage * TestbedProtocol::createAddContactWidget( QWidget *parent, KopeteAccount *account )
{
	kdDebug(14210) << "Creating Add Contact Page" << endl;
	return new TestbedAddContactPage( parent );
}

EditAccountWidget * TestbedProtocol::createEditAccountWidget( KopeteAccount *account, QWidget *parent )
{
	kdDebug(14210) << "Creating Edit Account Page" << endl;
	return new TestbedEditAccountWidget( parent, account );
}

KopeteAccount *TestbedProtocol::createNewAccount( const QString &accountId )
{
	return new TestbedAccount( this, accountId );
}

TestbedProtocol *TestbedProtocol::protocol()
{
	return s_protocol;
}

<|endoftext|>


<commit_before>#include <gmock/gmock.h>

#include "script/LuaTestSupportScript.hpp"

#include "Character.hpp"
#include "Item.hpp"
#include "World.hpp"
#include "Container.hpp"

class MockWorld : public World {
public:
    MockWorld() {
        World::_self = this;
    }

    MOCK_METHOD1(findCharacter, Character*(TYPE_OF_CHARACTER_ID id));
};

class MockCharacter : public Character {
public:
    MOCK_CONST_METHOD0(getType, unsigned short());
    MOCK_CONST_METHOD0(to_string, std::string());
    MOCK_CONST_METHOD2(inform, void(const std::string &, informType));
    MOCK_CONST_METHOD3(inform, void(const std::string &, const std::string &, informType));
    MOCK_CONST_METHOD0(GetBackPack, Container *());
};

using ::testing::Return;

class scriptitem_bindings : public ::testing::Test {
	public:
		ScriptItem item;
		MockWorld world;
		MockCharacter character;

	scriptitem_bindings() {
	    ON_CALL(world, findCharacter(character.getId())).WillByDefault(Return(&character));
	}
};

TEST_F(scriptitem_bindings, test_id_property) {
    item.setId(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item.id == 23)\n"
			  "item.id = 42\n"
                          "assert(item.id == 42)\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(42, retval.getId());
}

TEST_F(scriptitem_bindings, test_wear_property) {
    item.setWear(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item.wear == 23)\n"
			  "item.wear = 42\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(42, retval.getWear());
}

TEST_F(scriptitem_bindings, test_number_property) {
    item.setNumber(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item.number == 23)\n"
			  "item.number = 42\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(42, retval.getNumber());
}

TEST_F(scriptitem_bindings, test_quality_property) {
    item.setQuality(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item.quality == 23)\n"
			  "item.quality = 42\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(42, retval.getQuality());
}

TEST_F(scriptitem_bindings, test_data_property) {
    item.setData("foo", 1);
    item.setData("bar", "baz");
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item:getData(\"foo\") == \"1\")\n"
                          "assert(item:getData(\"bar\") == \"baz\")\n"
			  "item:setData(\"hello\", \"world\")\n"
			  "item:setData(\"answer\", 42)\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(std::string("world"), retval.getData("hello"));
    EXPECT_EQ(std::string("42"), retval.getData("answer"));
}

TEST_F(scriptitem_bindings, test_constructor) {
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "local foo = scriptItem()\n"
			  "foo.id = 23\n"
			  "return foo\n"
			  "end",
			  "scriptitem_constructor_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_constants) {
	std::list<std::pair<ScriptItem::itemtype, std::string>> constants {
		{ScriptItem::notdefined, "scriptItem.notdefined"},
		{ScriptItem::it_field, "scriptItem.field"},
		{ScriptItem::it_inventory, "scriptItem.inventory"},
		{ScriptItem::it_belt, "scriptItem.belt"},
		{ScriptItem::it_container, "scriptItem.container"},
	};
	auto function = [](ScriptItem::itemtype constant, const std::string& lua_name) {
		std::string code = "function int_test()\n";
		code += "return ";
		code += lua_name + "\n";
		code += "end";
		LuaTestSupportScript script {code,
			  "scriptitem_constants_test"
			  };
		EXPECT_EQ(constant,  script.int_test(0));
	};
	for (auto entry : constants) {
		function(entry.first, entry.second);
	}
}

TEST_F(scriptitem_bindings, test_owner) {
    item.setId(0);
    item.owner = &character;
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item.owner ~= nil)\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_owner_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_pos) {
    item.setId(0);
    item.pos = { 1, 2, 3 };
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item.pos == position(1,2,3))\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_pos_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_itempos) {
    item.setId(0);
    item.itempos = 42;
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item.itempos == 42)\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_itempos_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_gettype) {
    item.setId(0);
    item.type = ScriptItem::it_field;
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item:getType() == scriptItem.field)\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_gettype_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_inside) {
    item.setId(0);
    item.inside = new Container(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item.inside ~= nil)\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_inside_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

<commit_msg>Fix test with characters<commit_after>#include <gmock/gmock.h>

#include "script/LuaTestSupportScript.hpp"

#include "Character.hpp"
#include "Item.hpp"
#include "World.hpp"
#include "Container.hpp"

class MockWorld : public World {
public:
    MockWorld() {
        World::_self = this;
    }

    MOCK_METHOD1(findCharacter, Character*(TYPE_OF_CHARACTER_ID id));
};

class MockCharacter : public Character {
public:
    MOCK_CONST_METHOD0(getId, TYPE_OF_CHARACTER_ID());
    MOCK_CONST_METHOD0(getType, unsigned short());
    MOCK_CONST_METHOD0(to_string, std::string());
    MOCK_CONST_METHOD2(inform, void(const std::string &, informType));
    MOCK_CONST_METHOD3(inform, void(const std::string &, const std::string &, informType));
    MOCK_CONST_METHOD0(GetBackPack, Container *());
};

using ::testing::Return;

class scriptitem_bindings : public ::testing::Test {
	public:
		ScriptItem item;
		MockWorld world;
		MockCharacter character;

	scriptitem_bindings() {
	    ON_CALL(character, getId()).WillByDefault(Return(1));
        ON_CALL(world, findCharacter(character.getId())).WillByDefault(Return(&character));
	}
};

TEST_F(scriptitem_bindings, test_id_property) {
    item.setId(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item.id == 23)\n"
			  "item.id = 42\n"
                          "assert(item.id == 42)\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(42, retval.getId());
}

TEST_F(scriptitem_bindings, test_wear_property) {
    item.setWear(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item.wear == 23)\n"
			  "item.wear = 42\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(42, retval.getWear());
}

TEST_F(scriptitem_bindings, test_number_property) {
    item.setNumber(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item.number == 23)\n"
			  "item.number = 42\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(42, retval.getNumber());
}

TEST_F(scriptitem_bindings, test_quality_property) {
    item.setQuality(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item.quality == 23)\n"
			  "item.quality = 42\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(42, retval.getQuality());
}

TEST_F(scriptitem_bindings, test_data_property) {
    item.setData("foo", 1);
    item.setData("bar", "baz");
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
                          "assert(item:getData(\"foo\") == \"1\")\n"
                          "assert(item:getData(\"bar\") == \"baz\")\n"
			  "item:setData(\"hello\", \"world\")\n"
			  "item:setData(\"answer\", 42)\n"
			  "return item\n"
			  "end",
			  "item_id_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(std::string("world"), retval.getData("hello"));
    EXPECT_EQ(std::string("42"), retval.getData("answer"));
}

TEST_F(scriptitem_bindings, test_constructor) {
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "local foo = scriptItem()\n"
			  "foo.id = 23\n"
			  "return foo\n"
			  "end",
			  "scriptitem_constructor_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_constants) {
	std::list<std::pair<ScriptItem::itemtype, std::string>> constants {
		{ScriptItem::notdefined, "scriptItem.notdefined"},
		{ScriptItem::it_field, "scriptItem.field"},
		{ScriptItem::it_inventory, "scriptItem.inventory"},
		{ScriptItem::it_belt, "scriptItem.belt"},
		{ScriptItem::it_container, "scriptItem.container"},
	};
	auto function = [](ScriptItem::itemtype constant, const std::string& lua_name) {
		std::string code = "function int_test()\n";
		code += "return ";
		code += lua_name + "\n";
		code += "end";
		LuaTestSupportScript script {code,
			  "scriptitem_constants_test"
			  };
		EXPECT_EQ(constant,  script.int_test(0));
	};
	for (auto entry : constants) {
		function(entry.first, entry.second);
	}
}

TEST_F(scriptitem_bindings, test_owner) {
    item.setId(0);
    item.owner = &character;
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item.owner ~= nil)\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_owner_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_pos) {
    item.setId(0);
    item.pos = { 1, 2, 3 };
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item.pos == position(1,2,3))\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_pos_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_itempos) {
    item.setId(0);
    item.itempos = 42;
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item.itempos == 42)\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_itempos_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_gettype) {
    item.setId(0);
    item.type = ScriptItem::it_field;
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item:getType() == scriptItem.field)\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_gettype_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

TEST_F(scriptitem_bindings, test_inside) {
    item.setId(0);
    item.inside = new Container(23);
    LuaTestSupportScript script {"function scriptitem_test(item)\n"
			  "assert(item.inside ~= nil)\n"
			  "item.id = 23\n"
			  "return item\n"
			  "end",
			  "scriptitem_inside_test"
			 };
    auto retval = script.scriptitem_test(item);
    EXPECT_EQ(23, retval.getId());
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <string>

#include "c_file_sandbox.h"

#include "../../cvmfs/util.h"
#include "../../cvmfs/hash.h"
#include "../../cvmfs/prng.h"

class T_FileSandbox : public FileSandbox {
 protected:
  static const std::string sandbox_path;

 public:
  typedef std::vector<ExpectedHashString> ExpectedHashStrings;

  T_FileSandbox() :
    FileSandbox(T_FileSandbox::sandbox_path) {}

 protected:
  void SetUp() {
    CreateSandbox(T_FileSandbox::sandbox_path);
  }

  void TearDown() {
    RemoveSandbox(T_FileSandbox::sandbox_path);
  }

  shash::Any HashFile(const std::string &file_path) const {
    shash::Any sha_result(shash::kSha1);
    HashFileInternal(file_path, &sha_result);
    return sha_result;
  }

 private:
  /**
   * Wraps the call to shash::HashFile to create a check sum of the given file
   * googletest requires functions that have ASSERTs inside to return void, thus
   * we do a wrapper of the wrapper of the wrapper here :o)
   */
  void HashFileInternal(const std::string &file_path, shash::Any *digest) const {
    const bool retval = shash::HashFile(file_path, digest);
    ASSERT_TRUE (retval) << "failed to hash file: " << file_path;
  }
};

const std::string T_FileSandbox::sandbox_path = "/tmp/cvmfs_ut_filesandbox";

//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//

TEST_F(T_FileSandbox, SandboxCreation) {
  EXPECT_TRUE (DirectoryExists(T_FileSandbox::sandbox_path));
}

TEST_F(T_FileSandbox, CreateRandomBufferMethod) {
  Prng rng;
  rng.InitSeed(27);

  const uint64_t buffer_size = 10 * 1024 * 1024;
  char *buffer = (char*)malloc(buffer_size);
  ASSERT_NE (static_cast<char*>(NULL), buffer);
  memset(buffer, buffer_size, 0);

  // count number of zero-bytes in the random buffer as 'checksum'
  CreateRandomBuffer(buffer, buffer_size, rng);
  uint32_t zeros = 0;
  for (uint64_t i = 0; i < buffer_size; ++i) {
    if (buffer[i] == 0) {
      ++zeros;
    }
  }

  EXPECT_EQ (41207u, zeros);
}

TEST_F(T_FileSandbox, EmptyFile) {
  const std::string empty_file = GetEmptyFile();
  const int64_t file_size = GetFileSize(empty_file);

  EXPECT_EQ (0, file_size) << "empty file was not empty";
}

TEST_F(T_FileSandbox, SmallFile) {
  const std::string small_file = GetSmallFile();
  const int64_t file_size = GetFileSize(small_file);

  EXPECT_EQ (50 * 1024, file_size) << "small file size does not match";

  shash::Any sha = HashFile(small_file);
  EXPECT_EQ ("5f0956f4e6b99a57b60b590c326570b5a172e895", sha.ToString());
}

TEST_F(T_FileSandbox, BigFile) {
  const std::string big_file = GetBigFile();
  const int64_t file_size = GetFileSize(big_file);

  EXPECT_EQ (4 * 1024 * 1024, file_size) << "big file size does not match";

  shash::Any sha = HashFile(big_file);
  EXPECT_EQ ("59107e4c69e7687499423d3d85154fdba9cd8161", sha.ToString());
}

TEST_F(T_FileSandbox, HugeFile) {
  const std::string huge_file = GetHugeFile();
  const int64_t file_size = GetFileSize(huge_file);

  EXPECT_EQ (100 * 1024 * 1024, file_size) << "huge file size does not match";

  shash::Any sha = HashFile(huge_file);
  EXPECT_EQ ("e09bdb4354db2ac46309130ee91ad7c4131f29ea", sha.ToString());
}
<commit_msg>FIX: T_FileSandbox was affected by repaired shash::HashFile()<commit_after>#include <gtest/gtest.h>
#include <string>

#include "c_file_sandbox.h"

#include "../../cvmfs/util.h"
#include "../../cvmfs/hash.h"
#include "../../cvmfs/prng.h"

class T_FileSandbox : public FileSandbox {
 protected:
  static const std::string sandbox_path;

 public:
  typedef std::vector<ExpectedHashString> ExpectedHashStrings;

  T_FileSandbox() :
    FileSandbox(T_FileSandbox::sandbox_path) {}

 protected:
  void SetUp() {
    CreateSandbox(T_FileSandbox::sandbox_path);
  }

  void TearDown() {
    RemoveSandbox(T_FileSandbox::sandbox_path);
  }

  shash::Any HashFile(const std::string &file_path) const {
    shash::Any sha_result(shash::kSha1);
    HashFileInternal(file_path, &sha_result);
    return sha_result;
  }

 private:
  /**
   * Wraps the call to shash::HashFile to create a check sum of the given file
   * googletest requires functions that have ASSERTs inside to return void, thus
   * we do a wrapper of the wrapper of the wrapper here :o)
   */
  void HashFileInternal(const std::string &file_path, shash::Any *digest) const {
    const bool retval = shash::HashFile(file_path, digest);
    ASSERT_TRUE (retval) << "failed to hash file: " << file_path;
  }
};

const std::string T_FileSandbox::sandbox_path = "/tmp/cvmfs_ut_filesandbox";

//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//

TEST_F(T_FileSandbox, SandboxCreation) {
  EXPECT_TRUE (DirectoryExists(T_FileSandbox::sandbox_path));
}

TEST_F(T_FileSandbox, CreateRandomBufferMethod) {
  Prng rng;
  rng.InitSeed(27);

  const uint64_t buffer_size = 10 * 1024 * 1024;
  char *buffer = (char*)malloc(buffer_size);
  ASSERT_NE (static_cast<char*>(NULL), buffer);
  memset(buffer, buffer_size, 0);

  // count number of zero-bytes in the random buffer as 'checksum'
  CreateRandomBuffer(buffer, buffer_size, rng);
  uint32_t zeros = 0;
  for (uint64_t i = 0; i < buffer_size; ++i) {
    if (buffer[i] == 0) {
      ++zeros;
    }
  }

  EXPECT_EQ (41207u, zeros);
}

TEST_F(T_FileSandbox, EmptyFile) {
  const std::string empty_file = GetEmptyFile();
  const int64_t file_size = GetFileSize(empty_file);

  EXPECT_EQ (0, file_size) << "empty file was not empty";
}

TEST_F(T_FileSandbox, SmallFile) {
  const std::string small_file = GetSmallFile();
  const int64_t file_size = GetFileSize(small_file);

  EXPECT_EQ (50 * 1024, file_size) << "small file size does not match";

  shash::Any sha = HashFile(small_file);
  EXPECT_EQ ("e86f148ca3a9a1ad9cf19979548e61c38bfa1384", sha.ToString());
}

TEST_F(T_FileSandbox, BigFile) {
  const std::string big_file = GetBigFile();
  const int64_t file_size = GetFileSize(big_file);

  EXPECT_EQ (4 * 1024 * 1024, file_size) << "big file size does not match";

  shash::Any sha = HashFile(big_file);
  EXPECT_EQ ("59107e4c69e7687499423d3d85154fdba9cd8161", sha.ToString());
}

TEST_F(T_FileSandbox, HugeFile) {
  const std::string huge_file = GetHugeFile();
  const int64_t file_size = GetFileSize(huge_file);

  EXPECT_EQ (100 * 1024 * 1024, file_size) << "huge file size does not match";

  shash::Any sha = HashFile(huge_file);
  EXPECT_EQ ("e09bdb4354db2ac46309130ee91ad7c4131f29ea", sha.ToString());
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <string>

#include "../../cvmfs/util.h"

class T_UnlinkGuard : public ::testing::Test {
 protected:
  static const std::string sandbox;

 protected:
  virtual void SetUp() {
    const bool retval = MkdirDeep(sandbox, 0700);
    ASSERT_TRUE (retval) << "failed to create sandbox";
  }

  virtual void TearDown() {
    const bool retval = RemoveTree(sandbox);
    ASSERT_TRUE (retval) << "failed to remove sandbox";
  }

  std::string GetFilename() const {
    const std::string path = CreateTempPath(sandbox + "/catalog",
                                            0600);
    CheckEmpty(path);
    CheckExistence(path);
    return path;
  }

 protected:
  void CheckExistence(const std::string &path) const {
    ASSERT_TRUE (FileExists(path));
  }

 private:
  void CheckEmpty(const std::string &str) const {
    ASSERT_FALSE (str.empty());
  }
};

const std::string T_UnlinkGuard::sandbox = "/tmp/cvmfs_ut_unlink_guard";

TEST_F(T_UnlinkGuard, Initialize) {}

TEST_F(T_UnlinkGuard, SimpleUnlink) {
  const std::string file_path = GetFilename();
  {
    UnlinkGuard d(file_path);
    EXPECT_EQ (file_path, d.path());
    ASSERT_TRUE (FileExists(file_path));
    EXPECT_TRUE (d.IsEnabled());
  }
  EXPECT_FALSE (FileExists(file_path));
}

TEST_F(T_UnlinkGuard, Disable) {
  const std::string file_path = GetFilename();
  {
    UnlinkGuard d(file_path);
    EXPECT_EQ (file_path, d.path());
    ASSERT_TRUE (FileExists(file_path));
    EXPECT_TRUE (d.IsEnabled());
    d.Disable();
    ASSERT_TRUE  (FileExists(file_path));
    EXPECT_FALSE (d.IsEnabled());
  }
  EXPECT_TRUE (FileExists(file_path));
  unlink(file_path.c_str());
  EXPECT_FALSE (FileExists(file_path));
}

TEST_F(T_UnlinkGuard, Reenable) {
  const std::string file_path = GetFilename();
  {
    UnlinkGuard d(file_path);
    EXPECT_EQ (file_path, d.path());
    ASSERT_TRUE (FileExists(file_path));
    EXPECT_TRUE (d.IsEnabled());
    d.Disable();
    ASSERT_TRUE  (FileExists(file_path));
    EXPECT_FALSE (d.IsEnabled());
    d.Enable();
    ASSERT_TRUE (FileExists(file_path));
    EXPECT_TRUE (d.IsEnabled());
  }
  EXPECT_FALSE (FileExists(file_path));
}

TEST_F(T_UnlinkGuard, MultipleGuards) {
  const std::string file_path1 = GetFilename();
  const std::string file_path2 = GetFilename();
  const std::string file_path3 = GetFilename();
  const std::string file_path4 = GetFilename();
  const std::string file_path5 = GetFilename();

  {
    ASSERT_TRUE (FileExists(file_path1));
    ASSERT_TRUE (FileExists(file_path2));
    ASSERT_TRUE (FileExists(file_path3));
    ASSERT_TRUE (FileExists(file_path4));
    ASSERT_TRUE (FileExists(file_path5));

    UnlinkGuard d1(file_path1);
    UnlinkGuard d2(file_path2);
    {
      UnlinkGuard d4(file_path4);
      {
        UnlinkGuard d5(file_path5);
      }

      EXPECT_FALSE (FileExists(file_path5));
    }
    EXPECT_FALSE (FileExists(file_path4));
    EXPECT_TRUE (FileExists(file_path1));
    EXPECT_TRUE (FileExists(file_path2));
    EXPECT_TRUE (FileExists(file_path3));

    UnlinkGuard d3(file_path3);
    EXPECT_TRUE (FileExists(file_path1));
    EXPECT_TRUE (FileExists(file_path2));
    EXPECT_TRUE (FileExists(file_path3));
  }

  EXPECT_FALSE (FileExists(file_path1));
  EXPECT_FALSE (FileExists(file_path2));
  EXPECT_FALSE (FileExists(file_path3));
}

TEST_F(T_UnlinkGuard, DeferredInit) {
  const std::string file_path = GetFilename();
  {
    ASSERT_TRUE (FileExists(file_path));

    UnlinkGuard d;
    EXPECT_FALSE (d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));

    d.Set(file_path);
    EXPECT_TRUE (d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));
  }
  EXPECT_FALSE (FileExists(file_path));
}
<commit_msg>TEST: UnlinkGuard disabled initialisation<commit_after>#include <gtest/gtest.h>
#include <string>

#include "../../cvmfs/util.h"

class T_UnlinkGuard : public ::testing::Test {
 protected:
  static const std::string sandbox;

 protected:
  virtual void SetUp() {
    const bool retval = MkdirDeep(sandbox, 0700);
    ASSERT_TRUE (retval) << "failed to create sandbox";
  }

  virtual void TearDown() {
    const bool retval = RemoveTree(sandbox);
    ASSERT_TRUE (retval) << "failed to remove sandbox";
  }

  std::string GetFilename() const {
    const std::string path = CreateTempPath(sandbox + "/catalog",
                                            0600);
    CheckEmpty(path);
    CheckExistence(path);
    return path;
  }

 protected:
  void CheckExistence(const std::string &path) const {
    ASSERT_TRUE (FileExists(path));
  }

 private:
  void CheckEmpty(const std::string &str) const {
    ASSERT_FALSE (str.empty());
  }
};

const std::string T_UnlinkGuard::sandbox = "/tmp/cvmfs_ut_unlink_guard";

TEST_F(T_UnlinkGuard, Initialize) {}

TEST_F(T_UnlinkGuard, SimpleUnlink) {
  const std::string file_path = GetFilename();
  {
    UnlinkGuard d(file_path);
    EXPECT_EQ (file_path, d.path());
    ASSERT_TRUE (FileExists(file_path));
    EXPECT_TRUE (d.IsEnabled());
  }
  EXPECT_FALSE (FileExists(file_path));
}

TEST_F(T_UnlinkGuard, Disable) {
  const std::string file_path = GetFilename();
  {
    UnlinkGuard d(file_path);
    EXPECT_EQ (file_path, d.path());
    ASSERT_TRUE (FileExists(file_path));
    EXPECT_TRUE (d.IsEnabled());
    d.Disable();
    ASSERT_TRUE  (FileExists(file_path));
    EXPECT_FALSE (d.IsEnabled());
  }
  EXPECT_TRUE (FileExists(file_path));
  unlink(file_path.c_str());
  EXPECT_FALSE (FileExists(file_path));
}

TEST_F(T_UnlinkGuard, Reenable) {
  const std::string file_path = GetFilename();
  {
    UnlinkGuard d(file_path);
    EXPECT_EQ (file_path, d.path());
    ASSERT_TRUE (FileExists(file_path));
    EXPECT_TRUE (d.IsEnabled());
    d.Disable();
    ASSERT_TRUE  (FileExists(file_path));
    EXPECT_FALSE (d.IsEnabled());
    d.Enable();
    ASSERT_TRUE (FileExists(file_path));
    EXPECT_TRUE (d.IsEnabled());
  }
  EXPECT_FALSE (FileExists(file_path));
}

TEST_F(T_UnlinkGuard, MultipleGuards) {
  const std::string file_path1 = GetFilename();
  const std::string file_path2 = GetFilename();
  const std::string file_path3 = GetFilename();
  const std::string file_path4 = GetFilename();
  const std::string file_path5 = GetFilename();

  {
    ASSERT_TRUE (FileExists(file_path1));
    ASSERT_TRUE (FileExists(file_path2));
    ASSERT_TRUE (FileExists(file_path3));
    ASSERT_TRUE (FileExists(file_path4));
    ASSERT_TRUE (FileExists(file_path5));

    UnlinkGuard d1(file_path1);
    UnlinkGuard d2(file_path2);
    {
      UnlinkGuard d4(file_path4);
      {
        UnlinkGuard d5(file_path5);
      }

      EXPECT_FALSE (FileExists(file_path5));
    }
    EXPECT_FALSE (FileExists(file_path4));
    EXPECT_TRUE (FileExists(file_path1));
    EXPECT_TRUE (FileExists(file_path2));
    EXPECT_TRUE (FileExists(file_path3));

    UnlinkGuard d3(file_path3);
    EXPECT_TRUE (FileExists(file_path1));
    EXPECT_TRUE (FileExists(file_path2));
    EXPECT_TRUE (FileExists(file_path3));
  }

  EXPECT_FALSE (FileExists(file_path1));
  EXPECT_FALSE (FileExists(file_path2));
  EXPECT_FALSE (FileExists(file_path3));
}

TEST_F(T_UnlinkGuard, DeferredInit) {
  const std::string file_path = GetFilename();
  {
    ASSERT_TRUE (FileExists(file_path));

    UnlinkGuard d;
    EXPECT_FALSE (d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));

    d.Set(file_path);
    EXPECT_TRUE (d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));
  }
  EXPECT_FALSE (FileExists(file_path));
}

TEST_F(T_UnlinkGuard, DisabledInit) {
  const std::string file_path = GetFilename();
  {
    ASSERT_TRUE (FileExists(file_path));

    UnlinkGuard d(file_path, UnlinkGuard::kDisabled);
    EXPECT_FALSE(d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));
  }

  EXPECT_TRUE (FileExists(file_path));

  {
    ASSERT_TRUE (FileExists(file_path));

    UnlinkGuard d(file_path, UnlinkGuard::kDisabled);
    EXPECT_FALSE(d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));

    d.Enable();
    EXPECT_TRUE (d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));
  }
  EXPECT_FALSE (FileExists(file_path));
}

TEST_F(T_UnlinkGuard, ExplicitEnabledInit) {
  const std::string file_path = GetFilename();
  {
    ASSERT_TRUE (FileExists(file_path));

    UnlinkGuard d(file_path, UnlinkGuard::kEnabled);
    EXPECT_TRUE (d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));

    d.Disable();
    EXPECT_FALSE (d.IsEnabled());
    EXPECT_TRUE  (FileExists(file_path));
  }

  EXPECT_TRUE (FileExists(file_path));

  {
    ASSERT_TRUE (FileExists(file_path));

    UnlinkGuard d(file_path, UnlinkGuard::kEnabled);
    EXPECT_TRUE (d.IsEnabled());
    EXPECT_TRUE (FileExists(file_path));
  }
  EXPECT_FALSE (FileExists(file_path));
}
<|endoftext|>


<commit_before>#include <mettle.hpp>
using namespace mettle;

#include <iostream>
#include <thread>

#include <mettle/driver/exit_code.hpp>
#include <mettle/driver/windows/scoped_pipe.hpp>
#include <mettle/driver/windows/subprocess.hpp>
using namespace mettle::windows;

#include "last_error.hpp"

struct read_into_fixture {
  scoped_pipe pipe[2];
  std::string results[2];
  std::vector<readhandle> readhandles;
};

void sighandler(int) {}

suite<read_into_fixture> test_read_into("read_into()", [](auto &_) {
  _.setup([](read_into_fixture &f) {
    expect("open pipe 1", f.pipe[0].open(true, false), equal_to(true));
    expect("open pipe 2", f.pipe[1].open(true, false), equal_to(true));

    f.readhandles = {
      {f.pipe[0].read_handle, &f.results[0]},
      {f.pipe[1].read_handle, &f.results[1]}
    };
  });

  _.test("read until handles close", [](read_into_fixture &f) {
    std::thread t([&f]() {
      DWORD written;
      WriteFile(f.pipe[0].write_handle, "pipe 1", 6, &written, nullptr);
      WriteFile(f.pipe[1].write_handle, "pipe 2", 6, &written, nullptr);

      f.pipe[0].close_write();
      f.pipe[1].close_write();
    });
    std::vector<HANDLE> interrupts = {t.native_handle()};

    expect(read_into(f.readhandles, INFINITE, interrupts),
           not_equal_to(nullptr));
    t.join();

    expect(f.results[0], equal_to("pipe 1"));
    expect(f.results[1], equal_to("pipe 2"));
  });

  _.test("read until timeout", [](read_into_fixture &f) {
    std::thread t([&f]() {
      DWORD written;
      WriteFile(f.pipe[0].write_handle, "pipe 1", 6, &written, nullptr);
      std::this_thread::sleep_for(std::chrono::milliseconds(250));
      WriteFile(f.pipe[1].write_handle, "pipe 2", 6, &written, nullptr);
    });
    std::vector<HANDLE> interrupts = {t.native_handle()};
    t.detach();

    expect(read_into(f.readhandles, 10, interrupts),
           equal_to(nullptr));

    expect(f.results[0], equal_to("pipe 1"));
    expect(f.results[1], equal_to(""));
  });
});
<commit_msg>Fix intermittent Windows failure<commit_after>#include <mettle.hpp>
using namespace mettle;

#include <iostream>
#include <thread>

#include <mettle/driver/exit_code.hpp>
#include <mettle/driver/windows/scoped_pipe.hpp>
#include <mettle/driver/windows/subprocess.hpp>
using namespace mettle::windows;

#include "last_error.hpp"

struct read_into_fixture {
  scoped_pipe pipe[2];
  std::string results[2];
  std::vector<readhandle> readhandles;
};

void sighandler(int) {}

suite<read_into_fixture> test_read_into("read_into()", [](auto &_) {
  _.setup([](read_into_fixture &f) {
    expect("open pipe 1", f.pipe[0].open(true, false), equal_to(true));
    expect("open pipe 2", f.pipe[1].open(true, false), equal_to(true));

    f.readhandles = {
      {f.pipe[0].read_handle, &f.results[0]},
      {f.pipe[1].read_handle, &f.results[1]}
    };
  });

  _.test("read until handles close", [](read_into_fixture &f) {
    std::thread t([&f]() {
      DWORD written;
      WriteFile(f.pipe[0].write_handle, "pipe 1", 6, &written, nullptr);
      WriteFile(f.pipe[1].write_handle, "pipe 2", 6, &written, nullptr);

      f.pipe[0].close_write();
      f.pipe[1].close_write();
    });
    std::vector<HANDLE> interrupts = {t.native_handle()};

    expect(read_into(f.readhandles, INFINITE, interrupts),
           not_equal_to(nullptr));
    t.join();

    expect(f.results[0], equal_to("pipe 1"));
    expect(f.results[1], equal_to("pipe 2"));
  });

  _.test("read until timeout", [](read_into_fixture &f) {
    std::thread t([&f]() {
      DWORD written;
      WriteFile(f.pipe[0].write_handle, "pipe 1", 6, &written, nullptr);
      std::this_thread::sleep_for(std::chrono::milliseconds(250));
      WriteFile(f.pipe[1].write_handle, "pipe 2", 6, &written, nullptr);
    });
    std::vector<HANDLE> interrupts = {t.native_handle()};
    t.detach();

    expect(read_into(f.readhandles, 100, interrupts),
           equal_to(nullptr));

    expect(f.results[0], equal_to("pipe 1"));
    expect(f.results[1], equal_to(""));
  });
});
<|endoftext|>