예제 #1
0
VError VMacResFile::GetResourceListIDs(const VString& inType, VArrayLong& outIDs) const
{
OSErr macError = noErr;

	outIDs.SetCount(0);

	if (!testAssert(fRefNum != -1))
		return VE_STREAM_NOT_OPENED;
	
	ResType type = inType.GetOsType();
	if (type == 0)
		return VE_INVALID_PARAMETER;
	
	sWORD	oldref = ::CurResFile();
	sWORD	ref = fRefNum;
	while(ref != -1 && ref != 0)
	{
		::UseResFile(ref);
		sWORD	count = ::Count1Resources(type);
		::UseResFile(oldref);
		
		for(sWORD i = 1 ; i <= count ; ++i)
		{
			::UseResFile(ref);
			::SetResLoad(false);
			Handle data = ::Get1IndResource(type, i);
			macError = ::ResError();
			::SetResLoad(true);
			::UseResFile(oldref); // one must restore proper context before calling VArrayValue::AppendWord

			if (data != NULL)
			{
				ResType type2;
				sWORD	id;
				Str255 spName;
				::GetResInfo(data, &id, &type2, spName);
				macError = ::ResError();
				if (macError == noErr)
				{
					if (!fUseResourceChain || outIDs.Find(id) == -1)
						outIDs.AppendLong(id);
				}
			}
		}
		
		if (!fUseResourceChain)
			break;
		else
		{
			macError = ::GetNextResourceFile(ref, &ref); // returns ref = 0 and noerror at the end
			if (!testAssert(macError == noErr))
				break;
		}
	}
	return VE_OK;
}
void
StackAlloc_Test::core_system_isPtrInStack()
{
  int bla = 0;
  testAssert(core_system::isPtrInStack((void*)&bla) == true);

  char* tb = new char[1];
  testAssert(core_system::isPtrInStack((void*)tb) == false);
  delete tb;
}
예제 #3
0
VResourceIterator* VMacResFile::NewIterator(const VString& inType) const
{
	if (!testAssert(fRefNum != -1))
		return NULL;

	ResType type = inType.GetOsType();
	if (!testAssert(type != 0))
		return NULL;

	return new VMacResourceIterator(fRefNum, type, fUseResourceChain);
}
void
String2_Test::isType()
{
  testAssert(String::isAlpha(Nil) == false);
  testAssert(String::isAlpha("") == true);
  testAssert(String::isAlpha("abc") == true);
  testAssert(String::isAlpha("1") == false);
  testAssert(String::isAlpha("\n") == false);
  // continue other is tests

}
예제 #5
0
VFilePath VProcess::GetExecutableFilePath() const
{
	VFilePath filePath;

#if VERSIONMAC

	CFURLRef exeURL = ::CFBundleCopyExecutableURL( ::CFBundleGetMainBundle());
	
	if (testAssert( exeURL != NULL ))
	{
		CFStringRef cfPath = ::CFURLCopyFileSystemPath( exeURL, kCFURLHFSPathStyle);
		if (testAssert( cfPath != NULL ))
		{
			VString thepath;
			thepath.MAC_FromCFString( cfPath);
			thepath.Compose();
			filePath.FromFullPath( thepath, FPS_SYSTEM);
			::CFRelease( cfPath);
		}
		
		::CFRelease(exeURL );
	}

#elif VERSIONWIN

	// Get a path to the exe.
	UniChar path[4096];
	DWORD pathLength=0;

	path[sizeof(path)/sizeof(UniChar)-2]=0;
	pathLength = ::GetModuleFileNameW(NULL, path, sizeof(path));
	
	if (testAssert(pathLength != 0 && !path[sizeof(path)/sizeof(UniChar)-2]))
	{
		VString thepath( path);
		filePath.FromFullPath( thepath, FPS_SYSTEM);
	}

#elif VERSION_LINUX

	PathBuffer path;

	VError verr=path.InitWithExe();
	xbox_assert(verr==VE_OK);

	path.ToPath(&filePath);
	xbox_assert(verr==VE_OK);
		
#endif
	
	return filePath;
}
예제 #6
0
Boolean VMacResFile::GetString(VString& outString, sLONG inID, sLONG inIndex) const
{
	outString.Clear();

	if (!testAssert(fRefNum != -1))
		return false;
	
	if (!testAssert(inID >= -32768 && inID <= 32767 && inIndex > 0))
		return false;

	Boolean isOK = false;

	sWORD	curres = ::CurResFile();
	if (curres != fRefNum)
		::UseResFile(fRefNum);
		
	if (fReadOnly && (fLastStringListID == inID) && (fLastStringList != NULL))
	{
		if (*fLastStringList == NULL)
			::LoadResource(fLastStringList);
	}
	else
	{
		fLastStringListID = (short) inID;
		fLastStringList = fUseResourceChain ? ::GetResource('STR#', fLastStringListID) : ::Get1Resource('STR#', fLastStringListID);
	}
	
	if (curres != fRefNum)
		::UseResFile(curres);

	if (testAssert(fLastStringList != NULL))
	{
		if (testAssert(*fLastStringList != NULL))
		{
			::HLock(fLastStringList);
	
			sLONG count = **(sWORD**) fLastStringList;
			if (count >= inIndex)
			{
				StringPtr strs = (StringPtr) *fLastStringList + sizeof(sWORD);
				while(--inIndex)
					strs += strs[0] + 1;
				outString.MAC_FromMacPString(strs);
				isOK = true;
			}
	
			::HUnlock(fLastStringList);
		}
	}
	return isOK;
}
VError VZipComponent::CompressStream(VStream* inStreamToCompress, EZipCompressionLevel inCompressionLevel, VStream* outCompressedStream )
{
	if(!testAssert(inStreamToCompress != NULL))
		return VE_INVALID_PARAMETER;
	if(!testAssert(outCompressedStream != NULL))
		return VE_INVALID_PARAMETER;	
	if(!testAssert( ( (inStreamToCompress -> GetSize()) - (inStreamToCompress -> GetPos()) ) > 0))
		return VE_STREAM_EOF;
	
	VError errorToReturn = VE_OK;
	
	if (!inStreamToCompress->IsReading()){
		errorToReturn = vThrowError(VE_STREAM_NOT_OPENED);
	}
	
	if(errorToReturn == VE_OK){
		if(!outCompressedStream->IsWriting())
			errorToReturn = vThrowError(VE_STREAM_NOT_OPENED);
	}	
	
	if(errorToReturn == VE_OK){
		
		// The stream to compress is put in a buffer before calling CompressMemoryBlock
		sLONG8 streamToCompressSize = (inStreamToCompress -> GetSize()) - (inStreamToCompress -> GetPos());
		
		Bytef * bufferToCompress = (Bytef *) malloc(streamToCompressSize * sizeof(Bytef));
		if(bufferToCompress == NULL){
			errorToReturn = VE_MEMORY_FULL;
		}
		
		if (errorToReturn == VE_OK){
			
			errorToReturn = inStreamToCompress -> GetData(bufferToCompress, streamToCompressSize);
			if (errorToReturn != VE_OK){
				errorToReturn = vThrowError(VE_STREAM_CANNOT_READ);
			}
			
			
			if (errorToReturn == VE_OK){
				errorToReturn = CompressMemoryBlock(bufferToCompress, streamToCompressSize, inCompressionLevel, outCompressedStream);
			}
			
			free (bufferToCompress); // YT 23-Nov-2009 - Fix memory leaks
		}
	}
	
	return errorToReturn;

}
예제 #8
0
    virtual void run() override
    {
        auto clock = std::make_shared<SteppableClock>(3E-3f);
        ClockFactory::get(clock);

        std::unique_ptr<MultiRotorParams> params = MultiRotorParamsFactory::createConfig("SimpleFlight");
        MultiRotor vehicle;
        std::unique_ptr<Environment> environment;
        vehicle.initialize(params.get(), Pose(), 
            GeoPoint(), environment);

        std::vector<UpdatableObject*> vehicles = { &vehicle };
        std::unique_ptr<PhysicsEngineBase> physics_engine(new FastPhysicsEngine());
        PhysicsWorld physics_world(physics_engine.get(), vehicles, 
            static_cast<uint64_t>(clock->getStepSize() * 1E9));

        DroneControllerBase* controller = params->getController();
        testAssert(controller != nullptr, "Controller was null");
        std::string message;
        testAssert(controller->isAvailable(message), message);

        clock->sleep_for(0.04f);
        
        Utils::getSetMinLogLevel(true, 100);

        DirectCancelableBase cancellable(controller, &vehicle);
        controller->enableApiControl(true);
        controller->armDisarm(true, cancellable);
        controller->takeoff(10, cancellable);

        clock->sleep_for(2.0f);

        Utils::getSetMinLogLevel(true);

        controller->moveToPosition(-5, -5, -5, 5, DrivetrainType::MaxDegreeOfFreedom, YawMode(true, 0), -1, 0, cancellable);

        clock->sleep_for(2.0f);


        while (true) {
            clock->sleep_for(0.1f);
            controller->getStatusMessages(messages_);
            for (const auto& status_message : messages_) {
                std::cout << status_message << std::endl;
            }
            messages_.clear();
        }
    }
Boolean VHTTPConnectionListener::DoRun()
{
	XBOX::VError error = VE_OK;

	if (NULL != fRequestLogger)
		fRequestLogger->Log ('SRNT', 0, "SERVER_NET::VHTTPConnectionListener::DoRun()::Enter", 1);

	while (IsListening())
	{
        //jmo - Do not let errors accumulate in thread's error stack
        XBOX::VErrorContext errCtx(false, false);
        
		XTCPSock *	newConnection = fServerListener->GetNewConnectedSocket (1000 /*MsTimeout*/);

		if (NULL != newConnection)
		{
			XBOX::VTCPEndPoint *endPoint = new XBOX::VTCPEndPoint (newConnection, fSelectIOPool);

			if (testAssert (NULL != endPoint))
			{
				XBOX::VConnectionHandler * connectionHandler = fConnectionHandlerFactory->CreateConnectionHandler (error);

				if (testAssert ((NULL != connectionHandler) && (XBOX::VE_OK == error)))
				{
					connectionHandler->_ResetRedistributionCount();
					error = connectionHandler->SetEndPoint (endPoint);
					assert (XBOX::VE_OK == error);
				}

				/* Transfer connectionHandler to the thread pool for execution. */
				if (testAssert (NULL != fWorkerPool) && IsListening())
				{
					error = fWorkerPool->AddConnectionHandler (connectionHandler);
					assert (XBOX::VE_OK == error);
				}
			}
		}
	}

	DeInit();

	XBOX::VTask::GetCurrent()->Sleep (1000);

	if (NULL != fRequestLogger)
		fRequestLogger->Log ('SRNT', 0, "SERVER_NET::VHTTPConnectionListener::DoRun()::Exit", 1);

	return false;
}
void XPosixProcessLauncher::_BuildArrayArguments(char **&outArrayArg)
{	
	sLONG nbArguments = (sLONG) fArrayArg.size();
	
	// Dispose the previous array of arguments if not NULL
	_Free2DCharArray(outArrayArg);
	
	if(nbArguments < 1)
		return;
	
	size_t outArrayArgLength = (nbArguments + 1 ) * sizeof(char*);
	outArrayArg = (char **) gMemory->NewPtr(outArrayArgLength, 0);
	
	if(testAssert(outArrayArg != NULL))
	{
		for(sLONG i = 0; i < nbArguments; ++i)
		{
			VString		*currentArgPtr = &fArrayArg[i];
			size_t		argFullLength = currentArgPtr->GetLength() * 2;// + 1;
			char		*newArgPtr = new char[argFullLength];
			
			if(newArgPtr != NULL)
				currentArgPtr->ToCString(newArgPtr, argFullLength);
			
			outArrayArg[i] = newArgPtr;
		}
		outArrayArg[nbArguments] = NULL;
	}
}
예제 #11
0
bool VJSPropertyIterator::GetPropertyNameAsLong( sLONG *outValue) const
{
	if (testAssert( fIndex < fCount))
		return JS4D::StringToLong( JSPropertyNameArrayGetNameAtIndex( fNameArray, fIndex), outValue);
	else
		return false;
}
예제 #12
0
VHandle VMacResourceIterator::_GetResource(sLONG inIndex) const
{
	sWORD	refnum = fRefNums.GetWord(inIndex);
	sWORD	id = fIDs.GetWord(inIndex);
	
	sWORD	curres = ::CurResFile();
	if (curres != refnum)
		::UseResFile(refnum);

	::SetResLoad(false);
	Handle data = ::Get1Resource(fType, id);
	OSErr macError = ::ResError();
	::SetResLoad(true);

	if (curres != refnum)
		::UseResFile(curres);

	VHandle theData = NULL;
	if (data != NULL)
	{
		::LoadResource(data);
		macError = ::ResError();
		if (testAssert(macError == noErr))
		{
			assert(*data != NULL);
			::HLock(data);
			theData = VMemory::NewHandleFromData(*data, ::GetHandleSize(data));
			::HUnlock(data);
			data = NULL;
		}
	}
	return theData;
}
sLONG XPosixProcessLauncher::WriteToChild(const void *inBuffer, uLONG inBufferSizeInBytes, bool inClosePipeAfterWritting)
{
	if(testAssert(inBuffer != NULL))
	{
		if (fIsRunning && fPipeParentToChild[pWriteSide] != kInvalidDescriptor)
		{
			sLONG nb_written = 0;
			
			if(inBufferSizeInBytes > 0)
			{
				// yield first
				VTask::Yield();//gEngine->GiveHand(-1);
				
	//			_blocksigchild(1);
				nb_written = (sLONG) write(fPipeParentToChild[pWriteSide], inBuffer, inBufferSizeInBytes);
	//			_blocksigchild(0);
			}
			
			if(inClosePipeAfterWritting)
				CloseStandardInput();
			
			return nb_written;
		}
	}
	
	return -1;
}
예제 #14
0
VError VArchiveStream::_AddFile(VFile& inFile,const VFilePath& inSourceFolder,const VString& inExtraInfo)
{
	XBOX::VError result = VE_FILE_NOT_FOUND;
	if ( inFile.Exists() )
	{
		///ACI0078887, O.R. Nov 29th 2012: mask error if file is already known, does no harm 
		result = VE_OK;
		if (!ContainsFile( &inFile))
		{
			VString relativePath;
			if(testAssert(!inSourceFolder.IsEmpty() && inFile.GetPath().GetRelativePath(inSourceFolder,relativePath)))
			{
				fUniqueFilesCollection->insert(inFile.GetPath());
				fFileExtra.push_back( inExtraInfo );
				fFileList.push_back( &inFile );
				fSourceFolderForFiles.push_back(inSourceFolder);	
			}
			else
			{
				///ACI0078887, O.R. Nov 29th 2012: explicitely fail if item is not relative to source folder, this should never happen
				result = VE_INVALID_PARAMETER;
			}
		}
	}
	return result;
}
예제 #15
0
// [static]
VError XMacSystem::GetProcessorBrandName( XBOX::VString& outProcessorName)
{
	VError error = VE_OK;
	
	static VString sProcessorName;
	
	if (sProcessorName.IsEmpty())
	{
		// machdep.cpu.brand_string n'est dispo que sur intel
		char buffer[512];
		size_t size = sizeof( buffer);
		int	r = ::sysctlbyname( "machdep.cpu.brand_string", buffer, &size, NULL, 0);
		if (testAssert( r == 0))
		{
			sProcessorName.FromBlock( buffer, size, VTC_UTF_8);
		}
		else
		{
			error = VE_UNKNOWN_ERROR;
		}
	}
	
	outProcessorName = sProcessorName;
	
	return error;
}
예제 #16
0
/**
 * -----------------------------------------------------------------------------
 * @brief       mutex2_execute	 
 * @param[in]   None	
 * @param[out]  None
 * @retval      None	 
 * @par Description
 * @details     The code of mutex test example 3. 
 * -----------------------------------------------------------------------------
 */
static void mutex2_execute (void)
{
	unsigned char i;
	Cnt = 0;
	Exit_Flag = 0;
	
	CoTickDelay (1);
	
	for (i=0;i<MAX_SLAVE_TEST_TASKS;i++ ){
	 Flag [i] = 0;
	}
	
	for (i=0; i< MAX_SLAVE_TEST_TASKS; i++) {
	  Task_Id [i] = CoCreateTask (mutexTask02,(void*)i,MAINTEST_PRIMARY_PRIORITY-(i+1),&Task_Stack[i][SLAVE_TASK_STK_SIZE-1],SLAVE_TASK_STK_SIZE);
	  if (Task_Id[i] == E_CREATE_FAIL) {
	      printf ("\r Create the %d mutex task fail. \n",i+1);
	  }
	}
	
	while (Exit_Flag == 0) ;
	Exit_Flag = 0;
	
	for (i=0; i<MAX_SLAVE_TEST_TASKS; i++) {
	 testAssert((Flag[i] == Sequence2[i])," Mutex #2 ");
	}
}
예제 #17
0
bool VJSONSingleObjectWriter::AddMember( const VString& inName, const VValueSingle &inValue, JSONOption inModifier)
{
	bool ok = false;
	VString valueString;

	if(testAssert(inValue.GetJSONString( valueString, inModifier) == VE_OK) && !inName.IsEmpty())
	{
		if (fIsClosed)
		{
			fObject.Remove( fObject.GetLength(), 1);
			fIsClosed = false;
		}

		if (fMembersCount > 0)
			fObject.AppendUniChar( ',');
		
		fObject.AppendUniChar( '"');
		fObject.AppendString( inName);
		fObject.AppendUniChar( '"');
		fObject.AppendUniChar( ':');
		fObject.AppendString( valueString);
		++fMembersCount;
		ok = true;
	}
	return ok;
}
예제 #18
0
VFile *VProcess::RetainFile( EFolderKind inPrimarySelector, const VString& inFileName, EFolderKind inSecondarySelector) const
{
	VFile *file = NULL;

	VFolder *parent = RetainFolder( inPrimarySelector);
	if (testAssert( parent != NULL))
	{
		file = new VFile( *parent, inFileName);
		if ( (file != NULL) && !file->Exists())
			ReleaseRefCountable( &file);
	}
	ReleaseRefCountable( &parent);

	if ( (file == NULL) && (inSecondarySelector != 0) )
	{
		parent = RetainFolder( inSecondarySelector);
		if ( (parent != NULL) && parent->Exists())
		{
			file = new VFile( *parent, inFileName);
			if ( (file != NULL) && !file->Exists())
				ReleaseRefCountable( &file);
		}
		ReleaseRefCountable( &parent);
	}
	
	return file;
}
예제 #19
0
bool VBagArray::AddNth( VValueBag *inBag, VIndex inIndex)
{
	bool ok;
	if (testAssert(inBag != NULL))
	{
		if (inIndex <= 0)
			inIndex = 1;
		else if (inIndex > GetCount() + 1)
			inIndex = GetCount() + 1;
		
		try
		{
			fArray.insert( fArray.begin() + inIndex - 1, inBag);
			inBag->Retain();
			ok = true;
		}
		catch(...)
		{
			ok = false;
		}
	}
	else
	{
		ok = false;
	}
	return ok;
}
예제 #20
0
bool VValueBag::ReplaceElementByPath( const VValueBag::StKeyPath& inPath, VValueBag *inBag)
{
	if (!testAssert( !inPath.empty()))
		return false;
	
	bool ok;
	if (inPath.size() > 1)
	{
		VValueBag::StKeyPath father( inPath);
		father.pop_back();
		if (inBag == NULL)
		{
			// removing
			VValueBag *fatherBag = GetUniqueElementByPath( father);
			if (fatherBag != NULL)
				fatherBag->RemoveElements( inPath.back());
			ok = true;
		}
		else
		{
			VValueBag *fatherBag = GetElementByPathAndCreateIfDontExists( father);
			if (fatherBag != NULL)
				ok = fatherBag->ReplaceElement( inPath.back(), inBag);
			else
				ok = false;
		}
	}
	else
	{
		ok = ReplaceElement( inPath.back(), inBag);
	}
	
	return ok;
}
예제 #21
0
void VProcess::Run()
{
	VTask *mainTask = VTask::GetMain();
	if (!testAssert( (mainTask != NULL) && mainTask->IsCurrent() && (mainTask->GetState() == TS_RUNNING) ))
		return;

	if (!fInitCalled)
		fInitOK = Init();
	
	if (fInitOK)
	{
		vFlushErrors();
		
		StartMessaging();
		
		DoRun();

		DoQuit();
		mainTask->Kill();

		StopMessaging();
	}
	else
	{
		vThrowError(VE_CANNOT_INITIALIZE_APPLICATION, "VApplication::DoInit failed");
	}
}
예제 #22
0
CompareResult VUUID::CompareTo (const VValueSingle& inValue, Boolean /*inDiacritical*/) const
{
	if (!testAssert(inValue.GetValueKind() == VK_UUID))
		return CR_UNRELEVANT;
	
	return CompareToSameKind(&inValue);
}
예제 #23
0
void VJSPropertyIterator::GetPropertyName( VString& outName) const
{
	if (testAssert( fIndex < fCount))
		JS4D::StringToVString( JSPropertyNameArrayGetNameAtIndex( fNameArray, fIndex), outName);
	else
		outName.Clear();
}
void GetSubString (const XBOX::VString& inString, sLONG inFirst, sLONG inLast, XBOX::VString& outString)
{
	if (testAssert ((inFirst >= 0) && (inLast < inString.GetLength())))
		outString.FromBlock (inString.GetCPointer() + inFirst, (inLast - inFirst + 1) * sizeof(UniChar), XBOX::VTC_UTF_16);
	else
		outString.Clear();
}
bool VHTTPServerProject::AddVirtualHostFromSettings()
{
	XBOX::VError error = XBOX::VE_OK;

	if (fSettings->GetWebFolderPath().IsValid())
	{
		// sc 16/02/2012 create a virtual host if needed
		if (fVirtualHosts.empty())
		{
			// sc 16/02/2012 create a virtual host if needed
			VVirtualHost *virtualHost = new VVirtualHost (this);
			if (testAssert(virtualHost != NULL))
			{
				fVirtualHosts.push_back (virtualHost);
				error = fHTTPServer->AddVirtualHost (virtualHost);
			}
			else
			{
				error = XBOX::VE_MEMORY_FULL;
			}
		}

		if (error == XBOX::VE_OK)
		{
			for (std::vector<VVirtualHost *>::const_iterator it = fVirtualHosts.begin(); it != fVirtualHosts.end(); ++it)
			{
				_AddVirtualFoldersFromSettings (*it);
			}
		}
	}
	
	return (error == XBOX::VE_OK);
}
sLONG XWinProcessLauncher::ReadErrorFromChild(char *outBuffer, long inBufferSize)
{
	if(testAssert(fChildStdErrReadDup != INVALID_HANDLE_VALUE))
	{
		DWORD dwRead = 0;
		
		VTask::Yield();
		
	// Close the write end of the pipe before reading from the read end of the pipe.
		_CloseAndInvalidateHandle(&fChildStdErrWrite);
		
		
	// Read output from the child process, and write to parent's STDERR. 
		if (!ReadFile(fChildStdErrReadDup, outBuffer, inBufferSize, &dwRead, NULL)) {
			
			// ReadFile() has been set as non-blocking.

			if (GetLastError() != ERROR_NO_DATA)	

				dwRead = -1; 

		} else if (dwRead == 0) {
		
			dwRead = -1;	

		}
		
		return dwRead;
	}
	
	return -1;
}
예제 #27
0
void VJSONValue::SetProperty( const VString& inName, const VJSONValue& inValue)
{
    if (testAssert( fType == JSON_object))
    {
        fObject->SetProperty( inName, inValue);
    }
}
예제 #28
0
VError VMacResFile::_GetResource(const VString& inType, const VString& inName, Handle* outHandle) const
{
OSErr	macError = noErr;

	Str255	spName;
	*outHandle = NULL;

	if (!testAssert(fRefNum != -1))
		return VE_STREAM_NOT_OPENED;
	
	ResType type = inType.GetOsType();
	if (type == 0)
		return VE_INVALID_PARAMETER;
	
	inName.MAC_ToMacPString(spName, 255);
	
	sWORD	curres = ::CurResFile();
	if (curres != fRefNum)
		::UseResFile(fRefNum);

	*outHandle = fUseResourceChain ? ::GetNamedResource(type, spName) : ::Get1NamedResource(type, spName);
	macError = ::ResError();
	
	if (curres != fRefNum)
		::UseResFile(curres);

	VError error = VErrorBase::NativeErrorToVError((VNativeError)macError);
	
	return error;
}
예제 #29
0
void VMacResourceIterator::SetPos(sLONG inPos)
{
	if (fPos == -1)
		_Load();
	if (testAssert(inPos >= 1 && inPos <= fIDs.GetCount()))
		fPos = inPos;
}
void
String2_Test::distance()
{
  testAssert(String::indexOfDifference(Nil, "asdf") == -1);
  testAssert(String::indexOfDifference("asdf", Nil) == -1);
  testAssert(String::indexOfDifference("a b c", "a b_c") == 3);
  testAssert(String::getDistance("", "") == 0);
  testAssert(String::getDistance("", "a") == 1);
  testAssert(String::getDistance("a", "a") == 0);
  
  testAssert(String::getDistance("abcd", "a") == 3);
  testAssert(String::getDistance("Roger", "Rger") == 1);
  testAssert(String::getDistance("kommer", "koer") == 2);
  testAssert(String::getDistance("abc", "xyz") == 3);
  
}