398 test(ListingSupported(EThreads, EScopeThreadSpecific)); |
398 test(ListingSupported(EThreads, EScopeThreadSpecific)); |
399 |
399 |
400 test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse)); |
400 test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse)); |
401 test(KErrNone == iServSession.SuspendThread(iThreadID)); |
401 test(KErrNone == iServSession.SuspendThread(iThreadID)); |
402 |
402 |
403 //test getting the global list, ETrue as should find the target debug thread |
403 TBool found = EFalse; |
404 DoTestGetThreadList(ETrue, EScopeGlobal); |
404 |
405 |
405 /* We need these loops because on some system the kernel run mode debugger does not |
406 //test getting this thread's thread list, ETrue as should find the target debug thread |
406 immediately present the thread in the thread list. |
407 DoTestGetThreadList(ETrue, EScopeThreadSpecific, RThread().Id().Id()); |
407 */ |
408 |
408 |
409 //test getting this process's thread list, ETrue as should find the target debug thread |
409 for(TInt retryCount = 0; retryCount < 10 && !found; retryCount++ ) |
410 DoTestGetThreadList(ETrue, EScopeProcessSpecific, RProcess().Id().Id()); |
410 { |
|
411 //test getting this process's thread list, ETrue as should find the target debug thread |
|
412 User::After(50000); |
|
413 found = DoTestGetThreadList(ETrue, EScopeProcessSpecific, RProcess().Id().Id()); |
|
414 } |
|
415 test( found ); |
|
416 found = EFalse; |
|
417 |
|
418 for(TInt retryCount = 0; retryCount < 10 && !found; retryCount++ ) |
|
419 { |
|
420 //test getting the global list, ETrue as should find the target debug thread |
|
421 User::After(50000); |
|
422 found = DoTestGetThreadList(ETrue, EScopeGlobal); |
|
423 } |
|
424 test( found ); |
|
425 |
|
426 found = EFalse; |
|
427 for(TInt retryCount = 0; retryCount < 10 && !found; retryCount++ ) |
|
428 { |
|
429 //test getting this thread's thread list, ETrue as should find the target debug thread |
|
430 User::After(50000); |
|
431 found = DoTestGetThreadList(ETrue, EScopeThreadSpecific, RThread().Id().Id()); |
|
432 } |
|
433 test( found ); |
411 |
434 |
412 test(KErrNone == iServSession.ResumeThread(iThreadID)); |
435 test(KErrNone == iServSession.ResumeThread(iThreadID)); |
413 test(KErrNone == iServSession.DetachExecutable(iFileName)); |
436 test(KErrNone == iServSession.DetachExecutable(iFileName)); |
414 } |
437 } |
415 |
438 |
416 void CRunModeAgent::DoTestGetThreadList(const TBool aShouldPass, const TListScope aListScope, const TUint64 aTargetId) |
439 TBool CRunModeAgent::DoTestGetThreadList(const TBool aShouldPass, const TListScope aListScope, const TUint64 aTargetId) |
417 { |
440 { |
418 test.Next(_L("DoTestGetThreadList\n")); |
|
419 |
|
420 //create data to pass |
441 //create data to pass |
421 RBuf8 buffer; |
442 RBuf8 buffer; |
422 TUint32 size = 0; |
443 TUint32 size = 0; |
423 |
444 |
424 //perform the call to get the Code segs |
445 //perform the call to get the thread list |
425 DoGetList(EThreads, aListScope, buffer, size, aTargetId); |
446 DoGetList(EThreads, aListScope, buffer, size, aTargetId); |
426 |
447 |
427 //initialise data about the target debug thread to compare the kernel's data against |
448 //initialise data about the target debug thread to compare the kernel's data against |
428 TFileName name = iDebugThread.FullName(); |
449 TFileName name = iDebugThread.FullName(); |
429 RProcess thisProcess; |
450 RProcess thisProcess; |
436 const TUint8* ptrEnd = ptr + size; |
457 const TUint8* ptrEnd = ptr + size; |
437 while(ptr < ptrEnd) |
458 while(ptr < ptrEnd) |
438 { |
459 { |
439 TThreadListEntry* entry = (TThreadListEntry*)ptr; |
460 TThreadListEntry* entry = (TThreadListEntry*)ptr; |
440 TPtr entryName(&(entry->iName[0]), entry->iNameLength, entry->iNameLength); |
461 TPtr entryName(&(entry->iName[0]), entry->iNameLength, entry->iNameLength); |
|
462 |
441 if( (threadId == entry->iThreadId) && (processId == entry->iProcessId) && (0 == name.CompareF(entryName)) ) |
463 if( (threadId == entry->iThreadId) && (processId == entry->iProcessId) && (0 == name.CompareF(entryName)) ) |
442 { |
464 { |
443 test(entry->iSupervisorStackBaseValid); |
465 test(entry->iSupervisorStackBaseValid); |
444 test(entry->iSupervisorStackSizeValid); |
466 test(entry->iSupervisorStackSizeValid); |
445 //if all match then we've found it |
467 //if all match then we've found it |
446 found = ETrue; |
468 found = ETrue; |
|
469 break; |
447 } |
470 } |
448 |
471 |
449 ptr += Align4(entry->GetSize()); |
472 ptr += Align4(entry->GetSize()); |
450 } |
473 } |
451 |
|
452 //check whether the expected result happened |
|
453 test(found == aShouldPass); |
|
454 |
474 |
455 //clean up |
475 //clean up |
456 buffer.Close(); |
476 buffer.Close(); |
|
477 return found; |
457 |
478 |
458 } |
479 } |
459 |
480 |
460 //--------------------------------------------- |
481 //--------------------------------------------- |
461 //! @SYMTestCaseID KBase-T-RMDEBUG2-0431 |
482 //! @SYMTestCaseID KBase-T-RMDEBUG2-0431 |
580 //clean up |
601 //clean up |
581 buffer.Close(); |
602 buffer.Close(); |
582 |
603 |
583 } |
604 } |
584 |
605 |
|
606 |
|
607 /** |
|
608 * Get a list from the run mode debug system. Most list calls will initially return KErrTooBig, |
|
609 * since the initial size of the buffer is 0. However it is sometimes valid for a list to be empty |
|
610 * given its filtering and scope. These calls should return KErrNone. |
|
611 */ |
585 void CRunModeAgent::DoGetList(const TListId aListId, const TListScope aListScope, RBuf8& aBuffer, TUint32& aSize, const TUint64 aTargetId) |
612 void CRunModeAgent::DoGetList(const TListId aListId, const TListScope aListScope, RBuf8& aBuffer, TUint32& aSize, const TUint64 aTargetId) |
586 { |
613 { |
587 //close the buffer in case there's stuff allocated in it |
614 //close the buffer in case there's stuff allocated in it |
588 aBuffer.Close(); |
615 aBuffer.Close(); |
589 //initialise it to be one byte big, which will guarantee data won't fit in it |
616 //initialise it to be one byte big, which will guarantee data won't fit in it |
590 test(KErrNone == aBuffer.Create(1)); |
617 test(KErrNone == aBuffer.Create(1)); |
591 aSize = 0; |
618 aSize = 0; |
592 |
619 |
|
620 TInt ret = KErrNone; |
593 //should pass this test (assuming we've passed in sensible arguments above...) |
621 //should pass this test (assuming we've passed in sensible arguments above...) |
594 if(EScopeGlobal == aListScope) |
622 if(EScopeGlobal == aListScope) |
595 { |
623 { |
596 test(KErrTooBig == iServSession.GetList(aListId, aBuffer, aSize)); |
624 ret = iServSession.GetList(aListId, aBuffer, aSize); |
597 } |
625 } |
598 else if(EScopeThreadSpecific == aListScope) |
626 else if(EScopeThreadSpecific == aListScope) |
599 { |
627 { |
600 test(KErrTooBig == iServSession.GetList((TThreadId)aTargetId, aListId, aBuffer, aSize)); |
628 ret = iServSession.GetList((TThreadId)aTargetId, aListId, aBuffer, aSize); |
601 } |
629 } |
602 else if(EScopeProcessSpecific == aListScope) |
630 else if(EScopeProcessSpecific == aListScope) |
603 { |
631 { |
604 test(KErrTooBig == iServSession.GetList((TProcessId)aTargetId, aListId, aBuffer, aSize)); |
632 ret = iServSession.GetList((TProcessId)aTargetId, aListId, aBuffer, aSize); |
605 } |
633 } |
606 else |
634 else |
607 { |
635 { |
608 // unknown list scope |
636 // unknown list scope |
609 test(0); |
637 test(0); |
610 } |
638 } |
|
639 |
|
640 if( KErrNone == ret ) |
|
641 { |
|
642 /* In the case that there is no data, just return and let the caller check |
|
643 the buffer. It is valid for a caller to not expect any data to be returned. |
|
644 */ |
|
645 return; |
|
646 } |
|
647 |
|
648 // The only other allowed return is KErrTooBig |
|
649 test( ret == KErrTooBig ); |
611 |
650 |
612 //keep allocating larger buffers, beginning with the aSize returned by the above call, |
651 //keep allocating larger buffers, beginning with the aSize returned by the above call, |
613 //and hopefully we'll eventually make a large enough one |
652 //and hopefully we'll eventually make a large enough one |
614 test(KErrNone == aBuffer.ReAlloc(aSize)); |
653 test(KErrNone == aBuffer.ReAlloc(aSize)); |
615 |
654 |
2725 while((waitCount-- > 0) && ProcessExists(processId)) |
2764 while((waitCount-- > 0) && ProcessExists(processId)) |
2726 { |
2765 { |
2727 /* Wait a little while and try again, just in case the process is still being removed. |
2766 /* Wait a little while and try again, just in case the process is still being removed. |
2728 This can happen on a very busy system or when a popup for the events is still active |
2767 This can happen on a very busy system or when a popup for the events is still active |
2729 */ |
2768 */ |
2730 RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads. ProcessExists(id=%d), waiting for it to exit %d", |
2769 RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads. ProcessExists(id=%d), waiting count exit=%d", |
2731 I64LOW(processId), waitCount); |
2770 I64LOW(processId), waitCount); |
2732 User::After(500); |
2771 User::After(50000); |
2733 } |
2772 } |
2734 test(!ProcessExists(processId)); |
2773 test(!ProcessExists(processId)); |
2735 } |
2774 } |
2736 } |
2775 } |
2737 |
2776 |
2738 // helper function to check whether a thread with id aThreadId exists in the process with id aProcessId |
2777 // helper function to check whether a thread with id aThreadId exists in the process with id aProcessId |
2739 TBool CRunModeAgent::ThreadExistsForProcess(const TThreadId aThreadId, const TProcessId aProcessId) |
2778 TBool CRunModeAgent::ThreadExistsForProcess(const TThreadId aThreadId, const TProcessId aProcessId) |
2740 { |
2779 { |
2741 TUint32 size; |
2780 RThread lThread; |
2742 RBuf8 buffer; |
2781 TInt ret = lThread.Open( aThreadId.Id() ); |
2743 test(KErrNone == buffer.Create(1024)); |
2782 |
2744 TInt err = iServSession.GetList(aProcessId, EThreads, buffer, size); |
2783 if( ret != KErrNone ) |
2745 while(KErrTooBig == err) |
2784 { |
2746 { |
2785 RDebug::Printf("ThreadExistsForProcess: thread id=%d opening returned %d", |
2747 size*=2; |
2786 I64LOW( aThreadId.Id() ), ret ); |
2748 test(size<=16*1024); |
2787 lThread.Close(); |
2749 test(KErrNone == buffer.ReAlloc(size)); |
2788 return EFalse; |
2750 err = iServSession.GetList(aProcessId, EThreads, buffer, size); |
2789 } |
2751 } |
2790 |
2752 test(KErrNone == err); |
2791 RProcess lProcess; |
2753 |
2792 ret = lThread.Process( lProcess ); |
2754 //look through the buffer and check if the target debug thread is there |
2793 |
2755 TUint8* ptr = (TUint8*)buffer.Ptr(); |
2794 lThread.Close(); |
2756 const TUint8* ptrEnd = ptr + size; |
2795 |
2757 while(ptr < ptrEnd) |
2796 if( ret != KErrNone ) |
2758 { |
2797 { |
2759 TThreadListEntry& entry = *(TThreadListEntry*)ptr; |
2798 RDebug::Printf("ThreadExistsForProcess: proc opening returned %d", ret ); |
2760 if(aThreadId.Id() == entry.iThreadId) |
2799 ret = KErrNotFound; |
2761 { |
2800 } |
2762 buffer.Close(); |
2801 else if( lProcess.Id() != aProcessId ) |
2763 return ETrue; |
2802 { |
2764 } |
2803 RDebug::Printf("ThreadExistsForProcess: lProcess.Id()(%d)!= aProcessId(%d)", |
2765 ptr += Align4(entry.GetSize()); |
2804 I64LOW(lProcess.Id().Id()), I64LOW(aProcessId.Id())); |
2766 } |
2805 ret = KErrNotFound; |
2767 buffer.Close(); |
2806 } |
2768 return EFalse; |
2807 |
|
2808 lProcess.Close(); |
|
2809 |
|
2810 return ( ret == KErrNone ); |
2769 } |
2811 } |
2770 |
2812 |
2771 // helper function to check whether a process with id aProcessId exists |
2813 // helper function to check whether a process with id aProcessId exists |
2772 TBool CRunModeAgent::ProcessExists(const TProcessId aProcessId) |
2814 TBool CRunModeAgent::ProcessExists(const TProcessId aProcessId) |
2773 { |
2815 { |