<commit_before>/*
 *  SnapFind
 *  An interactive image search application
 *  Version 1
 *
 *  Copyright (c) 2002-2005 Intel Corporation
 *  Copyright (c) 2007 Carnegie Mellon University
 *  All Rights Reserved.
 *
 *  This software is distributed under the terms of the Eclipse Public
 *  License, Version 1.0 which can be found in the file named LICENSE.
 *  ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS SOFTWARE CONSTITUTES
 *  RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include <sys/time.h>
#include <math.h>
#include <libgen.h>
#include <stdint.h>
#include <limits.h>
#include <ctype.h>
#include <assert.h>

#include "diamond_types.h"
#include "searchlet_api.h"
#include "lib_results.h"
#include "lib_sfimage.h"
#include "sf_consts.h"
#include "ring.h"
#include "face_search.h"
#include "search_set.h"
#include "sfind_search.h"
#include "plugin.h"
#include "snapfind.h"

#include "lib_scope.h"

extern pthread_mutex_t ring_mutex;
extern void *log_cookie;

/*
 * this need to be global because we share it with the main
 * GUI.  XXX hack, do it right later.
 */
ls_search_handle_t shandle;
app_stats_t	astats;

/*
 * state the is global to all of these functions.
 */
/* XXX global for status window, fix  this someday */
int      search_active = 0;
static int     active  = 0;
int      search_number = 0;
struct timeval	search_start;

static search_set *sset = NULL;

/*
 * This initializes the search  state.
 */

void
init_search()
{
	shandle = ls_init_search();
	if (shandle == NULL) {
		printf("failed to initialize:  !! \n");
		exit(1);
	}
}

void
set_searchlist(int n, groupid_t * gids)
{
	int             err;

	err = ls_set_searchlist(shandle, n, gids);
	if (err) {
		printf("Failed to set searchlist on  err %d \n", err);
		exit(1);
	}
}

/*
 * This function initiates the search by building a filter
 * specification, setting the searchlet and then starting the search.
 */
void
do_search(gid_list_t * main_region, char *fspec)
{
	int             err;
	char           *filter_name;
	char           *dir_name;
	void 	       *cookie;
	search_iter_t iter;

	if (!fspec) {
		fspec = sset->build_filter_spec(NULL);
		if (fspec == NULL) {
			printf("failed to build filter specification \n");
			exit(1);
		}
	}

	dir_name = (char *) malloc(SF_MAX_PATH);
	if (dir_name == NULL) {
		exit(1);                /* XXX */
	}

	set_searchlist(main_region->ngids, main_region->gids);

	filter_name = first_searchlet_lib(&cookie);
	if (filter_name == NULL) {
		fprintf(stderr, "No filter libraries are defined \n");
		assert(0);
	}

	err = ls_set_searchlet(shandle, DEV_ISA_IA32, filter_name, fspec);
	if (err) {
		printf("Failed to set searchlet on err %d \n", err);
		exit(1);
	}
	free(filter_name);

	while ((filter_name = next_searchlet_lib(&cookie)) != NULL) {
		err = ls_add_filter_file(shandle, DEV_ISA_IA32, filter_name);
		free(filter_name);
	}

	/* Attach auxiliary data for this search.  */
	sset->write_blobs(shandle);

	/* reset application statistics */
	astats.as_objs_queued = 0;
	astats.as_objs_presented = 0;

	/* Go ahead and start the search.  */
	err = ls_start_search(shandle);
	if (err) {
		printf("Failed to start search on err %d \n", err);
		exit(1);
	}
}

/*
 *  Defines a scope for a new search.
 */
static void
define_scope(void *data)
{
	int             err;

	err = ls_define_scope();
	if (err != 0) {
		printf("XXX failed to define scope \n");
		exit(1);
	}
}

/*
 *  Stops a currently executing search.
 */
static void
stop_search(void *data)
{
	int             err;

	static int		old_total = 0;

	astats.as_objs_presented = user_measurement.total_seen - old_total;
	old_total = user_measurement.total_seen;
	err = ls_terminate_search_extended(shandle, &astats);
	if (err != 0) {
		printf("XXX failed to terminate search \n");
		exit(1);
	}
}

void
drain_ring(ring_data_t * ring)
{
	while (!ring_empty(ring)) {
		void           *msg = ring_deq(ring);
		free(msg);
	}
	assert(ring_empty(ring));

}

void
set_user_state(user_state_t state)
{
	int err;
	log_message(LOGT_APP, LOGL_TRACE, "snapfind: user is %s",
				state==USER_BUSY?"busy":"waiting");
	err = ls_set_user_state(shandle, state);
	if (err) {
		printf("failed to set user state: %d", err);
		exit(1);
	}
}

/*
 * This processes a message (command) from the interface
 * GUI to control the processing.
 */

void
handle_message(message_t * new_message)
{
	struct timezone tz;
	int				err;

	switch (new_message->type) {
		case START_SEARCH:

			assert(ring_empty(from_search_thread));
			/*
			 * delete old msgs
			 */
			pthread_mutex_lock(&ring_mutex);
			drain_ring(from_search_thread);
			pthread_mutex_unlock(&ring_mutex);
			do_search((gid_list_t *) new_message->data, NULL);
			active = 1;
			search_active = 1;
			search_number++;
			err = gettimeofday(&search_start, &tz);
			assert(err == 0);
			break;

		case TERM_SEARCH:
			stop_search(new_message->data);
			search_active = 0;
			break;

		case DEFINE_SCOPE:
			define_scope(new_message->data);
			break;

			/*
			 * XXX get stats ???
			 */
		case SET_USER_BUSY:
			set_user_state(USER_BUSY);
			break;

		case SET_USER_WAITING:
			set_user_state(USER_WAITING);
			break;

		default:
			printf("XXX unknown message %d \n", new_message->type);
			assert(0);
			break;
	}
}

void
update_stats()
{
	int             num_dev;
	ls_dev_handle_t dev_list[SF_MAX_DEVICES];
	int             i, err, len;
	dev_stats_t    *dstats;
	int             tobj = 0, sobj = 0, dobj = 0;

	dstats = (dev_stats_t *) malloc(DEV_STATS_SIZE(SF_MAX_FILTERS));
	assert(dstats);

	num_dev = SF_MAX_DEVICES;

	err = ls_get_dev_list(shandle, dev_list, &num_dev);
	if (err != 0) {
		printf("update states: %d \n", err);
		exit(1);
	}

	for (i = 0; i < num_dev; i++) {
		len = DEV_STATS_SIZE(SF_MAX_FILTERS);
		err = ls_get_dev_stats(shandle, dev_list[i], dstats, &len);
		if (err) {
			printf("Failed to get dev stats \n");
			exit(1);
		}
		tobj += dstats->ds_objs_total;
		sobj += dstats->ds_objs_processed;
		dobj += dstats->ds_objs_dropped;
	}
	free(dstats);

	tobj_cnt = tobj;
	sobj_cnt = sobj;
	dobj_cnt = dobj;
}

/*
 * This is main function that is called thread interacting with the
 * search subsystem.
 */

void           *
sfind_search_main(void *foo)
{

	message_t      *message;
	ls_obj_handle_t cur_obj;
	int             err;
	int             temp;
	int		any;

	struct timespec timeout;

	sset = (search_set *)foo;
	log_thread_register(log_cookie);

	/*
	 * XXX init_search();
	 */

	while (1) {
		any = 0;
		message = (message_t *) ring_deq(to_search_thread);
		if (message != NULL) {
			any = 1;
			handle_message(message);
			free(message);
		}
		if ((active) &&
			(ring_count(from_search_thread) < THUMBNAIL_DISPLAY_SIZE+1)) {
			err = ls_next_object(shandle, &cur_obj, LSEARCH_NO_BLOCK);
			if (err == ENOENT) {
				fprintf(stderr, "No more objects \n");  /* XXX */
				search_active = 0;
				active = 0;
				message = (message_t *) malloc(sizeof(*message));
				if (message == NULL) {
					fprintf(stderr, "non mem\n");
					exit(1);
				}
				message->type = DONE_OBJECTS;
				message->data = NULL;

				pthread_mutex_lock(&ring_mutex);
				err = ring_enq(from_search_thread, message);
				pthread_mutex_unlock(&ring_mutex);
				if (err) {
					fprintf(stderr, "XXX failed to enq \n");
					exit(1);
				}
			} else if ((err != 0) && (err != EWOULDBLOCK)) {
				/*
				 * XXX
				 */
				fprintf(stderr, "get_next_obj: failed on %d \n", err);
				exit(1);
			} else if (err == 0) {
				any = 1;
				message = (message_t *) malloc(sizeof(*message));
				assert(message != NULL);

				message->type = NEXT_OBJECT;
				message->data = cur_obj;
				pthread_mutex_lock(&ring_mutex);
				err = ring_enq(from_search_thread, message);
				pthread_mutex_unlock(&ring_mutex);
				if (err) {
					/*
					 * drop this on the floor
					 */
					ls_release_object(shandle, cur_obj);
					free(message);
				} else {
					astats.as_objs_queued++;
				}
			}
		}
		err = ls_num_objects(shandle, &temp);
		temp += ring_count(from_search_thread);

		pend_obj_cnt = temp;
		update_stats();
		if (any == 0) {
			timeout.tv_sec = 0;
			timeout.tv_nsec = 100000000;    /* XXX 100ms ?? */
			nanosleep(&timeout, NULL);
		}
	}
	return (0);
}
<commit_msg>Do not exit if define scope fails, it is not really fatal<commit_after>/*
 *  SnapFind
 *  An interactive image search application
 *  Version 1
 *
 *  Copyright (c) 2002-2005 Intel Corporation
 *  Copyright (c) 2007 Carnegie Mellon University
 *  All Rights Reserved.
 *
 *  This software is distributed under the terms of the Eclipse Public
 *  License, Version 1.0 which can be found in the file named LICENSE.
 *  ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS SOFTWARE CONSTITUTES
 *  RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include <sys/time.h>
#include <math.h>
#include <libgen.h>
#include <stdint.h>
#include <limits.h>
#include <ctype.h>
#include <assert.h>

#include "diamond_types.h"
#include "searchlet_api.h"
#include "lib_results.h"
#include "lib_sfimage.h"
#include "sf_consts.h"
#include "ring.h"
#include "face_search.h"
#include "search_set.h"
#include "sfind_search.h"
#include "plugin.h"
#include "snapfind.h"

#include "lib_scope.h"

extern pthread_mutex_t ring_mutex;
extern void *log_cookie;

/*
 * this need to be global because we share it with the main
 * GUI.  XXX hack, do it right later.
 */
ls_search_handle_t shandle;
app_stats_t	astats;

/*
 * state the is global to all of these functions.
 */
/* XXX global for status window, fix  this someday */
int      search_active = 0;
static int     active  = 0;
int      search_number = 0;
struct timeval	search_start;

static search_set *sset = NULL;

/*
 * This initializes the search  state.
 */

void
init_search()
{
	shandle = ls_init_search();
	if (shandle == NULL) {
		printf("failed to initialize:  !! \n");
		exit(1);
	}
}

void
set_searchlist(int n, groupid_t * gids)
{
	int             err;

	err = ls_set_searchlist(shandle, n, gids);
	if (err) {
		printf("Failed to set searchlist on  err %d \n", err);
		exit(1);
	}
}

/*
 * This function initiates the search by building a filter
 * specification, setting the searchlet and then starting the search.
 */
void
do_search(gid_list_t * main_region, char *fspec)
{
	int             err;
	char           *filter_name;
	char           *dir_name;
	void 	       *cookie;
	search_iter_t iter;

	if (!fspec) {
		fspec = sset->build_filter_spec(NULL);
		if (fspec == NULL) {
			printf("failed to build filter specification \n");
			exit(1);
		}
	}

	dir_name = (char *) malloc(SF_MAX_PATH);
	if (dir_name == NULL) {
		exit(1);                /* XXX */
	}

	set_searchlist(main_region->ngids, main_region->gids);

	filter_name = first_searchlet_lib(&cookie);
	if (filter_name == NULL) {
		fprintf(stderr, "No filter libraries are defined \n");
		assert(0);
	}

	err = ls_set_searchlet(shandle, DEV_ISA_IA32, filter_name, fspec);
	if (err) {
		printf("Failed to set searchlet on err %d \n", err);
		exit(1);
	}
	free(filter_name);

	while ((filter_name = next_searchlet_lib(&cookie)) != NULL) {
		err = ls_add_filter_file(shandle, DEV_ISA_IA32, filter_name);
		free(filter_name);
	}

	/* Attach auxiliary data for this search.  */
	sset->write_blobs(shandle);

	/* reset application statistics */
	astats.as_objs_queued = 0;
	astats.as_objs_presented = 0;

	/* Go ahead and start the search.  */
	err = ls_start_search(shandle);
	if (err) {
		printf("Failed to start search on err %d \n", err);
		exit(1);
	}
}

/*
 *  Defines a scope for a new search.
 */
static void
define_scope(void *data)
{
	int             err;

	err = ls_define_scope();
	if (err != 0) {
		printf("XXX failed to define scope \n");
	}
}

/*
 *  Stops a currently executing search.
 */
static void
stop_search(void *data)
{
	int             err;

	static int		old_total = 0;

	astats.as_objs_presented = user_measurement.total_seen - old_total;
	old_total = user_measurement.total_seen;
	err = ls_terminate_search_extended(shandle, &astats);
	if (err != 0) {
		printf("XXX failed to terminate search \n");
		exit(1);
	}
}

void
drain_ring(ring_data_t * ring)
{
	while (!ring_empty(ring)) {
		void           *msg = ring_deq(ring);
		free(msg);
	}
	assert(ring_empty(ring));

}

void
set_user_state(user_state_t state)
{
	int err;
	log_message(LOGT_APP, LOGL_TRACE, "snapfind: user is %s",
				state==USER_BUSY?"busy":"waiting");
	err = ls_set_user_state(shandle, state);
	if (err) {
		printf("failed to set user state: %d", err);
		exit(1);
	}
}

/*
 * This processes a message (command) from the interface
 * GUI to control the processing.
 */

void
handle_message(message_t * new_message)
{
	struct timezone tz;
	int				err;

	switch (new_message->type) {
		case START_SEARCH:

			assert(ring_empty(from_search_thread));
			/*
			 * delete old msgs
			 */
			pthread_mutex_lock(&ring_mutex);
			drain_ring(from_search_thread);
			pthread_mutex_unlock(&ring_mutex);
			do_search((gid_list_t *) new_message->data, NULL);
			active = 1;
			search_active = 1;
			search_number++;
			err = gettimeofday(&search_start, &tz);
			assert(err == 0);
			break;

		case TERM_SEARCH:
			stop_search(new_message->data);
			search_active = 0;
			break;

		case DEFINE_SCOPE:
			define_scope(new_message->data);
			break;

			/*
			 * XXX get stats ???
			 */
		case SET_USER_BUSY:
			set_user_state(USER_BUSY);
			break;

		case SET_USER_WAITING:
			set_user_state(USER_WAITING);
			break;

		default:
			printf("XXX unknown message %d \n", new_message->type);
			assert(0);
			break;
	}
}

void
update_stats()
{
	int             num_dev;
	ls_dev_handle_t dev_list[SF_MAX_DEVICES];
	int             i, err, len;
	dev_stats_t    *dstats;
	int             tobj = 0, sobj = 0, dobj = 0;

	dstats = (dev_stats_t *) malloc(DEV_STATS_SIZE(SF_MAX_FILTERS));
	assert(dstats);

	num_dev = SF_MAX_DEVICES;

	err = ls_get_dev_list(shandle, dev_list, &num_dev);
	if (err != 0) {
		printf("update states: %d \n", err);
		exit(1);
	}

	for (i = 0; i < num_dev; i++) {
		len = DEV_STATS_SIZE(SF_MAX_FILTERS);
		err = ls_get_dev_stats(shandle, dev_list[i], dstats, &len);
		if (err) {
			printf("Failed to get dev stats \n");
			exit(1);
		}
		tobj += dstats->ds_objs_total;
		sobj += dstats->ds_objs_processed;
		dobj += dstats->ds_objs_dropped;
	}
	free(dstats);

	tobj_cnt = tobj;
	sobj_cnt = sobj;
	dobj_cnt = dobj;
}

/*
 * This is main function that is called thread interacting with the
 * search subsystem.
 */

void           *
sfind_search_main(void *foo)
{

	message_t      *message;
	ls_obj_handle_t cur_obj;
	int             err;
	int             temp;
	int		any;

	struct timespec timeout;

	sset = (search_set *)foo;
	log_thread_register(log_cookie);

	/*
	 * XXX init_search();
	 */

	while (1) {
		any = 0;
		message = (message_t *) ring_deq(to_search_thread);
		if (message != NULL) {
			any = 1;
			handle_message(message);
			free(message);
		}
		if ((active) &&
			(ring_count(from_search_thread) < THUMBNAIL_DISPLAY_SIZE+1)) {
			err = ls_next_object(shandle, &cur_obj, LSEARCH_NO_BLOCK);
			if (err == ENOENT) {
				fprintf(stderr, "No more objects \n");  /* XXX */
				search_active = 0;
				active = 0;
				message = (message_t *) malloc(sizeof(*message));
				if (message == NULL) {
					fprintf(stderr, "non mem\n");
					exit(1);
				}
				message->type = DONE_OBJECTS;
				message->data = NULL;

				pthread_mutex_lock(&ring_mutex);
				err = ring_enq(from_search_thread, message);
				pthread_mutex_unlock(&ring_mutex);
				if (err) {
					fprintf(stderr, "XXX failed to enq \n");
					exit(1);
				}
			} else if ((err != 0) && (err != EWOULDBLOCK)) {
				/*
				 * XXX
				 */
				fprintf(stderr, "get_next_obj: failed on %d \n", err);
				exit(1);
			} else if (err == 0) {
				any = 1;
				message = (message_t *) malloc(sizeof(*message));
				assert(message != NULL);

				message->type = NEXT_OBJECT;
				message->data = cur_obj;
				pthread_mutex_lock(&ring_mutex);
				err = ring_enq(from_search_thread, message);
				pthread_mutex_unlock(&ring_mutex);
				if (err) {
					/*
					 * drop this on the floor
					 */
					ls_release_object(shandle, cur_obj);
					free(message);
				} else {
					astats.as_objs_queued++;
				}
			}
		}
		err = ls_num_objects(shandle, &temp);
		temp += ring_count(from_search_thread);

		pend_obj_cnt = temp;
		update_stats();
		if (any == 0) {
			timeout.tv_sec = 0;
			timeout.tv_nsec = 100000000;    /* XXX 100ms ?? */
			nanosleep(&timeout, NULL);
		}
	}
	return (0);
}
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE new_reasoner_test

#include <vector>
#include <iostream>

#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/bind.hpp>

#include <lemon/color.h>
#include <lemon/graph_to_eps.h>

#include <lemon/core.h>
#include <lemon/concepts/digraph.h>
#include <lemon/list_graph.h>
#include <lemon/maps.h>

#include "graph.h"
#include "hypotheses.h"
#include "energy.h"
#include "reasoning/mrf_reasoner.h"
#include "traxels.h"

using namespace Tracking;
using namespace std;
using namespace boost;

BOOST_AUTO_TEST_CASE( HypothesesGraph_build_hyp ) {
    HypothesesGraph graph;
    graph.add_node(13);
}

BOOST_AUTO_TEST_CASE( HypothesesGraph_build_hyp2 ) {

  std::cout << "Constructing HypothesesGraph" << std::endl;
  std::cout <<  std::endl;

  typedef HypothesesGraph::ArcIt ArcIt2;
  typedef HypothesesGraph::Arc Arc;
  typedef HypothesesGraph::NodeIt NodeIt;
  typedef HypothesesGraph::Node Node;
  using lemon::INVALID;

  HypothesesGraph g;
  HypothesesGraph* graph=&g;
  graph->add(node_traxel());

  std::cout << "Adding nodes" << std::endl;
  std::cout <<  std::endl;

  Node n1=g.add_node(0);
  Node n2=g.add_node(0);
  Node n3=g.add_node(0);
  Node n4=g.add_node(0);
  Node m1=g.add_node(1);
  Node m2=g.add_node(1);
  Node m3=g.add_node(1);
  Node m4=g.add_node(1);
  Node o1=g.add_node(2);
  Node o2=g.add_node(2);
  Node o3=g.add_node(2);
  Node o4=g.add_node(2);

  std::cout << "Nodes:";
  for (NodeIt i(g); i!=INVALID; ++i)
    std::cout << " " << g.id(i);
  std::cout << std::endl;

  std::cout << "Addings arcs" << std::endl;
  std::cout <<  std::endl;

  Arc n1_m2=g.addArc(n1,m2);
  Arc n2_m1=g.addArc(n2,m1);
  Arc n3_m3=g.addArc(n3,m3);
  Arc n3_m4=g.addArc(n3,m4);
  Arc m1_o1=g.addArc(m1,o1);
  Arc m2_o2=g.addArc(m2,o2);
  Arc m4_o3=g.addArc(m4,o3);
  Arc m4_o4=g.addArc(m4,o4);

  std::cout << "Arcs:";
  for (ArcIt2 i(g); i!=INVALID; ++i)
  std::cout << " (" << g.id(g.source(i)) << "," << g.id(g.target(i)) << ")";
  std::cout << std::endl;
  std::cout <<  std::endl;

  std::cout << "Constructing Reasoner" << std::endl;
  std::cout <<  std::endl;

   Traxels empty;
   ConstantEnergy e(25);

   SingleTimestepTraxelMrf mrf(bind<double>(e, _1, empty, empty),		//detection
			        bind<double>(e, _1, empty, empty),		//non_detection
			        bind<double>(e, _1, empty, empty),		//appearance
			        bind<double>(e, _1, empty, empty),		//disappearance
				bind<double>(e, _1, _2, empty, empty),		//move
				bind<double>(e, _1, _2, _3, empty, empty)	//division
			       );

  std::cout << "Formulating Factors" << std::endl;
  std::cout <<  std::endl;

    cout << "-> workflow: formulating model" << endl;
    mrf.formulate( *graph );
    cout << "-> workflow: infer" << endl;
    mrf.infer();
    cout << "-> workflow: conclude" << endl;
    mrf.conclude(*graph);
    prune_inactive(*graph);
}

BOOST_AUTO_TEST_CASE( HypothesesGraph_build_hyp_mrf ) {

    Traxel n1, n2, n3, n4, m1, m2, m3, m4, o1, o2, o3, o4, o5;
    feature_array comn1(feature_array::difference_type(3)); //float vector
    feature_array comn2(feature_array::difference_type(3));
    feature_array comn3(feature_array::difference_type(3));
    feature_array comn4(feature_array::difference_type(3));
    feature_array comm1(feature_array::difference_type(3));
    feature_array comm2(feature_array::difference_type(3));
    feature_array comm3(feature_array::difference_type(3));
    feature_array comm4(feature_array::difference_type(3));
    feature_array como1(feature_array::difference_type(3));
    feature_array como2(feature_array::difference_type(3));
    feature_array como3(feature_array::difference_type(3));
    feature_array como4(feature_array::difference_type(3));
    feature_array como5(feature_array::difference_type(3));

    comn1[0] = 0;
    comn1[1] = 0;
    comn1[2] = 0;
    n1.features["com"] = comn1;
    n1.Id = 11;
    n1.Timestep = 0;

    comn2[0] = 1;
    comn2[1] = 1;
    comn2[2] = 1;
    n2.features["com"] = comn2;
    n2.Id = 12;
    n2.Timestep = 0;

    comn3[0] = 0;
    comn3[1] = 0;
    comn3[2] = 2;
    n3.features["com"] = comn3;
    n3.Id = 13;
    n3.Timestep = 0;

    comn4[0] = 2;
    comn4[1] = 0;
    comn4[2] = 0;
    n4.features["com"] = comn4;
    n4.Id = 14;
    n4.Timestep = 0;

    comm1[0] = 2;
    comm1[1] = 2;
    comm1[2] = 2;
    m1.features["com"] = comm1;
    m1.Id = 21;
    m1.Timestep = 1;

    comm2[0] = 1;
    comm2[1] = 0;
    comm2[2] = 1;
    m2.features["com"] = comm2;
    m2.Id = 22;
    m2.Timestep = 1;

    comm3[0] = 0;
    comm3[1] = 1;
    comm3[2] = 1;
    m3.features["com"] = comm3;
    m3.Id = 23;
    m3.Timestep = 1;

    comm4[0] = 3;
    comm4[1] = 3;
    comm4[2] = 3;
    m4.features["com"] = comm4;
    m4.Id = 24;
    m4.Timestep = 1;

    como1[0] = 4;
    como1[1] = 4;
    como1[2] = 4;
    o1.features["com"] = como1;
    o1.Id = 31;
    o1.Timestep = 2;

    como2[0] = 7;
    como2[1] = 19;
    como2[2] = 8;
    o2.features["com"] = como2;
    o2.Id = 32;
    o2.Timestep = 2;

    como3[0] = 0;
    como3[1] = 7;
    como3[2] = 1;
    o3.features["com"] = como3;
    o3.Id = 33;
    o3.Timestep = 2;

    como4[0] = 5;
    como4[1] = 0;
    como4[2] = 9;
    o4.features["com"] = como4;
    o4.Id = 34;
    o4.Timestep = 2;

    como5[0] = 0;
    como5[1] = 4;
    como5[2] = 0;
    o5.features["com"] = como5;
    o5.Id = 34;
    o5.Timestep = 2;

    TraxelStore ts;
    add(ts,n1);
    add(ts,n2);
    add(ts,n3);
    add(ts,n4);
    add(ts,m1);
    add(ts,m2);
    add(ts,m3);
    add(ts,m4);
    add(ts,o1);
    add(ts,o2);
    add(ts,o3);
    add(ts,o4);
    add(ts,o5);

    SingleTimestepTraxel_HypothesesBuilder builder(&ts);
    HypothesesGraph* graph = builder.build();

    Traxels empty;
    ConstantEnergy e1(10);
    ConstantEnergy e2(90);
    ConstantEnergy e3(70);
    ConstantEnergy e4(50);
    ConstantEnergy e5(20);
    ConstantEnergy e6(5);

    SingleTimestepTraxelMrf mrf(bind<double>(e1, _1, empty, empty),		//detection
			        bind<double>(e2, _1, empty, empty),		//non_detection
			        bind<double>(e3, _1, empty, empty),		//appearance
			        bind<double>(e4, _1, empty, empty),		//disappearance
				bind<double>(e5, _1, _2, empty, empty),		//move
				bind<double>(e6, _1, _2, _3, empty, empty)	//division
			       );
    cout << "-> workflow: formulating model" << endl;
    mrf.formulate( *graph );
    cout << "-> workflow: infer" << endl;
    mrf.infer();
    cout << "-> workflow: conclude" << endl;
    mrf.conclude(*graph);
    prune_inactive(*graph);
}
<commit_msg>fixed warnings<commit_after>#define BOOST_TEST_MODULE new_reasoner_test

#include <vector>
#include <iostream>

#include <boost/test/unit_test.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/bind.hpp>

#include <lemon/color.h>
#include <lemon/graph_to_eps.h>

#include <lemon/core.h>
#include <lemon/concepts/digraph.h>
#include <lemon/list_graph.h>
#include <lemon/maps.h>

#include "graph.h"
#include "hypotheses.h"
#include "energy.h"
#include "reasoning/mrf_reasoner.h"
#include "traxels.h"

using namespace Tracking;
using namespace std;
using namespace boost;

BOOST_AUTO_TEST_CASE( HypothesesGraph_build_hyp ) {
    HypothesesGraph graph;
    graph.add_node(13);
}

BOOST_AUTO_TEST_CASE( HypothesesGraph_build_hyp2 ) {

  std::cout << "Constructing HypothesesGraph" << std::endl;
  std::cout <<  std::endl;

  typedef HypothesesGraph::ArcIt ArcIt2;
  typedef HypothesesGraph::Arc Arc;
  typedef HypothesesGraph::NodeIt NodeIt;
  typedef HypothesesGraph::Node Node;
  using lemon::INVALID;

  HypothesesGraph g;
  HypothesesGraph* graph=&g;
  graph->add(node_traxel());

  std::cout << "Adding nodes" << std::endl;
  std::cout <<  std::endl;

  Node n1=g.add_node(0);
  Node n2=g.add_node(0);
  Node n3=g.add_node(0);
  g.add_node(0);
  Node m1=g.add_node(1);
  Node m2=g.add_node(1);
  Node m3=g.add_node(1);
  Node m4=g.add_node(1);
  Node o1=g.add_node(2);
  Node o2=g.add_node(2);
  Node o3=g.add_node(2);
  Node o4=g.add_node(2);

  std::cout << "Nodes:";
  for (NodeIt i(g); i!=INVALID; ++i)
    std::cout << " " << g.id(i);
  std::cout << std::endl;

  std::cout << "Addings arcs" << std::endl;
  std::cout <<  std::endl;

  g.addArc(n1,m2);
  g.addArc(n2,m1);
  g.addArc(n3,m3);
  g.addArc(n3,m4);
  g.addArc(m1,o1);
  g.addArc(m2,o2);
  g.addArc(m4,o3);
  g.addArc(m4,o4);

  std::cout << "Arcs:";
  for (ArcIt2 i(g); i!=INVALID; ++i)
  std::cout << " (" << g.id(g.source(i)) << "," << g.id(g.target(i)) << ")";
  std::cout << std::endl;
  std::cout <<  std::endl;

  std::cout << "Constructing Reasoner" << std::endl;
  std::cout <<  std::endl;

   Traxels empty;
   ConstantEnergy e(25);

   SingleTimestepTraxelMrf mrf(bind<double>(e, _1, empty, empty),		//detection
			        bind<double>(e, _1, empty, empty),		//non_detection
			        bind<double>(e, _1, empty, empty),		//appearance
			        bind<double>(e, _1, empty, empty),		//disappearance
				bind<double>(e, _1, _2, empty, empty),		//move
				bind<double>(e, _1, _2, _3, empty, empty)	//division
			       );

  std::cout << "Formulating Factors" << std::endl;
  std::cout <<  std::endl;

    cout << "-> workflow: formulating model" << endl;
    mrf.formulate( *graph );
    cout << "-> workflow: infer" << endl;
    mrf.infer();
    cout << "-> workflow: conclude" << endl;
    mrf.conclude(*graph);
    prune_inactive(*graph);
}

BOOST_AUTO_TEST_CASE( HypothesesGraph_build_hyp_mrf ) {

    Traxel n1, n2, n3, n4, m1, m2, m3, m4, o1, o2, o3, o4, o5;
    feature_array comn1(feature_array::difference_type(3)); //float vector
    feature_array comn2(feature_array::difference_type(3));
    feature_array comn3(feature_array::difference_type(3));
    feature_array comn4(feature_array::difference_type(3));
    feature_array comm1(feature_array::difference_type(3));
    feature_array comm2(feature_array::difference_type(3));
    feature_array comm3(feature_array::difference_type(3));
    feature_array comm4(feature_array::difference_type(3));
    feature_array como1(feature_array::difference_type(3));
    feature_array como2(feature_array::difference_type(3));
    feature_array como3(feature_array::difference_type(3));
    feature_array como4(feature_array::difference_type(3));
    feature_array como5(feature_array::difference_type(3));

    comn1[0] = 0;
    comn1[1] = 0;
    comn1[2] = 0;
    n1.features["com"] = comn1;
    n1.Id = 11;
    n1.Timestep = 0;

    comn2[0] = 1;
    comn2[1] = 1;
    comn2[2] = 1;
    n2.features["com"] = comn2;
    n2.Id = 12;
    n2.Timestep = 0;

    comn3[0] = 0;
    comn3[1] = 0;
    comn3[2] = 2;
    n3.features["com"] = comn3;
    n3.Id = 13;
    n3.Timestep = 0;

    comn4[0] = 2;
    comn4[1] = 0;
    comn4[2] = 0;
    n4.features["com"] = comn4;
    n4.Id = 14;
    n4.Timestep = 0;

    comm1[0] = 2;
    comm1[1] = 2;
    comm1[2] = 2;
    m1.features["com"] = comm1;
    m1.Id = 21;
    m1.Timestep = 1;

    comm2[0] = 1;
    comm2[1] = 0;
    comm2[2] = 1;
    m2.features["com"] = comm2;
    m2.Id = 22;
    m2.Timestep = 1;

    comm3[0] = 0;
    comm3[1] = 1;
    comm3[2] = 1;
    m3.features["com"] = comm3;
    m3.Id = 23;
    m3.Timestep = 1;

    comm4[0] = 3;
    comm4[1] = 3;
    comm4[2] = 3;
    m4.features["com"] = comm4;
    m4.Id = 24;
    m4.Timestep = 1;

    como1[0] = 4;
    como1[1] = 4;
    como1[2] = 4;
    o1.features["com"] = como1;
    o1.Id = 31;
    o1.Timestep = 2;

    como2[0] = 7;
    como2[1] = 19;
    como2[2] = 8;
    o2.features["com"] = como2;
    o2.Id = 32;
    o2.Timestep = 2;

    como3[0] = 0;
    como3[1] = 7;
    como3[2] = 1;
    o3.features["com"] = como3;
    o3.Id = 33;
    o3.Timestep = 2;

    como4[0] = 5;
    como4[1] = 0;
    como4[2] = 9;
    o4.features["com"] = como4;
    o4.Id = 34;
    o4.Timestep = 2;

    como5[0] = 0;
    como5[1] = 4;
    como5[2] = 0;
    o5.features["com"] = como5;
    o5.Id = 34;
    o5.Timestep = 2;

    TraxelStore ts;
    add(ts,n1);
    add(ts,n2);
    add(ts,n3);
    add(ts,n4);
    add(ts,m1);
    add(ts,m2);
    add(ts,m3);
    add(ts,m4);
    add(ts,o1);
    add(ts,o2);
    add(ts,o3);
    add(ts,o4);
    add(ts,o5);

    SingleTimestepTraxel_HypothesesBuilder builder(&ts);
    HypothesesGraph* graph = builder.build();

    Traxels empty;
    ConstantEnergy e1(10);
    ConstantEnergy e2(90);
    ConstantEnergy e3(70);
    ConstantEnergy e4(50);
    ConstantEnergy e5(20);
    ConstantEnergy e6(5);

    SingleTimestepTraxelMrf mrf(bind<double>(e1, _1, empty, empty),		//detection
			        bind<double>(e2, _1, empty, empty),		//non_detection
			        bind<double>(e3, _1, empty, empty),		//appearance
			        bind<double>(e4, _1, empty, empty),		//disappearance
				bind<double>(e5, _1, _2, empty, empty),		//move
				bind<double>(e6, _1, _2, _3, empty, empty)	//division
			       );
    cout << "-> workflow: formulating model" << endl;
    mrf.formulate( *graph );
    cout << "-> workflow: infer" << endl;
    mrf.infer();
    cout << "-> workflow: conclude" << endl;
    mrf.conclude(*graph);
    prune_inactive(*graph);
}
<|endoftext|>


<commit_before>/*
 * 	SnapFind (Release 0.9)
 *      An interactive image search application
 *
 *      Copyright (c) 2002-2005, Intel Corporation
 *      All Rights Reserved
 *
 *  This software is distributed under the terms of the Eclipse Public
 *  License, Version 1.0 which can be found in the file named LICENSE.
 *  ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS SOFTWARE CONSTITUTES
 *  RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include <sys/time.h>
#include <math.h>
#include <libgen.h>
#include <stdint.h>
#include <limits.h>
#include <ctype.h>
#include <assert.h>

#include "searchlet_api.h"
#include "lib_results.h"
#include "lib_sfimage.h"
#include "sf_consts.h"
#include "ring.h"
#include "face_search.h"
#include "search_set.h"
#include "sfind_search.h"
#include "plugin.h"

extern pthread_mutex_t ring_mutex;
/*
 * this need to be global because we share it with the main
 * GUI.  XXX hack, do it right later.
 */
ls_search_handle_t shandle;

/*
 * state the is global to all of these functions.
 */
/* XXX global for status window, fix  this someday */
int      search_active = 0;
static int     active  = 0;
int      search_number = 0;
struct timeval	search_start;

static search_set *sset = NULL;

/*
 * This initializes the search  state.
 */

void
init_search()
{
	shandle = ls_init_search();
	if (shandle == NULL) {
		printf("failed to initialize:  !! \n");
		exit(1);
	}
}

void
set_searchlist(int n, groupid_t * gids)
{
	int             err;

	err = ls_set_searchlist(shandle, n, gids);
	if (err) {
		printf("Failed to set searchlist on  err %d \n", err);
		exit(1);
	}
}

/*
 * This function initiates the search by building a filter
 * specification, setting the searchlet and then starting the search.
 */
void
do_search(gid_list_t * main_region, char *fspec)
{
	int             err;
	char           *filter_name;
	char           *dir_name;
	void 	       *cookie;
	img_search     *search;

	if (!fspec) {
		fspec = sset->build_filter_spec(NULL);
		if (fspec == NULL) {
			printf("failed to build filter specification \n");
			exit(1);
		}
	}

	dir_name = (char *) malloc(SF_MAX_PATH);
	if (dir_name == NULL) {
		exit(1);                /* XXX */
	}

	set_searchlist(main_region->ngids, main_region->gids);

	filter_name = first_searchlet_lib(&cookie);
	if (filter_name == NULL) {
		fprintf(stderr, "No filter libraries are defined \n");
		assert(0);
	}

	err = ls_set_searchlet(shandle, DEV_ISA_IA32, filter_name, fspec);
	if (err) {
		printf("Failed to set searchlet on err %d \n", err);
		exit(1);
	}
	free(filter_name);

	while ((filter_name = next_searchlet_lib(&cookie)) != NULL) {
		err = ls_add_filter_file(shandle, DEV_ISA_IA32, filter_name);
		free(filter_name);
	}

	/*
	 * Attach auxiliary data for this search.
	 */
	for (filter_name = first_searchlet_lib(&cookie);
	     filter_name != NULL;
	     filter_name = next_searchlet_lib(&cookie)) {
		if (((search = sset->find_search(filter_name)) != NULL) &&
		    search->is_selected()) {
			err = ls_set_blob(shandle,
					  (char *)search->get_name(),
					  search->get_auxiliary_data_length(),
					  search->get_auxiliary_data());
			if (err) {
			  printf("Failed to set data on %s, err %d \n",
				 (char *)search->get_name(), err);
			  exit(1);
			}
		}
		free(filter_name);
	}

	/*
	 * Go ahead and start the search.
	 */
	err = ls_start_search(shandle);
	if (err) {
		printf("Failed to start search on err %d \n", err);
		exit(1);
	}
}

/*
 *  Stops a currently executing search.
 */
static void
stop_search(void *data)
{
	int             err;
	err = ls_terminate_search(shandle);
	if (err != 0) {
		printf("XXX failed to terminate search \n");
		exit(1);
	}
}

void
drain_ring(ring_data_t * ring)
{
	while (!ring_empty(ring)) {
		void           *msg = ring_deq(ring);
		free(msg);
	}
	assert(ring_empty(ring));

}

/*
 * This processes a message (command) from the interface
 * GUI to control the processing.
 */

void
handle_message(message_t * new_message)
{
	struct timezone tz;
	int				err;

	switch (new_message->type) {
		case START_SEARCH:

			assert(ring_empty(from_search_thread));
			/*
			 * delete old msgs
			 */
			pthread_mutex_lock(&ring_mutex);
			drain_ring(from_search_thread);
			pthread_mutex_unlock(&ring_mutex);
			do_search((gid_list_t *) new_message->data, NULL);
			active = 1;
			search_active = 1;
			search_number++;
			err = gettimeofday(&search_start, &tz);
			assert(err == 0);
			break;

		case TERM_SEARCH:
			stop_search(new_message->data);
			search_active = 0;
			break;

			/*
			 * XXX get stats ???
			 */

		default:
			printf("XXX unknown message %d \n", new_message->type);
			assert(0);
			break;
	}
}

void
update_stats()
{
	int             num_dev;
	ls_dev_handle_t dev_list[SF_MAX_DEVICES];
	int             i, err, len;
	dev_stats_t    *dstats;
	int             tobj = 0, sobj = 0, dobj = 0;

	dstats = (dev_stats_t *) malloc(DEV_STATS_SIZE(SF_MAX_FILTERS));
	assert(dstats);

	num_dev = SF_MAX_DEVICES;

	err = ls_get_dev_list(shandle, dev_list, &num_dev);
	if (err != 0) {
		printf("update states: %d \n", err);
		exit(1);
	}

	for (i = 0; i < num_dev; i++) {
		len = DEV_STATS_SIZE(SF_MAX_FILTERS);
		err = ls_get_dev_stats(shandle, dev_list[i], dstats, &len);
		if (err) {
			printf("Failed to get dev stats \n");
			exit(1);
		}
		tobj += dstats->ds_objs_total;
		sobj += dstats->ds_objs_processed;
		dobj += dstats->ds_objs_dropped;
	}
	free(dstats);

	tobj_cnt = tobj;
	sobj_cnt = sobj;
	dobj_cnt = dobj;
}

/*
 * This is main function that is called thread interacting with the
 * search subsystem.
 */

void           *
sfind_search_main(void *foo)
{

	message_t      *message;
	ls_obj_handle_t cur_obj;
	int             err;
	int             temp;

	struct timespec timeout;

	sset = (search_set *)foo;

	/*
	 * XXX init_search();
	 */

	while (1) {
		message = (message_t *) ring_deq(to_search_thread);
		if (message != NULL) {
			handle_message(message);
			free(message);
		}
		if ((active) && (ring_count(from_search_thread) < 7)) {
			err = ls_next_object(shandle, &cur_obj, LSEARCH_NO_BLOCK);
			if (err == EWOULDBLOCK) {
				/*
				 * no data is available, sleep for a small amount of time.
				 */
				timeout.tv_sec = 0;
				timeout.tv_nsec = 10000000; /* XXX 10ms ?? */
				nanosleep(&timeout, NULL);
			} else if (err == ENOENT) {
				fprintf(stderr, "No more objects \n");  /* XXX */
				search_active = 0;
				active = 0;
				message = (message_t *) malloc(sizeof(*message));
				if (message == NULL) {
					fprintf(stderr, "non mem\n");
					exit(1);
				}
				message->type = DONE_OBJECTS;
				message->data = NULL;

				pthread_mutex_lock(&ring_mutex);
				err = ring_enq(from_search_thread, message);
				pthread_mutex_unlock(&ring_mutex);
				if (err) {
					fprintf(stderr, "XXX failed to enq \n");
					exit(1);
				}

				timeout.tv_sec = 0;
				timeout.tv_nsec = 100000000;    /* XXX 100ms ?? */
				nanosleep(&timeout, NULL);

			} else if (err != 0) {
				/*
				 * XXX
				 */
				fprintf(stderr, "get_next_obj: failed on %d \n", err);
				exit(1);
			} else {
				message = (message_t *) malloc(sizeof(*message));
				assert(message != NULL);

				message->type = NEXT_OBJECT;
				message->data = cur_obj;
				pthread_mutex_lock(&ring_mutex);
				err = ring_enq(from_search_thread, message);
				pthread_mutex_unlock(&ring_mutex);
				if (err) {
					/*
					 * drop this on the floor
					 */
					ls_release_object(shandle, cur_obj);
					free(message);
				}
			}
		} else {
			timeout.tv_sec = 0;
			timeout.tv_nsec = 100000000;    /* XXX 100ms ?? */
			nanosleep(&timeout, NULL);
		}
		err = ls_num_objects(shandle, &temp);
		temp += ring_count(from_search_thread);

		pend_obj_cnt = temp;
		update_stats();
	}
	return (0);
}
<commit_msg>attach blobs per filter instance, not filter type<commit_after>/*
 * 	SnapFind (Release 0.9)
 *      An interactive image search application
 *
 *      Copyright (c) 2002-2005, Intel Corporation
 *      All Rights Reserved
 *
 *  This software is distributed under the terms of the Eclipse Public
 *  License, Version 1.0 which can be found in the file named LICENSE.
 *  ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS SOFTWARE CONSTITUTES
 *  RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include <sys/time.h>
#include <math.h>
#include <libgen.h>
#include <stdint.h>
#include <limits.h>
#include <ctype.h>
#include <assert.h>

#include "searchlet_api.h"
#include "lib_results.h"
#include "lib_sfimage.h"
#include "sf_consts.h"
#include "ring.h"
#include "face_search.h"
#include "search_set.h"
#include "sfind_search.h"
#include "plugin.h"

extern pthread_mutex_t ring_mutex;
/*
 * this need to be global because we share it with the main
 * GUI.  XXX hack, do it right later.
 */
ls_search_handle_t shandle;

/*
 * state the is global to all of these functions.
 */
/* XXX global for status window, fix  this someday */
int      search_active = 0;
static int     active  = 0;
int      search_number = 0;
struct timeval	search_start;

static search_set *sset = NULL;

/*
 * This initializes the search  state.
 */

void
init_search()
{
	shandle = ls_init_search();
	if (shandle == NULL) {
		printf("failed to initialize:  !! \n");
		exit(1);
	}
}

void
set_searchlist(int n, groupid_t * gids)
{
	int             err;

	err = ls_set_searchlist(shandle, n, gids);
	if (err) {
		printf("Failed to set searchlist on  err %d \n", err);
		exit(1);
	}
}

/*
 * This function initiates the search by building a filter
 * specification, setting the searchlet and then starting the search.
 */
void
do_search(gid_list_t * main_region, char *fspec)
{
	int             err;
	char           *filter_name;
	char           *dir_name;
	void 	       *cookie;
	img_search     *search;
	search_iter_t iter;

	if (!fspec) {
		fspec = sset->build_filter_spec(NULL);
		if (fspec == NULL) {
			printf("failed to build filter specification \n");
			exit(1);
		}
	}

	dir_name = (char *) malloc(SF_MAX_PATH);
	if (dir_name == NULL) {
		exit(1);                /* XXX */
	}

	set_searchlist(main_region->ngids, main_region->gids);

	filter_name = first_searchlet_lib(&cookie);
	if (filter_name == NULL) {
		fprintf(stderr, "No filter libraries are defined \n");
		assert(0);
	}

	err = ls_set_searchlet(shandle, DEV_ISA_IA32, filter_name, fspec);
	if (err) {
		printf("Failed to set searchlet on err %d \n", err);
		exit(1);
	}
	free(filter_name);

	while ((filter_name = next_searchlet_lib(&cookie)) != NULL) {
		err = ls_add_filter_file(shandle, DEV_ISA_IA32, filter_name);
		free(filter_name);
	}

	/*
	 * Attach auxiliary data for this search.
	 */
	for (filter_name = first_searchlet_lib(&cookie);
	     filter_name != NULL;
	     filter_name = next_searchlet_lib(&cookie)) {

     	// filter_name refers to the name of the filter library
		sset->reset_search_iter(&iter);
		while ((search = sset->find_search(filter_name, &iter)) != NULL) {
			if (search->is_selected()) {
				err = ls_set_blob(shandle,
				  	(char *)search->get_name(),
				  	search->get_auxiliary_data_length(),
				  	search->get_auxiliary_data());
				if (err) {
		  			printf("Failed to set data on %s, err %d \n",
							 (char *)search->get_name(), err);
				}
			}
		}
	}
	free(filter_name);

	/*
	 * Go ahead and start the search.
	 */
	err = ls_start_search(shandle);
	if (err) {
		printf("Failed to start search on err %d \n", err);
		exit(1);
	}
}

/*
 *  Stops a currently executing search.
 */
static void
stop_search(void *data)
{
	int             err;
	err = ls_terminate_search(shandle);
	if (err != 0) {
		printf("XXX failed to terminate search \n");
		exit(1);
	}
}

void
drain_ring(ring_data_t * ring)
{
	while (!ring_empty(ring)) {
		void           *msg = ring_deq(ring);
		free(msg);
	}
	assert(ring_empty(ring));

}

/*
 * This processes a message (command) from the interface
 * GUI to control the processing.
 */

void
handle_message(message_t * new_message)
{
	struct timezone tz;
	int				err;

	switch (new_message->type) {
		case START_SEARCH:

			assert(ring_empty(from_search_thread));
			/*
			 * delete old msgs
			 */
			pthread_mutex_lock(&ring_mutex);
			drain_ring(from_search_thread);
			pthread_mutex_unlock(&ring_mutex);
			do_search((gid_list_t *) new_message->data, NULL);
			active = 1;
			search_active = 1;
			search_number++;
			err = gettimeofday(&search_start, &tz);
			assert(err == 0);
			break;

		case TERM_SEARCH:
			stop_search(new_message->data);
			search_active = 0;
			break;

			/*
			 * XXX get stats ???
			 */

		default:
			printf("XXX unknown message %d \n", new_message->type);
			assert(0);
			break;
	}
}

void
update_stats()
{
	int             num_dev;
	ls_dev_handle_t dev_list[SF_MAX_DEVICES];
	int             i, err, len;
	dev_stats_t    *dstats;
	int             tobj = 0, sobj = 0, dobj = 0;

	dstats = (dev_stats_t *) malloc(DEV_STATS_SIZE(SF_MAX_FILTERS));
	assert(dstats);

	num_dev = SF_MAX_DEVICES;

	err = ls_get_dev_list(shandle, dev_list, &num_dev);
	if (err != 0) {
		printf("update states: %d \n", err);
		exit(1);
	}

	for (i = 0; i < num_dev; i++) {
		len = DEV_STATS_SIZE(SF_MAX_FILTERS);
		err = ls_get_dev_stats(shandle, dev_list[i], dstats, &len);
		if (err) {
			printf("Failed to get dev stats \n");
			exit(1);
		}
		tobj += dstats->ds_objs_total;
		sobj += dstats->ds_objs_processed;
		dobj += dstats->ds_objs_dropped;
	}
	free(dstats);

	tobj_cnt = tobj;
	sobj_cnt = sobj;
	dobj_cnt = dobj;
}

/*
 * This is main function that is called thread interacting with the
 * search subsystem.
 */

void           *
sfind_search_main(void *foo)
{

	message_t      *message;
	ls_obj_handle_t cur_obj;
	int             err;
	int             temp;

	struct timespec timeout;

	sset = (search_set *)foo;

	/*
	 * XXX init_search();
	 */

	while (1) {
		message = (message_t *) ring_deq(to_search_thread);
		if (message != NULL) {
			handle_message(message);
			free(message);
		}
		if ((active) && (ring_count(from_search_thread) < 7)) {
			err = ls_next_object(shandle, &cur_obj, LSEARCH_NO_BLOCK);
			if (err == EWOULDBLOCK) {
				/*
				 * no data is available, sleep for a small amount of time.
				 */
				timeout.tv_sec = 0;
				timeout.tv_nsec = 10000000; /* XXX 10ms ?? */
				nanosleep(&timeout, NULL);
			} else if (err == ENOENT) {
				fprintf(stderr, "No more objects \n");  /* XXX */
				search_active = 0;
				active = 0;
				message = (message_t *) malloc(sizeof(*message));
				if (message == NULL) {
					fprintf(stderr, "non mem\n");
					exit(1);
				}
				message->type = DONE_OBJECTS;
				message->data = NULL;

				pthread_mutex_lock(&ring_mutex);
				err = ring_enq(from_search_thread, message);
				pthread_mutex_unlock(&ring_mutex);
				if (err) {
					fprintf(stderr, "XXX failed to enq \n");
					exit(1);
				}

				timeout.tv_sec = 0;
				timeout.tv_nsec = 100000000;    /* XXX 100ms ?? */
				nanosleep(&timeout, NULL);

			} else if (err != 0) {
				/*
				 * XXX
				 */
				fprintf(stderr, "get_next_obj: failed on %d \n", err);
				exit(1);
			} else {
				message = (message_t *) malloc(sizeof(*message));
				assert(message != NULL);

				message->type = NEXT_OBJECT;
				message->data = cur_obj;
				pthread_mutex_lock(&ring_mutex);
				err = ring_enq(from_search_thread, message);
				pthread_mutex_unlock(&ring_mutex);
				if (err) {
					/*
					 * drop this on the floor
					 */
					ls_release_object(shandle, cur_obj);
					free(message);
				}
			}
		} else {
			timeout.tv_sec = 0;
			timeout.tv_nsec = 100000000;    /* XXX 100ms ?? */
			nanosleep(&timeout, NULL);
		}
		err = ls_num_objects(shandle, &temp);
		temp += ring_count(from_search_thread);

		pend_obj_cnt = temp;
		update_stats();
	}
	return (0);
}
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2012 Artem Pavlenko
 *
 * 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.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_UTIL_CONVERSIONS_HPP
#define MAPNIK_UTIL_CONVERSIONS_HPP

// mapnik
#include <mapnik/config.hpp>

// stl
#include <string>
// boost
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/karma.hpp>

// boost
#include <boost/version.hpp>

#if BOOST_VERSION >= 104500
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/karma.hpp>
#else
#include <boost/lexical_cast.hpp>
#endif

namespace mapnik { namespace util {

MAPNIK_DECL bool string2int(const char * value, int & result);
MAPNIK_DECL bool string2int(std::string const& value, int & result);

MAPNIK_DECL bool string2double(std::string const& value, double & result);
MAPNIK_DECL bool string2double(const char * value, double & result);

MAPNIK_DECL bool string2float(std::string const& value, float & result);
MAPNIK_DECL bool string2float(const char * value, float & result);

#if BOOST_VERSION >= 104500
// generic
template <typename T>
bool to_string(std::string & str, T value)
{
  namespace karma = boost::spirit::karma;
  std::back_insert_iterator<std::string> sink(str);
  return karma::generate(sink, value);
}

template <typename T>
struct double_policy : boost::spirit::karma::real_policies<T>
{
    typedef boost::spirit::karma::real_policies<T> base_type;
    static int floatfield(T n) { return base_type::fmtflags::fixed; }
    static unsigned precision(T n) { return 16 ;}
};

// specialisation for double
template <>
inline bool to_string(std::string & str, double value)
{
    namespace karma = boost::spirit::karma;
    typedef boost::spirit::karma::real_generator<double, double_policy<double> > double_type;
    std::back_insert_iterator<std::string> sink(str);
    return karma::generate(sink, double_type(), value);
}

#else

template <typename T>
bool to_string(std::string & str, T value)
{
    try
    {
        str = boost::lexical_cast<T>(value);
        return true;
    }
    catch (std::exception const& ex)
    {
        return false;
    }
}

#endif

}}

#endif // MAPNIK_UTIL_CONVERSIONS_HPP
<commit_msg>Fix float data conversion to string<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2012 Artem Pavlenko
 *
 * 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.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_UTIL_CONVERSIONS_HPP
#define MAPNIK_UTIL_CONVERSIONS_HPP

// mapnik
#include <mapnik/config.hpp>

// stl
#include <string>
// boost
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/karma.hpp>

// boost
#include <boost/version.hpp>

#if BOOST_VERSION >= 104500
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/karma.hpp>
#else
#include <boost/lexical_cast.hpp>
#endif

namespace mapnik { namespace util {

MAPNIK_DECL bool string2int(const char * value, int & result);
MAPNIK_DECL bool string2int(std::string const& value, int & result);

MAPNIK_DECL bool string2double(std::string const& value, double & result);
MAPNIK_DECL bool string2double(const char * value, double & result);

MAPNIK_DECL bool string2float(std::string const& value, float & result);
MAPNIK_DECL bool string2float(const char * value, float & result);

#if BOOST_VERSION >= 104500
// generic
template <typename T>
bool to_string(std::string & str, T value)
{
  namespace karma = boost::spirit::karma;
  std::back_insert_iterator<std::string> sink(str);
  return karma::generate(sink, value);
}

template <typename T>
struct double_policy : boost::spirit::karma::real_policies<T>
{
    typedef boost::spirit::karma::real_policies<T> base_type;
    static int floatfield(T n) { return base_type::fmtflags::fixed; }
    static unsigned precision(T n) { return 15 - trunc(log10(n)); }
    template <typename OutputIterator>
    static bool dot(OutputIterator& sink, T n, unsigned precision) {
      return n ? *sink = '.', true : false;
    }
};

// specialisation for double
template <>
inline bool to_string(std::string & str, double value)
{
    namespace karma = boost::spirit::karma;
    typedef karma::real_generator<double, double_policy<double> > double_type;
    std::back_insert_iterator<std::string> sink(str);
    return karma::generate(sink, double_type(), value);
}

#else

template <typename T>
bool to_string(std::string & str, T value)
{
    try
    {
        str = boost::lexical_cast<T>(value);
        return true;
    }
    catch (std::exception const& ex)
    {
        return false;
    }
}

#endif

}}

#endif // MAPNIK_UTIL_CONVERSIONS_HPP
<|endoftext|>


<commit_before>/*
Copyright 2015 Adam Grandquist

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.
 */
/**
 * @author Adam Grandquist
 * @copyright Apache
 */

#include "./cpp/wrapper.hpp"

using namespace ReQL;

Wrapper::Wrapper(ReQL_Obj_t *obj) : std::unique_ptr<ReQL_Obj_t>(obj) {
  switch (reql_datum_type(obj)) {
    case REQL_R_ARRAY: {
      break;
    }
    case REQL_R_BOOL: {
      break;
    }
    case REQL_R_JSON: throw;
    case REQL_R_NULL: {
      break;
    }
    case REQL_R_NUM: {
      break;
    }
    case REQL_R_OBJECT: {
      break;
    }
    case REQL_R_REQL: {
      break;
    }
    case REQL_R_STR: {
      break;
    }
  }
}

Wrapper::~Wrapper() {}
<commit_msg>Be consistent with use of namespaces.<commit_after>/*
Copyright 2015 Adam Grandquist

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.
 */
/**
 * @author Adam Grandquist
 * @copyright Apache
 */

#include "./cpp/wrapper.hpp"

namespace ReQL {

Wrapper::Wrapper(ReQL_Obj_t *obj) : std::unique_ptr<ReQL_Obj_t>(obj) {
  switch (reql_datum_type(obj)) {
    case REQL_R_ARRAY: {
      break;
    }
    case REQL_R_BOOL: {
      break;
    }
    case REQL_R_JSON: throw;
    case REQL_R_NULL: {
      break;
    }
    case REQL_R_NUM: {
      break;
    }
    case REQL_R_OBJECT: {
      break;
    }
    case REQL_R_REQL: {
      break;
    }
    case REQL_R_STR: {
      break;
    }
  }
}

Wrapper::~Wrapper() {}

}
<|endoftext|>


<commit_before>#include "register.h"

#include "../util/log.h"

u8 WordRegister::low() const {
    return static_cast<u8>(val);
}

u8 WordRegister::high() const {
    return static_cast<u8>((val) >> 8);
}

RegisterPair::RegisterPair(ByteRegister& high, ByteRegister& low) :
        low_byte(low),
        high_byte(high)
{
}

void RegisterPair::set_low(const u8 byte) {
    low_byte.set(byte);
}

void RegisterPair::set_high(const u8 byte) {
    high_byte.set(byte);
}

void RegisterPair::set_low(const ByteRegister& byte) {
    low_byte.set(byte.value());
}

void RegisterPair::set_high(const ByteRegister& byte) {
    low_byte.set(byte.value());
}

void RegisterPair::set(const u16 word) {
    /* Discard the upper byte */
    low_byte.set(static_cast<u8>(word));

    /* Discard the lower byte */
    high_byte.set(static_cast<u8>((word) >> 8));
}

u8 RegisterPair::low() const {
    return low_byte.value();
}

u8 RegisterPair::high() const {
    return high_byte.value();
}

u16 RegisterPair::value() const {
    return (high_byte.value() << 8) + low_byte.value();
}

void RegisterPair::increment() {
    set(value() + 1);
}

void RegisterPair::decrement() {
    set(value() - 1);
}
<commit_msg>Avoid a warning about precision loss by using compose_bytes<commit_after>#include "register.h"

#include "../bitwise.h"
#include "../util/log.h"

u8 WordRegister::low() const {
    return static_cast<u8>(val);
}

u8 WordRegister::high() const {
    return static_cast<u8>((val) >> 8);
}

RegisterPair::RegisterPair(ByteRegister& high, ByteRegister& low) :
        low_byte(low),
        high_byte(high)
{
}

void RegisterPair::set_low(const u8 byte) {
    low_byte.set(byte);
}

void RegisterPair::set_high(const u8 byte) {
    high_byte.set(byte);
}

void RegisterPair::set_low(const ByteRegister& byte) {
    low_byte.set(byte.value());
}

void RegisterPair::set_high(const ByteRegister& byte) {
    low_byte.set(byte.value());
}

void RegisterPair::set(const u16 word) {
    /* Discard the upper byte */
    low_byte.set(static_cast<u8>(word));

    /* Discard the lower byte */
    high_byte.set(static_cast<u8>((word) >> 8));
}

u8 RegisterPair::low() const {
    return low_byte.value();
}

u8 RegisterPair::high() const {
    return high_byte.value();
}

u16 RegisterPair::value() const {
    return compose_bytes(high_byte.value(), low_byte.value());
}

void RegisterPair::increment() {
    set(value() + 1);
}

void RegisterPair::decrement() {
    set(value() - 1);
}
<|endoftext|>


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

#include <cassert>
#include <cstdarg>
#include <map>
#include <stack>
#include <string>

#include "amxdebuginfo.h"
#include "amxpathfinder.h"
#include "amxstacktrace.h"
#include "amxutils.h"
#include "compiler.h"
#include "configreader.h"
#include "crashdetect.h"
#include "fileutils.h"
#include "logprintf.h"
#include "os.h"
#include "stacktrace.h"

#include "amx/amx.h"
#include "amx/amxaux.h" // for amx_StrError()

#define AMX_EXEC_GDK (-10)

static const char *kLogMessagePrefix = "[debug] ";
static const char *kServerConfig = "server.cfg";

bool crashdetect::errorCaught_ = false;
std::stack<crashdetect::NPCall> crashdetect::npCalls_;
ConfigReader crashdetect::serverCfg(kServerConfig);
crashdetect::InstanceMap crashdetect::instances_;

// static
crashdetect *crashdetect::GetInstance(AMX *amx) {
	InstanceMap::const_iterator iterator = instances_.find(amx);
	if (iterator == instances_.end()) {
		crashdetect *c = new crashdetect(amx);
		instances_.insert(std::make_pair(amx, c));
		return c;
	}
	return iterator->second;
}

// static
void crashdetect::DestroyInstance(AMX *amx) {
	instances_.erase(amx);
}

// static
void crashdetect::SystemException(void *context) {
	if (!npCalls_.empty()) {
		AMX *amx = npCalls_.top().amx();
		GetInstance(amx)->HandleException();
	} else {
		logprintf("Server crashed due to an unknown error");
	}
	PrintSystemBacktrace(context);
}

// static
void crashdetect::SystemInterrupt() {
	if (!npCalls_.empty()) {
		AMX *amx = npCalls_.top().amx();
		GetInstance(amx)->HandleInterrupt();
	} else {
		logprintf("Server recieved interrupt signal");
	}
	PrintSystemBacktrace();
}

// static
void crashdetect::DieOrContinue() {
	if (serverCfg.GetOption("die_on_error", false)) {
		logprintf("Aborting...");
		std::exit(EXIT_FAILURE);
	}
}

crashdetect::crashdetect(AMX *amx)
	: amx_(amx)
	, amxhdr_(reinterpret_cast<AMX_HEADER*>(amx->base))
{
	AMXPathFinder pathFinder;
	pathFinder.AddSearchPath("gamemodes");
	pathFinder.AddSearchPath("filterscripts");

	// Read a list of additional search paths from AMX_PATH.
	const char *AMX_PATH = getenv("AMX_PATH");
	if (AMX_PATH != 0) {
		std::string var(AMX_PATH);
		std::string path;
		std::string::size_type begin = 0;
		while (begin < var.length()) {
			std::string::size_type end = var.find(fileutils::kNativePathListSepChar, begin);
			if (end == std::string::npos) {
				end = var.length();
			}
			path.assign(var.begin() + begin, var.begin() + end);
			if (!path.empty()) {
				pathFinder.AddSearchPath(path);
			}
			begin = end + 1;
		}
	}

	amxPath_ = pathFinder.FindAMX(amx);
	amxName_ = fileutils::GetFileName(amxPath_);

	if (!amxPath_.empty()) {
		uint16_t flags;
		amx_Flags(amx_, &flags);
		if ((flags & AMX_FLAG_DEBUG) != 0) {
			debugInfo_.Load(amxPath_);
		}
	}

	amx_->sysreq_d = 0;
	prevCallback_ = amx_->callback;
}

int crashdetect::DoAmxCallback(cell index, cell *result, cell *params) {
	npCalls_.push(NPCall(NPCall::NATIVE, amx_, index, amx_->frm, amx_->cip));
	int retcode = prevCallback_(amx_, index, result, params);
	npCalls_.pop();
	return retcode;
}

int crashdetect::DoAmxExec(cell *retval, int index) {
	npCalls_.push(NPCall(NPCall::PUBLIC, amx_, index, amx_->frm, amx_->cip));

	int retcode = ::amx_Exec(amx_, retval, index);
	if (retcode != AMX_ERR_NONE && !errorCaught_) {
		amx_Error(amx_, index, retcode);
	} else {
		errorCaught_ = false;
	}

	npCalls_.pop();
	return retcode;
}

int crashdetect::DoAmxRelease(cell amx_addr, void *releaser) {
	if (amx_addr < amx_->hlw || amx_addr >= amx_->stk) {
		HandleReleaseError(amx_addr, releaser);
	}
	return amx_Release(amx_, amx_addr);
}

void crashdetect::HandleExecError(int index, int error) {
	crashdetect::errorCaught_ = true;

	if (error == AMX_ERR_INDEX && index == AMX_EXEC_GDK) {
		error = AMX_ERR_NONE;
		return;
	}

	logprintf("Run time error %d: \"%s\"", error, aux_StrError(error));

	switch (error) {
		case AMX_ERR_BOUNDS: {
			cell bound = *(reinterpret_cast<cell*>(amx_->cip + amx_->base + amxhdr_->cod + sizeof(cell)));
			cell index = amx_->pri;
			if (index < 0) {
				logprintf(" Accessing element at negative index %d", index);
			} else {
				logprintf(" Accessing element at index %d past array upper bound %d", index, bound);
			}
			break;
		}
		case AMX_ERR_NOTFOUND: {
			AMX_FUNCSTUBNT *natives = reinterpret_cast<AMX_FUNCSTUBNT*>(amx_->base + amxhdr_->natives);
			int numNatives = 0;
			amx_NumNatives(amx_, &numNatives);
			for (int i = 0; i < numNatives; ++i) {
				if (natives[i].address == 0) {
					char *name = reinterpret_cast<char*>(natives[i].nameofs + amx_->base);
					logprintf(" %s", name);
				}
			}
			break;
		}
		case AMX_ERR_STACKERR:
			logprintf(" Stack pointer (STK) is 0x%X, heap pointer (HEA) is 0x%X", amx_->stk, amx_->hea);
			break;
		case AMX_ERR_STACKLOW:
			logprintf(" Stack pointer (STK) is 0x%X, stack top (STP) is 0x%X", amx_->stk, amx_->stp);
			break;
		case AMX_ERR_HEAPLOW:
			logprintf(" Heap pointer (HEA) is 0x%X, heap bottom (HLW) is 0x%X", amx_->hea, amx_->hlw);
			break;
		case AMX_ERR_INVINSTR: {
			cell opcode = *(reinterpret_cast<cell*>(amx_->cip + amx_->base + amxhdr_->cod));
			logprintf(" Unknown opcode 0x%x at address 0x%08X", opcode , amx_->cip);
			break;
		}
	}

	if (error != AMX_ERR_NOTFOUND &&
		error != AMX_ERR_INDEX &&
		error != AMX_ERR_CALLBACK &&
		error != AMX_ERR_INIT)
	{
		PrintAmxBacktrace();
	}

	std::string command = serverCfg.GetOption("run_on_error", std::string());
	if (!command.empty()) {
		std::system(command.c_str());
	}

	DieOrContinue();
}

void crashdetect::HandleException() {
	logprintf("Server crashed while executing %s", amxName_.c_str());
	PrintAmxBacktrace();
}

void crashdetect::HandleInterrupt() {
	logprintf("Server recieved interrupt signal while executing %s", amxName_.c_str());
	PrintAmxBacktrace();
}

void crashdetect::HandleReleaseError(cell address, void *releaser) {
	std::string plugin = fileutils::GetFileName(os::GetModulePathFromAddr(releaser));
	if (plugin.empty()) {
		plugin.assign("<unknown>");
	}
	logprintf("Bad heap release detected:");
	logprintf(" %s [%08x] is releasing memory at %08x which is out of heap", plugin.c_str(), releaser, address);
	PrintSystemBacktrace();
}

// static
void crashdetect::PrintAmxBacktrace() {
	if (npCalls_.empty()) {
		return;
	}

	std::stack<NPCall> npCallStack = npCalls_;
	cell frm = npCallStack.top().amx()->frm;
	cell cip = npCallStack.top().amx()->cip;
	int level = 0;

	if (cip == 0) {
		return;
	}

	logprintf("AMX backtrace:");

	while (!npCallStack.empty() && cip != 0) {
		NPCall call = npCallStack.top();

		if (call.amx() != npCallStack.top().amx()) {
			assert(level != 0);
			break;
		}

		if (call.type() == NPCall::NATIVE) {
			AMX_NATIVE address = amxutils::GetNativeAddress(call.amx(), call.index());
			if (address != 0) {
				std::string module = fileutils::GetFileName(os::GetModulePathFromAddr((void*)address));
				std::string from = " from " + module;
				if (module.empty()) {
					from.clear();
				}
				const char *name = amxutils::GetNativeName(call.amx(), call.index());
				if (name != 0) {
					logprintf("#%d native %s () [%08x]%s", level++, name, address, from.c_str());
				}
			}
		} else if (call.type() == NPCall::PUBLIC) {
			AMXDebugInfo &debugInfo = instances_[call.amx()]->debugInfo_;

			amxutils::PushStack(call.amx(), cip); // push return address
			amxutils::PushStack(call.amx(), frm); // push frame pointer
			frm = call.amx()->stk;

			AMXStackTrace trace(call.amx(), debugInfo, frm);
			std::deque<AMXStackFrame> frames = trace.GetFrames();

			frm = amxutils::PopStack(call.amx()); // pop frame pointer
			cip = amxutils::PopStack(call.amx()); // pop return address

			if (frames.empty()) {
				ucell epAddr = amxutils::GetPublicAddress(call.amx(), call.index());
				frames.push_front(AMXStackFrame(call.amx(), frm, 0, epAddr, debugInfo));
			} else {
				if (!debugInfo.IsLoaded()) {
					AMXStackFrame &bottom = frames.back();
					bottom = AMXStackFrame(call.amx(),
						bottom.GetFrameAddress(),
						bottom.GetReturnAddress(),
						amxutils::GetPublicAddress(call.amx(), call.index()),
						debugInfo);
				}
			}

			std::string &amxName = instances_[call.amx()]->amxName_;
			for (size_t i = 0; i < frames.size(); i++) {
				std::string from = " from " + amxName;
				if (amxName.empty() || debugInfo.IsLoaded()) {
					from.clear();
				}
				logprintf("#%d %s%s", level++, frames[i].GetString().c_str(), from.c_str());
			}

			frm = call.frm();
			cip = call.cip();
		}
		npCallStack.pop();
	}
}

// static
void crashdetect::PrintSystemBacktrace(void *context) {
	logprintf("System backtrace:");

	int level = 0;

	StackTrace trace(context);
	std::deque<StackFrame> frames = trace.GetFrames();

	for (std::deque<StackFrame>::const_iterator iterator = frames.begin();
			iterator != frames.end(); ++iterator) {
		const StackFrame &frame = *iterator;

		std::string module = os::GetModulePathFromAddr(frame.GetReturnAddress());
		std::string from = " from " + module;
		if (module.empty()) {
			from.clear();
		}

		logprintf("#%d %s%s", level++, frame.GetString().c_str(), from.c_str());
	}
}

// static
void crashdetect::logprintf(const char *format, ...) {
	std::va_list args;
	va_start(args, format);

	std::string prefixed_format;
	prefixed_format.append(kLogMessagePrefix);
	prefixed_format.append(format);

	::vlogprintf(prefixed_format.c_str(), args);

	va_end(args);
}
<commit_msg>Fix missing #include <cstdlib><commit_after>// Copyright (c) 2011-2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <cassert>
#include <cstdarg>
#include <cstdlib>
#include <map>
#include <stack>
#include <string>

#include "amxdebuginfo.h"
#include "amxpathfinder.h"
#include "amxstacktrace.h"
#include "amxutils.h"
#include "compiler.h"
#include "configreader.h"
#include "crashdetect.h"
#include "fileutils.h"
#include "logprintf.h"
#include "os.h"
#include "stacktrace.h"

#include "amx/amx.h"
#include "amx/amxaux.h" // for amx_StrError()

#define AMX_EXEC_GDK (-10)

static const char *kLogMessagePrefix = "[debug] ";
static const char *kServerConfig = "server.cfg";

bool crashdetect::errorCaught_ = false;
std::stack<crashdetect::NPCall> crashdetect::npCalls_;
ConfigReader crashdetect::serverCfg(kServerConfig);
crashdetect::InstanceMap crashdetect::instances_;

// static
crashdetect *crashdetect::GetInstance(AMX *amx) {
	InstanceMap::const_iterator iterator = instances_.find(amx);
	if (iterator == instances_.end()) {
		crashdetect *c = new crashdetect(amx);
		instances_.insert(std::make_pair(amx, c));
		return c;
	}
	return iterator->second;
}

// static
void crashdetect::DestroyInstance(AMX *amx) {
	instances_.erase(amx);
}

// static
void crashdetect::SystemException(void *context) {
	if (!npCalls_.empty()) {
		AMX *amx = npCalls_.top().amx();
		GetInstance(amx)->HandleException();
	} else {
		logprintf("Server crashed due to an unknown error");
	}
	PrintSystemBacktrace(context);
}

// static
void crashdetect::SystemInterrupt() {
	if (!npCalls_.empty()) {
		AMX *amx = npCalls_.top().amx();
		GetInstance(amx)->HandleInterrupt();
	} else {
		logprintf("Server recieved interrupt signal");
	}
	PrintSystemBacktrace();
}

// static
void crashdetect::DieOrContinue() {
	if (serverCfg.GetOption("die_on_error", false)) {
		logprintf("Aborting...");
		std::exit(EXIT_FAILURE);
	}
}

crashdetect::crashdetect(AMX *amx)
	: amx_(amx)
	, amxhdr_(reinterpret_cast<AMX_HEADER*>(amx->base))
{
	AMXPathFinder pathFinder;
	pathFinder.AddSearchPath("gamemodes");
	pathFinder.AddSearchPath("filterscripts");

	// Read a list of additional search paths from AMX_PATH.
	const char *AMX_PATH = getenv("AMX_PATH");
	if (AMX_PATH != 0) {
		std::string var(AMX_PATH);
		std::string path;
		std::string::size_type begin = 0;
		while (begin < var.length()) {
			std::string::size_type end = var.find(fileutils::kNativePathListSepChar, begin);
			if (end == std::string::npos) {
				end = var.length();
			}
			path.assign(var.begin() + begin, var.begin() + end);
			if (!path.empty()) {
				pathFinder.AddSearchPath(path);
			}
			begin = end + 1;
		}
	}

	amxPath_ = pathFinder.FindAMX(amx);
	amxName_ = fileutils::GetFileName(amxPath_);

	if (!amxPath_.empty()) {
		uint16_t flags;
		amx_Flags(amx_, &flags);
		if ((flags & AMX_FLAG_DEBUG) != 0) {
			debugInfo_.Load(amxPath_);
		}
	}

	amx_->sysreq_d = 0;
	prevCallback_ = amx_->callback;
}

int crashdetect::DoAmxCallback(cell index, cell *result, cell *params) {
	npCalls_.push(NPCall(NPCall::NATIVE, amx_, index, amx_->frm, amx_->cip));
	int retcode = prevCallback_(amx_, index, result, params);
	npCalls_.pop();
	return retcode;
}

int crashdetect::DoAmxExec(cell *retval, int index) {
	npCalls_.push(NPCall(NPCall::PUBLIC, amx_, index, amx_->frm, amx_->cip));

	int retcode = ::amx_Exec(amx_, retval, index);
	if (retcode != AMX_ERR_NONE && !errorCaught_) {
		amx_Error(amx_, index, retcode);
	} else {
		errorCaught_ = false;
	}

	npCalls_.pop();
	return retcode;
}

int crashdetect::DoAmxRelease(cell amx_addr, void *releaser) {
	if (amx_addr < amx_->hlw || amx_addr >= amx_->stk) {
		HandleReleaseError(amx_addr, releaser);
	}
	return amx_Release(amx_, amx_addr);
}

void crashdetect::HandleExecError(int index, int error) {
	crashdetect::errorCaught_ = true;

	if (error == AMX_ERR_INDEX && index == AMX_EXEC_GDK) {
		error = AMX_ERR_NONE;
		return;
	}

	logprintf("Run time error %d: \"%s\"", error, aux_StrError(error));

	switch (error) {
		case AMX_ERR_BOUNDS: {
			cell bound = *(reinterpret_cast<cell*>(amx_->cip + amx_->base + amxhdr_->cod + sizeof(cell)));
			cell index = amx_->pri;
			if (index < 0) {
				logprintf(" Accessing element at negative index %d", index);
			} else {
				logprintf(" Accessing element at index %d past array upper bound %d", index, bound);
			}
			break;
		}
		case AMX_ERR_NOTFOUND: {
			AMX_FUNCSTUBNT *natives = reinterpret_cast<AMX_FUNCSTUBNT*>(amx_->base + amxhdr_->natives);
			int numNatives = 0;
			amx_NumNatives(amx_, &numNatives);
			for (int i = 0; i < numNatives; ++i) {
				if (natives[i].address == 0) {
					char *name = reinterpret_cast<char*>(natives[i].nameofs + amx_->base);
					logprintf(" %s", name);
				}
			}
			break;
		}
		case AMX_ERR_STACKERR:
			logprintf(" Stack pointer (STK) is 0x%X, heap pointer (HEA) is 0x%X", amx_->stk, amx_->hea);
			break;
		case AMX_ERR_STACKLOW:
			logprintf(" Stack pointer (STK) is 0x%X, stack top (STP) is 0x%X", amx_->stk, amx_->stp);
			break;
		case AMX_ERR_HEAPLOW:
			logprintf(" Heap pointer (HEA) is 0x%X, heap bottom (HLW) is 0x%X", amx_->hea, amx_->hlw);
			break;
		case AMX_ERR_INVINSTR: {
			cell opcode = *(reinterpret_cast<cell*>(amx_->cip + amx_->base + amxhdr_->cod));
			logprintf(" Unknown opcode 0x%x at address 0x%08X", opcode , amx_->cip);
			break;
		}
	}

	if (error != AMX_ERR_NOTFOUND &&
		error != AMX_ERR_INDEX &&
		error != AMX_ERR_CALLBACK &&
		error != AMX_ERR_INIT)
	{
		PrintAmxBacktrace();
	}

	std::string command = serverCfg.GetOption("run_on_error", std::string());
	if (!command.empty()) {
		std::system(command.c_str());
	}

	DieOrContinue();
}

void crashdetect::HandleException() {
	logprintf("Server crashed while executing %s", amxName_.c_str());
	PrintAmxBacktrace();
}

void crashdetect::HandleInterrupt() {
	logprintf("Server recieved interrupt signal while executing %s", amxName_.c_str());
	PrintAmxBacktrace();
}

void crashdetect::HandleReleaseError(cell address, void *releaser) {
	std::string plugin = fileutils::GetFileName(os::GetModulePathFromAddr(releaser));
	if (plugin.empty()) {
		plugin.assign("<unknown>");
	}
	logprintf("Bad heap release detected:");
	logprintf(" %s [%08x] is releasing memory at %08x which is out of heap", plugin.c_str(), releaser, address);
	PrintSystemBacktrace();
}

// static
void crashdetect::PrintAmxBacktrace() {
	if (npCalls_.empty()) {
		return;
	}

	std::stack<NPCall> npCallStack = npCalls_;
	cell frm = npCallStack.top().amx()->frm;
	cell cip = npCallStack.top().amx()->cip;
	int level = 0;

	if (cip == 0) {
		return;
	}

	logprintf("AMX backtrace:");

	while (!npCallStack.empty() && cip != 0) {
		NPCall call = npCallStack.top();

		if (call.amx() != npCallStack.top().amx()) {
			assert(level != 0);
			break;
		}

		if (call.type() == NPCall::NATIVE) {
			AMX_NATIVE address = amxutils::GetNativeAddress(call.amx(), call.index());
			if (address != 0) {
				std::string module = fileutils::GetFileName(os::GetModulePathFromAddr((void*)address));
				std::string from = " from " + module;
				if (module.empty()) {
					from.clear();
				}
				const char *name = amxutils::GetNativeName(call.amx(), call.index());
				if (name != 0) {
					logprintf("#%d native %s () [%08x]%s", level++, name, address, from.c_str());
				}
			}
		} else if (call.type() == NPCall::PUBLIC) {
			AMXDebugInfo &debugInfo = instances_[call.amx()]->debugInfo_;

			amxutils::PushStack(call.amx(), cip); // push return address
			amxutils::PushStack(call.amx(), frm); // push frame pointer
			frm = call.amx()->stk;

			AMXStackTrace trace(call.amx(), debugInfo, frm);
			std::deque<AMXStackFrame> frames = trace.GetFrames();

			frm = amxutils::PopStack(call.amx()); // pop frame pointer
			cip = amxutils::PopStack(call.amx()); // pop return address

			if (frames.empty()) {
				ucell epAddr = amxutils::GetPublicAddress(call.amx(), call.index());
				frames.push_front(AMXStackFrame(call.amx(), frm, 0, epAddr, debugInfo));
			} else {
				if (!debugInfo.IsLoaded()) {
					AMXStackFrame &bottom = frames.back();
					bottom = AMXStackFrame(call.amx(),
						bottom.GetFrameAddress(),
						bottom.GetReturnAddress(),
						amxutils::GetPublicAddress(call.amx(), call.index()),
						debugInfo);
				}
			}

			std::string &amxName = instances_[call.amx()]->amxName_;
			for (size_t i = 0; i < frames.size(); i++) {
				std::string from = " from " + amxName;
				if (amxName.empty() || debugInfo.IsLoaded()) {
					from.clear();
				}
				logprintf("#%d %s%s", level++, frames[i].GetString().c_str(), from.c_str());
			}

			frm = call.frm();
			cip = call.cip();
		}
		npCallStack.pop();
	}
}

// static
void crashdetect::PrintSystemBacktrace(void *context) {
	logprintf("System backtrace:");

	int level = 0;

	StackTrace trace(context);
	std::deque<StackFrame> frames = trace.GetFrames();

	for (std::deque<StackFrame>::const_iterator iterator = frames.begin();
			iterator != frames.end(); ++iterator) {
		const StackFrame &frame = *iterator;

		std::string module = os::GetModulePathFromAddr(frame.GetReturnAddress());
		std::string from = " from " + module;
		if (module.empty()) {
			from.clear();
		}

		logprintf("#%d %s%s", level++, frame.GetString().c_str(), from.c_str());
	}
}

// static
void crashdetect::logprintf(const char *format, ...) {
	std::va_list args;
	va_start(args, format);

	std::string prefixed_format;
	prefixed_format.append(kLogMessagePrefix);
	prefixed_format.append(format);

	::vlogprintf(prefixed_format.c_str(), args);

	va_end(args);
}
<|endoftext|>


<commit_before>#include "TestBCWrapper.h"
#include "braincloud/http_codes.h"
#include "braincloud/reason_codes.h"
#include "braincloud/BrainCloudWrapper.h"

// These tests are normally commented out for apple as the wrapper
// manipulates the keychain which asks the user for confirmation.
// Build machines dislike this :-)
// However you can uncomment to verify the wrapper is working.

#ifndef __APPLE__

TEST_F(TestBCWrapper, AaaRunFirst)
{
    // test that should be run before all others
#if defined (USE_IMMEDIATE_RETRY)
	m_bcWrapper->client->setImmediateRetryOnError(true);
#else
	m_bcWrapper->client->setImmediateRetryOnError(false);
#endif

    // this forces us to create a new anonymous account
	m_bcWrapper->setStoredAnonymousId("");
	m_bcWrapper->setStoredProfileId("");
}

TEST_F(TestBCWrapper, AuthenticateAnonymous)
{
    m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

    TestResult tr;
	m_bcWrapper->authenticateAnonymous(&tr);
    tr.run(m_bc);

    Logout();
}

TEST_F(TestBCWrapper, ManualRedirect) // Redirects to the same environement, different app id
{
    m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_redirectAppId.c_str(), m_version.c_str(), "wrapper", "unittest");

    TestResult tr;
 	m_bcWrapper->authenticateAnonymous(&tr);
    tr.run(m_bc);

    Logout();
}

TEST_F(TestBCWrapper, AuthenticateEmailPassword)
{
	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

    std::string email = GetUser(UserA)->m_email;
    email.append("_wrapper");

    TestResult tr;
	m_bcWrapper->authenticateEmailPassword(email.c_str(), GetUser(UserA)->m_password, true, &tr);
    tr.run(m_bc);

    Logout();
}

TEST_F(TestBCWrapper, AuthenticateUniversal)
{
    m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

    TestResult tr;
    std::string uid = GetUser(UserA)->m_id;
    uid.append("_wrapper");
    m_bcWrapper->authenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
    tr.run(m_bc);

    Logout();
}

TEST_F(TestBCWrapper, VerifyAlwaysAllowProfileFalse)
{
    m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");
    m_bcWrapper->setAlwaysAllowProfileSwitch(false);

    // this forces us to create a new anonymous account
    m_bcWrapper->setStoredAnonymousId("");
    m_bcWrapper->setStoredProfileId("");

    TestResult tr;
    m_bcWrapper->authenticateAnonymous(&tr);
    tr.run(m_bc);

    std::string anonId = m_bcWrapper->getStoredAnonymousId();
    std::string profileId = m_bcWrapper->getStoredProfileId();
    std::string uid = GetUser(UserA)->m_id;
    uid.append("_wrapperVerifyAlwaysAllowProfileFalse");

	m_bcWrapper->getIdentityService()->attachUniversalIdentity(uid.c_str(), GetUser(UserA)->m_password, &tr);
    tr.run(m_bc);

    Logout();
	m_bcWrapper->getBCClient()->getAuthenticationService()->clearSavedProfileId();

    m_bcWrapper->authenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
    tr.run(m_bc);

    EXPECT_TRUE(anonId.compare(m_bcWrapper->getStoredAnonymousId()) == 0);
    EXPECT_TRUE(profileId.compare(m_bcWrapper->getStoredProfileId()) == 0);

    m_bcWrapper->setAlwaysAllowProfileSwitch(true);
    Logout();
}

TEST_F(TestBCWrapper, ResetEmailPassword)
{
    const char* email = "braincloudunittest@gmail.com";

    TestResult tr;
    m_bcWrapper->resetEmailPassword(email, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCWrapper, ResetEmailPasswordAdvanced)
{
    const char* email = "braincloudunittest@gmail.com";
    std::string content = "{\"fromAddress\": \"fromAddress\",\"fromName\": \"fromName\",\"replyToAddress\": \"replyToAddress\",\"replyToName\": \"replyToName\", \"templateId\": \"8f14c77d-61f4-4966-ab6d-0bee8b13d090\",\"subject\": \"subject\",\"body\": \"Body goes here\", \"substitutions\": { \":name\": \"John Doe\",\":resetLink\": \"www.dummuyLink.io\"}, \"categories\": [\"category1\",\"category2\" ]}";

    TestResult tr;
    m_bcWrapper->resetEmailPasswordAdvanced(email, content, &tr);
    tr.runExpectFail(m_bc, HTTP_BAD_REQUEST, INVALID_FROM_ADDRESS);
}

TEST_F(TestBCWrapper, Reconnect)
{
	TestResult tr;

	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

	m_bcWrapper->reconnect(&tr);
	tr.run(m_bc);

	Logout();
}

TEST_F(TestBCWrapper, SmartSwitchAnonToUniversal)
{
	//need to separate these tests for windows and linux for the time being.
	#if defined(_WIN32)

	std::string uid = GetUser(UserA)->m_id;
	uid.append("_wrapper");

	/*
	std::string anonIdtest =  "\n STORED ID: " + m_bcWrapper->getStoredAnonymousId() + "\n";
	std::cout<< anonIdtest;

	//after testing and test cases it's noticeable that this fucntion does not work for linux.
	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());

	std::string anonIdtest1 =  "\n STORED ID: " + m_bcWrapper->getStoredAnonymousId() + "\n";
	std::cout<< anonIdtest1;
	*/
	//CONFIRMED : setStoredAnonymousId uses a pure virtual method save data helper, which is only implemented for Windows. Due to this it will not work on linux.

	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());
	m_bcWrapper->resetStoredProfileId();

	TestResult tr;

	m_bcWrapper->authenticateAnonymous(&tr);
	tr.run(m_bc);

	std::string profileId = m_bcWrapper->getStoredProfileId();

	m_bcWrapper->smartSwitchAuthenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	EXPECT_TRUE(profileId.compare(m_bcWrapper->getStoredAnonymousId()) != 0);

	#elif defined (UNIX)

	std::string uid = GetUser(UserA)->m_id;
	uid.append("_wrapper");

	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());
	m_bcWrapper->resetStoredProfileId();

	TestResult tr;

	m_bcWrapper->authenticateAnonymous(&tr);
	tr.run(m_bc);

	std::string profileId = m_bcWrapper->getStoredProfileId();

	m_bcWrapper->smartSwitchAuthenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	//WE WILL NOT HAVE A SAVED ANON ID, <<BUT>> the switchauthentication call works.
	EXPECT_FALSE(profileId.compare(m_bcWrapper->getStoredAnonymousId()) != 0);

	#endif
}

TEST_F(TestBCWrapper, SmartSwitchUniversalToEmail)
{
	//same reason, we have no way to properly store an anon id in linux yet
	#if defined(_WIN32)

	std::string email = GetUser(UserA)->m_email;
	email.append("_wrapper");

	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());
	m_bcWrapper->resetStoredProfileId();

	TestResult tr;
	std::string uid = GetUser(UserA)->m_id;
	uid.append("_wrapper");
	m_bcWrapper->authenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	std::string profileId = m_bcWrapper->getStoredProfileId();

	m_bcWrapper->smartSwitchAuthenticateEmailPassword(email.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	EXPECT_TRUE(profileId.compare(m_bcWrapper->getStoredProfileId()) != 0);

	#elif defined(UNIX)

	std::string email = GetUser(UserA)->m_email;
	email.append("_wrapper");

	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());
	m_bcWrapper->resetStoredProfileId();

	TestResult tr;
	std::string uid = GetUser(UserA)->m_id;
	uid.append("_wrapper");
	m_bcWrapper->authenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	std::string profileId = m_bcWrapper->getStoredProfileId();

	m_bcWrapper->smartSwitchAuthenticateEmailPassword(email.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	//makes it through until failure here.
	EXPECT_FAIL(profileId.compare(m_bcWrapper->getStoredProfileId()) != 0);

	#endif
}

TEST_F(TestBCWrapper, ReInit)
{
	//case 1 multiple inits
	int initCounter = 1;

	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");
	assert(initCounter == 1);
	initCounter++;

	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");
	assert(initCounter == 2);
	initCounter++;

	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");
	assert(initCounter == 3);
	initCounter++;

	//case 2
	//auth
	TestResult tr1;
    m_bcWrapper->authenticateAnonymous(&tr1);
    tr1.run(m_bc);

	//call
	TestResult tr2;
    m_bc->getTimeService()->readServerTime(&tr2);
    tr2.run(m_bc);

	//reinit
	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

	//call - expect failure no session
	TestResult tr3;
    m_bc->getTimeService()->readServerTime(&tr3);
    tr3.runExpectFail(m_bc, HTTP_FORBIDDEN, NO_SESSION);
}

#endif

<commit_msg>Hotfix for Reconnect Test<commit_after>#include "TestBCWrapper.h"
#include "braincloud/http_codes.h"
#include "braincloud/reason_codes.h"
#include "braincloud/BrainCloudWrapper.h"

// These tests are normally commented out for apple as the wrapper
// manipulates the keychain which asks the user for confirmation.
// Build machines dislike this :-)
// However you can uncomment to verify the wrapper is working.

#ifndef __APPLE__

TEST_F(TestBCWrapper, AaaRunFirst)
{
    // test that should be run before all others
#if defined (USE_IMMEDIATE_RETRY)
	m_bcWrapper->client->setImmediateRetryOnError(true);
#else
	m_bcWrapper->client->setImmediateRetryOnError(false);
#endif

    // this forces us to create a new anonymous account
	m_bcWrapper->setStoredAnonymousId("");
	m_bcWrapper->setStoredProfileId("");
}

TEST_F(TestBCWrapper, AuthenticateAnonymous)
{
    m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

    TestResult tr;
	m_bcWrapper->authenticateAnonymous(&tr);
    tr.run(m_bc);

    Logout();
}

TEST_F(TestBCWrapper, ManualRedirect) // Redirects to the same environement, different app id
{
    m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_redirectAppId.c_str(), m_version.c_str(), "wrapper", "unittest");

    TestResult tr;
 	m_bcWrapper->authenticateAnonymous(&tr);
    tr.run(m_bc);

    Logout();
}

TEST_F(TestBCWrapper, AuthenticateEmailPassword)
{
	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

    std::string email = GetUser(UserA)->m_email;
    email.append("_wrapper");

    TestResult tr;
	m_bcWrapper->authenticateEmailPassword(email.c_str(), GetUser(UserA)->m_password, true, &tr);
    tr.run(m_bc);

    Logout();
}

TEST_F(TestBCWrapper, AuthenticateUniversal)
{
    m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

    TestResult tr;
    std::string uid = GetUser(UserA)->m_id;
    uid.append("_wrapper");
    m_bcWrapper->authenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
    tr.run(m_bc);

    Logout();
}

TEST_F(TestBCWrapper, VerifyAlwaysAllowProfileFalse)
{
    m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");
    m_bcWrapper->setAlwaysAllowProfileSwitch(false);

    // this forces us to create a new anonymous account
    m_bcWrapper->setStoredAnonymousId("");
    m_bcWrapper->setStoredProfileId("");

    TestResult tr;
    m_bcWrapper->authenticateAnonymous(&tr);
    tr.run(m_bc);

    std::string anonId = m_bcWrapper->getStoredAnonymousId();
    std::string profileId = m_bcWrapper->getStoredProfileId();
    std::string uid = GetUser(UserA)->m_id;
    uid.append("_wrapperVerifyAlwaysAllowProfileFalse");

	m_bcWrapper->getIdentityService()->attachUniversalIdentity(uid.c_str(), GetUser(UserA)->m_password, &tr);
    tr.run(m_bc);

    Logout();
	m_bcWrapper->getBCClient()->getAuthenticationService()->clearSavedProfileId();

    m_bcWrapper->authenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
    tr.run(m_bc);

    EXPECT_TRUE(anonId.compare(m_bcWrapper->getStoredAnonymousId()) == 0);
    EXPECT_TRUE(profileId.compare(m_bcWrapper->getStoredProfileId()) == 0);

    m_bcWrapper->setAlwaysAllowProfileSwitch(true);
    Logout();
}

TEST_F(TestBCWrapper, ResetEmailPassword)
{
    const char* email = "braincloudunittest@gmail.com";

    TestResult tr;
    m_bcWrapper->resetEmailPassword(email, &tr);
    tr.run(m_bc);
}

TEST_F(TestBCWrapper, ResetEmailPasswordAdvanced)
{
    const char* email = "braincloudunittest@gmail.com";
    std::string content = "{\"fromAddress\": \"fromAddress\",\"fromName\": \"fromName\",\"replyToAddress\": \"replyToAddress\",\"replyToName\": \"replyToName\", \"templateId\": \"8f14c77d-61f4-4966-ab6d-0bee8b13d090\",\"subject\": \"subject\",\"body\": \"Body goes here\", \"substitutions\": { \":name\": \"John Doe\",\":resetLink\": \"www.dummuyLink.io\"}, \"categories\": [\"category1\",\"category2\" ]}";

    TestResult tr;
    m_bcWrapper->resetEmailPasswordAdvanced(email, content, &tr);
    tr.runExpectFail(m_bc, HTTP_BAD_REQUEST, INVALID_FROM_ADDRESS);
}

TEST_F(TestBCWrapper, Reconnect)
{
	TestResult tr;

	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

	m_bcWrapper->reconnect(&tr);
	tr.runExpectFail(m_bc, HTTP_ACCEPTED, MISSING_PROFILE_ERROR);

	Logout();
}

TEST_F(TestBCWrapper, SmartSwitchAnonToUniversal)
{
	//need to separate these tests for windows and linux for the time being.
	#if defined(_WIN32)

	std::string uid = GetUser(UserA)->m_id;
	uid.append("_wrapper");

	/*
	std::string anonIdtest =  "\n STORED ID: " + m_bcWrapper->getStoredAnonymousId() + "\n";
	std::cout<< anonIdtest;

	//after testing and test cases it's noticeable that this fucntion does not work for linux.
	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());

	std::string anonIdtest1 =  "\n STORED ID: " + m_bcWrapper->getStoredAnonymousId() + "\n";
	std::cout<< anonIdtest1;
	*/
	//CONFIRMED : setStoredAnonymousId uses a pure virtual method save data helper, which is only implemented for Windows. Due to this it will not work on linux.

	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());
	m_bcWrapper->resetStoredProfileId();

	TestResult tr;

	m_bcWrapper->authenticateAnonymous(&tr);
	tr.run(m_bc);

	std::string profileId = m_bcWrapper->getStoredProfileId();

	m_bcWrapper->smartSwitchAuthenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	EXPECT_TRUE(profileId.compare(m_bcWrapper->getStoredAnonymousId()) != 0);

	#elif defined (UNIX)

	std::string uid = GetUser(UserA)->m_id;
	uid.append("_wrapper");

	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());
	m_bcWrapper->resetStoredProfileId();

	TestResult tr;

	m_bcWrapper->authenticateAnonymous(&tr);
	tr.run(m_bc);

	std::string profileId = m_bcWrapper->getStoredProfileId();

	m_bcWrapper->smartSwitchAuthenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	//WE WILL NOT HAVE A SAVED ANON ID, <<BUT>> the switchauthentication call works.
	EXPECT_FALSE(profileId.compare(m_bcWrapper->getStoredAnonymousId()) != 0);

	#endif
}

TEST_F(TestBCWrapper, SmartSwitchUniversalToEmail)
{
	//same reason, we have no way to properly store an anon id in linux yet
	#if defined(_WIN32)

	std::string email = GetUser(UserA)->m_email;
	email.append("_wrapper");

	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());
	m_bcWrapper->resetStoredProfileId();

	TestResult tr;
	std::string uid = GetUser(UserA)->m_id;
	uid.append("_wrapper");
	m_bcWrapper->authenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	std::string profileId = m_bcWrapper->getStoredProfileId();

	m_bcWrapper->smartSwitchAuthenticateEmailPassword(email.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	EXPECT_TRUE(profileId.compare(m_bcWrapper->getStoredProfileId()) != 0);

	#elif defined(UNIX)

	std::string email = GetUser(UserA)->m_email;
	email.append("_wrapper");

	m_bcWrapper->setStoredAnonymousId(m_bcWrapper->client->getAuthenticationService()->generateAnonymousId().c_str());
	m_bcWrapper->resetStoredProfileId();

	TestResult tr;
	std::string uid = GetUser(UserA)->m_id;
	uid.append("_wrapper");
	m_bcWrapper->authenticateUniversal(uid.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	std::string profileId = m_bcWrapper->getStoredProfileId();

	m_bcWrapper->smartSwitchAuthenticateEmailPassword(email.c_str(), GetUser(UserA)->m_password, true, &tr);
	tr.run(m_bc);

	//makes it through until failure here.
	EXPECT_FAIL(profileId.compare(m_bcWrapper->getStoredProfileId()) != 0);

	#endif
}

TEST_F(TestBCWrapper, ReInit)
{
	//case 1 multiple inits
	int initCounter = 1;

	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");
	assert(initCounter == 1);
	initCounter++;

	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");
	assert(initCounter == 2);
	initCounter++;

	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");
	assert(initCounter == 3);
	initCounter++;

	//case 2
	//auth
	TestResult tr1;
    m_bcWrapper->authenticateAnonymous(&tr1);
    tr1.run(m_bc);

	//call
	TestResult tr2;
    m_bc->getTimeService()->readServerTime(&tr2);
    tr2.run(m_bc);

	//reinit
	m_bcWrapper->initialize(m_serverUrl.c_str(), m_secret.c_str(), m_appId.c_str(), m_version.c_str(), "wrapper", "unittest");

	//call - expect failure no session
	TestResult tr3;
    m_bc->getTimeService()->readServerTime(&tr3);
    tr3.runExpectFail(m_bc, HTTP_FORBIDDEN, NO_SESSION);
}

#endif

<|endoftext|>