<commit_before>/*
* robotBlocksSimulator.cpp
*
*  Created on: 12 janvier 2014
*      Author: Benoît
*/

#include <iostream>
#include "robotBlocksSimulator.h"
#include <string.h>
#include "trace.h"

using namespace std;

namespace RobotBlocks {

RobotBlocksBlockCode*(* RobotBlocksSimulator::buildNewBlockCode)(RobotBlocksBlock*)=NULL;

void RobotBlocksSimulator::help() {
   cerr << "VisibleSim:" << endl;
	cerr << "Robot01" << endl;
   exit(EXIT_SUCCESS);
}

RobotBlocksSimulator::RobotBlocksSimulator(int argc, char *argv[], RobotBlocksBlockCode *(*robotBlocksBlockCodeBuildingFunction)(RobotBlocksBlock*)) : BaseSimulator::Simulator(argc, argv) {
	OUTPUT << "\033[1;34m" << "RobotBlocksSimulator constructor" << "\033[0m" << endl;

	int currentID = 1;
	RobotBlocksWorld *world = NULL;
	buildNewBlockCode = robotBlocksBlockCodeBuildingFunction;

	testMode = false;

	/* reading the xml file */
	TiXmlNode *node = xmlDoc->FirstChild("world");
	if (node) {
		TiXmlElement* worldElement = node->ToElement();
		const char *attr= worldElement->Attribute("gridSize");
		int lx,ly,lz;
		if (attr) {
			string str=attr;
			int pos1 = str.find_first_of(','),
				pos2 = str.find_last_of(',');
			lx = atoi(str.substr(0,pos1).c_str());
			ly = atoi(str.substr(pos1+1,pos2-pos1-1).c_str());
			lz = atoi(str.substr(pos2+1,str.length()-pos1-1).c_str());
			OUTPUT << "grid size : " << lx << " x " << ly << " x " << lz << endl;
		} else {
			OUTPUT << "WARNING No grid size in XML file" << endl;
		}
		attr=worldElement->Attribute("windowSize");
		if (attr) {
			string str=attr;
	 		int pos = str.find_first_of(',');
			GlutContext::initialScreenWidth = atoi(str.substr(0,pos).c_str());
			GlutContext::initialScreenHeight = atoi(str.substr(pos+1,str.length()-pos-1).c_str());
			GlutContext::screenWidth = GlutContext::initialScreenWidth;
			GlutContext::screenHeight = GlutContext::initialScreenHeight;
		}

		createWorld(lx, ly, lz, argc, argv);
		world = getWorld();
		world->loadTextures("../../simulatorCore/robotBlocksTextures");

	} else {
		ERRPUT << "ERROR : NO world in XML file" << endl;
		exit(1);
	}

	createScheduler();

	// loading the camera parameters
	TiXmlNode *nodeConfig = node->FirstChild("camera");
	if (nodeConfig) {
		TiXmlElement* cameraElement = nodeConfig->ToElement();
		const char *attr=cameraElement->Attribute("target");
		double def_near=1,def_far=1500;
		float angle=45.0;
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			Vecteur target;
			target.pt[0] = atof(str.substr(0,pos1).c_str());
			target.pt[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
			target.pt[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
			world->getCamera()->setTarget(target);
		}
		attr=cameraElement->Attribute("angle");
		if (attr) {
			angle = atof(attr);
			world->getCamera()->setAngle(angle);
		}
		attr=cameraElement->Attribute("directionSpherical");
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			float az,ele,dist;
			az = -90.0+atof(str.substr(0,pos1).c_str());
			ele = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
			dist = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
			world->getCamera()->setDirection(az,ele);
			world->getCamera()->setDistance(dist);
			az = dist*sin(angle*M_PI/180.0);
			def_near = dist-az;
			def_far = dist+az;
		}
		attr=cameraElement->Attribute("near");
		if (attr) {
			def_near = atof(attr);
		}
		attr=cameraElement->Attribute("far");
		if (attr) {
			def_far = atof(attr);
		}
		world->getCamera()->setNearFar(def_near,def_far);
	}

	// loading the spotlight parameters
	nodeConfig = node->FirstChild("spotlight");
	if (nodeConfig) {
		Vecteur target;
		float az=0,ele=60,dist=1000,angle=50;
		TiXmlElement* lightElement = nodeConfig->ToElement();
		const char *attr=lightElement->Attribute("target");
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			target.pt[0] = atof(str.substr(0,pos1).c_str());
			target.pt[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
			target.pt[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
		}
		attr=lightElement->Attribute("directionSpherical");
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			az = -90.0+atof(str.substr(0,pos1).c_str());
			ele = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
			dist = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
		}
		attr=lightElement->Attribute("angle");
		if (attr) {
			angle = atof(attr);
		}
		float farplane=2.0*dist*tan(angle*M_PI/180.0);
		world->getCamera()->setLightParameters(target,az,ele,dist,angle,10.0,farplane);

	}

	TiXmlNode *nodeBlock = node->FirstChild("blockList");
	if (nodeBlock) {
		Color defaultColor=DARKGREY;
		TiXmlElement* element = nodeBlock->ToElement();
		const char *attr= element->Attribute("color");
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			defaultColor.rgba[0] = atof(str.substr(0,pos1).c_str())/255.0;
			defaultColor.rgba[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str())/255.0;
			defaultColor.rgba[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str())/255.0;
			OUTPUT << "new default color :" << defaultColor << endl;
		}
		attr= element->Attribute("blocksize");
    if (attr) {
		 string str(attr);
		 int pos1 = str.find_first_of(','),
		  pos2 = str.find_last_of(',');
		 float siz[3];
		 siz[0] = atof(str.substr(0,pos1).c_str());
		 siz[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
		 siz[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
		 OUTPUT << "blocksize =" << siz[0] << "," << siz[1] << "," << siz[2] << endl;
		 world->setBlocksSize(siz);
		}

	/* Reading a robotblock */
		TiXmlNode *block = nodeBlock->FirstChild("block");
		Vecteur position;
		Color color;
		bool master;
		while (block) {
		   element = block->ToElement();
		   color=defaultColor;
		   master=false;
		   attr = element->Attribute("color");
		   if (attr) {
			   string str(attr);
			   int pos1 = str.find_first_of(','),
		   		   pos2 = str.find_last_of(',');
			   color.set(atof(str.substr(0,pos1).c_str())/255.0,
                         atof(str.substr(pos1+1,pos2-pos1-1).c_str())/255.0,
                         atof(str.substr(pos2+1,str.length()-pos1-1).c_str())/255.0);
			   OUTPUT << "new color :" << defaultColor << endl;
			}
			attr = element->Attribute("position");
			if (attr) {
                string str(attr);
                int pos1 = str.find_first_of(','),
				pos2 = str.find_last_of(',');
				position.pt[0] = atof(str.substr(0,pos1).c_str());
				position.pt[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
				position.pt[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
				OUTPUT << "position : " << position << endl;
			}
			attr = element->Attribute("master");
			if (attr) {
        string str(attr);
        if (str.compare("true")==0 || str.compare("1")==0) {
					master=true;
        }
        OUTPUT << "master : " << master << endl;
			}
			world->addBlock(currentID++,RobotBlocksSimulator::buildNewBlockCode,position,color,master);
			block = block->NextSibling("block");
		} // end while (block)

		block = nodeBlock->FirstChild("blocksLine");
		int line,plane;
		while (block) {
			element = block->ToElement();
			color=defaultColor;
			attr = element->Attribute("color");
			if (attr) {
				string str(attr);
				int pos1 = str.find_first_of(','),
					pos2 = str.find_last_of(',');
				color.rgba[0] = atof(str.substr(0,pos1).c_str())/255.0;
				color.rgba[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str())/255.0;
				color.rgba[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str())/255.0;
				OUTPUT << "line color :" << color << endl;

			}
			attr = element->Attribute("line");
			if (attr) {
				line = atoi(attr);
			}
			attr = element->Attribute("plane");
			if (attr) {
				plane = atoi(attr);
			}
			attr = element->Attribute("values");
			if (attr) {
				string str(attr);
				position.pt[2] = plane;
				position.pt[1] = line;
				int n = str.length();
				for(int i=0; i<n; i++) {
			    	if  (str[i]=='1') {
			    		position.pt[0]=i;
			    		world->addBlock(currentID++,RobotBlocksSimulator::buildNewBlockCode,position,color);
			    	}
			    }
			}
			block = block->NextSibling("blocksLine");
		} // end while (nodeBlock)
	} else // end if(nodeBlock)
	{ cerr << "no Block List" << endl;
	}
	TiXmlNode *nodeGrid = node->FirstChild("targetGrid");
	if (nodeGrid) {
        world->initTargetGrid();
		TiXmlNode *block = nodeGrid->FirstChild("targetLine");
		int line,plane;
		while (block) {
			TiXmlElement* element = block->ToElement();
			const char *attr = element->Attribute("line");
	 		if (attr) {
	 			line = atoi(attr);
	 		}
	 		attr = element->Attribute("plane");
	 		if (attr) {
	 			plane = atoi(attr);
	 		}
	 		attr = element->Attribute("values");
	 		if (attr) {
	 			string str(attr);
	 			int n = str.length();
	 			for(int i=0; i<n; i++) {
	 		    	world->setTargetGrid((str[i]=='1')?fullCell:emptyCell,i,line,plane);
	 		    }
	 		}
	 		block = block->NextSibling("targetLine");
	 	}
	 } else {
	 	ERRPUT << "No target grid" << endl;
	 }

    TiXmlNode *nodeCapa = node->FirstChild("capabilities");
	if (nodeCapa) {
        world->setCapabilities(new RobotBlocksCapabilities(nodeCapa));
    }

    world->linkBlocks();

//	getScheduler()->sem_schedulerStart->post();
//	getScheduler()->setState(Scheduler::NOTSTARTED);

	if (!testMode) {
      GlutContext::mainLoop();
   }
}

RobotBlocksSimulator::~RobotBlocksSimulator() {
	OUTPUT << "\033[1;34m" << "RobotBlocksSimulator destructor" << "\033[0m" <<endl;
}

void RobotBlocksSimulator::createSimulator(int argc, char *argv[], RobotBlocksBlockCode *(*robotBlocksBlockCodeBuildingFunction)(RobotBlocksBlock*)) {
	simulator =  new RobotBlocksSimulator(argc, argv, robotBlocksBlockCodeBuildingFunction);
}

void RobotBlocksSimulator::deleteSimulator() {
	delete((RobotBlocksSimulator*)simulator);
}

} // RobotBlocks namespace
<commit_msg>Fixed error during config file parsing for gridsize on robotBlocks<commit_after>/*
* robotBlocksSimulator.cpp
*
*  Created on: 12 janvier 2014
*      Author: Benoît
*/

#include <iostream>
#include "robotBlocksSimulator.h"
#include <string.h>
#include "trace.h"

using namespace std;

namespace RobotBlocks {

RobotBlocksBlockCode*(* RobotBlocksSimulator::buildNewBlockCode)(RobotBlocksBlock*)=NULL;

void RobotBlocksSimulator::help() {
   cerr << "VisibleSim:" << endl;
	cerr << "Robot01" << endl;
   exit(EXIT_SUCCESS);
}

RobotBlocksSimulator::RobotBlocksSimulator(int argc, char *argv[], RobotBlocksBlockCode *(*robotBlocksBlockCodeBuildingFunction)(RobotBlocksBlock*)) : BaseSimulator::Simulator(argc, argv) {
	OUTPUT << "\033[1;34m" << "RobotBlocksSimulator constructor" << "\033[0m" << endl;

	int currentID = 1;
	RobotBlocksWorld *world = NULL;
	buildNewBlockCode = robotBlocksBlockCodeBuildingFunction;

	testMode = false;

	/* reading the xml file */
	TiXmlNode *node = xmlDoc->FirstChild("world");
	if (node) {
		TiXmlElement* worldElement = node->ToElement();
		const char *attr= worldElement->Attribute("gridsize");
		int lx,ly,lz;
		if (attr) {
			string str=attr;
			int pos1 = str.find_first_of(','),
				pos2 = str.find_last_of(',');
			lx = atoi(str.substr(0,pos1).c_str());
			ly = atoi(str.substr(pos1+1,pos2-pos1-1).c_str());
			lz = atoi(str.substr(pos2+1,str.length()-pos1-1).c_str());
			OUTPUT << "grid size : " << lx << " x " << ly << " x " << lz << endl;
		} else {
			OUTPUT << "WARNING No grid size in XML file" << endl;
		}
		attr=worldElement->Attribute("windowSize");
		if (attr) {
			string str=attr;
	 		int pos = str.find_first_of(',');
			GlutContext::initialScreenWidth = atoi(str.substr(0,pos).c_str());
			GlutContext::initialScreenHeight = atoi(str.substr(pos+1,str.length()-pos-1).c_str());
			GlutContext::screenWidth = GlutContext::initialScreenWidth;
			GlutContext::screenHeight = GlutContext::initialScreenHeight;
		}

		createWorld(lx, ly, lz, argc, argv);
		world = getWorld();
		world->loadTextures("../../simulatorCore/robotBlocksTextures");

	} else {
		ERRPUT << "ERROR : NO world in XML file" << endl;
		exit(1);
	}

	createScheduler();

	// loading the camera parameters
	TiXmlNode *nodeConfig = node->FirstChild("camera");
	if (nodeConfig) {
		TiXmlElement* cameraElement = nodeConfig->ToElement();
		const char *attr=cameraElement->Attribute("target");
		double def_near=1,def_far=1500;
		float angle=45.0;
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			Vecteur target;
			target.pt[0] = atof(str.substr(0,pos1).c_str());
			target.pt[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
			target.pt[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
			world->getCamera()->setTarget(target);
		}
		attr=cameraElement->Attribute("angle");
		if (attr) {
			angle = atof(attr);
			world->getCamera()->setAngle(angle);
		}
		attr=cameraElement->Attribute("directionSpherical");
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			float az,ele,dist;
			az = -90.0+atof(str.substr(0,pos1).c_str());
			ele = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
			dist = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
			world->getCamera()->setDirection(az,ele);
			world->getCamera()->setDistance(dist);
			az = dist*sin(angle*M_PI/180.0);
			def_near = dist-az;
			def_far = dist+az;
		}
		attr=cameraElement->Attribute("near");
		if (attr) {
			def_near = atof(attr);
		}
		attr=cameraElement->Attribute("far");
		if (attr) {
			def_far = atof(attr);
		}
		world->getCamera()->setNearFar(def_near,def_far);
	}

	// loading the spotlight parameters
	nodeConfig = node->FirstChild("spotlight");
	if (nodeConfig) {
		Vecteur target;
		float az=0,ele=60,dist=1000,angle=50;
		TiXmlElement* lightElement = nodeConfig->ToElement();
		const char *attr=lightElement->Attribute("target");
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			target.pt[0] = atof(str.substr(0,pos1).c_str());
			target.pt[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
			target.pt[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
		}
		attr=lightElement->Attribute("directionSpherical");
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			az = -90.0+atof(str.substr(0,pos1).c_str());
			ele = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
			dist = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
		}
		attr=lightElement->Attribute("angle");
		if (attr) {
			angle = atof(attr);
		}
		float farplane=2.0*dist*tan(angle*M_PI/180.0);
		world->getCamera()->setLightParameters(target,az,ele,dist,angle,10.0,farplane);

	}

	TiXmlNode *nodeBlock = node->FirstChild("blockList");
	if (nodeBlock) {
		Color defaultColor=DARKGREY;
		TiXmlElement* element = nodeBlock->ToElement();
		const char *attr= element->Attribute("color");
		if (attr) {
			string str(attr);
			int pos1 = str.find_first_of(','),
			pos2 = str.find_last_of(',');
			defaultColor.rgba[0] = atof(str.substr(0,pos1).c_str())/255.0;
			defaultColor.rgba[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str())/255.0;
			defaultColor.rgba[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str())/255.0;
			OUTPUT << "new default color :" << defaultColor << endl;
		}
		attr= element->Attribute("blocksize");
    if (attr) {
		 string str(attr);
		 int pos1 = str.find_first_of(','),
		  pos2 = str.find_last_of(',');
		 float siz[3];
		 siz[0] = atof(str.substr(0,pos1).c_str());
		 siz[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
		 siz[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
		 OUTPUT << "blocksize =" << siz[0] << "," << siz[1] << "," << siz[2] << endl;
		 world->setBlocksSize(siz);
		}

	/* Reading a robotblock */
		TiXmlNode *block = nodeBlock->FirstChild("block");
		Vecteur position;
		Color color;
		bool master;
		while (block) {
		   element = block->ToElement();
		   color=defaultColor;
		   master=false;
		   attr = element->Attribute("color");
		   if (attr) {
			   string str(attr);
			   int pos1 = str.find_first_of(','),
		   		   pos2 = str.find_last_of(',');
			   color.set(atof(str.substr(0,pos1).c_str())/255.0,
                         atof(str.substr(pos1+1,pos2-pos1-1).c_str())/255.0,
                         atof(str.substr(pos2+1,str.length()-pos1-1).c_str())/255.0);
			   OUTPUT << "new color :" << defaultColor << endl;
			}
			attr = element->Attribute("position");
			if (attr) {
                string str(attr);
                int pos1 = str.find_first_of(','),
				pos2 = str.find_last_of(',');
				position.pt[0] = atof(str.substr(0,pos1).c_str());
				position.pt[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str());
				position.pt[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str());
				OUTPUT << "position : " << position << endl;
			}
			attr = element->Attribute("master");
			if (attr) {
        string str(attr);
        if (str.compare("true")==0 || str.compare("1")==0) {
					master=true;
        }
        OUTPUT << "master : " << master << endl;
			}
			world->addBlock(currentID++,RobotBlocksSimulator::buildNewBlockCode,position,color,master);
			block = block->NextSibling("block");
		} // end while (block)

		block = nodeBlock->FirstChild("blocksLine");
		int line,plane;
		while (block) {
			element = block->ToElement();
			color=defaultColor;
			attr = element->Attribute("color");
			if (attr) {
				string str(attr);
				int pos1 = str.find_first_of(','),
					pos2 = str.find_last_of(',');
				color.rgba[0] = atof(str.substr(0,pos1).c_str())/255.0;
				color.rgba[1] = atof(str.substr(pos1+1,pos2-pos1-1).c_str())/255.0;
				color.rgba[2] = atof(str.substr(pos2+1,str.length()-pos1-1).c_str())/255.0;
				OUTPUT << "line color :" << color << endl;

			}
			attr = element->Attribute("line");
			if (attr) {
				line = atoi(attr);
			}
			attr = element->Attribute("plane");
			if (attr) {
				plane = atoi(attr);
			}
			attr = element->Attribute("values");
			if (attr) {
				string str(attr);
				position.pt[2] = plane;
				position.pt[1] = line;
				int n = str.length();
				for(int i=0; i<n; i++) {
			    	if  (str[i]=='1') {
			    		position.pt[0]=i;
			    		world->addBlock(currentID++,RobotBlocksSimulator::buildNewBlockCode,position,color);
			    	}
			    }
			}
			block = block->NextSibling("blocksLine");
		} // end while (nodeBlock)
	} else // end if(nodeBlock)
	{ cerr << "no Block List" << endl;
	}
	TiXmlNode *nodeGrid = node->FirstChild("targetGrid");
	if (nodeGrid) {
        world->initTargetGrid();
		TiXmlNode *block = nodeGrid->FirstChild("targetLine");
		int line,plane;
		while (block) {
			TiXmlElement* element = block->ToElement();
			const char *attr = element->Attribute("line");
	 		if (attr) {
	 			line = atoi(attr);
	 		}
	 		attr = element->Attribute("plane");
	 		if (attr) {
	 			plane = atoi(attr);
	 		}
	 		attr = element->Attribute("values");
	 		if (attr) {
	 			string str(attr);
	 			int n = str.length();
	 			for(int i=0; i<n; i++) {
	 		    	world->setTargetGrid((str[i]=='1')?fullCell:emptyCell,i,line,plane);
	 		    }
	 		}
	 		block = block->NextSibling("targetLine");
	 	}
	 } else {
	 	ERRPUT << "No target grid" << endl;
	 }

    TiXmlNode *nodeCapa = node->FirstChild("capabilities");
	if (nodeCapa) {
        world->setCapabilities(new RobotBlocksCapabilities(nodeCapa));
    }

    world->linkBlocks();

//	getScheduler()->sem_schedulerStart->post();
//	getScheduler()->setState(Scheduler::NOTSTARTED);

	if (!testMode) {
      GlutContext::mainLoop();
   }
}

RobotBlocksSimulator::~RobotBlocksSimulator() {
	OUTPUT << "\033[1;34m" << "RobotBlocksSimulator destructor" << "\033[0m" <<endl;
}

void RobotBlocksSimulator::createSimulator(int argc, char *argv[], RobotBlocksBlockCode *(*robotBlocksBlockCodeBuildingFunction)(RobotBlocksBlock*)) {
	simulator =  new RobotBlocksSimulator(argc, argv, robotBlocksBlockCodeBuildingFunction);
}

void RobotBlocksSimulator::deleteSimulator() {
	delete((RobotBlocksSimulator*)simulator);
}

} // RobotBlocks namespace
<|endoftext|>


<commit_before>//
// Copyright (C) 2007 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2007 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <sipxunit/TestUtilities.h>

#include <mp/MpMMTimer.h>
#include <os/OsDateTime.h>
#include <os/OsSysLog.h>
#include <os/OsNotification.h>
#include <os/OsTask.h>

#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mp/MpMMTimerWnt.h>
#endif

// Forward Decl's
class MpMMTimerTest;

class TimerNotification : public OsNotification
{
public:
   TimerNotification(MpMMTimerTest* pMMTimerTest);
   virtual ~TimerNotification() {}
   OsStatus signal(const intptr_t eventData);

private:
   MpMMTimerTest* mpMMTimerTest;
};

/**
 * Unittest for MpMMTimer and its successors
 */
class MpMMTimerTest : public CppUnit::TestCase
{
   CPPUNIT_TEST_SUITE(MpMMTimerTest);
   CPPUNIT_TEST(testGetResolution);
   CPPUNIT_TEST(testPeriodRange);
   CPPUNIT_TEST(testLinearTimer);
   CPPUNIT_TEST(testNotificationTimer);
   CPPUNIT_TEST_SUITE_END();

public:
   void setUp()
   {
      mpPerfTimes = NULL;
      mPerfTimesSz = 0;
      mCurNPerfTimes = 0;
   }

   void tearDown()
   {
      if(mpPerfTimes != NULL)
      {
         delete[] mpPerfTimes;
      }
      mpPerfTimes = NULL;
      mPerfTimesSz = 0;
      mCurNPerfTimes = 0;
   }

   void checkDeltasAgainstThresholds(long deltas[], long absDeltas[], unsigned nDeltas,
                                     unsigned targetDelta, // <-- was periodUSecs
                                     long lowerThresh, long upperThresh)
   {
      CPPUNIT_ASSERT_MESSAGE("Timer didn't fire or deltas were not collected!",
                             nDeltas > 0);

      printf("Timing values in microseconds, CSV: \n");
      long valOutsideThreshs = targetDelta; // initialize to exactly what we want.
      unsigned i;
      for(i = 0; i < nDeltas; i++)
      {
         // Print output in CSV format, for easy graphing.
         printf("%ld\t%ld", deltas[i], absDeltas[i]);
         printf((i < nDeltas-1) ? "\n" : "\n\n");  // done this way for easy change to comma CSV

         // Check if we're outside some reasonable thresholds.
         if(i > 0 && // don't include the first value in our tests - it's always high.
            valOutsideThreshs == targetDelta) // Only check if we haven't already gone outside threshold.
         {
            if(deltas[i]-(long)targetDelta < lowerThresh ||
               deltas[i]-(long)targetDelta > upperThresh)
            {
               valOutsideThreshs = deltas[i];
            }
         }
      }

      // Assert when single value outside error range specified above.
      char errStrBuf[256];
      snprintf(errStrBuf, 256,
               "Single timer value %ld falls outside threshold of %ld to %ld us",
               valOutsideThreshs, lowerThresh, upperThresh);

      CPPUNIT_ASSERT_MESSAGE(errStrBuf,
                             (valOutsideThreshs-(long)targetDelta >= lowerThresh &&
                              valOutsideThreshs-(long)targetDelta <= upperThresh));
   }

   void checkMeanAgainstThresholds(const OsTime& start, const OsTime& stop,
                                   unsigned nDeltas,
                                   unsigned targetDelta, // <-- was periodUSecs
                                   long lowerMeanThresh, long upperMeanThresh)
   {
      CPPUNIT_ASSERT_MESSAGE("Timer didn't fire or deltas were not collected!",
                             nDeltas > 0);

      double meanAvg = 0;

      int64_t totStartUSecs = start.seconds()*1000*1000 + start.usecs();
      int64_t totStopUSecs = stop.seconds()*1000*1000 + stop.usecs();

      meanAvg = (totStopUSecs-totStartUSecs)/(double)nDeltas;
      printf("Mean: %.2f us\n", meanAvg);

      // Assert when mean is outside error range specified above.
      char errStrBuf[256];
      snprintf(errStrBuf, 256,
         "Mean timer value %.2f falls outside threshold of %ld to %ld us",
         meanAvg, lowerMeanThresh, upperMeanThresh);

      CPPUNIT_ASSERT_MESSAGE(errStrBuf,
                             (meanAvg-(long)targetDelta >= lowerMeanThresh &&
                              meanAvg-(long)targetDelta <= upperMeanThresh));
   }

   void testGetResolution()
   {
      // Test getting the resolution, and get it..
      unsigned resolution;

#ifdef WIN32
      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, MpMMTimer::getResolution(resolution));
      printf("Minimum timer resolution is %d usecs\n", resolution);
#else
      printf("MpMMTimer::getResolution() not yet implemented on this "
             "platform, excluding test.\n");
#endif
   }

   void testPeriodRange()
   {
      // Test the period range static method..
      unsigned unusedMin = 0;
      unsigned unusedMax = 0;
#ifdef WIN32
      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS,
         MpMMTimer::getPeriodRange(&unusedMin, &unusedMax));
#else
      printf("MpMMTimer::getPeriodRange() not yet implemented on this "
             "platform, excluding test.\n");
#endif
   }

   void testLinearTimer()
   {
      // Set the below variables and preprocessor defines to tweak this test.
      // TLT_LOOP_COUNT defines the number of timer fire repetitions to do
      // (set this to an even value),
      // and periodUSecs defines how long to wait in each one.
#     define TLT_LOOP_CNT 2000
      unsigned periodUSecs = 10000;
      long lowerThresh = -(long)periodUSecs; // Assert when outside an error range
      long lowerMeanThresh = -50;            // specified below.
      long upperThresh = periodUSecs*2;      // One for single values
      long upperMeanThresh = 50;             // One for mean values

      MpMMTimer* pMMTimer = NULL;
#ifdef WIN32
      MpMMTimerWnt mmTimerWnt(MpMMTimer::Linear);
      pMMTimer = &mmTimerWnt;
#else
      // Right now MMTimers are only implemented for win32.
      // as other platforms are implemented, change this.
      printf("MMTimer not implemented for this platform.  Test disabled.\n");
      return;
#endif

      // Allocate time objects to hold measurements
      OsTime perfTimes[TLT_LOOP_CNT];

      // Initialize the timer.
      printf("Firing every %d usecs\n", periodUSecs);
      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->run(periodUSecs));

      // Perform the timing measurements.
      int i;
      for(i = 0; i < TLT_LOOP_CNT; i++)
      {
         OsDateTime::getCurTime(perfTimes[i]);
         CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->waitForNextTick());
      }

      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->stop());

      // Determine delta times from individual time measurements..
      int64_t curUsec_i = 0;
      int64_t curUsec_iPlus1 = 0;
      int64_t curUsec_0 = 0;
      long deltas[TLT_LOOP_CNT-1];
      long absDeltas[TLT_LOOP_CNT-1];
      for(i = 0; i < TLT_LOOP_CNT-1; i++)
      {
         curUsec_i = perfTimes[i].seconds()*1000*1000 + perfTimes[i].usecs();
         curUsec_iPlus1 = perfTimes[i+1].seconds()*1000*1000 + perfTimes[i+1].usecs();
         curUsec_0 = perfTimes[0].seconds()*1000*1000 + perfTimes[0].usecs();

         deltas[i] = (long)(curUsec_iPlus1 - curUsec_i);
         absDeltas[i] = (long)((curUsec_iPlus1 - curUsec_0) - periodUSecs*i);
      }

      checkDeltasAgainstThresholds(deltas, absDeltas, TLT_LOOP_CNT-1,
                                   periodUSecs,
                                   lowerThresh, upperThresh);
      checkMeanAgainstThresholds(perfTimes[0], perfTimes[TLT_LOOP_CNT-1],
                                 TLT_LOOP_CNT-1,
                                 periodUSecs,
                                 lowerMeanThresh, upperMeanThresh);
   }

   void notificationTimerRecordTick()
   {
      int x;
      x = mPerfTimesSz;
      CPPUNIT_ASSERT(mpPerfTimes != NULL);
      CPPUNIT_ASSERT(mPerfTimesSz > 0);

      // Collect measurements while we have space left.
      if(mCurNPerfTimes < mPerfTimesSz)
      {
         OsDateTime::getCurTime(mpPerfTimes[mCurNPerfTimes]);
         mCurNPerfTimes++;
      }
   }

   void testNotificationTimer()
   {
      // Set the below variables and preprocessor defines to tweak this test.
      // mPerfCountsSz defines the number of timer fire repetitions to do
      // (set this to an even value),
      // and periodUSecs defines how long to wait in each one.
      mPerfTimesSz = 2000;
      unsigned periodUSecs = 10000;
      long lowerThresh = -(long)periodUSecs+1; // Assert when outside an error range
      long lowerMeanThresh = -50;              // specified below.
      long upperThresh = periodUSecs*2-1;      // One for single values
      long upperMeanThresh = 50;               // One for mean values

      TimerNotification timerNotification(this);
      MpMMTimer* pMMTimer = NULL;
#ifdef WIN32
      MpMMTimerWnt mmTimerWnt(MpMMTimer::Notification);
      pMMTimer = &mmTimerWnt;
#else
      // Right now MMTimers are only implemented for win32.
      // as other platforms are implemented, change this.
      printf("MMTimer not implemented for this platform.  Test disabled.\n");
      return;
#endif

      // Set the notification..
      pMMTimer->setNotification(&timerNotification);

      // Allocate time objects to hold measurements
      mpPerfTimes = new OsTime[mPerfTimesSz];

      // Initialize the timer.
      printf("Firing every %d usecs\n", periodUSecs);
      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->run(periodUSecs));

      // Wait for the callbacks to perform the timing measurements.
      OsTask::delay(periodUSecs*mPerfTimesSz/1000 + 50);

      // The callbacks should be done by now, so if they aren't,
      // then bitch.
      //We should have a current count of the actual size of the perf buffer.
      CPPUNIT_ASSERT_EQUAL(mPerfTimesSz, mCurNPerfTimes);

      // Clear the OsNotification, as it doesn't need to be continuing to notify.
      pMMTimer->setNotification(NULL);

      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->stop());

      // Determine delta times from individual time measurements..
      int64_t curUsec_i = 0;
      int64_t curUsec_iPlus1 = 0;
      int64_t curUsec_0 = 0;
      long* pDeltas = new long[mPerfTimesSz-1];
      long* pAbsDeltas = new long[mPerfTimesSz-1];
      unsigned i;
      for(i = 0; i < mPerfTimesSz-1; i = i++)
      {
         curUsec_i = mpPerfTimes[i].seconds()*1000*1000 + mpPerfTimes[i].usecs();
         curUsec_iPlus1 = mpPerfTimes[i+1].seconds()*1000*1000 + mpPerfTimes[i+1].usecs();
         curUsec_0 = mpPerfTimes[0].seconds()*1000*1000 + mpPerfTimes[0].usecs();

         pDeltas[i] = (long)(curUsec_iPlus1 - curUsec_i);
         pAbsDeltas[i] = (long)((curUsec_iPlus1 - curUsec_0) - periodUSecs*i);
      }

      checkDeltasAgainstThresholds(pDeltas, pAbsDeltas, mPerfTimesSz-1,
                                   periodUSecs,
                                   lowerThresh, upperThresh);
      checkMeanAgainstThresholds(mpPerfTimes[0], mpPerfTimes[mPerfTimesSz-1],
                                 mPerfTimesSz-1,
                                 periodUSecs,
                                 lowerMeanThresh, upperMeanThresh);

      // Cleanup!
      delete[] pDeltas;
      pDeltas = NULL;
      delete[] pAbsDeltas;
      pAbsDeltas = NULL;
      delete[] mpPerfTimes;
      mpPerfTimes = NULL;
      mCurNPerfTimes = 0;
      mPerfTimesSz = 0;
   }

protected:

   OsTime* mpPerfTimes;
   unsigned mPerfTimesSz;
   unsigned mCurNPerfTimes;
};

CPPUNIT_TEST_SUITE_REGISTRATION(MpMMTimerTest);

// Implementation of TimerNotification methods.
TimerNotification::TimerNotification(MpMMTimerTest* pMMTimerTest)
   : mpMMTimerTest(pMMTimerTest)
{
   CPPUNIT_ASSERT(pMMTimerTest != NULL);
}

OsStatus TimerNotification::signal(const intptr_t eventData)
{
   mpMMTimerTest->notificationTimerRecordTick();
   return OS_SUCCESS;
}
<commit_msg>Fix infinite loop in MpMMTimerTest::testNotificationTimer().<commit_after>//
// Copyright (C) 2007 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2007 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <sipxunit/TestUtilities.h>

#include <mp/MpMMTimer.h>
#include <os/OsDateTime.h>
#include <os/OsSysLog.h>
#include <os/OsNotification.h>
#include <os/OsTask.h>

#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mp/MpMMTimerWnt.h>
#endif

// Forward Decl's
class MpMMTimerTest;

class TimerNotification : public OsNotification
{
public:
   TimerNotification(MpMMTimerTest* pMMTimerTest);
   virtual ~TimerNotification() {}
   OsStatus signal(const intptr_t eventData);

private:
   MpMMTimerTest* mpMMTimerTest;
};

/**
 * Unittest for MpMMTimer and its successors
 */
class MpMMTimerTest : public CppUnit::TestCase
{
   CPPUNIT_TEST_SUITE(MpMMTimerTest);
   CPPUNIT_TEST(testGetResolution);
   CPPUNIT_TEST(testPeriodRange);
   CPPUNIT_TEST(testLinearTimer);
   CPPUNIT_TEST(testNotificationTimer);
   CPPUNIT_TEST_SUITE_END();

public:
   void setUp()
   {
      mpPerfTimes = NULL;
      mPerfTimesSz = 0;
      mCurNPerfTimes = 0;
   }

   void tearDown()
   {
      if(mpPerfTimes != NULL)
      {
         delete[] mpPerfTimes;
      }
      mpPerfTimes = NULL;
      mPerfTimesSz = 0;
      mCurNPerfTimes = 0;
   }

   void checkDeltasAgainstThresholds(long deltas[], long absDeltas[], unsigned nDeltas,
                                     unsigned targetDelta, // <-- was periodUSecs
                                     long lowerThresh, long upperThresh)
   {
      CPPUNIT_ASSERT_MESSAGE("Timer didn't fire or deltas were not collected!",
                             nDeltas > 0);

      printf("Timing values in microseconds, CSV: \n");
      long valOutsideThreshs = targetDelta; // initialize to exactly what we want.
      unsigned i;
      for(i = 0; i < nDeltas; i++)
      {
         // Print output in CSV format, for easy graphing.
         printf("%ld\t%ld", deltas[i], absDeltas[i]);
         printf((i < nDeltas-1) ? "\n" : "\n\n");  // done this way for easy change to comma CSV

         // Check if we're outside some reasonable thresholds.
         if(i > 0 && // don't include the first value in our tests - it's always high.
            valOutsideThreshs == targetDelta) // Only check if we haven't already gone outside threshold.
         {
            if(deltas[i]-(long)targetDelta < lowerThresh ||
               deltas[i]-(long)targetDelta > upperThresh)
            {
               valOutsideThreshs = deltas[i];
            }
         }
      }

      // Assert when single value outside error range specified above.
      char errStrBuf[256];
      snprintf(errStrBuf, 256,
               "Single timer value %ld falls outside threshold of %ld to %ld us",
               valOutsideThreshs, lowerThresh, upperThresh);

      CPPUNIT_ASSERT_MESSAGE(errStrBuf,
                             (valOutsideThreshs-(long)targetDelta >= lowerThresh &&
                              valOutsideThreshs-(long)targetDelta <= upperThresh));
   }

   void checkMeanAgainstThresholds(const OsTime& start, const OsTime& stop,
                                   unsigned nDeltas,
                                   unsigned targetDelta, // <-- was periodUSecs
                                   long lowerMeanThresh, long upperMeanThresh)
   {
      CPPUNIT_ASSERT_MESSAGE("Timer didn't fire or deltas were not collected!",
                             nDeltas > 0);

      double meanAvg = 0;

      int64_t totStartUSecs = start.seconds()*1000*1000 + start.usecs();
      int64_t totStopUSecs = stop.seconds()*1000*1000 + stop.usecs();

      meanAvg = (totStopUSecs-totStartUSecs)/(double)nDeltas;
      printf("Mean: %.2f us\n", meanAvg);

      // Assert when mean is outside error range specified above.
      char errStrBuf[256];
      snprintf(errStrBuf, 256,
         "Mean timer value %.2f falls outside threshold of %ld to %ld us",
         meanAvg, lowerMeanThresh, upperMeanThresh);

      CPPUNIT_ASSERT_MESSAGE(errStrBuf,
                             (meanAvg-(long)targetDelta >= lowerMeanThresh &&
                              meanAvg-(long)targetDelta <= upperMeanThresh));
   }

   void testGetResolution()
   {
      // Test getting the resolution, and get it..
      unsigned resolution;

#ifdef WIN32
      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, MpMMTimer::getResolution(resolution));
      printf("Minimum timer resolution is %d usecs\n", resolution);
#else
      printf("MpMMTimer::getResolution() not yet implemented on this "
             "platform, excluding test.\n");
#endif
   }

   void testPeriodRange()
   {
      // Test the period range static method..
      unsigned unusedMin = 0;
      unsigned unusedMax = 0;
#ifdef WIN32
      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS,
         MpMMTimer::getPeriodRange(&unusedMin, &unusedMax));
#else
      printf("MpMMTimer::getPeriodRange() not yet implemented on this "
             "platform, excluding test.\n");
#endif
   }

   void testLinearTimer()
   {
      // Set the below variables and preprocessor defines to tweak this test.
      // TLT_LOOP_COUNT defines the number of timer fire repetitions to do
      // (set this to an even value),
      // and periodUSecs defines how long to wait in each one.
#     define TLT_LOOP_CNT 2000
      unsigned periodUSecs = 10000;
      long lowerThresh = -(long)periodUSecs; // Assert when outside an error range
      long lowerMeanThresh = -50;            // specified below.
      long upperThresh = periodUSecs*2;      // One for single values
      long upperMeanThresh = 50;             // One for mean values

      MpMMTimer* pMMTimer = NULL;
#ifdef WIN32
      MpMMTimerWnt mmTimerWnt(MpMMTimer::Linear);
      pMMTimer = &mmTimerWnt;
#else
      // Right now MMTimers are only implemented for win32.
      // as other platforms are implemented, change this.
      printf("MMTimer not implemented for this platform.  Test disabled.\n");
      return;
#endif

      // Allocate time objects to hold measurements
      OsTime perfTimes[TLT_LOOP_CNT];

      // Initialize the timer.
      printf("Firing every %d usecs\n", periodUSecs);
      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->run(periodUSecs));

      // Perform the timing measurements.
      int i;
      for(i = 0; i < TLT_LOOP_CNT; i++)
      {
         OsDateTime::getCurTime(perfTimes[i]);
         CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->waitForNextTick());
      }

      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->stop());

      // Determine delta times from individual time measurements..
      int64_t curUsec_i = 0;
      int64_t curUsec_iPlus1 = 0;
      int64_t curUsec_0 = 0;
      long deltas[TLT_LOOP_CNT-1];
      long absDeltas[TLT_LOOP_CNT-1];
      for(i = 0; i < TLT_LOOP_CNT-1; i++)
      {
         curUsec_i = perfTimes[i].seconds()*1000*1000 + perfTimes[i].usecs();
         curUsec_iPlus1 = perfTimes[i+1].seconds()*1000*1000 + perfTimes[i+1].usecs();
         curUsec_0 = perfTimes[0].seconds()*1000*1000 + perfTimes[0].usecs();

         deltas[i] = (long)(curUsec_iPlus1 - curUsec_i);
         absDeltas[i] = (long)((curUsec_iPlus1 - curUsec_0) - periodUSecs*i);
      }

      checkDeltasAgainstThresholds(deltas, absDeltas, TLT_LOOP_CNT-1,
                                   periodUSecs,
                                   lowerThresh, upperThresh);
      checkMeanAgainstThresholds(perfTimes[0], perfTimes[TLT_LOOP_CNT-1],
                                 TLT_LOOP_CNT-1,
                                 periodUSecs,
                                 lowerMeanThresh, upperMeanThresh);
   }

   void notificationTimerRecordTick()
   {
      int x;
      x = mPerfTimesSz;
      CPPUNIT_ASSERT(mpPerfTimes != NULL);
      CPPUNIT_ASSERT(mPerfTimesSz > 0);

      // Collect measurements while we have space left.
      if(mCurNPerfTimes < mPerfTimesSz)
      {
         OsDateTime::getCurTime(mpPerfTimes[mCurNPerfTimes]);
         mCurNPerfTimes++;
      }
   }

   void testNotificationTimer()
   {
      // Set the below variables and preprocessor defines to tweak this test.
      // mPerfCountsSz defines the number of timer fire repetitions to do
      // (set this to an even value),
      // and periodUSecs defines how long to wait in each one.
      mPerfTimesSz = 2000;
      unsigned periodUSecs = 10000;
      long lowerThresh = -(long)periodUSecs+1; // Assert when outside an error range
      long lowerMeanThresh = -50;              // specified below.
      long upperThresh = periodUSecs*2-1;      // One for single values
      long upperMeanThresh = 50;               // One for mean values

      TimerNotification timerNotification(this);
      MpMMTimer* pMMTimer = NULL;
#ifdef WIN32
      MpMMTimerWnt mmTimerWnt(MpMMTimer::Notification);
      pMMTimer = &mmTimerWnt;
#else
      // Right now MMTimers are only implemented for win32.
      // as other platforms are implemented, change this.
      printf("MMTimer not implemented for this platform.  Test disabled.\n");
      return;
#endif

      // Set the notification..
      pMMTimer->setNotification(&timerNotification);

      // Allocate time objects to hold measurements
      mpPerfTimes = new OsTime[mPerfTimesSz];

      // Initialize the timer.
      printf("Firing every %d usecs\n", periodUSecs);
      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->run(periodUSecs));

      // Wait for the callbacks to perform the timing measurements.
      OsTask::delay(periodUSecs*mPerfTimesSz/1000 + 50);

      // The callbacks should be done by now, so if they aren't,
      // then bitch.
      //We should have a current count of the actual size of the perf buffer.
      CPPUNIT_ASSERT_EQUAL(mPerfTimesSz, mCurNPerfTimes);

      // Clear the OsNotification, as it doesn't need to be continuing to notify.
      pMMTimer->setNotification(NULL);

      CPPUNIT_ASSERT_EQUAL(OS_SUCCESS, pMMTimer->stop());

      // Determine delta times from individual time measurements..
      int64_t curUsec_i = 0;
      int64_t curUsec_iPlus1 = 0;
      int64_t curUsec_0 = 0;
      long* pDeltas = new long[mPerfTimesSz-1];
      long* pAbsDeltas = new long[mPerfTimesSz-1];
      unsigned i;
      for(i = 0; i < mPerfTimesSz-1; i++)
      {
         curUsec_i = mpPerfTimes[i].seconds()*1000*1000 + mpPerfTimes[i].usecs();
         curUsec_iPlus1 = mpPerfTimes[i+1].seconds()*1000*1000 + mpPerfTimes[i+1].usecs();
         curUsec_0 = mpPerfTimes[0].seconds()*1000*1000 + mpPerfTimes[0].usecs();

         pDeltas[i] = (long)(curUsec_iPlus1 - curUsec_i);
         pAbsDeltas[i] = (long)((curUsec_iPlus1 - curUsec_0) - periodUSecs*i);
      }

      checkDeltasAgainstThresholds(pDeltas, pAbsDeltas, mPerfTimesSz-1,
                                   periodUSecs,
                                   lowerThresh, upperThresh);
      checkMeanAgainstThresholds(mpPerfTimes[0], mpPerfTimes[mPerfTimesSz-1],
                                 mPerfTimesSz-1,
                                 periodUSecs,
                                 lowerMeanThresh, upperMeanThresh);

      // Cleanup!
      delete[] pDeltas;
      pDeltas = NULL;
      delete[] pAbsDeltas;
      pAbsDeltas = NULL;
      delete[] mpPerfTimes;
      mpPerfTimes = NULL;
      mCurNPerfTimes = 0;
      mPerfTimesSz = 0;
   }

protected:

   OsTime* mpPerfTimes;
   unsigned mPerfTimesSz;
   unsigned mCurNPerfTimes;
};

CPPUNIT_TEST_SUITE_REGISTRATION(MpMMTimerTest);

// Implementation of TimerNotification methods.
TimerNotification::TimerNotification(MpMMTimerTest* pMMTimerTest)
   : mpMMTimerTest(pMMTimerTest)
{
   CPPUNIT_ASSERT(pMMTimerTest != NULL);
}

OsStatus TimerNotification::signal(const intptr_t eventData)
{
   mpMMTimerTest->notificationTimerRecordTick();
   return OS_SUCCESS;
}
<|endoftext|>


<commit_before>//
//  refract/Element.cc
//  librefract
//
//  Created by Jiri Kratochvil on 18/05/15.
//  Copyright (c) 2015 Apiary Inc. All rights reserved.
//
#include "Element.h"
#include <cassert>

#include <set>
#include <map>
#include <string>

#include "ComparableVisitor.h"
#include "TypeQueryVisitor.h"

#include <string.h>
#include <array>

namespace refract
{

    namespace {

        const constexpr std::array<const char*, 13> reservedKeywords = {

            "null",
            "boolean",
            "number",
            "string",

            "member",

            "array",
            "enum",
            "object",

            "ref",
            "select",
            "option",
            "extend",

            "generic"
        };

        const constexpr std::array<const char*, 3> noMetaKeywords = {
            "id",
            "prefix",
            "namespace"
        };

        const constexpr std::array<const char*, 0> emptyArray;

        template <typename Container>
        struct inKeys {
            const Container& keywords;
            inKeys(const Container& keywords) : keywords(keywords) {}

            bool operator()(const std::string& searched) {
                return std::any_of(keywords.begin(), keywords.end(),
                                   [&searched](const char* key) {
                                       return !strcmp(key, searched.c_str());
                                   });
            }
        };

        template <typename Container>
        inKeys<Container> InKeysChecker(const Container& keywords) {
            return inKeys<Container>(keywords);
        }

    }

    bool isReserved(const std::string& element) {
        return InKeysChecker(reservedKeywords)(element);
    }

    IElement::MemberElementCollection::const_iterator IElement::MemberElementCollection::find(
        const std::string& name) const
    {
        ComparableVisitor v(name);
        Visitor visitor(v);

        return std::find_if(elements.begin(), elements.end(), [&visitor, &v](const MemberElement* e) {
            e->value.first->content(visitor);
            return v.get();
        });
    }

    IElement::MemberElementCollection::iterator IElement::MemberElementCollection::find(const std::string& name)
    {
        ComparableVisitor v(name);
        Visitor visitor(v);

        return std::find_if(elements.begin(), elements.end(), [&visitor, &v](const MemberElement* e) {
            e->value.first->content(visitor);
            return v.get();
        });
    }

    IElement::MemberElementCollection::~MemberElementCollection()
    {
        for (MemberElement* e : elements)
            delete e;
    }

    StringElement* IElement::Create(const char* value)
    {
        return Create(std::string(value));
    };

    MemberElement& IElement::MemberElementCollection::operator[](const std::string& name)
    {
        auto it = find(name);
        if (it != elements.end()) {
            return *(*it);
        }

        elements.emplace_back(new MemberElement(new StringElement(name), nullptr));

        return *elements.back();
    }

    void IElement::MemberElementCollection::clone(const IElement::MemberElementCollection& other)
    {
        for (const auto& el : other.elements) {
            elements.emplace_back(static_cast<MemberElement*>(el->clone()));
        }
    }

    void IElement::MemberElementCollection::erase(const std::string& key)
    {
        auto it = find(key);

        if (it != elements.end()) {
            delete *it;
            elements.erase(it);
        }
    }

    namespace
    {

        bool TypeChecker(const ExtendElement::ValueType& values)
        {
            if (values.empty()) {
                return true;
            }

            TypeQueryVisitor visitor;
            Visit(visitor, *values.front());

            const TypeQueryVisitor::ElementType base = visitor.get();

            return std::all_of(values.begin(), values.end(), [&visitor, base](const IElement* e) {
                Visit(visitor, *e);
                return base == visitor.get();
            });
        }
    }

    void ExtendElement::set(const ExtendElement::ValueType& val)
    {
        if (!TypeChecker(val)) {
            throw LogicError("ExtendElement must be composed from Elements of same type");
        }

        if (val.empty()) {
            return;
        }

        hasContent = true;
        value = val;
    }

    void ExtendElement::push_back(IElement* e)
    {

        if (!e) {
            return;
        }

        if (!value.empty()) {
            TypeQueryVisitor baseType;
            Visit(baseType, *value.front());

            TypeQueryVisitor type;
            Visit(type, *e);

            if (baseType.get() != type.get()) {
                throw LogicError("ExtendElement must be composed from Elements of same type");
            }
        }

        hasContent = true;
        value.push_back(e);
    }

    namespace
    {

        class ElementMerger
        {

            IElement* result;
            TypeQueryVisitor::ElementType base;

            /**
             * Merge strategy for Primitive types - just replace by latest value
             */
            template <typename T, typename V = typename T::ValueType>
            struct ValueMerge {
                V& value;
                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    value = merge.value;
                }
            };

            template <typename T>
            struct ValueMerge<T, IElement*> {
                IElement*& value;
                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    if (!value && merge.value) {
                        value = merge.value->clone();
                    }
                }
            };

            /**
             * Merge stategy for objects/array
             * - if member
             *   - without existing key -> append
             *   - with existing key - replace old value
             * - if not member
             *   - if empty value -> ignore (type holder for array)
             *   - else append
             */
            template <typename T>
            struct ValueMerge<T, RefractElements> {
                typename T::ValueType& value;

                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    typedef std::map<std::string, MemberElement*> MapKeyToMember;
                    typedef std::map<std::string, RefElement*> MapNameToRef;

                    MapKeyToMember keysBase;
                    MapNameToRef refBase;

                    for (auto& element : value) {
                        if (MemberElement* member = TypeQueryVisitor::as<MemberElement>(element)) {

                            if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                                keysBase[key->value] = member;
                            }
                        } else if (RefElement* ref = TypeQueryVisitor::as<RefElement>(element)) {
                            refBase[ref->value] = ref;
                        }
                    }

                    for (auto const& element : merge.value) {
                        if (MemberElement* member = TypeQueryVisitor::as<MemberElement>(element)) {
                            if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                                MapKeyToMember::iterator iKey = keysBase.find(key->value);

                                if (iKey != keysBase.end()) { // key is already presented, replace value
                                    delete iKey->second->value.second;
                                    iKey->second->value.second = member->value.second->clone();

                                    CollectionMerge()(iKey->second->meta, member->meta, InKeysChecker(noMetaKeywords));
                                    CollectionMerge()(iKey->second->attributes, member->attributes, InKeysChecker(emptyArray));
                                }
                                else { // unknown key, append value
                                    MemberElement* clone = static_cast<MemberElement*>(member->clone());
                                    value.push_back(clone);
                                    keysBase[key->value] = clone;
                                }
                            }
                        } else if (RefElement* ref = TypeQueryVisitor::as<RefElement>(element)) {
                            if (refBase.find(ref->value) == refBase.end()) {
                                RefElement* clone = static_cast<RefElement*>(member->clone());
                                value.push_back(clone);
                                refBase[ref->value] = clone;
                            }
                        } else if (!(element)->empty()) { // merge member is not MemberElement, append value
                            value.push_back(element->clone());
                        }
                    }
                }
            };

            class CollectionMerge {

            public:
                CollectionMerge() = default;

                void operator()(IElement::MemberElementCollection& info, const IElement::MemberElementCollection& append, std::function<bool (const std::string&)> noMerge) {
                    IElement::MemberElementCollection toAppend;

                    for (const auto& member : append) {

                        assert(member);

                        if (!member) {
                            continue;
                        }

                        if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                            if (noMerge(key->value)) {
                                continue;
                            }

                            IElement::MemberElementCollection::iterator item = info.find(key->value);
                            if (item != info.end()) {
                                // this key alrady exist, replace value
                                delete (*item)->value.second;
                                (*item)->value.second = member->value.second->clone();
                                continue;
                            }
                        }

                        toAppend.push_back(static_cast<MemberElement*>(member->clone()));
                    }

                    for (const auto& member : toAppend) {
                        info.push_back(member);
                    }

                    toAppend.clear();
                }
            };

            /**
             * precondition - target && append element MUST BE of same type
             * we use static_cast<> without checking type this is responsibility of caller
             */
            template <typename T>
            static void doMerge(IElement* target, const IElement* append)
            {
                typedef T ElementType;

                CollectionMerge()(target->meta, append->meta, InKeysChecker(noMetaKeywords));
                CollectionMerge()(target->attributes, append->attributes, InKeysChecker(emptyArray));

                ValueMerge<T>(static_cast<ElementType&>(*target))(static_cast<const ElementType&>(*append));
            }

        public:
            ElementMerger() : result(NULL), base(TypeQueryVisitor::Unknown)
            {
            }

            void operator()(const IElement* e)
            {
                if (!e) {
                    return;
                }

                if (!result) {
                    result = e->clone();

                    TypeQueryVisitor type;
                    Visit(type, *result);
                    base = type.get();
                    return;
                }

                TypeQueryVisitor type;
                VisitBy(*e, type);

                if (type.get() != base) {
                    throw refract::LogicError("Can not merge different types of elements");
                }

                switch (base) {
                    case TypeQueryVisitor::String:
                        doMerge<StringElement>(result, e);
                        return;

                    case TypeQueryVisitor::Number:
                        doMerge<NumberElement>(result, e);
                        return;

                    case TypeQueryVisitor::Boolean:
                        doMerge<BooleanElement>(result, e);
                        return;

                    case TypeQueryVisitor::Array:
                        doMerge<ArrayElement>(result, e);
                        return;

                    case TypeQueryVisitor::Object:
                        doMerge<ObjectElement>(result, e);
                        return;

                    case TypeQueryVisitor::Enum:
                        doMerge<EnumElement>(result, e);
                        return;

                    case TypeQueryVisitor::Ref:
                        doMerge<RefElement>(result, e);
                        return;

                    case TypeQueryVisitor::Member:
                    case TypeQueryVisitor::Extend:
                    case TypeQueryVisitor::Null:
                        throw LogicError("Unappropriate kind of element to merging");
                    default:
                        throw LogicError("Element has no implemented merging");
                }
            }

            operator IElement*() const
            {
                return result;
            }
        };
    }

    IElement* ExtendElement::merge() const
    {
        return std::for_each(value.begin(), value.end(), ElementMerger());
    }

}; // namespace refract
<commit_msg>reformat according to clangformat as required in review<commit_after>//
//  refract/Element.cc
//  librefract
//
//  Created by Jiri Kratochvil on 18/05/15.
//  Copyright (c) 2015 Apiary Inc. All rights reserved.
//
#include "Element.h"
#include <cassert>

#include <set>
#include <map>
#include <string>

#include "ComparableVisitor.h"
#include "TypeQueryVisitor.h"

#include <string.h>
#include <array>

namespace refract
{

    namespace
    {

        const constexpr std::array<const char*, 13> reservedKeywords = {

            "null",
            "boolean",
            "number",
            "string",

            "member",

            "array",
            "enum",
            "object",

            "ref",
            "select",
            "option",
            "extend",

            "generic"
        };

        const constexpr std::array<const char*, 3> noMetaKeywords = { "id", "prefix", "namespace" };

        const constexpr std::array<const char*, 0> emptyArray;

        template <typename Container>
        struct inKeys {
            const Container& keywords;
            inKeys(const Container& keywords) : keywords(keywords)
            {
            }

            bool operator()(const std::string& searched)
            {
                return std::any_of(keywords.begin(), keywords.end(), [&searched](const char* key) {
                    return !strcmp(key, searched.c_str());
                });
            }
        };

        template <typename Container>
        inKeys<Container> InKeysChecker(const Container& keywords)
        {
            return inKeys<Container>(keywords);
        }
    }

    bool isReserved(const std::string& element)
    {
        return InKeysChecker(reservedKeywords)(element);
    }

    IElement::MemberElementCollection::const_iterator IElement::MemberElementCollection::find(
        const std::string& name) const
    {
        ComparableVisitor v(name);
        Visitor visitor(v);

        return std::find_if(elements.begin(), elements.end(), [&visitor, &v](const MemberElement* e) {
            e->value.first->content(visitor);
            return v.get();
        });
    }

    IElement::MemberElementCollection::iterator IElement::MemberElementCollection::find(const std::string& name)
    {
        ComparableVisitor v(name);
        Visitor visitor(v);

        return std::find_if(elements.begin(), elements.end(), [&visitor, &v](const MemberElement* e) {
            e->value.first->content(visitor);
            return v.get();
        });
    }

    IElement::MemberElementCollection::~MemberElementCollection()
    {
        for (MemberElement* e : elements)
            delete e;
    }

    StringElement* IElement::Create(const char* value)
    {
        return Create(std::string(value));
    };

    MemberElement& IElement::MemberElementCollection::operator[](const std::string& name)
    {
        auto it = find(name);
        if (it != elements.end()) {
            return *(*it);
        }

        elements.emplace_back(new MemberElement(new StringElement(name), nullptr));

        return *elements.back();
    }

    void IElement::MemberElementCollection::clone(const IElement::MemberElementCollection& other)
    {
        for (const auto& el : other.elements) {
            elements.emplace_back(static_cast<MemberElement*>(el->clone()));
        }
    }

    void IElement::MemberElementCollection::erase(const std::string& key)
    {
        auto it = find(key);

        if (it != elements.end()) {
            delete *it;
            elements.erase(it);
        }
    }

    namespace
    {

        bool TypeChecker(const ExtendElement::ValueType& values)
        {
            if (values.empty()) {
                return true;
            }

            TypeQueryVisitor visitor;
            Visit(visitor, *values.front());

            const TypeQueryVisitor::ElementType base = visitor.get();

            return std::all_of(values.begin(), values.end(), [&visitor, base](const IElement* e) {
                Visit(visitor, *e);
                return base == visitor.get();
            });
        }
    }

    void ExtendElement::set(const ExtendElement::ValueType& val)
    {
        if (!TypeChecker(val)) {
            throw LogicError("ExtendElement must be composed from Elements of same type");
        }

        if (val.empty()) {
            return;
        }

        hasContent = true;
        value = val;
    }

    void ExtendElement::push_back(IElement* e)
    {

        if (!e) {
            return;
        }

        if (!value.empty()) {
            TypeQueryVisitor baseType;
            Visit(baseType, *value.front());

            TypeQueryVisitor type;
            Visit(type, *e);

            if (baseType.get() != type.get()) {
                throw LogicError("ExtendElement must be composed from Elements of same type");
            }
        }

        hasContent = true;
        value.push_back(e);
    }

    namespace
    {

        class ElementMerger
        {

            IElement* result;
            TypeQueryVisitor::ElementType base;

            /**
             * Merge strategy for Primitive types - just replace by latest value
             */
            template <typename T, typename V = typename T::ValueType>
            struct ValueMerge {
                V& value;
                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    value = merge.value;
                }
            };

            template <typename T>
            struct ValueMerge<T, IElement*> {
                IElement*& value;
                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    if (!value && merge.value) {
                        value = merge.value->clone();
                    }
                }
            };

            /**
             * Merge stategy for objects/array
             * - if member
             *   - without existing key -> append
             *   - with existing key - replace old value
             * - if not member
             *   - if empty value -> ignore (type holder for array)
             *   - else append
             */
            template <typename T>
            struct ValueMerge<T, RefractElements> {
                typename T::ValueType& value;

                ValueMerge(T& element) : value(element.value)
                {
                }

                void operator()(const T& merge)
                {
                    typedef std::map<std::string, MemberElement*> MapKeyToMember;
                    typedef std::map<std::string, RefElement*> MapNameToRef;

                    MapKeyToMember keysBase;
                    MapNameToRef refBase;

                    for (auto& element : value) {
                        if (MemberElement* member = TypeQueryVisitor::as<MemberElement>(element)) {

                            if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                                keysBase[key->value] = member;
                            }
                        } else if (RefElement* ref = TypeQueryVisitor::as<RefElement>(element)) {
                            refBase[ref->value] = ref;
                        }
                    }

                    for (auto const& element : merge.value) {
                        if (MemberElement* member = TypeQueryVisitor::as<MemberElement>(element)) {
                            if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                                MapKeyToMember::iterator iKey = keysBase.find(key->value);

                                if (iKey != keysBase.end()) { // key is already presented, replace value
                                    delete iKey->second->value.second;
                                    iKey->second->value.second = member->value.second->clone();

                                    CollectionMerge()(iKey->second->meta, member->meta, InKeysChecker(noMetaKeywords));
                                    CollectionMerge()(
                                        iKey->second->attributes, member->attributes, InKeysChecker(emptyArray));
                                } else { // unknown key, append value
                                    MemberElement* clone = static_cast<MemberElement*>(member->clone());
                                    value.push_back(clone);
                                    keysBase[key->value] = clone;
                                }
                            }
                        } else if (RefElement* ref = TypeQueryVisitor::as<RefElement>(element)) {
                            if (refBase.find(ref->value) == refBase.end()) {
                                RefElement* clone = static_cast<RefElement*>(member->clone());
                                value.push_back(clone);
                                refBase[ref->value] = clone;
                            }
                        } else if (!(element)->empty()) { // merge member is not MemberElement, append value
                            value.push_back(element->clone());
                        }
                    }
                }
            };

            class CollectionMerge
            {

            public:
                CollectionMerge() = default;

                void operator()(IElement::MemberElementCollection& info, const IElement::MemberElementCollection& append, std::function<bool (const std::string&)> noMerge) {
                    IElement::MemberElementCollection toAppend;

                    for (const auto& member : append) {

                        assert(member);

                        if (!member) {
                            continue;
                        }

                        if (StringElement* key = TypeQueryVisitor::as<StringElement>(member->value.first)) {
                            if (noMerge(key->value)) {
                                continue;
                            }

                            IElement::MemberElementCollection::iterator item = info.find(key->value);
                            if (item != info.end()) {
                                // this key alrady exist, replace value
                                delete (*item)->value.second;
                                (*item)->value.second = member->value.second->clone();
                                continue;
                            }
                        }

                        toAppend.push_back(static_cast<MemberElement*>(member->clone()));
                    }

                    for (const auto& member : toAppend) {
                        info.push_back(member);
                    }

                    toAppend.clear();
                }
            };

            /**
             * precondition - target && append element MUST BE of same type
             * we use static_cast<> without checking type this is responsibility of caller
             */
            template <typename T>
            static void doMerge(IElement* target, const IElement* append)
            {
                typedef T ElementType;

                CollectionMerge()(target->meta, append->meta, InKeysChecker(noMetaKeywords));
                CollectionMerge()(target->attributes, append->attributes, InKeysChecker(emptyArray));

                ValueMerge<T>(static_cast<ElementType&>(*target))(static_cast<const ElementType&>(*append));
            }

        public:
            ElementMerger() : result(NULL), base(TypeQueryVisitor::Unknown)
            {
            }

            void operator()(const IElement* e)
            {
                if (!e) {
                    return;
                }

                if (!result) {
                    result = e->clone();

                    TypeQueryVisitor type;
                    Visit(type, *result);
                    base = type.get();
                    return;
                }

                TypeQueryVisitor type;
                VisitBy(*e, type);

                if (type.get() != base) {
                    throw refract::LogicError("Can not merge different types of elements");
                }

                switch (base) {
                    case TypeQueryVisitor::String:
                        doMerge<StringElement>(result, e);
                        return;

                    case TypeQueryVisitor::Number:
                        doMerge<NumberElement>(result, e);
                        return;

                    case TypeQueryVisitor::Boolean:
                        doMerge<BooleanElement>(result, e);
                        return;

                    case TypeQueryVisitor::Array:
                        doMerge<ArrayElement>(result, e);
                        return;

                    case TypeQueryVisitor::Object:
                        doMerge<ObjectElement>(result, e);
                        return;

                    case TypeQueryVisitor::Enum:
                        doMerge<EnumElement>(result, e);
                        return;

                    case TypeQueryVisitor::Ref:
                        doMerge<RefElement>(result, e);
                        return;

                    case TypeQueryVisitor::Member:
                    case TypeQueryVisitor::Extend:
                    case TypeQueryVisitor::Null:
                        throw LogicError("Unappropriate kind of element to merging");
                    default:
                        throw LogicError("Element has no implemented merging");
                }
            }

            operator IElement*() const
            {
                return result;
            }
        };
    }

    IElement* ExtendElement::merge() const
    {
        return std::for_each(value.begin(), value.end(), ElementMerger());
    }

}; // namespace refract
<|endoftext|>


<commit_before>/* ************************************************************************
 * Copyright 2018 Advanced Micro Devices, Inc.
 * ************************************************************************ */

#include "unit.hpp"

#include <rocsparse.h>
#include <hip/hip_runtime_api.h>

#ifdef GOOGLE_TEST
#include <gtest/gtest.h>
#endif

/* ========================================Gtest Unit Check
 * ==================================================== */

/*! \brief Template: gtest unit compare two matrices float/double/complex */
// Do not put a wrapper over ASSERT_FLOAT_EQ, sincer assert exit the current function NOT the test
// case
// a wrapper will cause the loop keep going

template <>
void unit_check_general(rocsparse_int M, rocsparse_int N, float* hCPU, float* hGPU)
{
    for(rocsparse_int j = 0; j < N; j++)
    {
        for(rocsparse_int i = 0; i < M; i++)
        {
#ifdef GOOGLE_TEST
            ASSERT_FLOAT_EQ(hCPU[i + j], hGPU[i + j]);
#endif
        }
    }
}

template <>
void unit_check_general(rocsparse_int M, rocsparse_int N, double* hCPU, double* hGPU)
{
    for(rocsparse_int j = 0; j < N; j++)
    {
        for(rocsparse_int i = 0; i < M; i++)
        {
#ifdef GOOGLE_TEST
            ASSERT_DOUBLE_EQ(hCPU[i + j], hGPU[i + j]);
#endif
        }
    }
}

template <>
void unit_check_general(rocsparse_int M, rocsparse_int N, rocsparse_int* hCPU, rocsparse_int* hGPU)
{
    for(rocsparse_int j = 0; j < N; j++)
    {
        for(rocsparse_int i = 0; i < M; i++)
        {
#ifdef GOOGLE_TEST
            ASSERT_EQ(hCPU[i + j], hGPU[i + j]);
#endif
        }
    }
}
<commit_msg>added asserts to unit check to be able to verify when benchmarking<commit_after>/* ************************************************************************
 * Copyright 2018 Advanced Micro Devices, Inc.
 * ************************************************************************ */

#include "unit.hpp"

#include <rocsparse.h>
#include <assert.h>
#include <hip/hip_runtime_api.h>

#ifdef GOOGLE_TEST
#include <gtest/gtest.h>
#endif

/* ========================================Gtest Unit Check
 * ==================================================== */

/*! \brief Template: gtest unit compare two matrices float/double/complex */
// Do not put a wrapper over ASSERT_FLOAT_EQ, sincer assert exit the current function NOT the test
// case
// a wrapper will cause the loop keep going

template <>
void unit_check_general(rocsparse_int M, rocsparse_int N, float* hCPU, float* hGPU)
{
    for(rocsparse_int j = 0; j < N; j++)
    {
        for(rocsparse_int i = 0; i < M; i++)
        {
#ifdef GOOGLE_TEST
            ASSERT_FLOAT_EQ(hCPU[i + j], hGPU[i + j]);
#else
            assert(hCPU[i + j] == hGPU[i + j]);
#endif
        }
    }
}

template <>
void unit_check_general(rocsparse_int M, rocsparse_int N, double* hCPU, double* hGPU)
{
    for(rocsparse_int j = 0; j < N; j++)
    {
        for(rocsparse_int i = 0; i < M; i++)
        {
#ifdef GOOGLE_TEST
            ASSERT_DOUBLE_EQ(hCPU[i + j], hGPU[i + j]);
#else
            assert(hCPU[i + j] == hGPU[i + j]);
#endif
        }
    }
}

template <>
void unit_check_general(rocsparse_int M, rocsparse_int N, rocsparse_int* hCPU, rocsparse_int* hGPU)
{
    for(rocsparse_int j = 0; j < N; j++)
    {
        for(rocsparse_int i = 0; i < M; i++)
        {
#ifdef GOOGLE_TEST
            ASSERT_EQ(hCPU[i + j], hGPU[i + j]);
#else
            assert(hCPU[i + j] == hGPU[i + j]);
#endif
        }
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: AccessibleSelectionBase.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-24 16:49:39 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SVX_ACCESSIBILITY_ACCESSIBLE_SELECTION_BASE_HXX
#define _SVX_ACCESSIBILITY_ACCESSIBLE_SELECTION_BASE_HXX

#ifndef COMPHELPER_ACCESSIBLE_SELECTION_HELPER_HXX
#include <comphelper/accessibleselectionhelper.hxx>
#endif

namespace accessibility
{
/** @descr
        This base class provides a base implementation of the
        <type>XAccessibleSelection</type> interface.
        The following methods have to be implemented if this
        class is used:

        <method>implGetMutex</method>,
        <method>implGetAccessibleContext</method>,
        <method>implIsSelected</method>,
        <method>implSelect</method>,
*/
    class AccessibleSelectionBase : public ::comphelper::OCommonAccessibleSelection,
                                    public ::com::sun::star::accessibility::XAccessibleSelection
    {
    protected:

        virtual ::osl::Mutex&   implGetMutex() = 0;

    public:

        // XAccessibleSelection - default implementations
        virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL clearAccessibleSelection(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL selectAllAccessible(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);

    public:

                                AccessibleSelectionBase();
        virtual                 ~AccessibleSelectionBase();
    };

}

#endif // _SVX_ACCESSIBILITY_ACCESSIBLE_SELECTION_BASE_HXX
<commit_msg>INTEGRATION: CWS uaa03 (1.2.30); FILE MERGED 2003/05/21 15:46:00 mt 1.2.30.1: #i14623# UAA finalization<commit_after>/*************************************************************************
 *
 *  $RCSfile: AccessibleSelectionBase.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2003-05-22 12:53:27 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SVX_ACCESSIBILITY_ACCESSIBLE_SELECTION_BASE_HXX
#define _SVX_ACCESSIBILITY_ACCESSIBLE_SELECTION_BASE_HXX

#ifndef COMPHELPER_ACCESSIBLE_SELECTION_HELPER_HXX
#include <comphelper/accessibleselectionhelper.hxx>
#endif

namespace accessibility
{
/** @descr
        This base class provides a base implementation of the
        <type>XAccessibleSelection</type> interface.
        The following methods have to be implemented if this
        class is used:

        <method>implGetMutex</method>,
        <method>implGetAccessibleContext</method>,
        <method>implIsSelected</method>,
        <method>implSelect</method>,
*/
    class AccessibleSelectionBase : public ::comphelper::OCommonAccessibleSelection,
                                    public ::com::sun::star::accessibility::XAccessibleSelection
    {
    protected:

        virtual ::osl::Mutex&   implGetMutex() = 0;

    public:

        // XAccessibleSelection - default implementations
        virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL clearAccessibleSelection(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL selectAllAccessibleChildren(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount(  ) throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException);

    public:

                                AccessibleSelectionBase();
        virtual                 ~AccessibleSelectionBase();
    };

}

#endif // _SVX_ACCESSIBILITY_ACCESSIBLE_SELECTION_BASE_HXX
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: txatbase.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 21:47:32 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#ifndef _SFXITEMPOOL_HXX
#include <svtools/itempool.hxx>
#endif
#ifndef _TXATBASE_HXX
#include <txatbase.hxx>
#endif

SwTxtAttr::SwTxtAttr( const SfxPoolItem& rAttr, xub_StrLen nStt )
    : pAttr( &rAttr ), nStart( nStt )
{
    bDontExpand = bLockExpandFlag = bDontMergeAttr = bDontMoveAttr =
        bCharFmtAttr = bOverlapAllowedAttr = bPriorityAttr =
        bDontExpandStart = FALSE;
}

SwTxtAttr::~SwTxtAttr( )
{
}

xub_StrLen* SwTxtAttr::GetEnd()
{
    return 0;
}

    // RemoveFromPool muss immer vorm DTOR Aufruf erfolgen!!
    // Meldet sein Attribut beim Pool ab
void SwTxtAttr::RemoveFromPool( SfxItemPool& rPool )
{
    rPool.Remove( GetAttr() );
    pAttr = 0;
}

int SwTxtAttr::operator==( const SwTxtAttr& rAttr ) const
{
    return GetAttr() == rAttr.GetAttr();
}

SwTxtAttrEnd::SwTxtAttrEnd( const SfxPoolItem& rAttr, xub_StrLen nS,
                            xub_StrLen nE )
    : SwTxtAttr( rAttr, nS ), nEnd( nE )
{
}

xub_StrLen* SwTxtAttrEnd::GetEnd()
{
    return &nEnd;
}
<commit_msg>INTEGRATION: CWS notes2 (1.9.320); FILE MERGED 2007/10/12 22:30:10 mod 1.9.320.1: fix for overlays, layout algorithm fix, patch for ww8 import<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: txatbase.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2008-02-19 13:48:46 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#ifndef _SFXITEMPOOL_HXX
#include <svtools/itempool.hxx>
#endif
#ifndef _TXATBASE_HXX
#include <txatbase.hxx>
#endif

#ifndef _FMTFLD_HXX //autogen
#include <fmtfld.hxx>
#endif
#ifndef _DOCUFLD_HXX //autogen
#include <docufld.hxx>
#endif

#include "doc.hxx"
#include "docsh.hxx"
#include "../../../inc/PostItMgr.hxx"
#include "../../ui/inc/view.hxx"

SwTxtAttr::SwTxtAttr( const SfxPoolItem& rAttr, xub_StrLen nStt )
    : pAttr( &rAttr ), nStart( nStt )
{
    bDontExpand = bLockExpandFlag = bDontMergeAttr = bDontMoveAttr =
        bCharFmtAttr = bOverlapAllowedAttr = bPriorityAttr =
        bDontExpandStart = FALSE;
}

SwTxtAttr::~SwTxtAttr( )
{
}

xub_StrLen* SwTxtAttr::GetEnd()
{
    return 0;
}

    // RemoveFromPool muss immer vorm DTOR Aufruf erfolgen!!
    // Meldet sein Attribut beim Pool ab
void SwTxtAttr::RemoveFromPool( SfxItemPool& rPool )
{
    /*
    // delete in SwPostItMgr
    if (Which()==RES_TXTATR_FIELD)
    {
        if ( ((SwFmtFld&)(GetAttr())).GetFld()->GetTyp()->Which()==RES_POSTITFLD)
        {
            SwDocShell* aShell = static_cast<SwPostItFieldType*>(((SwFmtFld&)GetAttr()).GetFld()->GetTyp())->GetDoc()->GetDocShell();
            if (aShell)
            {
                aShell->GetView()->GetPostItMgr()->Delete(&(SwFmtFld&)GetAttr());
            }

        }
    }
    */
    rPool.Remove( GetAttr() );
    pAttr = 0;
}

int SwTxtAttr::operator==( const SwTxtAttr& rAttr ) const
{
    return GetAttr() == rAttr.GetAttr();
}

SwTxtAttrEnd::SwTxtAttrEnd( const SfxPoolItem& rAttr, xub_StrLen nS,
                            xub_StrLen nE )
    : SwTxtAttr( rAttr, nS ), nEnd( nE )
{
}

xub_StrLen* SwTxtAttrEnd::GetEnd()
{
    return &nEnd;
}
<|endoftext|>


<commit_before>#include <stdlib.h>

#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif

class DLLEXPORT Foo {
public:
    Foo();
    ~Foo();
    virtual int TakeAVoid(void);
    virtual int TakeABool(bool i);
    virtual int TakeAChar(char i);
    virtual int TakeAShort(short i);
    virtual int TakeAnInt(int i);
    virtual int TakeALong(long i);
    virtual int TakeALongLong(long long i);
    virtual int TakeAFloat(float i);
    virtual int TakeADouble(double i);
    virtual int TakeAString(char *i);
    virtual int TakeAnArray(int i[]);
    virtual int TakeAPointer(void *i);
    virtual int TakeABoolPointer(bool *i);
    virtual int TakeACharPointer(char *i);
    virtual int TakeAShortPointer(short *i);
    virtual int TakeAnIntPointer(int *i);
    virtual int TakeALongPointer(long *i);
    virtual int TakeALongLongPointer(long long *i);
    virtual int TakeAFloatPointer(float *i);
    virtual int TakeADoublePointer(double *i);
    virtual int TakeAUInt(uint i);
    virtual int TakeAUShort(ushort i);
    virtual int TakeAUChar(unsigned char i);
    virtual int TakeAInt64(long long i);
    virtual int TakeAULongLong(unsigned long long i);
    virtual int TakeAUInt64(unsigned long long i);
};

Foo::Foo()  { };
Foo::~Foo() { };

int Foo::TakeAVoid(void)                    { return  0; }
int Foo::TakeABool(bool i)                  { return  1; }
int Foo::TakeAChar(char i)                  { return  2; }
int Foo::TakeAShort(short i)                { return  3; }
int Foo::TakeAnInt(int i)                   { return  4; }
int Foo::TakeALong(long i)                  { return  5; }
int Foo::TakeALongLong(long long i)         { return  6; }
int Foo::TakeAFloat(float i)                { return  7; }
int Foo::TakeADouble(double i)              { return  8; }
int Foo::TakeAString(char *i)               { return  9; }
int Foo::TakeAnArray(int i[])               { return 10; }
int Foo::TakeAPointer(void *i)              { return 11; }
int Foo::TakeABoolPointer(bool *i)          { return 12; }
int Foo::TakeACharPointer(char *i)          { return 13; }
int Foo::TakeAShortPointer(short *i)        { return 14; }
int Foo::TakeAnIntPointer(int *i)           { return 15; }
int Foo::TakeALongPointer(long *i)          { return 16; }
int Foo::TakeALongLongPointer(long long *i) { return 17; }
int Foo::TakeAFloatPointer(float *i)        { return 18; }
int Foo::TakeADoublePointer(double *i)      { return 19; }
int Foo::TakeAUInt(uint i)                  { return 20; }
int Foo::TakeAUShort(ushort i)              { return 21; }
int Foo::TakeAUChar(unsigned char i)        { return 22; }
int Foo::TakeAInt64(long long i)            { return 23; }
int Foo::TakeAULongLong(unsigned long long i) { return 24; }
int Foo::TakeAUInt64(unsigned long long i)    { return 25; }
<commit_msg>Fixes for Windows suggested by FROGGS++<commit_after>#include <stdlib.h>

#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif

class DLLEXPORT Foo {
public:
    Foo();
    ~Foo();
    virtual int TakeAVoid(void);
    virtual int TakeABool(bool i);
    virtual int TakeAChar(char i);
    virtual int TakeAShort(short i);
    virtual int TakeAnInt(int i);
    virtual int TakeALong(long i);
    virtual int TakeALongLong(long long i);
    virtual int TakeAFloat(float i);
    virtual int TakeADouble(double i);
    virtual int TakeAString(char *i);
    virtual int TakeAnArray(int i[]);
    virtual int TakeAPointer(void *i);
    virtual int TakeABoolPointer(bool *i);
    virtual int TakeACharPointer(char *i);
    virtual int TakeAShortPointer(short *i);
    virtual int TakeAnIntPointer(int *i);
    virtual int TakeALongPointer(long *i);
    virtual int TakeALongLongPointer(long long *i);
    virtual int TakeAFloatPointer(float *i);
    virtual int TakeADoublePointer(double *i);
    virtual int TakeAUInt(unsigned int i);
    virtual int TakeAUShort(unsigned short i);
    virtual int TakeAUChar(unsigned char i);
    virtual int TakeAInt64(long long i);
    virtual int TakeAULongLong(unsigned long long i);
    virtual int TakeAUInt64(unsigned long long i);
};

Foo::Foo()  { };
Foo::~Foo() { };

int Foo::TakeAVoid(void)                    { return  0; }
int Foo::TakeABool(bool i)                  { return  1; }
int Foo::TakeAChar(char i)                  { return  2; }
int Foo::TakeAShort(short i)                { return  3; }
int Foo::TakeAnInt(int i)                   { return  4; }
int Foo::TakeALong(long i)                  { return  5; }
int Foo::TakeALongLong(long long i)         { return  6; }
int Foo::TakeAFloat(float i)                { return  7; }
int Foo::TakeADouble(double i)              { return  8; }
int Foo::TakeAString(char *i)               { return  9; }
int Foo::TakeAnArray(int i[])               { return 10; }
int Foo::TakeAPointer(void *i)              { return 11; }
int Foo::TakeABoolPointer(bool *i)          { return 12; }
int Foo::TakeACharPointer(char *i)          { return 13; }
int Foo::TakeAShortPointer(short *i)        { return 14; }
int Foo::TakeAnIntPointer(int *i)           { return 15; }
int Foo::TakeALongPointer(long *i)          { return 16; }
int Foo::TakeALongLongPointer(long long *i) { return 17; }
int Foo::TakeAFloatPointer(float *i)        { return 18; }
int Foo::TakeADoublePointer(double *i)      { return 19; }
int Foo::TakeAUInt(unsigned int i)          { return 20; }
int Foo::TakeAUShort(unsigned short i)      { return 21; }
int Foo::TakeAUChar(unsigned char i)        { return 22; }
int Foo::TakeAInt64(long long i)            { return 23; }
int Foo::TakeAULongLong(unsigned long long i) { return 24; }
int Foo::TakeAUInt64(unsigned long long i)    { return 25; }
<|endoftext|>