From f3fbd1c0586ff6ec7895991e6c28f61a503c36a8 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 23 Jul 2016 20:50:09 +0000 Subject: Vendor import of lldb release_39 branch r276489: https://llvm.org/svn/llvm-project/lldb/branches/release_39@276489 --- packages/Python/lldbsuite/support/encoded_file.py | 48 + packages/Python/lldbsuite/support/funcutils.py | 16 + packages/Python/lldbsuite/support/gmodules.py | 30 + packages/Python/lldbsuite/support/optional_with.py | 56 + .../android/platform/TestDefaultCacheLineSize.py | 3 +- .../TestPublicAPIHeaders.py | 3 +- .../Python/lldbsuite/test/api/listeners/Makefile | 6 + .../lldbsuite/test/api/listeners/TestListener.py | 55 + .../Python/lldbsuite/test/api/listeners/main.c | 7 + .../multiple-debuggers/TestMultipleDebuggers.py | 14 +- .../test/api/multithreaded/TestMultithreaded.py | 6 +- .../test_listener_event_process_state.cpp | 46 +- .../lldbsuite/test/arm_emulation/TestEmulations.py | 2 + .../benchmarks/continue/TestBenchmarkContinue.py | 4 +- .../test/benchmarks/disassembly/TestDisassembly.py | 8 +- .../disassembly/TestDoAttachThenDisassembly.py | 3 +- .../disassembly/TestXcode41Vs42GDBDisassembly.py | 9 +- .../benchmarks/expression/TestExpressionCmd.py | 7 +- .../benchmarks/expression/TestRepeatedExprs.py | 7 +- .../frame_variable/TestFrameVariableResponse.py | 3 +- .../libcxxlist/TestBenchmarkLibcxxList.py | 4 +- .../benchmarks/libcxxmap/TestBenchmarkLibcxxMap.py | 4 +- .../test/benchmarks/startup/TestStartupDelays.py | 3 +- .../test/benchmarks/stepping/TestSteppingSpeed.py | 5 +- .../TestCompileRunToBreakpointTurnaround.py | 7 +- packages/Python/lldbsuite/test/configuration.py | 9 + packages/Python/lldbsuite/test/curses_results.py | 224 ---- packages/Python/lldbsuite/test/decorators.py | 524 ++++++++ packages/Python/lldbsuite/test/dosep.py | 61 +- packages/Python/lldbsuite/test/dotest.py | 174 +-- packages/Python/lldbsuite/test/dotest_args.py | 2 + packages/Python/lldbsuite/test/dotest_channels.py | 200 --- .../test/driver/batch_mode/TestBatchMode.py | 8 +- .../expression_command/anonymous-struct/Makefile | 12 + .../anonymous-struct/TestCallUserAnonTypedef.py | 42 + .../expression_command/anonymous-struct/main.cpp | 26 + .../call-function/TestCallStdStringFunction.py | 9 +- .../call-function/TestCallStopAndContinue.py | 5 +- .../call-function/TestCallUserDefinedFunction.py | 5 +- .../call-restarts/TestCallThatRestarts.py | 3 +- .../call-throws/TestCallThatThrows.py | 3 +- .../test/expression_command/char/TestExprsChar.py | 17 +- .../expr-in-syscall/TestExpressionInSyscall.py | 5 +- .../test/expression_command/fixits/Makefile | 12 + .../test/expression_command/fixits/TestFixIts.py | 81 ++ .../test/expression_command/fixits/main.cpp | 25 + .../formatters/TestFormatters.py | 8 +- .../ir-interpreter-phi-nodes/Makefile | 5 + .../TestIRInterpreterPHINodes.py | 40 + .../ir-interpreter-phi-nodes/main.cpp | 17 + .../expression_command/ir-interpreter/Makefile | 7 + .../ir-interpreter/TestIRInterpreter.py | 72 ++ .../test/expression_command/ir-interpreter/main.c | 7 + .../expression_command/issue_11588/Test11588.py | 5 +- .../test/expression_command/macros/TestMacros.py | 10 +- .../test/expression_command/multiline/Makefile | 5 + .../multiline/TestMultilineExpressions.py | 57 + .../test/expression_command/multiline/main.c | 6 + .../TestPersistObjCPointeeType.py | 3 +- .../persistent_types/TestNestedPersistentTypes.py | 4 +- .../persistent_types/TestPersistentTypes.py | 4 +- .../po_verbosity/TestPoVerbosity.py | 3 +- .../radar_9531204/TestPrintfAfterUp.py | 5 +- .../radar_9673664/TestExprHelpExamples.py | 5 +- .../test/expression_command/test/TestExprs.py | 16 +- .../test/expression_command/test/TestExprs2.py | 5 +- .../timeout/TestCallWithTimeout.py | 10 +- .../test/expression_command/top-level/Makefile | 12 + .../top-level/TestTopLevelExprs.py | 89 ++ .../test/expression_command/top-level/dummy.cpp | 7 + .../test/expression_command/top-level/main.cpp | 9 + .../test/expression_command/top-level/test.cpp | 107 ++ .../TestObjCTypeQueryFromOtherCompileUnit.py | 3 +- .../expression_command/unwind_expression/Makefile | 5 + .../unwind_expression/TestUnwindExpression.py | 83 ++ .../expression_command/unwind_expression/main.cpp | 14 + .../abbreviation/TestAbbreviations.py | 4 +- .../abbreviation/TestCommonShortSpellings.py | 3 +- .../functionalities/apropos_with_process/Makefile | 5 + .../apropos_with_process/TestAproposWithProcess.py | 44 + .../functionalities/apropos_with_process/main.cpp | 15 + .../functionalities/archives/TestBSDArchives.py | 6 +- .../test/functionalities/asan/TestMemoryHistory.py | 33 +- .../test/functionalities/asan/TestReportData.py | 24 +- .../attach_resume/TestAttachResume.py | 22 +- .../functionalities/avoids-fd-leak/TestFdLeak.py | 16 +- .../backticks/TestBackticksWithoutATarget.py | 2 + .../TestBadAddressBreakpoints.py | 77 ++ .../breakpoint_case_sensitivity/Makefile | 6 + .../TestBreakpointCaseSensitivity.py | 121 ++ .../breakpoint/breakpoint_case_sensitivity/main.c | 8 + .../breakpoint_command/TestBreakpointCommand.py | 7 +- .../TestBreakpointCommandsFromPython.py | 5 +- .../TestBreakpointConditions.py | 11 +- .../TestBreakpointIgnoreCount.py | 3 +- .../TestAvoidBreakpointInDelaySlot.py | 5 +- .../TestBreakpointLocations.py | 6 +- .../breakpoint/breakpoint_set_restart/Makefile | 5 + .../TestBreakpointSetRestart.py | 43 + .../breakpoint/breakpoint_set_restart/main.cpp | 25 + .../comp_dir_symlink/TestCompDirSymLink.py | 11 +- .../breakpoint/consecutive_breakpoins/Makefile | 9 - .../TestConsecutiveBreakpoints.py | 59 - .../breakpoint/consecutive_breakpoins/main.cpp | 19 - .../breakpoint/consecutive_breakpoints/Makefile | 9 + .../TestConsecutiveBreakpoints.py | 101 ++ .../breakpoint/consecutive_breakpoints/main.cpp | 19 + .../breakpoint/cpp/TestCPPBreakpointLocations.py | 39 +- .../test/functionalities/breakpoint/cpp/main.cpp | 14 +- .../cpp_exception/TestCPPExceptionBreakpoint.py | 7 +- .../breakpoint/debugbreak/TestDebugBreak.py | 11 +- .../breakpoint/objc/TestObjCBreakpoints.py | 7 +- .../breakpoint/source_regexp/Makefile | 5 + .../source_regexp/TestSourceRegexBreakpoints.py | 100 ++ .../functionalities/breakpoint/source_regexp/a.c | 16 + .../functionalities/breakpoint/source_regexp/a.h | 1 + .../breakpoint/source_regexp/main.c | 17 + .../command_history/TestCommandHistory.py | 2 + .../command_regex/TestCommandRegex.py | 4 +- .../command_script/TestCommandScript.py | 4 +- .../command_script/import/TestImport.py | 2 + .../import/rdar-12586188/TestRdar12586188.py | 2 + .../command_script/import/thepackage/__init__.py | 6 +- .../command_script_alias/.categories | 1 + .../command_script_alias/TestCommandScriptAlias.py | 37 + .../command_script_alias/tcsacmd.py | 11 + .../TestCommandScriptImmediateOutput.py | 86 ++ .../custom_command.py | 17 + .../command_source/TestCommandSource.py | 2 + .../functionalities/completion/TestCompletion.py | 69 +- .../conditional_break/TestConditionalBreak.py | 11 +- .../boolreference/TestFormattersBoolRefPtr.py | 11 +- .../data-formatter/boolreference/main.mm | 4 +- .../compactvectors/TestCompactVectors.py | 3 +- .../TestDataFormatterCategories.py | 4 +- .../data-formatter-cpp/TestDataFormatterCpp.py | 5 +- .../TestDataFormatterDisabling.py | 7 +- .../TestDataFormatterNamedSummaries.py | 4 +- .../data-formatter-objc/TestDataFormatterObjC.py | 71 +- .../data-formatter/data-formatter-objc/main.m | 86 +- .../nsstring/TestDataFormatterNSString.py | 5 +- .../TestFormattersOneIsSingular.py | 17 +- .../data-formatter-proper-plurals/main.m | 27 +- .../TestDataFormatterPythonSynth.py | 84 +- .../data-formatter-python-synth/main.cpp | 2 +- .../TestDataFormatterScript.py | 1 + .../data-formatter-skip-summary/Makefile | 6 +- .../TestDataFormatterSkipSummary.py | 7 +- .../TestDataFormatterSmartArray.py | 113 +- .../data-formatter-stl/libcxx/atomic/Makefile | 5 + .../libcxx/atomic/TestLibCxxAtomic.py | 52 + .../data-formatter-stl/libcxx/atomic/main.cpp | 26 + .../libcxx/initializerlist/TestInitializerList.py | 7 +- .../iterator/TestDataFormatterLibccIterator.py | 5 +- .../libcxx/list/TestDataFormatterLibcxxList.py | 6 +- .../list/loop/TestDataFormatterLibcxxListLoop.py | 6 +- .../libcxx/map/TestDataFormatterLibccMap.py | 5 +- .../multimap/TestDataFormatterLibccMultiMap.py | 6 +- .../multiset/TestDataFormatterLibcxxMultiSet.py | 5 +- .../libcxx/set/TestDataFormatterLibcxxSet.py | 89 +- .../libcxx/string/TestDataFormatterLibcxxString.py | 5 +- .../libcxx/unordered/TestDataFormatterUnordered.py | 6 +- .../libcxx/vbool/TestDataFormatterLibcxxVBool.py | 5 +- .../libcxx/vector/TestDataFormatterLibcxxVector.py | 5 +- .../iterator/TestDataFormatterStdIterator.py | 5 +- .../libstdcpp/list/TestDataFormatterStdList.py | 3 +- .../libstdcpp/map/TestDataFormatterStdMap.py | 5 +- .../libstdcpp/smart_ptr/Makefile | 15 + .../smart_ptr/TestDataFormatterStdSmartPtr.py | 46 + .../libstdcpp/smart_ptr/main.cpp | 20 + .../libstdcpp/string/TestDataFormatterStdString.py | 3 +- .../libstdcpp/vbool/TestDataFormatterStdVBool.py | 7 +- .../libstdcpp/vector/TestDataFormatterStdVector.py | 5 +- .../data-formatter-synthtype/Makefile | 5 + .../TestDataFormatterSynthType.py | 56 + .../data-formatter-synthtype/main.cpp | 29 + .../data-formatter-synthtype/myIntSynthProvider.py | 36 + .../TestDataFormatterSynthVal.py | 5 +- .../data-formatter/dump_dynamic/TestDumpDynamic.py | 2 +- .../nsarraysynth/TestNSArraySynthetic.py | 5 +- .../nsdictionarysynth/TestNSDictionarySynthetic.py | 5 +- .../nssetsynth/TestNSSetSynthetic.py | 5 +- .../ostypeformatting/TestFormattersOsType.py | 5 +- .../functionalities/data-formatter/parray/Makefile | 5 + .../data-formatter/parray/TestPrintArray.py | 70 ++ .../functionalities/data-formatter/parray/main.cpp | 29 + .../data-formatter/poarray/Makefile | 9 + .../data-formatter/poarray/TestPrintObjectArray.py | 60 + .../functionalities/data-formatter/poarray/main.mm | 30 + .../setvaluefromcstring/TestSetValueFromCString.py | 6 +- .../stringprinter/TestStringPrinter.py | 6 +- .../synthcapping/TestSyntheticCapping.py | 25 +- .../synthcapping/fooSynthProvider.py | 38 +- .../data-formatter/synthcapping/main.cpp | 2 +- .../synthupdate/TestSyntheticFilterRecompute.py | 5 +- .../TestTypeSummaryListArg.py | 31 + .../type_summary_list_script/Makefile | 5 + .../TestTypeSummaryListScript.py | 61 + .../type_summary_list_script/main.cpp | 15 + .../type_summary_list_script/tslsformatters.py | 10 + .../typedef_array/TestTypedefArray.py | 6 +- .../TestDataFormatterVarScriptFormatting.py | 5 +- .../vector-types/TestVectorTypesFormatting.py | 3 +- .../functionalities/dead-strip/TestDeadStrip.py | 8 +- .../disassembly/TestDisassembleBreakpoint.py | 10 +- .../TestDynamicValueChildCount.py | 8 +- .../TestConvenienceVariables.py | 4 +- .../test/functionalities/exec/TestExec.py | 38 +- .../expr-doesnt-deadlock/TestExprDoesntBlock.py | 8 +- .../fat_archives/TestFatArchives.py | 5 +- .../test/functionalities/format/TestFormats.py | 4 +- .../inferior-assert/TestInferiorAssert.py | 36 +- .../inferior-changed/TestInferiorChanged.py | 8 +- .../inferior-crashing/TestInferiorCrashing.py | 23 +- .../recursive-inferior/TestRecursiveInferior.py | 24 +- .../inline-stepping/TestInlineStepping.py | 8 +- .../jitloader_gdb/TestJITLoaderGDB.py | 7 +- .../TestLaunchWithShellExpand.py | 13 +- .../test/functionalities/llvm/TestLLVM.py | 60 + .../functionalities/load_unload/TestLoadUnload.py | 8 +- .../test/functionalities/longjmp/TestLongjmp.py | 15 +- .../test/functionalities/memory/cache/Makefile | 5 + .../memory/cache/TestMemoryCache.py | 64 + .../test/functionalities/memory/cache/main.cpp | 14 + .../TestMultipleDebuggersCommands.py | 48 + .../test/functionalities/nested_alias/Makefile | 5 + .../nested_alias/TestNestedAlias.py | 68 + .../test/functionalities/nested_alias/main.cpp | 22 + .../object-file/TestImageListMultiArchitecture.py | 7 +- .../test/functionalities/paths/TestPaths.py | 3 +- .../platform/TestPlatformCommand.py | 2 + .../plugins/commands/TestPluginCommands.py | 5 +- .../postmortem/linux-core/TestLinuxCore.py | 164 +++ .../postmortem/linux-core/altmain.c | 6 + .../postmortem/linux-core/altmain.core | Bin 0 -> 40960 bytes .../postmortem/linux-core/altmain.out | Bin 0 -> 2330 bytes .../postmortem/linux-core/i386.core | Bin 0 -> 28672 bytes .../functionalities/postmortem/linux-core/i386.out | Bin 0 -> 1971 bytes .../functionalities/postmortem/linux-core/main.c | 17 + .../postmortem/linux-core/make-core.sh | 40 + .../postmortem/linux-core/s390x.core | Bin 0 -> 16384 bytes .../postmortem/linux-core/s390x.out | Bin 0 -> 2824 bytes .../postmortem/linux-core/x86_64.core | Bin 0 -> 40960 bytes .../postmortem/linux-core/x86_64.out | Bin 0 -> 2575 bytes .../postmortem/minidump/TestMiniDump.py | 3 +- .../postmortem/wow64_minidump/TestWow64MiniDump.py | 76 ++ .../postmortem/wow64_minidump/fizzbuzz.cpp | 31 + .../postmortem/wow64_minidump/fizzbuzz_wow64.dmp | Bin 0 -> 9280561 bytes .../process_attach/TestProcessAttach.py | 3 +- .../attach_denied/TestAttachDenied.py | 24 +- .../process_group/TestChangeProcessGroup.py | 27 +- .../process_launch/TestProcessLaunch.py | 48 +- .../functionalities/process_launch/print_env.cpp | 3 +- .../process_save_core/TestProcessSaveCore.py | 2 + .../test/functionalities/ptr_refs/Makefile | 5 + .../test/functionalities/ptr_refs/TestPtrRefs.py | 43 + .../lldbsuite/test/functionalities/ptr_refs/main.c | 27 + .../test/functionalities/register/TestRegisters.py | 17 +- .../test/functionalities/rerun/TestRerun.py | 34 +- .../return-value/TestReturnValue.py | 5 +- .../test/functionalities/set-data/TestSetData.py | 3 +- .../test/functionalities/signal/TestSendSignal.py | 5 +- .../signal/handle-segv/TestHandleSegv.py | 8 +- .../test/functionalities/signal/raise/TestRaise.py | 9 +- .../TestSingleQuoteInFilename.py | 4 +- .../step-avoids-no-debug/TestStepNoDebug.py | 12 +- .../functionalities/stop-hook/TestStopHookCmd.py | 3 +- .../stop-hook/TestStopHookMechanism.py | 6 +- .../TestStopHookMultipleThreads.py | 6 +- .../target_command/TestTargetCommand.py | 3 +- .../thread/backtrace_all/TestBacktraceAll.py | 3 +- .../thread/break_after_join/TestBreakAfterJoin.py | 9 +- .../thread/break_after_join/main.cpp | 16 +- .../concurrent_events/TestConcurrentEvents.py | 40 +- .../thread/concurrent_events/main.cpp | 14 +- .../crash_during_step/TestCrashDuringStep.py | 15 +- .../create_after_attach/TestCreateAfterAttach.py | 4 +- .../create_during_step/TestCreateDuringStep.py | 27 +- .../thread/create_during_step/main.cpp | 12 +- .../exit_during_break/TestExitDuringBreak.py | 11 +- .../thread/exit_during_break/main.cpp | 18 +- .../thread/exit_during_step/TestExitDuringStep.py | 64 +- .../thread/exit_during_step/main.cpp | 12 +- .../functionalities/thread/jump/TestThreadJump.py | 3 +- .../thread/multi_break/TestMultipleBreakpoints.py | 13 +- .../functionalities/thread/multi_break/main.cpp | 14 +- .../thread/state/TestThreadStates.py | 134 +- .../thread/step_out/TestThreadStepOut.py | 21 +- .../test/functionalities/thread/step_out/main.cpp | 14 +- .../thread/thread_exit/TestThreadExit.py | 68 +- .../functionalities/thread/thread_exit/main.cpp | 18 +- .../TestThreadSpecificBreakpoint.py | 5 +- .../TestThreadSpecificBpPlusCondition.py | 6 +- .../test/functionalities/tsan/basic/Makefile | 6 + .../functionalities/tsan/basic/TestTsanBasic.py | 118 ++ .../test/functionalities/tsan/basic/main.c | 37 + .../tsan/cpp_global_location/Makefile | 6 + .../TestTsanCPPGlobalLocation.py | 54 + .../tsan/cpp_global_location/main.cpp | 38 + .../functionalities/tsan/global_location/Makefile | 6 + .../tsan/global_location/TestTsanGlobalLocation.py | 54 + .../functionalities/tsan/global_location/main.c | 38 + .../test/functionalities/tsan/multiple/Makefile | 6 + .../tsan/multiple/TestTsanMultiple.py | 69 ++ .../test/functionalities/tsan/multiple/main.m | 138 +++ .../test/functionalities/tsan/thread_leak/Makefile | 6 + .../tsan/thread_leak/TestTsanThreadLeak.py | 40 + .../test/functionalities/tsan/thread_leak/main.c | 24 + .../functionalities/tsan/thread_numbers/Makefile | 6 + .../tsan/thread_numbers/TestTsanThreadNumbers.py | 68 + .../functionalities/tsan/thread_numbers/main.c | 58 + .../test/functionalities/tty/TestTerminal.py | 3 +- .../type_completion/TestTypeCompletion.py | 5 +- .../functionalities/type_lookup/TestTypeLookup.py | 6 +- .../test/functionalities/unwind/ehframe/Makefile | 7 + .../unwind/ehframe/TestEhFrameUnwind.py | 51 + .../test/functionalities/unwind/ehframe/main.c | 20 + .../unwind/noreturn/TestNoreturnUnwind.py | 4 +- .../unwind/sigtramp/TestSigtrampUnwind.py | 3 +- .../unwind/standard/TestStandardUnwind.py | 3 +- .../value_md5_crash/TestValueMD5Crash.py | 5 +- .../hello_watchlocation/TestWatchLocation.py | 13 +- .../watchpoint/hello_watchlocation/main.cpp | 6 +- .../hello_watchpoint/TestMyFirstWatchpoint.py | 5 +- .../TestWatchpointMultipleThreads.py | 13 +- .../watchpoint/multiple_threads/main.cpp | 10 +- .../step_over_watchpoint/TestStepOverWatchpoint.py | 10 +- .../watchpoint_commands/TestWatchpointCommands.py | 18 +- .../command/TestWatchpointCommandLLDB.py | 9 +- .../command/TestWatchpointCommandPython.py | 60 +- .../command/watchpoint_command.py | 14 + .../condition/TestWatchpointConditionCmd.py | 6 +- .../watchpoint_events/TestWatchpointEvents.py | 8 +- .../TestValueOfVectorVariable.py | 5 +- .../watchpoint/watchpoint_on_vectors/main.c | 2 +- .../TestWatchLocationWithWatchSet.py | 7 +- .../TestWatchpointSetErrorCases.py | 2 + .../watchpoint/watchpoint_size/Makefile | 5 + .../watchpoint_size/TestWatchpointSizes.py | 117 ++ .../watchpoint/watchpoint_size/main.c | 66 + packages/Python/lldbsuite/test/help/TestApropos.py | 22 + packages/Python/lldbsuite/test/help/TestHelp.py | 50 +- .../TestInvalidDecorator.py.park | 13 + .../issue_verification/TestRerunTimeout.py.park | 8 +- .../test/lang/c/anonymous/TestAnonymous.py | 20 +- .../test/lang/c/array_types/TestArrayTypes.py | 12 +- .../test/lang/c/bitfields/TestBitfields.py | 21 +- .../Python/lldbsuite/test/lang/c/bitfields/main.c | 14 + .../lldbsuite/test/lang/c/blocks/TestBlocks.py | 18 +- .../lang/c/const_variables/TestConstVariables.py | 7 +- .../test/lang/c/enum_types/TestEnumTypes.py | 17 +- .../Python/lldbsuite/test/lang/c/enum_types/main.c | 11 + .../lang/c/function_types/TestFunctionTypes.py | 5 +- .../lang/c/global_variables/TestGlobalVariables.py | 7 +- .../Python/lldbsuite/test/lang/c/inlines/Makefile | 5 - .../lang/c/inlines/TestRedefinitionsInInlines.py | 5 + .../Python/lldbsuite/test/lang/c/inlines/inlines.c | 53 - .../Python/lldbsuite/test/lang/c/inlines/inlines.h | 4 - .../Python/lldbsuite/test/lang/c/inlines/main.c | 19 + .../lldbsuite/test/lang/c/modules/TestCModules.py | 17 +- .../test/lang/c/register_variables/Makefile | 2 +- .../c/register_variables/TestRegisterVariables.py | 150 ++- .../test/lang/c/register_variables/test.c | 12 +- .../test/lang/c/set_values/TestSetValues.py | 4 +- .../TestSharedLibStrippedSymbols.py | 7 +- .../lldbsuite/test/lang/c/step-target/Makefile | 5 + .../test/lang/c/step-target/TestStepTarget.py | 113 ++ .../lldbsuite/test/lang/c/step-target/main.c | 40 + .../test/lang/c/stepping/TestStepAndBreakpoints.py | 16 +- .../lldbsuite/test/lang/c/strings/TestCStrings.py | 5 +- .../test/lang/c/struct_types/TestStructTypes.py | 6 +- .../test/lang/c/tls_globals/TestTlsGlobals.py | 5 +- .../Python/lldbsuite/test/lang/c/tls_globals/a.c | 6 + .../lldbsuite/test/lang/c/tls_globals/main.c | 14 +- .../lldbsuite/test/lang/c/typedef/Testtypedef.py | 7 +- .../Python/lldbsuite/test/lang/c/unions/Makefile | 5 + .../test/lang/c/unions/TestUnionMembers.py | 46 + .../Python/lldbsuite/test/lang/c/unions/main.c | 18 + .../lldbsuite/test/lang/cpp/auto/TestCPPAuto.py | 6 +- .../TestCPPBreakpointCommands.py | 4 +- .../lang/cpp/call-function/TestCallCPPFunction.py | 5 +- .../lang/cpp/chained-calls/TestCppChainedCalls.py | 5 +- .../test/lang/cpp/char1632_t/TestChar1632T.py | 6 +- .../lang/cpp/class_static/TestStaticVariables.py | 17 +- .../test/lang/cpp/class_types/TestClassTypes.py | 18 +- .../cpp/class_types/TestClassTypesDisassembly.py | 6 +- .../lldbsuite/test/lang/cpp/const_this/Makefile | 8 + .../test/lang/cpp/const_this/TestConstThis.py | 4 + .../lldbsuite/test/lang/cpp/const_this/main.cpp | 23 + .../lldbsuite/test/lang/cpp/diamond/TestDiamond.py | 3 +- .../lang/cpp/dynamic-value/TestCppValueCast.py | 3 +- .../lang/cpp/dynamic-value/TestDynamicValue.py | 6 +- .../cpp/exceptions/TestCPPExceptionBreakpoints.py | 5 +- .../lldbsuite/test/lang/cpp/extern_c/Makefile | 3 + .../test/lang/cpp/extern_c/TestExternCSymbols.py | 4 + .../lldbsuite/test/lang/cpp/extern_c/main.cpp | 29 + .../TestFrameVariableAnonymousUnions.py | 8 +- .../cpp/global_operators/TestCppGlobalOperators.py | 5 +- .../lldbsuite/test/lang/cpp/gmodules/Makefile | 7 + .../lang/cpp/gmodules/TestWithModuleDebugging.py | 50 + .../lldbsuite/test/lang/cpp/gmodules/main.cpp | 5 + .../Python/lldbsuite/test/lang/cpp/gmodules/pch.h | 12 + .../cpp/incomplete-types/TestCppIncompleteTypes.py | 8 +- .../lldbsuite/test/lang/cpp/inlines/Makefile | 5 + .../lldbsuite/test/lang/cpp/inlines/TestInlines.py | 52 + .../lldbsuite/test/lang/cpp/inlines/inlines.cpp | 53 + .../lldbsuite/test/lang/cpp/inlines/inlines.h | 4 + .../lldbsuite/test/lang/cpp/lambdas/TestLambdas.py | 4 + .../lldbsuite/test/lang/cpp/lambdas/main.cpp | 17 + .../cpp/limit-debug-info/TestWithLimitDebugInfo.py | 5 +- .../member-and-local-vars-with-same-name/Makefile | 5 + .../TestMembersAndLocalsWithSameName.py | 197 +++ .../member-and-local-vars-with-same-name/main.cpp | 73 ++ .../test/lang/cpp/namespace/TestNamespace.py | 74 +- .../test/lang/cpp/namespace/TestNamespaceLookup.py | 17 +- .../test/lang/cpp/namespace_definitions/Makefile | 19 + .../TestNamespaceDefinitions.py | 57 + .../test/lang/cpp/namespace_definitions/a.cpp | 16 + .../test/lang/cpp/namespace_definitions/a.mk | 9 + .../test/lang/cpp/namespace_definitions/b.cpp | 12 + .../test/lang/cpp/namespace_definitions/b.mk | 9 + .../test/lang/cpp/namespace_definitions/foo.h | 18 + .../test/lang/cpp/namespace_definitions/main.cpp | 16 + .../test/lang/cpp/nsimport/TestCppNsImport.py | 6 +- .../TestOverloadedFunctions.py | 5 +- .../lldbsuite/test/lang/cpp/printf/TestPrintf.py | 4 + .../Python/lldbsuite/test/lang/cpp/printf/main.cpp | 21 + .../lldbsuite/test/lang/cpp/rdar12991846/Makefile | 8 - .../test/lang/cpp/rdar12991846/TestRdar12991846.py | 85 -- .../lldbsuite/test/lang/cpp/rdar12991846/main.cpp | 21 - .../cpp/rvalue-references/TestRvalueReferences.py | 7 +- .../lldbsuite/test/lang/cpp/scope/TestCppScope.py | 5 +- .../test/lang/cpp/signed_types/TestSignedTypes.py | 4 +- .../cpp/static_members/TestCPPStaticMembers.py | 5 +- .../cpp/static_methods/TestCPPStaticMethods.py | 5 +- .../Python/lldbsuite/test/lang/cpp/stl/TestSTL.py | 8 +- .../test/lang/cpp/stl/TestStdCXXDisassembly.py | 3 +- .../lldbsuite/test/lang/cpp/template/Makefile | 7 + .../test/lang/cpp/template/TestTemplateArgs.py | 87 ++ .../lldbsuite/test/lang/cpp/template/main.cpp | 72 ++ .../lldbsuite/test/lang/cpp/this/TestCPPThis.py | 11 +- .../test/lang/cpp/unicode-literals/Makefile | 8 + .../cpp/unicode-literals/TestUnicodeLiterals.py | 82 ++ .../test/lang/cpp/unicode-literals/main.cpp | 21 + .../lang/cpp/unsigned_types/TestUnsignedTypes.py | 2 + .../lldbsuite/test/lang/cpp/virtual/TestVirtual.py | 22 +- .../lldbsuite/test/lang/cpp/virtual/main.cpp | 25 +- .../test/lang/go/expressions/TestExpressions.py | 3 +- .../test/lang/go/formatters/TestGoFormatters.py | 3 +- .../test/lang/go/goroutines/TestGoroutines.py | 3 +- .../test/lang/go/runtime/TestGoLanguageRuntime | 2 +- .../test/lang/go/types/TestGoASTContext.py | 3 +- .../lang/objc/bitfield_ivars/TestBitfieldIvars.py | 4 + .../lldbsuite/test/lang/objc/bitfield_ivars/main.m | 52 + .../test/lang/objc/blocks/TestObjCIvarsInBlocks.py | 5 +- .../test/lang/objc/forward-decl/TestForwardDecl.py | 3 +- .../test/lang/objc/foundation/TestConstStrings.py | 3 +- .../objc/foundation/TestFoundationDisassembly.py | 3 +- .../test/lang/objc/foundation/TestObjCMethods.py | 3 +- .../test/lang/objc/foundation/TestObjCMethods2.py | 6 +- .../objc/foundation/TestObjectDescriptionAPI.py | 3 +- .../test/lang/objc/foundation/TestRuntimeTypes.py | 4 +- .../test/lang/objc/foundation/TestSymbolTable.py | 6 +- .../lang/objc/global_ptrs/TestGlobalObjects.py | 3 +- .../test/lang/objc/hidden-ivars/TestHiddenIvars.py | 15 +- .../test/lang/objc/ivar-IMP/TestObjCiVarIMP.py | 6 +- .../modules-auto-import/TestModulesAutoImport.py | 6 +- .../modules-incomplete/TestIncompleteModules.py | 7 +- .../TestModulesInlineFunctions.py | 9 +- .../test/lang/objc/modules/TestObjCModules.py | 6 +- .../lldbsuite/test/lang/objc/objc++/TestObjCXX.py | 3 +- .../TestObjCBaseClassSBType.py | 3 +- .../objc-builtin-types/TestObjCBuiltinTypes.py | 3 +- .../lang/objc/objc-checker/TestObjCCheckers.py | 3 +- .../objc/objc-class-method/TestObjCClassMethod.py | 5 +- .../objc/objc-dyn-sbtype/TestObjCDynamicSBType.py | 5 +- .../objc-dynamic-value/TestObjCDynamicValue.py | 3 +- .../objc/objc-ivar-offsets/TestObjCIvarOffsets.py | 3 +- .../objc/objc-ivar-protocols/TestIvarProtocols.py | 6 +- .../objc-ivar-stripped/TestObjCIvarStripped.py | 6 +- .../lang/objc/objc-new-syntax/TestObjCNewSyntax.py | 5 +- .../lang/objc/objc-optimized/TestObjcOptimized.py | 6 +- .../lang/objc/objc-property/TestObjCProperty.py | 17 +- .../lldbsuite/test/lang/objc/objc-property/main.m | 13 + .../objc/objc-runtime-ivars/TestRuntimeIvars.py | 6 +- .../lang/objc/objc-static-method-stripped/Makefile | 3 +- .../TestObjCStaticMethodStripped.py | 8 +- .../objc-static-method/TestObjCStaticMethod.py | 3 +- .../lang/objc/objc-stepping/TestObjCStepping.py | 3 +- .../objc-struct-argument/TestObjCStructArgument.py | 3 +- .../objc-struct-return/TestObjCStructReturn.py | 3 +- .../test/lang/objc/objc-super/TestObjCSuper.py | 5 +- .../test/lang/objc/print-obj/TestPrintObj.py | 2 + .../radar-9691614/TestObjCMethodReturningBOOL.py | 3 +- .../lang/objc/rdar-10967107/TestRdar10967107.py | 3 +- .../lang/objc/rdar-11355592/TestRdar11355592.py | 3 +- .../lang/objc/rdar-12408181/TestRdar12408181.py | 3 +- .../objc/real-definition/TestRealDefinition.py | 3 +- .../lldbsuite/test/lang/objc/self/TestObjCSelf.py | 3 +- .../lang/objc/single-entry-dictionary/Makefile | 7 + .../TestObjCSingleEntryDictionary.py | 68 + .../test/lang/objc/single-entry-dictionary/main.m | 7 + .../objc/variadic_methods/TestVariadicMethods.py | 4 + .../test/lang/objc/variadic_methods/main.m | 31 + .../objcxx/objcxx-ivar-vector/TestIvarVector.py | 6 +- .../test/linux/builtin_trap/TestBuiltinTrap.py | 4 +- .../TestCreateDuringInstructionStep.py | 4 +- packages/Python/lldbsuite/test/lldbinline.py | 35 +- packages/Python/lldbsuite/test/lldbpexpect.py | 96 +- packages/Python/lldbsuite/test/lldbplatform.py | 44 + packages/Python/lldbsuite/test/lldbplatformutil.py | 125 +- packages/Python/lldbsuite/test/lldbtest.py | 1064 +++------------- packages/Python/lldbsuite/test/lldbutil.py | 47 +- .../Python/lldbsuite/test/logging/TestLogging.py | 8 +- .../add-dsym/TestAddDsymMidExecutionCommand.py | 2 + .../apple_types/TestAppleTypesIsProduced.py | 2 + .../macosx/indirect_symbol/TestIndirectSymbols.py | 3 +- .../Python/lldbsuite/test/macosx/nslog/Makefile | 6 + .../test/macosx/nslog/TestDarwinNSLogOutput.py | 148 +++ packages/Python/lldbsuite/test/macosx/nslog/main.m | 18 + .../lldbsuite/test/macosx/order/TestOrderFile.py | 2 + .../lldbsuite/test/macosx/queues/TestQueues.py | 3 +- .../macosx/safe-to-func-call/TestSafeFuncCalls.py | 3 +- .../test/macosx/universal/TestUniversal.py | 53 +- .../Python/lldbsuite/test/macosx/universal/main.c | 14 + packages/Python/lldbsuite/test/make/Makefile.rules | 37 +- packages/Python/lldbsuite/test/make/test_common.h | 42 +- .../Python/lldbsuite/test/plugins/builder_base.py | 42 +- .../lldbsuite/test/plugins/builder_darwin.py | 4 +- .../Python/lldbsuite/test/plugins/builder_linux.py | 4 + .../lldbsuite/test/plugins/builder_linux2.py | 4 - .../python_api/breakpoint/TestBreakpointAPI.py | 3 +- .../class_members/TestSBTypeClassMembers.py | 3 +- .../test/python_api/debugger/TestDebuggerAPI.py | 3 + .../TestDefaultConstructorForAPIObjects.py | 3 +- .../disassemble-raw-data/TestDisassembleRawData.py | 4 +- .../TestDisassemble_VST1_64.py | 5 +- .../lldbsuite/test/python_api/event/TestEvents.py | 19 +- .../exprpath_synthetic/TestExprPathSynthetic.py | 6 +- .../findvalue_duplist/TestSBFrameFindValue.py | 3 +- .../python_api/formatters/TestFormattersSBAPI.py | 3 +- .../lldbsuite/test/python_api/frame/TestFrames.py | 15 +- .../test/python_api/frame/get-variables/Makefile | 5 + .../frame/get-variables/TestGetVariables.py | 190 +++ .../test/python_api/frame/get-variables/main.c | 29 + .../python_api/frame/inlines/TestInlinedFrame.py | 8 +- .../python_api/function_symbol/TestDisasmAPI.py | 3 +- .../python_api/function_symbol/TestSymbolAPI.py | 3 +- .../test/python_api/hello_world/TestHelloWorld.py | 23 +- .../interpreter/TestCommandInterpreterAPI.py | 2 + .../python_api/lldbutil/frame/TestFrameUtils.py | 2 + .../python_api/lldbutil/iter/TestLLDBIterator.py | 2 + .../lldbutil/iter/TestRegistersIterator.py | 4 +- .../lldbutil/process/TestPrintStackTraces.py | 6 +- .../module_section/TestModuleAndSection.py | 2 + .../test/python_api/objc_type/TestObjCType.py | 3 +- .../test/python_api/process/TestProcessAPI.py | 20 +- .../test/python_api/process/io/TestProcessIO.py | 8 +- .../lldbsuite/test/python_api/sbdata/TestSBData.py | 19 +- .../sbtype_typeclass/TestSBTypeTypeClass.py | 6 +- .../sbvalue_persist/TestSBValuePersist.py | 5 +- .../test/python_api/section/TestSectionAPI.py | 3 +- .../test/python_api/signals/TestSignalsAPI.py | 5 +- .../python_api/symbol-context/TestSymbolContext.py | 9 +- .../python_api/symbol-context/two-files/Makefile | 5 + .../two-files/TestSymbolContextTwoFiles.py | 36 + .../python_api/symbol-context/two-files/decls.h | 11 + .../python_api/symbol-context/two-files/file1.cpp | 13 + .../python_api/symbol-context/two-files/file2.cpp | 6 + .../test/python_api/target/TestTargetAPI.py | 5 +- .../test/python_api/thread/TestThreadAPI.py | 8 +- .../lldbsuite/test/python_api/type/TestTypeList.py | 7 +- .../test/python_api/value/TestValueAPI.py | 20 +- .../value/change_values/TestChangeValueAPI.py | 5 +- .../value/linked_list/TestValueAPILinkedList.py | 3 +- .../Python/lldbsuite/test/python_api/value/main.c | 4 + .../value_var_update/TestValueVarUpdate.py | 2 + .../python_api/watchpoint/TestSetWatchpoint.py | 6 +- .../watchpoint/TestWatchpointIgnoreCount.py | 6 +- .../python_api/watchpoint/TestWatchpointIter.py | 11 +- .../condition/TestWatchpointConditionAPI.py | 4 +- .../watchlocation/TestSetWatchlocation.py | 9 +- .../watchlocation/TestTargetWatchAddress.py | 6 +- packages/Python/lldbsuite/test/result_formatter.py | 1304 -------------------- .../Python/lldbsuite/test/settings/TestSettings.py | 12 +- .../lldbsuite/test/settings/quoting/TestQuoting.py | 19 +- .../test/source-manager/TestSourceManager.py | 38 +- .../test/terminal/TestSTTYBeforeAndAfter.py | 4 +- packages/Python/lldbsuite/test/test_categories.py | 22 +- packages/Python/lldbsuite/test/test_result.py | 45 +- .../Python/lldbsuite/test/test_runner/__init__.py | 0 .../lldbsuite/test/test_runner/lib/lldb_utils.py | 66 - .../test/test_runner/lib/process_control.py | 705 ----------- .../lldbsuite/test/test_runner/process_control.py | 705 +++++++++++ .../lldbsuite/test/test_runner/test/__init__.py | 0 .../test/test_runner/test/process_control_tests.py | 235 ---- .../test/test_runner/test/test_process_control.py | 238 ++++ .../lldbsuite/test/tools/lldb-mi/TestMiExit.py | 10 +- .../lldbsuite/test/tools/lldb-mi/TestMiFile.py | 2 + .../test/tools/lldb-mi/TestMiGdbSetShow.py | 20 +- .../test/tools/lldb-mi/TestMiLibraryLoaded.py | 2 + .../lldbsuite/test/tools/lldb-mi/TestMiPrompt.py | 2 + .../test/tools/lldb-mi/breakpoint/TestMiBreak.py | 49 +- .../test/tools/lldb-mi/control/TestMiExec.py | 14 +- .../test/tools/lldb-mi/data/TestMiData.py | 2 + .../tools/lldb-mi/interpreter/TestMiCliSupport.py | 2 + .../lldb-mi/interpreter/TestMiInterpreterExec.py | 6 +- .../test/tools/lldb-mi/signal/TestMiSignal.py | 2 + .../test/tools/lldb-mi/stack/TestMiStack.py | 15 + .../lldbsuite/test/tools/lldb-mi/stack/main.cpp | 15 + .../startup_options/TestMiStartupOptions.py | 4 +- .../test/tools/lldb-mi/symbol/TestMiSymbol.py | 4 +- .../test/tools/lldb-mi/syntax/TestMiSyntax.py | 4 +- .../test/tools/lldb-mi/target/TestMiTarget.py | 4 +- .../test/tools/lldb-mi/threadinfo/Makefile | 7 + .../tools/lldb-mi/threadinfo/TestMiThreadInfo.py | 39 + .../tools/lldb-mi/threadinfo/test_threadinfo.cpp | 21 + .../lldb-mi/variable/TestMiGdbSetShowPrint.py | 6 +- .../test/tools/lldb-mi/variable/TestMiVar.py | 6 +- .../tools/lldb-server/TestGDBRemoteMemoryRead.py | 12 +- .../test/tools/lldb-server/TestGdbRemoteAttach.py | 3 +- .../tools/lldb-server/TestGdbRemoteAuxvSupport.py | 4 +- .../lldb-server/TestGdbRemoteExpeditedRegisters.py | 2 + .../test/tools/lldb-server/TestGdbRemoteKill.py | 3 +- .../tools/lldb-server/TestGdbRemoteProcessInfo.py | 7 +- .../lldb-server/TestGdbRemoteRegisterState.py | 4 +- .../tools/lldb-server/TestGdbRemoteSingleStep.py | 5 +- .../lldb-server/TestGdbRemoteThreadsInStopReply.py | 4 +- .../lldb-server/TestGdbRemote_qThreadStopInfo.py | 2 + .../test/tools/lldb-server/TestGdbRemote_vCont.py | 10 +- .../test/tools/lldb-server/TestLldbGdbServer.py | 25 +- .../commandline/TestStubReverseConnect.py | 2 + .../lldb-server/commandline/TestStubSetSID.py | 4 +- .../test/tools/lldb-server/gdbremote_testcase.py | 155 ++- .../inferior-crash/TestGdbRemoteAbort.py | 2 + .../inferior-crash/TestGdbRemoteSegFault.py | 2 + .../test/tools/lldb-server/lldbgdbserverutils.py | 14 +- .../TestPlatformProcessConnect.py | 28 +- .../test/tools/lldb-server/socket_packet_pump.py | 60 +- .../Python/lldbsuite/test/types/TestFloatTypes.py | 5 +- .../lldbsuite/test/types/TestFloatTypesExpr.py | 6 +- .../lldbsuite/test/types/TestIntegerTypes.py | 7 +- .../lldbsuite/test/types/TestIntegerTypesExpr.py | 6 +- .../test/warnings/uuid/TestAddDsymCommand.py | 2 + packages/Python/lldbsuite/test/xunit_formatter.py | 565 --------- packages/Python/lldbsuite/test_event/__init__.py | 0 .../Python/lldbsuite/test_event/build_exception.py | 14 + .../Python/lldbsuite/test_event/dotest_channels.py | 207 ++++ .../Python/lldbsuite/test_event/event_builder.py | 475 +++++++ .../lldbsuite/test_event/formatter/__init__.py | 162 +++ .../lldbsuite/test_event/formatter/curses.py | 229 ++++ .../test_event/formatter/dump_formatter.py | 23 + .../lldbsuite/test_event/formatter/pickled.py | 72 ++ .../test_event/formatter/results_formatter.py | 717 +++++++++++ .../Python/lldbsuite/test_event/formatter/xunit.py | 592 +++++++++ .../invalid_decorator/TestInvalidDecorator.py | 13 + .../test/src/TestCatchInvalidDecorator.py | 70 ++ .../test_event/test/src/event_collector.py | 85 ++ 658 files changed, 13715 insertions(+), 6511 deletions(-) create mode 100644 packages/Python/lldbsuite/support/encoded_file.py create mode 100644 packages/Python/lldbsuite/support/funcutils.py create mode 100644 packages/Python/lldbsuite/support/gmodules.py create mode 100644 packages/Python/lldbsuite/support/optional_with.py create mode 100644 packages/Python/lldbsuite/test/api/listeners/Makefile create mode 100644 packages/Python/lldbsuite/test/api/listeners/TestListener.py create mode 100644 packages/Python/lldbsuite/test/api/listeners/main.c delete mode 100644 packages/Python/lldbsuite/test/curses_results.py create mode 100644 packages/Python/lldbsuite/test/decorators.py delete mode 100644 packages/Python/lldbsuite/test/dotest_channels.py create mode 100644 packages/Python/lldbsuite/test/expression_command/anonymous-struct/Makefile create mode 100644 packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py create mode 100644 packages/Python/lldbsuite/test/expression_command/anonymous-struct/main.cpp create mode 100644 packages/Python/lldbsuite/test/expression_command/fixits/Makefile create mode 100644 packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py create mode 100644 packages/Python/lldbsuite/test/expression_command/fixits/main.cpp create mode 100644 packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/Makefile create mode 100644 packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py create mode 100644 packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp create mode 100644 packages/Python/lldbsuite/test/expression_command/ir-interpreter/Makefile create mode 100644 packages/Python/lldbsuite/test/expression_command/ir-interpreter/TestIRInterpreter.py create mode 100644 packages/Python/lldbsuite/test/expression_command/ir-interpreter/main.c create mode 100644 packages/Python/lldbsuite/test/expression_command/multiline/Makefile create mode 100644 packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py create mode 100644 packages/Python/lldbsuite/test/expression_command/multiline/main.c create mode 100644 packages/Python/lldbsuite/test/expression_command/top-level/Makefile create mode 100644 packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py create mode 100644 packages/Python/lldbsuite/test/expression_command/top-level/dummy.cpp create mode 100644 packages/Python/lldbsuite/test/expression_command/top-level/main.cpp create mode 100644 packages/Python/lldbsuite/test/expression_command/top-level/test.cpp create mode 100644 packages/Python/lldbsuite/test/expression_command/unwind_expression/Makefile create mode 100644 packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py create mode 100644 packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/apropos_with_process/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/apropos_with_process/TestAproposWithProcess.py create mode 100644 packages/Python/lldbsuite/test/functionalities/apropos_with_process/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/main.c create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp delete mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/Makefile delete mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/TestConsecutiveBreakpoints.py delete mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h create mode 100644 packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c create mode 100644 packages/Python/lldbsuite/test/functionalities/command_script_alias/.categories create mode 100644 packages/Python/lldbsuite/test/functionalities/command_script_alias/TestCommandScriptAlias.py create mode 100644 packages/Python/lldbsuite/test/functionalities/command_script_alias/tcsacmd.py create mode 100644 packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py create mode 100644 packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/custom_command.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/TestLibCxxAtomic.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/atomic/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/TestDataFormatterSynthType.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/myIntSynthProvider.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/parray/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/parray/TestPrintArray.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/parray/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/TestPrintObjectArray.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/main.mm create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_arg/TestTypeSummaryListArg.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/TestTypeSummaryListScript.py create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/tslsformatters.py create mode 100644 packages/Python/lldbsuite/test/functionalities/llvm/TestLLVM.py create mode 100644 packages/Python/lldbsuite/test/functionalities/memory/cache/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py create mode 100644 packages/Python/lldbsuite/test/functionalities/memory/cache/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py create mode 100644 packages/Python/lldbsuite/test/functionalities/nested_alias/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/nested_alias/TestNestedAlias.py create mode 100644 packages/Python/lldbsuite/test/functionalities/nested_alias/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.c create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.core create mode 100755 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/altmain.out create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.core create mode 100755 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/i386.out create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/main.c create mode 100755 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/make-core.sh create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core create mode 100755 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core create mode 100755 packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp create mode 100644 packages/Python/lldbsuite/test/functionalities/ptr_refs/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/ptr_refs/TestPtrRefs.py create mode 100644 packages/Python/lldbsuite/test/functionalities/ptr_refs/main.c create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/basic/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/basic/TestTsanBasic.py create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/basic/main.c create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/TestTsanCPPGlobalLocation.py create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/main.cpp create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/global_location/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/global_location/TestTsanGlobalLocation.py create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/global_location/main.c create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/multiple/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/multiple/TestTsanMultiple.py create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/multiple/main.m create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/TestTsanThreadLeak.py create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/main.c create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/TestTsanThreadNumbers.py create mode 100644 packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/main.c create mode 100644 packages/Python/lldbsuite/test/functionalities/unwind/ehframe/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/unwind/ehframe/TestEhFrameUnwind.py create mode 100644 packages/Python/lldbsuite/test/functionalities/unwind/ehframe/main.c create mode 100644 packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/watchpoint_command.py create mode 100644 packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile create mode 100644 packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py create mode 100644 packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c create mode 100644 packages/Python/lldbsuite/test/help/TestApropos.py create mode 100644 packages/Python/lldbsuite/test/issue_verification/TestInvalidDecorator.py.park delete mode 100644 packages/Python/lldbsuite/test/lang/c/inlines/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py delete mode 100644 packages/Python/lldbsuite/test/lang/c/inlines/inlines.c delete mode 100644 packages/Python/lldbsuite/test/lang/c/inlines/inlines.h create mode 100644 packages/Python/lldbsuite/test/lang/c/inlines/main.c create mode 100644 packages/Python/lldbsuite/test/lang/c/step-target/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py create mode 100644 packages/Python/lldbsuite/test/lang/c/step-target/main.c create mode 100644 packages/Python/lldbsuite/test/lang/c/unions/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/c/unions/TestUnionMembers.py create mode 100644 packages/Python/lldbsuite/test/lang/c/unions/main.c create mode 100644 packages/Python/lldbsuite/test/lang/cpp/const_this/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/const_this/TestConstThis.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/const_this/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/extern_c/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/extern_c/TestExternCSymbols.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/extern_c/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/gmodules/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/gmodules/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/gmodules/pch.h create mode 100644 packages/Python/lldbsuite/test/lang/cpp/inlines/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/inlines/TestInlines.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/inlines/inlines.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/inlines/inlines.h create mode 100644 packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/lambdas/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/TestNamespaceDefinitions.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/a.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/a.mk create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/b.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/b.mk create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/foo.h create mode 100644 packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/printf/TestPrintf.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/printf/main.cpp delete mode 100644 packages/Python/lldbsuite/test/lang/cpp/rdar12991846/Makefile delete mode 100644 packages/Python/lldbsuite/test/lang/cpp/rdar12991846/TestRdar12991846.py delete mode 100644 packages/Python/lldbsuite/test/lang/cpp/rdar12991846/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/template/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/template/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/cpp/unicode-literals/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py create mode 100644 packages/Python/lldbsuite/test/lang/cpp/unicode-literals/main.cpp create mode 100644 packages/Python/lldbsuite/test/lang/objc/bitfield_ivars/TestBitfieldIvars.py create mode 100644 packages/Python/lldbsuite/test/lang/objc/bitfield_ivars/main.m create mode 100644 packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/Makefile create mode 100644 packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/TestObjCSingleEntryDictionary.py create mode 100644 packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/main.m create mode 100644 packages/Python/lldbsuite/test/lang/objc/variadic_methods/TestVariadicMethods.py create mode 100644 packages/Python/lldbsuite/test/lang/objc/variadic_methods/main.m create mode 100644 packages/Python/lldbsuite/test/lldbplatform.py create mode 100644 packages/Python/lldbsuite/test/macosx/nslog/Makefile create mode 100644 packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py create mode 100644 packages/Python/lldbsuite/test/macosx/nslog/main.m create mode 100644 packages/Python/lldbsuite/test/plugins/builder_linux.py delete mode 100644 packages/Python/lldbsuite/test/plugins/builder_linux2.py create mode 100644 packages/Python/lldbsuite/test/python_api/frame/get-variables/Makefile create mode 100644 packages/Python/lldbsuite/test/python_api/frame/get-variables/TestGetVariables.py create mode 100644 packages/Python/lldbsuite/test/python_api/frame/get-variables/main.c create mode 100644 packages/Python/lldbsuite/test/python_api/symbol-context/two-files/Makefile create mode 100644 packages/Python/lldbsuite/test/python_api/symbol-context/two-files/TestSymbolContextTwoFiles.py create mode 100644 packages/Python/lldbsuite/test/python_api/symbol-context/two-files/decls.h create mode 100644 packages/Python/lldbsuite/test/python_api/symbol-context/two-files/file1.cpp create mode 100644 packages/Python/lldbsuite/test/python_api/symbol-context/two-files/file2.cpp delete mode 100644 packages/Python/lldbsuite/test/result_formatter.py create mode 100644 packages/Python/lldbsuite/test/test_runner/__init__.py delete mode 100644 packages/Python/lldbsuite/test/test_runner/lib/lldb_utils.py delete mode 100644 packages/Python/lldbsuite/test/test_runner/lib/process_control.py create mode 100644 packages/Python/lldbsuite/test/test_runner/process_control.py create mode 100644 packages/Python/lldbsuite/test/test_runner/test/__init__.py delete mode 100755 packages/Python/lldbsuite/test/test_runner/test/process_control_tests.py create mode 100755 packages/Python/lldbsuite/test/test_runner/test/test_process_control.py create mode 100644 packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/Makefile create mode 100644 packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/TestMiThreadInfo.py create mode 100644 packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/test_threadinfo.cpp delete mode 100644 packages/Python/lldbsuite/test/xunit_formatter.py create mode 100644 packages/Python/lldbsuite/test_event/__init__.py create mode 100644 packages/Python/lldbsuite/test_event/build_exception.py create mode 100644 packages/Python/lldbsuite/test_event/dotest_channels.py create mode 100644 packages/Python/lldbsuite/test_event/event_builder.py create mode 100644 packages/Python/lldbsuite/test_event/formatter/__init__.py create mode 100644 packages/Python/lldbsuite/test_event/formatter/curses.py create mode 100644 packages/Python/lldbsuite/test_event/formatter/dump_formatter.py create mode 100644 packages/Python/lldbsuite/test_event/formatter/pickled.py create mode 100644 packages/Python/lldbsuite/test_event/formatter/results_formatter.py create mode 100644 packages/Python/lldbsuite/test_event/formatter/xunit.py create mode 100644 packages/Python/lldbsuite/test_event/test/resources/invalid_decorator/TestInvalidDecorator.py create mode 100644 packages/Python/lldbsuite/test_event/test/src/TestCatchInvalidDecorator.py create mode 100644 packages/Python/lldbsuite/test_event/test/src/event_collector.py (limited to 'packages/Python') diff --git a/packages/Python/lldbsuite/support/encoded_file.py b/packages/Python/lldbsuite/support/encoded_file.py new file mode 100644 index 000000000000..7581564f7e3a --- /dev/null +++ b/packages/Python/lldbsuite/support/encoded_file.py @@ -0,0 +1,48 @@ +""" + The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. + +Prepares language bindings for LLDB build process. Run with --help +to see a description of the supported command line arguments. +""" + +# Python modules: +import io + +# Third party modules +import six + +def _encoded_read(old_read, encoding): + def impl(size): + result = old_read(size) + # If this is Python 2 then we need to convert the resulting `unicode` back + # into a `str` before returning + if six.PY2: + result = result.encode(encoding) + return result + return impl + +def _encoded_write(old_write, encoding): + def impl(s): + # If we were asked to write a `str` (in Py2) or a `bytes` (in Py3) decode it + # as unicode before attempting to write. + if isinstance(s, six.binary_type): + s = s.decode(encoding) + return old_write(s) + return impl + +''' +Create a Text I/O file object that can be written to with either unicode strings or byte strings +under Python 2 and Python 3, and automatically encodes and decodes as necessary to return the +native string type for the current Python version +''' +def open(file, encoding, mode='r', buffering=-1, errors=None, newline=None, closefd=True): + wrapped_file = io.open(file, mode=mode, buffering=buffering, encoding=encoding, + errors=errors, newline=newline, closefd=closefd) + new_read = _encoded_read(getattr(wrapped_file, 'read'), encoding) + new_write = _encoded_write(getattr(wrapped_file, 'write'), encoding) + setattr(wrapped_file, 'read', new_read) + setattr(wrapped_file, 'write', new_write) + return wrapped_file diff --git a/packages/Python/lldbsuite/support/funcutils.py b/packages/Python/lldbsuite/support/funcutils.py new file mode 100644 index 000000000000..53dd1fb370ba --- /dev/null +++ b/packages/Python/lldbsuite/support/funcutils.py @@ -0,0 +1,16 @@ +from __future__ import print_function +from __future__ import absolute_import + +# System modules +import inspect + +# Third-party modules + +# LLDB modules + +def requires_self(func): + func_argc = len(inspect.getargspec(func).args) + if func_argc == 0 or (getattr(func,'im_self', None) is not None) or (hasattr(func, '__self__')): + return False + else: + return True diff --git a/packages/Python/lldbsuite/support/gmodules.py b/packages/Python/lldbsuite/support/gmodules.py new file mode 100644 index 000000000000..4f2fd9643b14 --- /dev/null +++ b/packages/Python/lldbsuite/support/gmodules.py @@ -0,0 +1,30 @@ +from __future__ import absolute_import +from __future__ import print_function + +# System modules +import os +import re + + +GMODULES_SUPPORT_MAP = {} +GMODULES_HELP_REGEX = re.compile(r"\s-gmodules\s") + + +def is_compiler_clang_with_gmodules(compiler_path): + # Before computing the result, check if we already have it cached. + if compiler_path in GMODULES_SUPPORT_MAP: + return GMODULES_SUPPORT_MAP[compiler_path] + + def _gmodules_supported_internal(): + compiler = os.path.basename(compiler_path) + if "clang" not in compiler: + return False + else: + # Check the compiler help for the -gmodules option. + clang_help = os.popen("%s --help" % compiler_path).read() + return GMODULES_HELP_REGEX.search(clang_help, re.DOTALL) is not None + + GMODULES_SUPPORT_MAP[compiler_path] = _gmodules_supported_internal() + return GMODULES_SUPPORT_MAP[compiler_path] + + diff --git a/packages/Python/lldbsuite/support/optional_with.py b/packages/Python/lldbsuite/support/optional_with.py new file mode 100644 index 000000000000..41342288bc6a --- /dev/null +++ b/packages/Python/lldbsuite/support/optional_with.py @@ -0,0 +1,56 @@ +# ==================================================================== +# Provides a with-style resource handler for optionally-None resources +# ==================================================================== + +class optional_with(object): + # pylint: disable=too-few-public-methods + # This is a wrapper - it is not meant to provide any extra methods. + """Provides a wrapper for objects supporting "with", allowing None. + + This lets a user use the "with object" syntax for resource usage + (e.g. locks) even when the wrapped with object is None. + + e.g. + + wrapped_lock = optional_with(thread.Lock()) + with wrapped_lock: + # Do something while the lock is obtained. + pass + + might_be_none = None + wrapped_none = optional_with(might_be_none) + with wrapped_none: + # This code here still works. + pass + + This prevents having to write code like this when + a lock is optional: + + if lock: + lock.acquire() + + try: + code_fragment_always_run() + finally: + if lock: + lock.release() + + And I'd posit it is safer, as it becomes impossible to + forget the try/finally using optional_with(), since + the with syntax can be used. + """ + def __init__(self, wrapped_object): + self.wrapped_object = wrapped_object + + def __enter__(self): + if self.wrapped_object is not None: + return self.wrapped_object.__enter__() + else: + return self + + def __exit__(self, the_type, value, traceback): + if self.wrapped_object is not None: + return self.wrapped_object.__exit__(the_type, value, traceback) + else: + # Don't suppress any exceptions + return False diff --git a/packages/Python/lldbsuite/test/android/platform/TestDefaultCacheLineSize.py b/packages/Python/lldbsuite/test/android/platform/TestDefaultCacheLineSize.py index b925afe1b70c..2b6ac1818de7 100644 --- a/packages/Python/lldbsuite/test/android/platform/TestDefaultCacheLineSize.py +++ b/packages/Python/lldbsuite/test/android/platform/TestDefaultCacheLineSize.py @@ -8,8 +8,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DefaultCacheLineSizeTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/api/check_public_api_headers/TestPublicAPIHeaders.py b/packages/Python/lldbsuite/test/api/check_public_api_headers/TestPublicAPIHeaders.py index 0d0507f1d70c..0ed2df3ceab1 100644 --- a/packages/Python/lldbsuite/test/api/check_public_api_headers/TestPublicAPIHeaders.py +++ b/packages/Python/lldbsuite/test/api/check_public_api_headers/TestPublicAPIHeaders.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, re +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SBDirCheckerCase(TestBase): diff --git a/packages/Python/lldbsuite/test/api/listeners/Makefile b/packages/Python/lldbsuite/test/api/listeners/Makefile new file mode 100644 index 000000000000..fbedeab4cb9b --- /dev/null +++ b/packages/Python/lldbsuite/test/api/listeners/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules + diff --git a/packages/Python/lldbsuite/test/api/listeners/TestListener.py b/packages/Python/lldbsuite/test/api/listeners/TestListener.py new file mode 100644 index 000000000000..bd8c204e78cb --- /dev/null +++ b/packages/Python/lldbsuite/test/api/listeners/TestListener.py @@ -0,0 +1,55 @@ +""" +Test that we can listen to modules loaded events. +""" + +from __future__ import print_function + +import copy +import os +import time + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +import six + +class ListenToModuleLoadedEvents (TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.build() + + def test_receiving_breakpoint_added (self): + """Test that we get breakpoint added events, waiting on event classes on the debugger""" + + my_listener = lldb.SBListener("test_listener") + + my_listener.StartListeningForEventClass(self.dbg, lldb.SBTarget.GetBroadcasterClassName(), lldb.SBTarget.eBroadcastBitBreakpointChanged) + + exe = os.path.join (os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + + bkpt = target.BreakpointCreateByName("main") + + event = lldb.SBEvent() + my_listener.WaitForEvent(1, event) + + self.assertTrue(event.IsValid(), "Got a valid event.") + self.assertTrue(lldb.SBBreakpoint.EventIsBreakpointEvent(event), "It is a breakpoint event.") + self.assertTrue(lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) == lldb.eBreakpointEventTypeAdded, "It is a breakpoint added event.") + self.assertTrue(bkpt == lldb.SBBreakpoint.GetBreakpointFromEvent(event), "It is our breakpoint.") + + # Now make sure if we stop listening for events we don't get them: + + my_listener.StopListeningForEventClass(self.dbg, lldb.SBTarget.GetBroadcasterClassName(), lldb.SBTarget.eBroadcastBitBreakpointChanged) + my_listener.StopListeningForEvents(target.GetBroadcaster(), lldb.SBTarget.eBroadcastBitBreakpointChanged) + + bkpt2 = target.BreakpointCreateByName("main") + my_listener.WaitForEvent(1, event) + self.assertTrue(not event.IsValid(), "We don't get events we aren't listening to.") diff --git a/packages/Python/lldbsuite/test/api/listeners/main.c b/packages/Python/lldbsuite/test/api/listeners/main.c new file mode 100644 index 000000000000..f930e5119158 --- /dev/null +++ b/packages/Python/lldbsuite/test/api/listeners/main.c @@ -0,0 +1,7 @@ +#include + +int +main() +{ + printf ("Hello there.\n"); +} diff --git a/packages/Python/lldbsuite/test/api/multiple-debuggers/TestMultipleDebuggers.py b/packages/Python/lldbsuite/test/api/multiple-debuggers/TestMultipleDebuggers.py index 67dca2273d8a..ca2b986ce740 100644 --- a/packages/Python/lldbsuite/test/api/multiple-debuggers/TestMultipleDebuggers.py +++ b/packages/Python/lldbsuite/test/api/multiple-debuggers/TestMultipleDebuggers.py @@ -5,21 +5,21 @@ from __future__ import print_function import os, re -from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import lldb import subprocess +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + class TestMultipleSimultaneousDebuggers(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIfi386 @skipIfNoSBHeaders - @expectedFailureFreeBSD("llvm.org/pr20282") - @expectedFailureLinux("llvm.org/pr20282") - @expectedFailureWindows # Test crashes @expectedFlakeyDarwin() + @expectedFailureAll(archs="i[3-6]86", bugnumber="multi-process-driver.cpp creates an x64 target") + @expectedFailureAll(oslist=["windows", "linux", "freebsd"], bugnumber="llvm.org/pr20282") def test_multiple_debuggers(self): env = {self.dylibPath : self.getLLDBLibraryEnvVal()} diff --git a/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py b/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py index 9963cf23a8c6..7959bb73de02 100644 --- a/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py +++ b/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, re +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil import subprocess class SBBreakpointCallbackCase(TestBase): @@ -36,7 +37,6 @@ class SBBreakpointCallbackCase(TestBase): @skipIfNoSBHeaders @skipIfWindows # clang-cl does not support throw or catch (llvm.org/pr24538) @expectedFlakeyFreeBSD - @expectedFlakeyLinux # Driver occasionally returns '1' as exit status @expectedFailureAll("llvm.org/pr23139", oslist=["linux"], compiler="gcc", compiler_version=[">=","4.9"], archs=["x86_64"]) def test_sb_api_listener_event_process_state(self): """ Test that a registered SBListener receives events when a process @@ -51,7 +51,7 @@ class SBBreakpointCallbackCase(TestBase): @skipIfNoSBHeaders @skipIfWindows # clang-cl does not support throw or catch (llvm.org/pr24538) @expectedFlakeyFreeBSD - @expectedFailureLinux + @expectedFailureAll(oslist=["linux"]) def test_sb_api_listener_resume(self): """ Test that a process can be resumed from a non-main thread. """ self.build_and_test('driver.cpp listener_test.cpp test_listener_resume.cpp', diff --git a/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_process_state.cpp b/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_process_state.cpp index 0a698d1081d4..a79c5cb2a08b 100644 --- a/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_process_state.cpp +++ b/packages/Python/lldbsuite/test/api/multithreaded/test_listener_event_process_state.cpp @@ -18,7 +18,6 @@ using namespace std; // listener thread control extern atomic g_done; -multithreaded_queue g_thread_descriptions; multithreaded_queue g_frame_functions; extern SBListener g_listener; @@ -30,26 +29,21 @@ void listener_func() { if (got_event) { if (!event.IsValid()) throw Exception("event is not valid in listener thread"); - - // send process description - SBProcess process = SBProcess::GetProcessFromEvent(event); - SBStream description; - - for (int i = 0; i < process.GetNumThreads(); ++i) { - // send each thread description - description.Clear(); - SBThread thread = process.GetThreadAtIndex(i); - thread.GetDescription(description); - g_thread_descriptions.push(description.GetData()); - - // send each frame function name - uint32_t num_frames = thread.GetNumFrames(); - for(int j = 0; j < num_frames; ++j) { - const char* function_name = thread.GetFrameAtIndex(j).GetSymbol().GetName(); - if (function_name) - g_frame_functions.push(function_name); + // send process description + SBProcess process = SBProcess::GetProcessFromEvent(event); + SBStream description; + + for (int i = 0; i < process.GetNumThreads(); ++i) { + // send each thread description + SBThread thread = process.GetThreadAtIndex(i); + // send each frame function name + uint32_t num_frames = thread.GetNumFrames(); + for(int j = 0; j < num_frames; ++j) { + const char* function_name = thread.GetFrameAtIndex(j).GetSymbol().GetName(); + if (function_name) + g_frame_functions.push(string(function_name)); + } } - } } } } @@ -57,12 +51,8 @@ void listener_func() { void check_listener(SBDebugger &dbg) { // check thread description bool got_description = false; - string desc = g_thread_descriptions.pop(5, got_description); - if (!got_description) - throw Exception("Expected at least one thread description string"); - - // check at least one frame has a function name - desc = g_frame_functions.pop(5, got_description); - if (!got_description) - throw Exception("Expected at least one frame function name string"); + string func_name = g_frame_functions.pop(5, got_description); + + if(got_description == false) + throw Exception("Expected at least one frame function"); } diff --git a/packages/Python/lldbsuite/test/arm_emulation/TestEmulations.py b/packages/Python/lldbsuite/test/arm_emulation/TestEmulations.py index 8a78d21e7978..d502b6dfca8a 100644 --- a/packages/Python/lldbsuite/test/arm_emulation/TestEmulations.py +++ b/packages/Python/lldbsuite/test/arm_emulation/TestEmulations.py @@ -8,7 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ARMEmulationTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/benchmarks/continue/TestBenchmarkContinue.py b/packages/Python/lldbsuite/test/benchmarks/continue/TestBenchmarkContinue.py index 25ca13a3bfd9..f7c274522f9b 100644 --- a/packages/Python/lldbsuite/test/benchmarks/continue/TestBenchmarkContinue.py +++ b/packages/Python/lldbsuite/test/benchmarks/continue/TestBenchmarkContinue.py @@ -8,8 +8,10 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbbench import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestBenchmarkContinue(BenchBase): diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py index a18cb2a64c76..8a0c044147a0 100644 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py +++ b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py @@ -6,8 +6,10 @@ from __future__ import print_function import os, sys import lldb -from lldbsuite.test import configuration +from lldbsuite.test.decorators import * from lldbsuite.test.lldbbench import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil def is_exe(fpath): """Returns true if fpath is an executable.""" @@ -40,7 +42,7 @@ class DisassembleDriverMainLoop(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_run_lldb_then_gdb(self): """Test disassembly on a large function with lldb vs. gdb.""" print() @@ -56,7 +58,7 @@ class DisassembleDriverMainLoop(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_run_gdb_then_lldb(self): """Test disassembly on a large function with lldb vs. gdb.""" print() diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py index b7b07090959e..f8e3d94b6577 100644 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py +++ b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, sys import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbbench import * -from lldbsuite.test import configuration +from lldbsuite.test.lldbtest import * class AttachThenDisassemblyBench(BenchBase): diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py index 745e7b6a8c3b..618aac7eafcd 100644 --- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py +++ b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py @@ -6,8 +6,11 @@ from __future__ import print_function import os, sys import lldb -from lldbsuite.test import configuration +from lldbsuite.test.decorators import * from lldbsuite.test.lldbbench import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import configuration +from lldbsuite.test import lldbutil class XCode41Vs42GDBDisassembly(BenchBase): @@ -25,7 +28,7 @@ class XCode41Vs42GDBDisassembly(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_run_41_then_42(self): """Test disassembly on a large function with 4.1 vs. 4.2's gdb.""" print() @@ -39,7 +42,7 @@ class XCode41Vs42GDBDisassembly(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_run_42_then_41(self): """Test disassembly on a large function with 4.1 vs. 4.2's gdb.""" print() diff --git a/packages/Python/lldbsuite/test/benchmarks/expression/TestExpressionCmd.py b/packages/Python/lldbsuite/test/benchmarks/expression/TestExpressionCmd.py index abf45147d636..68d2bd9793e1 100644 --- a/packages/Python/lldbsuite/test/benchmarks/expression/TestExpressionCmd.py +++ b/packages/Python/lldbsuite/test/benchmarks/expression/TestExpressionCmd.py @@ -6,8 +6,11 @@ from __future__ import print_function import os, sys import lldb -from lldbsuite.test import configuration +from lldbsuite.test.decorators import * from lldbsuite.test.lldbbench import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import configuration +from lldbsuite.test import lldbutil class ExpressionEvaluationCase(BenchBase): @@ -20,7 +23,7 @@ class ExpressionEvaluationCase(BenchBase): self.count = 25 @benchmarks_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_expr_cmd(self): """Test lldb's expression commands and collect statistics.""" self.build() diff --git a/packages/Python/lldbsuite/test/benchmarks/expression/TestRepeatedExprs.py b/packages/Python/lldbsuite/test/benchmarks/expression/TestRepeatedExprs.py index e5cada3563fa..2ad409e53b07 100644 --- a/packages/Python/lldbsuite/test/benchmarks/expression/TestRepeatedExprs.py +++ b/packages/Python/lldbsuite/test/benchmarks/expression/TestRepeatedExprs.py @@ -6,8 +6,11 @@ from __future__ import print_function import os, sys import lldb +from lldbsuite.test.lldbbench import BenchBase +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * from lldbsuite.test import configuration -from lldbsuite.test.lldbbench import * +from lldbsuite.test import lldbutil class RepeatedExprsCase(BenchBase): @@ -22,7 +25,7 @@ class RepeatedExprsCase(BenchBase): self.count = 100 @benchmarks_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_compare_lldb_to_gdb(self): """Test repeated expressions with lldb vs. gdb.""" self.build() diff --git a/packages/Python/lldbsuite/test/benchmarks/frame_variable/TestFrameVariableResponse.py b/packages/Python/lldbsuite/test/benchmarks/frame_variable/TestFrameVariableResponse.py index 5fdf05763fd1..9f5835297379 100644 --- a/packages/Python/lldbsuite/test/benchmarks/frame_variable/TestFrameVariableResponse.py +++ b/packages/Python/lldbsuite/test/benchmarks/frame_variable/TestFrameVariableResponse.py @@ -8,6 +8,7 @@ import os, sys import lldb from lldbsuite.test import configuration from lldbsuite.test import lldbtest_config +from lldbsuite.test.decorators import * from lldbsuite.test.lldbbench import * class FrameVariableResponseBench(BenchBase): @@ -22,7 +23,7 @@ class FrameVariableResponseBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_startup_delay(self): """Test response time for the 'frame variable' command.""" print() diff --git a/packages/Python/lldbsuite/test/benchmarks/libcxxlist/TestBenchmarkLibcxxList.py b/packages/Python/lldbsuite/test/benchmarks/libcxxlist/TestBenchmarkLibcxxList.py index 7606bd1d3e8b..12e23e956943 100644 --- a/packages/Python/lldbsuite/test/benchmarks/libcxxlist/TestBenchmarkLibcxxList.py +++ b/packages/Python/lldbsuite/test/benchmarks/libcxxlist/TestBenchmarkLibcxxList.py @@ -8,8 +8,10 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbbench import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestBenchmarkLibcxxList(BenchBase): diff --git a/packages/Python/lldbsuite/test/benchmarks/libcxxmap/TestBenchmarkLibcxxMap.py b/packages/Python/lldbsuite/test/benchmarks/libcxxmap/TestBenchmarkLibcxxMap.py index 806bc0ee29e2..4466cd083ca3 100644 --- a/packages/Python/lldbsuite/test/benchmarks/libcxxmap/TestBenchmarkLibcxxMap.py +++ b/packages/Python/lldbsuite/test/benchmarks/libcxxmap/TestBenchmarkLibcxxMap.py @@ -9,7 +9,9 @@ from __future__ import print_function import os, time import lldb from lldbsuite.test.lldbbench import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestBenchmarkLibcxxMap(BenchBase): diff --git a/packages/Python/lldbsuite/test/benchmarks/startup/TestStartupDelays.py b/packages/Python/lldbsuite/test/benchmarks/startup/TestStartupDelays.py index a215721ed52f..9d2356ab54f9 100644 --- a/packages/Python/lldbsuite/test/benchmarks/startup/TestStartupDelays.py +++ b/packages/Python/lldbsuite/test/benchmarks/startup/TestStartupDelays.py @@ -8,6 +8,7 @@ import os, sys import lldb from lldbsuite.test import configuration from lldbsuite.test import lldbtest_config +from lldbsuite.test.decorators import * from lldbsuite.test.lldbbench import * class StartupDelaysBench(BenchBase): @@ -27,7 +28,7 @@ class StartupDelaysBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_startup_delay(self): """Test start up delays creating a target, setting a breakpoint, and run to breakpoint stop.""" print() diff --git a/packages/Python/lldbsuite/test/benchmarks/stepping/TestSteppingSpeed.py b/packages/Python/lldbsuite/test/benchmarks/stepping/TestSteppingSpeed.py index 14738a978e86..3ab760d4abe8 100644 --- a/packages/Python/lldbsuite/test/benchmarks/stepping/TestSteppingSpeed.py +++ b/packages/Python/lldbsuite/test/benchmarks/stepping/TestSteppingSpeed.py @@ -7,6 +7,9 @@ import lldb from lldbsuite.test import configuration from lldbsuite.test import lldbtest_config from lldbsuite.test.lldbbench import * +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SteppingSpeedBench(BenchBase): @@ -23,7 +26,7 @@ class SteppingSpeedBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_run_lldb_steppings(self): """Test lldb steppings on a large executable.""" print() diff --git a/packages/Python/lldbsuite/test/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py b/packages/Python/lldbsuite/test/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py index 731eb13bbcfb..3106c4511f58 100644 --- a/packages/Python/lldbsuite/test/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py +++ b/packages/Python/lldbsuite/test/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py @@ -6,8 +6,11 @@ from __future__ import print_function import os, sys import lldb -from lldbsuite.test import configuration from lldbsuite.test.lldbbench import * +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import configuration +from lldbsuite.test import lldbutil class CompileRunToBreakpointBench(BenchBase): @@ -24,7 +27,7 @@ class CompileRunToBreakpointBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_run_lldb_then_gdb(self): """Benchmark turnaround time with lldb vs. gdb.""" print() diff --git a/packages/Python/lldbsuite/test/configuration.py b/packages/Python/lldbsuite/test/configuration.py index 69ed9fc32e2b..d797b17c164e 100644 --- a/packages/Python/lldbsuite/test/configuration.py +++ b/packages/Python/lldbsuite/test/configuration.py @@ -100,6 +100,15 @@ regexp = None # run. Use '-s session-dir-name' to specify a specific dir name. sdir_name = None +# Valid options: +# f - test file name (without extension) +# n - test class name +# m - test method name +# a - architecture +# c - compiler path +# The default is to write all fields. +session_file_format = 'fnmac' + # Set this flag if there is any session info dumped during the test run. sdir_has_content = False diff --git a/packages/Python/lldbsuite/test/curses_results.py b/packages/Python/lldbsuite/test/curses_results.py deleted file mode 100644 index 9d480b946ea2..000000000000 --- a/packages/Python/lldbsuite/test/curses_results.py +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/env python - -""" - The LLVM Compiler Infrastructure - - This file is distributed under the University of Illinois Open Source - License. See LICENSE.TXT for details. - -Configuration options for lldbtest.py set by dotest.py during initialization -""" - -from __future__ import print_function -from __future__ import absolute_import - -# System modules -import curses -import datetime -import math -import sys -import time - -# Third-party modules - -# LLDB modules -from . import lldbcurses -from . import result_formatter -from .result_formatter import EventBuilder - - -class Curses(result_formatter.ResultsFormatter): - """Receives live results from tests that are running and reports them to the terminal in a curses GUI""" - - def __init__(self, out_file, options): - # Initialize the parent - super(Curses, self).__init__(out_file, options) - self.using_terminal = True - self.have_curses = True - self.initialize_event = None - self.jobs = [None] * 64 - self.job_tests = [None] * 64 - self.results = list() - try: - self.main_window = lldbcurses.intialize_curses() - self.main_window.add_key_action('\t', self.main_window.select_next_first_responder, "Switch between views that can respond to keyboard input") - self.main_window.refresh() - self.job_panel = None - self.results_panel = None - self.status_panel = None - self.info_panel = None - self.hide_status_list = list() - self.start_time = time.time() - except: - self.have_curses = False - lldbcurses.terminate_curses() - self.using_terminal = False - print("Unexpected error:", sys.exc_info()[0]) - raise - - self.line_dict = dict() - # self.events_file = open("/tmp/events.txt", "w") - # self.formatters = list() - # if tee_results_formatter: - # self.formatters.append(tee_results_formatter) - - def status_to_short_str(self, status): - if status == EventBuilder.STATUS_SUCCESS: - return '.' - elif status == EventBuilder.STATUS_FAILURE: - return 'F' - elif status == EventBuilder.STATUS_UNEXPECTED_SUCCESS: - return '?' - elif status == EventBuilder.STATUS_EXPECTED_FAILURE: - return 'X' - elif status == EventBuilder.STATUS_SKIP: - return 'S' - elif status == EventBuilder.STATUS_ERROR: - return 'E' - else: - return status - - def show_info_panel(self): - selected_idx = self.results_panel.get_selected_idx() - if selected_idx >= 0 and selected_idx < len(self.results): - if self.info_panel is None: - info_frame = self.results_panel.get_contained_rect(top_inset=10, left_inset=10, right_inset=10, height=30) - self.info_panel = lldbcurses.BoxedPanel(info_frame, "Result Details") - # Add a key action for any key that will hide this panel when any key is pressed - self.info_panel.add_key_action(-1, self.hide_info_panel, 'Hide the info panel') - self.info_panel.top() - else: - self.info_panel.show() - - self.main_window.push_first_responder(self.info_panel) - test_start = self.results[selected_idx][0] - test_result = self.results[selected_idx][1] - self.info_panel.set_line(0, "File: %s" % (test_start['test_filename'])) - self.info_panel.set_line(1, "Test: %s.%s" % (test_start['test_class'], test_start['test_name'])) - self.info_panel.set_line(2, "Time: %s" % (test_result['elapsed_time'])) - self.info_panel.set_line(3, "Status: %s" % (test_result['status'])) - - def hide_info_panel(self): - self.main_window.pop_first_responder(self.info_panel) - self.info_panel.hide() - self.main_window.refresh() - - def toggle_status(self, status): - if status: - # Toggle showing and hiding results whose status matches "status" in "Results" window - if status in self.hide_status_list: - self.hide_status_list.remove(status) - else: - self.hide_status_list.append(status) - self.update_results() - - def update_results(self, update=True): - '''Called after a category of test have been show/hidden to update the results list with - what the user desires to see.''' - self.results_panel.clear(update=False) - for result in self.results: - test_result = result[1] - status = test_result['status'] - if status in self.hide_status_list: - continue - name = test_result['test_class'] + '.' + test_result['test_name'] - self.results_panel.append_line('%s (%6.2f sec) %s' % (self.status_to_short_str(status), test_result['elapsed_time'], name)) - if update: - self.main_window.refresh() - - def handle_event(self, test_event): - with self.lock: - super(Curses, self).handle_event(test_event) - # for formatter in self.formatters: - # formatter.process_event(test_event) - if self.have_curses: - worker_index = -1 - if 'worker_index' in test_event: - worker_index = test_event['worker_index'] - if 'event' in test_event: - check_for_one_key = True - #print(str(test_event), file=self.events_file) - event = test_event['event'] - if self.status_panel: - self.status_panel.update_status('time', str(datetime.timedelta(seconds=math.floor(time.time() - self.start_time)))) - if event == 'test_start': - name = test_event['test_class'] + '.' + test_event['test_name'] - self.job_tests[worker_index] = test_event - if 'pid' in test_event: - line = 'pid: %5d ' % (test_event['pid']) + name - else: - line = name - self.job_panel.set_line(worker_index, line) - self.main_window.refresh() - elif event == 'test_result': - status = test_event['status'] - self.status_panel.increment_status(status) - if 'pid' in test_event: - line = 'pid: %5d ' % (test_event['pid']) - else: - line = '' - self.job_panel.set_line(worker_index, line) - name = test_event['test_class'] + '.' + test_event['test_name'] - elapsed_time = test_event['event_time'] - self.job_tests[worker_index]['event_time'] - if not status in self.hide_status_list: - self.results_panel.append_line('%s (%6.2f sec) %s' % (self.status_to_short_str(status), elapsed_time, name)) - self.main_window.refresh() - # Append the result pairs - test_event['elapsed_time'] = elapsed_time - self.results.append([self.job_tests[worker_index], test_event]) - self.job_tests[worker_index] = '' - elif event == 'job_begin': - self.jobs[worker_index] = test_event - if 'pid' in test_event: - line = 'pid: %5d ' % (test_event['pid']) - else: - line = '' - self.job_panel.set_line(worker_index, line) - elif event == 'job_end': - self.jobs[worker_index] = '' - self.job_panel.set_line(worker_index, '') - elif event == 'initialize': - self.initialize_event = test_event - num_jobs = test_event['worker_count'] - job_frame = self.main_window.get_contained_rect(height=num_jobs+2) - results_frame = self.main_window.get_contained_rect(top_inset=num_jobs+2, bottom_inset=1) - status_frame = self.main_window.get_contained_rect(height=1, top_inset=self.main_window.get_size().h-1) - self.job_panel = lldbcurses.BoxedPanel(frame=job_frame, title="Jobs") - self.results_panel = lldbcurses.BoxedPanel(frame=results_frame, title="Results") - - self.results_panel.add_key_action(curses.KEY_UP, self.results_panel.select_prev , "Select the previous list entry") - self.results_panel.add_key_action(curses.KEY_DOWN, self.results_panel.select_next , "Select the next list entry") - self.results_panel.add_key_action(curses.KEY_HOME, self.results_panel.scroll_begin , "Scroll to the start of the list") - self.results_panel.add_key_action(curses.KEY_END, self.results_panel.scroll_end , "Scroll to the end of the list") - self.results_panel.add_key_action(curses.KEY_ENTER, self.show_info_panel , "Display info for the selected result item") - self.results_panel.add_key_action('.', lambda : self.toggle_status(EventBuilder.STATUS_SUCCESS) , "Toggle showing/hiding tests whose status is 'success'") - self.results_panel.add_key_action('e', lambda : self.toggle_status(EventBuilder.STATUS_ERROR) , "Toggle showing/hiding tests whose status is 'error'") - self.results_panel.add_key_action('f', lambda : self.toggle_status(EventBuilder.STATUS_FAILURE) , "Toggle showing/hiding tests whose status is 'failure'") - self.results_panel.add_key_action('s', lambda : self.toggle_status(EventBuilder.STATUS_SKIP) , "Toggle showing/hiding tests whose status is 'skip'") - self.results_panel.add_key_action('x', lambda : self.toggle_status(EventBuilder.STATUS_EXPECTED_FAILURE) , "Toggle showing/hiding tests whose status is 'expected_failure'") - self.results_panel.add_key_action('?', lambda : self.toggle_status(EventBuilder.STATUS_UNEXPECTED_SUCCESS), "Toggle showing/hiding tests whose status is 'unexpected_success'") - self.status_panel = lldbcurses.StatusPanel(frame=status_frame) - - self.main_window.add_child(self.job_panel) - self.main_window.add_child(self.results_panel) - self.main_window.add_child(self.status_panel) - self.main_window.set_first_responder(self.results_panel) - - self.status_panel.add_status_item(name="time", title="Elapsed", format="%s", width=20, value="0:00:00", update=False) - self.status_panel.add_status_item(name=EventBuilder.STATUS_SUCCESS, title="Success", format="%u", width=20, value=0, update=False) - self.status_panel.add_status_item(name=EventBuilder.STATUS_FAILURE, title="Failure", format="%u", width=20, value=0, update=False) - self.status_panel.add_status_item(name=EventBuilder.STATUS_ERROR, title="Error", format="%u", width=20, value=0, update=False) - self.status_panel.add_status_item(name=EventBuilder.STATUS_SKIP, title="Skipped", format="%u", width=20, value=0, update=True) - self.status_panel.add_status_item(name=EventBuilder.STATUS_EXPECTED_FAILURE, title="Expected Failure", format="%u", width=30, value=0, update=False) - self.status_panel.add_status_item(name=EventBuilder.STATUS_UNEXPECTED_SUCCESS, title="Unexpected Success", format="%u", width=30, value=0, update=False) - self.main_window.refresh() - elif event == 'terminate': - #self.main_window.key_event_loop() - lldbcurses.terminate_curses() - check_for_one_key = False - self.using_terminal = False - # Check for 1 keypress with no delay - - # Check for 1 keypress with no delay - if check_for_one_key: - self.main_window.key_event_loop(0, 1) diff --git a/packages/Python/lldbsuite/test/decorators.py b/packages/Python/lldbsuite/test/decorators.py new file mode 100644 index 000000000000..93e48272c5d3 --- /dev/null +++ b/packages/Python/lldbsuite/test/decorators.py @@ -0,0 +1,524 @@ +from __future__ import absolute_import +from __future__ import print_function + +# System modules +from distutils.version import LooseVersion, StrictVersion +from functools import wraps +import os +import re +import sys +import tempfile + +# Third-party modules +import six +import unittest2 + +# LLDB modules +import use_lldb_suite + +import lldb +from . import configuration +from . import test_categories +from lldbsuite.test_event.event_builder import EventBuilder +from lldbsuite.support import funcutils +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbplatformutil + +class DecorateMode: + Skip, Xfail = range(2) + + +# You can use no_match to reverse the test of the conditional that is used to match keyword +# arguments in the skip / xfail decorators. If oslist=["windows", "linux"] skips windows +# and linux, oslist=no_match(["windows", "linux"]) skips *unless* windows or linux. +class no_match: + def __init__(self, item): + self.item = item + +def _check_expected_version(comparison, expected, actual): + def fn_leq(x,y): return x <= y + def fn_less(x,y): return x < y + def fn_geq(x,y): return x >= y + def fn_greater(x,y): return x > y + def fn_eq(x,y): return x == y + def fn_neq(x,y): return x != y + + op_lookup = { + "==": fn_eq, + "=": fn_eq, + "!=": fn_neq, + "<>": fn_neq, + ">": fn_greater, + "<": fn_less, + ">=": fn_geq, + "<=": fn_leq + } + expected_str = '.'.join([str(x) for x in expected]) + actual_str = '.'.join([str(x) for x in actual]) + + return op_lookup[comparison](LooseVersion(actual_str), LooseVersion(expected_str)) + +def _match_decorator_property(expected, actual): + if actual is None or expected is None: + return True + + if isinstance(expected, no_match): + return not _match_decorator_property(expected.item, actual) + elif isinstance(expected, (re._pattern_type,)+six.string_types): + return re.search(expected, actual) is not None + elif hasattr(expected, "__iter__"): + return any([x is not None and _match_decorator_property(x, actual) for x in expected]) + else: + return expected == actual + +def expectedFailure(expected_fn, bugnumber=None): + def expectedFailure_impl(func): + if isinstance(func, type) and issubclass(func, unittest2.TestCase): + raise Exception("Decorator can only be used to decorate a test method") + @wraps(func) + def wrapper(*args, **kwargs): + self = args[0] + if funcutils.requires_self(expected_fn): + xfail_reason = expected_fn(self) + else: + xfail_reason = expected_fn() + if xfail_reason is not None: + if configuration.results_formatter_object is not None: + # Mark this test as expected to fail. + configuration.results_formatter_object.handle_event( + EventBuilder.event_for_mark_test_expected_failure(self)) + xfail_func = unittest2.expectedFailure(func) + xfail_func(*args, **kwargs) + else: + func(*args, **kwargs) + return wrapper + # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) + # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called + # the first way, the first argument will be the actual function because decorators are + # weird like that. So this is basically a check that says "which syntax was the original + # function decorated with?" + if six.callable(bugnumber): + return expectedFailure_impl(bugnumber) + else: + return expectedFailure_impl + +def skipTestIfFn(expected_fn, bugnumber=None): + def skipTestIfFn_impl(func): + if isinstance(func, type) and issubclass(func, unittest2.TestCase): + raise Exception("@skipTestIfFn can only be used to decorate a test method") + + @wraps(func) + def wrapper(*args, **kwargs): + self = args[0] + if funcutils.requires_self(expected_fn): + reason = expected_fn(self) + else: + reason = expected_fn() + + if reason is not None: + self.skipTest(reason) + else: + func(*args, **kwargs) + return wrapper + + # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) + # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called + # the first way, the first argument will be the actual function because decorators are + # weird like that. So this is basically a check that says "how was the decorator used" + if six.callable(bugnumber): + return skipTestIfFn_impl(bugnumber) + else: + return skipTestIfFn_impl + +def _decorateTest(mode, + bugnumber=None, oslist=None, hostoslist=None, + compiler=None, compiler_version=None, + archs=None, triple=None, + debug_info=None, + swig_version=None, py_version=None, + remote=None): + def fn(self): + skip_for_os = _match_decorator_property(lldbplatform.translate(oslist), self.getPlatform()) + skip_for_hostos = _match_decorator_property(lldbplatform.translate(hostoslist), lldbplatformutil.getHostPlatform()) + skip_for_compiler = _match_decorator_property(compiler, self.getCompiler()) and self.expectedCompilerVersion(compiler_version) + skip_for_arch = _match_decorator_property(archs, self.getArchitecture()) + skip_for_debug_info = _match_decorator_property(debug_info, self.debug_info) + skip_for_triple = _match_decorator_property(triple, lldb.DBG.GetSelectedPlatform().GetTriple()) + skip_for_remote = _match_decorator_property(remote, lldb.remote_platform is not None) + + skip_for_swig_version = (swig_version is None) or (not hasattr(lldb, 'swig_version')) or (_check_expected_version(swig_version[0], swig_version[1], lldb.swig_version)) + skip_for_py_version = (py_version is None) or _check_expected_version(py_version[0], py_version[1], sys.version_info) + + # For the test to be skipped, all specified (e.g. not None) parameters must be True. + # An unspecified parameter means "any", so those are marked skip by default. And we skip + # the final test if all conditions are True. + conditions = [(oslist, skip_for_os, "target o/s"), + (hostoslist, skip_for_hostos, "host o/s"), + (compiler, skip_for_compiler, "compiler or version"), + (archs, skip_for_arch, "architecture"), + (debug_info, skip_for_debug_info, "debug info format"), + (triple, skip_for_triple, "target triple"), + (swig_version, skip_for_swig_version, "swig version"), + (py_version, skip_for_py_version, "python version"), + (remote, skip_for_remote, "platform locality (remote/local)")] + reasons = [] + final_skip_result = True + for this_condition in conditions: + final_skip_result = final_skip_result and this_condition[1] + if this_condition[0] is not None and this_condition[1]: + reasons.append(this_condition[2]) + reason_str = None + if final_skip_result: + mode_str = {DecorateMode.Skip : "skipping", DecorateMode.Xfail : "xfailing"}[mode] + if len(reasons) > 0: + reason_str = ",".join(reasons) + reason_str = "{} due to the following parameter(s): {}".format(mode_str, reason_str) + else: + reason_str = "{} unconditionally" + if bugnumber is not None and not six.callable(bugnumber): + reason_str = reason_str + " [" + str(bugnumber) + "]" + return reason_str + + if mode == DecorateMode.Skip: + return skipTestIfFn(fn, bugnumber) + elif mode == DecorateMode.Xfail: + return expectedFailure(fn, bugnumber) + else: + return None + +# provide a function to xfail on defined oslist, compiler version, and archs +# if none is specified for any argument, that argument won't be checked and thus means for all +# for example, +# @expectedFailureAll, xfail for all platform/compiler/arch, +# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture +# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386 +def expectedFailureAll(bugnumber=None, + oslist=None, hostoslist=None, + compiler=None, compiler_version=None, + archs=None, triple=None, + debug_info=None, + swig_version=None, py_version=None, + remote=None): + return _decorateTest(DecorateMode.Xfail, + bugnumber=bugnumber, + oslist=oslist, hostoslist=hostoslist, + compiler=compiler, compiler_version=compiler_version, + archs=archs, triple=triple, + debug_info=debug_info, + swig_version=swig_version, py_version=py_version, + remote=remote) + + +# provide a function to skip on defined oslist, compiler version, and archs +# if none is specified for any argument, that argument won't be checked and thus means for all +# for example, +# @skipIf, skip for all platform/compiler/arch, +# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture +# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 +def skipIf(bugnumber=None, + oslist=None, hostoslist=None, + compiler=None, compiler_version=None, + archs=None, triple=None, + debug_info=None, + swig_version=None, py_version=None, + remote=None): + return _decorateTest(DecorateMode.Skip, + bugnumber=bugnumber, + oslist=oslist, hostoslist=hostoslist, + compiler=compiler, compiler_version=compiler_version, + archs=archs, triple=triple, + debug_info=debug_info, + swig_version=swig_version, py_version=py_version, + remote=remote) + +def _skip_for_android(reason, api_levels, archs): + def impl(obj): + result = lldbplatformutil.match_android_device(obj.getArchitecture(), valid_archs=archs, valid_api_levels=api_levels) + return reason if result else None + return impl + +def add_test_categories(cat): + """Add test categories to a TestCase method""" + cat = test_categories.validate(cat, True) + def impl(func): + if isinstance(func, type) and issubclass(func, unittest2.TestCase): + raise Exception("@add_test_categories can only be used to decorate a test method") + if hasattr(func, "categories"): + cat.extend(func.categories) + func.categories = cat + return func + + return impl + +def benchmarks_test(func): + """Decorate the item as a benchmarks test.""" + def should_skip_benchmarks_test(): + return "benchmarks test" + + # Mark this function as such to separate them from the regular tests. + result = skipTestIfFn(should_skip_benchmarks_test)(func) + result.__benchmarks_test__ = True + return result + +def no_debug_info_test(func): + """Decorate the item as a test what don't use any debug info. If this annotation is specified + then the test runner won't generate a separate test for each debug info format. """ + if isinstance(func, type) and issubclass(func, unittest2.TestCase): + raise Exception("@no_debug_info_test can only be used to decorate a test method") + @wraps(func) + def wrapper(self, *args, **kwargs): + return func(self, *args, **kwargs) + + # Mark this function as such to separate them from the regular tests. + wrapper.__no_debug_info_test__ = True + return wrapper + +def debugserver_test(func): + """Decorate the item as a debugserver test.""" + def should_skip_debugserver_test(): + return "debugserver tests" if configuration.dont_do_debugserver_test else None + return skipTestIfFn(should_skip_debugserver_test)(func) + +def llgs_test(func): + """Decorate the item as a lldb-server test.""" + def should_skip_llgs_tests(): + return "llgs tests" if configuration.dont_do_llgs_test else None + return skipTestIfFn(should_skip_llgs_tests)(func) + +def not_remote_testsuite_ready(func): + """Decorate the item as a test which is not ready yet for remote testsuite.""" + def is_remote(): + return "Not ready for remote testsuite" if lldb.remote_platform else None + return skipTestIfFn(is_remote)(func) + +def expectedFailureOS(oslist, bugnumber=None, compilers=None, debug_info=None, archs=None): + return expectedFailureAll(oslist=oslist, bugnumber=bugnumber, compiler=compilers, archs=archs, debug_info=debug_info) + +def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None): + # For legacy reasons, we support both "darwin" and "macosx" as OS X triples. + return expectedFailureOS(lldbplatform.darwin_all, bugnumber, compilers, debug_info=debug_info) + +def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None): + """ Mark a test as xfail for Android. + + Arguments: + bugnumber - The LLVM pr associated with the problem. + api_levels - A sequence of numbers specifying the Android API levels + for which a test is expected to fail. None means all API level. + arch - A sequence of architecture names specifying the architectures + for which a test is expected to fail. None means all architectures. + """ + return expectedFailure(_skip_for_android("xfailing on android", api_levels, archs), bugnumber) + +# Flakey tests get two chances to run. If they fail the first time round, the result formatter +# makes sure it is run one more time. +def expectedFlakey(expected_fn, bugnumber=None): + def expectedFailure_impl(func): + @wraps(func) + def wrapper(*args, **kwargs): + self = args[0] + if expected_fn(self): + # Send event marking test as explicitly eligible for rerunning. + if configuration.results_formatter_object is not None: + # Mark this test as rerunnable. + configuration.results_formatter_object.handle_event( + EventBuilder.event_for_mark_test_rerun_eligible(self)) + func(*args, **kwargs) + return wrapper + # Some decorators can be called both with no arguments (e.g. @expectedFailureWindows) + # or with arguments (e.g. @expectedFailureWindows(compilers=['gcc'])). When called + # the first way, the first argument will be the actual function because decorators are + # weird like that. So this is basically a check that says "which syntax was the original + # function decorated with?" + if six.callable(bugnumber): + return expectedFailure_impl(bugnumber) + else: + return expectedFailure_impl + +def expectedFlakeyDwarf(bugnumber=None): + def fn(self): + return self.debug_info == "dwarf" + return expectedFlakey(fn, bugnumber) + +def expectedFlakeyDsym(bugnumber=None): + def fn(self): + return self.debug_info == "dwarf" + return expectedFlakey(fn, bugnumber) + +def expectedFlakeyOS(oslist, bugnumber=None, compilers=None): + def fn(self): + return (self.getPlatform() in oslist and + self.expectedCompiler(compilers)) + return expectedFlakey(fn, bugnumber) + +def expectedFlakeyDarwin(bugnumber=None, compilers=None): + # For legacy reasons, we support both "darwin" and "macosx" as OS X triples. + return expectedFlakeyOS(lldbplatformutil.getDarwinOSTriples(), bugnumber, compilers) + +def expectedFlakeyFreeBSD(bugnumber=None, compilers=None): + return expectedFlakeyOS(['freebsd'], bugnumber, compilers) + +def expectedFlakeyLinux(bugnumber=None, compilers=None): + return expectedFlakeyOS(['linux'], bugnumber, compilers) + +def expectedFlakeyNetBSD(bugnumber=None, compilers=None): + return expectedFlakeyOS(['netbsd'], bugnumber, compilers) + +def expectedFlakeyCompiler(compiler, compiler_version=None, bugnumber=None): + if compiler_version is None: + compiler_version=['=', None] + def fn(self): + return compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version) + return expectedFlakey(fn, bugnumber) + +# @expectedFlakeyClang('bugnumber', ['<=', '3.4']) +def expectedFlakeyClang(bugnumber=None, compiler_version=None): + return expectedFlakeyCompiler('clang', compiler_version, bugnumber) + +# @expectedFlakeyGcc('bugnumber', ['<=', '3.4']) +def expectedFlakeyGcc(bugnumber=None, compiler_version=None): + return expectedFlakeyCompiler('gcc', compiler_version, bugnumber) + +def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None): + return expectedFlakey(_skip_for_android("flakey on android", api_levels, archs), bugnumber) + +def skipIfRemote(func): + """Decorate the item to skip tests if testing remotely.""" + def is_remote(): + return "skip on remote platform" if lldb.remote_platform else None + return skipTestIfFn(is_remote)(func) + +def skipIfRemoteDueToDeadlock(func): + """Decorate the item to skip tests if testing remotely due to the test deadlocking.""" + def is_remote(): + return "skip on remote platform (deadlocks)" if lldb.remote_platform else None + return skipTestIfFn(is_remote)(func) + +def skipIfNoSBHeaders(func): + """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers.""" + def are_sb_headers_missing(): + if lldbplatformutil.getHostPlatform() == 'darwin': + header = os.path.join(os.environ["LLDB_LIB_DIR"], 'LLDB.framework', 'Versions','Current','Headers','LLDB.h') + else: + header = os.path.join(os.environ["LLDB_SRC"], "include", "lldb", "API", "LLDB.h") + if not os.path.exists(header): + return "skip because LLDB.h header not found" + return None + + return skipTestIfFn(are_sb_headers_missing)(func) + +def skipIfiOSSimulator(func): + """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" + def is_ios_simulator(): + return "skip on the iOS Simulator" if configuration.lldb_platform_name == 'ios-simulator' else None + return skipTestIfFn(is_ios_simulator)(func) + +def skipIfFreeBSD(func): + """Decorate the item to skip tests that should be skipped on FreeBSD.""" + return skipIfPlatform(["freebsd"])(func) + +def skipIfNetBSD(func): + """Decorate the item to skip tests that should be skipped on NetBSD.""" + return skipIfPlatform(["netbsd"])(func) + +def skipIfDarwin(func): + """Decorate the item to skip tests that should be skipped on Darwin.""" + return skipIfPlatform(lldbplatform.translate(lldbplatform.darwin_all))(func) + +def skipIfLinux(func): + """Decorate the item to skip tests that should be skipped on Linux.""" + return skipIfPlatform(["linux"])(func) + +def skipIfWindows(func): + """Decorate the item to skip tests that should be skipped on Windows.""" + return skipIfPlatform(["windows"])(func) + +def skipUnlessWindows(func): + """Decorate the item to skip tests that should be skipped on any non-Windows platform.""" + return skipUnlessPlatform(["windows"])(func) + +def skipUnlessDarwin(func): + """Decorate the item to skip tests that should be skipped on any non Darwin platform.""" + return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func) + +def skipUnlessGoInstalled(func): + """Decorate the item to skip tests when no Go compiler is available.""" + def is_go_missing(self): + compiler = self.getGoCompilerVersion() + if not compiler: + return "skipping because go compiler not found" + match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler) + if not match_version: + # Couldn't determine version. + return "skipping because go version could not be parsed out of {}".format(compiler) + else: + min_strict_version = StrictVersion("1.4.0") + compiler_strict_version = StrictVersion(match_version.group(1)) + if compiler_strict_version < min_strict_version: + return "skipping because available version ({}) does not meet minimum required version ({})".format( + compiler_strict_version, min_strict_version) + return None + return skipTestIfFn(is_go_missing)(func) + +def skipIfHostIncompatibleWithRemote(func): + """Decorate the item to skip tests if binaries built on this host are incompatible.""" + def is_host_incompatible_with_remote(self): + host_arch = self.getLldbArchitecture() + host_platform = lldbplatformutil.getHostPlatform() + target_arch = self.getArchitecture() + target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform() + if not (target_arch == 'x86_64' and host_arch == 'i386') and host_arch != target_arch: + return "skipping because target %s is not compatible with host architecture %s" % (target_arch, host_arch) + elif target_platform != host_platform: + return "skipping because target is %s but host is %s" % (target_platform, host_platform) + return None + return skipTestIfFn(is_host_incompatible_with_remote)(func) + +def skipIfPlatform(oslist): + """Decorate the item to skip tests if running on one of the listed platforms.""" + # This decorator cannot be ported to `skipIf` yet because it is used on entire + # classes, which `skipIf` explicitly forbids. + return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist, + "skip on %s" % (", ".join(oslist))) + +def skipUnlessPlatform(oslist): + """Decorate the item to skip tests unless running on one of the listed platforms.""" + # This decorator cannot be ported to `skipIf` yet because it is used on entire + # classes, which `skipIf` explicitly forbids. + return unittest2.skipUnless(lldbplatformutil.getPlatform() in oslist, + "requires on of %s" % (", ".join(oslist))) + +def skipIfTargetAndroid(api_levels=None, archs=None): + """Decorator to skip tests when the target is Android. + + Arguments: + api_levels - The API levels for which the test should be skipped. If + it is None, then the test will be skipped for all API levels. + arch - A sequence of architecture names specifying the architectures + for which a test is skipped. None means all architectures. + """ + return skipTestIfFn(_skip_for_android("skipping for android", api_levels, archs)) + +def skipUnlessCompilerRt(func): + """Decorate the item to skip tests if testing remotely.""" + def is_compiler_rt_missing(): + compilerRtPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "llvm","projects","compiler-rt") + return "compiler-rt not found" if not os.path.exists(compilerRtPath) else None + return skipTestIfFn(is_compiler_rt_missing)(func) + +def skipUnlessThreadSanitizer(func): + """Decorate the item to skip test unless Clang -fsanitize=thread is supported.""" + def is_compiler_clang_with_thread_sanitizer(self): + compiler_path = self.getCompiler() + compiler = os.path.basename(compiler_path) + if not compiler.startswith("clang"): + return "Test requires clang as compiler" + f = tempfile.NamedTemporaryFile() + cmd = "echo 'int main() {}' | %s -x c -o %s -" % (compiler_path, f.name) + if os.popen(cmd).close() != None: + return None # The compiler cannot compile at all, let's *not* skip the test + cmd = "echo 'int main() {}' | %s -fsanitize=thread -x c -o %s -" % (compiler_path, f.name) + if os.popen(cmd).close() != None: + return "Compiler cannot compile with -fsanitize=thread" + return None + return skipTestIfFn(is_compiler_clang_with_thread_sanitizer)(func) diff --git a/packages/Python/lldbsuite/test/dosep.py b/packages/Python/lldbsuite/test/dosep.py index 87a410fa090f..37ca91adb140 100644 --- a/packages/Python/lldbsuite/test/dosep.py +++ b/packages/Python/lldbsuite/test/dosep.py @@ -30,8 +30,8 @@ ulimit -c unlimited echo core.%p | sudo tee /proc/sys/kernel/core_pattern """ -from __future__ import print_function from __future__ import absolute_import +from __future__ import print_function # system packages and modules import asyncore @@ -53,18 +53,13 @@ import lldbsuite import lldbsuite.support.seven as seven from . import configuration -from . import dotest_channels from . import dotest_args -from . import result_formatter - -from .result_formatter import EventBuilder +from lldbsuite.support import optional_with +from lldbsuite.test_event import dotest_channels +from lldbsuite.test_event.event_builder import EventBuilder +from lldbsuite.test_event import formatter - -# Todo: Convert this folder layout to be relative-import friendly and -# don't hack up sys.path like this -sys.path.append(os.path.join(os.path.dirname(__file__), "test_runner", "lib")) -import lldb_utils -import process_control +from .test_runner import process_control # Status codes for running command with timeout. eTimedOut, ePassed, eFailed = 124, 0, 1 @@ -109,13 +104,17 @@ def setup_global_variables( global GET_WORKER_INDEX GET_WORKER_INDEX = get_worker_index_use_pid -def report_test_failure(name, command, output): +def report_test_failure(name, command, output, timeout): global output_lock with output_lock: if not (RESULTS_FORMATTER and RESULTS_FORMATTER.is_using_terminal()): print(file=sys.stderr) print(output, file=sys.stderr) - print("[%s FAILED]" % name, file=sys.stderr) + if timeout: + timeout_str = " (TIMEOUT)" + else: + timeout_str = "" + print("[%s FAILED]%s" % (name, timeout_str), file=sys.stderr) print("Command invoked: %s" % ' '.join(command), file=sys.stderr) update_progress(name) @@ -173,7 +172,7 @@ class DoTestProcessDriver(process_control.ProcessDriver): super(DoTestProcessDriver, self).__init__( soft_terminate_timeout=soft_terminate_timeout) self.output_file = output_file - self.output_lock = lldb_utils.OptionalWith(output_file_lock) + self.output_lock = optional_with.optional_with(output_file_lock) self.pid_events = pid_events self.results = None self.file_name = file_name @@ -211,7 +210,7 @@ class DoTestProcessDriver(process_control.ProcessDriver): # only stderr does. report_test_pass(self.file_name, output[1]) else: - report_test_failure(self.file_name, command, output[1]) + report_test_failure(self.file_name, command, output[1], was_timeout) # Save off the results for the caller. self.results = ( @@ -299,9 +298,9 @@ def send_events_to_collector(events, command): event_port = int(command[arg_index]) # Create results formatter connected back to collector via socket. - config = result_formatter.FormatterConfig() + config = formatter.FormatterConfig() config.port = event_port - formatter_spec = result_formatter.create_results_formatter(config) + formatter_spec = formatter.create_results_formatter(config) if formatter_spec is None or formatter_spec.formatter is None: raise Exception( "Failed to create socket-based ResultsFormatter " @@ -420,9 +419,14 @@ def process_dir(root, files, dotest_argv, inferior_pid_events): results = [] for (base_name, full_test_path) in files: import __main__ as main + global dotest_options + if dotest_options.p and not re.search(dotest_options.p, base_name): + continue + script_file = main.__file__ command = ([sys.executable, script_file] + dotest_argv + + ["-S", dotest_options.session_file_format] + ["--inferior", "-p", base_name, root]) timeout_name = os.path.basename(os.path.splitext(base_name)[0]).upper() @@ -1135,34 +1139,27 @@ def walk_and_invoke(test_files, dotest_argv, num_workers, test_runner_func): def getExpectedTimeouts(platform_name): # returns a set of test filenames that might timeout # are we running against a remote target? - host = sys.platform + + # Figure out the target system for which we're collecting + # the set of expected timeout test filenames. if platform_name is None: target = sys.platform else: m = re.search(r'remote-(\w+)', platform_name) - target = m.group(1) + if m is not None: + target = m.group(1) + else: + target = platform_name expected_timeout = set() - if target.startswith("android"): - expected_timeout |= { - "TestExitDuringStep.py", - "TestHelloWorld.py", - } - elif target.startswith("freebsd"): + if target.startswith("freebsd"): expected_timeout |= { "TestBreakpointConditions.py", "TestChangeProcessGroup.py", "TestValueObjectRecursion.py", "TestWatchpointConditionAPI.py", } - elif target.startswith("darwin"): - expected_timeout |= { - # times out on MBP Retina, Mid 2012 - "TestThreadSpecificBreakpoint.py", - "TestExitDuringStep.py", - "TestIntegerTypesExpr.py", - } return expected_timeout diff --git a/packages/Python/lldbsuite/test/dotest.py b/packages/Python/lldbsuite/test/dotest.py index 723f26a417e4..702e57e99871 100644 --- a/packages/Python/lldbsuite/test/dotest.py +++ b/packages/Python/lldbsuite/test/dotest.py @@ -23,7 +23,6 @@ from __future__ import print_function # System modules import atexit -import importlib import os import errno import platform @@ -31,7 +30,6 @@ import signal import socket import subprocess import sys -import inspect # Third-party modules import six @@ -43,9 +41,9 @@ from . import configuration from . import dotest_args from . import lldbtest_config from . import test_categories -from . import result_formatter +from lldbsuite.test_event import formatter from . import test_result -from .result_formatter import EventBuilder +from lldbsuite.test_event.event_builder import EventBuilder from ..support import seven def is_exe(fpath): @@ -309,7 +307,7 @@ def parseOptionsAndInitTestdirs(): configuration.lldbFrameworkPath = args.framework if args.executable: - lldbtest_config.lldbExec = args.executable + lldbtest_config.lldbExec = os.path.realpath(args.executable) if args.p: if args.p.startswith('-'): @@ -323,6 +321,7 @@ def parseOptionsAndInitTestdirs(): if args.s.startswith('-'): usage(parser) configuration.sdir_name = args.s + configuration.session_file_format = args.session_file_format if args.t: os.environ['LLDB_COMMAND_TRACE'] = 'YES' @@ -359,7 +358,7 @@ def parseOptionsAndInitTestdirs(): # Capture test results-related args. if args.curses and not args.inferior: # Act as if the following args were set. - args.results_formatter = "lldbsuite.test.curses_results.Curses" + args.results_formatter = "lldbsuite.test_event.formatter.curses.Curses" args.results_file = "stdout" if args.results_file: @@ -383,7 +382,7 @@ def parseOptionsAndInitTestdirs(): # and we're not a test inferior. if not args.inferior and configuration.results_formatter_name is None: configuration.results_formatter_name = ( - "lldbsuite.test.result_formatter.ResultsFormatter") + "lldbsuite.test_event.formatter.results_formatter.ResultsFormatter") # rerun-related arguments configuration.rerun_all_issues = args.rerun_all_issues @@ -412,7 +411,7 @@ def parseOptionsAndInitTestdirs(): # Tell the event builder to create all events with these # key/val pairs in them. if len(entries) > 0: - result_formatter.EventBuilder.add_entries_to_all_events(entries) + EventBuilder.add_entries_to_all_events(entries) # Gather all the dirs passed on the command line. if len(args.args) > 0: @@ -453,7 +452,7 @@ def createSocketToLocalPort(port): def setupTestResults(): """Sets up test results-related objects based on arg settings.""" # Setup the results formatter configuration. - formatter_config = result_formatter.FormatterConfig() + formatter_config = formatter.FormatterConfig() formatter_config.filename = configuration.results_filename formatter_config.formatter_name = configuration.results_formatter_name formatter_config.formatter_options = ( @@ -461,12 +460,12 @@ def setupTestResults(): formatter_config.port = configuration.results_port # Create the results formatter. - formatter_spec = result_formatter.create_results_formatter( + formatter_spec = formatter.create_results_formatter( formatter_config) if formatter_spec is not None and formatter_spec.formatter is not None: configuration.results_formatter_object = formatter_spec.formatter - # Send an intialize message to the formatter. + # Send an initialize message to the formatter. initialize_event = EventBuilder.bare_event("initialize") if isMultiprocessTestRunner(): if (configuration.test_runner_name is not None and @@ -640,16 +639,15 @@ def setupSysPath(): if not lldbPythonDir: if platform.system() == "Darwin": python_resource_dir = ['LLDB.framework', 'Resources', 'Python'] - outputPaths = getXcodeOutputPaths() + outputPaths = getXcodeOutputPaths(lldbRootDirectory) for outputPath in outputPaths: - candidatePath = os.path.join(outputPath, python_resource_dir) + candidatePath = os.path.join(outputPath, *python_resource_dir) if os.path.isfile(os.path.join(candidatePath, init_in_python_dir)): lldbPythonDir = candidatePath break if not lldbPythonDir: - print('This script requires lldb.py to be in either ' + dbgPath + ',', end=' ') - print(relPath + ', or ' + baiPath + '. Some tests might fail.') + print("lldb.py is not found, some tests may fail.") else: print("Unable to load lldb extension module. Possible reasons for this include:") print(" 1) LLDB was built with LLDB_DISABLE_PYTHON=1") @@ -659,7 +657,7 @@ def setupSysPath(): print(" location of LLDB\'s site-packages folder.") print(" 3) A different version of Python than that which was built against is exported in") print(" the system\'s PATH environment variable, causing conflicts.") - print(" 4) The executable '%s' could not be found. Please check " % lldbExecutable) + print(" 4) The executable '%s' could not be found. Please check " % lldbtest_config.lldbExec) print(" that it exists and is executable.") if lldbPythonDir: @@ -678,73 +676,98 @@ def setupSysPath(): # This is to locate the lldb.py module. Insert it right after sys.path[0]. sys.path[1:1] = [lldbPythonDir] + +def visit_file(dir, name): + # Try to match the regexp pattern, if specified. + if configuration.regexp: + import re + if not re.search(configuration.regexp, name): + # We didn't match the regex, we're done. + return + + # We found a match for our test. Add it to the suite. + + # Update the sys.path first. + if not sys.path.count(dir): + sys.path.insert(0, dir) + base = os.path.splitext(name)[0] + + # Thoroughly check the filterspec against the base module and admit + # the (base, filterspec) combination only when it makes sense. + filterspec = None + for filterspec in configuration.filters: + # Optimistically set the flag to True. + filtered = True + module = __import__(base) + parts = filterspec.split('.') + obj = module + for part in parts: + try: + parent, obj = obj, getattr(obj, part) + except AttributeError: + # The filterspec has failed. + filtered = False + break + + # If filtered, we have a good filterspec. Add it. + if filtered: + # print("adding filter spec %s to module %s" % (filterspec, module)) + configuration.suite.addTests( + unittest2.defaultTestLoader.loadTestsFromName(filterspec, module)) + continue + + # Forgo this module if the (base, filterspec) combo is invalid + if configuration.filters and not filtered: + return + + if not filterspec or not filtered: + # Add the entire file's worth of tests since we're not filtered. + # Also the fail-over case when the filterspec branch + # (base, filterspec) combo doesn't make sense. + configuration.suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base)) + + def visit(prefix, dir, names): """Visitor function for os.path.walk(path, visit, arg).""" dir_components = set(dir.split(os.sep)) excluded_components = set(['.svn', '.git']) if dir_components.intersection(excluded_components): - #print("Detected an excluded dir component: %s" % dir) return - for name in names: - if '.py' == os.path.splitext(name)[1] and name.startswith(prefix): + # Gather all the Python test file names that follow the Test*.py pattern. + python_test_files = [ + name + for name in names + if name.endswith('.py') and name.startswith(prefix)] + # Visit all the python test files. + for name in python_test_files: + try: + # Ensure we error out if we have multiple tests with the same + # base name. + # Future improvement: find all the places where we work with base + # names and convert to full paths. We have directory structure + # to disambiguate these, so we shouldn't need this constraint. if name in configuration.all_tests: raise Exception("Found multiple tests with the name %s" % name) configuration.all_tests.add(name) - # Try to match the regexp pattern, if specified. - if configuration.regexp: - import re - if re.search(configuration.regexp, name): - #print("Filename: '%s' matches pattern: '%s'" % (name, regexp)) - pass - else: - #print("Filename: '%s' does not match pattern: '%s'" % (name, regexp)) - continue - - # We found a match for our test. Add it to the suite. - - # Update the sys.path first. - if not sys.path.count(dir): - sys.path.insert(0, dir) - base = os.path.splitext(name)[0] - - # Thoroughly check the filterspec against the base module and admit - # the (base, filterspec) combination only when it makes sense. - filterspec = None - for filterspec in configuration.filters: - # Optimistically set the flag to True. - filtered = True - module = __import__(base) - parts = filterspec.split('.') - obj = module - for part in parts: - try: - parent, obj = obj, getattr(obj, part) - except AttributeError: - # The filterspec has failed. - filtered = False - break + # Run the relevant tests in the python file. + visit_file(dir, name) + except Exception as ex: + # Convert this exception to a test event error for the file. + test_filename = os.path.abspath(os.path.join(dir, name)) + if configuration.results_formatter_object is not None: + # Grab the backtrace for the exception. + import traceback + backtrace = traceback.format_exc() - # If filtered, we have a good filterspec. Add it. - if filtered: - #print("adding filter spec %s to module %s" % (filterspec, module)) - configuration.suite.addTests( - unittest2.defaultTestLoader.loadTestsFromName(filterspec, module)) - continue - - # Forgo this module if the (base, filterspec) combo is invalid - if configuration.filters and not filtered: - continue - - # Add either the filtered test case(s) (which is done before) or the entire test class. - if not filterspec or not filtered: - # A simple case of just the module name. Also the failover case - # from the filterspec branch when the (base, filterspec) combo - # doesn't make sense. - configuration.suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base)) + # Generate the test event. + configuration.results_formatter_object.handle_event( + EventBuilder.event_for_job_test_add_error( + test_filename, ex, backtrace)) + raise def disabledynamics(): @@ -987,12 +1010,6 @@ def run_suite(): except OSError as exception: if exception.errno != errno.EEXIST: raise - where_to_save_session = os.getcwd() - fname = os.path.join(configuration.sdir_name, "TestStarted-%d" % os.getpid()) - with open(fname, "w") as f: - print("Test started at: %s\n" % timestamp_started, file=f) - print(configuration.svn_info, file=f) - print("Command invoked: %s\n" % getMyCommandLine(), file=f) # # Invoke the default TextTestRunner to run the test suite, possibly iterating @@ -1092,7 +1109,7 @@ def run_suite(): # mark __ignore_singleton__ flag as True so the signleton pattern is # not enforced. test_result.LLDBTestResult.__ignore_singleton__ = True - for i in range(count): + for i in range(configuration.count): result = unittest2.TextTestRunner(stream=sys.stderr, verbosity=v, @@ -1109,11 +1126,6 @@ def run_suite(): for category in configuration.failuresPerCategory: sys.stderr.write("%s - %d\n" % (category, configuration.failuresPerCategory[category])) - os.chdir(where_to_save_session) - fname = os.path.join(configuration.sdir_name, "TestFinished-%d" % os.getpid()) - with open(fname, "w") as f: - print("Test finished at: %s\n" % datetime.datetime.now().strftime("%Y-%m-%d-%H_%M_%S"), file=f) - # Terminate the test suite if ${LLDB_TESTSUITE_FORCE_FINISH} is defined. # This should not be necessary now. if ("LLDB_TESTSUITE_FORCE_FINISH" in os.environ): diff --git a/packages/Python/lldbsuite/test/dotest_args.py b/packages/Python/lldbsuite/test/dotest_args.py index 105156df7e84..8bbc29c98f00 100644 --- a/packages/Python/lldbsuite/test/dotest_args.py +++ b/packages/Python/lldbsuite/test/dotest_args.py @@ -11,6 +11,7 @@ import textwrap # Third-party modules # LLDB modules +from . import configuration class ArgParseNamespace(object): pass @@ -70,6 +71,7 @@ def create_parser(): group.add_argument('--framework', metavar='framework-path', help='The path to LLDB.framework') group.add_argument('--executable', metavar='executable-path', help='The path to the lldb executable') group.add_argument('-s', metavar='name', help='Specify the name of the dir created to store the session files of tests with errored or failed status. If not specified, the test driver uses the timestamp as the session dir name') + group.add_argument('-S', '--session-file-format', default=configuration.session_file_format, metavar='format', help='Specify session file name format. See configuration.py for a description.') group.add_argument('-y', type=int, metavar='count', help="Specify the iteration count used to collect our benchmarks. An example is the number of times to do 'thread step-over' to measure stepping speed.") group.add_argument('-#', type=int, metavar='sharp', dest='sharp', help='Repeat the test suite for a specified number of times') group.add_argument('--channel', metavar='channel', dest='channels', action='append', help=textwrap.dedent("Specify the log channels (and optional categories) e.g. 'lldb all' or 'gdb-remote packets' if no categories are specified, 'default' is used")) diff --git a/packages/Python/lldbsuite/test/dotest_channels.py b/packages/Python/lldbsuite/test/dotest_channels.py deleted file mode 100644 index d2faf10c8929..000000000000 --- a/packages/Python/lldbsuite/test/dotest_channels.py +++ /dev/null @@ -1,200 +0,0 @@ -""" - The LLVM Compiler Infrastructure - -This file is distributed under the University of Illinois Open Source -License. See LICENSE.TXT for details. - -Sync lldb and related source from a local machine to a remote machine. - -This facilitates working on the lldb sourcecode on multiple machines -and multiple OS types, verifying changes across all. - - -This module provides asyncore channels used within the LLDB test -framework. -""" - -from __future__ import print_function -from __future__ import absolute_import - - -# System modules -import asyncore -import socket - -# Third-party modules -from six.moves import cPickle - -# LLDB modules - - -class UnpicklingForwardingReaderChannel(asyncore.dispatcher): - """Provides an unpickling, forwarding asyncore dispatch channel reader. - - Inferior dotest.py processes with side-channel-based test results will - send test result event data in a pickled format, one event at a time. - This class supports reconstructing the pickled data and forwarding it - on to its final destination. - - The channel data is written in the form: - {num_payload_bytes}#{payload_bytes} - - The bulk of this class is devoted to reading and parsing out - the payload bytes. - """ - def __init__(self, file_object, async_map, forwarding_func): - asyncore.dispatcher.__init__(self, sock=file_object, map=async_map) - - self.header_contents = b"" - self.packet_bytes_remaining = 0 - self.reading_header = True - self.ibuffer = b'' - self.forwarding_func = forwarding_func - if forwarding_func is None: - # This whole class is useless if we do nothing with the - # unpickled results. - raise Exception("forwarding function must be set") - - def deserialize_payload(self): - """Unpickles the collected input buffer bytes and forwards.""" - if len(self.ibuffer) > 0: - self.forwarding_func(cPickle.loads(self.ibuffer)) - self.ibuffer = b'' - - def consume_header_bytes(self, data): - """Consumes header bytes from the front of data. - @param data the incoming data stream bytes - @return any data leftover after consuming header bytes. - """ - # We're done if there is no content. - if not data or (len(data) == 0): - return None - - full_header_len = 4 - - assert len(self.header_contents) < full_header_len - - bytes_avail = len(data) - bytes_needed = full_header_len - len(self.header_contents) - header_bytes_avail = min(bytes_needed, bytes_avail) - self.header_contents += data[:header_bytes_avail] - if len(self.header_contents) == full_header_len: - import struct - # End of header. - self.packet_bytes_remaining = struct.unpack( - "!I", self.header_contents)[0] - self.header_contents = b"" - self.reading_header = False - return data[header_bytes_avail:] - - # If we made it here, we've exhausted the data and - # we're still parsing header content. - return None - - def consume_payload_bytes(self, data): - """Consumes payload bytes from the front of data. - @param data the incoming data stream bytes - @return any data leftover after consuming remaining payload bytes. - """ - if not data or (len(data) == 0): - # We're done and there's nothing to do. - return None - - data_len = len(data) - if data_len <= self.packet_bytes_remaining: - # We're consuming all the data provided. - self.ibuffer += data - self.packet_bytes_remaining -= data_len - - # If we're no longer waiting for payload bytes, - # we flip back to parsing header bytes and we - # unpickle the payload contents. - if self.packet_bytes_remaining < 1: - self.reading_header = True - self.deserialize_payload() - - # We're done, no more data left. - return None - else: - # We're only consuming a portion of the data since - # the data contains more than the payload amount. - self.ibuffer += data[:self.packet_bytes_remaining] - data = data[self.packet_bytes_remaining:] - - # We now move on to reading the header. - self.reading_header = True - self.packet_bytes_remaining = 0 - - # And we can deserialize the payload. - self.deserialize_payload() - - # Return the remaining data. - return data - - def handle_read(self): - # Read some data from the socket. - try: - data = self.recv(8192) - # print('driver socket READ: %d bytes' % len(data)) - except socket.error as socket_error: - print( - "\nINFO: received socket error when reading data " - "from test inferior:\n{}".format(socket_error)) - raise - except Exception as general_exception: - print( - "\nERROR: received non-socket error when reading data " - "from the test inferior:\n{}".format(general_exception)) - raise - - # Consume the message content. - while data and (len(data) > 0): - # If we're reading the header, gather header bytes. - if self.reading_header: - data = self.consume_header_bytes(data) - else: - data = self.consume_payload_bytes(data) - - def handle_close(self): - # print("socket reader: closing port") - self.close() - - -class UnpicklingForwardingListenerChannel(asyncore.dispatcher): - """Provides a socket listener asyncore channel for unpickling/forwarding. - - This channel will listen on a socket port (use 0 for host-selected). Any - client that connects will have an UnpicklingForwardingReaderChannel handle - communication over the connection. - - The dotest parallel test runners, when collecting test results, open the - test results side channel over a socket. This channel handles connections - from inferiors back to the test runner. Each worker fires up a listener - for each inferior invocation. This simplifies the asyncore.loop() usage, - one of the reasons for implementing with asyncore. This listener shuts - down once a single connection is made to it. - """ - def __init__(self, async_map, host, port, backlog_count, forwarding_func): - asyncore.dispatcher.__init__(self, map=async_map) - self.create_socket(socket.AF_INET, socket.SOCK_STREAM) - self.set_reuse_addr() - self.bind((host, port)) - self.address = self.socket.getsockname() - self.listen(backlog_count) - self.handler = None - self.async_map = async_map - self.forwarding_func = forwarding_func - if forwarding_func is None: - # This whole class is useless if we do nothing with the - # unpickled results. - raise Exception("forwarding function must be set") - - def handle_accept(self): - (sock, addr) = self.socket.accept() - if sock and addr: - # print('Incoming connection from %s' % repr(addr)) - self.handler = UnpicklingForwardingReaderChannel( - sock, self.async_map, self.forwarding_func) - - def handle_close(self): - self.close() diff --git a/packages/Python/lldbsuite/test/driver/batch_mode/TestBatchMode.py b/packages/Python/lldbsuite/test/driver/batch_mode/TestBatchMode.py index 0a9edd2755c9..6713a5a764e4 100644 --- a/packages/Python/lldbsuite/test/driver/batch_mode/TestBatchMode.py +++ b/packages/Python/lldbsuite/test/driver/batch_mode/TestBatchMode.py @@ -8,7 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class DriverBatchModeTest (TestBase): @@ -34,7 +36,7 @@ class DriverBatchModeTest (TestBase): @skipIfRemote # test not remote-ready llvm.org/pr24813 @expectedFlakeyFreeBSD("llvm.org/pr25172 fails rarely on the buildbot") @expectedFlakeyLinux("llvm.org/pr25172") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_batch_mode_run_crash (self): """Test that the lldb driver's batch mode works correctly.""" self.build() @@ -71,7 +73,7 @@ class DriverBatchModeTest (TestBase): @skipIfRemote # test not remote-ready llvm.org/pr24813 @expectedFlakeyFreeBSD("llvm.org/pr25172 fails rarely on the buildbot") @expectedFlakeyLinux("llvm.org/pr25172") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_batch_mode_run_exit (self): """Test that the lldb driver's batch mode works correctly.""" self.build() @@ -108,7 +110,7 @@ class DriverBatchModeTest (TestBase): @skipIfRemote # test not remote-ready llvm.org/pr24813 @expectedFlakeyFreeBSD("llvm.org/pr25172 fails rarely on the buildbot") @expectedFlakeyLinux("llvm.org/pr25172") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_batch_mode_attach_exit (self): """Test that the lldb driver's batch mode works correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/Makefile b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/Makefile new file mode 100644 index 000000000000..7df664ac43e3 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/Makefile @@ -0,0 +1,12 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD +# targets. Other targets do not, which causes this test to fail. +# This flag enables FullDebugInfo for all targets. +ifneq (,$(findstring clang,$(CC))) + CFLAGS_EXTRAS += -fno-limit-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py new file mode 100644 index 000000000000..e1a53305a0d0 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py @@ -0,0 +1,42 @@ +""" +Test calling user defined functions using expression evaluation. +This test checks that typesystem lookup works correctly for typedefs of +untagged structures. + +Ticket: https://llvm.org/bugs/show_bug.cgi?id=26790 +""" + +from __future__ import print_function + +import lldb + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestExprLookupAnonStructTypedef(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + # Find the breakpoint + self.line = line_number('main.cpp', '// lldb testsuite break') + + @expectedFailureAll(oslist=["windows"]) + @expectedFailureAll(oslist=['linux'], archs=['arm'], bugnumber="llvm.org/pr27868") + def test(self): + """Test typedeffed untagged struct arguments for function call expressions""" + self.build() + + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + lldbutil.run_break_set_by_file_and_line( + self, + "main.cpp", + self.line, + num_expected_locations=-1, + loc_exact=True + ) + + self.runCmd("run", RUN_SUCCEEDED) + self.expect("expr multiply(&s)", substrs=['$0 = 1']) diff --git a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/main.cpp b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/main.cpp new file mode 100644 index 000000000000..5b170c5f943a --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/main.cpp @@ -0,0 +1,26 @@ +#include + +typedef struct { + float f; + int i; +} my_untagged_struct; + +double multiply(my_untagged_struct *s) +{ + return s->f * s->i; +} + +double multiply(my_untagged_struct *s, int x) +{ + return multiply(s) * x; +} + +int main(int argc, char **argv) +{ + my_untagged_struct s = { + .f = (float)argc, + .i = argc, + }; + // lldb testsuite break + return !(multiply(&s, argc) == pow(argc, 3)); +} diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStdStringFunction.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStdStringFunction.py index 3756b4a8cea4..61702ee88033 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStdStringFunction.py +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStdStringFunction.py @@ -7,8 +7,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCommandCallFunctionTestCase(TestBase): @@ -21,9 +22,9 @@ class ExprCommandCallFunctionTestCase(TestBase): self.line = line_number('main.cpp', '// Please test these expressions while stopped at this line:') - @expectedFailureIcc # llvm.org/pr14437, fails with ICC 13.1 - @expectedFailureFreeBSD('llvm.org/pr17807') # Fails on FreeBSD buildbot - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(compiler="icc", bugnumber="llvm.org/pr14437, fails with ICC 13.1") + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr17807 Fails on FreeBSD buildbot') + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_with(self): """Test calling std::String member function.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py index f6d63885248a..4d18cfc980f2 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py @@ -7,8 +7,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCommandCallStopContinueTestCase(TestBase): @@ -24,7 +25,7 @@ class ExprCommandCallStopContinueTestCase(TestBase): '{ 5, "five" }') @expectedFlakeyDarwin("llvm.org/pr20274") - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test(self): """Test gathering result from interrupted function call.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py index 9138af0b0b47..c0727a84fc02 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py +++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py @@ -12,8 +12,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCommandCallUserDefinedFunction(TestBase): @@ -26,7 +27,7 @@ class ExprCommandCallUserDefinedFunction(TestBase): self.line = line_number('main.cpp', '// Please test these expressions while stopped at this line:') @expectedFlakeyDsym("llvm.org/pr20274") - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test(self): """Test return values of user defined function calls.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py b/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py index abf48742567d..6b754a76878b 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py +++ b/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py @@ -7,8 +7,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCommandThatRestartsTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py b/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py index 0e766ac2953a..a6eb1bddc005 100644 --- a/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py +++ b/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py @@ -7,8 +7,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCommandWithThrowTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py index 5e1f307f622d..66fa69cdfff2 100644 --- a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py +++ b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py @@ -3,8 +3,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCharTestCase(TestBase): @@ -52,19 +53,17 @@ class ExprCharTestCase(TestBase): self.assertTrue(value.GetError().Success()) self.assertEqual(value.GetValueAsSigned(0), 3) - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_default_char(self): self.do_test() - @expectedFailureArch("arm", "llvm.org/pr23069") - @expectedFailureArch("aarch64", "llvm.org/pr23069") - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(archs=["arm", "aarch64", "s390x"], bugnumber="llvm.org/pr23069") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_signed_char(self): self.do_test(dictionary={'CFLAGS_EXTRAS': '-fsigned-char'}) - @expectedFailurei386("llvm.org/pr23069") - @expectedFailurex86_64("llvm.org/pr23069") - @expectedFailureWindows("llvm.org/pr21765") - @expectedFailureAll(bugnumber="llvm.org/pr23069", triple = 'mips*') + @expectedFailureAll(archs=["i[3-6]86", "x86_64"], bugnumber="llvm.org/pr23069") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") + @expectedFailureAll(triple = 'mips*', bugnumber="llvm.org/pr23069") def test_unsigned_char(self): self.do_test(dictionary={'CFLAGS_EXTRAS': '-funsigned-char'}) diff --git a/packages/Python/lldbsuite/test/expression_command/expr-in-syscall/TestExpressionInSyscall.py b/packages/Python/lldbsuite/test/expression_command/expr-in-syscall/TestExpressionInSyscall.py index 0430fa55f995..a715ee31e5fa 100644 --- a/packages/Python/lldbsuite/test/expression_command/expr-in-syscall/TestExpressionInSyscall.py +++ b/packages/Python/lldbsuite/test/expression_command/expr-in-syscall/TestExpressionInSyscall.py @@ -6,15 +6,16 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ExprSyscallTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr21765") # Also getpid() is not a function on Windows anyway + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765, getpid() does not exist on Windows") def test_setpgid(self): self.build() self.expr_syscall() diff --git a/packages/Python/lldbsuite/test/expression_command/fixits/Makefile b/packages/Python/lldbsuite/test/expression_command/fixits/Makefile new file mode 100644 index 000000000000..7df664ac43e3 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/fixits/Makefile @@ -0,0 +1,12 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD +# targets. Other targets do not, which causes this test to fail. +# This flag enables FullDebugInfo for all targets. +ifneq (,$(findstring clang,$(CC))) + CFLAGS_EXTRAS += -fno-limit-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py b/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py new file mode 100644 index 000000000000..7e11f2b201f2 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py @@ -0,0 +1,81 @@ +""" +Test calling an expression with errors that a FixIt can fix. +""" + +from __future__ import print_function + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ExprCommandWithFixits(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec (self.main_source) + + @skipUnlessDarwin + def test(self): + """Test calling a function that throws and ObjC exception.""" + self.build() + self.try_expressions() + + def try_expressions(self): + """Test calling expressions with errors that can be fixed by the FixIts.""" + exe_name = "a.out" + exe = os.path.join(os.getcwd(), exe_name) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateBySourceRegex('Stop here to evaluate expressions',self.main_source_spec) + self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be at our breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint) + + self.assertTrue(len(threads) == 1) + self.thread = threads[0] + + options = lldb.SBExpressionOptions() + options.SetAutoApplyFixIts(True) + + frame = self.thread.GetFrameAtIndex(0) + + # Try with one error: + value = frame.EvaluateExpression("my_pointer.first", options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertTrue(value.GetValueAsUnsigned() == 10) + + # Try with two errors: + two_error_expression = "my_pointer.second->a" + value = frame.EvaluateExpression(two_error_expression, options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertTrue(value.GetValueAsUnsigned() == 20) + + # Now turn off the fixits, and the expression should fail: + options.SetAutoApplyFixIts(False) + value = frame.EvaluateExpression(two_error_expression, options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Fail()) + error_string = value.GetError().GetCString() + self.assertTrue(error_string.find("fixed expression suggested:") != -1, "Fix was suggested") + self.assertTrue(error_string.find("my_pointer->second.a") != -1, "Fix was right") + + + diff --git a/packages/Python/lldbsuite/test/expression_command/fixits/main.cpp b/packages/Python/lldbsuite/test/expression_command/fixits/main.cpp new file mode 100644 index 000000000000..371d8333763b --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/fixits/main.cpp @@ -0,0 +1,25 @@ +#include + +struct SubStruct +{ + int a; + int b; +}; + +struct MyStruct +{ + int first; + struct SubStruct second; +}; + +int +main() +{ + struct MyStruct my_struct = {10, {20, 30}}; + struct MyStruct *my_pointer = &my_struct; + printf ("Stop here to evaluate expressions: %d %d %p\n", my_pointer->first, my_pointer->second.a, my_pointer); + return 0; +} + + + diff --git a/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py b/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py index 3f47206480c3..4a99dc479019 100644 --- a/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py +++ b/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py @@ -7,8 +7,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprFormattersTestCase(TestBase): @@ -22,9 +23,8 @@ class ExprFormattersTestCase(TestBase): '// Stop here') @skipIfFreeBSD # llvm.org/pr24691 skipping to avoid crashing the test runner - @expectedFailureFreeBSD('llvm.org/pr19011') # Newer Clang omits C1 complete object constructor - @expectedFailureFreeBSD('llvm.org/pr24691') # we hit an assertion in clang - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr19011 Newer Clang omits C1 complete object constructor') + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") @skipIfTargetAndroid() # skipping to avoid crashing the test runner @expectedFailureAndroid('llvm.org/pr24691') # we hit an assertion in clang def test(self): diff --git a/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/Makefile b/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/Makefile new file mode 100644 index 000000000000..8a7102e347af --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py b/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py new file mode 100644 index 000000000000..c4f176703225 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py @@ -0,0 +1,40 @@ +""" +Test PHI nodes work in the IR interpreter. +""" + +import os, os.path + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class IRInterpreterPHINodesTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def test_phi_node_support(self): + """Test support for PHI nodes in the IR interpreter.""" + + self.build() + exe = os.path.join(os.getcwd(), 'a.out') + self.runCmd('file ' + exe, CURRENT_EXECUTABLE_SET) + + # Break on the first assignment to i + line = line_number('main.cpp', 'i = 5') + lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', line, num_expected_locations=1, loc_exact=True) + + self.runCmd('run', RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint + self.expect('thread list', STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + self.runCmd('s') + + # The logical 'or' causes a PHI node to be generated. Execute without JIT + # to test that the interpreter can handle this + self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['true']) + + self.runCmd('s') + self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['false']) + self.runCmd('s') + self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['true']) diff --git a/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp b/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp new file mode 100644 index 000000000000..b144f9cc1b47 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp @@ -0,0 +1,17 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +int main() +{ + int i; + i = 5; + i = 2; + i = 3; + return 0; +} diff --git a/packages/Python/lldbsuite/test/expression_command/ir-interpreter/Makefile b/packages/Python/lldbsuite/test/expression_command/ir-interpreter/Makefile new file mode 100644 index 000000000000..c4169a9b1012 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/ir-interpreter/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../make + +default: a.out + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/ir-interpreter/TestIRInterpreter.py b/packages/Python/lldbsuite/test/expression_command/ir-interpreter/TestIRInterpreter.py new file mode 100644 index 000000000000..2a21d0473715 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/ir-interpreter/TestIRInterpreter.py @@ -0,0 +1,72 @@ +""" +Test the IR interpreter +""" + +from __future__ import print_function + +import unittest2 + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class IRInterpreterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number('main.c', + '// Set breakpoint here') + + # Disable confirmation prompt to avoid infinite wait + self.runCmd("settings set auto-confirm true") + self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm")) + + def build_and_run(self): + """Test the IR interpreter""" + self.build() + + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.c", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=['windows'], bugnumber="http://llvm.org/pr21765") # getpid() is POSIX, among other problems, see bug + @expectedFailureAll(oslist=['linux'], archs=['arm'], bugnumber="llvm.org/pr27868") + def test_ir_interpreter(self): + self.build_and_run() + + options = lldb.SBExpressionOptions() + options.SetLanguage(lldb.eLanguageTypeC_plus_plus) + + set_up_expressions = ["int $i = 9", "int $j = 3", "int $k = 5"] + + expressions = ["$i + $j", + "$i - $j", + "$i * $j", + "$i / $j", + "$i % $k", + "$i << $j", + "$i & $j", + "$i | $j", + "$i ^ $j"] + + for expression in set_up_expressions: + self.frame().EvaluateExpression(expression, options) + + for expression in expressions: + interp_expression = expression + jit_expression = "(int)getpid(); " + expression + + interp_result = self.frame().EvaluateExpression(interp_expression, options).GetValueAsSigned() + jit_result = self.frame().EvaluateExpression(jit_expression, options).GetValueAsSigned() + + self.assertEqual(interp_result, jit_result, "While evaluating " + expression) + diff --git a/packages/Python/lldbsuite/test/expression_command/ir-interpreter/main.c b/packages/Python/lldbsuite/test/expression_command/ir-interpreter/main.c new file mode 100644 index 000000000000..31204b21d972 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/ir-interpreter/main.c @@ -0,0 +1,7 @@ +#include + +int main() +{ + printf("This is a dummy\n"); // Set breakpoint here + return 0; +} diff --git a/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py b/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py index fdc981ea178d..2d0b23b4e5ba 100644 --- a/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py +++ b/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py @@ -10,14 +10,15 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class Issue11581TestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_11581_commands(self): # This is the function to remove the custom commands in order to have a # clean slate for the next test case. diff --git a/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py b/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py index c3d6306c5a63..939d2e45d7d5 100644 --- a/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py +++ b/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py @@ -1,13 +1,17 @@ +from __future__ import print_function + + import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestMacros(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureClang("clang does not emit .debug_macro[.dwo] sections.") - @expectedFailureDwo("GCC produces multiple .debug_macro.dwo sections and the spec is unclear as to what it means") + @expectedFailureAll(compiler="clang", bugnumber="clang does not emit .debug_macro[.dwo] sections.") + @expectedFailureAll(debug_info="dwo", bugnumber="GCC produces multiple .debug_macro.dwo sections and the spec is unclear as to what it means") @expectedFailureAll(hostoslist=["windows"], compiler="gcc", triple='.*-android') def test_expr_with_macros(self): self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/Makefile b/packages/Python/lldbsuite/test/expression_command/multiline/Makefile new file mode 100644 index 000000000000..0d70f2595019 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/multiline/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py b/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py new file mode 100644 index 000000000000..0691a866743b --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py @@ -0,0 +1,57 @@ +"""Test multiline expressions.""" + +from __future__ import print_function + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class MultilineExpressionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break on inside main.cpp. + self.line = line_number('main.c', 'break') + + @skipIfRemote + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") + def test_with_run_commands(self): + """Test that multiline expressions work correctly""" + self.build() + import pexpect + exe = os.path.join(os.getcwd(), "a.out") + prompt = "(lldb) " + + # So that the child gets torn down after the test. + self.child = pexpect.spawn('%s %s %s' % (lldbtest_config.lldbExec, self.lldbOption, exe)) + child = self.child + # Turn on logging for what the child sends back. + if self.TraceOn(): + child.logfile_read = sys.stdout + + # Set the breakpoint, run the inferior, when it breaks, issue print on + # the various convenience variables. + child.expect_exact(prompt) + child.sendline('breakpoint set -f main.c -l %d' % self.line) + child.expect_exact(prompt) + child.sendline('run') + child.expect_exact("stop reason = breakpoint 1.1") + child.expect_exact(prompt) + child.sendline('expr') + child.expect_exact('1:') + + child.sendline('2+') + child.expect_exact('2:') + + child.sendline('3') + child.expect_exact('3:') + + child.sendline('') + child.expect_exact(prompt) + self.expect(child.before, exe=False, + patterns = ['= 5']) diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/main.c b/packages/Python/lldbsuite/test/expression_command/multiline/main.c new file mode 100644 index 000000000000..da16b1e7846f --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/multiline/main.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char const *argv[]) { + printf("Hello world.\n"); // break here + return 0; +} diff --git a/packages/Python/lldbsuite/test/expression_command/persist_objc_pointeetype/TestPersistObjCPointeeType.py b/packages/Python/lldbsuite/test/expression_command/persist_objc_pointeetype/TestPersistObjCPointeeType.py index 7b0707cdf22c..d3ce10d8f2ab 100644 --- a/packages/Python/lldbsuite/test/expression_command/persist_objc_pointeetype/TestPersistObjCPointeeType.py +++ b/packages/Python/lldbsuite/test/expression_command/persist_objc_pointeetype/TestPersistObjCPointeeType.py @@ -7,8 +7,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class PersistObjCPointeeType(TestBase): diff --git a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py index 3ea5b7040655..9099ae1806e3 100644 --- a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py +++ b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py @@ -8,13 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class NestedPersistentTypesTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_persistent_types(self): """Test that nested persistent types work.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py index 47c6675511fd..59e0f0b84f69 100644 --- a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py +++ b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py @@ -8,13 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class PersistenttypesTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_persistent_types(self): """Test that lldb persistent types works correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/po_verbosity/TestPoVerbosity.py b/packages/Python/lldbsuite/test/expression_command/po_verbosity/TestPoVerbosity.py index e415b92a43a6..da87bcee9cfc 100644 --- a/packages/Python/lldbsuite/test/expression_command/po_verbosity/TestPoVerbosity.py +++ b/packages/Python/lldbsuite/test/expression_command/po_verbosity/TestPoVerbosity.py @@ -7,8 +7,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class PoVerbosityTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py b/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py index fb16d2a93326..e0b219dbe2b9 100644 --- a/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py +++ b/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py @@ -8,15 +8,16 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class Radar9531204TestCase(TestBase): mydir = TestBase.compute_mydir(__file__) # rdar://problem/9531204 - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_expr_commands(self): """The evaluating printf(...) after break stop and then up a stack frame.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py b/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py index ce3e51d05149..a1505b08c508 100644 --- a/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py +++ b/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class Radar9673644TestCase(TestBase): @@ -22,7 +23,7 @@ class Radar9673644TestCase(TestBase): self.main_source = "main.c" self.line = line_number(self.main_source, '// Set breakpoint here.') - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_expr_commands(self): """The following expression commands should just work.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py b/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py index ec3e7f93af26..8c9a9a5a27e7 100644 --- a/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py +++ b/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py @@ -19,8 +19,9 @@ import unittest2 import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class BasicExprCommandsTestCase(TestBase): @@ -56,7 +57,6 @@ class BasicExprCommandsTestCase(TestBase): patterns = ["\(float\) \$.* = 2\.234"]) # (float) $2 = 2.234 - @expectedFailureWindows("llvm.org/pr21765") def test_many_expr_commands(self): self.build_and_run() @@ -98,7 +98,7 @@ class BasicExprCommandsTestCase(TestBase): # (const char *) $8 = 0x... "/Volumes/data/lldb/svn/trunk/test/expression_command/test/a.out" @add_test_categories(['pyapi']) - @expectedFailureWindows # Test crashes + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_evaluate_expression_python(self): """Test SBFrame.EvaluateExpression() API for evaluating an expression.""" self.build() @@ -130,12 +130,8 @@ class BasicExprCommandsTestCase(TestBase): "instead the actual state is: '%s'" % lldbutil.state_type_to_str(process.GetState())) - # The stop reason of the thread should be breakpoint. - thread = process.GetThreadAtIndex(0) - if thread.GetStopReason() != lldb.eStopReasonBreakpoint: - from lldbsuite.test.lldbutil import stop_reason_to_str - self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % - stop_reason_to_str(thread.GetStopReason())) + thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, breakpoint) + self.assertIsNotNone(thread, "Expected one thread to be stopped at the breakpoint") # The filename of frame #0 should be 'main.cpp' and function is main. self.expect(lldbutil.get_filenames(thread)[0], @@ -198,7 +194,7 @@ class BasicExprCommandsTestCase(TestBase): # rdar://problem/8686536 # CommandInterpreter::HandleCommand is stripping \'s from input for WantsRawCommand commands - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_expr_commands_can_handle_quotes(self): """Throw some expression commands with quotes at lldb.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py b/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py index 578a037e9f0f..523ee51a9f18 100644 --- a/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py +++ b/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py @@ -8,8 +8,9 @@ from __future__ import print_function import os import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCommands2TestCase(TestBase): @@ -22,7 +23,7 @@ class ExprCommands2TestCase(TestBase): self.line = line_number('main.cpp', '// Please test many expressions while stopped at this line:') - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_more_expr_commands(self): """Test some more expression commands.""" self.build() diff --git a/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py b/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py index a602afc47edb..7cb4a647efb4 100644 --- a/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py +++ b/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py @@ -7,8 +7,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprCommandWithTimeoutsTestCase(TestBase): @@ -23,8 +24,7 @@ class ExprCommandWithTimeoutsTestCase(TestBase): @expectedFlakeyFreeBSD("llvm.org/pr19605") - @expectedFlakeyLinux("llvm.org/pr20275") - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows", "macosx"], bugnumber="llvm.org/pr21765") def test(self): """Test calling std::String member function.""" self.build() @@ -57,7 +57,7 @@ class ExprCommandWithTimeoutsTestCase(TestBase): frame = thread.GetFrameAtIndex(0) - value = frame.EvaluateExpression ("wait_a_while (200000)", options) + value = frame.EvaluateExpression("wait_a_while(300000)", options) self.assertTrue (value.IsValid()) self.assertFalse (value.GetError().Success()) @@ -65,7 +65,7 @@ class ExprCommandWithTimeoutsTestCase(TestBase): interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() - return_value = interp.HandleCommand ("expr -t 100 -u true -- wait_a_while(200000)", result) + return_value = interp.HandleCommand("expr -t 100 -u true -- wait_a_while(300000)", result) self.assertTrue (return_value == lldb.eReturnStatusFailed) # Okay, now do it again with long enough time outs: diff --git a/packages/Python/lldbsuite/test/expression_command/top-level/Makefile b/packages/Python/lldbsuite/test/expression_command/top-level/Makefile new file mode 100644 index 000000000000..7146f227b98a --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/top-level/Makefile @@ -0,0 +1,12 @@ +LEVEL = ../../make + +default: a.out dummy + +CXX_SOURCES := main.cpp test.cpp + +dummy: dummy.cpp + +clean:: + rm -rf dummy dummy.dSYM + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py b/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py new file mode 100644 index 000000000000..9a17624cb8e6 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/top-level/TestTopLevelExprs.py @@ -0,0 +1,89 @@ +""" +Test top-level expressions. +""" + +from __future__ import print_function + + + +import unittest2 + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TopLevelExpressionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number('main.cpp', + '// Set breakpoint here') + self.dummy_line = line_number('dummy.cpp', + '// Set breakpoint here') + + # Disable confirmation prompt to avoid infinite wait + self.runCmd("settings set auto-confirm true") + self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm")) + + + def build_and_run(self): + """Test top-level expressions.""" + self.build() + + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + def run_dummy(self): + self.runCmd("file dummy", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "dummy.cpp", self.dummy_line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + @add_test_categories(['pyapi']) + @expectedFailureAndroid(api_levels=[21, 22], bugnumber="llvm.org/pr27787") + @expectedFailureAll(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr27787") + @expectedFailureAll(bugnumber="llvm.org/pr28353", oslist=["linux"], archs=["i386", "x86_64"], compiler="gcc", compiler_version=["<", "4.9"]) + @skipIf(debug_info="gmodules") # not relevant + @skipIf(oslist=["windows"]) # Error in record layout on Windows + def test_top_level_expressions(self): + self.build_and_run() + + resultFromCode = self.frame().EvaluateExpression("doTest()").GetValueAsUnsigned() + + self.runCmd("kill") + + self.run_dummy() + + codeFile = open('test.cpp', 'r') + + expressions = [] + current_expression = "" + + for line in codeFile: + if line.startswith("// --"): + expressions.append(current_expression) + current_expression = "" + else: + current_expression += line + + options = lldb.SBExpressionOptions() + options.SetLanguage(lldb.eLanguageTypeC_plus_plus) + options.SetTopLevel(True) + + for expression in expressions: + self.frame().EvaluateExpression(expression, options) + + resultFromTopLevel = self.frame().EvaluateExpression("doTest()") + + self.assertTrue(resultFromTopLevel.IsValid()) + self.assertEqual(resultFromCode, resultFromTopLevel.GetValueAsUnsigned()) diff --git a/packages/Python/lldbsuite/test/expression_command/top-level/dummy.cpp b/packages/Python/lldbsuite/test/expression_command/top-level/dummy.cpp new file mode 100644 index 000000000000..31204b21d972 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/top-level/dummy.cpp @@ -0,0 +1,7 @@ +#include + +int main() +{ + printf("This is a dummy\n"); // Set breakpoint here + return 0; +} diff --git a/packages/Python/lldbsuite/test/expression_command/top-level/main.cpp b/packages/Python/lldbsuite/test/expression_command/top-level/main.cpp new file mode 100644 index 000000000000..f9b2dd4c6d9d --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/top-level/main.cpp @@ -0,0 +1,9 @@ +#include + +extern int doTest(); + +int main() +{ + printf("%d\n", doTest()); // Set breakpoint here + return 0; +} diff --git a/packages/Python/lldbsuite/test/expression_command/top-level/test.cpp b/packages/Python/lldbsuite/test/expression_command/top-level/test.cpp new file mode 100644 index 000000000000..ce2ea3bbb131 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/top-level/test.cpp @@ -0,0 +1,107 @@ +class MyClass +{ +public: + int memberResult() + { + return 1; + } + static int staticResult() + { + return 1; + } + int externResult(); +}; + +// -- + +int MyClass::externResult() +{ + return 1; +} + +// -- + +MyClass m; + +// -- + +enum MyEnum { + myEnumOne = 1, + myEnumTwo, + myEnumThree +}; + +// -- + +class AnotherClass +{ +public: + __attribute__ ((always_inline)) int complicatedFunction() + { + struct { + int i; + } s = { 15 }; + + int as[4] = { 2, 3, 4, 5 }; + + for (signed char a : as) + { + s.i -= a; + } + + return s.i; + } +}; + +// -- + +class DiamondA +{ +private: + struct { + int m_i; + }; +public: + DiamondA(int i) : m_i(i) { } + int accessor() { return m_i; } +}; + +// -- + +class DiamondB : public virtual DiamondA +{ +public: + DiamondB(int i) : DiamondA(i) { } +}; + +// -- + +class DiamondC : public virtual DiamondA +{ +public: + DiamondC(int i) : DiamondA(i) { } +}; + +// -- + +class DiamondD : public DiamondB, public DiamondC +{ +public: + DiamondD(int i) : DiamondA(i), DiamondB(i), DiamondC(i) { } +}; + +// -- + +int doTest() +{ + int a = m.memberResult(); + a += MyClass::staticResult(); + a += m.externResult(); + a += MyEnum::myEnumThree; + a += myEnumOne; + a += AnotherClass().complicatedFunction(); + a += DiamondD(3).accessor(); + return a; +} + +// -- diff --git a/packages/Python/lldbsuite/test/expression_command/two-files/TestObjCTypeQueryFromOtherCompileUnit.py b/packages/Python/lldbsuite/test/expression_command/two-files/TestObjCTypeQueryFromOtherCompileUnit.py index 5b0233509112..2b37faad807b 100644 --- a/packages/Python/lldbsuite/test/expression_command/two-files/TestObjCTypeQueryFromOtherCompileUnit.py +++ b/packages/Python/lldbsuite/test/expression_command/two-files/TestObjCTypeQueryFromOtherCompileUnit.py @@ -9,8 +9,9 @@ from __future__ import print_function import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ObjCTypeQueryTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/Makefile b/packages/Python/lldbsuite/test/expression_command/unwind_expression/Makefile new file mode 100644 index 000000000000..8a7102e347af --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py new file mode 100644 index 000000000000..6e9af641d038 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py @@ -0,0 +1,83 @@ +""" +Test stopping at a breakpoint in an expression, and unwinding from there. +""" + +from __future__ import print_function + + + +import unittest2 + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class UnwindFromExpressionTest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + @add_test_categories(['pyapi']) + + def test_unwind_expression(self): + """Test unwinding from an expression.""" + self.build() + + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint. + main_spec = lldb.SBFileSpec("main.cpp", False) + breakpoint = target.BreakpointCreateBySourceRegex("// Set a breakpoint here to get started", main_spec) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.LaunchProcess() failed") + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, breakpoint) + self.assertIsNotNone(thread, "Expected one thread to be stopped at the breakpoint") + + # + # Use Python API to evaluate expressions while stopped in a stack frame. + # + main_frame = thread.GetFrameAtIndex(0) + + # Next set a breakpoint in this function, set up Expression options to stop on + # breakpoint hits, and call the function. + fun_bkpt = target.BreakpointCreateBySourceRegex("// Stop inside the function here.", main_spec) + self.assertTrue(fun_bkpt, VALID_BREAKPOINT) + options = lldb.SBExpressionOptions() + options.SetIgnoreBreakpoints(False) + options.SetUnwindOnError(False) + + val = main_frame.EvaluateExpression("a_function_to_call()", options) + + self.assertTrue(val.GetError().Fail(), "We did not complete the execution.") + error_str = val.GetError().GetCString() + self.assertTrue("Execution was interrupted, reason: breakpoint" in error_str, "And the reason was right.") + + thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, fun_bkpt) + self.assertTrue(thread.IsValid(), "We are indeed stopped at our breakpoint") + + # Now unwind the expression, and make sure we got back to where we started. + error = thread.UnwindInnermostExpression() + self.assertTrue(error.Success(), "We succeeded in unwinding") + + cur_frame = thread.GetFrameAtIndex(0) + self.assertTrue(cur_frame.IsEqual(main_frame), "We got back to the main frame.") + diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp b/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp new file mode 100644 index 000000000000..e93c34a30b03 --- /dev/null +++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp @@ -0,0 +1,14 @@ +static int static_value = 0; + +int +a_function_to_call() +{ + static_value++; // Stop inside the function here. + return static_value; +} + +int main (int argc, char const *argv[]) +{ + a_function_to_call(); // Set a breakpoint here to get started + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/abbreviation/TestAbbreviations.py b/packages/Python/lldbsuite/test/functionalities/abbreviation/TestAbbreviations.py index 1bce5bed491f..6423ecf27aeb 100644 --- a/packages/Python/lldbsuite/test/functionalities/abbreviation/TestAbbreviations.py +++ b/packages/Python/lldbsuite/test/functionalities/abbreviation/TestAbbreviations.py @@ -8,14 +8,14 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class AbbreviationsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFlakeyFreeBSD("llvm.org/pr22611 thread race condition breaks prompt setting") @no_debug_info_test def test_command_abbreviations_and_aliases (self): command_interpreter = self.dbg.GetCommandInterpreter() diff --git a/packages/Python/lldbsuite/test/functionalities/abbreviation/TestCommonShortSpellings.py b/packages/Python/lldbsuite/test/functionalities/abbreviation/TestCommonShortSpellings.py index 9edbf212278c..fa6f3f306898 100644 --- a/packages/Python/lldbsuite/test/functionalities/abbreviation/TestCommonShortSpellings.py +++ b/packages/Python/lldbsuite/test/functionalities/abbreviation/TestCommonShortSpellings.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CommonShortSpellingsTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/apropos_with_process/Makefile b/packages/Python/lldbsuite/test/functionalities/apropos_with_process/Makefile new file mode 100644 index 000000000000..8a7102e347af --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/apropos_with_process/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/apropos_with_process/TestAproposWithProcess.py b/packages/Python/lldbsuite/test/functionalities/apropos_with_process/TestAproposWithProcess.py new file mode 100644 index 000000000000..66ed3ff73298 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/apropos_with_process/TestAproposWithProcess.py @@ -0,0 +1,44 @@ +""" +Test that apropos env doesn't crash trying to touch the process plugin commmand +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class AproposWithProcessTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// break here') + + def test_apropos_with_process(self): + """Test that apropos env doesn't crash trying to touch the process plugin commmand.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break in main() aftre the variables are assigned values. + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) + + self.runCmd('apropos env') diff --git a/packages/Python/lldbsuite/test/functionalities/apropos_with_process/main.cpp b/packages/Python/lldbsuite/test/functionalities/apropos_with_process/main.cpp new file mode 100644 index 000000000000..44c149687f21 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/apropos_with_process/main.cpp @@ -0,0 +1,15 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +int main (int argc, char const *argv[]) +{ + return 0; // break here +} + diff --git a/packages/Python/lldbsuite/test/functionalities/archives/TestBSDArchives.py b/packages/Python/lldbsuite/test/functionalities/archives/TestBSDArchives.py index 02e1b9551853..b419ad97a694 100644 --- a/packages/Python/lldbsuite/test/functionalities/archives/TestBSDArchives.py +++ b/packages/Python/lldbsuite/test/functionalities/archives/TestBSDArchives.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BSDArchivesTestCase(TestBase): @@ -19,7 +20,8 @@ class BSDArchivesTestCase(TestBase): # Find the line number in a(int) to break at. self.line = line_number('a.c', '// Set file and line breakpoint inside a().') - @expectedFailureWindows("llvm.org/pr24527") # Makefile.rules doesn't know how to build static libs on Windows. + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24527. Makefile.rules doesn't know how to build static libs on Windows") + @expectedFailureAll(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr27795") def test(self): """Break inside a() and b() defined within libfoo.a.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/asan/TestMemoryHistory.py b/packages/Python/lldbsuite/test/functionalities/asan/TestMemoryHistory.py index e92b967d8adf..6416bccc483d 100644 --- a/packages/Python/lldbsuite/test/functionalities/asan/TestMemoryHistory.py +++ b/packages/Python/lldbsuite/test/functionalities/asan/TestMemoryHistory.py @@ -8,18 +8,19 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbutil class AsanTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureLinux # non-core functionality, need to reenable and fix later (DES 2014.11.07) + @expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default @skipIfRemote @skipUnlessCompilerRt - @expectedFailureDarwin def test (self): self.build () self.asan_tests () @@ -45,11 +46,10 @@ class AsanTestCase(TestBase): self.runCmd("run") - # ASan will relaunch the process to insert its library. - self.expect("thread list", "Process should be stopped due to exec.", - substrs = ['stopped', 'stop reason = ']) - - self.runCmd("continue") + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable interceptors. + self.runCmd("continue") # the stop reason of the thread should be breakpoint. self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, @@ -62,8 +62,8 @@ class AsanTestCase(TestBase): # test the 'memory history' command self.expect("memory history 'pointer'", substrs = [ - 'Memory allocated at', 'a.out`f1', 'main.c:%d' % self.line_malloc, - 'Memory deallocated at', 'a.out`f2', 'main.c:%d' % self.line_free]) + 'Memory allocated by Thread', 'a.out`f1', 'main.c:%d' % self.line_malloc, + 'Memory deallocated by Thread', 'a.out`f2', 'main.c:%d' % self.line_free]) # do the same using SB API process = self.dbg.GetSelectedTarget().process @@ -87,17 +87,14 @@ class AsanTestCase(TestBase): self.assertTrue(history_thread.num_frames >= 2) self.assertEqual(history_thread.frames[1].GetLineEntry().GetFileSpec().GetFilename(), "main.c") self.assertEqual(history_thread.frames[1].GetLineEntry().GetLine(), self.line_malloc) - - # now let's break when an ASan report occurs and try the API then - self.runCmd("breakpoint set -n __asan_report_error") - + + # ASan will break when a report occurs and we'll try the API then self.runCmd("continue") - # the stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', 'stop reason = breakpoint']) + self.expect("thread list", "Process should be stopped due to ASan report", + substrs = ['stopped', 'stop reason = Use of deallocated memory detected']) # make sure the 'memory history' command still works even when we're generating a report now self.expect("memory history 'another_pointer'", substrs = [ - 'Memory allocated at', 'a.out`f1', 'main.c:%d' % self.line_malloc2]) + 'Memory allocated by Thread', 'a.out`f1', 'main.c:%d' % self.line_malloc2]) diff --git a/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py b/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py index 4ef587895196..b02732ddeddf 100644 --- a/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py +++ b/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py @@ -7,20 +7,20 @@ from __future__ import print_function import os, time +import json import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import json +from lldbsuite.test import lldbutil class AsanTestReportDataCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureLinux # non-core functionality, need to reenable and fix later (DES 2014.11.07) + @expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default @skipIfRemote @skipUnlessCompilerRt - @expectedFailureDarwin def test(self): self.build () self.asan_tests () @@ -39,16 +39,10 @@ class AsanTestReportDataCase(TestBase): self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ]) self.runCmd("run") - # ASan will relaunch the process to insert its library. - self.expect("thread list", "Process should be stopped due to exec.", - substrs = ['stopped', 'stop reason = ']) - - # no extended info when we have no ASan report - thread = self.dbg.GetSelectedTarget().process.GetSelectedThread() - s = lldb.SBStream() - self.assertFalse(thread.GetStopReasonExtendedInfoAsJSON(s)) - - self.runCmd("continue") + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable interceptors. + self.runCmd("continue") self.expect("thread list", "Process should be stopped due to ASan report", substrs = ['stopped', 'stop reason = Use of deallocated memory detected']) @@ -62,7 +56,7 @@ class AsanTestReportDataCase(TestBase): substrs = ["access_size", "access_type", "address", "pc", "description", "heap-use-after-free"]) output_lines = self.res.GetOutput().split('\n') - json_line = output_lines[2] + json_line = '\n'.join(output_lines[2:]) data = json.loads(json_line) self.assertEqual(data["description"], "heap-use-after-free") self.assertEqual(data["instrumentation_class"], "AddressSanitizer") diff --git a/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py b/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py index 693c0a70fd62..54463c56827a 100644 --- a/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py +++ b/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil exe_name = "AttachResume" # Must match Makefile @@ -18,8 +19,8 @@ class AttachResumeTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfRemote - @expectedFailureFreeBSD('llvm.org/pr19310') - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr19310') + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_attach_continue_interrupt_detach(self): """Test attach/continue/interrupt/detach""" self.build() @@ -37,19 +38,20 @@ class AttachResumeTestCase(TestBase): self.setAsync(True) listener = self.dbg.GetListener() + process = self.dbg.GetSelectedTarget().GetProcess() self.runCmd("c") - lldbutil.expect_state_changes(self, listener, [lldb.eStateRunning]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning]) self.runCmd("process interrupt") - lldbutil.expect_state_changes(self, listener, [lldb.eStateStopped]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateStopped]) # be sure to continue/interrupt/continue (r204504) self.runCmd("c") - lldbutil.expect_state_changes(self, listener, [lldb.eStateRunning]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning]) self.runCmd("process interrupt") - lldbutil.expect_state_changes(self, listener, [lldb.eStateStopped]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateStopped]) # Second interrupt should have no effect. self.expect("process interrupt", patterns=["Process is not running"], error=True) @@ -58,7 +60,7 @@ class AttachResumeTestCase(TestBase): self.runCmd("br set -f main.cpp -l %u" % (line_number('main.cpp', '// Set breakpoint here'))) self.runCmd("c") - lldbutil.expect_state_changes(self, listener, [lldb.eStateRunning, lldb.eStateStopped]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning, lldb.eStateStopped]) self.expect('br list', 'Breakpoint not hit', substrs = ['hit count = 1']) @@ -66,8 +68,8 @@ class AttachResumeTestCase(TestBase): self.expect("expr debugger_flag = false", substrs=[" = false"]); self.runCmd("c") - lldbutil.expect_state_changes(self, listener, [lldb.eStateRunning]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning]) # make sure to detach while in running state (r204759) self.runCmd("detach") - lldbutil.expect_state_changes(self, listener, [lldb.eStateDetached]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateDetached]) diff --git a/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py b/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py index e4bc08711f4c..e31eac48ad7a 100644 --- a/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py +++ b/packages/Python/lldbsuite/test/functionalities/avoids-fd-leak/TestFdLeak.py @@ -8,29 +8,34 @@ from __future__ import print_function import os import lldb +from lldbsuite.test import lldbutil from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * def python_leaky_fd_version(test): import sys # Python random module leaks file descriptors on some versions. - return sys.version_info >= (2, 7, 8) and sys.version_info < (2, 7, 10) + if sys.version_info >= (2, 7, 8) and sys.version_info < (2, 7, 10): + return "Python random module leaks file descriptors in this python version" + return None class AvoidsFdLeakTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + mydir = TestBase.compute_mydir(__file__) @expectedFailure(python_leaky_fd_version, "bugs.freebsd.org/197376") - @expectedFailureFreeBSD("llvm.org/pr25624 still failing with Python 2.7.10") + @expectedFailureAll(oslist=['freebsd'], bugnumber="llvm.org/pr25624 still failing with Python 2.7.10") @skipIfWindows # The check for descriptor leakage needs to be implemented differently here. @skipIfTargetAndroid() # Android have some other file descriptors open by the shell def test_fd_leak_basic (self): self.do_test([]) @expectedFailure(python_leaky_fd_version, "bugs.freebsd.org/197376") - @expectedFailureFreeBSD("llvm.org/pr25624 still failing with Python 2.7.10") + @expectedFailureAll(oslist=['freebsd'], bugnumber="llvm.org/pr25624 still failing with Python 2.7.10") @skipIfWindows # The check for descriptor leakage needs to be implemented differently here. @skipIfTargetAndroid() # Android have some other file descriptors open by the shell def test_fd_leak_log (self): @@ -53,8 +58,7 @@ class AvoidsFdLeakTestCase(TestBase): "Process returned non-zero status. Were incorrect file descriptors passed?") @expectedFailure(python_leaky_fd_version, "bugs.freebsd.org/197376") - @expectedFailureFreeBSD("llvm.org/pr25624 still failing with Python 2.7.10") - @expectedFlakeyLinux + @expectedFailureAll(oslist=['freebsd'], bugnumber="llvm.org/pr25624 still failing with Python 2.7.10") @skipIfWindows # The check for descriptor leakage needs to be implemented differently here. @skipIfTargetAndroid() # Android have some other file descriptors open by the shell def test_fd_leak_multitarget (self): diff --git a/packages/Python/lldbsuite/test/functionalities/backticks/TestBackticksWithoutATarget.py b/packages/Python/lldbsuite/test/functionalities/backticks/TestBackticksWithoutATarget.py index d31412bc783c..851e4d376b38 100644 --- a/packages/Python/lldbsuite/test/functionalities/backticks/TestBackticksWithoutATarget.py +++ b/packages/Python/lldbsuite/test/functionalities/backticks/TestBackticksWithoutATarget.py @@ -8,7 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class BackticksWithNoTargetTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py new file mode 100644 index 000000000000..73b3ef5eae28 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/address_breakpoints/TestBadAddressBreakpoints.py @@ -0,0 +1,77 @@ +""" +Test that breakpoints set on a bad address say they are bad. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class BadAddressBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_bad_address_breakpoints (self): + """Test that breakpoints set on a bad address say they are bad.""" + self.build() + self.address_breakpoints() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def address_breakpoints(self): + """Test that breakpoints set on a bad address say they are bad.""" + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateBySourceRegex("Set a breakpoint here", lldb.SBFileSpec("main.c")) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + launch_info = lldb.SBLaunchInfo(None) + + error = lldb.SBError() + + process = target.Launch (launch_info, error) + self.assertTrue(process, PROCESS_IS_VALID) + + # Did we hit our breakpoint? + from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint + threads = get_threads_stopped_at_breakpoint (process, breakpoint) + self.assertTrue(len(threads) == 1, "There should be a thread stopped at our breakpoint") + + # The hit count for the breakpoint should be 1. + self.assertTrue(breakpoint.GetHitCount() == 1) + + # Now see if we can read from 0. If I can't do that, I don't have a good way to know + # what an illegal address is... + error.Clear() + + ptr = process.ReadPointerFromMemory(0x0, error) + + if not error.Success(): + bkpt = target.BreakpointCreateByAddress(0x0) + for bp_loc in bkpt: + self.assertTrue(bp_loc.IsResolved() == False) + else: + self.fail("Could not find an illegal address at which to set a bad breakpoint.") + + diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/Makefile new file mode 100644 index 000000000000..6067ee45e984 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py new file mode 100644 index 000000000000..aa4ee14ffc5a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/TestBreakpointCaseSensitivity.py @@ -0,0 +1,121 @@ +""" +Test case sensitivity of paths on Windows / POSIX +llvm.org/pr22667 +""" + +import os +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test import lldbplatform, lldbplatformutil + +class BreakpointCaseSensitivityTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + BREAKPOINT_TEXT = 'Set a breakpoint here' + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line = line_number('main.c', self.BREAKPOINT_TEXT) + + @skipIf(oslist=no_match(['windows'])) # Skip for non-windows platforms + def test_breakpoint_matches_file_with_different_case(self): + """Set breakpoint on file, should match files with different case on Windows""" + self.build() + self.case_sensitivity_breakpoint(True) + + @skipIf(oslist=['windows']) # Skip for windows platforms + @expectedFailureAll() # Failing for unknown reason on non-Windows platforms. + def test_breakpoint_doesnt_match_file_with_different_case(self): + """Set breakpoint on file, shouldn't match files with different case on POSIX systems""" + self.build() + self.case_sensitivity_breakpoint(False) + + def case_sensitivity_breakpoint(self, case_insensitive): + """Set breakpoint on file, should match files with different case if case_insensitive is True""" + + # use different case to check CreateTarget + exe = 'a.out' + if case_insensitive: + exe = exe.upper() + + exe = os.path.join(os.getcwd(), exe) + + # Create a target by the debugger. + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + cwd = self.get_process_working_directory(); + + # try both BreakpointCreateByLocation and BreakpointCreateBySourceRegex + for regex in [False, True]: + # should always hit + self.check_breakpoint('main.c', regex, True) + # should always hit + self.check_breakpoint(os.path.join(cwd, 'main.c'), regex, True) + # different case for directory + self.check_breakpoint(os.path.join(cwd.upper(), 'main.c'), + regex, + case_insensitive) + # different case for file + self.check_breakpoint('Main.c', + regex, + case_insensitive) + # different case for both + self.check_breakpoint(os.path.join(cwd.upper(), 'Main.c'), + regex, + case_insensitive) + + def check_breakpoint(self, file, source_regex, should_hit): + """ + Check breakpoint hit at given file set by given method + + file: + File where insert the breakpoint + + source_regex: + True for testing using BreakpointCreateBySourceRegex, + False for BreakpointCreateByLocation + + should_hit: + True if the breakpoint should hit, False otherwise + """ + + desc = ' file %s set by %s' % (file, 'regex' if source_regex else 'location') + if source_regex: + breakpoint = self.target.BreakpointCreateBySourceRegex(self.BREAKPOINT_TEXT, + lldb.SBFileSpec(file)) + else: + breakpoint = self.target.BreakpointCreateByLocation(file, self.line) + + self.assertEqual(breakpoint and breakpoint.GetNumLocations() == 1, + should_hit, + VALID_BREAKPOINT + desc) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertEqual(location and location.IsEnabled(), + should_hit, + VALID_BREAKPOINT_LOCATION + desc) + + process = self.target.LaunchSimple(None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID + desc) + + if should_hit: + # Did we hit our breakpoint? + from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint + threads = get_threads_stopped_at_breakpoint (process, breakpoint) + self.assertEqual(len(threads), 1, "There should be a thread stopped at breakpoint" + desc) + # The hit count for the breakpoint should be 1. + self.assertEqual(breakpoint.GetHitCount(), 1) + + else: + # check the breakpoint was not hit + self.assertEqual(lldb.eStateExited, process.GetState()) + self.assertEqual(breakpoint.GetHitCount(), 0) + + # let process finish + process.Continue() + + # cleanup + self.target.BreakpointDelete(breakpoint.GetID()) diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/main.c new file mode 100644 index 000000000000..281ddfe7ef67 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_case_sensitivity/main.c @@ -0,0 +1,8 @@ +#include + +int +main() +{ + printf("Set a breakpoint here.\n"); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py index 8cf7539432ba..78d14b7d7705 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BreakpointCommandTestCase(TestBase): @@ -21,7 +22,7 @@ class BreakpointCommandTestCase(TestBase): cls.RemoveTempFile("output.txt") cls.RemoveTempFile("output2.txt") - @expectedFailureWindows("llvm.org/pr24528") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") def test(self): """Test a sequence of breakpoint command add, list, and delete.""" self.build() @@ -142,7 +143,7 @@ class BreakpointCommandTestCase(TestBase): self.expect("breakpoint command list 1", startstr = "Breakpoint 1 does not have an associated command.") self.expect("breakpoint command list 2", error=True, - startstr = "error: '2' is not a currently valid breakpoint id.") + startstr = "error: '2' is not a currently valid breakpoint ID.") # The breakpoint list now only contains breakpoint 1. self.expect("breakpoint list -f", "Breakpoint 1 exists", diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py index 7a9cc744d528..4f8ab9e115de 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommandsFromPython.py @@ -8,10 +8,11 @@ from __future__ import print_function import os import re -import lldb -import lldbsuite.test.lldbutil as lldbutil import sys +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class PythonBreakpointCommandSettingTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py index 8c22c8fe869c..0d34dd85dc50 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class BreakpointConditionsTestCase(TestBase): @@ -107,11 +108,13 @@ class BreakpointConditionsTestCase(TestBase): if arch in ['x86_64', 'i386']: self.runCmd("breakpoint modify -c ($eax&&i)") elif arch in ['aarch64']: - self.runCmd("breakpoint modify -c ($x1&&i)") + self.runCmd("breakpoint modify -c ($x0&&i)") elif arch in ['arm']: self.runCmd("breakpoint modify -c ($r0&&i)") elif re.match("mips",arch): self.runCmd("breakpoint modify -c ($r2&&i)") + elif arch in ['s390x']: + self.runCmd("breakpoint modify -c ($r2&&i)") self.runCmd("run") self.expect("process status", PROCESS_STOPPED, @@ -178,4 +181,8 @@ class BreakpointConditionsTestCase(TestBase): # The hit count for the breakpoint should be 1. self.assertTrue(breakpoint.GetHitCount() == 1) + # Test that the condition expression didn't create a result variable: + options = lldb.SBExpressionOptions() + value = frame0.EvaluateExpression("$0", options) + self.assertTrue(value.GetError().Fail(), "Conditions should not make result variables.") process.Continue() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py index 8a83cb627f7a..05ef1c6d94c7 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class BreakpointIgnoreCountTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py index 324401ff44e1..b1e0d3deeae7 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py @@ -8,14 +8,15 @@ import os, time import re import unittest2 import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class AvoidBreakpointInDelaySlotAPITestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipUnlessArch(archs=re.compile('mips*')) + @skipIf(archs=no_match(re.compile('mips*'))) def test(self): self.build() exe = os.path.join(os.getcwd(), "a.out") diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py index 5c4dc219a106..707b6502e91c 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py @@ -8,15 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BreakpointLocationsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr24528") - @expectedFailureAll(oslist=["linux"], compiler="clang", compiler_version=["=", "3.8"], archs=["i386"], debug_info="dwo") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528") def test(self): """Test breakpoint enable/disable for a breakpoint ID with multiple locations.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py new file mode 100644 index 000000000000..4ca93765b656 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/TestBreakpointSetRestart.py @@ -0,0 +1,43 @@ +""" +Test inferior restart when breakpoint is set on running target. +""" + +import os +import lldb +from lldbsuite.test.lldbtest import * + +class BreakpointSetRestart(TestBase): + + mydir = TestBase.compute_mydir(__file__) + BREAKPOINT_TEXT = 'Set a breakpoint here' + + def test_breakpoint_set_restart(self): + self.build() + + cwd = os.getcwd() + exe = os.path.join(cwd, 'a.out') + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.dbg.SetAsync(True) + process = target.LaunchSimple(None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + event = lldb.SBEvent() + # Wait for inferior to transition to running state + while self.dbg.GetListener().WaitForEvent(2, event): + if lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateRunning: + break + + bp = target.BreakpointCreateBySourceRegex(self.BREAKPOINT_TEXT, + lldb.SBFileSpec(os.path.join(cwd, 'main.cpp'))) + self.assertTrue(bp.IsValid() and bp.GetNumLocations() == 1, VALID_BREAKPOINT) + + while self.dbg.GetListener().WaitForEvent(2, event): + if lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and lldb.SBProcess.GetRestartedFromEvent(event): + continue + if lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateRunning: + continue + self.fail("Setting a breakpoint generated an unexpected event: %s" % lldb.SBDebugger.StateAsCString(lldb.SBProcess.GetStateFromEvent(event))) + diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp new file mode 100644 index 000000000000..e6d3a95d017f --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_set_restart/main.cpp @@ -0,0 +1,25 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + + +int main(int argc, char const *argv[]) +{ + static bool done = false; + while (!done) + { + std::this_thread::sleep_for(std::chrono::milliseconds{100}); + } + printf("Set a breakpoint here.\n"); + return 0; +} + diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py index e1de38bcad8c..4933d6d01d44 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/comp_dir_symlink/TestCompDirSymLink.py @@ -6,10 +6,11 @@ from __future__ import print_function import os +import shutil import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import shutil +from lldbsuite.test import lldbutil _EXE_NAME = 'CompDirSymLink' # Must match Makefile @@ -27,21 +28,21 @@ class CompDirSymLinkTestCase(TestBase): self.line = line_number(_SRC_FILE, '// Set break point at this line.') self.src_path = os.path.join(os.getcwd(), _SRC_FILE) - @skipIfHostWindows + @skipIf(hostoslist=["windows"]) def test_symlink_paths_set(self): pwd_symlink = self.create_src_symlink() self.doBuild(pwd_symlink) self.runCmd("settings set %s %s" % (_COMP_DIR_SYM_LINK_PROP, pwd_symlink)) lldbutil.run_break_set_by_file_and_line(self, self.src_path, self.line) - @skipUnlessHostLinux + @skipIf(hostoslist=no_match(["linux"])) def test_symlink_paths_set_procselfcwd(self): pwd_symlink = '/proc/self/cwd' self.doBuild(pwd_symlink) self.runCmd("settings set %s %s" % (_COMP_DIR_SYM_LINK_PROP, pwd_symlink)) lldbutil.run_break_set_by_file_and_line(self, self.src_path, self.line) - @skipIfHostWindows + @skipIf(hostoslist=["windows"]) def test_symlink_paths_unset(self): pwd_symlink = self.create_src_symlink() self.doBuild(pwd_symlink) diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/Makefile deleted file mode 100644 index f89b52a972e9..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -LEVEL = ../../../make - -CXX_SOURCES := main.cpp - -ifneq (,$(findstring icc,$(CC))) - CXXFLAGS += -debug inline-debug-info -endif - -include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/TestConsecutiveBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/TestConsecutiveBreakpoints.py deleted file mode 100644 index af6df3764829..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/TestConsecutiveBreakpoints.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Test continue from a breakpoint when there is a breakpoint on the next instruction also. -""" - -from __future__ import print_function - - - -import unittest2 -import lldb -import lldbsuite.test.lldbutil as lldbutil -from lldbsuite.test.lldbtest import * - -class ConsecutiveBreakpoitsTestCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - @expectedFailureAll("llvm.org/pr23478", oslist = not_in(["macosx"])) - def test (self): - self.build () - self.consecutive_breakpoints_tests() - - def consecutive_breakpoints_tests(self): - exe = os.path.join (os.getcwd(), "a.out") - - # Create a target by the debugger. - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex("Set breakpoint here", lldb.SBFileSpec("main.cpp")) - self.assertTrue(breakpoint and - breakpoint.GetNumLocations() == 1, - VALID_BREAKPOINT) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple (None, None, self.get_process_working_directory()) - self.assertTrue(process, PROCESS_IS_VALID) - - # We should be stopped at the first breakpoint - thread = process.GetThreadAtIndex(0) - self.assertEqual(thread.GetStopReason(), lldb.eStopReasonBreakpoint) - - # Set breakpoint to the next instruction - frame = thread.GetFrameAtIndex(0) - - address = frame.GetPCAddress() - instructions = target.ReadInstructions(address, 2) - self.assertTrue(len(instructions) == 2) - address = instructions[1].GetAddress() - - target.BreakpointCreateByAddress(address.GetLoadAddress(target)) - process.Continue() - - # We should be stopped at the second breakpoint - thread = process.GetThreadAtIndex(0) - self.assertEqual(thread.GetStopReason(), lldb.eStopReasonBreakpoint) - - # Run the process until termination - process.Continue() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/main.cpp b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/main.cpp deleted file mode 100644 index c1943f03dbf1..000000000000 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoins/main.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//===-- main.cpp ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -int -main(int argc, char const *argv[]) -{ - int a = 0; - int b = 1; - a = b + 1; // Set breakpoint here - b = a + 1; - return 0; -} - diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile new file mode 100644 index 000000000000..f89b52a972e9 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +ifneq (,$(findstring icc,$(CC))) + CXXFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py new file mode 100644 index 000000000000..472479391c02 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/TestConsecutiveBreakpoints.py @@ -0,0 +1,101 @@ +""" +Test that we handle breakpoints on consecutive instructions correctly. +""" + +from __future__ import print_function + + + +import unittest2 +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ConsecutiveBreakpointsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def prepare_test(self): + self.build() + exe = os.path.join (os.getcwd(), "a.out") + + # Create a target by the debugger. + self.target = self.dbg.CreateTarget(exe) + self.assertTrue(self.target, VALID_TARGET) + + breakpoint1 = self.target.BreakpointCreateBySourceRegex("Set breakpoint here", lldb.SBFileSpec("main.cpp")) + self.assertTrue(breakpoint1 and breakpoint1.GetNumLocations() == 1, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + self.process = self.target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertIsNotNone(self.process, PROCESS_IS_VALID) + + # We should be stopped at the first breakpoint + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, breakpoint1) + self.assertIsNotNone(self.thread, "Expected one thread to be stopped at breakpoint 1") + + # Set breakpoint to the next instruction + frame = self.thread.GetFrameAtIndex(0) + + address = frame.GetPCAddress() + instructions = self.target.ReadInstructions(address, 2) + self.assertTrue(len(instructions) == 2) + self.bkpt_address = instructions[1].GetAddress() + self.breakpoint2 = self.target.BreakpointCreateByAddress(self.bkpt_address.GetLoadAddress(self.target)) + self.assertTrue(self.breakpoint2 and self.breakpoint2.GetNumLocations() == 1, VALID_BREAKPOINT) + + def finish_test(self): + # Run the process until termination + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateExited) + + @no_debug_info_test + def test_continue(self): + """Test that continue stops at the second breakpoint.""" + self.prepare_test() + + self.process.Continue() + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + # We should be stopped at the second breakpoint + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint2) + self.assertIsNotNone(self.thread, "Expected one thread to be stopped at breakpoint 2") + + self.finish_test() + + @no_debug_info_test + def test_single_step(self): + """Test that single step stops at the second breakpoint.""" + self.prepare_test() + + step_over = False + self.thread.StepInstruction(step_over) + + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals(self.thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress(self.target), + self.bkpt_address.GetLoadAddress(self.target)) + self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint2) + self.assertIsNotNone(self.thread, "Expected one thread to be stopped at breakpoint 2") + + self.finish_test() + + @no_debug_info_test + def test_single_step_thread_specific(self): + """Test that single step stops, even though the second breakpoint is not valid.""" + self.prepare_test() + + # Choose a thread other than the current one. A non-existing thread is fine. + thread_index = self.process.GetNumThreads()+1 + self.assertFalse(self.process.GetThreadAtIndex(thread_index).IsValid()) + self.breakpoint2.SetThreadIndex(thread_index) + + step_over = False + self.thread.StepInstruction(step_over) + + self.assertEquals(self.process.GetState(), lldb.eStateStopped) + self.assertEquals(self.thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress(self.target), + self.bkpt_address.GetLoadAddress(self.target)) + self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete, + "Stop reason should be 'plan complete'") + + self.finish_test() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp new file mode 100644 index 000000000000..c1943f03dbf1 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/consecutive_breakpoints/main.cpp @@ -0,0 +1,19 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +int +main(int argc, char const *argv[]) +{ + int a = 0; + int b = 1; + a = b + 1; // Set breakpoint here + b = a + 1; + return 0; +} + diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py index dea206b9e9d2..c2aa597214ed 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/TestCPPBreakpointLocations.py @@ -8,14 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestCPPBreakpointLocations(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr24764") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test (self): self.build () self.breakpoint_id_tests () @@ -25,7 +26,7 @@ class TestCPPBreakpointLocations(TestBase): name = bp_dict['name'] names = bp_dict['loc_names'] bp = target.BreakpointCreateByName (name) - self.assertTrue (bp.GetNumLocations() == len(names), "Make sure we find the right number of breakpoint locations") + self.assertEquals(bp.GetNumLocations(), len(names), "Make sure we find the right number of breakpoint locations") bp_loc_names = list() for bp_loc in bp: @@ -60,3 +61,35 @@ class TestCPPBreakpointLocations(TestBase): for bp_dict in bp_dicts: self.verify_breakpoint_locations(target, bp_dict) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") + def test_destructors(self): + self.build() + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + + # Don't skip prologue, so we can check the breakpoint address more easily + self.runCmd("settings set target.skip-prologue false") + try: + names = ['~c', 'c::~c', 'c::~c()'] + loc_names = {'a::c::~c()', 'b::c::~c()'} + # TODO: For windows targets we should put windows mangled names here + symbols = ['_ZN1a1cD1Ev', '_ZN1a1cD2Ev', '_ZN1b1cD1Ev', '_ZN1b1cD2Ev'] + + for name in names: + bp = target.BreakpointCreateByName(name) + + bp_loc_names = { bp_loc.GetAddress().GetFunction().GetName() for bp_loc in bp } + self.assertEquals(bp_loc_names, loc_names, "Breakpoint set on the correct symbol") + + bp_addresses = { bp_loc.GetLoadAddress() for bp_loc in bp } + symbol_addresses = set() + for symbol in symbols: + sc_list = target.FindSymbols(symbol, lldb.eSymbolTypeCode) + self.assertEquals(sc_list.GetSize(), 1, "Found symbol " + symbol) + symbol = sc_list.GetContextAtIndex(0).GetSymbol() + symbol_addresses.add(symbol.GetStartAddress().GetLoadAddress(target)) + + self.assertEquals(symbol_addresses, bp_addresses, "Breakpoint set on correct address") + finally: + self.runCmd("settings clear target.skip-prologue") diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp b/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp index ef582aa36ebb..01f679139249 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp/main.cpp @@ -12,8 +12,8 @@ namespace a { class c { public: - c () {} - ~c() {} + c(); + ~c(); void func1() { puts (__PRETTY_FUNCTION__); @@ -27,13 +27,16 @@ namespace a { puts (__PRETTY_FUNCTION__); } }; + + c::c() {} + c::~c() {} } namespace b { class c { public: - c () {} - ~c() {} + c(); + ~c(); void func1() { puts (__PRETTY_FUNCTION__); @@ -43,6 +46,9 @@ namespace b { puts (__PRETTY_FUNCTION__); } }; + + c::c() {} + c::~c() {} } namespace c { diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py index f7a19098b492..2aac3a9600d3 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/cpp_exception/TestCPPExceptionBreakpoint.py @@ -8,10 +8,11 @@ from __future__ import print_function import os import re -import lldb -import lldbsuite.test.lldbutil as lldbutil import sys +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestCPPExceptionBreakpoint (TestBase): @@ -19,7 +20,7 @@ class TestCPPExceptionBreakpoint (TestBase): my_var = 10 @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24538") # clang-cl does not support throw or catch + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24538") def test_cpp_exception_breakpoint(self): """Test setting and hitting the C++ exception breakpoint.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py index b32c970301c9..de61f9e88f1b 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/debugbreak/TestDebugBreak.py @@ -6,14 +6,15 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DebugBreakTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIf(archs=not_in(["i386", "i686"])) + @skipIf(archs=no_match(["i386", "i686", "x86_64"])) @no_debug_info_test def test_asm_int_3(self): """Test that intrinsics like `__debugbreak();` and `asm {"int3"}` are treated like breakpoints.""" @@ -26,13 +27,15 @@ class DebugBreakTestCase(TestBase): # We've hit the first stop, so grab the frame. self.assertEqual(process.GetState(), lldb.eStateStopped) - thread = process.GetThreadAtIndex(0) + stop_reason = lldb.eStopReasonException if (lldbplatformutil.getPlatform()=="windows" or lldbplatformutil.getPlatform()=="macosx") else lldb.eStopReasonSignal + thread = lldbutil.get_stopped_thread(process, stop_reason) + self.assertIsNotNone(thread, "Unable to find thread stopped at the __debugbreak()") frame = thread.GetFrameAtIndex(0) # We should be in funciton 'bar'. self.assertTrue(frame.IsValid()) function_name = frame.GetFunctionName() - self.assertTrue('bar' in function_name) + self.assertTrue('bar' in function_name, "Unexpected function name {}".format(function_name)) # We should be able to evaluate the parameter foo. value = frame.EvaluateExpression('*foo') diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py index 648a0f5ea07c..c48cee1bd2b2 100644 --- a/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/objc/TestObjCBreakpoints.py @@ -8,11 +8,12 @@ from __future__ import print_function import os, time -import lldb -from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil import shutil import subprocess +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil @skipUnlessDarwin class TestObjCBreakpoints(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile new file mode 100644 index 000000000000..ac984f101c18 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c a.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py new file mode 100644 index 000000000000..81cab927d214 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/TestSourceRegexBreakpoints.py @@ -0,0 +1,100 @@ +""" +Test lldb breakpoint setting by source regular expression. +This test just tests the source file & function restrictions. +""" + +from __future__ import print_function + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestSourceRegexBreakpoints(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_location (self): + self.build() + self.source_regex_locations() + + def test_restrictions (self): + self.build () + self.source_regex_restrictions () + + + def source_regex_locations (self): + """ Test that restricting source expressions to files & to functions. """ + # Create a target by the debugger. + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # First look just in main: + target_files = lldb.SBFileSpecList() + target_files.Append(lldb.SBFileSpec("a.c")) + + func_names = lldb.SBStringList() + func_names.AppendString("a_func") + + source_regex = "Set . breakpoint here" + main_break = target.BreakpointCreateBySourceRegex (source_regex, + lldb.SBFileSpecList(), + target_files, + func_names) + num_locations = main_break.GetNumLocations() + self.assertTrue(num_locations == 1, "a.c in a_func should give one breakpoint, got %d."%(num_locations)) + + loc = main_break.GetLocationAtIndex(0) + self.assertTrue(loc.IsValid(), "Got a valid location.") + address = loc.GetAddress() + self.assertTrue(address.IsValid(), "Got a valid address from the location.") + + a_func_line = line_number("a.c", "Set A breakpoint here") + line_entry = address.GetLineEntry() + self.assertTrue(line_entry.IsValid(), "Got a valid line entry.") + self.assertTrue(line_entry.line == a_func_line, "Our line number matches the one lldbtest found.") + + def source_regex_restrictions (self): + """ Test that restricting source expressions to files & to functions. """ + # Create a target by the debugger. + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # First look just in main: + target_files = lldb.SBFileSpecList() + target_files.Append(lldb.SBFileSpec("main.c")) + source_regex = "Set . breakpoint here" + main_break = target.BreakpointCreateBySourceRegex (source_regex, + lldb.SBFileSpecList(), + target_files, + lldb.SBStringList()) + + num_locations = main_break.GetNumLocations() + self.assertTrue(num_locations == 2, "main.c should have 2 matches, got %d."%(num_locations)) + + # Now look in both files: + target_files.Append(lldb.SBFileSpec("a.c")) + + main_break = target.BreakpointCreateBySourceRegex (source_regex, + lldb.SBFileSpecList(), + target_files, + lldb.SBStringList()) + + num_locations =main_break.GetNumLocations() + self.assertTrue(num_locations == 4, "main.c and a.c should have 4 matches, got %d."%(num_locations)) + + # Now restrict it to functions: + func_names = lldb.SBStringList() + func_names.AppendString("main_func") + main_break = target.BreakpointCreateBySourceRegex (source_regex, + lldb.SBFileSpecList(), + target_files, + func_names) + + num_locations =main_break.GetNumLocations() + self.assertTrue(num_locations == 2, "main_func in main.c and a.c should have 2 matches, got %d."%(num_locations)) + + diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c new file mode 100644 index 000000000000..056583f1c42c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.c @@ -0,0 +1,16 @@ +#include + +#include "a.h" + +static int +main_func(int input) +{ + return printf("Set B breakpoint here: %d", input); +} + +int +a_func(int input) +{ + input += 1; // Set A breakpoint here; + return main_func(input); +} diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h new file mode 100644 index 000000000000..f578ac0304cd --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/a.h @@ -0,0 +1 @@ +int a_func(int); diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c new file mode 100644 index 000000000000..9c8625e877f5 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/source_regexp/main.c @@ -0,0 +1,17 @@ +#include +#include "a.h" + +int +main_func(int input) +{ + return printf("Set B breakpoint here: %d.\n", input); +} + +int +main() +{ + a_func(10); + main_func(10); + printf("Set a breakpoint here:\n"); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/command_history/TestCommandHistory.py b/packages/Python/lldbsuite/test/functionalities/command_history/TestCommandHistory.py index 312c91517f98..66ba8d07622d 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_history/TestCommandHistory.py +++ b/packages/Python/lldbsuite/test/functionalities/command_history/TestCommandHistory.py @@ -8,7 +8,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class CommandHistoryTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/command_regex/TestCommandRegex.py b/packages/Python/lldbsuite/test/functionalities/command_regex/TestCommandRegex.py index 2c48efa863b4..5b680ec65de5 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_regex/TestCommandRegex.py +++ b/packages/Python/lldbsuite/test/functionalities/command_regex/TestCommandRegex.py @@ -8,13 +8,15 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class CommandRegexTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureHostWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @no_debug_info_test def test_command_regex(self): """Test a simple scenario of 'command regex' invocation and subsequent use.""" diff --git a/packages/Python/lldbsuite/test/functionalities/command_script/TestCommandScript.py b/packages/Python/lldbsuite/test/functionalities/command_script/TestCommandScript.py index 542ee7a1e5f3..97e52231e818 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_script/TestCommandScript.py +++ b/packages/Python/lldbsuite/test/functionalities/command_script/TestCommandScript.py @@ -87,8 +87,8 @@ class CmdPythonTestCase(TestBase): 'For more information run']) self.expect("help targetname", - substrs = ['This', 'command', 'takes', '\'raw\'', 'input', - 'quote', 'stuff']) + substrs = ['Expects', '\'raw\'', 'input', + 'help', 'raw-input']) self.expect("longwait", substrs = ['Done; if you saw the delays I am doing OK']) diff --git a/packages/Python/lldbsuite/test/functionalities/command_script/import/TestImport.py b/packages/Python/lldbsuite/test/functionalities/command_script/import/TestImport.py index 691045ae82ed..01c3f35bf300 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_script/import/TestImport.py +++ b/packages/Python/lldbsuite/test/functionalities/command_script/import/TestImport.py @@ -6,7 +6,9 @@ from __future__ import print_function import os, sys, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ImportTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/command_script/import/rdar-12586188/TestRdar12586188.py b/packages/Python/lldbsuite/test/functionalities/command_script/import/rdar-12586188/TestRdar12586188.py index 9800a08c06de..4f7ebebd4dd2 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_script/import/rdar-12586188/TestRdar12586188.py +++ b/packages/Python/lldbsuite/test/functionalities/command_script/import/rdar-12586188/TestRdar12586188.py @@ -6,7 +6,9 @@ from __future__ import print_function import os, sys, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class Rdar12586188TestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/command_script/import/thepackage/__init__.py b/packages/Python/lldbsuite/test/functionalities/command_script/import/thepackage/__init__.py index faa4e3b0cbff..1181462af868 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_script/import/thepackage/__init__.py +++ b/packages/Python/lldbsuite/test/functionalities/command_script/import/thepackage/__init__.py @@ -1,5 +1,7 @@ -import TPunitA -import TPunitB +from __future__ import absolute_import + +from . import TPunitA +from . import TPunitB def __lldb_init_module(debugger,*args): debugger.HandleCommand("command script add -f thepackage.TPunitA.command TPcommandA") diff --git a/packages/Python/lldbsuite/test/functionalities/command_script_alias/.categories b/packages/Python/lldbsuite/test/functionalities/command_script_alias/.categories new file mode 100644 index 000000000000..3a3f4df6416b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/command_script_alias/.categories @@ -0,0 +1 @@ +cmdline diff --git a/packages/Python/lldbsuite/test/functionalities/command_script_alias/TestCommandScriptAlias.py b/packages/Python/lldbsuite/test/functionalities/command_script_alias/TestCommandScriptAlias.py new file mode 100644 index 000000000000..694728a9f9c0 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/command_script_alias/TestCommandScriptAlias.py @@ -0,0 +1,37 @@ +""" +Test lldb Python commands. +""" + +from __future__ import print_function + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * + +class CommandScriptAliasTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test (self): + self.pycmd_tests () + + def pycmd_tests (self): + self.runCmd("command script import tcsacmd.py") + self.runCmd("command script add -f tcsacmd.some_command_here attach") + + # This is the function to remove the custom commands in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('command script delete attach', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # We don't want to display the stdout if not in TraceOn() mode. + if not self.TraceOn(): + self.HideStdout() + + self.expect('attach a', substrs = ['Victory is mine']); + self.runCmd("command script delete attach") + self.runCmd('attach noprocessexistswiththisname', check=False) # this can't crash but we don't care whether the actual attach works diff --git a/packages/Python/lldbsuite/test/functionalities/command_script_alias/tcsacmd.py b/packages/Python/lldbsuite/test/functionalities/command_script_alias/tcsacmd.py new file mode 100644 index 000000000000..6c60e3ca1a55 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/command_script_alias/tcsacmd.py @@ -0,0 +1,11 @@ +from __future__ import print_function +import lldb, sys + +def some_command_here(debugger, command, result, d): + if command == "a": + print("Victory is mine", file=result) + return True + else: + print("Sadness for all", file=result) + return False + diff --git a/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py new file mode 100644 index 000000000000..a843d08a97d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py @@ -0,0 +1,86 @@ +""" +Test that LLDB correctly allows scripted commands to set an immediate output file +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test.lldbpexpect import * +from lldbsuite.test import lldbutil + +class CommandScriptImmediateOutputTestCase (PExpectTest): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + PExpectTest.setUp(self) + + @skipIfRemote # test not remote-ready llvm.org/pr24813 + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr26139") + def test_command_script_immediate_output_console (self): + """Test that LLDB correctly allows scripted commands to set immediate output to the console.""" + self.launch(timeout=10) + + script = os.path.join(os.getcwd(), 'custom_command.py') + prompt = "\(lldb\) " + + self.sendline('command script import %s' % script, patterns=[prompt]) + self.sendline('command script add -f custom_command.command_function mycommand', patterns=[prompt]) + self.sendline('mycommand', patterns='this is a test string, just a test string') + self.sendline('command script delete mycommand', patterns=[prompt]) + self.quit(gracefully=False) + + @skipIfRemote # test not remote-ready llvm.org/pr24813 + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr26139") + def test_command_script_immediate_output_file (self): + """Test that LLDB correctly allows scripted commands to set immediate output to a file.""" + self.launch(timeout=10) + + test_files = {os.path.join(os.getcwd(), 'read.txt') :'r', + os.path.join(os.getcwd(), 'write.txt') :'w', + os.path.join(os.getcwd(), 'append.txt') :'a', + os.path.join(os.getcwd(), 'write_plus.txt') :'w+', + os.path.join(os.getcwd(), 'read_plus.txt') :'r+', + os.path.join(os.getcwd(), 'append_plus.txt') :'a+'} + + starter_string = 'Starter Garbage\n' + write_string = 'writing to file with mode: ' + + for path, mode in test_files.iteritems(): + with open(path, 'w+') as init: + init.write(starter_string) + + script = os.path.join(os.getcwd(), 'custom_command.py') + prompt = "\(lldb\) " + + self.sendline('command script import %s' % script, patterns=[prompt]) + + self.sendline('command script add -f custom_command.write_file mywrite', patterns=[prompt]) + for path, mode in test_files.iteritems(): + command = 'mywrite "' + path + '" ' + mode + + self.sendline(command, patterns=[prompt]) + + self.sendline('command script delete mywrite', patterns=[prompt]) + + self.quit(gracefully=False) + + for path, mode in test_files.iteritems(): + with open(path, 'r') as result: + if mode in ['r', 'a', 'a+']: + self.assertEquals(result.readline(), starter_string) + if mode in ['w', 'w+', 'r+', 'a', 'a+']: + self.assertEquals(result.readline(), write_string + mode + '\n') + + self.assertTrue(os.path.isfile(path)) + os.remove(path) + diff --git a/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/custom_command.py b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/custom_command.py new file mode 100644 index 000000000000..30a3cfb9093c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/custom_command.py @@ -0,0 +1,17 @@ +from __future__ import print_function + +import sys +import shlex + +def command_function(debugger, command, exe_ctx, result, internal_dict): + result.SetImmediateOutputFile(sys.__stdout__) + print('this is a test string, just a test string', file=result) + +def write_file(debugger, command, exe_ctx, result, internal_dict): + args = shlex.split(command) + path = args[0] + mode = args[1] + with open(path, mode) as f: + result.SetImmediateOutputFile(f) + if not mode in ['r']: + print('writing to file with mode: ' + mode, file=result) diff --git a/packages/Python/lldbsuite/test/functionalities/command_source/TestCommandSource.py b/packages/Python/lldbsuite/test/functionalities/command_source/TestCommandSource.py index 013803e698af..0d4eb0776e79 100644 --- a/packages/Python/lldbsuite/test/functionalities/command_source/TestCommandSource.py +++ b/packages/Python/lldbsuite/test/functionalities/command_source/TestCommandSource.py @@ -10,7 +10,9 @@ from __future__ import print_function import os, sys import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class CommandSourceTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py b/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py index d7aab03c0830..7a9ded03ad20 100644 --- a/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py +++ b/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py @@ -8,7 +8,10 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbutil class CommandLineCompletionTestCase(TestBase): @@ -23,21 +26,21 @@ class CommandLineCompletionTestCase(TestBase): except: pass - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_at(self): """Test that 'at' completes to 'attach '.""" self.complete_from_to('at', 'attach ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_de(self): """Test that 'de' completes to 'detach '.""" self.complete_from_to('de', 'detach ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_process_attach_dash_dash_con(self): @@ -45,7 +48,7 @@ class CommandLineCompletionTestCase(TestBase): self.complete_from_to('process attach --con', 'process attach --continue ') # - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_infinite_loop_while_completing(self): @@ -53,147 +56,147 @@ class CommandLineCompletionTestCase(TestBase): self.complete_from_to('process print hello\\', 'process print hello\\', turn_off_re_match=True) - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_watchpoint_co(self): """Test that 'watchpoint co' completes to 'watchpoint command '.""" self.complete_from_to('watchpoint co', 'watchpoint command ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_watchpoint_command_space(self): """Test that 'watchpoint command ' completes to ['Available completions:', 'add', 'delete', 'list'].""" self.complete_from_to('watchpoint command ', ['Available completions:', 'add', 'delete', 'list']) - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_watchpoint_command_a(self): """Test that 'watchpoint command a' completes to 'watchpoint command add '.""" self.complete_from_to('watchpoint command a', 'watchpoint command add ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_watchpoint_set_variable_dash_w(self): """Test that 'watchpoint set variable -w' completes to 'watchpoint set variable -w '.""" self.complete_from_to('watchpoint set variable -w', 'watchpoint set variable -w ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_watchpoint_set_variable_dash_w_space(self): """Test that 'watchpoint set variable -w ' completes to ['Available completions:', 'read', 'write', 'read_write'].""" self.complete_from_to('watchpoint set variable -w ', ['Available completions:', 'read', 'write', 'read_write']) - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_watchpoint_set_ex(self): """Test that 'watchpoint set ex' completes to 'watchpoint set expression '.""" self.complete_from_to('watchpoint set ex', 'watchpoint set expression ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_watchpoint_set_var(self): """Test that 'watchpoint set var' completes to 'watchpoint set variable '.""" self.complete_from_to('watchpoint set var', 'watchpoint set variable ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_watchpoint_set_variable_dash_w_read_underbar(self): """Test that 'watchpoint set variable -w read_' completes to 'watchpoint set variable -w read_write'.""" self.complete_from_to('watchpoint set variable -w read_', 'watchpoint set variable -w read_write') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_help_fi(self): """Test that 'help fi' completes to ['Available completions:', 'file', 'finish'].""" self.complete_from_to('help fi', ['Available completions:', 'file', 'finish']) - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_help_watchpoint_s(self): """Test that 'help watchpoint s' completes to 'help watchpoint set '.""" self.complete_from_to('help watchpoint s', 'help watchpoint set ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_append_target_er(self): """Test that 'settings append target.er' completes to 'settings append target.error-path'.""" self.complete_from_to('settings append target.er', 'settings append target.error-path') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_insert_after_target_en(self): """Test that 'settings insert-after target.env' completes to 'settings insert-after target.env-vars'.""" self.complete_from_to('settings insert-after target.env', 'settings insert-after target.env-vars') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_insert_before_target_en(self): """Test that 'settings insert-before target.env' completes to 'settings insert-before target.env-vars'.""" self.complete_from_to('settings insert-before target.env', 'settings insert-before target.env-vars') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_replace_target_ru(self): """Test that 'settings replace target.ru' completes to 'settings replace target.run-args'.""" self.complete_from_to('settings replace target.ru', 'settings replace target.run-args') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_s(self): """Test that 'settings s' completes to ['Available completions:', 'set', 'show'].""" self.complete_from_to('settings s', ['Available completions:', 'set', 'show']) - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_set_th(self): """Test that 'settings set th' completes to 'settings set thread-format'.""" self.complete_from_to('settings set th', 'settings set thread-format') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_s_dash(self): """Test that 'settings set -' completes to 'settings set -g'.""" self.complete_from_to('settings set -', 'settings set -g') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_clear_th(self): """Test that 'settings clear th' completes to 'settings clear thread-format'.""" self.complete_from_to('settings clear th', 'settings clear thread-format') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_set_ta(self): """Test that 'settings set ta' completes to 'settings set target.'.""" self.complete_from_to('settings set target.ma', 'settings set target.max-') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_set_target_exec(self): """Test that 'settings set target.exec' completes to 'settings set target.exec-search-paths '.""" self.complete_from_to('settings set target.exec', 'settings set target.exec-search-paths') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_set_target_pr(self): @@ -204,21 +207,21 @@ class CommandLineCompletionTestCase(TestBase): 'target.prefer-dynamic-value', 'target.process.']) - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_set_target_process(self): """Test that 'settings set target.process' completes to 'settings set target.process.'.""" self.complete_from_to('settings set target.process', 'settings set target.process.') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_set_target_process_dot(self): """Test that 'settings set target.process.t' completes to 'settings set target.process.thread.'.""" self.complete_from_to('settings set target.process.t', 'settings set target.process.thread.') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_settings_set_target_process_thread_dot(self): @@ -229,7 +232,7 @@ class CommandLineCompletionTestCase(TestBase): 'target.process.thread.step-avoid-regexp', 'target.process.thread.trace-thread']) - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_target_space(self): @@ -239,22 +242,22 @@ class CommandLineCompletionTestCase(TestBase): ['Available completions:', 'create', 'delete', 'list', 'modules', 'select', 'stop-hook', 'variable']) - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_target_create_dash_co(self): """Test that 'target create --co' completes to 'target variable --core '.""" self.complete_from_to('target create --co', 'target create --core ') - @expectedFailureHostWindows("llvm.org/pr24679") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") @skipIfFreeBSD # timing out on the FreeBSD buildbot @no_debug_info_test def test_target_va(self): """Test that 'target va' completes to 'target variable '.""" self.complete_from_to('target va', 'target variable ') - @expectedFailureHostWindows("llvm.org/pr24679") - @expectedFailureDarwin("llvm.org/pr25485") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr24679") + @expectedFailureAll(oslist=lldbplatform.darwin_all, bugnumber="llvm.org/pr25485") def test_symbol_name(self): self.build() self.complete_from_to('''file a.out diff --git a/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py b/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py index 3ae7a20b4c7d..7fcb44f0b3ec 100644 --- a/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py +++ b/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil # rdar://problem/8532131 # lldb not able to digest the clang-generated debug info correctly with respect to function name @@ -32,6 +33,7 @@ class ConditionalBreakTestCase(TestBase): self.build() self.simulate_conditional_break_by_user() + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265: args in frames other than #0 are not evaluated correctly") def do_conditional_break(self): """Exercise some thread and frame APIs to break if c() is called by a().""" exe = os.path.join(os.getcwd(), "a.out") @@ -64,7 +66,8 @@ class ConditionalBreakTestCase(TestBase): for j in range(10): if self.TraceOn(): print("j is: ", j) - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, breakpoint) + self.assertIsNotNone(thread, "Expected one thread to be stopped at the breakpoint") if thread.GetNumFrames() >= 2: frame0 = thread.GetFrameAtIndex(0) @@ -82,8 +85,8 @@ class ConditionalBreakTestCase(TestBase): # And the local variable 'val' should have a value of (int) 3. val = frame1.FindVariable("val") - self.assertTrue(val.GetTypeName() == "int", "'val' has int type") - self.assertTrue(val.GetValue() == "3", "'val' has a value of 3") + self.assertEqual("int", val.GetTypeName()) + self.assertEqual("3", val.GetValue()) break process.Continue() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/TestFormattersBoolRefPtr.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/TestFormattersBoolRefPtr.py index 94cdfdfeb343..fb3511ebd91d 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/TestFormattersBoolRefPtr.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/TestFormattersBoolRefPtr.py @@ -6,11 +6,12 @@ from __future__ import print_function +import datetime import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import datetime -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DataFormatterBoolRefPtr(TestBase): @@ -56,6 +57,8 @@ class DataFormatterBoolRefPtr(TestBase): substrs = ['YES']) self.expect('frame variable no_ref', substrs = ['NO']) + self.expect('frame variable unset_ref', + substrs = ['12']) # Now check that we use the right summary for BOOL* @@ -63,6 +66,8 @@ class DataFormatterBoolRefPtr(TestBase): substrs = ['YES']) self.expect('frame variable no_ptr', substrs = ['NO']) + self.expect('frame variable unset_ptr', + substrs = ['12']) # Now check that we use the right summary for BOOL @@ -70,3 +75,5 @@ class DataFormatterBoolRefPtr(TestBase): substrs = ['YES']) self.expect('frame variable no', substrs = ['NO']) + self.expect('frame variable unset', + substrs = ['12']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/main.mm b/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/main.mm index a2461fd9da91..22c8790a7541 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/main.mm +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/boolreference/main.mm @@ -11,17 +11,19 @@ int main (int argc, const char * argv[]) { - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; BOOL yes = YES; BOOL no = NO; + BOOL unset = 12; BOOL &yes_ref = yes; BOOL &no_ref = no; + BOOL &unset_ref = unset; BOOL* yes_ptr = &yes; BOOL* no_ptr = &no; + BOOL* unset_ptr = &unset; [pool drain];// Set break point at this line. return 0; diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/TestCompactVectors.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/TestCompactVectors.py index 7cd2a49b4717..914c5260ac24 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/TestCompactVectors.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/compactvectors/TestCompactVectors.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CompactVectorsFormattingTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py index db426cac6e59..f8209f03d0c2 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-categories/TestDataFormatterCategories.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CategoriesDataFormatterTestCase(TestBase): @@ -154,6 +155,7 @@ class CategoriesDataFormatterTestCase(TestBase): self.runCmd("type category enable Category1") self.runCmd("type summary list -w Category1") + self.expect("type summary list -w NoSuchCategoryHere", substrs=['no matching results found']) self.expect("frame variable r1 r2 r3", substrs = ['r1 = Category1', diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py index 2ca737156a1a..99443a04f672 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CppDataFormatterTestCase(TestBase): @@ -21,7 +22,7 @@ class CppDataFormatterTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFailureWindows("llvm.org/pr24462") # Data formatters have problems on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24462: Data formatters have problems on Windows") def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/TestDataFormatterDisabling.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/TestDataFormatterDisabling.py index 0f254a67d5a6..2c2e08431175 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/TestDataFormatterDisabling.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-disabling/TestDataFormatterDisabling.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DataFormatterDisablingTestCase(TestBase): @@ -21,7 +22,7 @@ class DataFormatterDisablingTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFailureWindows("llvm.org/pr24462") # Data formatters have problems on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24462, Data formatters have problems on Windows") def test_with_run_command(self): """Check that we can properly disable all data formatter categories.""" self.build() @@ -61,6 +62,8 @@ class DataFormatterDisablingTestCase(TestBase): self.expect('frame variable string1', matching=False, substrs = ['hello world']) + self.expect('type summary list', substrs=['Category: system (disabled)']) + self.expect('type category list', substrs = ['system','disabled',]) # now enable and check that we are back to normal diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py index 94df520d29b3..e9ac79ad08e2 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py @@ -48,7 +48,9 @@ class NamedSummariesDataFormatterTestCase(TestBase): self.runCmd("type summary add --summary-string \"First: x=${var.x} y=${var.y} dummy=${var.dummy}\" First") self.runCmd("type summary add --summary-string \"Second: x=${var.x} y=${var.y%hex}\" Second") self.runCmd("type summary add --summary-string \"Third: x=${var.x} z=${var.z}\" Third") - + + self.expect('type summary list', substrs=['AllUseIt']) + self.expect("frame variable first", substrs = ['First: x=12']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py index e12ddca2eea7..d7d4118d1d6a 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjC.py @@ -7,11 +7,12 @@ from __future__ import print_function +import datetime import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import datetime -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ObjCDataFormatterTestCase(TestBase): @@ -66,11 +67,6 @@ class ObjCDataFormatterTestCase(TestBase): """Test formatters for NSException.""" self.appkit_tester_impl(self.nsexception_data_formatter_commands) - @skipUnlessDarwin - def test_nsmisc_with_run_command(self): - """Test formatters for misc NS classes.""" - self.appkit_tester_impl(self.nsmisc_data_formatter_commands) - @skipUnlessDarwin def test_nsdate_with_run_command(self): @@ -191,7 +187,7 @@ class ObjCDataFormatterTestCase(TestBase): def nsnumber_data_formatter_commands(self): # Now enable AppKit and check we are displaying Cocoa classes correctly - self.expect('frame variable num1 num2 num3 num4 num5 num6 num7 num8_Y num8_N num9', + self.expect('frame variable num1 num2 num3 num4 num5 num6 num7 num9', substrs = ['(NSNumber *) num1 = ',' (int)5', '(NSNumber *) num2 = ',' (float)3.1', '(NSNumber *) num3 = ',' (double)3.14', @@ -199,13 +195,8 @@ class ObjCDataFormatterTestCase(TestBase): '(NSNumber *) num5 = ',' (char)65', '(NSNumber *) num6 = ',' (long)255', '(NSNumber *) num7 = ','2000000', - '(NSNumber *) num8_Y = ',' @"1"', - '(NSNumber *) num8_N = ',' @"0"', '(NSNumber *) num9 = ',' (short)-31616']) - self.expect('frame variable decimal_one', - substrs = ['(NSDecimalNumber *) decimal_one = 0x','1']) - self.expect('frame variable num_at1 num_at2 num_at3 num_at4', substrs = ['(NSNumber *) num_at1 = ',' (int)12', '(NSNumber *) num_at2 = ',' (int)-12', @@ -213,26 +204,19 @@ class ObjCDataFormatterTestCase(TestBase): '(NSNumber *) num_at4 = ',' (double)-12.5']) def nscontainers_data_formatter_commands(self): - self.expect('frame variable newArray newDictionary newMutableDictionary cfdict_ref mutable_dict_ref cfarray_ref mutable_array_ref', + self.expect('frame variable newArray newDictionary newMutableDictionary cfarray_ref mutable_array_ref', substrs = ['(NSArray *) newArray = ','@"50 elements"', '(NSDictionary *) newDictionary = ',' 12 key/value pairs', '(NSDictionary *) newMutableDictionary = ',' 21 key/value pairs', - '(CFDictionaryRef) cfdict_ref = ','3 key/value pairs', - '(CFMutableDictionaryRef) mutable_dict_ref = ','12 key/value pairs', '(CFArrayRef) cfarray_ref = ','@"3 elements"', '(CFMutableArrayRef) mutable_array_ref = ','@"11 elements"']) - self.expect('frame variable nscounted_set', - substrs = ['(NSCountedSet *) nscounted_set = ','5 elements']) - self.expect('frame variable iset1 iset2 imset', substrs = ['4 indexes','512 indexes','10 indexes']) - self.expect('frame variable mutable_bag_ref cfbag_ref binheap_ref', - substrs = ['(CFMutableBagRef) mutable_bag_ref = ','@"17 values"', - '(CFBagRef) cfbag_ref = ','@"15 values"', - '(CFBinaryHeapRef) binheap_ref = ','@"21 items"']) - + self.expect('frame variable binheap_ref', + substrs = ['(CFBinaryHeapRef) binheap_ref = ','@"21 items"']) + self.expect('expression -d run -- [NSArray new]', substrs=['@"0 elements"']) def nsdata_data_formatter_commands(self): @@ -258,6 +242,9 @@ class ObjCDataFormatterTestCase(TestBase): self.expect('frame variable nserror', substrs = ['domain: @"Foobar" - code: 12']) + self.expect('frame variable nserrorptr', + substrs = ['domain: @"Foobar" - code: 12']) + self.expect('frame variable nserror->_userInfo', substrs = ['2 key/value pairs']) @@ -272,24 +259,10 @@ class ObjCDataFormatterTestCase(TestBase): def nsexception_data_formatter_commands(self): self.expect('frame variable except0 except1 except2 except3', - substrs = ['(NSException *) except0 = ','name:@"TheGuyWhoHasNoName" reason:@"cuz it\'s funny"', - '(NSException *) except1 = ','name:@"TheGuyWhoHasNoName~1" reason:@"cuz it\'s funny"', - '(NSException *) except2 = ','name:@"TheGuyWhoHasNoName`2" reason:@"cuz it\'s funny"', - '(NSException *) except3 = ','name:@"TheGuyWhoHasNoName/3" reason:@"cuz it\'s funny"']) - - def nsmisc_data_formatter_commands(self): - self.expect('frame variable localhost', - substrs = [' localhost ((','"127.0.0.1"']) - - if self.getArchitecture() in ['i386', 'x86_64']: - self.expect('frame variable my_task', - substrs = [' + +struct S { + int x = 1; + int y = 2; +}; + +int main () +{ + std::atomic s; + s.store(S()); + std::atomic i; + i.store(5); + + return 0; // Set break point at this line. +} + diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/TestInitializerList.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/TestInitializerList.py index e01f1b6679fc..d452c1be69bf 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/TestInitializerList.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/initializerlist/TestInitializerList.py @@ -8,16 +8,17 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class InitializerListTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfWindows # libc++ not ported to Windows yet - @skipIfGcc - @expectedFailureLinux # fails on clang 3.5 and tot + @skipIf(compiler="gcc") + @expectedFailureAll(oslist=["linux"], bugnumber="fails on clang 3.5 and tot") def test(self): """Test that that file and class static variables display correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py index a87a2ed2d434..23f6956cf3f0 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxIteratorDataFormatterTestCase(TestBase): @@ -21,7 +22,7 @@ class LibcxxIteratorDataFormatterTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows yet def test_with_run_command(self): """Test that libc++ iterators format properly.""" diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py index 18ee31a86106..6fcdc37465db 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time, re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxListDataFormatterTestCase(TestBase): @@ -24,8 +25,9 @@ class LibcxxListDataFormatterTestCase(TestBase): self.line3 = line_number('main.cpp', '// Set third break point at this line.') self.line4 = line_number('main.cpp', '// Set fourth break point at this line.') - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows yet + @expectedFailureAll(oslist=["macosx"], bugnumber="rdar://25499635") def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/TestDataFormatterLibcxxListLoop.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/TestDataFormatterLibcxxListLoop.py index 167cb2b887af..9e68e1dbc004 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/TestDataFormatterLibcxxListLoop.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/TestDataFormatterLibcxxListLoop.py @@ -9,16 +9,18 @@ from __future__ import print_function import os, time, re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxListDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows yet @add_test_categories(["pyapi"]) + @skipIfDarwin # rdar://25499635 def test_with_run_command(self): self.build() exe = os.path.join(os.getcwd(), "a.out") diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py index 70a98f9c2cae..cecc3178b318 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py @@ -8,14 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxMapDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows yet def test_with_run_command(self): """Test that that file and class static variables display correctly.""" diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py index d0ca73d3251d..eb74818c91f5 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py @@ -9,14 +9,16 @@ from __future__ import print_function import os, time import lldb from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class LibcxxMultiMapDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfWindows # libc++ not ported to Windows yet - @skipIfGcc + @skipIf(compiler="gcc") def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py index 384f6130d0c0..cfdfd07ddec1 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py @@ -8,14 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxMultiSetDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows yet def test_with_run_command(self): """Test that that file and class static variables display correctly.""" diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py index fcbfb0a8f0ed..00c1e548cf6b 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py @@ -8,62 +8,63 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxSetDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows yet def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) - bkpt = self.target().FindBreakpointByID(lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line.")) +# bkpt = self.target().FindBreakpointByID(lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line.")) self.runCmd("run", RUN_SUCCEEDED) - lldbutil.skip_if_library_missing(self, self.target(), lldbutil.PrintableRegex("libc\+\+")) - - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', - 'stop reason = breakpoint']) - - # This is the function to remove the custom formats in order to have a - # clean slate for the next test case. - def cleanup(): - self.runCmd('type format clear', check=False) - self.runCmd('type summary clear', check=False) - self.runCmd('type filter clear', check=False) - self.runCmd('type synth clear', check=False) - self.runCmd("settings set target.max-children-count 256", check=False) - - # Execute the cleanup function during test case tear down. - self.addTearDownHook(cleanup) - - self.expect('image list', substrs = self.getLibcPlusPlusLibs()) - - self.expect("frame variable ii",substrs = ["size=0","{}"]) - lldbutil.continue_to_breakpoint(self.process(), bkpt) - self.expect("frame variable ii",substrs = ["size=6","[0] = 0","[1] = 1", "[2] = 2", "[3] = 3", "[4] = 4", "[5] = 5"]) - lldbutil.continue_to_breakpoint(self.process(), bkpt) - self.expect("frame variable ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"]) - self.expect("frame variable ii[2]",substrs = [" = 2"]) - self.expect("p ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"]) - lldbutil.continue_to_breakpoint(self.process(), bkpt) - self.expect("frame variable ii",substrs = ["size=0","{}"]) - lldbutil.continue_to_breakpoint(self.process(), bkpt) - self.expect("frame variable ii",substrs = ["size=0","{}"]) - self.expect("frame variable ss",substrs = ["size=0","{}"]) - lldbutil.continue_to_breakpoint(self.process(), bkpt) - self.expect("frame variable ss",substrs = ["size=2",'[0] = "a"','[1] = "a very long string is right here"']) - lldbutil.continue_to_breakpoint(self.process(), bkpt) - self.expect("frame variable ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"']) - self.expect("p ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"']) - self.expect("frame variable ss[2]",substrs = [' = "b"']) - lldbutil.continue_to_breakpoint(self.process(), bkpt) - self.expect("frame variable ss",substrs = ["size=3",'[0] = "a"','[1] = "a very long string is right here"','[2] = "c"']) +# lldbutil.skip_if_library_missing(self, self.target(), lldbutil.PrintableRegex("libc\+\+")) +# +# # The stop reason of the thread should be breakpoint. +# self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +# substrs = ['stopped', +# 'stop reason = breakpoint']) +# +# # This is the function to remove the custom formats in order to have a +# # clean slate for the next test case. +# def cleanup(): +# self.runCmd('type format clear', check=False) +# self.runCmd('type summary clear', check=False) +# self.runCmd('type filter clear', check=False) +# self.runCmd('type synth clear', check=False) +# self.runCmd("settings set target.max-children-count 256", check=False) +# +# # Execute the cleanup function during test case tear down. +# self.addTearDownHook(cleanup) +# +# self.expect('image list', substrs = self.getLibcPlusPlusLibs()) +# +# self.expect("frame variable ii",substrs = ["size=0","{}"]) +# lldbutil.continue_to_breakpoint(self.process(), bkpt) +# self.expect("frame variable ii",substrs = ["size=6","[0] = 0","[1] = 1", "[2] = 2", "[3] = 3", "[4] = 4", "[5] = 5"]) +# lldbutil.continue_to_breakpoint(self.process(), bkpt) +# self.expect("frame variable ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"]) +# self.expect("frame variable ii[2]",substrs = [" = 2"]) +# self.expect("p ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"]) +# lldbutil.continue_to_breakpoint(self.process(), bkpt) +# self.expect("frame variable ii",substrs = ["size=0","{}"]) +# lldbutil.continue_to_breakpoint(self.process(), bkpt) +# self.expect("frame variable ii",substrs = ["size=0","{}"]) +# self.expect("frame variable ss",substrs = ["size=0","{}"]) +# lldbutil.continue_to_breakpoint(self.process(), bkpt) +# self.expect("frame variable ss",substrs = ["size=2",'[0] = "a"','[1] = "a very long string is right here"']) +# lldbutil.continue_to_breakpoint(self.process(), bkpt) +# self.expect("frame variable ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"']) +# self.expect("p ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"']) +# self.expect("frame variable ss[2]",substrs = [' = "b"']) +# lldbutil.continue_to_breakpoint(self.process(), bkpt) +# self.expect("frame variable ss",substrs = ["size=3",'[0] = "a"','[1] = "a very long string is right here"','[2] = "c"']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py index 942124255f55..76eedb8c8919 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxStringDataFormatterTestCase(TestBase): @@ -22,7 +23,7 @@ class LibcxxStringDataFormatterTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows yet def test_with_run_command(self): """Test that that file and class static variables display correctly.""" diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py index 5e6ec2519323..4765cd70f67c 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/unordered/TestDataFormatterUnordered.py @@ -8,15 +8,16 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxUnorderedDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfWindows # libc++ not ported to Windows yet - @skipIfGcc + @skipIf(compiler="gcc") def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() @@ -71,5 +72,6 @@ class LibcxxUnorderedDataFormatterTestCase(TestBase): '(\[\d\] = "world"(\\n|.)+){2}']) def look_for_content_and_continue(self, var_name, patterns): + self.expect( ("frame variable %s" % var_name), patterns=patterns) self.expect( ("frame variable %s" % var_name), patterns=patterns) self.runCmd("continue") diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/TestDataFormatterLibcxxVBool.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/TestDataFormatterLibcxxVBool.py index 9771a819aa6b..fe3b6c115e31 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/TestDataFormatterLibcxxVBool.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vbool/TestDataFormatterLibcxxVBool.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxVBoolDataFormatterTestCase(TestBase): @@ -21,7 +22,7 @@ class LibcxxVBoolDataFormatterTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows. def test_with_run_command(self): """Test that that file and class static variables display correctly.""" diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py index f8cd65be0931..9a145fba73e8 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py @@ -8,14 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LibcxxVectorDataFormatterTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # libc++ not ported to Windows yet def test_with_run_command(self): """Test that that file and class static variables display correctly.""" diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py index 6742c9e71701..dbaa37daa2d1 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class StdIteratorDataFormatterTestCase(TestBase): @@ -22,7 +23,7 @@ class StdIteratorDataFormatterTestCase(TestBase): self.line = line_number('main.cpp', '// Set break point at this line.') @skipIfWindows # libstdcpp not ported to Windows - @expectedFailureIcc # llvm.org/pr15301 LLDB prints incorrect sizes of STL containers + @expectedFailureAll(compiler="icc", bugnumber="llvm.org/pr15301 LLDB prints incorrect sizes of STL containers") def test_with_run_command(self): """Test that libstdcpp iterators format properly.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py index 5147d18da0fe..55658af1f2a3 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class StdListDataFormatterTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py index e21c4e94c2c4..ff99255aec0c 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class StdMapDataFormatterTestCase(TestBase): @@ -21,7 +22,7 @@ class StdMapDataFormatterTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFailureIcc # llvm.org/pr15301: LLDB prints incorrect size of libstdc++ containers + @expectedFailureAll(compiler="icc", bugnumber="llvm.org/pr15301 LLDB prints incorrect sizes of STL containers") @skipIfWindows # libstdcpp not ported to Windows @skipIfFreeBSD def test_with_run_command(self): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile new file mode 100644 index 000000000000..88cb026aba1c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/Makefile @@ -0,0 +1,15 @@ +LEVEL = ../../../../../make + +CXX_SOURCES := main.cpp + +CXXFLAGS := -O0 +USE_LIBSTDCPP := 1 + +# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD +# targets. Other targets do not, which causes this test to fail. +# This flag enables FullDebugInfo for all targets. +ifneq (,$(findstring clang,$(CC))) + CFLAGS_EXTRAS += -fno-limit-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py new file mode 100644 index 000000000000..20b1a3d21156 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/TestDataFormatterStdSmartPtr.py @@ -0,0 +1,46 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class StdSmartPtrDataFormatterTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @skipIfFreeBSD + @skipIfWindows # libstdcpp not ported to Windows + @skipIfDarwin # doesn't compile on Darwin + def test_with_run_command(self): + self.build() + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line.") + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + self.expect("frame variable nsp", substrs = ['nsp = nullptr']) + self.expect("frame variable isp", substrs = ['isp = 123']) + self.expect("frame variable ssp", substrs = ['ssp = "foobar"']) + + self.expect("frame variable nwp", substrs = ['nwp = nullptr']) + self.expect("frame variable iwp", substrs = ['iwp = 123']) + self.expect("frame variable swp", substrs = ['swp = "foobar"']) + + self.runCmd("continue") + + self.expect("frame variable nsp", substrs = ['nsp = nullptr']) + self.expect("frame variable isp", substrs = ['isp = nullptr']) + self.expect("frame variable ssp", substrs = ['ssp = nullptr']) + + self.expect("frame variable nwp", substrs = ['nwp = nullptr']) + self.expect("frame variable iwp", substrs = ['iwp = nullptr']) + self.expect("frame variable swp", substrs = ['swp = nullptr']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp new file mode 100644 index 000000000000..7ba50875a6db --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/smart_ptr/main.cpp @@ -0,0 +1,20 @@ +#include +#include + +int +main() +{ + std::shared_ptr nsp; + std::shared_ptr isp(new int{123}); + std::shared_ptr ssp = std::make_shared("foobar"); + + std::weak_ptr nwp; + std::weak_ptr iwp = isp; + std::weak_ptr swp = ssp; + + nsp.reset(); // Set break point at this line. + isp.reset(); + ssp.reset(); + + return 0; // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py index 2d6af24c6afc..fde2f791183a 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class StdStringDataFormatterTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py index 9e73009aba83..f5cf7c04c3a7 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class StdVBoolDataFormatterTestCase(TestBase): @@ -21,8 +22,8 @@ class StdVBoolDataFormatterTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFailureFreeBSD("llvm.org/pr20548") # fails to build on lab.llvm.org buildbot - @expectedFailureIcc # llvm.org/pr15301: lldb does not print the correct sizes of STL containers when building with ICC + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr20548 fails to build on lab.llvm.org buildbot') + @expectedFailureAll(compiler="icc", bugnumber="llvm.org/pr15301 LLDB prints incorrect sizes of STL containers") @skipIfWindows # libstdcpp not ported to Windows. @skipIfDarwin def test_with_run_command(self): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py index ed4313657e93..4a352ef41c17 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/TestDataFormatterStdVector.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class StdVectorDataFormatterTestCase(TestBase): @@ -22,7 +23,7 @@ class StdVectorDataFormatterTestCase(TestBase): self.line = line_number('main.cpp', '// Set break point at this line.') @skipIfFreeBSD - @expectedFailureIcc # llvm.org/pr15301 LLDB prints incorrect sizes of STL containers + @expectedFailureAll(compiler="icc", bugnumber="llvm.org/pr15301 LLDB prints incorrect sizes of STL containers") @skipIfWindows # libstdcpp not ported to Windows def test_with_run_command(self): """Test that that file and class static variables display correctly.""" diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/TestDataFormatterSynthType.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/TestDataFormatterSynthType.py new file mode 100644 index 000000000000..6a03456e5c32 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/TestDataFormatterSynthType.py @@ -0,0 +1,56 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class DataFormatterSynthTypeTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', 'break here') + + @skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser + def test_with_run_command(self): + """Test using Python synthetic children provider to provide a typename.""" + self.build() + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("script from myIntSynthProvider import *") + self.runCmd("type synth add -l myIntSynthProvider myInt") + + self.expect('frame variable x', substrs=['ThisTestPasses']) + self.expect('frame variable y', substrs=['ThisTestPasses']) + self.expect('frame variable z', substrs=['ThisTestPasses']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/main.cpp new file mode 100644 index 000000000000..accbf0a5a578 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/main.cpp @@ -0,0 +1,29 @@ +class myInt { + private: int theValue; + public: myInt() : theValue(0) {} + public: myInt(int _x) : theValue(_x) {} + int val() { return theValue; } +}; + +class myArray { +public: + int array[16]; +}; + +class hasAnInt { + public: + myInt theInt; + hasAnInt() : theInt(42) {} +}; + +myInt operator + (myInt x, myInt y) { return myInt(x.val() + y.val()); } + +int main() { + myInt x{3}; + myInt y{4}; + myInt z {x+y}; + hasAnInt hi; + myArray ma; + + return z.val(); // break here +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/myIntSynthProvider.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/myIntSynthProvider.py new file mode 100644 index 000000000000..42737140b112 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthtype/myIntSynthProvider.py @@ -0,0 +1,36 @@ +class myIntSynthProvider(object): + def __init__(self, valobj, dict): + self.valobj = valobj; + self.val = self.valobj.GetChildMemberWithName("theValue") + def num_children(self): + return 0; + def get_child_at_index(self, index): + return None + def get_child_index(self, name): + return None + def update(self): + return False + def has_children(self): + return False + def get_type_name(self): + return "ThisTestPasses" + + +class myArraySynthProvider(object): + def __init__(self, valobj, dict): + self.valobj = valobj + self.array = self.valobj.GetChildMemberWithName("array") + + def num_children(self, max_count): + if 16 < max_count: + return 16 + return max_count + + def get_child_at_index(self, index): + return None # Keep it simple when this is not tested here. + + def get_child_index(self, name): + return None # Keep it simple when this is not tested here. + + def has_children(self): + return True diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py index 8d6e5df37a5c..e7a34647a6de 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DataFormatterSynthValueTestCase(TestBase): @@ -22,7 +23,7 @@ class DataFormatterSynthValueTestCase(TestBase): self.line = line_number('main.cpp', 'break here') @skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser - @expectedFailureWindows("llvm.org/pr24462") # Data formatters have problems on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24462, Data formatters have problems on Windows") def test_with_run_command(self): """Test using Python synthetic children provider to provide a value.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/TestDumpDynamic.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/TestDumpDynamic.py index 8ae09d691940..886d09fda456 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/TestDumpDynamic.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/dump_dynamic/TestDumpDynamic.py @@ -2,4 +2,4 @@ from __future__ import absolute_import from lldbsuite.test import lldbinline -lldbinline.MakeInlineTest(__file__, globals(), [lldbinline.expectedFailureWindows("llvm.org/pr24663")]) +lldbinline.MakeInlineTest(__file__, globals(), [lldbinline.expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24663")]) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/TestNSArraySynthetic.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/TestNSArraySynthetic.py index a12f9c841a7f..871cc19373a4 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/TestNSArraySynthetic.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/nsarraysynth/TestNSArraySynthetic.py @@ -6,11 +6,12 @@ from __future__ import print_function +import datetime import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import datetime -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class NSArraySyntheticTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py index 13d493ecbdcc..5ee54c3a2952 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/nsdictionarysynth/TestNSDictionarySynthetic.py @@ -6,11 +6,12 @@ from __future__ import print_function +import datetime import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import datetime -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class NSDictionarySyntheticTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py index 6c558001bb04..d1680434d3b9 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/nssetsynth/TestNSSetSynthetic.py @@ -6,11 +6,12 @@ from __future__ import print_function +import datetime import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import datetime -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class NSSetSyntheticTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/TestFormattersOsType.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/TestFormattersOsType.py index 4fb6176e9e4f..4158ec8a661c 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/TestFormattersOsType.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/ostypeformatting/TestFormattersOsType.py @@ -6,11 +6,12 @@ from __future__ import print_function +import datetime import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import datetime -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DataFormatterOSTypeTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/TestPrintArray.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/TestPrintArray.py new file mode 100644 index 000000000000..700b7418118a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/TestPrintArray.py @@ -0,0 +1,70 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + + +import datetime +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class PrintArrayTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_print_array(self): + """Test that expr -Z works""" + self.build() + self.printarray_data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', 'break here') + + def printarray_data_formatter_commands(self): + """Test that expr -Z works""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect('expr --element-count 3 -- data', substrs=['[0] = 1', '[1] = 3', '[2] = 5']) + self.expect('expr data', substrs=['int *', '$', '0x']) + self.expect('expr -f binary --element-count 0 -- data', substrs=['int *', '$', '0b']) + self.expect('expr -f hex --element-count 3 -- data', substrs=['[0] = 0x', '1', '[1] = 0x', '3', '[2] = 0x', '5']) + self.expect('expr -f binary --element-count 2 -- data', substrs=['int *', '$', '0x', '[0] = 0b', '1', '[1] = 0b', '11']) + self.expect('parray 3 data', substrs=['[0] = 1', '[1] = 3', '[2] = 5']) + self.expect('parray `1 + 1 + 1` data', substrs=['[0] = 1', '[1] = 3', '[2] = 5']) + self.expect('parray `data[1]` data', substrs=['[0] = 1', '[1] = 3', '[2] = 5']) + self.expect('parray/x 3 data', substrs=['[0] = 0x', '1', '[1] = 0x', '3', '[2] = 0x', '5']) + self.expect('parray/x `data[1]` data', substrs=['[0] = 0x', '1', '[1] = 0x', '3', '[2] = 0x', '5']) + + # check error conditions + self.expect('expr --element-count 10 -- 123', error=True, substrs=['expression cannot be used with --element-count as it does not refer to a pointer']) + self.expect('expr --element-count 10 -- (void*)123', error=True, substrs=['expression cannot be used with --element-count as it refers to a pointer to void']) + self.expect('parray data', error=True, substrs=["invalid element count 'data'"]) + self.expect('parray data data', error=True, substrs=["invalid element count 'data'"]) + self.expect('parray', error=True, substrs=['Not enough arguments provided']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/main.cpp new file mode 100644 index 000000000000..b2d6309947ad --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/parray/main.cpp @@ -0,0 +1,29 @@ +//===-- main.cpp -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include + +template +ElemType* alloc(size_t count, std::function get) +{ + ElemType *elems = new ElemType[count]; + for(size_t i = 0; i < count; i++) + elems[i] = get(i); + return elems; +} + +int main (int argc, const char * argv[]) +{ + int* data = alloc(5, [] (size_t idx) -> int { + return 2 * idx + 1; + }); + return 0; // break here +} + diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/Makefile new file mode 100644 index 000000000000..261658b10ae8 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +OBJCXX_SOURCES := main.mm + +CFLAGS_EXTRAS += -w + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/TestPrintObjectArray.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/TestPrintObjectArray.py new file mode 100644 index 000000000000..7eb26a569867 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/TestPrintObjectArray.py @@ -0,0 +1,60 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + + +import datetime +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class PrintObjectArrayTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_print_array(self): + """Test that expr -O -Z works""" + self.build() + self.printarray_data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.mm', 'break here') + + def printarray_data_formatter_commands(self): + """Test that expr -O -Z works""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.mm", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type synth clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect('expr --element-count 3 --object-description -- objects', substrs=['3735928559', '4276993775', '3203398366', 'Hello', 'World', 'Two =', '1 =']) + self.expect('poarray 3 objects', substrs=['3735928559', '4276993775', '3203398366', 'Hello', 'World', 'Two =', '1 =']) + self.expect('expr --element-count 3 --object-description --description-verbosity=full -- objects', substrs=['[0] =', '3735928559', '4276993775', '3203398366', '[1] =', 'Hello', 'World', '[2] =', 'Two =', '1 =']) + self.expect('parray 3 objects', substrs=['[0] = 0x', '[1] = 0x', '[2] = 0x']) + self.expect('expr --element-count 3 -d run -- objects', substrs=['3 elements', '2 elements', '2 key/value pairs']) + self.expect('expr --element-count 3 -d run --ptr-depth=1 -- objects', substrs=['3 elements', '2 elements', '2 key/value pairs', '3735928559', '4276993775', '3203398366', '"Hello"', '"World"']) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/main.mm b/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/main.mm new file mode 100644 index 000000000000..9ef61e6a73f2 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/poarray/main.mm @@ -0,0 +1,30 @@ +//===-- main.cpp -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import + +struct ThreeObjects +{ + id one; + id two; + id three; +}; + +int main() +{ + NSArray *array1 = @[@0xDEADBEEF, @0xFEEDBEEF, @0xBEEFFADE]; + NSArray *array2 = @[@"Hello", @"World"]; + NSDictionary *dictionary = @{@1: array2, @"Two": array2}; + ThreeObjects *tobjects = new ThreeObjects(); + tobjects->one = array1; + tobjects->two = array2; + tobjects->three = dictionary; + id* objects = (id*)tobjects; + return 0; // break here +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/TestSetValueFromCString.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/TestSetValueFromCString.py index 80305e303d03..791ce27dad00 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/TestSetValueFromCString.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/setvaluefromcstring/TestSetValueFromCString.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIfFreeBSD,decorators.skipIfLinux,decorators.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/TestStringPrinter.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/TestStringPrinter.py index 69f7d48c8b6c..e26344f2711a 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/TestStringPrinter.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/stringprinter/TestStringPrinter.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.expectedFailureWindows("llvm.org/pr24772")]) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24772")]) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/TestSyntheticCapping.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/TestSyntheticCapping.py index 0550f57ae62a..e8b6c1ad95f5 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/TestSyntheticCapping.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/TestSyntheticCapping.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SyntheticCappingTestCase(TestBase): @@ -30,6 +31,8 @@ class SyntheticCappingTestCase(TestBase): self.runCmd("run", RUN_SUCCEEDED) + process = self.dbg.GetSelectedTarget().GetProcess() + # The stop reason of the thread should be breakpoint. self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs = ['stopped', @@ -51,25 +54,31 @@ class SyntheticCappingTestCase(TestBase): self.runCmd("script from fooSynthProvider import *") self.runCmd("type synth add -l fooSynthProvider foo") + # note that the value of fake_a depends on target byte order + if process.GetByteOrder() == lldb.eByteOrderLittle: + fake_a_val = 0x02000000 + else: + fake_a_val = 0x00000100 + # check that the synthetic children work, so we know we are doing the right thing self.expect("frame variable f00_1", - substrs = ['r = 33', - 'fake_a = 16777216', - 'a = 0']); + substrs = ['r = 34', + 'fake_a = %d' % fake_a_val, + 'a = 1']); # check that capping works self.runCmd("settings set target.max-children-count 2", check=False) self.expect("frame variable f00_1", substrs = ['...', - 'fake_a = 16777216', - 'a = 0']); + 'fake_a = %d' % fake_a_val, + 'a = 1']); self.expect("frame variable f00_1", matching=False, - substrs = ['r = 33']); + substrs = ['r = 34']); self.runCmd("settings set target.max-children-count 256", check=False) self.expect("frame variable f00_1", matching=True, - substrs = ['r = 33']); + substrs = ['r = 34']); diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/fooSynthProvider.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/fooSynthProvider.py index fb95ac2b54d0..1a7e5679c0b8 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/fooSynthProvider.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/fooSynthProvider.py @@ -1,21 +1,21 @@ import lldb class fooSynthProvider: - def __init__(self, valobj, dict): - self.valobj = valobj; - self.int_type = valobj.GetType().GetBasicType(lldb.eBasicTypeInt) - def num_children(self): - return 3; - def get_child_at_index(self, index): - if index == 0: - child = self.valobj.GetChildMemberWithName('a'); - if index == 1: - child = self.valobj.CreateChildAtOffset ('fake_a', 1, self.int_type); - if index == 2: - child = self.valobj.GetChildMemberWithName('r'); - return child; - def get_child_index(self, name): - if name == 'a': - return 0; - if name == 'fake_a': - return 1; - return 2; + def __init__(self, valobj, dict): + self.valobj = valobj; + self.int_type = valobj.GetType().GetBasicType(lldb.eBasicTypeInt) + def num_children(self): + return 3; + def get_child_at_index(self, index): + if index == 0: + child = self.valobj.GetChildMemberWithName('a'); + if index == 1: + child = self.valobj.CreateChildAtOffset ('fake_a', 1, self.int_type); + if index == 2: + child = self.valobj.GetChildMemberWithName('r'); + return child; + def get_child_index(self, name): + if name == 'a': + return 0; + if name == 'fake_a': + return 1; + return 2; diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp index b921915b91c5..fec7907e0031 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp @@ -48,7 +48,7 @@ struct wrapint int main() { - foo f00_1(0); + foo f00_1(1); foo *f00_ptr = new foo(12); f00_1.a++; // Set break point at this line. diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/TestSyntheticFilterRecompute.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/TestSyntheticFilterRecompute.py index 6b70a88b9f2c..23a31da685de 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/TestSyntheticFilterRecompute.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthupdate/TestSyntheticFilterRecompute.py @@ -6,11 +6,12 @@ from __future__ import print_function +import datetime import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import datetime -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SyntheticFilterRecomputingTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_arg/TestTypeSummaryListArg.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_arg/TestTypeSummaryListArg.py new file mode 100644 index 000000000000..6568056f761b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_arg/TestTypeSummaryListArg.py @@ -0,0 +1,31 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TypeSummaryListArgumentTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + @no_debug_info_test + def test_type_summary_list_with_arg(self): + """Test that the 'type summary list' command handles command line arguments properly""" + self.expect('type summary list Foo', substrs=['Category: default', 'Category: system']) + self.expect('type summary list char', substrs=['char *', 'unsigned char']) + + self.expect('type summary list -w default', substrs=['system'], matching=False) + self.expect('type summary list -w system unsigned', substrs=['default', '0-9'], matching=False) + self.expect('type summary list -w system char', substrs=['unsigned char *'], matching=True) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/TestTypeSummaryListScript.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/TestTypeSummaryListScript.py new file mode 100644 index 000000000000..63a4a3a4ba8c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/TestTypeSummaryListScript.py @@ -0,0 +1,61 @@ +""" +Test lldb data formatter subsystem. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TypeSummaryListScriptTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_typesummarylist_script(self): + """Test data formatter commands.""" + self.build() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', 'Break here') + + def data_formatter_commands(self): + """Test printing out Python summary formatters.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type category delete TSLSFormatters', check=False) + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + + self.addTearDownHook(cleanup) + + self.runCmd("command script import tslsformatters.py") + + self.expect("frame variable myStruct", substrs=['A data formatter at work']) + + self.expect('type summary list', substrs=['Struct_SummaryFormatter']) + self.expect('type summary list Struct', substrs=['Struct_SummaryFormatter']) + + diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/main.cpp new file mode 100644 index 000000000000..2de37041f263 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/main.cpp @@ -0,0 +1,15 @@ +#include + +typedef struct Struct +{ + int one; + int two; +} Struct; + +int +main() +{ + Struct myStruct = {10, 20}; + printf ("Break here: %d\n.", myStruct.one); + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/tslsformatters.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/tslsformatters.py new file mode 100644 index 000000000000..d1ce8b7db17a --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/type_summary_list_script/tslsformatters.py @@ -0,0 +1,10 @@ +import lldb + +def Struct_SummaryFormatter(valobj, internal_dict): + return 'A data formatter at work' + +category = lldb.debugger.CreateCategory("TSLSFormatters") +category.SetEnabled(True) +summary = lldb.SBTypeSummary.CreateWithFunctionName("tslsformatters.Struct_SummaryFormatter", lldb.eTypeOptionCascade) +spec = lldb.SBTypeNameSpecifier("Struct", False) +category.AddTypeSummary(spec, summary) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/TestTypedefArray.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/TestTypedefArray.py index 30b66e062827..41b8c3499ccd 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/TestTypedefArray.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/TestTypedefArray.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.expectedFailureGcc]) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.expectedFailureAll(compiler="gcc")]) diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py index 4d060c332f93..f3eced625898 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py @@ -7,10 +7,11 @@ from __future__ import print_function import os, time +import os.path import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import os.path +from lldbsuite.test import lldbutil class PythonSynthDataFormatterTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py index 05899a24ad22..365ddff3c7e8 100644 --- a/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py +++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/vector-types/TestVectorTypesFormatting.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class VectorTypesFormattingTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py b/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py index f10736bd75c0..efbaa69eef57 100644 --- a/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py +++ b/packages/Python/lldbsuite/test/functionalities/dead-strip/TestDeadStrip.py @@ -8,15 +8,17 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DeadStripTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr24778") - @expectedFailureDwo("llvm.org/pr25087") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @expectedFailureAll(debug_info="dwo", bugnumber="llvm.org/pr25087") + @expectedFailureAll(oslist=["linux"], debug_info="gmodules", bugnumber="llvm.org/pr27865") @skipIfFreeBSD # The -dead_strip linker option isn't supported on FreeBSD versions of ld. def test(self): """Test breakpoint works correctly with dead-code stripping.""" diff --git a/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py b/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py index df2308de7605..be0ea1441333 100644 --- a/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py +++ b/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py @@ -8,14 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class DisassemblyTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows # Function name prints fully demangled instead of name-only + @expectedFailureAll(oslist=["windows"], bugnumber="function names print fully demangled instead of name-only") def test(self): self.build() exe = os.path.join (os.getcwd(), "a.out") @@ -41,7 +42,10 @@ class DisassemblyTestCase(TestBase): instructions = [' add ', ' ldr ', ' str '] elif re.match("mips" , arch): breakpoint_opcodes = ["break"] - instructions = ['lw', 'sw', 'jr'] + instructions = ['lw', 'sw'] + elif arch in ["s390x"]: + breakpoint_opcodes = [".long"] + instructions = [' l ', ' a ', ' st '] else: # TODO please add your arch here self.fail('unimplemented for arch = "{arch}"'.format(arch=self.getArchitecture())) diff --git a/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/TestDynamicValueChildCount.py b/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/TestDynamicValueChildCount.py index ac039990b5bf..37593768f4a8 100644 --- a/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/TestDynamicValueChildCount.py +++ b/packages/Python/lldbsuite/test/functionalities/dynamic_value_child_count/TestDynamicValueChildCount.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class DynamicValueChildCountTestCase(TestBase): @@ -31,11 +32,8 @@ class DynamicValueChildCountTestCase(TestBase): self.main_sixth_call_line = line_number('pass-to-base.cpp', '// Break here and check b has 0 children again') - @expectedFailureLinux("llvm.org/pr23039") - @expectedFailureFreeBSD("llvm.org/pr19311") # continue at a breakpoint does not work - @expectedFailureWindows("llvm.org/pr24663") - @expectedFailurei386("to be figured out") @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24663") def test_get_dynamic_vals(self): """Test fetching C++ dynamic values from pointers & references.""" """Get argument vals for the call stack when stopped on a breakpoint.""" diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py b/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py index eddaa3cc9840..4b1880dee96f 100644 --- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py +++ b/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py @@ -6,7 +6,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ConvenienceVariablesCase(TestBase): @@ -20,7 +22,7 @@ class ConvenienceVariablesCase(TestBase): @skipIfFreeBSD # llvm.org/pr17228 @skipIfRemote - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_with_run_commands(self): """Test convenience variables lldb.debugger, lldb.target, lldb.process, lldb.thread, and lldb.frame.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py b/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py index 9321a308a83c..912d51fb6b02 100644 --- a/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py +++ b/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py @@ -8,9 +8,10 @@ from __future__ import print_function import lldb import os import time +from lldbsuite.support import seven +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import lldbsuite.support.seven as seven +from lldbsuite.test import lldbutil def execute_command (command): #print('%% %s' % (command)) @@ -55,15 +56,18 @@ class ExecTestCase(TestBase): self.assertTrue(process.GetState() == lldb.eStateStopped, STOPPED_DUE_TO_BREAKPOINT) - thread = process.GetThreadAtIndex (0) + threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertTrue(len(threads) == 1) - self.assertTrue (thread.IsValid(), - "Process stopped at 'main' should have a valid thread"); + # We had a deadlock tearing down the TypeSystemMap on exec, but only if some + # expression had been evaluated. So make sure we do that here so the teardown + # is not trivial. - stop_reason = thread.GetStopReason() - - self.assertTrue (stop_reason == lldb.eStopReasonBreakpoint, - "Thread in process stopped in 'main' should have a stop reason of eStopReasonBreakpoint"); + thread = threads[0] + value = thread.frames[0].EvaluateExpression("1 + 2") + self.assertTrue(value.IsValid(), "Expression evaluated successfully") + int_value = value.GetValueAsSigned() + self.assertTrue(int_value == 3, "Expression got the right result.") # Run and we should stop due to exec process.Continue() @@ -71,15 +75,11 @@ class ExecTestCase(TestBase): self.assertTrue(process.GetState() == lldb.eStateStopped, "Process should be stopped at __dyld_start") - thread = process.GetThreadAtIndex (0) - - self.assertTrue (thread.IsValid(), - "Process stopped at exec should have a valid thread"); - - stop_reason = thread.GetStopReason() - - self.assertTrue (stop_reason == lldb.eStopReasonExec, - "Thread in process stopped on exec should have a stop reason of eStopReasonExec"); - + threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonExec) + self.assertTrue(len(threads) == 1, "We got a thread stopped for exec.") + # Run and we should stop at breakpoint in main after exec process.Continue() + + threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertTrue(len(threads) == 1, "Stopped at breakpoint in exec'ed process.") diff --git a/packages/Python/lldbsuite/test/functionalities/expr-doesnt-deadlock/TestExprDoesntBlock.py b/packages/Python/lldbsuite/test/functionalities/expr-doesnt-deadlock/TestExprDoesntBlock.py index a54b45822a6a..1492fe069220 100644 --- a/packages/Python/lldbsuite/test/functionalities/expr-doesnt-deadlock/TestExprDoesntBlock.py +++ b/packages/Python/lldbsuite/test/functionalities/expr-doesnt-deadlock/TestExprDoesntBlock.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ExprDoesntDeadlockTestCase(TestBase): @@ -19,9 +20,8 @@ class ExprDoesntDeadlockTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureFreeBSD('llvm.org/pr17946') - @expectedFlakeyLinux # failed 1/365 test runs, line 61, thread.IsValid() - @expectedFailureWindows # Windows doesn't have pthreads, need to port this test. + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr17946') + @expectedFailureAll(oslist=["windows"], bugnumber="Windows doesn't have pthreads, test needs to be ported") def test_with_run_command(self): """Test that expr will time out and allow other threads to run if it blocks.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/fat_archives/TestFatArchives.py b/packages/Python/lldbsuite/test/functionalities/fat_archives/TestFatArchives.py index 19a2dba2109a..6d2763c1ead1 100644 --- a/packages/Python/lldbsuite/test/functionalities/fat_archives/TestFatArchives.py +++ b/packages/Python/lldbsuite/test/functionalities/fat_archives/TestFatArchives.py @@ -8,9 +8,10 @@ from __future__ import print_function import lldb import os import time -from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil import lldbsuite.support.seven as seven +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil def execute_command (command): # print('%% %s' % (command)) diff --git a/packages/Python/lldbsuite/test/functionalities/format/TestFormats.py b/packages/Python/lldbsuite/test/functionalities/format/TestFormats.py index cc962150bc8c..0ba036124b03 100644 --- a/packages/Python/lldbsuite/test/functionalities/format/TestFormats.py +++ b/packages/Python/lldbsuite/test/functionalities/format/TestFormats.py @@ -8,13 +8,15 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestFormats(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureHostWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_formats(self): """Test format string functionality.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py b/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py index 950b021b69ce..ceeb2eadaf4f 100644 --- a/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py +++ b/packages/Python/lldbsuite/test/functionalities/inferior-assert/TestInferiorAssert.py @@ -6,55 +6,56 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil -import lldbsuite.test.lldbplatformutil as lldbplatformutil +from lldbsuite.test import lldbutil +from lldbsuite.test import lldbplatformutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * class AssertingInferiorTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") - @expectedFailurei386("llvm.org/pr25338") - @expectedFailureLinux("llvm.org/pr25338", archs=['arm', 'i386']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll(oslist=["linux"], archs=["arm"], bugnumber="llvm.org/pr25338") + @expectedFailureAll(bugnumber="llvm.org/pr26592", triple = '^mips') def test_inferior_asserting(self): """Test that lldb reliably catches the inferior asserting (command).""" self.build() self.inferior_asserting() - @expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") @expectedFailureAndroid(api_levels=list(range(16 + 1))) # b.android.com/179836 def test_inferior_asserting_register(self): """Test that lldb reliably reads registers from the inferior after asserting (command).""" self.build() self.inferior_asserting_registers() - @expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") - @expectedFailurei386("llvm.org/pr25338") - @expectedFailureLinux("llvm.org/pr25338", archs=['arm', 'i386']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll(oslist=["linux"], archs=["aarch64", "arm"], bugnumber="llvm.org/pr25338") + @expectedFailureAll(bugnumber="llvm.org/pr26592", triple = '^mips') def test_inferior_asserting_disassemble(self): """Test that lldb reliably disassembles frames after asserting (command).""" self.build() self.inferior_asserting_disassemble() @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") def test_inferior_asserting_python(self): """Test that lldb reliably catches the inferior asserting (Python API).""" self.build() self.inferior_asserting_python() - @expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") - @expectedFailurei386("llvm.org/pr25338") - @expectedFailureLinux("llvm.org/pr25338", archs=['arm', 'i386']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll(oslist=["linux"], archs=["aarch64", "arm"], bugnumber="llvm.org/pr25338") + @expectedFailureAll(bugnumber="llvm.org/pr26592", triple = '^mips') def test_inferior_asserting_expr(self): """Test that the lldb expression interpreter can read from the inferior after asserting (command).""" self.build() self.inferior_asserting_expr() - @expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") - @expectedFailurei386("llvm.org/pr25338") - @expectedFailureLinux("llvm.org/pr25338", archs=['arm', 'i386']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows") + @expectedFailureAll(oslist=["linux"], archs=["aarch64", "arm"], bugnumber="llvm.org/pr25338") + @expectedFailureAll(bugnumber="llvm.org/pr26592", triple = '^mips') def test_inferior_asserting_step(self): """Test that lldb functions correctly after stepping through a call to assert().""" self.build() @@ -64,7 +65,8 @@ class AssertingInferiorTestCase(TestBase): lldbutil.run_break_set_by_file_and_line (self, "main.c", line, num_expected_locations=1, loc_exact=True) def check_stop_reason(self): - if matchAndroid(api_levels=list(range(1, 16+1)))(self): + matched = lldbplatformutil.match_android_device(self.getArchitecture(), valid_api_levels=list(range(1, 16+1))) + if matched: # On android until API-16 the abort() call ended in a sigsegv instead of in a sigabrt stop_reason = 'stop reason = signal SIGSEGV' else: diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-changed/TestInferiorChanged.py b/packages/Python/lldbsuite/test/functionalities/inferior-changed/TestInferiorChanged.py index 830c7f69355f..359846c314f6 100644 --- a/packages/Python/lldbsuite/test/functionalities/inferior-changed/TestInferiorChanged.py +++ b/packages/Python/lldbsuite/test/functionalities/inferior-changed/TestInferiorChanged.py @@ -6,15 +6,17 @@ from __future__ import print_function import os, time import lldb -from lldbsuite.test import configuration +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import configuration +from lldbsuite.test import lldbutil class ChangedInferiorTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIfHostWindows + @skipIf(hostoslist=["windows"]) + @no_debug_info_test def test_inferior_crashing(self): """Test lldb reloads the inferior after it was changed during the session.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py index c547df116c16..fd6a9abce36e 100644 --- a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py +++ b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py @@ -6,55 +6,56 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil -import lldbsuite.test.lldbplatformutil as lldbplatformutil +from lldbsuite.test import lldbutil +from lldbsuite.test import lldbplatformutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * class CrashingInferiorTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureFreeBSD("llvm.org/pr23699 SIGSEGV is reported as exception, not signal") - @expectedFailureWindows("llvm.org/pr24778") # This actually works, but the test relies on the output format instead of the API + @expectedFailureAll(oslist=['freebsd'], bugnumber="llvm.org/pr23699 SIGSEGV is reported as exception, not signal") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") def test_inferior_crashing(self): """Test that lldb reliably catches the inferior crashing (command).""" self.build() self.inferior_crashing() - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") def test_inferior_crashing_register(self): """Test that lldb reliably reads registers from the inferior after crashing (command).""" self.build() self.inferior_crashing_registers() @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") def test_inferior_crashing_python(self): """Test that lldb reliably catches the inferior crashing (Python API).""" self.build() self.inferior_crashing_python() - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") def test_inferior_crashing_expr(self): """Test that the lldb expression interpreter can read from the inferior after crashing (command).""" self.build() self.inferior_crashing_expr() - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") def test_inferior_crashing_step(self): """Test that stepping after a crash behaves correctly.""" self.build() self.inferior_crashing_step() - @expectedFailureFreeBSD('llvm.org/pr24939') - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr24939') + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") @expectedFailureAndroid(archs=['aarch64'], api_levels=list(range(21 + 1))) # No eh_frame for sa_restorer def test_inferior_crashing_step_after_break(self): """Test that lldb functions correctly after stepping through a crash.""" self.build() self.inferior_crashing_step_after_break() - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API") @skipIfLinux # Inferior exits after stepping after a segfault. This is working as intended IMHO. def test_inferior_crashing_expr_step_and_expr(self): """Test that lldb expressions work before and after stepping after a crash.""" diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py index 8afc81f6892a..0d1992d7b4b1 100644 --- a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py +++ b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py @@ -6,57 +6,57 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil -import lldbsuite.test.lldbplatformutil as lldbplatformutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatformutil +from lldbsuite.test import lldbutil class CrashingRecursiveInferiorTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureFreeBSD("llvm.org/pr23699 SIGSEGV is reported as exception, not signal") - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=['freebsd'], bugnumber="llvm.org/pr23699 SIGSEGV is reported as exception, not signal") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing(self): """Test that lldb reliably catches the inferior crashing (command).""" self.build() self.recursive_inferior_crashing() - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_register(self): """Test that lldb reliably reads registers from the inferior after crashing (command).""" self.build() self.recursive_inferior_crashing_registers() @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_python(self): """Test that lldb reliably catches the inferior crashing (Python API).""" self.build() self.recursive_inferior_crashing_python() - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_expr(self): """Test that the lldb expression interpreter can read from the inferior after crashing (command).""" self.build() self.recursive_inferior_crashing_expr() - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_step(self): """Test that stepping after a crash behaves correctly.""" self.build() self.recursive_inferior_crashing_step() - @expectedFailureFreeBSD('llvm.org/pr24939') - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr24939') + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") @expectedFailureAndroid(archs=['aarch64'], api_levels=list(range(21 + 1))) # No eh_frame for sa_restorer def test_recursive_inferior_crashing_step_after_break(self): """Test that lldb functions correctly after stepping through a crash.""" self.build() self.recursive_inferior_crashing_step_after_break() - @expectedFailureFreeBSD('llvm.org/pr15989') # Couldn't allocate space for the stack frame @skipIfLinux # Inferior exits after stepping after a segfault. This is working as intended IMHO. - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_recursive_inferior_crashing_expr_step_and_expr(self): """Test that lldb expressions work before and after stepping after a crash.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py b/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py index 023f6f31e395..8257106888d6 100644 --- a/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py +++ b/packages/Python/lldbsuite/test/functionalities/inline-stepping/TestInlineStepping.py @@ -6,18 +6,16 @@ from __future__ import print_function import os, time, sys import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestInlineStepping(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) - @expectedFailureFreeBSD('llvm.org/pr17214') - @expectedFailureIcc # Not really a bug. ICC combines two inlined functions. - # failed 1/365 dosep runs, (i386-clang), TestInlineStepping.py:237 failed to stop at first breakpoint in main - @expectedFailureAll(oslist=["linux"], archs=["i386"]) + @expectedFailureAll(compiler="icc", bugnumber="# Not really a bug. ICC combines two inlined functions.") def test_with_python_api(self): """Test stepping over and into inlined functions.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py b/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py index c7abf3464412..336260a8e4a3 100644 --- a/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py +++ b/packages/Python/lldbsuite/test/functionalities/jitloader_gdb/TestJITLoaderGDB.py @@ -2,13 +2,12 @@ from __future__ import print_function - - import unittest2 import os import lldb +from lldbsuite.test import lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil import re @@ -16,7 +15,7 @@ class JITLoaderGDBTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipTestIfFn(lambda x: True, "llvm.org/pr24702", "Skipped because the test crashes the test runner") + @skipTestIfFn(lambda : "Skipped because the test crashes the test runner", bugnumber="llvm.org/pr24702") @unittest2.expectedFailure("llvm.org/pr24702") def test_bogus_values(self): """Test that we handle inferior misusing the GDB JIT interface""" diff --git a/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py b/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py index 8f712dc21110..28d8cccacfcf 100644 --- a/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py +++ b/packages/Python/lldbsuite/test/functionalities/launch_with_shellexpand/TestLaunchWithShellExpand.py @@ -8,16 +8,15 @@ from __future__ import print_function import lldb import os import time +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LaunchWithShellExpandTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureFreeBSD("llvm.org/pr22627 process launch w/ shell expansion not working") - @expectedFailureLinux("llvm.org/pr22627 process launch w/ shell expansion not working") - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows", "linux", "freebsd"], bugnumber="llvm.org/pr24778 llvm.org/pr22627") def test(self): self.build() exe = os.path.join (os.getcwd(), "a.out") @@ -31,7 +30,7 @@ class LaunchWithShellExpandTestCase(TestBase): breakpoint = target.BreakpointCreateBySourceRegex ('break here', lldb.SBFileSpec ("main.cpp", False)) self.assertTrue(breakpoint, VALID_BREAKPOINT) - self.runCmd("process launch -X true -w %s -- fi*.tx?" % (os.getcwd())) + self.runCmd("process launch -X true -w %s -- fi*.tx? () > <" % (os.getcwd())) process = self.process() @@ -52,7 +51,11 @@ class LaunchWithShellExpandTestCase(TestBase): self.expect("frame variable argv[2]", substrs=['file2.txt']) self.expect("frame variable argv[3]", substrs=['file3.txt']) self.expect("frame variable argv[4]", substrs=['file4.txy']) + self.expect("frame variable argv[5]", substrs=['()']) + self.expect("frame variable argv[6]", substrs=['>']) + self.expect("frame variable argv[7]", substrs=['<']) self.expect("frame variable argv[5]", substrs=['file5.tyx'], matching=False) + self.expect("frame variable argv[8]", substrs=['file5.tyx'], matching=False) self.runCmd("process kill") diff --git a/packages/Python/lldbsuite/test/functionalities/llvm/TestLLVM.py b/packages/Python/lldbsuite/test/functionalities/llvm/TestLLVM.py new file mode 100644 index 000000000000..a2a43bf2fabd --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/llvm/TestLLVM.py @@ -0,0 +1,60 @@ +""" +Test lldb 'commands regex' command which allows the user to create a regular expression command. +""" + +from __future__ import print_function + + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestHomeDirectory(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") + @no_debug_info_test + def test_tilde_home_directory(self): + """Test that we can resolve "~/" in paths correctly. + When a path starts with "~/", we use llvm::sys::path::home_directory() to + resolve the home directory. This currently relies on "HOME" being set in the + environment. While this is usually set, we can't rely upon that. We might + eventually get a fix into llvm::sys::path::home_directory() so it doesn't rely + on having to have an environment variable set, but until then we have work around + code in FileSpec::ResolveUsername (llvm::SmallVectorImpl &path) to ensure + this always works. This test tests that we get the correct answer for with and + without "HOME" being set in the environment.""" + import pexpect + prompt = "(lldb) " + + child = pexpect.spawn('%s --no-use-colors %s' % (lldbtest_config.lldbExec, self.lldbOption)) + # Turn on logging for what the child sends back. + if self.TraceOn(): + child.logfile_read = sys.stdout + # So that the spawned lldb session gets shutdown durng teardown. + self.child = child + + # Resolve "~/." to the full path of our home directory + "/." + if 'HOME' in os.environ: + home_dir = os.environ['HOME'] + if self.TraceOn(): + print("home directory is: '%s'" % (home_dir)) + if os.path.exists(home_dir): + home_dir_slash_dot = home_dir + '/.' + child.expect_exact(prompt) + child.sendline('''script str(lldb.SBFileSpec("~/.", True))''') + child.expect_exact(home_dir) + child.expect_exact(prompt) + child.sendline('''script import os; os.unsetenv('HOME'); str(lldb.SBFileSpec("~/", True))'''); + child.expect_exact(home_dir) + child.expect_exact(prompt) + elif self.TraceOn(): + print('''home directory "%s" doesn't exist, skipping home directory test''' % (home_dir)) + elif self.TraceOn(): + print('"HOME" not in environment, skipping home directory test') + + child.sendline('quit') diff --git a/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py b/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py index 481e7c887bd0..3a703b2ee04e 100644 --- a/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py +++ b/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently class LoadUnloadTestCase(TestBase): @@ -125,7 +126,6 @@ class LoadUnloadTestCase(TestBase): substrs = [new_dylib]) @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support - @skipUnlessListedRemote(['android']) @expectedFailureAndroid # wrong source file shows up for hidden library @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently def test_dyld_library_path(self): @@ -182,7 +182,6 @@ class LoadUnloadTestCase(TestBase): @expectedFailureAll(bugnumber="llvm.org/pr25805", hostoslist=["windows"], compiler="gcc", archs=["i386"], triple='.*-android') @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support - @skipUnlessListedRemote(['android']) @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently def test_lldb_process_load_and_unload_commands(self): """Test that lldb process load/unload command work correctly.""" @@ -241,7 +240,6 @@ class LoadUnloadTestCase(TestBase): self.runCmd("process continue") @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support - @skipUnlessListedRemote(['android']) def test_load_unload(self): """Test breakpoint by name works correctly with dlopen'ing.""" @@ -283,7 +281,6 @@ class LoadUnloadTestCase(TestBase): substrs = [' resolved, hit count = 2']) @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support - @skipUnlessListedRemote(['android']) @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently def test_step_over_load (self): """Test stepping over code that loads a shared library works correctly.""" @@ -313,7 +310,6 @@ class LoadUnloadTestCase(TestBase): 'stop reason = step over']) @skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support - @skipUnlessListedRemote(['android']) @skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently @unittest2.expectedFailure("llvm.org/pr25806") def test_static_init_during_load (self): diff --git a/packages/Python/lldbsuite/test/functionalities/longjmp/TestLongjmp.py b/packages/Python/lldbsuite/test/functionalities/longjmp/TestLongjmp.py index 1316a01c924c..d9f2b2231895 100644 --- a/packages/Python/lldbsuite/test/functionalities/longjmp/TestLongjmp.py +++ b/packages/Python/lldbsuite/test/functionalities/longjmp/TestLongjmp.py @@ -8,8 +8,9 @@ from __future__ import print_function import os import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class LongjmpTestCase(TestBase): @@ -20,8 +21,8 @@ class LongjmpTestCase(TestBase): @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp @skipIfFreeBSD # llvm.org/pr17214 - @expectedFailureLinux("llvm.org/pr20231") - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20231") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_step_out(self): """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-out.""" self.build() @@ -29,8 +30,8 @@ class LongjmpTestCase(TestBase): @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp @skipIfFreeBSD # llvm.org/pr17214 - @expectedFailureLinux("llvm.org/pr20231") - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20231") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_step_over(self): """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-over a longjmp.""" self.build() @@ -38,8 +39,8 @@ class LongjmpTestCase(TestBase): @skipIfDarwin # llvm.org/pr16769: LLDB on Mac OS X dies in function ReadRegisterBytes in GDBRemoteRegisterContext.cpp @skipIfFreeBSD # llvm.org/pr17214 - @expectedFailureLinux("llvm.org/pr20231") - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20231") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_step_back_out(self): """Test stepping when the inferior calls setjmp/longjmp, in particular, thread step-out after thread step-in.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/memory/cache/Makefile b/packages/Python/lldbsuite/test/functionalities/memory/cache/Makefile new file mode 100644 index 000000000000..314f1cb2f077 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/memory/cache/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py b/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py new file mode 100644 index 000000000000..a65882d3fa43 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py @@ -0,0 +1,64 @@ +""" +Test the MemoryCache L1 flush. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class MemoryCacheTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// Set break point at this line.') + + @expectedFlakeyOS(oslist=["windows"]) + def test_memory_cache(self): + """Test the MemoryCache class with a sequence of 'memory read' and 'memory write' operations.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break in main() after the variables are assigned values. + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) + + # Read a chunk of memory containing &my_ints[0]. The number of bytes read + # must be greater than m_L2_cache_line_byte_size to make sure the L1 + # cache is used. + self.runCmd('memory read -f d -c 201 `&my_ints - 100`') + + # Check the value of my_ints[0] is the same as set in main.cpp. + line = self.res.GetOutput().splitlines()[100] + self.assertTrue(0x00000042 == int(line.split(':')[1], 0)) + + # Change the value of my_ints[0] in memory. + self.runCmd("memory write -s 4 `&my_ints` AA") + + # Re-read the chunk of memory. The cache line should have been + # flushed because of the 'memory write'. + self.runCmd('memory read -f d -c 201 `&my_ints - 100`') + + # Check the value of my_ints[0] have been updated correctly. + line = self.res.GetOutput().splitlines()[100] + self.assertTrue(0x000000AA == int(line.split(':')[1], 0)) diff --git a/packages/Python/lldbsuite/test/functionalities/memory/cache/main.cpp b/packages/Python/lldbsuite/test/functionalities/memory/cache/main.cpp new file mode 100644 index 000000000000..7f25e2f4bf68 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/memory/cache/main.cpp @@ -0,0 +1,14 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +int main () +{ + int my_ints[] = {0x42}; + return 0; // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py b/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py new file mode 100644 index 000000000000..7d959ec504c8 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/multidebugger_commands/TestMultipleDebuggersCommands.py @@ -0,0 +1,48 @@ +""" +Test that commands do not try and hold on to stale CommandInterpreters in a multiple debuggers scenario +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class MultipleDebuggersCommandsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_multipledebuggers_commands(self): + """Test that commands do not try and hold on to stale CommandInterpreters in a multiple debuggers scenario""" + source_init_files = False + magic_text = "The following commands may relate to 'env'" + + debugger_1 = lldb.SBDebugger.Create(source_init_files) + interpreter_1 = debugger_1.GetCommandInterpreter() + + retobj = lldb.SBCommandReturnObject() + interpreter_1.HandleCommand("apropos env", retobj) + self.assertTrue(magic_text in str(retobj), "[interpreter_1]: the output does not contain the correct words") + + if self.TraceOn(): print(str(retobj)) + + lldb.SBDebugger.Destroy(debugger_1) + + # now do this again with a different debugger - we shouldn't crash + + debugger_2 = lldb.SBDebugger.Create(source_init_files) + interpreter_2 = debugger_2.GetCommandInterpreter() + + retobj = lldb.SBCommandReturnObject() + interpreter_2.HandleCommand("apropos env", retobj) + self.assertTrue(magic_text in str(retobj), "[interpreter_2]: the output does not contain the correct words") + + if self.TraceOn(): print(str(retobj)) + + lldb.SBDebugger.Destroy(debugger_2) + diff --git a/packages/Python/lldbsuite/test/functionalities/nested_alias/Makefile b/packages/Python/lldbsuite/test/functionalities/nested_alias/Makefile new file mode 100644 index 000000000000..8a7102e347af --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/nested_alias/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/nested_alias/TestNestedAlias.py b/packages/Python/lldbsuite/test/functionalities/nested_alias/TestNestedAlias.py new file mode 100644 index 000000000000..6a74ddb727df --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/nested_alias/TestNestedAlias.py @@ -0,0 +1,68 @@ +""" +Test that an alias can reference other aliases without crashing. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class NestedAliasTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// break here') + + def test_nested_alias(self): + """Test that an alias can reference other aliases without crashing.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break in main() aftre the variables are assigned values. + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) + + # This is the function to remove the custom aliases in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('command unalias read', check=False) + self.runCmd('command unalias rd', check=False) + self.runCmd('command unalias fo', check=False) + self.runCmd('command unalias foself', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd('command alias read memory read -f A') + self.runCmd('command alias rd read -c 3') + + self.expect('memory read -f A -c 3 `&my_ptr[0]`', substrs=['deadbeef', 'main.cpp:', 'feedbeef']) + self.expect('rd `&my_ptr[0]`', substrs=['deadbeef', 'main.cpp:', 'feedbeef']) + + self.expect('memory read -f A -c 3 `&my_ptr[0]`', substrs=['deadfeed'], matching=False) + self.expect('rd `&my_ptr[0]`', substrs=['deadfeed'], matching=False) + + self.runCmd('command alias fo frame variable -O --') + self.runCmd('command alias foself fo self') + + self.expect('help foself', substrs=['--show-all-children', '--raw-output'], matching=False) + self.expect('help foself', substrs=['Show variables for the current', 'stack frame.'], matching=True) diff --git a/packages/Python/lldbsuite/test/functionalities/nested_alias/main.cpp b/packages/Python/lldbsuite/test/functionalities/nested_alias/main.cpp new file mode 100644 index 000000000000..4424cf30c3a4 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/nested_alias/main.cpp @@ -0,0 +1,22 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +int main (int argc, char const *argv[]) +{ + void* my_ptr[] = { + reinterpret_cast(0xDEADBEEF), + reinterpret_cast(main), + reinterpret_cast(0xFEEDBEEF), + reinterpret_cast(0xFEEDDEAD), + reinterpret_cast(0xDEADFEED) + }; + return 0; // break here +} + diff --git a/packages/Python/lldbsuite/test/functionalities/object-file/TestImageListMultiArchitecture.py b/packages/Python/lldbsuite/test/functionalities/object-file/TestImageListMultiArchitecture.py index 4f4a22ed6067..0fdc43bb9feb 100644 --- a/packages/Python/lldbsuite/test/functionalities/object-file/TestImageListMultiArchitecture.py +++ b/packages/Python/lldbsuite/test/functionalities/object-file/TestImageListMultiArchitecture.py @@ -9,16 +9,19 @@ from __future__ import print_function import os.path +import re + import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import re +from lldbsuite.test import lldbutil class TestImageListMultiArchitecture(TestBase): mydir = TestBase.compute_mydir(__file__) @no_debug_info_test + @skipIfRemote def test_image_list_shows_multiple_architectures(self): """Test that image list properly shows the correct architecture for a set of different architecture object files.""" images = { diff --git a/packages/Python/lldbsuite/test/functionalities/paths/TestPaths.py b/packages/Python/lldbsuite/test/functionalities/paths/TestPaths.py index f718b62f95ea..db577dc5bacd 100644 --- a/packages/Python/lldbsuite/test/functionalities/paths/TestPaths.py +++ b/packages/Python/lldbsuite/test/functionalities/paths/TestPaths.py @@ -8,8 +8,9 @@ from __future__ import print_function import lldb import os import time +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestPaths(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/platform/TestPlatformCommand.py b/packages/Python/lldbsuite/test/functionalities/platform/TestPlatformCommand.py index 6b3eedaf603a..9599f83d6a53 100644 --- a/packages/Python/lldbsuite/test/functionalities/platform/TestPlatformCommand.py +++ b/packages/Python/lldbsuite/test/functionalities/platform/TestPlatformCommand.py @@ -8,7 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class PlatformCommandTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/plugins/commands/TestPluginCommands.py b/packages/Python/lldbsuite/test/functionalities/plugins/commands/TestPluginCommands.py index b62c30bcf4e7..619ed7afe328 100644 --- a/packages/Python/lldbsuite/test/functionalities/plugins/commands/TestPluginCommands.py +++ b/packages/Python/lldbsuite/test/functionalities/plugins/commands/TestPluginCommands.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class PluginCommandTestCase(TestBase): @@ -18,7 +19,7 @@ class PluginCommandTestCase(TestBase): @skipIfNoSBHeaders @skipIfHostIncompatibleWithRemote # Requires a compatible arch and platform to link against the host's built lldb lib. - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") @no_debug_info_test def test_load_plugin(self): """Test that plugins that load commands work correctly.""" diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py new file mode 100644 index 000000000000..fd5bb00d0565 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py @@ -0,0 +1,164 @@ +""" +Test basics of linux core file debugging. +""" + +from __future__ import print_function + +import shutil +import struct + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class LinuxCoreTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + _i386_pid = 32306 + _x86_64_pid = 32259 + _s390x_pid = 1045 + + _i386_regions = 4 + _x86_64_regions = 5 + _s390x_regions = 2 + + @skipIf(bugnumber="llvm.org/pr26947") + def test_i386(self): + """Test that lldb can read the process information from an i386 linux core file.""" + self.do_test("i386", self._i386_pid, self._i386_regions) + + def test_x86_64(self): + """Test that lldb can read the process information from an x86_64 linux core file.""" + self.do_test("x86_64", self._x86_64_pid, self._x86_64_regions) + + # This seems to hang on non-s390x platforms for some reason. Disabling for now. + @skipIf(archs=no_match(['s390x'])) + def test_s390x(self): + """Test that lldb can read the process information from an s390x linux core file.""" + self.do_test("s390x", self._s390x_pid, self._s390x_regions) + + def test_same_pid_running(self): + """Test that we read the information from the core correctly even if we have a running + process with the same PID around""" + try: + shutil.copyfile("x86_64.out", "x86_64-pid.out") + shutil.copyfile("x86_64.core", "x86_64-pid.core") + with open("x86_64-pid.core", "r+b") as f: + # These are offsets into the NT_PRSTATUS and NT_PRPSINFO structures in the note + # segment of the core file. If you update the file, these offsets may need updating + # as well. (Notes can be viewed with readelf --notes.) + for pid_offset in [0x1c4, 0x320]: + f.seek(pid_offset) + self.assertEqual(struct.unpack(" smaller core files. +exec ./a.out diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core new file mode 100644 index 000000000000..b97fc43e967d Binary files /dev/null and b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core differ diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out new file mode 100755 index 000000000000..640fbdc257d9 Binary files /dev/null and b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out differ diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core new file mode 100644 index 000000000000..e2fa69e4558e Binary files /dev/null and b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.core differ diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out new file mode 100755 index 000000000000..842402fd519d Binary files /dev/null and b/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/x86_64.out differ diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py index 1dda59ac374b..89d1974b6703 100644 --- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py @@ -7,8 +7,9 @@ from six import iteritems import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class MiniDumpTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py new file mode 100644 index 000000000000..08debab538f5 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/TestWow64MiniDump.py @@ -0,0 +1,76 @@ +""" +Test basics of a mini dump taken of a 32-bit process running in WoW64 + +WoW64 is the subsystem that lets 32-bit processes run in 64-bit Windows. If you +capture a mini dump of a process running under WoW64 with a 64-bit debugger, you +end up with a dump of the WoW64 layer. In that case, LLDB must do extra work to +get the 32-bit register contexts. +""" + +from __future__ import print_function +from six import iteritems + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class Wow64MiniDumpTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts + @no_debug_info_test + def test_wow64_mini_dump(self): + """Test that lldb can read the process information from the minidump.""" + # target create -c fizzbuzz_wow64.dmp + target = self.dbg.CreateTarget("") + process = target.LoadCore("fizzbuzz_wow64.dmp") + self.assertTrue(process, PROCESS_IS_VALID) + self.assertEqual(process.GetNumThreads(), 1) + self.assertEqual(process.GetProcessID(), 0x1E9C) + + @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts + @no_debug_info_test + def test_thread_info_in_wow64_mini_dump(self): + """Test that lldb can read the thread information from the minidump.""" + # target create -c fizzbuzz_wow64.dmp + target = self.dbg.CreateTarget("") + process = target.LoadCore("fizzbuzz_wow64.dmp") + # This process crashed due to an access violation (0xc0000005), but the + # minidump doesn't have an exception record--perhaps the crash handler + # ate it. + # TODO: See if we can recover the exception information from the TEB, + # which, according to Windbg, has a pointer to an exception list. + + # In the dump, none of the threads are stopped, so we cannot use + # lldbutil.get_stopped_thread. + thread = process.GetThreadAtIndex(0) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone) + + @skipUnlessWindows # for now mini-dump debugging is limited to Windows hosts + @no_debug_info_test + def test_stack_info_in_wow64_mini_dump(self): + """Test that we can see a trivial stack in a VS-generate mini dump.""" + # target create -c fizzbuzz_no_heap.dmp + target = self.dbg.CreateTarget("") + process = target.LoadCore("fizzbuzz_wow64.dmp") + self.assertGreaterEqual(process.GetNumThreads(), 1) + # This process crashed due to an access violation (0xc0000005), but the + # minidump doesn't have an exception record--perhaps the crash handler + # ate it. + # TODO: See if we can recover the exception information from the TEB, + # which, according to Windbg, has a pointer to an exception list. + + # In the dump, none of the threads are stopped, so we cannot use + # lldbutil.get_stopped_thread. + thread = process.GetThreadAtIndex(0) + # The crash is in main, so there should be at least one frame on the stack. + self.assertGreaterEqual(thread.GetNumFrames(), 1) + frame = thread.GetFrameAtIndex(0) + self.assertTrue(frame.IsValid()) + pc = frame.GetPC() + eip = frame.FindRegister("pc") + self.assertTrue(eip.IsValid()) + self.assertEqual(pc, eip.GetValueAsUnsigned()) diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp new file mode 100644 index 000000000000..295d4a1f24db --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz.cpp @@ -0,0 +1,31 @@ +// A sample program for getting minidumps on Windows. + +#include + +bool +fizz(int x) +{ + return x % 3 == 0; +} + +bool +buzz(int x) +{ + return x % 5 == 0; +} + +int +main() +{ + int *buggy = 0; + + for (int i = 1; i <= 100; ++i) + { + if (fizz(i)) std::cout << "fizz"; + if (buzz(i)) std::cout << "buzz"; + if (!fizz(i) && !buzz(i)) std::cout << i; + std::cout << '\n'; + } + + return *buggy; +} diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp new file mode 100644 index 000000000000..3d97186f2cd2 Binary files /dev/null and b/packages/Python/lldbsuite/test/functionalities/postmortem/wow64_minidump/fizzbuzz_wow64.dmp differ diff --git a/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py b/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py index 83906b546300..e4eb302d83d1 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py +++ b/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil exe_name = "ProcessAttach" # Must match Makefile diff --git a/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py b/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py index ed9d58f90888..3d1d7fdc7907 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py +++ b/packages/Python/lldbsuite/test/functionalities/process_attach/attach_denied/TestAttachDenied.py @@ -9,7 +9,9 @@ from __future__ import print_function import os import time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil exe_name = 'AttachDenied' # Must match Makefile @@ -17,12 +19,6 @@ class AttachDeniedTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - def run_platform_command(self, cmd): - platform = self.dbg.GetSelectedPlatform() - shell_command = lldb.SBPlatformShellCommand(cmd) - err = platform.Run(shell_command) - return (err, shell_command.GetStatus(), shell_command.GetOutput()) - @skipIfWindows @skipIfiOSSimulator def test_attach_to_process_by_id_denied(self): @@ -39,21 +35,7 @@ class AttachDeniedTestCase(TestBase): popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) - max_attempts = 5 - for i in range(max_attempts): - err, retcode, msg = self.run_platform_command("ls %s" % pid_file_path) - if err.Success() and retcode == 0: - break - else: - print(msg) - if i < max_attempts: - # Exponential backoff! - time.sleep(pow(2, i) * 0.25) - else: - self.fail("Child PID file %s not found even after %d attempts." % (pid_file_path, max_attempts)) - err, retcode, pid = self.run_platform_command("cat %s" % (pid_file_path)) - self.assertTrue(err.Success() and retcode == 0, - "Failed to read file %s: %s, retcode: %d" % (pid_file_path, err.GetCString(), retcode)) + pid = lldbutil.wait_for_file_on_target(self, pid_file_path) self.expect('process attach -p ' + pid, startstr = 'error: attach failed:', diff --git a/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py b/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py index 25be37b2b12d..c20d66aa3ab0 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py +++ b/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py @@ -6,8 +6,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ChangeProcessGroupTestCase(TestBase): @@ -35,23 +36,7 @@ class ChangeProcessGroupTestCase(TestBase): popen = self.spawnSubprocess(exe, [pid_file_path]) self.addTearDownHook(self.cleanupSubprocesses) - max_attempts = 5 - for i in range(max_attempts): - err, retcode, msg = self.run_platform_command("ls %s" % pid_file_path) - if err.Success() and retcode == 0: - break - else: - print(msg) - if i < max_attempts: - # Exponential backoff! - time.sleep(pow(2, i) * 0.25) - else: - self.fail("Child PID file %s not found even after %d attempts." % (pid_file_path, max_attempts)) - - err, retcode, pid = self.run_platform_command("cat %s" % (pid_file_path)) - - self.assertTrue(err.Success() and retcode == 0, - "Failed to read file %s: %s, retcode: %d" % (pid_file_path, err.GetCString(), retcode)) + pid = lldbutil.wait_for_file_on_target(self, pid_file_path) # make sure we cleanup the forked child also def cleanupChild(): @@ -99,9 +84,3 @@ class ChangeProcessGroupTestCase(TestBase): # run to completion process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited) - - def run_platform_command(self, cmd): - platform = self.dbg.GetSelectedPlatform() - shell_command = lldb.SBPlatformShellCommand(cmd) - err = platform.Run(shell_command) - return (err, shell_command.GetStatus(), shell_command.GetOutput()) diff --git a/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py b/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py index 3131000be428..5998edb3c7e0 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py +++ b/packages/Python/lldbsuite/test/functionalities/process_launch/TestProcessLaunch.py @@ -4,11 +4,16 @@ Test lldb process launch flags. from __future__ import print_function +import copy +import os +import time - -import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +import six class ProcessLaunchTestCase(TestBase): @@ -17,9 +22,11 @@ class ProcessLaunchTestCase(TestBase): def setUp(self): # Call super's setUp(). TestBase.setUp(self) - # disable "There is a running process, kill it and restart?" prompt self.runCmd("settings set auto-confirm true") - self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm")) + + def tearDown(self): + self.runCmd("settings clear auto-confirm") + TestBase.tearDown(self) @not_remote_testsuite_ready def test_io (self): @@ -109,7 +116,7 @@ class ProcessLaunchTestCase(TestBase): # rdar://problem/9056462 # The process launch flag '-w' for setting the current working directory not working? @not_remote_testsuite_ready - @expectedFailureLinux("llvm.org/pr20265") + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr20265") def test_set_working_dir (self): """Test that '-w dir' sets the working dir when running the inferior.""" d = {'CXX_SOURCES' : 'print_cwd.cpp'} @@ -180,8 +187,9 @@ class ProcessLaunchTestCase(TestBase): self.fail(err_msg) def test_environment_with_special_char (self): - """Test that environment variables containing '*' and '}' are communicated correctly to the lldb-server.""" - d = {'CXX_SOURCES' : 'print_env.cpp'} + """Test that environment variables containing '*' and '}' are handled correctly by the inferior.""" + source = 'print_env.cpp' + d = {'CXX_SOURCES' : source} self.build(dictionary=d) self.setTearDownCleanup(d) exe = os.path.join (os.getcwd(), "a.out") @@ -189,19 +197,19 @@ class ProcessLaunchTestCase(TestBase): evil_var = 'INIT*MIDDLE}TAIL' target = self.dbg.CreateTarget(exe) - process = target.LaunchSimple(None, ['EVIL=' + evil_var], self.get_process_working_directory()) - self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) - - out = process.GetSTDOUT(len(evil_var)) - self.assertIsNotNone(out, "Encountered an error reading the process's output") + main_source_spec = lldb.SBFileSpec(source) + breakpoint = target.BreakpointCreateBySourceRegex('// Set breakpoint here.', main_source_spec) - out = out[:len(evil_var)] - if out != evil_var: - self.fail('The environment variable was mis-coded: %s\n' % repr(out)) + process = target.LaunchSimple(None, ['EVIL=' + evil_var], self.get_process_working_directory()) + self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) - newline = process.GetSTDOUT(1) - self.assertIsNotNone(newline, "Encountered an error reading the process's output") + threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertEqual(len(threads), 1) + frame = threads[0].GetFrameAtIndex(0) + sbvalue = frame.EvaluateExpression("evil") + value = sbvalue.GetSummary().strip('"') - newline = newline[0] - if newline != '\r' and newline != '\n': - self.fail('Garbage at end of environment variable') + self.assertEqual(value, evil_var) + process.Continue() + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) + pass diff --git a/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp b/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp index cbb9b2175916..8c6df8ea01a4 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp +++ b/packages/Python/lldbsuite/test/functionalities/process_launch/print_env.cpp @@ -5,7 +5,6 @@ int main (int argc, char **argv) { char *evil = getenv("EVIL"); - puts(evil); - return 0; + return 0; // Set breakpoint here. } diff --git a/packages/Python/lldbsuite/test/functionalities/process_save_core/TestProcessSaveCore.py b/packages/Python/lldbsuite/test/functionalities/process_save_core/TestProcessSaveCore.py index 0578bcf44b4c..1c01e2138c2e 100644 --- a/packages/Python/lldbsuite/test/functionalities/process_save_core/TestProcessSaveCore.py +++ b/packages/Python/lldbsuite/test/functionalities/process_save_core/TestProcessSaveCore.py @@ -6,7 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ProcessSaveCoreTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/ptr_refs/Makefile b/packages/Python/lldbsuite/test/functionalities/ptr_refs/Makefile new file mode 100644 index 000000000000..0d70f2595019 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/ptr_refs/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/ptr_refs/TestPtrRefs.py b/packages/Python/lldbsuite/test/functionalities/ptr_refs/TestPtrRefs.py new file mode 100644 index 000000000000..81db42d8e3c6 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/ptr_refs/TestPtrRefs.py @@ -0,0 +1,43 @@ +""" +Test the ptr_refs tool on Darwin +""" + +from __future__ import print_function + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestPtrRefs(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_ptr_refs(self): + """Test format string functionality.""" + self.build() + exe_name = 'a.out' + exe = os.path.join(os.getcwd(), exe_name) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + main_file_spec = lldb.SBFileSpec ('main.c') + breakpoint = target.BreakpointCreateBySourceRegex('break', main_file_spec) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1 and the break condition should hold. + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + + frame = thread.GetFrameAtIndex(0) + + self.dbg.HandleCommand("script import lldb.macosx.heap") + self.expect("ptr_refs my_ptr", substrs=["malloc", "stack"]); diff --git a/packages/Python/lldbsuite/test/functionalities/ptr_refs/main.c b/packages/Python/lldbsuite/test/functionalities/ptr_refs/main.c new file mode 100644 index 000000000000..4053f9997276 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/ptr_refs/main.c @@ -0,0 +1,27 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +struct referent { + const char *p; +}; + +int main (int argc, char const *argv[]) +{ + const char *my_ptr = strdup("hello"); + struct referent *r = malloc(sizeof(struct referent)); + r->p = my_ptr; + + printf("%p\n", r); // break here + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py b/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py index c5d4650aa371..21de3ab7cc37 100644 --- a/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py +++ b/packages/Python/lldbsuite/test/functionalities/register/TestRegisters.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, sys, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class RegisterCommandsTestCase(TestBase): @@ -25,7 +26,7 @@ class RegisterCommandsTestCase(TestBase): TestBase.tearDown(self) @skipIfiOSSimulator - @skipUnlessArch(['amd64', 'arm', 'i386', 'x86_64']) + @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) def test_register_commands(self): """Test commands related to registers, in particular vector registers.""" self.build() @@ -48,7 +49,7 @@ class RegisterCommandsTestCase(TestBase): @skipIfiOSSimulator @skipIfTargetAndroid(archs=["i386"]) # Writing of mxcsr register fails, presumably due to a kernel/hardware problem - @skipUnlessArch(['amd64', 'arm', 'i386', 'x86_64']) + @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) def test_fp_register_write(self): """Test commands that write to registers, in particular floating-point registers.""" self.build() @@ -57,14 +58,14 @@ class RegisterCommandsTestCase(TestBase): @skipIfiOSSimulator @expectedFailureAndroid(archs=["i386"]) # "register read fstat" always return 0xffff @skipIfFreeBSD #llvm.org/pr25057 - @skipUnlessArch(['amd64', 'i386', 'x86_64']) + @skipIf(archs=no_match(['amd64', 'i386', 'x86_64'])) def test_fp_special_purpose_register_read(self): """Test commands that read fpu special purpose registers.""" self.build() self.fp_special_purpose_register_read() @skipIfiOSSimulator - @skipUnlessArch(['amd64', 'arm', 'i386', 'x86_64']) + @skipIf(archs=no_match(['amd64', 'arm', 'i386', 'x86_64'])) def test_register_expressions(self): """Test expression evaluation with commands related to registers.""" self.build() @@ -85,21 +86,21 @@ class RegisterCommandsTestCase(TestBase): self.expect("expr -- ($rax & 0xffffffff) == $eax", substrs = ['true']) @skipIfiOSSimulator - @skipUnlessArch(['amd64', 'x86_64']) + @skipIf(archs=no_match(['amd64', 'x86_64'])) def test_convenience_registers(self): """Test convenience registers.""" self.build() self.convenience_registers() @skipIfiOSSimulator - @skipUnlessArch(['amd64', 'x86_64']) + @skipIf(archs=no_match(['amd64', 'x86_64'])) def test_convenience_registers_with_process_attach(self): """Test convenience registers after a 'process attach'.""" self.build() self.convenience_registers_with_process_attach(test_16bit_regs=False) @skipIfiOSSimulator - @skipUnlessArch(['amd64', 'x86_64']) + @skipIf(archs=no_match(['amd64', 'x86_64'])) def test_convenience_registers_16bit_with_process_attach(self): """Test convenience registers after a 'process attach'.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/rerun/TestRerun.py b/packages/Python/lldbsuite/test/functionalities/rerun/TestRerun.py index 0ed56de35699..8636abadd104 100644 --- a/packages/Python/lldbsuite/test/functionalities/rerun/TestRerun.py +++ b/packages/Python/lldbsuite/test/functionalities/rerun/TestRerun.py @@ -8,8 +8,9 @@ from __future__ import print_function import lldb import os import time +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestRerun(TestBase): @@ -31,19 +32,9 @@ class TestRerun(TestBase): self.runCmd("process launch 1 2 3") process = self.process() - - self.assertTrue(process.GetState() == lldb.eStateStopped, - STOPPED_DUE_TO_BREAKPOINT) - - thread = process.GetThreadAtIndex (0) - - self.assertTrue (thread.IsValid(), - "Process stopped at 'main' should have a valid thread"); - - stop_reason = thread.GetStopReason() - - self.assertTrue (stop_reason == lldb.eStopReasonBreakpoint, - "Thread in process stopped in 'main' should have a stop reason of eStopReasonBreakpoint"); + thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, breakpoint) + self.assertIsNotNone(thread, "Process should be stopped at a breakpoint in main") + self.assertTrue(thread.IsValid(), "Stopped thread is not valid") self.expect("frame variable argv[1]", substrs=['1']) self.expect("frame variable argv[2]", substrs=['2']) @@ -57,19 +48,10 @@ class TestRerun(TestBase): self.runCmd("process launch") process = self.process() - - self.assertTrue(process.GetState() == lldb.eStateStopped, - STOPPED_DUE_TO_BREAKPOINT) - - thread = process.GetThreadAtIndex (0) + thread = lldbutil.get_one_thread_stopped_at_breakpoint(process, breakpoint) - self.assertTrue (thread.IsValid(), - "Process stopped at 'main' should have a valid thread"); - - stop_reason = thread.GetStopReason() - - self.assertTrue (stop_reason == lldb.eStopReasonBreakpoint, - "Thread in process stopped in 'main' should have a stop reason of eStopReasonBreakpoint"); + self.assertIsNotNone(thread, "Process should be stopped at a breakpoint in main"); + self.assertTrue(thread.IsValid(), "Stopped thread is not valid") self.expect("frame variable argv[1]", substrs=['1']) self.expect("frame variable argv[2]", substrs=['2']) diff --git a/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py b/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py index 246eb5c3fdbd..81d93294b5a5 100644 --- a/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py +++ b/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ReturnValueTestCase(TestBase): @@ -19,7 +20,7 @@ class ReturnValueTestCase(TestBase): @expectedFailureAll(oslist=["macosx","freebsd"], archs=["i386"]) @expectedFailureAll(oslist=["linux"], compiler="clang", compiler_version=["<=", "3.6"], archs=["i386"]) @expectedFailureAll(bugnumber="llvm.org/pr25785", hostoslist=["windows"], compiler="gcc", archs=["i386"], triple='.*-android') - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") @add_test_categories(['pyapi']) def test_with_python(self): """Test getting return values from stepping out.""" diff --git a/packages/Python/lldbsuite/test/functionalities/set-data/TestSetData.py b/packages/Python/lldbsuite/test/functionalities/set-data/TestSetData.py index 3acad5f87be0..294aa6725155 100644 --- a/packages/Python/lldbsuite/test/functionalities/set-data/TestSetData.py +++ b/packages/Python/lldbsuite/test/functionalities/set-data/TestSetData.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SetDataTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/signal/TestSendSignal.py b/packages/Python/lldbsuite/test/functionalities/signal/TestSendSignal.py index 971b82a7c75d..1da4d701a590 100644 --- a/packages/Python/lldbsuite/test/functionalities/signal/TestSendSignal.py +++ b/packages/Python/lldbsuite/test/functionalities/signal/TestSendSignal.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time, signal import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SendSignalTestCase(TestBase): @@ -20,7 +21,7 @@ class SendSignalTestCase(TestBase): # Find the line number to break inside main(). self.line = line_number('main.c', 'Put breakpoint here') - @expectedFailureFreeBSD("llvm.org/pr23318: does not report running state") + @expectedFailureAll(oslist=['freebsd'], bugnumber="llvm.org/pr23318: does not report running state") @skipIfWindows # Windows does not support signals def test_with_run_command(self): """Test that lldb command 'process signal SIGUSR1' sends a signal to the inferior process.""" diff --git a/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/TestHandleSegv.py b/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/TestHandleSegv.py index feed5bfb3c76..d8dbb7f68936 100644 --- a/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/TestHandleSegv.py +++ b/packages/Python/lldbsuite/test/functionalities/signal/handle-segv/TestHandleSegv.py @@ -5,10 +5,12 @@ from __future__ import print_function import os +import re + import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import re +from lldbsuite.test import lldbutil class HandleSegvTestCase(TestBase): @@ -17,7 +19,7 @@ class HandleSegvTestCase(TestBase): @skipIfWindows # signals do not exist on Windows @skipIfDarwin - @expectedFailureFreeBSD("llvm.org/pr23699 SIGSEGV is reported as exception, not signal") + @expectedFailureAll(oslist=['freebsd'], bugnumber="llvm.org/pr23699 SIGSEGV is reported as exception, not signal") def test_inferior_handle_sigsegv(self): self.build() exe = os.path.join(os.getcwd(), "a.out") diff --git a/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py b/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py index 39e7753397d1..2c30f69d7b20 100644 --- a/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py +++ b/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py @@ -6,9 +6,11 @@ from __future__ import print_function import os import lldb -from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil import re +from lldbsuite.test.lldbplatformutil import getDarwinOSTriples +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil @skipIfWindows # signals do not exist on Windows @@ -148,8 +150,7 @@ class RaiseTestCase(TestBase): # reset signal handling to default self.set_handle(signal, default_pass, default_stop, default_notify) - @expectedFailureLinux("llvm.org/pr24530") # the signal the inferior generates gets lost - @expectedFailureDarwin("llvm.org/pr24530") # the signal the inferior generates gets lost + @expectedFailureAll(oslist=["linux"]+getDarwinOSTriples(), bugnumber="llvm.org/pr20231") def test_restart_bug(self): """Test that we catch a signal in the edge case where the process receives it while we are about to interrupt it""" diff --git a/packages/Python/lldbsuite/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py b/packages/Python/lldbsuite/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py index 6a2dd74d3956..6f5882636cb6 100644 --- a/packages/Python/lldbsuite/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py +++ b/packages/Python/lldbsuite/test/functionalities/single-quote-in-filename-to-lldb/TestSingleQuoteInFilename.py @@ -8,7 +8,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SingleQuoteInCommandLineTestCase(TestBase): @@ -25,7 +27,7 @@ class SingleQuoteInCommandLineTestCase(TestBase): except: pass - @expectedFailureHostWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @no_debug_info_test def test_lldb_invocation_with_single_quote_in_filename(self): """Test that 'lldb my_file_name' works where my_file_name is a string with a single quote char in it.""" diff --git a/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/TestStepNoDebug.py b/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/TestStepNoDebug.py index 6c1f2c3da41b..8b9c91217de4 100644 --- a/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/TestStepNoDebug.py +++ b/packages/Python/lldbsuite/test/functionalities/step-avoids-no-debug/TestStepNoDebug.py @@ -8,10 +8,12 @@ from __future__ import print_function import os import re -import lldb -import lldbsuite.test.lldbutil as lldbutil import sys + +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ReturnValueTestCase(TestBase): @@ -25,7 +27,8 @@ class ReturnValueTestCase(TestBase): self.do_step_out_past_nodebug() @add_test_categories(['pyapi']) - @expectedFailureGcc("llvm.org/pr19247") + @decorators.expectedFailureAll(compiler="gcc", bugnumber="llvm.org/pr28549") + @decorators.expectedFailureAll(compiler="clang", compiler_version=[">=", "3.9"], archs=["i386"], bugnumber="llvm.org/pr28549") def test_step_over_with_python(self): """Test stepping over using avoid-no-debug with dwarf.""" self.build() @@ -33,7 +36,8 @@ class ReturnValueTestCase(TestBase): self.do_step_over_past_nodebug() @add_test_categories(['pyapi']) - @expectedFailureGcc("llvm.org/pr19247") + @decorators.expectedFailureAll(compiler="gcc", bugnumber="llvm.org/pr28549") + @decorators.expectedFailureAll(compiler="clang", compiler_version=[">=", "3.9"], archs=["i386"], bugnumber="llvm.org/pr28549") def test_step_in_with_python(self): """Test stepping in using avoid-no-debug with dwarf.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py index 753491339c4c..93f846a06870 100644 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py +++ b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py @@ -8,8 +8,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class StopHookCmdTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py index 7785d85772e2..c42c1e563881 100644 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py +++ b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py @@ -8,8 +8,10 @@ from __future__ import print_function import os import lldb -from lldbsuite.test import configuration +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import configuration +from lldbsuite.test import lldbutil class StopHookMechanismTestCase(TestBase): @@ -26,7 +28,7 @@ class StopHookMechanismTestCase(TestBase): @skipIfFreeBSD # llvm.org/pr15037 @expectedFlakeyLinux('llvm.org/pr15037') # stop-hooks sometimes fail to fire on Linux - @expectedFailureHostWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test(self): """Test the stop-hook mechanism.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py index c7fb53d495e6..57395832dc21 100644 --- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py +++ b/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py @@ -8,8 +8,10 @@ from __future__ import print_function import os, time import lldb -from lldbsuite.test import configuration +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import configuration +from lldbsuite.test import lldbutil class StopHookForMultipleThreadsTestCase(TestBase): @@ -29,7 +31,7 @@ class StopHookForMultipleThreadsTestCase(TestBase): @expectedFlakeyFreeBSD("llvm.org/pr15037") @expectedFlakeyLinux("llvm.org/pr15037") # stop hooks sometimes fail to fire on Linux - @expectedFailureHostWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") def test_stop_hook_multiple_threads(self): """Test that lldb stop-hook works for multiple threads.""" self.build(dictionary=self.d) diff --git a/packages/Python/lldbsuite/test/functionalities/target_command/TestTargetCommand.py b/packages/Python/lldbsuite/test/functionalities/target_command/TestTargetCommand.py index 0ab965d2aa16..126f6e4dab80 100644 --- a/packages/Python/lldbsuite/test/functionalities/target_command/TestTargetCommand.py +++ b/packages/Python/lldbsuite/test/functionalities/target_command/TestTargetCommand.py @@ -8,8 +8,9 @@ from __future__ import print_function import lldb import sys +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class targetCommandTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py index 91bc68577a43..902adacb2abd 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py @@ -5,8 +5,9 @@ Test regression for Bug 25251. import os, time import unittest2 import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BreakpointAfterJoinTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py b/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py index 43397a122391..8ef0fb0a000d 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/TestBreakAfterJoin.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BreakpointAfterJoinTestCase(TestBase): @@ -21,9 +22,9 @@ class BreakpointAfterJoinTestCase(TestBase): # Find the line number for our breakpoint. self.breakpoint = line_number('main.cpp', '// Set breakpoint here') - @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr18190 thread states not properly maintained") def test(self): """Test breakpoint handling after a thread join.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp index a63079524ee2..f9f33fda82bb 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/thread/break_after_join/main.cpp @@ -19,24 +19,12 @@ volatile int g_test = 0; -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. -#define do_nothing() - -#define pseudo_barrier_wait(bar) \ - --bar; \ - while (bar > 0) \ - do_nothing(); - -#define pseudo_barrier_init(bar, count) (bar = count) - // A barrier to synchronize all the threads. -std::atomic_int g_barrier1; +pseudo_barrier_t g_barrier1; // A barrier to keep the threads from exiting until after the breakpoint has // been passed. -std::atomic_int g_barrier2; +pseudo_barrier_t g_barrier2; void * break_thread_func () diff --git a/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py b/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py index 9eb25b68765a..30adcccd203f 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py @@ -17,11 +17,11 @@ from __future__ import print_function import unittest2 import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipIfWindows -@expectedFailureAll(archs=['mips64', 'mips64el']) # Atomic sequences are not supported yet for MIPS in LLDB. class ConcurrentEventsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @@ -30,24 +30,28 @@ class ConcurrentEventsTestCase(TestBase): ## Tests for multiple threads that generate a single event. # @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_many_breakpoints(self): """Test 100 breakpoints from 100 threads.""" self.build(dictionary=self.getBuildFlags()) self.do_thread_actions(num_breakpoint_threads=100) @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_many_watchpoints(self): """Test 100 watchpoints from 100 threads.""" self.build(dictionary=self.getBuildFlags()) self.do_thread_actions(num_watchpoint_threads=100) @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_many_signals(self): """Test 100 signals from 100 threads.""" self.build(dictionary=self.getBuildFlags()) self.do_thread_actions(num_signal_threads=100) @unittest2.skipIf(TestBase.skipLongRunningTest(), "Skip this long running test") + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_many_crash(self): """Test 100 threads that cause a segfault.""" self.build(dictionary=self.getBuildFlags()) @@ -58,18 +62,21 @@ class ConcurrentEventsTestCase(TestBase): ## Tests for concurrent signal and breakpoint # @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_signal_break(self): """Test signal and a breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) self.do_thread_actions(num_breakpoint_threads=1, num_signal_threads=1) @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_delay_signal_break(self): """Test (1-second delay) signal and a breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) self.do_thread_actions(num_breakpoint_threads=1, num_delay_signal_threads=1) @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_signal_delay_break(self): """Test signal and a (1 second delay) breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -81,6 +88,7 @@ class ConcurrentEventsTestCase(TestBase): # @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_watch_break(self): """Test watchpoint and a breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -88,6 +96,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_delay_watch_break(self): """Test (1-second delay) watchpoint and a breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -95,6 +104,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_watch_break_delay(self): """Test watchpoint and a (1 second delay) breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -105,6 +115,7 @@ class ConcurrentEventsTestCase(TestBase): # @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_signal_watch(self): """Test a watchpoint and a signal in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -112,6 +123,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_delay_signal_watch(self): """Test a watchpoint and a (1 second delay) signal in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -119,7 +131,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock - @expectedFailureAll("llvm.org/pr16714", oslist=["linux"], archs=["i386"]) + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_signal_delay_watch(self): """Test a (1 second delay) watchpoint and a signal in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -130,12 +142,14 @@ class ConcurrentEventsTestCase(TestBase): ## Tests for multiple breakpoint threads # @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_two_breakpoint_threads(self): """Test two threads that trigger a breakpoint. """ self.build(dictionary=self.getBuildFlags()) self.do_thread_actions(num_breakpoint_threads=2) @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_breakpoint_one_delay_breakpoint_threads(self): """Test threads that trigger a breakpoint where one thread has a 1 second delay. """ self.build(dictionary=self.getBuildFlags()) @@ -143,12 +157,14 @@ class ConcurrentEventsTestCase(TestBase): num_delay_breakpoint_threads=1) @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_two_breakpoints_one_signal(self): """Test two threads that trigger a breakpoint and one signal thread. """ self.build(dictionary=self.getBuildFlags()) self.do_thread_actions(num_breakpoint_threads=2, num_signal_threads=1) @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_breakpoint_delay_breakpoint_one_signal(self): """Test two threads that trigger a breakpoint (one with a 1 second delay) and one signal thread. """ self.build(dictionary=self.getBuildFlags()) @@ -157,6 +173,7 @@ class ConcurrentEventsTestCase(TestBase): num_signal_threads=1) @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_two_breakpoints_one_delay_signal(self): """Test two threads that trigger a breakpoint and one (1 second delay) signal thread. """ self.build(dictionary=self.getBuildFlags()) @@ -164,6 +181,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_two_breakpoints_one_watchpoint(self): """Test two threads that trigger a breakpoint and one watchpoint thread. """ self.build(dictionary=self.getBuildFlags()) @@ -171,6 +189,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_breakpoints_delayed_breakpoint_one_watchpoint(self): """Test a breakpoint, a delayed breakpoint, and one watchpoint thread. """ self.build(dictionary=self.getBuildFlags()) @@ -183,6 +202,7 @@ class ConcurrentEventsTestCase(TestBase): # @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_two_watchpoint_threads(self): """Test two threads that trigger a watchpoint. """ self.build(dictionary=self.getBuildFlags()) @@ -190,6 +210,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_watchpoint_with_delay_watchpoint_threads(self): """Test two threads that trigger a watchpoint where one thread has a 1 second delay. """ self.build(dictionary=self.getBuildFlags()) @@ -198,6 +219,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_two_watchpoints_one_breakpoint(self): """Test two threads that trigger a watchpoint and one breakpoint thread. """ self.build(dictionary=self.getBuildFlags()) @@ -205,6 +227,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_two_watchpoints_one_delay_breakpoint(self): """Test two threads that trigger a watchpoint and one (1 second delay) breakpoint thread. """ self.build(dictionary=self.getBuildFlags()) @@ -212,6 +235,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_watchpoint_delay_watchpoint_one_breakpoint(self): """Test two threads that trigger a watchpoint (one with a 1 second delay) and one breakpoint thread. """ self.build(dictionary=self.getBuildFlags()) @@ -221,6 +245,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_two_watchpoints_one_signal(self): """Test two threads that trigger a watchpoint and one signal thread. """ self.build(dictionary=self.getBuildFlags()) @@ -231,6 +256,7 @@ class ConcurrentEventsTestCase(TestBase): # @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_signal_watch_break(self): """Test a signal/watchpoint/breakpoint in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -240,6 +266,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_signal_watch_break(self): """Test one signal thread with 5 watchpoint and breakpoint threads.""" self.build(dictionary=self.getBuildFlags()) @@ -249,6 +276,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_signal_watch_break(self): """Test with 5 watchpoint and breakpoint threads.""" self.build(dictionary=self.getBuildFlags()) @@ -260,6 +288,7 @@ class ConcurrentEventsTestCase(TestBase): ## Test for crashing threads happening concurrently with other events # @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_crash_with_break(self): """ Test a thread that crashes while another thread hits a breakpoint.""" self.build(dictionary=self.getBuildFlags()) @@ -267,12 +296,14 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_crash_with_watchpoint(self): """ Test a thread that crashes while another thread hits a watchpoint.""" self.build(dictionary=self.getBuildFlags()) self.do_thread_actions(num_crash_threads=1, num_watchpoint_threads=1) @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_crash_with_signal(self): """ Test a thread that crashes while another thread generates a signal.""" self.build(dictionary=self.getBuildFlags()) @@ -280,6 +311,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_crash_with_watchpoint_breakpoint_signal(self): """ Test a thread that crashes while other threads generate a signal and hit a watchpoint and breakpoint. """ self.build(dictionary=self.getBuildFlags()) @@ -290,6 +322,7 @@ class ConcurrentEventsTestCase(TestBase): @skipIfFreeBSD # timing out on buildbot @skipIfRemoteDueToDeadlock + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_delayed_crash_with_breakpoint_watchpoint(self): """ Test a thread with a delayed crash while other threads hit a watchpoint and a breakpoint. """ self.build(dictionary=self.getBuildFlags()) @@ -298,6 +331,7 @@ class ConcurrentEventsTestCase(TestBase): num_watchpoint_threads=1) @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(triple = '^mips') # Atomic sequences are not supported yet for MIPS in LLDB. def test_delayed_crash_with_breakpoint_signal(self): """ Test a thread with a delayed crash while other threads generate a signal and hit a breakpoint. """ self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp index ac2535cd2bff..10b55bff3ba4 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/main.cpp @@ -23,22 +23,10 @@ using namespace std; #include #include -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. -#define do_nothing() - -#define pseudo_barrier_wait(bar) \ - --bar; \ - while (bar > 0) \ - do_nothing(); - -#define pseudo_barrier_init(bar, count) (bar = count) - typedef std::vector > action_counts; typedef std::vector thread_vector; -std::atomic_int g_barrier; +pseudo_barrier_t g_barrier; int g_breakpoint = 0; int g_sigusr1_count = 0; std::atomic_int g_watchme; diff --git a/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py index 24b5bf0dad36..edd1e885ca9e 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py @@ -8,8 +8,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CreateDuringStepTestCase(TestBase): @@ -19,9 +20,10 @@ class CreateDuringStepTestCase(TestBase): TestBase.setUp(self) self.breakpoint = line_number('main.cpp', '// Set breakpoint here') - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") @expectedFailureAndroid("llvm.org/pr24497", archs=['arm', 'aarch64']) - @expectedFailureAll(archs=['mips', 'mipsel', 'mips64', 'mips64el']) # IO error due to breakpoint at invalid address + @expectedFailureAll(oslist=["linux"], archs=["arm"], bugnumber="llvm.org/pr24497") + @expectedFailureAll(triple = re.compile('^mips')) # IO error due to breakpoint at invalid address def test_step_inst_with(self): """Test thread creation during step-inst handling.""" self.build(dictionary=self.getBuildFlags()) @@ -38,11 +40,8 @@ class CreateDuringStepTestCase(TestBase): # The stop reason should be breakpoint. self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) - self.assertEqual(lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint).IsValid(), 1, - STOPPED_DUE_TO_BREAKPOINT) - - thread = process.GetThreadAtIndex(0) - self.assertTrue(thread and thread.IsValid(), "Thread is valid") + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), STOPPED_DUE_TO_BREAKPOINT) # Keep stepping until the inferior crashes while process.GetState() == lldb.eStateStopped and not lldbutil.is_thread_crashed(self, thread): diff --git a/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py b/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py index 977254343aa0..1cb97355395f 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CreateAfterAttachTestCase(TestBase): @@ -29,7 +30,6 @@ class CreateAfterAttachTestCase(TestBase): # for FreeBSD. @skipIfRemote @skipIfWindows # Windows doesn't have fork. - @expectedFlakeyLinux("llvm.org/pr16229") # 1/100 dosep, build 3546, clang-3.5 x84_64 @skipIfiOSSimulator def test_create_after_attach_with_fork(self): """Test thread creation after process attach.""" diff --git a/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/TestCreateDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/TestCreateDuringStep.py index 046a86509c0f..9401826e304e 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/TestCreateDuringStep.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/TestCreateDuringStep.py @@ -8,35 +8,36 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CreateDuringStepTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureWindows("llvm.org/pr24668") # Breakpoints not resolved correctly + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") def test_step_inst(self): """Test thread creation during step-inst handling.""" self.build(dictionary=self.getBuildFlags()) self.create_during_step_base("thread step-inst -m all-threads", 'stop reason = instruction step') - @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureWindows("llvm.org/pr24668") # Breakpoints not resolved correctly + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") def test_step_over(self): """Test thread creation during step-over handling.""" self.build(dictionary=self.getBuildFlags()) self.create_during_step_base("thread step-over -m all-threads", 'stop reason = step over') - @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureWindows("llvm.org/pr24668") # Breakpoints not resolved correctly + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") def test_step_in(self): """Test thread creation during step-in handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp index 3a00248c022a..70681fd11603 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/thread/create_during_step/main.cpp @@ -13,19 +13,9 @@ #include #include -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. #define do_nothing() -#define pseudo_barrier_wait(bar) \ - --bar; \ - while (bar > 0) \ - do_nothing(); - -#define pseudo_barrier_init(bar, count) (bar = count) - -std::atomic_int g_barrier; +pseudo_barrier_t g_barrier; volatile int g_thread_created = 0; volatile int g_test = 0; diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py index f999ffe108f3..2c394263d36e 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ExitDuringBreakpointTestCase(TestBase): @@ -21,10 +22,10 @@ class ExitDuringBreakpointTestCase(TestBase): # Find the line number for our breakpoint. self.breakpoint = line_number('main.cpp', '// Set breakpoint here') - @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureWindows("llvm.org/pr24668") # Breakpoints not resolved correctly + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") def test(self): """Test thread exit during breakpoint handling.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp index 3570637207d2..a032da835ea6 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/main.cpp @@ -19,27 +19,15 @@ volatile int g_test = 0; -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. -#define do_nothing() - -#define pseudo_barrier_wait(bar) \ - --bar; \ - while (bar > 0) \ - do_nothing(); - -#define pseudo_barrier_init(bar, count) (bar = count) - // A barrier to synchronize all the threads except the one that will exit. -std::atomic_int g_barrier1; +pseudo_barrier_t g_barrier1; // A barrier to synchronize all the threads including the one that will exit. -std::atomic_int g_barrier2; +pseudo_barrier_t g_barrier2; // A barrier to keep the first group of threads from exiting until after the // breakpoint has been passed. -std::atomic_int g_barrier3; +pseudo_barrier_t g_barrier3; void * break_thread_func () diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py index 67d1c96fd342..af4a022ed0c1 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py @@ -8,42 +8,31 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ExitDuringStepTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureWindows("llvm.org/pr24681") - def test_thread_state_is_stopped(self): - """Test thread exit during step handling.""" - self.build(dictionary=self.getBuildFlags()) - self.exit_during_step_base("thread step-in -m all-threads", 'stop reason = step in', True) - @skipIfFreeBSD # llvm.org/pr21411: test is hanging - @expectedFailureWindows("llvm.org/pr24681") def test(self): """Test thread exit during step handling.""" self.build(dictionary=self.getBuildFlags()) - self.exit_during_step_base("thread step-inst -m all-threads", 'stop reason = instruction step', False) + self.exit_during_step_base("thread step-inst -m all-threads", 'stop reason = instruction step') @skipIfFreeBSD # llvm.org/pr21411: test is hanging - @expectedFailureWindows("llvm.org/pr24681") def test_step_over(self): """Test thread exit during step-over handling.""" self.build(dictionary=self.getBuildFlags()) - self.exit_during_step_base("thread step-over -m all-threads", 'stop reason = step over', False) + self.exit_during_step_base("thread step-over -m all-threads", 'stop reason = step over') @skipIfFreeBSD # llvm.org/pr21411: test is hanging - @expectedFailureWindows("llvm.org/pr24681") def test_step_in(self): """Test thread exit during step-in handling.""" self.build(dictionary=self.getBuildFlags()) - self.exit_during_step_base("thread step-in -m all-threads", 'stop reason = step in', False) + self.exit_during_step_base("thread step-in -m all-threads", 'stop reason = step in') def setUp(self): # Call super's setUp(). @@ -52,7 +41,7 @@ class ExitDuringStepTestCase(TestBase): self.breakpoint = line_number('main.cpp', '// Set breakpoint here') self.continuepoint = line_number('main.cpp', '// Continue from here') - def exit_during_step_base(self, step_cmd, step_stop_reason, test_thread_state): + def exit_during_step_base(self, step_cmd, step_stop_reason): """Test thread exit during step handling.""" exe = os.path.join(os.getcwd(), "a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) @@ -76,37 +65,16 @@ class ExitDuringStepTestCase(TestBase): target = self.dbg.GetSelectedTarget() process = target.GetProcess() - # Get the number of threads num_threads = process.GetNumThreads() - # Make sure we see all three threads - self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match.') - - # Get the thread objects - thread1 = process.GetThreadAtIndex(0) - thread2 = process.GetThreadAtIndex(1) - thread3 = process.GetThreadAtIndex(2) - - # Make sure all threads are stopped - if test_thread_state: - self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint") - self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint") - self.assertTrue(thread3.IsStopped(), "Thread 3 didn't stop during breakpoint") - return - - # Find the thread that is stopped at the breakpoint - stepping_thread = None - for thread in process: - expected_bp_desc = "breakpoint %s." % self.bp_num - stop_desc = thread.GetStopDescription(100) - if stop_desc and (expected_bp_desc in stop_desc): - stepping_thread = thread - break - self.assertTrue(stepping_thread != None, "unable to find thread stopped at %s" % expected_bp_desc) + self.assertGreaterEqual(num_threads, 3, 'Number of expected threads and actual threads do not match.') + + stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(process, self.bp_num) + self.assertIsNotNone(stepping_thread, "Could not find a thread stopped at the breakpoint") current_line = self.breakpoint stepping_frame = stepping_thread.GetFrameAtIndex(0) - self.assertTrue(current_line == stepping_frame.GetLineEntry().GetLine(), "Starting line for stepping doesn't match breakpoint line.") + self.assertEqual(current_line, stepping_frame.GetLineEntry().GetLine(), "Starting line for stepping doesn't match breakpoint line.") # Keep stepping until we've reached our designated continue point while current_line != self.continuepoint: @@ -122,16 +90,16 @@ class ExitDuringStepTestCase(TestBase): current_line = frame.GetLineEntry().GetLine() - self.assertTrue(current_line >= self.breakpoint, "Stepped to unexpected line, " + str(current_line)) - self.assertTrue(current_line <= self.continuepoint, "Stepped to unexpected line, " + str(current_line)) + self.assertGreaterEqual(current_line, self.breakpoint, "Stepped to unexpected line, " + str(current_line)) + self.assertLessEqual(current_line, self.continuepoint, "Stepped to unexpected line, " + str(current_line)) self.runCmd("thread list") # Update the number of threads - num_threads = process.GetNumThreads() + new_num_threads = process.GetNumThreads() # Check to see that we reduced the number of threads as expected - self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match after thread exit.') + self.assertEqual(new_num_threads, num_threads-1, 'Number of threads did not reduce by 1 after thread exit.') self.expect("thread list", 'Process state is stopped due to step', substrs = ['stopped', @@ -141,4 +109,4 @@ class ExitDuringStepTestCase(TestBase): self.runCmd("continue") # At this point, the inferior process should have exited. - self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp index d1b364b8baa2..45adf28ce813 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/main.cpp @@ -12,20 +12,10 @@ #include -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. #define do_nothing() -#define pseudo_barrier_wait(bar) \ - --bar; \ - while (bar > 0) \ - do_nothing(); - -#define pseudo_barrier_init(bar, count) (bar = count) - // A barrier to synchronize thread start. -volatile int g_barrier; +pseudo_barrier_t g_barrier; volatile int g_thread_exited = 0; diff --git a/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py b/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py index 768e2fe4f87a..4c55bcd982a7 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ThreadJumpTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py index 9dd212412216..d4b1eb32a9ae 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class MultipleBreakpointTestCase(TestBase): @@ -21,10 +22,10 @@ class MultipleBreakpointTestCase(TestBase): # Find the line number for our breakpoint. self.breakpoint = line_number('main.cpp', '// Set breakpoint here') - @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureFreeBSD("llvm.org/pr18190") # thread states not properly maintained - @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureWindows("llvm.org/pr24668") # Breakpoints not resolved correctly + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr18190 thread states not properly maintained") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") def test(self): """Test simultaneous breakpoints in multiple threads.""" self.build(dictionary=self.getBuildFlags()) @@ -55,7 +56,7 @@ class MultipleBreakpointTestCase(TestBase): num_threads = process.GetNumThreads() # Make sure we see all three threads - self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match.') + self.assertTrue(num_threads >= 3, 'Number of expected threads and actual threads do not match.') # Get the thread objects thread1 = process.GetThreadAtIndex(0) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp index 01f4b8f98ea7..c3d695dbc745 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/main.cpp @@ -15,19 +15,7 @@ #include #include -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. -#define do_nothing() - -#define pseudo_barrier_wait(bar) \ - --bar; \ - while (bar > 0) \ - do_nothing(); - -#define pseudo_barrier_init(bar, count) (bar = count) - -std::atomic_int g_barrier; +pseudo_barrier_t g_barrier; volatile int g_test = 0; diff --git a/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py b/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py index 4938ec50453e..5afb57bf4ba8 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py @@ -9,25 +9,26 @@ from __future__ import print_function import unittest2 import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ThreadStateTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureDarwin("rdar://15367566") - @expectedFailureFreeBSD('llvm.org/pr15824') - @expectedFailureLinux("llvm.org/pr15824") # thread states not properly maintained + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr15824 thread states not properly maintained") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr18190 thread states not properly maintained") def test_state_after_breakpoint(self): """Test thread state after breakpoint.""" self.build(dictionary=self.getBuildFlags(use_cpp11=False)) self.thread_state_after_breakpoint_test() @skipIfDarwin # 'llvm.org/pr23669', cause Python crash randomly - @expectedFailureDarwin('llvm.org/pr23669') - @expectedFailureFreeBSD('llvm.org/pr15824') - @expectedFailureWindows("llvm.org/pr24660") + @expectedFailureAll(oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr23669") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr15824") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24660") def test_state_after_continue(self): """Test thread state after continue.""" self.build(dictionary=self.getBuildFlags(use_cpp11=False)) @@ -35,7 +36,7 @@ class ThreadStateTestCase(TestBase): @skipIfDarwin # 'llvm.org/pr23669', cause Python crash randomly @expectedFailureDarwin('llvm.org/pr23669') - @expectedFailureWindows("llvm.org/pr24660") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24660") @unittest2.expectedFailure("llvm.org/pr16712") # thread states not properly maintained def test_state_after_expression(self): """Test thread state after expression.""" @@ -43,14 +44,14 @@ class ThreadStateTestCase(TestBase): self.thread_state_after_expression_test() @unittest2.expectedFailure("llvm.org/pr16712") # thread states not properly maintained - @expectedFailureWindows("llvm.org/pr24668") # Breakpoints not resolved correctly + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") def test_process_interrupt(self): """Test process interrupt.""" self.build(dictionary=self.getBuildFlags(use_cpp11=False)) self.process_interrupt_test() @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained - @expectedFailureWindows("llvm.org/pr24668") # Breakpoints not resolved correctly + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly") def test_process_state(self): """Test thread states (comprehensive).""" self.build(dictionary=self.getBuildFlags(use_cpp11=False)) @@ -69,28 +70,17 @@ class ThreadStateTestCase(TestBase): self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) # This should create a breakpoint in the main thread. - lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1) + bp = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1) # Run the program. self.runCmd("run", RUN_SUCCEEDED) - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', - '* thread #1', - 'stop reason = breakpoint']) - # Get the target process target = self.dbg.GetSelectedTarget() process = target.GetProcess() - # Get the number of threads - num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.') - - # Get the thread object - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # Make sure the thread is in the stopped state. self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' during breakpoint 1.") @@ -99,11 +89,11 @@ class ThreadStateTestCase(TestBase): # Kill the process self.runCmd("process kill") - def wait_for_running_event(self): + def wait_for_running_event(self, process): listener = self.dbg.GetListener() if lldb.remote_platform: - lldbutil.expect_state_changes(self, listener, [lldb.eStateConnected]) - lldbutil.expect_state_changes(self, listener, [lldb.eStateRunning]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateConnected]) + lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning]) def thread_state_after_continue_test(self): """Test thread state after continue.""" @@ -117,28 +107,17 @@ class ThreadStateTestCase(TestBase): # Run the program. self.runCmd("run", RUN_SUCCEEDED) - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', - '* thread #1', - 'stop reason = breakpoint']) - # Get the target process target = self.dbg.GetSelectedTarget() process = target.GetProcess() - # Get the number of threads - num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.') - - # Get the thread object - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # Continue, the inferior will go into an infinite loop waiting for 'g_test' to change. self.dbg.SetAsync(True) self.runCmd("continue") - self.wait_for_running_event() + self.wait_for_running_event(process) # Check the thread state. It should be running. self.assertFalse(thread.IsStopped(), "Thread state is \'stopped\' when it should be running.") @@ -162,23 +141,12 @@ class ThreadStateTestCase(TestBase): # Run the program. self.runCmd("run", RUN_SUCCEEDED) - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', - '* thread #1', - 'stop reason = breakpoint']) - # Get the target process target = self.dbg.GetSelectedTarget() process = target.GetProcess() - # Get the number of threads - num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.') - - # Get the thread object - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # Get the inferior out of its loop self.runCmd("expression g_test = 1") @@ -202,25 +170,17 @@ class ThreadStateTestCase(TestBase): # Run the program. self.runCmd("run", RUN_SUCCEEDED) - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', - '* thread #1', - 'stop reason = breakpoint']) - # Get the target process target = self.dbg.GetSelectedTarget() process = target.GetProcess() - # Get the number of threads - num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.') + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # Continue, the inferior will go into an infinite loop waiting for 'g_test' to change. self.dbg.SetAsync(True) self.runCmd("continue") - self.wait_for_running_event() + self.wait_for_running_event(process) # Go back to synchronous interactions self.dbg.SetAsync(False) @@ -228,11 +188,7 @@ class ThreadStateTestCase(TestBase): # Stop the process self.runCmd("process interrupt") - # The stop reason of the thread should be signal. - self.expect("process status", STOPPED_DUE_TO_SIGNAL, - substrs = ['stopped', - '* thread #1', - 'stop reason = signal']) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonSignal) # Get the inferior out of its loop self.runCmd("expression g_test = 1") @@ -252,23 +208,11 @@ class ThreadStateTestCase(TestBase): # Run the program. self.runCmd("run", RUN_SUCCEEDED) - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', - '* thread #1', - 'stop reason = breakpoint']) - # Get the target process target = self.dbg.GetSelectedTarget() process = target.GetProcess() - - # Get the number of threads - num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match.') - - # Get the thread object - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # Make sure the thread is in the stopped state. self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' during breakpoint 1.") @@ -277,7 +221,7 @@ class ThreadStateTestCase(TestBase): # Continue, the inferior will go into an infinite loop waiting for 'g_test' to change. self.dbg.SetAsync(True) self.runCmd("continue") - self.wait_for_running_event() + self.wait_for_running_event(process) # Check the thread state. It should be running. self.assertFalse(thread.IsStopped(), "Thread state is \'stopped\' when it should be running.") @@ -289,11 +233,7 @@ class ThreadStateTestCase(TestBase): # Stop the process self.runCmd("process interrupt") - # The stop reason of the thread should be signal. - self.expect("process status", STOPPED_DUE_TO_SIGNAL, - substrs = ['stopped', - '* thread #1', - 'stop reason = signal']) + self.assertEqual(thread.GetState(), lldb.eStopReasonSignal) # Check the thread state self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' after process stop.") @@ -306,20 +246,12 @@ class ThreadStateTestCase(TestBase): self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' after expression evaluation.") self.assertFalse(thread.IsSuspended(), "Thread state is \'suspended\' after expression evaluation.") - # The stop reason of the thread should be signal. - self.expect("process status", STOPPED_DUE_TO_SIGNAL, - substrs = ['stopped', - '* thread #1', - 'stop reason = signal']) + self.assertEqual(thread.GetState(), lldb.eStopReasonSignal) # Run to breakpoint 2 self.runCmd("continue") - # The stop reason of the thread should be breakpoint. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, - substrs = ['stopped', - '* thread #1', - 'stop reason = breakpoint']) + self.assertEqual(thread.GetState(), lldb.eStopReasonBreakpoint) # Make sure both threads are stopped self.assertTrue(thread.IsStopped(), "Thread state isn't \'stopped\' during breakpoint 2.") @@ -329,4 +261,4 @@ class ThreadStateTestCase(TestBase): self.runCmd("continue") # At this point, the inferior process should have exited. - self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py b/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py index b2d966c4c0f3..735ee80d624e 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py @@ -8,35 +8,36 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ThreadStepOutTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfLinux # Test occasionally times out on the Linux build bot - @expectedFailureLinux("llvm.org/pr23477") # Test occasionally times out on the Linux build bot - @expectedFailureFreeBSD("llvm.org/pr18066") # inferior does not exit - @expectedFailureWindows # Test crashes + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr18066 inferior does not exit") + @expectedFailureAll(oslist=["windows"]) def test_step_single_thread(self): """Test thread step out on one thread via command interpreter. """ self.build(dictionary=self.getBuildFlags()) self.step_out_test(self.step_out_single_thread_with_cmd) @skipIfLinux # Test occasionally times out on the Linux build bot - @expectedFailureLinux("llvm.org/pr23477") # Test occasionally times out on the Linux build bot - @expectedFailureFreeBSD("llvm.org/pr19347") # 2nd thread stops at breakpoint - @expectedFailureWindows # Test crashes + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint") + @expectedFailureAll(oslist=["windows"]) def test_step_all_threads(self): """Test thread step out on all threads via command interpreter. """ self.build(dictionary=self.getBuildFlags()) self.step_out_test(self.step_out_all_threads_with_cmd) @skipIfLinux # Test occasionally times out on the Linux build bot - @expectedFailureLinux("llvm.org/pr23477") # Test occasionally times out on the Linux build bot - @expectedFailureFreeBSD("llvm.org/pr19347") - @expectedFailureWindows("llvm.org/pr24681") + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr23477 Test occasionally times out on the Linux build bot") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24681") def test_python(self): """Test thread step out on one thread via Python API (dwarf).""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp index b4c6216d6bfe..31f9a1576b92 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/thread/step_out/main.cpp @@ -13,19 +13,7 @@ #include #include -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. -#define do_nothing() - -#define pseudo_barrier_wait(bar) \ - --bar; \ - while (bar > 0) \ - do_nothing(); - -#define pseudo_barrier_init(bar, count) (bar = count) - -std::atomic_int g_barrier; +pseudo_barrier_t g_barrier; volatile int g_test = 0; diff --git a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py index f785401277a4..2ba6f2e57f2b 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py @@ -24,7 +24,6 @@ class ThreadExitTestCase(TestBase): self.break_3 = line_number('main.cpp', '// Set third breakpoint here') self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here') - @expectedFailureWindows("llvm.org/pr24681") def test(self): """Test thread exit handling.""" self.build(dictionary=self.getBuildFlags()) @@ -32,10 +31,10 @@ class ThreadExitTestCase(TestBase): self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) # This should create a breakpoint with 1 location. - lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1) - lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_2, num_expected_locations=1) - lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_3, num_expected_locations=1) - lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_4, num_expected_locations=1) + bp1_id = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1) + bp2_id = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_2, num_expected_locations=1) + bp3_id = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_3, num_expected_locations=1) + bp4_id = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_4, num_expected_locations=1) # The breakpoint list should show 1 locations. self.expect("breakpoint list -f", "Breakpoint location shown correctly", @@ -46,71 +45,46 @@ class ThreadExitTestCase(TestBase): # Run the program. self.runCmd("run", RUN_SUCCEEDED) - - # The stop reason of the thread should be breakpoint 1. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 1", - substrs = ['stopped', - '* thread #1', - 'stop reason = breakpoint 1', - 'thread #2']) - # Get the target process target = self.dbg.GetSelectedTarget() process = target.GetProcess() + stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(process, bp1_id) + self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 1") + # Get the number of threads num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match at breakpoint 1.') + self.assertGreaterEqual(num_threads, 2, 'Number of expected threads and actual threads do not match at breakpoint 1.') # Run to the second breakpoint self.runCmd("continue") - - # The stop reason of the thread should be breakpoint 1. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 2", - substrs = ['stopped', - 'thread #1', - 'thread #2', - 'stop reason = breakpoint 2', - 'thread #3']) + stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(process, bp2_id) + self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 2") # Update the number of threads - num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match at breakpoint 2.') + new_num_threads = process.GetNumThreads() + self.assertEqual(new_num_threads, num_threads+1, 'Number of expected threads did not increase by 1 at bp 2.') # Run to the third breakpoint self.runCmd("continue") - - # The stop reason of the thread should be breakpoint 3. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 3", - substrs = ['stopped', - 'thread #1', - 'stop reason = breakpoint 3', - 'thread #3', - ]) + stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(process, bp3_id) + self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 3") # Update the number of threads - num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match at breakpoint 3.') + new_num_threads = process.GetNumThreads() + self.assertEqual(new_num_threads, num_threads, 'Number of expected threads is not equal to original number of threads at bp 3.') # Run to the fourth breakpoint self.runCmd("continue") - - # The stop reason of the thread should be breakpoint 4. - self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 4", - substrs = ['stopped', - 'thread #1', - 'stop reason = breakpoint 4']) + stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id(process, bp4_id) + self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 4") # Update the number of threads - num_threads = process.GetNumThreads() - - self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match at breakpoint 4.') + new_num_threads = process.GetNumThreads() + self.assertEqual(new_num_threads, num_threads-1, 'Number of expected threads did not decrease by 1 at bp 4.') # Run to completion self.runCmd("continue") # At this point, the inferior process should have exited. - self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) + self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) diff --git a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp index e498db7895d2..c57db9f48527 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/main.cpp @@ -12,21 +12,9 @@ #include #include -// Note that although hogging the CPU while waiting for a variable to change -// would be terrible in production code, it's great for testing since it -// avoids a lot of messy context switching to get multiple threads synchronized. -#define do_nothing() - -#define pseudo_barrier_wait(bar) \ - --bar; \ - while (bar > 0) \ - do_nothing(); - -#define pseudo_barrier_init(bar, count) (bar = count) - -std::atomic_int g_barrier1; -std::atomic_int g_barrier2; -std::atomic_int g_barrier3; +pseudo_barrier_t g_barrier1; +pseudo_barrier_t g_barrier2; +pseudo_barrier_t g_barrier3; void * thread1 () diff --git a/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py b/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py index 3c69b6667f7d..12bacabd0d78 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py @@ -9,15 +9,16 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ThreadSpecificBreakTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) - @expectedFailureWindows # Thread specific breakpoints cause the inferior to crash + @expectedFailureAll(oslist=["windows"]) def test_python(self): """Test that we obey thread conditioned breakpoints.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/TestThreadSpecificBpPlusCondition.py b/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/TestThreadSpecificBpPlusCondition.py index 68c96a0fba75..ccb58c965b3f 100644 --- a/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/TestThreadSpecificBpPlusCondition.py +++ b/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break_plus_condition/TestThreadSpecificBpPlusCondition.py @@ -10,17 +10,17 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ThreadSpecificBreakPlusConditionTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfFreeBSD # test frequently times out or hangs - @expectedFailureFreeBSD('llvm.org/pr18522') # hits break in another thread in testrun + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr18522') # hits break in another thread in testrun @add_test_categories(['pyapi']) - @expectedFlakeyLinux # this test fails 6/100 dosep runs def test_python(self): """Test that we obey thread conditioned breakpoints.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/basic/Makefile b/packages/Python/lldbsuite/test/functionalities/tsan/basic/Makefile new file mode 100644 index 000000000000..c930ae563fc1 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/basic/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/basic/TestTsanBasic.py b/packages/Python/lldbsuite/test/functionalities/tsan/basic/TestTsanBasic.py new file mode 100644 index 000000000000..44fa9cedc86c --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/basic/TestTsanBasic.py @@ -0,0 +1,118 @@ +""" +Tests basic ThreadSanitizer support (detecting a data race). +""" + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + +class TsanBasicTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessCompilerRt + @skipUnlessThreadSanitizer + def test (self): + self.build () + self.tsan_tests () + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line_malloc = line_number('main.c', '// malloc line') + self.line_thread1 = line_number('main.c', '// thread1 line') + self.line_thread2 = line_number('main.c', '// thread2 line') + + def tsan_tests (self): + exe = os.path.join (os.getcwd(), "a.out") + self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A data race should be detected", + substrs = ['stopped', 'stop reason = Data race detected']) + + self.assertEqual(self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(), lldb.eStopReasonInstrumentation) + + # test that the TSan dylib is present + self.expect("image lookup -n __tsan_get_current_report", "__tsan_get_current_report should be present", + substrs = ['1 match found']) + + # We should be stopped in __tsan_on_report + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + self.assertTrue("__tsan_on_report" in frame.GetFunctionName()) + + # The stopped thread backtrace should contain either line1 or line2 from main.c. + found = False + for i in range(0, thread.GetNumFrames()): + frame = thread.GetFrameAtIndex(i) + if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c": + if frame.GetLineEntry().GetLine() == self.line_thread1: + found = True + if frame.GetLineEntry().GetLine() == self.line_thread2: + found = True + self.assertTrue(found) + + self.expect("thread info -s", "The extended stop info should contain the TSan provided fields", + substrs = ["instrumentation_class", "description", "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + self.assertEqual(data["issue_type"], "data-race") + self.assertEqual(len(data["mops"]), 2) + + backtraces = thread.GetStopReasonExtendedBacktraces(lldb.eInstrumentationRuntimeTypeAddressSanitizer) + self.assertEqual(backtraces.GetSize(), 0) + + backtraces = thread.GetStopReasonExtendedBacktraces(lldb.eInstrumentationRuntimeTypeThreadSanitizer) + self.assertTrue(backtraces.GetSize() >= 2) + + # First backtrace is a memory operation + thread = backtraces.GetThreadAtIndex(0) + found = False + for i in range(0, thread.GetNumFrames()): + frame = thread.GetFrameAtIndex(i) + if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c": + if frame.GetLineEntry().GetLine() == self.line_thread1: + found = True + if frame.GetLineEntry().GetLine() == self.line_thread2: + found = True + self.assertTrue(found) + + # Second backtrace is a memory operation + thread = backtraces.GetThreadAtIndex(1) + found = False + for i in range(0, thread.GetNumFrames()): + frame = thread.GetFrameAtIndex(i) + if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c": + if frame.GetLineEntry().GetLine() == self.line_thread1: + found = True + if frame.GetLineEntry().GetLine() == self.line_thread2: + found = True + self.assertTrue(found) + + self.runCmd("continue") + + # the stop reason of the thread should be a SIGABRT. + self.expect("thread list", "We should be stopped due a SIGABRT", + substrs = ['stopped', 'stop reason = signal SIGABRT']) + + # test that we're in pthread_kill now (TSan abort the process) + self.expect("thread list", "We should be stopped in pthread_kill", + substrs = ['pthread_kill']) diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/basic/main.c b/packages/Python/lldbsuite/test/functionalities/tsan/basic/main.c new file mode 100644 index 000000000000..c082b01a57c7 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/basic/main.c @@ -0,0 +1,37 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include +#include +#include + +char *pointer; + +void *f1(void *p) { + pointer[0] = 'x'; // thread1 line + return NULL; +} + +void *f2(void *p) { + pointer[0] = 'y'; // thread2 line + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pointer = (char *)malloc(10); // malloc line + + pthread_t t1, t2; + pthread_create(&t1, NULL, f1, NULL); + pthread_create(&t2, NULL, f2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/Makefile b/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/Makefile new file mode 100644 index 000000000000..a58194779074 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CFLAGS_EXTRAS := -fsanitize=thread -g + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/TestTsanCPPGlobalLocation.py b/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/TestTsanCPPGlobalLocation.py new file mode 100644 index 000000000000..230ff982da0d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/TestTsanCPPGlobalLocation.py @@ -0,0 +1,54 @@ +""" +Tests that TSan correctly reports the filename and line number of a racy global C++ variable. +""" + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + +class TsanCPPGlobalLocationTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessCompilerRt + @skipUnlessThreadSanitizer + def test (self): + self.build () + self.tsan_tests () + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def tsan_tests (self): + exe = os.path.join (os.getcwd(), "a.out") + self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A data race should be detected", + substrs = ['stopped', 'stop reason = Data race detected']) + + self.expect("thread info -s", "The extended stop info should contain the TSan provided fields", + substrs = ["instrumentation_class", "description", "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + self.assertEqual(data["issue_type"], "data-race") + + self.assertTrue(data["location_filename"].endswith("/main.cpp")) + self.assertEqual(data["location_line"], line_number('main.cpp', '// global variable')) diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/main.cpp b/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/main.cpp new file mode 100644 index 000000000000..80f72ae83cf7 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/cpp_global_location/main.cpp @@ -0,0 +1,38 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include +#include +#include +#include + +long my_global_variable; // global variable + +void *f1(void *p) { + my_global_variable = 42; + return NULL; +} + +void *f2(void *p) { + my_global_variable = 43; + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/global_location/Makefile b/packages/Python/lldbsuite/test/functionalities/tsan/global_location/Makefile new file mode 100644 index 000000000000..c930ae563fc1 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/global_location/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/global_location/TestTsanGlobalLocation.py b/packages/Python/lldbsuite/test/functionalities/tsan/global_location/TestTsanGlobalLocation.py new file mode 100644 index 000000000000..b268c46fead3 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/global_location/TestTsanGlobalLocation.py @@ -0,0 +1,54 @@ +""" +Tests that TSan correctly reports the filename and line number of a racy global variable. +""" + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + +class TsanGlobalLocationTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessCompilerRt + @skipUnlessThreadSanitizer + def test (self): + self.build () + self.tsan_tests () + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def tsan_tests (self): + exe = os.path.join (os.getcwd(), "a.out") + self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A data race should be detected", + substrs = ['stopped', 'stop reason = Data race detected']) + + self.expect("thread info -s", "The extended stop info should contain the TSan provided fields", + substrs = ["instrumentation_class", "description", "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + self.assertEqual(data["issue_type"], "data-race") + + self.assertTrue(data["location_filename"].endswith("/main.c")) + self.assertEqual(data["location_line"], line_number('main.c', '// global variable')) diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/global_location/main.c b/packages/Python/lldbsuite/test/functionalities/tsan/global_location/main.c new file mode 100644 index 000000000000..caa2c3cb43cd --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/global_location/main.c @@ -0,0 +1,38 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include +#include +#include +#include + +long my_global_variable; // global variable + +void *f1(void *p) { + my_global_variable = 42; + return NULL; +} + +void *f2(void *p) { + my_global_variable = 43; + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/multiple/Makefile b/packages/Python/lldbsuite/test/functionalities/tsan/multiple/Makefile new file mode 100644 index 000000000000..c930ae563fc1 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/multiple/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/multiple/TestTsanMultiple.py b/packages/Python/lldbsuite/test/functionalities/tsan/multiple/TestTsanMultiple.py new file mode 100644 index 000000000000..c22501141cca --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/multiple/TestTsanMultiple.py @@ -0,0 +1,69 @@ +""" +Test ThreadSanitizer when multiple different issues are found. +""" + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + +class TsanMultipleTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessCompilerRt + @skipUnlessThreadSanitizer + def test (self): + self.build () + self.tsan_tests () + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def tsan_tests (self): + exe = os.path.join (os.getcwd(), "a.out") + self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ]) + + self.runCmd("env TSAN_OPTIONS=abort_on_error=0") + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable interceptors. + self.runCmd("continue") + + report_count = 0 + while self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() == lldb.eStopReasonInstrumentation: + report_count += 1 + + stop_description = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopDescription(100) + + self.assertTrue( + (stop_description == "Data race detected") or + (stop_description == "Use of deallocated memory detected") or + (stop_description == "Thread leak detected") or + (stop_description == "Use of an uninitialized or destroyed mutex detected") or + (stop_description == "Unlock of an unlocked mutex (or by a wrong thread) detected") + ) + + self.expect("thread info -s", "The extended stop info should contain the TSan provided fields", + substrs = ["instrumentation_class", "description", "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + + backtraces = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReasonExtendedBacktraces(lldb.eInstrumentationRuntimeTypeThreadSanitizer) + self.assertTrue(backtraces.GetSize() >= 1) + + self.runCmd("continue") + + self.assertEqual(self.dbg.GetSelectedTarget().process.GetState(), lldb.eStateExited, PROCESS_EXITED) diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/multiple/main.m b/packages/Python/lldbsuite/test/functionalities/tsan/multiple/main.m new file mode 100644 index 000000000000..f7c48b45422b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/multiple/main.m @@ -0,0 +1,138 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import +#import + +long my_global; + +void *Thread1(void *arg) { + my_global = 42; + return NULL; +} + +void *Thread2(void *arg) { + my_global = 144; + return NULL; +} + +void TestDataRace1() { + pthread_t t1, t2; + pthread_create(&t1, NULL, Thread1, NULL); + pthread_create(&t2, NULL, Thread2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); +} + +void TestInvalidMutex() { + pthread_mutex_t m = {0}; + pthread_mutex_lock(&m); + + pthread_mutex_init(&m, NULL); + pthread_mutex_lock(&m); + pthread_mutex_unlock(&m); + pthread_mutex_destroy(&m); + pthread_mutex_lock(&m); +} + +void TestMutexWrongLock() { + pthread_mutex_t m = {0}; + pthread_mutex_init(&m, NULL); + pthread_mutex_unlock(&m); +} + +long some_global; + +void TestDataRaceBlocks1() { + dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT); + + for (int i = 0; i < 2; i++) { + dispatch_async(q, ^{ + some_global++; // race 1 + + usleep(100000); // force the blocks to be on different threads + }); + } + + usleep(100000); + dispatch_barrier_sync(q, ^{ }); +} + +void TestDataRaceBlocks2() { + dispatch_queue_t q = dispatch_queue_create("my.queue2", DISPATCH_QUEUE_CONCURRENT); + + char *c; + + c = malloc((rand() % 1000) + 10); + for (int i = 0; i < 2; i++) { + dispatch_async(q, ^{ + c[0] = 'x'; // race 2 + fprintf(stderr, "tid: %p\n", pthread_self()); + usleep(100000); // force the blocks to be on different threads + }); + } + dispatch_barrier_sync(q, ^{ }); + + free(c); +} + +void TestUseAfterFree() { + char *c; + + c = malloc((rand() % 1000) + 10); + free(c); + c[0] = 'x'; +} + +void TestRacePipe() { + dispatch_queue_t q = dispatch_queue_create("my.queue3", DISPATCH_QUEUE_CONCURRENT); + + int a[2]; + pipe(a); + int fd = a[0]; + + for (int i = 0; i < 2; i++) { + dispatch_async(q, ^{ + write(fd, "abc", 3); + usleep(100000); // force the blocks to be on different threads + }); + dispatch_async(q, ^{ + close(fd); + usleep(100000); + }); + } + + dispatch_barrier_sync(q, ^{ }); +} + +void TestThreadLeak() { + pthread_t t1; + pthread_create(&t1, NULL, Thread1, NULL); +} + +int main(int argc, const char * argv[]) { + TestDataRace1(); + + TestInvalidMutex(); + + TestMutexWrongLock(); + + TestDataRaceBlocks1(); + + TestDataRaceBlocks2(); + + TestUseAfterFree(); + + TestRacePipe(); + + TestThreadLeak(); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/Makefile b/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/Makefile new file mode 100644 index 000000000000..c930ae563fc1 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/TestTsanThreadLeak.py b/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/TestTsanThreadLeak.py new file mode 100644 index 000000000000..ed620093c1f3 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/TestTsanThreadLeak.py @@ -0,0 +1,40 @@ +""" +Tests ThreadSanitizer's support to detect a leaked thread. +""" + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + +class TsanThreadLeakTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessCompilerRt + @skipUnlessThreadSanitizer + def test (self): + self.build () + self.tsan_tests () + + def tsan_tests (self): + exe = os.path.join (os.getcwd(), "a.out") + self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A thread leak should be detected", + substrs = ['stopped', 'stop reason = Thread leak detected']) + + self.assertEqual(self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(), lldb.eStopReasonInstrumentation) diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/main.c b/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/main.c new file mode 100644 index 000000000000..3c17e228487b --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/thread_leak/main.c @@ -0,0 +1,24 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include +#include +#include + +void *f1(void *p) { + printf("hello\n"); + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/Makefile b/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/Makefile new file mode 100644 index 000000000000..c930ae563fc1 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=thread -g + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/TestTsanThreadNumbers.py b/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/TestTsanThreadNumbers.py new file mode 100644 index 000000000000..c7905bcb1c1d --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/TestTsanThreadNumbers.py @@ -0,0 +1,68 @@ +""" +Tests that TSan and LLDB have correct thread numbers. +""" + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + +class TsanThreadNumbersTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["linux"], bugnumber="non-core functionality, need to reenable and fix later (DES 2014.11.07)") + @skipIfFreeBSD # llvm.org/pr21136 runtimes not yet available by default + @skipIfRemote + @skipUnlessCompilerRt + @skipUnlessThreadSanitizer + def test (self): + self.build () + self.tsan_tests () + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def tsan_tests (self): + exe = os.path.join (os.getcwd(), "a.out") + self.expect("file " + exe, patterns = [ "Current executable set to .*a.out" ]) + + self.runCmd("run") + + stop_reason = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason() + if stop_reason == lldb.eStopReasonExec: + # On OS X 10.10 and older, we need to re-exec to enable interceptors. + self.runCmd("continue") + + # the stop reason of the thread should be breakpoint. + self.expect("thread list", "A data race should be detected", + substrs = ['stopped', 'stop reason = Data race detected']) + + self.assertEqual(self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(), lldb.eStopReasonInstrumentation) + + report_thread_id = self.dbg.GetSelectedTarget().process.GetSelectedThread().GetIndexID() + + self.expect("thread info -s", "The extended stop info should contain the TSan provided fields", + substrs = ["instrumentation_class", "description", "mops"]) + + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "ThreadSanitizer") + self.assertEqual(data["issue_type"], "data-race") + self.assertEqual(len(data["mops"]), 2) + + self.assertEqual(data["mops"][0]["thread_id"], report_thread_id) + + other_thread_id = data["mops"][1]["thread_id"] + self.assertTrue(other_thread_id != report_thread_id) + other_thread = self.dbg.GetSelectedTarget().process.GetThreadByIndexID(other_thread_id) + self.assertTrue(other_thread.IsValid()) + + self.runCmd("thread select %d" % other_thread_id) + + self.expect("thread backtrace", "The other thread should be stopped in f1 or f2", + substrs = ["a.out", "main.c"]) diff --git a/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/main.c b/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/main.c new file mode 100644 index 000000000000..04ebb723c3b7 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/tsan/thread_numbers/main.c @@ -0,0 +1,58 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include +#include +#include +#include + +char *pointer; + +void *nothing(void *p) { + return NULL; +} + +void *f1(void *p) { + pointer[0] = 'x'; + sleep(100); + return NULL; +} + +void *f2(void *p) { + pointer[0] = 'y'; + sleep(100); + return NULL; +} + +int main (int argc, char const *argv[]) +{ + pointer = (char *)malloc(10); + + for (int i = 0; i < 3; i++) { + pthread_t t; + pthread_create(&t, NULL, nothing, NULL); + pthread_join(t, NULL); + } + + pthread_t t1; + pthread_create(&t1, NULL, f1, NULL); + + for (int i = 0; i < 3; i++) { + pthread_t t; + pthread_create(&t, NULL, nothing, NULL); + pthread_join(t, NULL); + } + + pthread_t t2; + pthread_create(&t2, NULL, f2, NULL); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/functionalities/tty/TestTerminal.py b/packages/Python/lldbsuite/test/functionalities/tty/TestTerminal.py index 5697c2c37283..cebba1b4c573 100644 --- a/packages/Python/lldbsuite/test/functionalities/tty/TestTerminal.py +++ b/packages/Python/lldbsuite/test/functionalities/tty/TestTerminal.py @@ -9,8 +9,9 @@ from __future__ import print_function import unittest2 import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class LaunchInTerminalTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/functionalities/type_completion/TestTypeCompletion.py b/packages/Python/lldbsuite/test/functionalities/type_completion/TestTypeCompletion.py index 5a238b7d3542..2bf10204ea6b 100644 --- a/packages/Python/lldbsuite/test/functionalities/type_completion/TestTypeCompletion.py +++ b/packages/Python/lldbsuite/test/functionalities/type_completion/TestTypeCompletion.py @@ -8,14 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TypeCompletionTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureIcc # often fails with 'NameAndAddress should be valid' + @expectedFailureAll(compiler="icc", bugnumber="often fails with 'NameAndAddress should be valid.") # Fails with gcc 4.8.1 with llvm.org/pr15301 LLDB prints incorrect sizes of STL containers def test_with_run_command(self): """Check that types only get completed when necessary.""" diff --git a/packages/Python/lldbsuite/test/functionalities/type_lookup/TestTypeLookup.py b/packages/Python/lldbsuite/test/functionalities/type_lookup/TestTypeLookup.py index ca0b1f1d1e53..774eb437b78e 100644 --- a/packages/Python/lldbsuite/test/functionalities/type_lookup/TestTypeLookup.py +++ b/packages/Python/lldbsuite/test/functionalities/type_lookup/TestTypeLookup.py @@ -6,11 +6,12 @@ from __future__ import print_function +import datetime import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import datetime -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TypeLookupTestCase(TestBase): @@ -41,3 +42,4 @@ class TypeLookupTestCase(TestBase): self.expect('type lookup NSURL', substrs=['NSURL']) self.expect('type lookup NSArray', substrs=['NSArray']) self.expect('type lookup NSObject', substrs=['NSObject', 'isa']) + self.expect('type lookup PleaseDontBeARealTypeThatExists', substrs=["no type was found matching 'PleaseDontBeARealTypeThatExists'"]) diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/Makefile b/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/Makefile new file mode 100644 index 000000000000..289d25698ffb --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +CFLAGS ?= -g -fomit-frame-pointer + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/TestEhFrameUnwind.py b/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/TestEhFrameUnwind.py new file mode 100644 index 000000000000..e17d5d36d394 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/TestEhFrameUnwind.py @@ -0,0 +1,51 @@ +""" +Test that we can backtrace correctly from Non ABI functions on the stack +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class EHFrameBasedUnwind(TestBase): + mydir = TestBase.compute_mydir(__file__) + + + @skipUnlessPlatform(['linux']) + @skipIf(archs=["aarch64", "arm", "i386", "i686"]) + def test (self): + """Test that we can backtrace correctly from Non ABI functions on the stack""" + self.build() + self.setTearDownCleanup() + + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + + self.assertTrue(target, VALID_TARGET) + + lldbutil.run_break_set_by_symbol (self, "func") + + process = target.LaunchSimple (["abc", "xyz"], None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.Launch() failed") + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) + self.expect(stacktraces, exe=False, + substrs = ['(int)argc=3']) + + self.runCmd("thread step-inst") + + stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) + self.expect(stacktraces, exe=False, + substrs = ['(int)argc=3']) diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/main.c b/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/main.c new file mode 100644 index 000000000000..f62f7d814f38 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/unwind/ehframe/main.c @@ -0,0 +1,20 @@ +void func() { + __asm__ ( + "pushq $0x10;" + ".cfi_def_cfa_offset 16;" + "jmp label;" + "movq $0x48, %rax;" +"label: subq $0x38, %rax;" + "movq $0x48, %rcx;" + "movq $0x48, %rdx;" + "movq $0x48, %rax;" + "popq %rax;" + ); + +} + + +int main(int argc, char const *argv[]) +{ + func(); +} \ No newline at end of file diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py index c0a311f7ac9e..62c6c16080a3 100644 --- a/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py +++ b/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py @@ -8,13 +8,13 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class NoreturnUnwind(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailurei386("llvm.org/pr25338") @skipIfWindows # clang-cl does not support gcc style attributes. def test (self): """Test that we can backtrace correctly with 'noreturn' functions on the stack""" diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py b/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py index ddfb1122b6f1..d2b36412f1f0 100644 --- a/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py +++ b/packages/Python/lldbsuite/test/functionalities/unwind/sigtramp/TestSigtrampUnwind.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SigtrampUnwind(TestBase): mydir = TestBase.compute_mydir(__file__) diff --git a/packages/Python/lldbsuite/test/functionalities/unwind/standard/TestStandardUnwind.py b/packages/Python/lldbsuite/test/functionalities/unwind/standard/TestStandardUnwind.py index 3f88e7b6e1aa..20532c6fc675 100644 --- a/packages/Python/lldbsuite/test/functionalities/unwind/standard/TestStandardUnwind.py +++ b/packages/Python/lldbsuite/test/functionalities/unwind/standard/TestStandardUnwind.py @@ -17,8 +17,9 @@ from __future__ import print_function import unittest2 import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil test_source_dirs = ["."] diff --git a/packages/Python/lldbsuite/test/functionalities/value_md5_crash/TestValueMD5Crash.py b/packages/Python/lldbsuite/test/functionalities/value_md5_crash/TestValueMD5Crash.py index 763ecc94c2eb..cbea7d22cc44 100644 --- a/packages/Python/lldbsuite/test/functionalities/value_md5_crash/TestValueMD5Crash.py +++ b/packages/Python/lldbsuite/test/functionalities/value_md5_crash/TestValueMD5Crash.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ValueMD5CrashTestCase(TestBase): @@ -21,7 +22,7 @@ class ValueMD5CrashTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// break here') - @expectedFailureWindows("llvm.org/pr24663") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24663") def test_with_run_command(self): """Verify that the hash computing logic for ValueObject's values can't crash us.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py index f0a0b5ab99d0..933f21a90bbf 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class HelloWatchLocationTestCase(TestBase): @@ -30,8 +31,11 @@ class HelloWatchLocationTestCase(TestBase): self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows - @expectedFailureAll(archs=['mips', 'mipsel', 'mips64', 'mips64el']) # Most of the MIPS boards provide only one H/W watchpoints, and S/W watchpoints are not supported yet + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(triple = re.compile('^mips')) # Most of the MIPS boards provide only one H/W watchpoints, and S/W watchpoints are not supported yet + @expectedFailureAll(archs=['s390x']) # SystemZ also currently supports only one H/W watchpoint + @expectedFailureAll(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr27795") + @skipIfDarwin def test_hello_watchlocation(self): """Test watching a location with '-s size' option.""" self.build(dictionary=self.d) @@ -52,9 +56,6 @@ class HelloWatchLocationTestCase(TestBase): 'stop reason = breakpoint']) # Now let's set a write-type watchpoint pointed to by 'g_char_ptr'. - # The main.cpp, by design, misbehaves by not following the agreed upon - # protocol of using a mutex while accessing the global pool and by not - # incrmenting the global pool by 2. self.expect("watchpoint set expression -w write -s 1 -- g_char_ptr", WATCHPOINT_CREATED, substrs = ['Watchpoint created', 'size = 1', 'type = w']) # Get a hold of the watchpoint id just created, it is used later on to diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/main.cpp b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/main.cpp index 59b0afc6d5f7..e20a6d988c84 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/main.cpp @@ -43,15 +43,13 @@ uint32_t access_pool (bool flag = false) { static std::mutex g_access_mutex; - if (!flag) - g_access_mutex.lock(); + g_access_mutex.lock(); char old_val = *g_char_ptr; if (flag) do_bad_thing_with_location(g_char_ptr, old_val + 1); - if (!flag) - g_access_mutex.unlock(); + g_access_mutex.unlock(); return *g_char_ptr; } diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py index 57467c38d5f8..5214c7f5e089 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class HelloWatchpointTestCase(TestBase): @@ -31,7 +32,7 @@ class HelloWatchpointTestCase(TestBase): self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_hello_watchpoint_using_watchpoint_set(self): """Test a simple sequence of watchpoint creation and watchpoint hit.""" self.build(dictionary=self.d) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py index 2318214a0d5c..af8306c9a20e 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py @@ -9,15 +9,16 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class WatchpointForMultipleThreadsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watchpoint_multiple_threads(self): """Test that lldb watchpoint works for multiple threads.""" self.build() @@ -25,7 +26,7 @@ class WatchpointForMultipleThreadsTestCase(TestBase): self.hello_multiple_threads() @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watchpoint_multiple_threads_wp_set_and_then_delete(self): """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" self.build() @@ -57,9 +58,6 @@ class WatchpointForMultipleThreadsTestCase(TestBase): 'stop reason = breakpoint']) # Now let's set a write-type watchpoint for variable 'g_val'. - # The main.cpp, by design, misbehaves by not following the agreed upon - # protocol of using a mutex while accessing the global pool and by not - # writing to the variable. self.expect("watchpoint set variable -w write g_val", WATCHPOINT_CREATED, substrs = ['Watchpoint created', 'size = 4', 'type = w']) @@ -101,9 +99,6 @@ class WatchpointForMultipleThreadsTestCase(TestBase): 'stop reason = breakpoint']) # Now let's set a write-type watchpoint for variable 'g_val'. - # The main.cpp, by design, misbehaves by not following the agreed upon - # protocol of using a mutex while accessing the global pool and by not - # writing to the variable. self.expect("watchpoint set variable -w write g_val", WATCHPOINT_CREATED, substrs = ['Watchpoint created', 'size = 4', 'type = w']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp index 8a31041f8fca..7f2e5e6e6cb5 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_threads/main.cpp @@ -23,8 +23,7 @@ uint32_t access_pool (bool flag = false) { static std::mutex g_access_mutex; - if (!flag) - g_access_mutex.lock(); + g_access_mutex.lock(); uint32_t old_val = g_val; if (flag) @@ -33,17 +32,14 @@ access_pool (bool flag = false) g_val = old_val + 1; } - if (!flag) - g_access_mutex.unlock(); + g_access_mutex.unlock(); return g_val; } void thread_func (uint32_t thread_index) { - // Break here in order to allow the thread - // to inherit the global watchpoint state. - printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); + printf ("%s (thread index = %u) starting...\n", __FUNCTION__, thread_index); uint32_t count = 0; uint32_t val; diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py index f51da36b72d7..22011f11352c 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py @@ -5,8 +5,9 @@ from __future__ import print_function import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestStepOverWatchpoint(TestBase): @@ -17,8 +18,9 @@ class TestStepOverWatchpoint(TestBase): return ['basic_process'] @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureLinux(bugnumber="llvm.org/pr26031", archs=['arm']) - @expectedFailureWindows("llvm.org/pr24446") + @expectedFailureAll(oslist=["linux"], archs=['aarch64', 'arm'], bugnumber="llvm.org/pr26031") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ def test(self): """Test stepping over watchpoints.""" self.build() @@ -73,7 +75,7 @@ class TestStepOverWatchpoint(TestBase): # Most of the MIPS boards provide only one H/W watchpoints, and S/W watchpoints are not supported yet arch = self.getArchitecture() - if arch in ['mips', 'mipsel', 'mips64', 'mips64el']: + if re.match("^mips",arch): self.runCmd("watchpoint delete 1") # resolve_location=True, read=False, write=True diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py index 339de45a085a..4ce05af96e2e 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class WatchpointCommandsTestCase(TestBase): @@ -30,7 +31,8 @@ class WatchpointCommandsTestCase(TestBase): self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ def test_rw_watchpoint(self): """Test read_write watchpoint and expect to stop two times.""" self.build(dictionary=self.d) @@ -90,7 +92,8 @@ class WatchpointCommandsTestCase(TestBase): substrs = ['hit_count = 2']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ def test_rw_watchpoint_delete(self): """Test delete watchpoint and expect not to stop for watchpoint.""" self.build(dictionary=self.d) @@ -135,7 +138,8 @@ class WatchpointCommandsTestCase(TestBase): substrs = ['exited']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ def test_rw_watchpoint_set_ignore_count(self): """Test watchpoint ignore count and expect to not to stop at all.""" self.build(dictionary=self.d) @@ -184,7 +188,8 @@ class WatchpointCommandsTestCase(TestBase): substrs = ['hit_count = 2', 'ignore_count = 2']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ def test_rw_disable_after_first_stop(self): """Test read_write watchpoint but disable it after the first stop.""" self.build(dictionary=self.d) @@ -243,7 +248,8 @@ class WatchpointCommandsTestCase(TestBase): substrs = ['hit_count = 1']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ def test_rw_disable_then_enable(self): """Test read_write watchpoint, disable initially, then enable it.""" self.build(dictionary=self.d) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py index f2bf90866330..ee276dd5687f 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandLLDB.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class WatchpointLLDBCommandTestCase(TestBase): @@ -29,7 +30,8 @@ class WatchpointLLDBCommandTestCase(TestBase): self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["linux"], archs=["aarch64"], bugnumber="llvm.org/pr27710") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watchpoint_command(self): """Test 'watchpoint command'.""" self.build(dictionary=self.d) @@ -83,7 +85,8 @@ class WatchpointLLDBCommandTestCase(TestBase): substrs = ['(int32_t)', 'cookie = 777']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["linux"], archs=["aarch64"], bugnumber="llvm.org/pr27710") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watchpoint_command_can_disable_a_watchpoint(self): """Test that 'watchpoint command' action can disable a watchpoint after it is triggered.""" self.build(dictionary=self.d) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py index a476aebb8db9..f6ea4fc16861 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class WatchpointPythonCommandTestCase(TestBase): @@ -29,8 +30,9 @@ class WatchpointPythonCommandTestCase(TestBase): self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} @skipIfFreeBSD # timing out on buildbot - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureAll(oslist=["linux"], archs=["aarch64"], bugnumber="llvm.org/pr27710") def test_watchpoint_command(self): """Test 'watchpoint command'.""" self.build(dictionary=self.d) @@ -85,3 +87,57 @@ class WatchpointPythonCommandTestCase(TestBase): # The watchpoint command "forced" our global variable 'cookie' to become 777. self.expect("frame variable --show-globals cookie", substrs = ['(int32_t)', 'cookie = 777']) + + @skipIfFreeBSD # timing out on buildbot + @expectedFailureAll(bugnumber="llvm.org/pr28055: continue in watchpoint commands disables the watchpoint") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureAll(oslist=["linux"], archs=["aarch64"], bugnumber="llvm.org/pr27710") + def test_continue_in_watchpoint_command(self): + """Test continue in a watchpoint command.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Add a breakpoint to set a watchpoint when stopped on the breakpoint. + lldbutil.run_break_set_by_file_and_line (self, None, self.line, num_expected_locations=1) +# self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED, +# startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" % +# (self.source, self.line))# + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # We should be stopped again due to the breakpoint. + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # Now let's set a write-type watchpoint for 'global'. + self.expect("watchpoint set variable -w write global", WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = 4', 'type = w', + '%s:%d' % (self.source, self.decl)]) + + cmd_script_file = os.path.join(os.getcwd(), "watchpoint_command.py") + self.runCmd("command script import '%s'"%(cmd_script_file)) + + self.runCmd('watchpoint command add -F watchpoint_command.watchpoint_command') + + # List the watchpoint command we just added. + self.expect("watchpoint command list 1", + substrs = ['watchpoint_command.watchpoint_command']) + + self.runCmd("process continue") + + # We should be stopped again due to the watchpoint (write type). + # The stop reason of the thread should be watchpoint. + self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stop reason = watchpoint']) + + # We should have hit the watchpoint once, set cookie to 888, then continued to the + # second hit and set it to 999 + self.expect("frame variable --show-globals cookie", + substrs = ['(int32_t)', 'cookie = 999']) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/watchpoint_command.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/watchpoint_command.py new file mode 100644 index 000000000000..575a5160d219 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/watchpoint_command.py @@ -0,0 +1,14 @@ +import lldb + +num_hits = 0 +def watchpoint_command (frame, wp, dict): + global num_hits + if num_hits == 0: + print ("I stopped the first time") + frame.EvaluateExpression("cookie = 888") + num_hits += 1 + frame.thread.process.Continue() + else: + print ("I stopped the %d time"%(num_hits)) + frame.EvaluateExpression("cookie = 999") + diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/TestWatchpointConditionCmd.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/TestWatchpointConditionCmd.py index 355204a4ce1e..64e01e5cb937 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/TestWatchpointConditionCmd.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/condition/TestWatchpointConditionCmd.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class WatchpointConditionCmdTestCase(TestBase): @@ -29,7 +30,8 @@ class WatchpointConditionCmdTestCase(TestBase): self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["linux"], archs=["aarch64"], bugnumber="llvm.org/pr27710") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watchpoint_cond(self): """Test watchpoint condition.""" self.build(dictionary=self.d) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py index e4d6e019c20e..fdeb4b8fa3b5 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestWatchpointEvents (TestBase): @@ -21,7 +22,8 @@ class TestWatchpointEvents (TestBase): @add_test_categories(['pyapi']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["linux"], archs=["aarch64"], bugnumber="llvm.org/pr27710") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_with_python_api(self): """Test that adding, deleting and modifying watchpoints sends the appropriate events.""" self.build() @@ -58,7 +60,7 @@ class TestWatchpointEvents (TestBase): self.listener.StartListeningForEvents (self.target_bcast, lldb.SBTarget.eBroadcastBitWatchpointChanged) error = lldb.SBError() - local_watch = local_var.Watch(True, True, True, error) + local_watch = local_var.Watch(True, False, True, error) if not error.Success(): self.fail ("Failed to make watchpoint for local_var: %s"%(error.GetCString())) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/TestValueOfVectorVariable.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/TestValueOfVectorVariable.py index 73752d2d18d5..c66ddb512884 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/TestValueOfVectorVariable.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/TestValueOfVectorVariable.py @@ -8,15 +8,16 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestValueOfVectorVariableTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_value_of_vector_variable_using_watchpoint_set(self): """Test verify displayed value of vector variable.""" self.build(dictionary=self.d) diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/main.c b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/main.c index 98f8c477eb31..ac2370e32d2a 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/main.c +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_on_vectors/main.c @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -typedef char v4i8 __attribute__ ((vector_size(4))); +typedef signed char v4i8 __attribute__ ((vector_size(4))); v4i8 global_vector = {1, 2, 3, 4}; int diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py index 9301a6f9fd00..735a5678c4f9 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class WatchLocationUsingWatchpointSetTestCase(TestBase): @@ -27,8 +28,8 @@ class WatchLocationUsingWatchpointSetTestCase(TestBase): # Build dictionary to have unique executable names for each test method. @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureLinux(bugnumber="llvm.org/pr26031", archs=['arm']) - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["linux"], archs=['aarch64', 'arm'], bugnumber="llvm.org/pr26031") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watchlocation_using_watchpoint_set(self): """Test watching a location with 'watchpoint set expression -w write -s size' option.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchpointSetErrorCases.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchpointSetErrorCases.py index 27c759e6fb64..43597ec28f59 100644 --- a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchpointSetErrorCases.py +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_set_command/TestWatchpointSetErrorCases.py @@ -8,6 +8,7 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * import lldbsuite.test.lldbutil as lldbutil @@ -24,6 +25,7 @@ class WatchpointSetErrorTestCase(TestBase): self.line = line_number(self.source, '// Set break point at this line.') # Build dictionary to have unique executable names for each test method. + @expectedFailureAll(oslist=["windows"]) def test_error_cases_with_watchpoint_set(self): """Test error cases with the 'watchpoint set' command.""" self.build() diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py new file mode 100644 index 000000000000..55e36649ce10 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/TestWatchpointSizes.py @@ -0,0 +1,117 @@ +""" +Test watchpoint size cases (1-byte, 2-byte, 4-byte). +Make sure we can watch all bytes, words or double words individually +when they are packed in a 8-byte region. + +""" + +from __future__ import print_function + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class WatchpointSizeTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + # Source filename. + self.source = 'main.c' + + # Output filename. + self.exe_name = 'a.out' + self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name} + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ + def test_byte_size_watchpoints_with_byte_selection(self): + """Test to selectively watch different bytes in a 8-byte array.""" + self.run_watchpoint_size_test('byteArray', 8, '1') + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ + def test_two_byte_watchpoints_with_word_selection(self): + """Test to selectively watch different words in an 8-byte word array.""" + self.run_watchpoint_size_test('wordArray', 4, '2') + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ + def test_four_byte_watchpoints_with_dword_selection(self): + """Test to selectively watch two double words in an 8-byte dword array.""" + self.run_watchpoint_size_test('dwordArray', 2, '4') + + def run_watchpoint_size_test(self, arrayName, array_size, watchsize): + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Detect line number after which we are going to increment arrayName. + loc_line = line_number('main.c', '// About to write ' + arrayName) + + # Set a breakpoint on the line detected above. + lldbutil.run_break_set_by_file_and_line (self, "main.c",loc_line, + num_expected_locations=1, loc_exact=True) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + for i in range(array_size): + # We should be stopped again due to the breakpoint. + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + # Set a read_write type watchpoint arrayName + watch_loc=arrayName+"[" + str(i) + "]" + self.expect("watchpoint set variable -w read_write " + watch_loc, + WATCHPOINT_CREATED, + substrs = ['Watchpoint created', 'size = ' + watchsize, 'type = rw']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should be 0 initially. + self.expect("watchpoint list -v", substrs = ['hit_count = 0']) + + self.runCmd("process continue") + + # We should be stopped due to the watchpoint. + # The stop reason of the thread should be watchpoint. + self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stopped', 'stop reason = watchpoint']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be 1. + self.expect("watchpoint list -v", + substrs = ['hit_count = 1']) + + self.runCmd("process continue") + + # We should be stopped due to the watchpoint. + # The stop reason of the thread should be watchpoint. + self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT, + substrs = ['stopped', 'stop reason = watchpoint']) + + # Use the '-v' option to do verbose listing of the watchpoint. + # The hit count should now be 1. + # Verify hit_count has been updated after value has been read. + self.expect("watchpoint list -v", + substrs = ['hit_count = 2']) + + # Delete the watchpoint immediately, but set auto-confirm to true first. + self.runCmd("settings set auto-confirm true") + self.expect("watchpoint delete", substrs = ['All watchpoints removed.']) + # Restore the original setting of auto-confirm. + self.runCmd("settings clear auto-confirm") + + self.runCmd("process continue") diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c new file mode 100644 index 000000000000..ed9fed1e2113 --- /dev/null +++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_size/main.c @@ -0,0 +1,66 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include +#include + +uint64_t pad0 = 0; +uint8_t byteArray[8] = {0}; +uint64_t pad1 = 0; +uint16_t wordArray[4] = {0}; +uint64_t pad2 = 0; +uint32_t dwordArray[2] = {0}; + +int main(int argc, char** argv) { + + int i; + uint8_t localByte; + uint16_t localWord; + uint32_t localDword; + + for (i = 0; i < 8; i++) + { + printf("About to write byteArray[%d] ...\n", i); // About to write byteArray + pad0++; + byteArray[i] = 7; + pad1++; + localByte = byteArray[i]; // Here onwards we should'nt be stopped in loop + byteArray[i]++; + localByte = byteArray[i]; + } + + pad0 = 0; + pad1 = 0; + + for (i = 0; i < 4; i++) + { + printf("About to write wordArray[%d] ...\n", i); // About to write wordArray + pad0++; + wordArray[i] = 7; + pad1++; + localWord = wordArray[i]; // Here onwards we should'nt be stopped in loop + wordArray[i]++; + localWord = wordArray[i]; + } + + pad0 = 0; + pad1 = 0; + + for (i = 0; i < 2; i++) + { + printf("About to write dwordArray[%d] ...\n", i); // About to write dwordArray + pad0++; + dwordArray[i] = 7; + pad1++; + localDword = dwordArray[i]; // Here onwards we shouldn't be stopped in loop + dwordArray[i]++; + localDword = dwordArray[i]; + } + + return 0; +} diff --git a/packages/Python/lldbsuite/test/help/TestApropos.py b/packages/Python/lldbsuite/test/help/TestApropos.py new file mode 100644 index 000000000000..7b2e69938a0e --- /dev/null +++ b/packages/Python/lldbsuite/test/help/TestApropos.py @@ -0,0 +1,22 @@ +""" +Test some lldb apropos commands. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class AproposCommandTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @no_debug_info_test + def test_apropos_variable(self): + """Test that 'apropos variable' prints the fully qualified command name""" + self.expect('apropos variable', substrs=['frame variable', 'target variable', 'watchpoint set variable']) diff --git a/packages/Python/lldbsuite/test/help/TestHelp.py b/packages/Python/lldbsuite/test/help/TestHelp.py index f51b6aa59f12..f4e9faff0edf 100644 --- a/packages/Python/lldbsuite/test/help/TestHelp.py +++ b/packages/Python/lldbsuite/test/help/TestHelp.py @@ -10,7 +10,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class HelpCommandTestCase(TestBase): @@ -80,7 +82,7 @@ class HelpCommandTestCase(TestBase): def test_help_version(self): """Test 'help version' and 'version' commands.""" self.expect("help version", - substrs = ['Show version of LLDB debugger.']) + substrs = ['Show the LLDB debugger version.']) version_str = self.version_number_string() import re match = re.match('[0-9]+', version_str) @@ -163,3 +165,49 @@ class HelpCommandTestCase(TestBase): substrs = ['The following subcommands are supported:'], patterns = ['expression +--', 'variable +--']) + + @no_debug_info_test + def test_help_po_hides_options(self): + """Test that 'help po' does not show all the options for expression""" + self.expect("help po", + substrs = ['--show-all-children', '--object-description'], matching=False) + + @no_debug_info_test + def test_help_run_hides_options(self): + """Test that 'help run' does not show all the options for process launch""" + self.expect("help run", + substrs = ['--arch', '--environment'], matching=False) + + @no_debug_info_test + def test_help_next_shows_options(self): + """Test that 'help next' shows all the options for thread step-over""" + self.expect("help next", + substrs = ['--python-class','--run-mode'], matching=True) + + @no_debug_info_test + def test_help_provides_alternatives(self): + """Test that help on commands that don't exist provides information on additional help avenues""" + self.expect("help thisisnotadebuggercommand", + substrs = ["'thisisnotadebuggercommand' is not a known command.", + "Try 'help' to see a current list of commands.", + "Try 'apropos thisisnotadebuggercommand' for a list of related commands.", + "Try 'type lookup thisisnotadebuggercommand' for information on types, methods, functions, modules, etc."], error=True) + + self.expect("help process thisisnotadebuggercommand", + substrs = ["'process thisisnotadebuggercommand' is not a known command.", + "Try 'help' to see a current list of commands.", + "Try 'apropos thisisnotadebuggercommand' for a list of related commands.", + "Try 'type lookup thisisnotadebuggercommand' for information on types, methods, functions, modules, etc."]) + + @no_debug_info_test + def test_custom_help_alias(self): + """Test that aliases pick up custom help text.""" + def cleanup(): + self.runCmd('command unalias afriendlyalias', check=False) + self.runCmd('command unalias averyfriendlyalias', check=False) + + self.addTearDownHook(cleanup) + self.runCmd('command alias --help "I am a friendly alias" -- afriendlyalias help') + self.expect("help afriendlyalias", matching=True, substrs = ['I am a friendly alias']) + self.runCmd('command alias --long-help "I am a very friendly alias" -- averyfriendlyalias help') + self.expect("help averyfriendlyalias", matching=True, substrs = ['I am a very friendly alias']) diff --git a/packages/Python/lldbsuite/test/issue_verification/TestInvalidDecorator.py.park b/packages/Python/lldbsuite/test/issue_verification/TestInvalidDecorator.py.park new file mode 100644 index 000000000000..7f5c4cb79cf5 --- /dev/null +++ b/packages/Python/lldbsuite/test/issue_verification/TestInvalidDecorator.py.park @@ -0,0 +1,13 @@ +from __future__ import print_function +from lldbsuite.test import lldbtest +from lldbsuite.test import decorators + + +class NonExistentDecoratorTestCase(lldbtest.TestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + @decorators.nonExistentDecorator(bugnumber="yt/1300") + def test(self): + """Verify non-existent decorators are picked up by test runner.""" + pass diff --git a/packages/Python/lldbsuite/test/issue_verification/TestRerunTimeout.py.park b/packages/Python/lldbsuite/test/issue_verification/TestRerunTimeout.py.park index 1cf5373ac491..a8f5542ae2f5 100644 --- a/packages/Python/lldbsuite/test/issue_verification/TestRerunTimeout.py.park +++ b/packages/Python/lldbsuite/test/issue_verification/TestRerunTimeout.py.park @@ -3,19 +3,21 @@ from __future__ import print_function import time -import lldbsuite.test.lldbtest as lldbtest +import lldbsuite.test.decorators as decorators import rerun_base class RerunTimeoutTestCase(rerun_base.RerunBaseTestCase): - @lldbtest.no_debug_info_test + @decorators.no_debug_info_test def test_timeout_rerun_succeeds(self): - """Tests that timeout logic kicks in and is picked up.""" + """Tests that the timeout logic kicks in and that this timeout is picked up.""" if not self.should_generate_issue(): # We pass this time. return + # We time out this time. while True: + # noinspection PyBroadException try: time.sleep(1) except: diff --git a/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py b/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py index 7cb66ba8238b..e6f1092c702a 100644 --- a/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py +++ b/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py @@ -6,14 +6,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class AnonymousTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIfIcc # llvm.org/pr15036: LLDB generates an incorrect AST layout for an anonymous struct when DWARF is generated by ICC + @skipIf(compiler="icc", bugnumber="llvm.org/pr15036: LLDB generates an incorrect AST layout for an anonymous struct when DWARF is generated by ICC") def test_expr_nest(self): self.build() self.common_setup(self.line0) @@ -36,7 +37,7 @@ class AnonymousTestCase(TestBase): self.expect("expression c->grandchild.b", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["= 2"]) - @skipIfIcc # llvm.org/pr15036: This particular regression was introduced by r181498 + @skipIf(compiler="icc", bugnumber="llvm.org/pr15036: This particular regression was introduced by r181498") def test_expr_grandchild(self): self.build() self.common_setup(self.line2) @@ -61,7 +62,7 @@ class AnonymousTestCase(TestBase): self.expect("expression z.y", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["(type_y) $", "dummy = 2"]) - @expectedFailureWindows('llvm.org/pr21550') + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21550") def test_expr_null(self): self.build() self.common_setup(self.line2) @@ -111,6 +112,17 @@ class AnonymousTestCase(TestBase): if not error.Success() or value != 0: self.fail ("failed to get the correct value for element a in n") + def test_nest_flat(self): + self.build() + self.common_setup(self.line2) + + # These should display correctly. + self.expect('frame variable n --flat', + substrs = ['n.a = 0', + 'n.b = 2', + 'n.foo.c = 0', + 'n.foo.d = 4']) + def setUp(self): # Call super's setUp(). TestBase.setUp(self) diff --git a/packages/Python/lldbsuite/test/lang/c/array_types/TestArrayTypes.py b/packages/Python/lldbsuite/test/lang/c/array_types/TestArrayTypes.py index e835fb096496..5a4907465682 100644 --- a/packages/Python/lldbsuite/test/lang/c/array_types/TestArrayTypes.py +++ b/packages/Python/lldbsuite/test/lang/c/array_types/TestArrayTypes.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ArrayTypesTestCase(TestBase): @@ -100,11 +101,8 @@ class ArrayTypesTestCase(TestBase): "executable = a.out"]) # The stop reason of the thread should be breakpoint. - thread = process.GetThreadAtIndex(0) - if thread.GetStopReason() != lldb.eStopReasonBreakpoint: - from lldbsuite.test.lldbutil import stop_reason_to_str - self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % - stop_reason_to_str(thread.GetStopReason())) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # Sanity check the print representation of thread. thr = str(thread) @@ -120,7 +118,7 @@ class ArrayTypesTestCase(TestBase): substrs = [tidstr]) # The breakpoint should have a hit count of 1. - self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE) + self.assertEqual(breakpoint.GetHitCount(), 1, BREAKPOINT_HIT_ONCE) # The breakpoint should be resolved by now. bp = str(breakpoint) diff --git a/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py b/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py index de7a333a18fa..30175c5e1c15 100644 --- a/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py +++ b/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BitfieldsTestCase(TestBase): @@ -95,8 +96,17 @@ class BitfieldsTestCase(TestBase): self.expect("expr (more_bits.d)", VARIABLES_DISPLAYED_CORRECTLY, substrs = ['uint8_t', '\\0']) + self.expect("expr (packed.a)", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['char', "'a'"]) + self.expect("expr (packed.b)", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['uint32_t', "10"]) + self.expect("expr/x (packed.c)", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['uint32_t', "7112233"]) + + @add_test_categories(['pyapi']) @skipIfWindows # BitFields exhibit crashes in record layout on Windows (http://llvm.org/pr21800) + @expectedFailureAll("llvm.org/pr27510", oslist=["linux"], compiler="clang", compiler_version=[">=", "3.9"]) def test_and_python_api(self): """Use Python APIs to inspect a bitfields variable.""" self.build() @@ -112,14 +122,11 @@ class BitfieldsTestCase(TestBase): self.assertTrue(process, PROCESS_IS_VALID) # The stop reason of the thread should be breakpoint. - thread = target.GetProcess().GetThreadAtIndex(0) - if thread.GetStopReason() != lldb.eStopReasonBreakpoint: - from lldbsuite.test.lldbutil import stop_reason_to_str - self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % - stop_reason_to_str(thread.GetStopReason())) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # The breakpoint should have a hit count of 1. - self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE) + self.assertEqual(breakpoint.GetHitCount(), 1, BREAKPOINT_HIT_ONCE) # Lookup the "bits" variable which contains 8 bitfields. frame = thread.GetFrameAtIndex(0) diff --git a/packages/Python/lldbsuite/test/lang/c/bitfields/main.c b/packages/Python/lldbsuite/test/lang/c/bitfields/main.c index 26c0176d759c..236c926d81bd 100644 --- a/packages/Python/lldbsuite/test/lang/c/bitfields/main.c +++ b/packages/Python/lldbsuite/test/lang/c/bitfields/main.c @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include #include + int main (int argc, char const *argv[]) { struct Bits @@ -62,6 +63,19 @@ int main (int argc, char const *argv[]) more_bits.c = 1; more_bits.d = 0; +#pragma pack(1) + struct PackedBits + { + char a; + uint32_t b : 5, + c : 27; + }; +#pragma pack() + struct PackedBits packed; + packed.a = 'a'; + packed.b = 10; + packed.c = 0x7112233; + return 0; //// Set break point at this line. } diff --git a/packages/Python/lldbsuite/test/lang/c/blocks/TestBlocks.py b/packages/Python/lldbsuite/test/lang/c/blocks/TestBlocks.py index 8f1c3be22836..0cc9456af32e 100644 --- a/packages/Python/lldbsuite/test/lang/c/blocks/TestBlocks.py +++ b/packages/Python/lldbsuite/test/lang/c/blocks/TestBlocks.py @@ -8,6 +8,7 @@ import unittest2 import os, time import lldb from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * import lldbsuite.test.lldbutil as lldbutil class BlocksTestCase(TestBase): @@ -21,9 +22,8 @@ class BlocksTestCase(TestBase): # Find the line numbers to break at. self.lines.append(line_number('main.c', '// Set breakpoint 0 here.')) self.lines.append(line_number('main.c', '// Set breakpoint 1 here.')) - - @unittest2.expectedFailure("rdar://problem/10413887 - Call blocks in expressions") - def test_expr(self): + + def launch_common(self): self.build() exe = os.path.join(os.getcwd(), "a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) @@ -35,6 +35,10 @@ class BlocksTestCase(TestBase): lldbutil.run_break_set_by_file_and_line (self, "main.c", line, num_expected_locations=1, loc_exact=True) self.wait_for_breakpoint() + + @skipUnlessDarwin + def test_expr(self): + self.launch_common() self.expect("expression a + b", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["= 7"]) @@ -47,6 +51,14 @@ class BlocksTestCase(TestBase): # This should display correctly. self.expect("expression (int)neg (-12)", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["= 12"]) + + @skipUnlessDarwin + def test_define(self): + self.launch_common() + + self.runCmd("expression int (^$add)(int, int) = ^int(int a, int b) { return a + b; };") + + self.expect("expression $add(2,3)", VARIABLES_DISPLAYED_CORRECTLY, substrs = [" = 5"]) def wait_for_breakpoint(self): if self.is_started == False: diff --git a/packages/Python/lldbsuite/test/lang/c/const_variables/TestConstVariables.py b/packages/Python/lldbsuite/test/lang/c/const_variables/TestConstVariables.py index a112b2a1777c..99544c7bd80e 100644 --- a/packages/Python/lldbsuite/test/lang/c/const_variables/TestConstVariables.py +++ b/packages/Python/lldbsuite/test/lang/c/const_variables/TestConstVariables.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ConstVariableTestCase(TestBase): @@ -24,8 +25,8 @@ class ConstVariableTestCase(TestBase): compiler="clang", compiler_version=["=", "3.8"]) @expectedFailureAll(oslist=["freebsd", "linux"], compiler="icc") @expectedFailureAll(archs=['mips', 'mipsel', 'mips64', 'mips64el']) - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") - @expectedFailureWindows("llvm.org/pr24490: We shouldn't be using platform-specific names like `getpid` in tests") + @expectedFailureAll(oslist=["linux"], archs=['arm', 'aarch64'], bugnumber="llvm.org/pr27883") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_and_run_command(self): """Test interpreted and JITted expressions on constant values.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/enum_types/TestEnumTypes.py b/packages/Python/lldbsuite/test/lang/c/enum_types/TestEnumTypes.py index b0c5c882f6a9..044accf14f65 100644 --- a/packages/Python/lldbsuite/test/lang/c/enum_types/TestEnumTypes.py +++ b/packages/Python/lldbsuite/test/lang/c/enum_types/TestEnumTypes.py @@ -8,6 +8,7 @@ import os, time import lldb from lldbsuite.test.lldbtest import * import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * class EnumTypesTestCase(TestBase): @@ -19,6 +20,7 @@ class EnumTypesTestCase(TestBase): # Find the line number to break inside main(). self.line = line_number('main.c', '// Set break point at this line.') + @expectedFailureAll(oslist=['windows']) # derefing the null pointer "works" on Windows def test(self): """Test 'image lookup -t days' and check for correct display and enum value printing.""" self.build() @@ -53,10 +55,10 @@ class EnumTypesTestCase(TestBase): 'kNumDays', '}']) - enum_values = [ '-4', - 'Monday', - 'Tuesday', - 'Wednesday', + enum_values = [ '-4', + 'Monday', + 'Tuesday', + 'Wednesday', 'Thursday', 'Friday', 'Saturday', @@ -64,6 +66,13 @@ class EnumTypesTestCase(TestBase): 'kNumDays', '5']; + # Make sure a pointer to an anonymous enum type does crash LLDB and displays correctly using + # frame variable and expression commands + self.expect('frame variable f.op', DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ['ops *', 'f.op'], patterns = ['0x0+$']) + self.expect('frame variable *f.op', DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ['ops', '*f.op', '']) + self.expect('expr f.op', DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ['ops *', '$'], patterns = ['0x0+$']) + self.expect('expr *f.op', DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ['error:'], error = True) + bkpt = self.target().FindBreakpointByID(bkpt_id) for enum_value in enum_values: self.expect("frame variable day", 'check for valid enumeration value', diff --git a/packages/Python/lldbsuite/test/lang/c/enum_types/main.c b/packages/Python/lldbsuite/test/lang/c/enum_types/main.c index 3d59654eff69..59ea21300693 100644 --- a/packages/Python/lldbsuite/test/lang/c/enum_types/main.c +++ b/packages/Python/lldbsuite/test/lang/c/enum_types/main.c @@ -8,6 +8,15 @@ //===----------------------------------------------------------------------===// #include +#include + +// Forward declare an enumeration (only works in C, not C++) +typedef enum ops ops; + +struct foo { + ops *op; +}; + int main (int argc, char const *argv[]) { enum days { @@ -21,6 +30,8 @@ int main (int argc, char const *argv[]) kNumDays }; enum days day; + struct foo f; + f.op = NULL; for (day = Monday - 1; day <= kNumDays + 1; day++) { printf("day as int is %i\n", (int)day); // Set break point at this line. diff --git a/packages/Python/lldbsuite/test/lang/c/function_types/TestFunctionTypes.py b/packages/Python/lldbsuite/test/lang/c/function_types/TestFunctionTypes.py index 2f9f1d10b58c..67ccb1aa3fa4 100644 --- a/packages/Python/lldbsuite/test/lang/c/function_types/TestFunctionTypes.py +++ b/packages/Python/lldbsuite/test/lang/c/function_types/TestFunctionTypes.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class FunctionTypesTestCase(TestBase): @@ -37,7 +38,7 @@ class FunctionTypesTestCase(TestBase): substrs = ['a.out`string_not_empty', 'stop reason = breakpoint']) - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_pointers(self): """Test that a function pointer to 'printf' works and can be called.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py b/packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py index 1f91cd1660c3..87160f5252be 100644 --- a/packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py +++ b/packages/Python/lldbsuite/test/lang/c/global_variables/TestGlobalVariables.py @@ -3,8 +3,9 @@ from __future__ import print_function +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class GlobalVariablesTestCase(TestBase): @@ -18,8 +19,8 @@ class GlobalVariablesTestCase(TestBase): self.line = line_number(self.source, '// Set break point at this line.') self.shlib_names = ["a"] - @expectedFailureWindows("llvm.org/pr24764") - @expectedFailureAll("llvm.org/pr25872", oslist=["macosx"], debug_info="dwarf") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") + @expectedFailureAll("llvm.org/pr25872", oslist=["macosx"], debug_info=["dwarf", "gmodules"]) def test_c_global_variables(self): """Test 'frame variable --scope --no-args' which omits args and shows scopes.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/inlines/Makefile b/packages/Python/lldbsuite/test/lang/c/inlines/Makefile deleted file mode 100644 index c5b0d18f995d..000000000000 --- a/packages/Python/lldbsuite/test/lang/c/inlines/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -LEVEL = ../../../make - -C_SOURCES := inlines.c - -include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py b/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py new file mode 100644 index 000000000000..d6fbf42b7570 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [decorators.expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr27845"), + decorators.expectedFailureAll(compiler="clang", compiler_version=["<", "3.5"], bugnumber="llvm.org/pr27845")]) diff --git a/packages/Python/lldbsuite/test/lang/c/inlines/inlines.c b/packages/Python/lldbsuite/test/lang/c/inlines/inlines.c deleted file mode 100644 index 1e920f1ef2f6..000000000000 --- a/packages/Python/lldbsuite/test/lang/c/inlines/inlines.c +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include "inlines.h" - -#define INLINE_ME __inline__ __attribute__((always_inline)) - -int -not_inlined_2 (int input) -{ - printf ("Called in not_inlined_2 with : %d.\n", input); - return input; -} - -int -not_inlined_1 (int input) -{ - printf ("Called in not_inlined_1 with %d.\n", input); - return not_inlined_2(input); -} - -INLINE_ME int -inner_inline (int inner_input, int mod_value) -{ - int inner_result; - inner_result = inner_input % mod_value; - printf ("Returning: %d.\n", inner_result); - return not_inlined_1 (inner_result); -} - -INLINE_ME int -outer_inline (int outer_input) -{ - int outer_result; - - outer_result = inner_inline (outer_input, outer_input % 3); - return outer_result; -} - -int -main (int argc, char **argv) -{ - printf ("Starting...\n"); - - int (*func_ptr) (int); - func_ptr = outer_inline; - - outer_inline (argc); - - func_ptr (argc); - - return 0; -} - - diff --git a/packages/Python/lldbsuite/test/lang/c/inlines/inlines.h b/packages/Python/lldbsuite/test/lang/c/inlines/inlines.h deleted file mode 100644 index 265d7b4966ed..000000000000 --- a/packages/Python/lldbsuite/test/lang/c/inlines/inlines.h +++ /dev/null @@ -1,4 +0,0 @@ -int inner_inline (int inner_input, int mod_value); -int outer_inline (int outer_input); -int not_inlined_2 (int input); -int not_inlined_1 (int input); diff --git a/packages/Python/lldbsuite/test/lang/c/inlines/main.c b/packages/Python/lldbsuite/test/lang/c/inlines/main.c new file mode 100644 index 000000000000..e9bd894bf726 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/inlines/main.c @@ -0,0 +1,19 @@ +#include + +inline void test1(int) __attribute__ ((always_inline)); +inline void test2(int) __attribute__ ((always_inline)); + +void test2(int b) { + printf("test2(%d)\n", b); //% self.expect("expression b", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["42"]) +} + +void test1(int a) { + printf("test1(%d)\n", a); + test2(a+1);//% self.dbg.HandleCommand("step") + //% self.expect("expression b", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["24"]) +} + +int main() { + test2(42); + test1(23); +} diff --git a/packages/Python/lldbsuite/test/lang/c/modules/TestCModules.py b/packages/Python/lldbsuite/test/lang/c/modules/TestCModules.py index cd31f9dbacfe..5a940e2e5eff 100644 --- a/packages/Python/lldbsuite/test/lang/c/modules/TestCModules.py +++ b/packages/Python/lldbsuite/test/lang/c/modules/TestCModules.py @@ -4,23 +4,22 @@ from __future__ import print_function +from distutils.version import StrictVersion import os, time -import lldb import platform -import lldbsuite.test.lldbutil as lldbutil - -from distutils.version import StrictVersion +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class CModulesTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @skipIfFreeBSD - @expectedFailureDarwin('http://llvm.org/pr24302') - @expectedFailureLinux('http://llvm.org/pr23456') # 'fopen' has unknown return type - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(oslist=["linux"], bugnumber="http://llvm.org/pr23456 'fopen' has unknown return type") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_expr(self): if platform.system() == "Darwin" and platform.release() < StrictVersion('12.0.0'): self.skipTest() @@ -43,11 +42,11 @@ class CModulesTestCase(TestBase): self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, substrs = [' resolved, hit count = 1']) - self.expect("expr @import Darwin; 3", VARIABLES_DISPLAYED_CORRECTLY, + self.expect("expr -l objc++ -- @import Darwin; 3", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["int", "3"]) self.expect("expr *fopen(\"/dev/zero\", \"w\")", VARIABLES_DISPLAYED_CORRECTLY, - substrs = ["FILE", "_close", "__sclose"]) + substrs = ["FILE", "_close"]) self.expect("expr *myFile", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["a", "5", "b", "9"]) diff --git a/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile b/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile index 12e55616b540..a09f73fb3fa7 100644 --- a/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile +++ b/packages/Python/lldbsuite/test/lang/c/register_variables/Makefile @@ -2,6 +2,6 @@ LEVEL = ../../../make C_SOURCES := test.c -CFLAGS ?= -g -O1 +CFLAGS_EXTRAS += -O1 include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py b/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py index 7ef1f246bfd3..6b2dc6a9b126 100644 --- a/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py +++ b/packages/Python/lldbsuite/test/lang/c/register_variables/TestRegisterVariables.py @@ -2,28 +2,113 @@ from __future__ import print_function - - import os, time +import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil + +# This method attempts to figure out if a given variable +# is in a register. +# +# Return: +# True if the value has a readable value and is in a register +# False otherwise +def is_variable_in_register(frame, var_name): + # Ensure we can lookup the variable. + var = frame.FindVariable(var_name) + # print("\nchecking {}...".format(var_name)) + if var is None or not var.IsValid(): + # print("{} cannot be found".format(var_name)) + return False + + # Check that we can get its value. If not, this + # may be a variable that is just out of scope at this point. + value = var.GetValue() + # print("checking value...") + if value is None: + # print("value is invalid") + return False + # else: + # print("value is {}".format(value)) + + # We have a variable and we can get its value. The variable is in + # a register if we cannot get an address for it, assuming it is + # not a struct pointer. (This is an approximation - compilers can + # do other things with spitting up a value into multiple parts of + # multiple registers, but what we're verifying here is much more + # than it was doing before). + var_addr = var.GetAddress() + # print("checking address...") + if var_addr.IsValid(): + # We have an address, it must not be in a register. + # print("var {} is not in a register: has a valid address {}".format(var_name, var_addr)) + return False + else: + # We don't have an address but we can read the value. + # It is likely stored in a register. + # print("var {} is in a register (we don't have an address for it)".format(var_name)) + return True + + +def is_struct_pointer_in_register(frame, var_name): + # Ensure we can lookup the variable. + var = frame.FindVariable(var_name) + # print("\nchecking {}...".format(var_name)) + if var is None or not var.IsValid(): + # print("{} cannot be found".format(var_name)) + return False + + # Check that we can get its value. If not, this + # may be a variable that is just out of scope at this point. + value = var.GetValue() + # print("checking value...") + if value is None: + # print("value is invalid") + return False + # else: + # print("value is {}".format(value)) + + var_loc = var.GetLocation() + # print("checking location: {}".format(var_loc)) + if var_loc is None or var_loc.startswith("0x"): + # The frame var is not in a register but rather a memory location. + # print("frame var {} is not in a register".format(var_name)) + return False + else: + # print("frame var {} is in a register".format(var_name)) + return True + + +def re_expr_equals(val_type, val): + # Match ({val_type}) ${sum_digits} = {val} + return re.compile(r'\(' + val_type + '\) \$\d+ = ' + str(val)) + class RegisterVariableTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll(oslist=['macosx'], compiler='clang', compiler_version=['<', '7.0.0'], debug_info="dsym") - @expectedFailureClang(None, ['<', '3.5']) - @expectedFailureGcc(None, ['is', '4.8.2']) + + @expectedFailureAll(compiler="clang", compiler_version=['<', '3.5']) + @expectedFailureAll(compiler="gcc", compiler_version=['>=', '4.8.2'], archs=["i386", "x86_64"]) def test_and_run_command(self): """Test expressions on register values.""" + + # This test now ensures that each probable + # register variable location is actually a register, and + # if so, whether we can print out the variable there. + # It only requires one of them to be handled in a non-error + # way. + register_variables_count = 0 + self.build() exe = os.path.join(os.getcwd(), "a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) # Break inside the main. - lldbutil.run_break_set_by_source_regexp(self, "break", num_expected_locations=2) + lldbutil.run_break_set_by_source_regexp(self, "break", num_expected_locations=3) #################### # First breakpoint @@ -40,11 +125,16 @@ class RegisterVariableTestCase(TestBase): substrs = [' resolved, hit count = 1']) # Try some variables that should be visible - self.expect("expr a", VARIABLES_DISPLAYED_CORRECTLY, - substrs = ['(int) $0 = 2']) + frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() + if is_variable_in_register(frame, 'a'): + register_variables_count += 1 + self.expect("expr a", VARIABLES_DISPLAYED_CORRECTLY, + patterns = [re_expr_equals('int', 2)]) - self.expect("expr b->m1", VARIABLES_DISPLAYED_CORRECTLY, - substrs = ['(int) $1 = 3']) + if is_struct_pointer_in_register(frame, 'b'): + register_variables_count += 1 + self.expect("expr b->m1", VARIABLES_DISPLAYED_CORRECTLY, + patterns = [re_expr_equals('int', 3)]) ##################### # Second breakpoint @@ -61,10 +151,40 @@ class RegisterVariableTestCase(TestBase): substrs = [' resolved, hit count = 1']) # Try some variables that should be visible - self.expect("expr b->m2", VARIABLES_DISPLAYED_CORRECTLY, - substrs = ['(int) $2 = 5']) + frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() + if is_struct_pointer_in_register(frame, 'b'): + register_variables_count += 1 + self.expect("expr b->m2", VARIABLES_DISPLAYED_CORRECTLY, + patterns = [re_expr_equals('int', 5)]) + + if is_variable_in_register(frame, 'c'): + register_variables_count += 1 + self.expect("expr c", VARIABLES_DISPLAYED_CORRECTLY, + patterns = [re_expr_equals('int', 5)]) + + ##################### + # Third breakpoint + + self.runCmd("continue") - self.expect("expr c", VARIABLES_DISPLAYED_CORRECTLY, - substrs = ['(int) $3 = 5']) + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) + + # Try some variables that should be visible + frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() + if is_variable_in_register(frame, 'f'): + register_variables_count += 1 + self.expect("expr f", VARIABLES_DISPLAYED_CORRECTLY, + patterns = [re_expr_equals('float', '3.1')]) + + # Validate that we verified at least one register variable + self.assertTrue(register_variables_count > 0, "expected to verify at least one variable in a register") + # print("executed {} expressions with values in registers".format(register_variables_count)) self.runCmd("kill") diff --git a/packages/Python/lldbsuite/test/lang/c/register_variables/test.c b/packages/Python/lldbsuite/test/lang/c/register_variables/test.c index e467ac48f745..476c32899edc 100644 --- a/packages/Python/lldbsuite/test/lang/c/register_variables/test.c +++ b/packages/Python/lldbsuite/test/lang/c/register_variables/test.c @@ -5,23 +5,31 @@ struct bar { int m2; }; -void f1(int a, struct bar *b) __attribute__ ((noinline)); +void f1(int a, struct bar *b) __attribute__((noinline)) __attribute__((regparm(2))); void f1(int a, struct bar *b) { b->m2 = b->m1 + a; // set breakpoint here } -void f2(struct bar *b) __attribute__ ((noinline)); +void f2(struct bar *b) __attribute__((noinline)) __attribute__((regparm(1))); void f2(struct bar *b) { int c = b->m2; printf("%d\n", c); // set breakpoint here } +float f3() __attribute__((noinline)); +float f3() { + return 3.14f; +} + int main() { struct bar myBar = { 3, 4 }; f1(2, &myBar); f2(&myBar); + + float f = f3(); + printf("%f\n", f); // set breakpoint here return 0; } diff --git a/packages/Python/lldbsuite/test/lang/c/set_values/TestSetValues.py b/packages/Python/lldbsuite/test/lang/c/set_values/TestSetValues.py index ab8102496091..12e20dd42d44 100644 --- a/packages/Python/lldbsuite/test/lang/c/set_values/TestSetValues.py +++ b/packages/Python/lldbsuite/test/lang/c/set_values/TestSetValues.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SetValuesTestCase(TestBase): @@ -23,7 +24,6 @@ class SetValuesTestCase(TestBase): self.line4 = line_number('main.c', '// Set break point #4.') self.line5 = line_number('main.c', '// Set break point #5.') - @expectedFailureWindows("llvm.org/pr21765") def test(self): """Test settings and readings of program variables.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py b/packages/Python/lldbsuite/test/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py index a9cb46ca137b..011e4d1f22a4 100644 --- a/packages/Python/lldbsuite/test/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py +++ b/packages/Python/lldbsuite/test/lang/c/shared_lib_stripped_symbols/TestSharedLibStrippedSymbols.py @@ -6,14 +6,15 @@ from __future__ import print_function import unittest2 import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SharedLibStrippedTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows # Test crashes + @expectedFailureAll(oslist=["windows"]) def test_expr(self): """Test that types work when defined in a shared library and forward-declared in the main executable""" if "clang" in self.getCompiler() and "3.4" in self.getCompilerVersion(): @@ -26,7 +27,7 @@ class SharedLibStrippedTestCase(TestBase): self.expect("expression --show-types -- *my_foo_ptr", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["(foo)", "(sub_foo)", "other_element = 3"]) - @expectedFailureWindows # Test crashes + @expectedFailureAll(oslist=["windows"]) @unittest2.expectedFailure("rdar://problem/10381325") def test_frame_variable(self): """Test that types work when defined in a shared library and forward-declared in the main executable""" diff --git a/packages/Python/lldbsuite/test/lang/c/step-target/Makefile b/packages/Python/lldbsuite/test/lang/c/step-target/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/step-target/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py b/packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py new file mode 100644 index 000000000000..2bd72434d390 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/step-target/TestStepTarget.py @@ -0,0 +1,113 @@ +"""Test the 'step target' feature.""" + +from __future__ import print_function + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestStepTarget(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def getCategories(self): + return ['basic_process'] + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers that we will step to in main: + self.main_source = "main.c" + self.end_line = line_number(self.main_source, "All done") + + @add_test_categories(['pyapi']) + + def get_to_start (self): + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + self.main_source_spec = lldb.SBFileSpec (self.main_source) + + break_in_main = target.BreakpointCreateBySourceRegex ('Break here to try targetted stepping', self.main_source_spec) + self.assertTrue(break_in_main, VALID_BREAKPOINT) + self.assertTrue(break_in_main.GetNumLocations() > 0,"Has locations.") + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint (process, break_in_main) + + if len(threads) != 1: + self.fail ("Failed to stop at first breakpoint in main.") + + thread = threads[0] + return thread + + def test_with_end_line(self): + """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" + + thread = self.get_to_start() + + error = lldb.SBError() + thread.StepInto("lotsOfArgs", self.end_line, error) + frame = thread.frames[0] + + self.assertTrue (frame.name == "lotsOfArgs", "Stepped to lotsOfArgs.") + + def test_with_end_line_bad_name(self): + """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" + + thread = self.get_to_start() + + error = lldb.SBError() + thread.StepInto("lotsOfArgssss", self.end_line, error) + frame = thread.frames[0] + self.assertTrue (frame.line_entry.line == self.end_line, "Stepped to the block end.") + + def test_with_end_line_deeper(self): + """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" + + thread = self.get_to_start() + + error = lldb.SBError() + thread.StepInto("modifyInt", self.end_line, error) + frame = thread.frames[0] + self.assertTrue (frame.name == "modifyInt", "Stepped to modifyInt.") + + def test_with_command_and_block(self): + """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" + + thread = self.get_to_start() + + result = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand('thread step-in -t "lotsOfArgs" -e block', result) + self.assertTrue(result.Succeeded(), "thread step-in command succeeded.") + + frame = thread.frames[0] + self.assertTrue (frame.name == "lotsOfArgs", "Stepped to lotsOfArgs.") + + def test_with_command_and_block_and_bad_name(self): + """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" + + thread = self.get_to_start() + + result = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand('thread step-in -t "lotsOfArgsssss" -e block', result) + self.assertTrue(result.Succeeded(), "thread step-in command succeeded.") + + frame = thread.frames[0] + + self.assertTrue (frame.name == "main", "Stepped back out to main.") + # end_line is set to the line after the containing block. Check that we got there: + self.assertTrue(frame.line_entry.line == self.end_line, "Got out of the block") + + + diff --git a/packages/Python/lldbsuite/test/lang/c/step-target/main.c b/packages/Python/lldbsuite/test/lang/c/step-target/main.c new file mode 100644 index 000000000000..86a26c4d47a4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/step-target/main.c @@ -0,0 +1,40 @@ +#include + +void +lotsOfArgs +( + int firstArg, + int secondArg, + int thirdArg, + int fourthArg +) +{ + printf ("First: %d Second: %d Third: %d Fourth: %d.\n", + firstArg, + secondArg, + thirdArg, + fourthArg); +} + +int +modifyInt(int incoming) +{ + return incoming % 2; +} + +int +main (int argc, char **argv) +{ + if (argc > 0) + { + int var_makes_block = argc + 1; + printf ("Break here to try targetted stepping.\n"); + lotsOfArgs(var_makes_block, + modifyInt(20), + 30, + modifyInt(40)); + printf ("Done calling lotsOfArgs."); + } + printf ("All done.\n"); + return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/c/stepping/TestStepAndBreakpoints.py b/packages/Python/lldbsuite/test/lang/c/stepping/TestStepAndBreakpoints.py index c7a3de4b6846..cfaff91daa45 100644 --- a/packages/Python/lldbsuite/test/lang/c/stepping/TestStepAndBreakpoints.py +++ b/packages/Python/lldbsuite/test/lang/c/stepping/TestStepAndBreakpoints.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestCStepping(TestBase): @@ -22,10 +23,10 @@ class TestCStepping(TestBase): # Find the line numbers that we will step to in main: self.main_source = "main.c" - @expectedFailureFreeBSD('llvm.org/pr17932') - @expectedFailureLinux # llvm.org/pr14437 - @expectedFailureWindows("llvm.org/pr24777") @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr17932') + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr14437") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24777") def test_and_python_api(self): """Test stepping over vrs. hitting breakpoints & subsequent stepping in various forms.""" self.build() @@ -155,9 +156,14 @@ class TestCStepping(TestBase): current_file = frame.GetLineEntry().GetFileSpec() break_in_b.SetEnabled(True) - frame.EvaluateExpression ("b (4)", lldb.eNoDynamicValues, False) + options = lldb.SBExpressionOptions() + options.SetIgnoreBreakpoints(False) + options.SetFetchDynamicValue(False) + options.SetUnwindOnError(False) + frame.EvaluateExpression ("b (4)", options) threads = lldbutil.get_threads_stopped_at_breakpoint (process, break_in_b) + if len(threads) != 1: self.fail ("Failed to stop at breakpoint in b when calling b.") thread = threads[0] diff --git a/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py b/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py index 6f2a9ff03be0..a9f49c30d101 100644 --- a/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py +++ b/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py @@ -2,14 +2,15 @@ Tests that C strings work as expected in expressions """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CStringsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_with_run_command(self): """Tests that C strings work as expected in expressions""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py b/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py index 87ad326f3181..2249a8c9b16a 100644 --- a/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py +++ b/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.expectedFailureWindows("llvm.org/pr24764")] ) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")] ) diff --git a/packages/Python/lldbsuite/test/lang/c/tls_globals/TestTlsGlobals.py b/packages/Python/lldbsuite/test/lang/c/tls_globals/TestTlsGlobals.py index 0d9e22ec3adf..0ca9923c89a6 100644 --- a/packages/Python/lldbsuite/test/lang/c/tls_globals/TestTlsGlobals.py +++ b/packages/Python/lldbsuite/test/lang/c/tls_globals/TestTlsGlobals.py @@ -7,8 +7,9 @@ from __future__ import print_function import unittest2 import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TlsGlobalTestCase(TestBase): @@ -25,8 +26,8 @@ class TlsGlobalTestCase(TestBase): self.runCmd("settings set target.env-vars " + self.dylibPath + "=" + os.getcwd()) self.addTearDownHook(lambda: self.runCmd("settings remove target.env-vars " + self.dylibPath)) - @unittest2.expectedFailure("rdar://7796742") @skipIfWindows # TLS works differently on Windows, this would need to be implemented separately. + @expectedFailureAll(bugnumber="llvm.org/pr28392", oslist=no_match(lldbplatformutil.getDarwinOSTriples())) def test(self): """Test thread-local storage.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/tls_globals/a.c b/packages/Python/lldbsuite/test/lang/c/tls_globals/a.c index b9a85902d117..ab1022514d1e 100644 --- a/packages/Python/lldbsuite/test/lang/c/tls_globals/a.c +++ b/packages/Python/lldbsuite/test/lang/c/tls_globals/a.c @@ -11,6 +11,12 @@ __thread int var_shared = 33; +int +touch_shared() +{ + return var_shared; +} + void shared_check() { var_shared *= 2; diff --git a/packages/Python/lldbsuite/test/lang/c/tls_globals/main.c b/packages/Python/lldbsuite/test/lang/c/tls_globals/main.c index cbe01b89b7ef..73e32ca39a58 100644 --- a/packages/Python/lldbsuite/test/lang/c/tls_globals/main.c +++ b/packages/Python/lldbsuite/test/lang/c/tls_globals/main.c @@ -11,6 +11,10 @@ #include void shared_check(); +// On some OS's (darwin) you must actually access a thread local variable +// before you can read it +int +touch_shared(); // Create some TLS storage within the static executable. __thread int var_static = 44; @@ -28,9 +32,11 @@ int main (int argc, char const *argv[]) { pthread_t handle; pthread_create(&handle, NULL, &fn_static, NULL); + touch_shared(); + for (; var_static;) + { + usleep(1); // main breakpoint + } - for(;;) - usleep(1); // main breakpoint - - return 0; + return 0; } diff --git a/packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py b/packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py index a4870de1d177..232a86a2cde3 100644 --- a/packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py +++ b/packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py @@ -6,15 +6,16 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TypedefTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureAll(bugnumber="llvm.org/pr19238", compiler="clang") - @expectedFailureAll(bugnumber="llvm.org/pr25626 expectedFailureClang fails on FreeBSD", oslist=["freebsd"]) + @expectedFailureAll(compiler="clang", bugnumber="llvm.org/pr19238") + @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr25626 expectedFailureClang fails on FreeBSD") def test_typedef(self): """Test 'image lookup -t a' and check for correct display at different scopes.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/c/unions/Makefile b/packages/Python/lldbsuite/test/lang/c/unions/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/unions/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/c/unions/TestUnionMembers.py b/packages/Python/lldbsuite/test/lang/c/unions/TestUnionMembers.py new file mode 100644 index 000000000000..114be3ade01a --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/unions/TestUnionMembers.py @@ -0,0 +1,46 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestUnionMembers(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_union_members(self): + self._load_exe() + + # Set breakpoints + bp = self.target.BreakpointCreateBySourceRegex("Break here", self.src_file_spec) + self.assertTrue(bp.IsValid() and bp.GetNumLocations() >= 1, VALID_BREAKPOINT) + + # Launch the process + self.process = self.target.LaunchSimple(None, None, self.get_process_working_directory()) + self.assertTrue(self.process.IsValid(), PROCESS_IS_VALID) + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + + thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid()) + frame = thread.GetSelectedFrame() + self.assertTrue(frame.IsValid()) + + val = frame.EvaluateExpression("u"); + self.assertTrue(val.IsValid()) + val = frame.EvaluateExpression("u.s"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetNumChildren(), 2) + + def _load_exe(self): + self.build() + + cwd = os.getcwd() + + src_file = os.path.join(cwd, "main.c") + self.src_file_spec = lldb.SBFileSpec(src_file) + self.assertTrue(self.src_file_spec.IsValid(), "breakpoint file") + + # Get the path of the executable + exe_path = os.path.join(cwd, 'a.out') + + # Load the executable + self.target = self.dbg.CreateTarget(exe_path) + self.assertTrue(self.target.IsValid(), VALID_TARGET) diff --git a/packages/Python/lldbsuite/test/lang/c/unions/main.c b/packages/Python/lldbsuite/test/lang/c/unions/main.c new file mode 100644 index 000000000000..2c6a7d1e7821 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/c/unions/main.c @@ -0,0 +1,18 @@ +#include + +union S +{ + int32_t n; // occupies 4 bytes + uint16_t s[2]; // occupies 4 bytes + uint8_t c; // occupies 1 byte +}; // the whole union occupies 4 bytes + +int main() +{ + union S u; + + u.s[0] = 1234; + u.s[1] = 4321; + + return 0; // Break here +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py b/packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py index 9746dec2fa3d..ea210a1e9ea2 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py +++ b/packages/Python/lldbsuite/test/lang/cpp/auto/TestCPPAuto.py @@ -2,14 +2,16 @@ Tests that auto types work """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CPPAutoTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureGcc("GCC does not generate complete debug info") + @expectedFailureAll(compiler="gcc", bugnumber="GCC generates incomplete debug info") + @expectedFailureAll(oslist=['windows'], bugnumber="llvm.org/pr26339") def test_with_run_command(self): """Test that auto types work in the expression parser""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py b/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py index 6c06f3750d13..0a1ac11adcea 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py +++ b/packages/Python/lldbsuite/test/lang/cpp/breakpoint-commands/TestCPPBreakpointCommands.py @@ -8,13 +8,15 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class CPPBreakpointCommandsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows + @expectedFailureAll(oslist=["windows"]) def test(self): """Test a sequence of breakpoint command add, list, and delete.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py index 3aa97af68819..260dd763c007 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py +++ b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py @@ -3,8 +3,9 @@ Tests calling a function by basename """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CallCPPFunctionTestCase(TestBase): @@ -14,7 +15,7 @@ class CallCPPFunctionTestCase(TestBase): TestBase.setUp(self) self.line = line_number('main.cpp', '// breakpoint') - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_with_run_command(self): """Test calling a function by basename""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py index 272665a78577..140c4a832fd9 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py +++ b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py @@ -1,12 +1,13 @@ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestCppChainedCalls(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_with_run_command(self): self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/char1632_t/TestChar1632T.py b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/TestChar1632T.py index 9bb1faf4ba6d..d4400d3a488d 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/char1632_t/TestChar1632T.py +++ b/packages/Python/lldbsuite/test/lang/cpp/char1632_t/TestChar1632T.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class Char1632TestCase(TestBase): @@ -24,8 +25,7 @@ class Char1632TestCase(TestBase): self.lines = [ line_number(self.source, '// breakpoint1'), line_number(self.source, '// breakpoint2') ] - @expectedFailureIcc # ICC (13.1) does not emit the DW_TAG_base_type for char16_t and char32_t. - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(compiler="icc", bugnumber="ICC (13.1) does not emit the DW_TAG_base_type for char16_t and char32_t.") def test(self): """Test that the C++11 support for char16_t and char32_t works correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py index d47d1b7dde41..acce769bf949 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py +++ b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class StaticVariableTestCase(TestBase): @@ -21,7 +22,7 @@ class StaticVariableTestCase(TestBase): # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFailureWindows("llvm.org/pr24764") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test_with_run_command(self): """Test that file and class static variables display correctly.""" self.build() @@ -49,9 +50,8 @@ class StaticVariableTestCase(TestBase): startstr = "(int) A::g_points[1].x = 11") @expectedFailureDarwin(9980907) - @expectedFailureClang('Clang emits incomplete debug info.') - @expectedFailureFreeBSD('llvm.org/pr20550 failing on FreeBSD-11') - @expectedFailureGcc('GCC emits incomplete debug info.') + @expectedFailureAll(compiler=["clang", "gcc"], bugnumber="Compiler emits incomplete debug info") + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr20550 failing on FreeBSD-11') @add_test_categories(['pyapi']) def test_with_python_api(self): """Test Python APIs on file and class static variables.""" @@ -69,11 +69,8 @@ class StaticVariableTestCase(TestBase): self.assertTrue(process, PROCESS_IS_VALID) # The stop reason of the thread should be breakpoint. - thread = process.GetThreadAtIndex(0) - if thread.GetStopReason() != lldb.eStopReasonBreakpoint: - from lldbsuite.test.lldbutil import stop_reason_to_str - self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % - stop_reason_to_str(thread.GetStopReason())) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # Get the SBValue of 'A::g_points' and 'g_points'. frame = thread.GetFrameAtIndex(0) diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypes.py b/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypes.py index b67e53c30745..fe10120d497e 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypes.py +++ b/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypes.py @@ -6,9 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ClassTypesTestCase(TestBase): @@ -92,11 +92,8 @@ class ClassTypesTestCase(TestBase): lldbutil.state_type_to_str(process.GetState())) # The stop reason of the thread should be breakpoint. - thread = process.GetThreadAtIndex(0) - if thread.GetStopReason() != lldb.eStopReasonBreakpoint: - from lldbsuite.test.lldbutil import stop_reason_to_str - self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % - stop_reason_to_str(thread.GetStopReason())) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # The filename of frame #0 should be 'main.cpp' and the line number # should be 93. @@ -203,11 +200,8 @@ class ClassTypesTestCase(TestBase): lldbutil.state_type_to_str(process.GetState())) # The stop reason of the thread should be breakpoint. - thread = process.GetThreadAtIndex(0) - if thread.GetStopReason() != lldb.eStopReasonBreakpoint: - from lldbsuite.test.lldbutil import stop_reason_to_str - self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % - stop_reason_to_str(thread.GetStopReason())) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) frame = thread.frames[0] self.assertTrue (frame.IsValid(), "Got a valid frame.") diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypesDisassembly.py b/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypesDisassembly.py index 595d075d5180..6413b3e056ff 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypesDisassembly.py +++ b/packages/Python/lldbsuite/test/lang/cpp/class_types/TestClassTypesDisassembly.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class IterateFrameAndDisassembleTestCase(TestBase): @@ -46,7 +47,8 @@ class IterateFrameAndDisassembleTestCase(TestBase): # disassemble it. target = self.dbg.GetSelectedTarget() process = target.GetProcess() - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) depth = thread.GetNumFrames() for i in range(depth - 1): frame = thread.GetFrameAtIndex(i) diff --git a/packages/Python/lldbsuite/test/lang/cpp/const_this/Makefile b/packages/Python/lldbsuite/test/lang/cpp/const_this/Makefile new file mode 100644 index 000000000000..52a92c0b61ae --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/const_this/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +CXXFLAGS += -std=c++11 +include $(LEVEL)/Makefile.rules + +cleanup: + rm -f Makefile *.d + diff --git a/packages/Python/lldbsuite/test/lang/cpp/const_this/TestConstThis.py b/packages/Python/lldbsuite/test/lang/cpp/const_this/TestConstThis.py new file mode 100644 index 000000000000..a08af5d091e1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/const_this/TestConstThis.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [] ) diff --git a/packages/Python/lldbsuite/test/lang/cpp/const_this/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/const_this/main.cpp new file mode 100644 index 000000000000..7614977b245f --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/const_this/main.cpp @@ -0,0 +1,23 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +class foo { +public: + template T func(T x) const { + return x+2; //% self.expect("expr 2+3", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["5"]) + } +}; + +int i; + +int main() { + return foo().func(i); +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/diamond/TestDiamond.py b/packages/Python/lldbsuite/test/lang/cpp/diamond/TestDiamond.py index 67de03b54b20..d525e12b31ee 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/diamond/TestDiamond.py +++ b/packages/Python/lldbsuite/test/lang/cpp/diamond/TestDiamond.py @@ -20,7 +20,8 @@ class CPPTestDiamondInheritance(TestBase): self.set_breakpoint(line_number('main.cpp', '// breakpoint 2')) process = target.LaunchSimple (None, None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) frame = thread.GetFrameAtIndex(0) j1 = frame.FindVariable("j1") j1_Derived1 = j1.GetChildAtIndex(0) diff --git a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestCppValueCast.py b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestCppValueCast.py index 4e23cd899285..b456de450a82 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestCppValueCast.py +++ b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestCppValueCast.py @@ -10,8 +10,9 @@ import unittest2 import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class CppValueCastTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestDynamicValue.py b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestDynamicValue.py index 56e81c56cfa6..98e6ef92665d 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestDynamicValue.py +++ b/packages/Python/lldbsuite/test/lang/cpp/dynamic-value/TestDynamicValue.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class DynamicValueTestCase(TestBase): @@ -28,9 +29,8 @@ class DynamicValueTestCase(TestBase): self.main_second_call_line = line_number('pass-to-base.cpp', '// Break here and get real address of reallyA.') - @expectedFailureFreeBSD # FIXME: This needs to be root-caused. - @expectedFailureWindows("llvm.org/pr24663") @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24663") def test_get_dynamic_vals(self): """Test fetching C++ dynamic values from pointers & references.""" self.build(dictionary=self.getBuildFlags()) diff --git a/packages/Python/lldbsuite/test/lang/cpp/exceptions/TestCPPExceptionBreakpoints.py b/packages/Python/lldbsuite/test/lang/cpp/exceptions/TestCPPExceptionBreakpoints.py index 65cf0b361d84..4ca4cb8b79ef 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/exceptions/TestCPPExceptionBreakpoints.py +++ b/packages/Python/lldbsuite/test/lang/cpp/exceptions/TestCPPExceptionBreakpoints.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class CPPBreakpointTestCase(TestBase): @@ -21,7 +22,7 @@ class CPPBreakpointTestCase(TestBase): self.source = 'exceptions.cpp' self.catch_line = line_number(self.source, '// This is the line you should stop at for catch') - @expectedFailureWindows("llvm.org/pr24538") # clang-cl does not support throw or catch + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24538, clang-cl does not support throw or catch") def test(self): """Test lldb exception breakpoint command for CPP.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/extern_c/Makefile b/packages/Python/lldbsuite/test/lang/cpp/extern_c/Makefile new file mode 100644 index 000000000000..99bfa7e03b47 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/extern_c/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/extern_c/TestExternCSymbols.py b/packages/Python/lldbsuite/test/lang/cpp/extern_c/TestExternCSymbols.py new file mode 100644 index 000000000000..f08c0dcbda98 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/extern_c/TestExternCSymbols.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), []) diff --git a/packages/Python/lldbsuite/test/lang/cpp/extern_c/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/extern_c/main.cpp new file mode 100644 index 000000000000..a4006c2f7ed1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/extern_c/main.cpp @@ -0,0 +1,29 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include + +extern "C" +{ + int foo(); +}; + +int foo() +{ + puts("foo"); + return 2; +} + +int main (int argc, char const *argv[], char const *envp[]) +{ + foo(); + return 0; //% self.expect("expression -- foo()", substrs = ['2']) +} + diff --git a/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/TestFrameVariableAnonymousUnions.py b/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/TestFrameVariableAnonymousUnions.py index 396a637041cb..d5d536388222 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/TestFrameVariableAnonymousUnions.py +++ b/packages/Python/lldbsuite/test/lang/cpp/frame-var-anon-unions/TestFrameVariableAnonymousUnions.py @@ -19,7 +19,13 @@ class FrameVariableAnonymousUnionsTestCase(TestBase): self.runCmd("process launch", RUN_SUCCEEDED) - self.expect('frame variable -f x i', substrs=['ffffff41']) + process = self.dbg.GetSelectedTarget().GetProcess() + + if process.GetByteOrder() == lldb.eByteOrderLittle: + self.expect('frame variable -f x i', substrs=['ffffff41']) + else: + self.expect('frame variable -f x i', substrs=['41ffff00']) + self.expect('frame variable c', substrs=["'A"]) self.expect('frame variable x', matching=False, substrs=['3']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py index de56cd6a6c49..eac78cd29951 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py +++ b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py @@ -2,14 +2,15 @@ Test that global operators are found and evaluated. """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestCppGlobalOperators(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_with_run_command(self): self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/gmodules/Makefile b/packages/Python/lldbsuite/test/lang/cpp/gmodules/Makefile new file mode 100644 index 000000000000..da6f39a7488c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/gmodules/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +PCH_CXX_SOURCE = pch.h +CXX_SOURCES = main.cpp +CFLAGS_EXTRAS += $(MODULE_DEBUG_INFO_FLAGS) + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py b/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py new file mode 100644 index 000000000000..942149f6173b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py @@ -0,0 +1,50 @@ +import lldb, os +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestWithGmodulesDebugInfo(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["gmodules"]) + @expectedFailureAll(oslist=["macosx"], bugnumber="llvm.org/pr28156") + def test_specialized_typedef_from_pch(self): + self.build() + cwd = os.getcwd() + + src_file = os.path.join(cwd, "main.cpp") + src_file_spec = lldb.SBFileSpec(src_file) + self.assertTrue(src_file_spec.IsValid(), "breakpoint file") + + # Get the path of the executable + exe_path = os.path.join(cwd, 'a.out') + + # Load the executable + target = self.dbg.CreateTarget(exe_path) + self.assertTrue(target.IsValid(), VALID_TARGET) + + # Break on interesting line + breakpoint = target.BreakpointCreateBySourceRegex("break here", src_file_spec) + self.assertTrue(breakpoint.IsValid() and breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) + + # Launch the process + process = target.LaunchSimple(None, None, self.get_process_working_directory()) + self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + + # Get the thread of the process + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + + # Get frame for current thread + frame = thread.frames[0] + + testValue = frame.EvaluateExpression("test") + self.assertTrue(testValue.GetError().Success(), "Test expression value invalid: %s" % (testValue.GetError().GetCString())) + self.assertTrue(testValue.GetTypeName() == "IntContainer", "Test expression type incorrect") + + memberValue = testValue.GetChildMemberWithName("storage") + self.assertTrue(memberValue.GetError().Success(), "Member value missing or invalid: %s" % (testValue.GetError().GetCString())) + self.assertTrue(memberValue.GetTypeName() == "int", "Member type incorrect") + self.assertEqual(42, memberValue.GetValueAsSigned(), "Member value incorrect") diff --git a/packages/Python/lldbsuite/test/lang/cpp/gmodules/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/gmodules/main.cpp new file mode 100644 index 000000000000..aa4013685171 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/gmodules/main.cpp @@ -0,0 +1,5 @@ +int main(int argc, const char * argv[]) +{ + IntContainer test(42); + return 0; // break here +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/gmodules/pch.h b/packages/Python/lldbsuite/test/lang/cpp/gmodules/pch.h new file mode 100644 index 000000000000..a6c59b94c896 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/gmodules/pch.h @@ -0,0 +1,12 @@ +template +class GenericContainer { + private: + T storage; + + public: + GenericContainer(T value) { + storage = value; + }; +}; + +typedef GenericContainer IntContainer; diff --git a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py index 324f476efb9b..1e3359ecde49 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py +++ b/packages/Python/lldbsuite/test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py @@ -1,13 +1,13 @@ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestCppIncompleteTypes(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureFreeBSD("llvm.org/pr25626 test executable not built correctly on FreeBSD") - @skipIfGcc + @skipIf(compiler="gcc") def test_limit_debug_info(self): self.build() frame = self.get_test_frame('limit') @@ -20,7 +20,7 @@ class TestCppIncompleteTypes(TestBase): self.assertTrue(value_a.IsValid(), "'expr a' results in a valid SBValue object") self.assertTrue(value_a.GetError().Success(), "'expr a' is successful") - @skipIfGcc + @skipIf(compiler="gcc") @skipIfWindows # Clang on Windows asserts in external record layout in this case. def test_partial_limit_debug_info(self): self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/inlines/Makefile b/packages/Python/lldbsuite/test/lang/cpp/inlines/Makefile new file mode 100644 index 000000000000..8f67abdf2b34 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/inlines/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := inlines.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/inlines/TestInlines.py b/packages/Python/lldbsuite/test/lang/cpp/inlines/TestInlines.py new file mode 100644 index 000000000000..284057de9dcd --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/inlines/TestInlines.py @@ -0,0 +1,52 @@ +"""Test variable lookup when stopped in inline functions.""" + +from __future__ import print_function + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class InlinesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('inlines.cpp', '// Set break point at this line.') + + @expectedFailureAll("llvm.org/pr26710", oslist=["linux"], compiler="gcc") + def test(self): + """Test that local variables are visible in expressions.""" + self.build() + self.runToBreakpoint() + + # Check that 'frame variable' finds a variable + self.expect("frame variable inner_input", VARIABLES_DISPLAYED_CORRECTLY, + startstr = '(int) inner_input =') + + # Check that 'expr' finds a variable + self.expect("expr inner_input", VARIABLES_DISPLAYED_CORRECTLY, + startstr = '(int) $0 =') + + def runToBreakpoint(self): + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break inside the main. + lldbutil.run_break_set_by_file_and_line(self, "inlines.cpp", self.line, num_expected_locations=2, + loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/inlines/inlines.cpp b/packages/Python/lldbsuite/test/lang/cpp/inlines/inlines.cpp new file mode 100644 index 000000000000..822d88e22f9b --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/inlines/inlines.cpp @@ -0,0 +1,53 @@ +#include +#include "inlines.h" + +#define INLINE_ME __inline__ __attribute__((always_inline)) + +int +not_inlined_2 (int input) +{ + printf ("Called in not_inlined_2 with : %d.\n", input); + return input; +} + +int +not_inlined_1 (int input) +{ + printf ("Called in not_inlined_1 with %d.\n", input); + return not_inlined_2(input); +} + +INLINE_ME int +inner_inline (int inner_input, int mod_value) +{ + int inner_result; + inner_result = inner_input % mod_value; + printf ("Returning: %d.\n", inner_result); + return not_inlined_1 (inner_result); // Set break point at this line. +} + +INLINE_ME int +outer_inline (int outer_input) +{ + int outer_result; + + outer_result = inner_inline (outer_input, outer_input % 3); + return outer_result; +} + +int +main (int argc, char **argv) +{ + printf ("Starting...\n"); + + int (*func_ptr) (int); + func_ptr = outer_inline; + + outer_inline (argc); + + func_ptr (argc); + + return 0; +} + + diff --git a/packages/Python/lldbsuite/test/lang/cpp/inlines/inlines.h b/packages/Python/lldbsuite/test/lang/cpp/inlines/inlines.h new file mode 100644 index 000000000000..265d7b4966ed --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/inlines/inlines.h @@ -0,0 +1,4 @@ +int inner_inline (int inner_input, int mod_value); +int outer_inline (int outer_input); +int not_inlined_2 (int input); +int not_inlined_1 (int input); diff --git a/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py b/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py new file mode 100644 index 000000000000..97cc177aab70 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [lldbinline.expectedFailureAll(oslist=["windows"])]) diff --git a/packages/Python/lldbsuite/test/lang/cpp/lambdas/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/lambdas/main.cpp new file mode 100644 index 000000000000..3cce3baf2924 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/lambdas/main.cpp @@ -0,0 +1,17 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +int main (int argc, char const *argv[]) +{ + printf("Stop here\n"); //% self.runCmd("expression auto $add = [](int a, int b) { return a + b; }") + //% self.expect("expression $add(2,3)", substrs = ['= 5']) + return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py index ec26f9efe907..9d4d1b54a9d3 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py +++ b/packages/Python/lldbsuite/test/lang/cpp/limit-debug-info/TestWithLimitDebugInfo.py @@ -1,12 +1,13 @@ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestWithLimitDebugInfo(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIf(debug_info=not_in(["dwarf"])) + @skipIf(debug_info=no_match(["dwarf"])) def test_limit_debug_info(self): self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/Makefile b/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/Makefile new file mode 100644 index 000000000000..35eb63f922f7 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES = main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py b/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py new file mode 100644 index 000000000000..12fc4c236376 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/TestMembersAndLocalsWithSameName.py @@ -0,0 +1,197 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestMembersAndLocalsWithSameName(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_when_stopped_in_method(self): + self._load_exe() + + # Set breakpoints + bp1 = self.target.BreakpointCreateBySourceRegex("Break 1", self.src_file_spec) + self.assertTrue(bp1.IsValid() and bp1.GetNumLocations() >= 1, VALID_BREAKPOINT) + bp2 = self.target.BreakpointCreateBySourceRegex("Break 2", self.src_file_spec) + self.assertTrue(bp2.IsValid() and bp2.GetNumLocations() >= 1, VALID_BREAKPOINT) + bp3 = self.target.BreakpointCreateBySourceRegex("Break 3", self.src_file_spec) + self.assertTrue(bp3.IsValid() and bp3.GetNumLocations() >= 1, VALID_BREAKPOINT) + bp4 = self.target.BreakpointCreateBySourceRegex("Break 4", self.src_file_spec) + self.assertTrue(bp4.IsValid() and bp4.GetNumLocations() >= 1, VALID_BREAKPOINT) + + # Launch the process + self.process = self.target.LaunchSimple(None, None, self.get_process_working_directory()) + self.assertTrue(self.process.IsValid(), PROCESS_IS_VALID) + + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + + self._test_globals() + + self.process.Continue() + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid()) + frame = thread.GetSelectedFrame() + self.assertTrue(frame.IsValid()) + + val = frame.EvaluateExpression("a"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 12345) + + val = frame.EvaluateExpression("b"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 54321) + + val = frame.EvaluateExpression("c"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 34567) + + self.process.Continue() + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid()) + frame = thread.GetSelectedFrame() + self.assertTrue(frame.IsValid()) + + val = frame.EvaluateExpression("a"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 10001) + + val = frame.EvaluateExpression("b"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 10002) + + val = frame.EvaluateExpression("c"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 10003) + + self.process.Continue() + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid()) + frame = thread.GetSelectedFrame() + self.assertTrue(frame.IsValid()) + + val = frame.EvaluateExpression("a"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 1) + + val = frame.EvaluateExpression("b"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 2) + + val = frame.EvaluateExpression("c"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 778899) + + def test_when_stopped_in_function(self): + self._load_exe() + + # Set breakpoints + bp1 = self.target.BreakpointCreateBySourceRegex("Break 1", self.src_file_spec) + self.assertTrue(bp1.IsValid() and bp1.GetNumLocations() >= 1, VALID_BREAKPOINT) + bp5 = self.target.BreakpointCreateBySourceRegex("Break 5", self.src_file_spec) + self.assertTrue(bp5.IsValid() and bp5.GetNumLocations() >= 1, VALID_BREAKPOINT) + bp6 = self.target.BreakpointCreateBySourceRegex("Break 6", self.src_file_spec) + self.assertTrue(bp6.IsValid() and bp6.GetNumLocations() >= 1, VALID_BREAKPOINT) + bp7 = self.target.BreakpointCreateBySourceRegex("Break 7", self.src_file_spec) + self.assertTrue(bp7.IsValid() and bp7.GetNumLocations() >= 1, VALID_BREAKPOINT) + + # Launch the process + self.process = self.target.LaunchSimple(None, None, self.get_process_working_directory()) + self.assertTrue(self.process.IsValid(), PROCESS_IS_VALID) + + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + + self._test_globals() + + self.process.Continue() + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid()) + frame = thread.GetSelectedFrame() + self.assertTrue(frame.IsValid()) + + val = frame.EvaluateExpression("a"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 12345) + + val = frame.EvaluateExpression("b"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 54321) + + val = frame.EvaluateExpression("c"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 34567) + + self.process.Continue() + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid()) + frame = thread.GetSelectedFrame() + self.assertTrue(frame.IsValid()) + + val = frame.EvaluateExpression("a"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 10001) + + val = frame.EvaluateExpression("b"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 10002) + + val = frame.EvaluateExpression("c"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 10003) + + self.process.Continue() + self.assertTrue(self.process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid()) + frame = thread.GetSelectedFrame() + self.assertTrue(frame.IsValid()) + + val = frame.EvaluateExpression("a"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 1) + + val = frame.EvaluateExpression("b"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 2) + + val = frame.EvaluateExpression("c"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 778899) + + def _load_exe(self): + self.build() + + cwd = os.getcwd() + + src_file = os.path.join(cwd, "main.cpp") + self.src_file_spec = lldb.SBFileSpec(src_file) + self.assertTrue(self.src_file_spec.IsValid(), "breakpoint file") + + # Get the path of the executable + exe_path = os.path.join(cwd, 'a.out') + + # Load the executable + self.target = self.dbg.CreateTarget(exe_path) + self.assertTrue(self.target.IsValid(), VALID_TARGET) + + def _test_globals(self): + thread = lldbutil.get_stopped_thread(self.process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid()) + frame = thread.GetSelectedFrame() + self.assertTrue(frame.IsValid()) + + val = frame.EvaluateExpression("a"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 112233) + + val = frame.EvaluateExpression("b"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 445566) + + val = frame.EvaluateExpression("c"); + self.assertTrue(val.IsValid()) + self.assertEqual(val.GetValueAsUnsigned(), 778899) diff --git a/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/main.cpp new file mode 100644 index 000000000000..baf08f6a9832 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/member-and-local-vars-with-same-name/main.cpp @@ -0,0 +1,73 @@ +namespace NN +{ + int a = 778899; + int b = 665544; + int c = 445566; +} + +class A +{ +public: + A(); + int Method(int a, int b); + +private: + int a, b; +}; + +A::A() : a(10), b(100) { } + +int a = 112233; +int b = 445566; +int c = 778899; + +int +A::Method(int a, int b) +{ + { + int a = 12345; + int b = 54321; + int c = 34567; + this->a = a + b + this->b; // Break 2 + } + + { + using namespace NN; + int a = 10001; + int b = 10002; + int c = 10003; + this->a = a + b + this->b; // Break 3 + } + + return this->a + this->b + a + b; // Break 4 +} + +int +Function(int a, int b) +{ + int A; + + { + int a = 12345; + int b = 54321; + int c = 34567; + A = a + b + c; // Break 5 + } + + { + using namespace NN; + int a = 10001; + int b = 10002; + int c = 10003; + A = a + b + c; // Break 6 + } + + return A + a + b; // Break 7 +} + +int +main() +{ + A obj; + return obj.Method(1, 2) + Function(1, 2); // Break 1 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespace.py b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespace.py index a60d8252e9f0..93d53c7de712 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespace.py +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespace.py @@ -8,8 +8,78 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil + +class NamespaceBreakpointTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(bugnumber="llvm.org/pr28548", compiler="gcc") + def test_breakpoints_func_auto(self): + """Test that we can set breakpoints correctly by basename to find all functions whose basename is "func".""" + self.build() + + names = [ "func()", "func(int)", "A::B::func()", "A::func()", "A::func(int)"] + + # Create a target by the debugger. + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + module_list = lldb.SBFileSpecList() + module_list.Append(lldb.SBFileSpec(exe, False)) + cu_list = lldb.SBFileSpecList() + # Set a breakpoint by name "func" which should pick up all functions whose basename is "func" + bp = target.BreakpointCreateByName ("func", lldb.eFunctionNameTypeAuto, module_list, cu_list); + for bp_loc in bp: + name = bp_loc.GetAddress().GetFunction().GetName() + self.assertTrue(name in names, "make sure breakpoint locations are correct for 'func' with eFunctionNameTypeAuto") + + @expectedFailureAll(bugnumber="llvm.org/pr28548", compiler="gcc") + def test_breakpoints_func_full(self): + """Test that we can set breakpoints correctly by fullname to find all functions whose fully qualified name is "func" + (no namespaces).""" + self.build() + + names = [ "func()", "func(int)"] + + # Create a target by the debugger. + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + module_list = lldb.SBFileSpecList() + module_list.Append(lldb.SBFileSpec(exe, False)) + cu_list = lldb.SBFileSpecList() + + # Set a breakpoint by name "func" whose fullly qualified named matches "func" which + # should pick up only functions whose basename is "func" and has no containing context + bp = target.BreakpointCreateByName ("func", lldb.eFunctionNameTypeFull, module_list, cu_list); + for bp_loc in bp: + name = bp_loc.GetAddress().GetFunction().GetName() + self.assertTrue(name in names, "make sure breakpoint locations are correct for 'func' with eFunctionNameTypeFull") + + def test_breakpoints_a_func_full(self): + """Test that we can set breakpoints correctly by fullname to find all functions whose fully qualified name is "A::func".""" + self.build() + + names = [ "A::func()", "A::func(int)"] + + # Create a target by the debugger. + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + module_list = lldb.SBFileSpecList() + module_list.Append(lldb.SBFileSpec(exe, False)) + cu_list = lldb.SBFileSpecList() + + # Set a breakpoint by name "A::func" whose fullly qualified named matches "A::func" which + # should pick up only functions whose basename is "func" and is contained in the "A" namespace + bp = target.BreakpointCreateByName ("A::func", lldb.eFunctionNameTypeFull, module_list, cu_list); + for bp_loc in bp: + name = bp_loc.GetAddress().GetFunction().GetName() + self.assertTrue(name in names, "make sure breakpoint locations are correct for 'A::func' with eFunctionNameTypeFull") + class NamespaceTestCase(TestBase): @@ -38,7 +108,7 @@ class NamespaceTestCase(TestBase): 'stop reason = breakpoint']) # rdar://problem/8668674 - @expectedFailureWindows("llvm.org/pr24764") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test_with_run_command(self): """Test that anonymous and named namespace variables display correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py index 4cad45564c87..12e8eef40cf3 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py @@ -7,8 +7,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class NamespaceLookupTestCase(TestBase): @@ -33,8 +34,7 @@ class NamespaceLookupTestCase(TestBase): substrs = ['stopped', 'stop reason = breakpoint']) - @expectedFailureFreeBSD("llvm.org/pr25819") - @expectedFailureLinux("llvm.org/pr25819") + @expectedFailureAll(oslist=["windows", "linux", "freebsd"], bugnumber="llvm.org/pr25819") def test_scope_lookup_with_run_command(self): """Test scope lookup of functions in lldb.""" self.build() @@ -144,7 +144,7 @@ class NamespaceLookupTestCase(TestBase): # finds the global ::func(). self.expect("expr -- func()", startstr = "(int) $0 = 2") - @expectedFailureLinux("llvm.org/pr25819") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr25819") def test_scope_lookup_before_using_with_run_command(self): """Test scope lookup before using in lldb.""" self.build() @@ -158,9 +158,9 @@ class NamespaceLookupTestCase(TestBase): self.expect("expr -- func()", startstr = "(int) $0 = 1") # NOTE: this test may fail on older systems that don't emit import - # emtries in DWARF - may need to add checks for compiler versions here. - @expectedFailureFreeBSD("llvm.org/pr25819") - @expectedFailureLinux("llvm.org/pr25819") + # entries in DWARF - may need to add checks for compiler versions here. + @skipIf(compiler="gcc", oslist=["linux"], debug_info=["dwo"]) # Skip to avoid crash + @expectedFailureAll(oslist=["windows", "linux", "freebsd"], bugnumber="llvm.org/pr25819") def test_scope_after_using_directive_lookup_with_run_command(self): """Test scope lookup after using directive in lldb.""" self.build() @@ -203,8 +203,7 @@ class NamespaceLookupTestCase(TestBase): # the same type. self.expect("expr -- func()", startstr = "error") - @expectedFailureFreeBSD("llvm.org/pr25819") - @expectedFailureLinux("llvm.org/pr25819") + @expectedFailureAll(oslist=["windows", "linux", "freebsd"], bugnumber="llvm.org/pr25819") def test_scope_lookup_shadowed_by_using_with_run_command(self): """Test scope lookup shadowed by using in lldb.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/Makefile b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/Makefile new file mode 100644 index 000000000000..0041add935a6 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/Makefile @@ -0,0 +1,19 @@ +LEVEL := ../../../make + +LD_EXTRAS := -L. -l$(LIB_PREFIX)a -l$(LIB_PREFIX)b +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +.PHONY: +a.out: lib_a lib_b + +lib_%: + $(MAKE) -f $*.mk + +hidden_lib_d: + $(MAKE) -C hidden + +clean:: + $(MAKE) -f a.mk clean + $(MAKE) -f b.mk clean diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/TestNamespaceDefinitions.py b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/TestNamespaceDefinitions.py new file mode 100644 index 000000000000..f45969429004 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/TestNamespaceDefinitions.py @@ -0,0 +1,57 @@ +"""Test that forward declarations don't cause bogus conflicts in namespaced types""" + +from __future__ import print_function + + + +import unittest2 +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class NamespaceDefinitionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_expr(self): + self.build() + self.common_setup() + + self.expect("expression -- Foo::MyClass()", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['thing = ']) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.source = 'main.cpp' + self.line = line_number(self.source, '// Set breakpoint here') + self.shlib_names = ["a", "b"] + + def common_setup(self): + # Run in synchronous mode + self.dbg.SetAsync(False) + + # Create a target by the debugger. + target = self.dbg.CreateTarget("a.out") + self.assertTrue(target, VALID_TARGET) + + # Break inside the foo function which takes a bar_ptr argument. + lldbutil.run_break_set_by_file_and_line (self, self.source, self.line, num_expected_locations=1, loc_exact=True) + + # Register our shared libraries for remote targets so they get automatically uploaded + environment = self.registerSharedLibrariesWithTarget(target, self.shlib_names) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, environment, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) + diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/a.cpp b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/a.cpp new file mode 100644 index 000000000000..2ea0d2df2eca --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/a.cpp @@ -0,0 +1,16 @@ +//===-- a.cpp ---------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "foo.h" + +class ThingInside { + int a; +}; + +Foo::MyClass a_class; diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/a.mk b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/a.mk new file mode 100644 index 000000000000..5943e5077c54 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/a.mk @@ -0,0 +1,9 @@ +LEVEL := ../../../make + +DYLIB_NAME := a +DYLIB_CXX_SOURCES := a.cpp +DYLIB_ONLY := YES + +CXXFLAGS += -fPIC + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/b.cpp b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/b.cpp new file mode 100644 index 000000000000..6e7b41e00164 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/b.cpp @@ -0,0 +1,12 @@ +//===-- b.cpp ---------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "foo.h" + +Foo::MyClass b_class; diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/b.mk b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/b.mk new file mode 100644 index 000000000000..8ee2a13b1291 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/b.mk @@ -0,0 +1,9 @@ +LEVEL := ../../../make + +DYLIB_NAME := b +DYLIB_CXX_SOURCES := b.cpp +DYLIB_ONLY := YES + +CXXFLAGS += -fPIC + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/foo.h b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/foo.h new file mode 100644 index 000000000000..76b8e70880ec --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/foo.h @@ -0,0 +1,18 @@ +//===-- foo.h ---------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +class ThingInside; + +namespace Foo { + class MyClass { + ThingInside *thing; + public: + MyClass() { } + }; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/main.cpp new file mode 100644 index 000000000000..076814eae1de --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_definitions/main.cpp @@ -0,0 +1,16 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +int +main (int argc, char const *argv[]) +{ + return 0; // Set breakpoint here +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/nsimport/TestCppNsImport.py b/packages/Python/lldbsuite/test/lang/cpp/nsimport/TestCppNsImport.py index 97e9e27a6e98..d66d2ac530e5 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/nsimport/TestCppNsImport.py +++ b/packages/Python/lldbsuite/test/lang/cpp/nsimport/TestCppNsImport.py @@ -2,15 +2,15 @@ Tests imported namespaces in C++. """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestCppNsImport(TestBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureFreeBSD("llvm.org/pr25925") - @expectedFailureGcc(None, ['>=', '4.9']) + @expectedFailureAll(oslist=['freebsd'], bugnumber="llvm.org/pr25925") def test_with_run_command(self): """Tests imported namespaces in C++.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py index d485dcd0f652..ff00d99d7763 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py +++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py @@ -3,8 +3,9 @@ Tests that functions with the same name are resolved correctly. """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CPPStaticMethodsTestCase(TestBase): @@ -14,7 +15,7 @@ class CPPStaticMethodsTestCase(TestBase): TestBase.setUp(self) self.line = line_number('main.cpp', '// breakpoint') - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_with_run_command(self): """Test that functions with the same name are resolved correctly""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/printf/TestPrintf.py b/packages/Python/lldbsuite/test/lang/cpp/printf/TestPrintf.py new file mode 100644 index 000000000000..2a2c673f8675 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/printf/TestPrintf.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [decorators.expectedFailureAll(bugnumber="rdar://problem/24599697")] ) diff --git a/packages/Python/lldbsuite/test/lang/cpp/printf/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/printf/main.cpp new file mode 100644 index 000000000000..badf1be0b41f --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/printf/main.cpp @@ -0,0 +1,21 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +class PrintfContainer { +public: + int printf() { + return 0; + } +}; + +int main() { + PrintfContainer().printf(); //% self.expect("expression -- printf(\"Hello\\n\")", substrs = ['6']) + return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/Makefile b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/Makefile deleted file mode 100644 index 1476447db355..000000000000 --- a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -LEVEL = ../../../make - -CXX_SOURCES := main.cpp -CFLAGS := -g -O0 -std=c++11 - -clean: OBJECTS+=$(wildcard main.d.*) - -include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/TestRdar12991846.py b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/TestRdar12991846.py deleted file mode 100644 index 636a82b425da..000000000000 --- a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/TestRdar12991846.py +++ /dev/null @@ -1,85 +0,0 @@ -# coding=utf8 -""" -Test that the expression parser returns proper Unicode strings. -""" - -from __future__ import print_function - - - -import unittest2 -import os, time -import lldb -from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil - -# this test case fails because of rdar://12991846 -# the expression parser does not deal correctly with Unicode expressions -# e.g. -#(lldb) expr L"Hello" -#(const wchar_t [6]) $0 = { -# [0] = \0\0\0\0 -# [1] = \0\0\0\0 -# [2] = \0\0\0\0 -# [3] = \0\0\0\0 -# [4] = H\0\0\0 -# [5] = e\0\0\0 -#} - -class Rdar12991846TestCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - @unittest2.expectedFailure("rdar://18684408") - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") - def test_expr1(self): - """Test that the expression parser returns proper Unicode strings.""" - self.build() - self.rdar12991846(expr=1) - - @unittest2.expectedFailure("rdar://18684408") - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") - def test_expr2(self): - """Test that the expression parser returns proper Unicode strings.""" - self.build() - self.rdar12991846(expr=2) - - @unittest2.expectedFailure("rdar://18684408") - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") - def test_expr3(self): - """Test that the expression parser returns proper Unicode strings.""" - self.build() - self.rdar12991846(expr=3) - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line number to break for main.cpp. - self.source = 'main.cpp' - self.line = line_number(self.source, '// Set break point at this line.') - - def rdar12991846(self, expr=None): - """Test that the expression parser returns proper Unicode strings.""" - if self.getArchitecture() in ['i386']: - self.skipTest("Skipping because this test is known to crash on i386") - - exe = os.path.join(os.getcwd(), "a.out") - - # Create a target by the debugger. - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - # Break on the struct declration statement in main.cpp. - lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple (None, None, self.get_process_working_directory()) - - if not process: - self.fail("SBTarget.Launch() failed") - - if expr == 1: self.expect('expression L"hello"', substrs = ['hello']) - - if expr == 2: self.expect('expression u"hello"', substrs = ['hello']) - - if expr == 3: self.expect('expression U"hello"', substrs = ['hello']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/main.cpp deleted file mode 100644 index fda951a78991..000000000000 --- a/packages/Python/lldbsuite/test/lang/cpp/rdar12991846/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===-- main.c --------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -int main (int argc, char const *argv[]) -{ - auto cs16 = u"hello world ྒྙྐ"; - auto cs32 = U"hello world ྒྙྐ"; - char16_t *s16 = (char16_t *)u"ﺸﺵۻ"; - char32_t *s32 = (char32_t *)U"ЕЙРГЖО"; - s32 = nullptr; // Set break point at this line. - s32 = (char32_t *)U"෴"; - s16 = (char16_t *)u"色ハ匂ヘト散リヌルヲ"; - return 0; -} diff --git a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py index d02c34ecb0fe..78a2727094a7 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py +++ b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py @@ -3,16 +3,17 @@ Tests that rvalue references are supported in C++ """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class RvalueReferencesTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) #rdar://problem/11479676 - @expectedFailureIcc("ICC (13.1, 14-beta) do not emit DW_TAG_rvalue_reference_type.") - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") + @expectedFailureAll(compiler="icc", bugnumber="ICC (13.1, 14-beta) do not emit DW_TAG_rvalue_reference_type.") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_with_run_command(self): """Test that rvalues are supported in the C++ expression parser""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py index 66d4a1591575..d075eb65b848 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py +++ b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py @@ -2,15 +2,16 @@ Test scopes in C++. """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestCppScopes(TestBase): mydir = TestBase.compute_mydir(__file__) @expectedFailureDarwin - @expectedFailureWindows("llvm.org/pr24764") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") def test_with_run_command(self): self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/signed_types/TestSignedTypes.py b/packages/Python/lldbsuite/test/lang/cpp/signed_types/TestSignedTypes.py index 51e6d4579e28..3158c4c5bcf0 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/signed_types/TestSignedTypes.py +++ b/packages/Python/lldbsuite/test/lang/cpp/signed_types/TestSignedTypes.py @@ -12,7 +12,7 @@ import lldb from lldbsuite.test.lldbtest import * import lldbsuite.test.lldbutil as lldbutil -class UnsignedTypesTestCase(TestBase): +class SignedTypesTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @@ -48,7 +48,7 @@ class UnsignedTypesTestCase(TestBase): self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, substrs = [' resolved, hit count = 1']) - # Execute the assignment statement. + # Execute the puts(). self.runCmd("thread step-over") # Test that signed types display correctly. diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_members/TestCPPStaticMembers.py b/packages/Python/lldbsuite/test/lang/cpp/static_members/TestCPPStaticMembers.py index 1c41b1b6f571..dd220d905278 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/static_members/TestCPPStaticMembers.py +++ b/packages/Python/lldbsuite/test/lang/cpp/static_members/TestCPPStaticMembers.py @@ -8,15 +8,16 @@ from __future__ import print_function import unittest2 import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CPPStaticMembersTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @unittest2.expectedFailure # llvm.org/pr15401 - @expectedFailureWindows("llvm.org/pr21765") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_with_run_command(self): """Test that member variables have the correct layout, scope and qualifiers when stopped inside and outside C++ methods""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py index dba556431e39..9784be189cb4 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py +++ b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py @@ -3,8 +3,9 @@ Tests expressions that distinguish between static and non-static methods. """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CPPStaticMethodsTestCase(TestBase): @@ -14,7 +15,7 @@ class CPPStaticMethodsTestCase(TestBase): TestBase.setUp(self) self.line = line_number('main.cpp', '// Break at this line') - @expectedFailureWindows + @expectedFailureAll(oslist=["windows"]) def test_with_run_command(self): """Test that static methods are properly distinguished from regular methods""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py index 6dba1398947e..e25820857025 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py @@ -9,8 +9,9 @@ from __future__ import print_function import unittest2 import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class STLTestCase(TestBase): @@ -23,8 +24,7 @@ class STLTestCase(TestBase): self.source = 'main.cpp' self.line = line_number(self.source, '// Set break point at this line.') - # rdar://problem/10400981 - @unittest2.expectedFailure + @expectedFailureAll(bugnumber="rdar://problem/10400981") def test(self): """Test some expressions involving STL data types.""" self.build() @@ -67,7 +67,7 @@ class STLTestCase(TestBase): self.expect('expr associative_array["hello"]', substrs = [' = 2']) - @expectedFailureIcc # icc 13.1 and 14-beta do not emit DW_TAG_template_type_parameter + @expectedFailureAll(compiler="icc", bugnumber="ICC (13.1, 14-beta) do not emit DW_TAG_template_type_parameter.") @add_test_categories(['pyapi']) def test_SBType_template_aspects(self): """Test APIs for getting template arguments from an SBType.""" diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/TestStdCXXDisassembly.py b/packages/Python/lldbsuite/test/lang/cpp/stl/TestStdCXXDisassembly.py index d7435c467274..865516de4edc 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/stl/TestStdCXXDisassembly.py +++ b/packages/Python/lldbsuite/test/lang/cpp/stl/TestStdCXXDisassembly.py @@ -51,7 +51,8 @@ class StdCXXDisassembleTestCase(TestBase): # Disassemble the functions on the call stack. self.runCmd("thread backtrace") - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) depth = thread.GetNumFrames() for i in range(depth - 1): frame = thread.GetFrameAtIndex(i) diff --git a/packages/Python/lldbsuite/test/lang/cpp/template/Makefile b/packages/Python/lldbsuite/test/lang/cpp/template/Makefile new file mode 100644 index 000000000000..194af7b32398 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/template/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +CFLAGS_EXTRAS += $(NO_LIMIT_DEBUG_INFO_FLAGS) + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py b/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py new file mode 100644 index 000000000000..e08d3a10786c --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py @@ -0,0 +1,87 @@ +""" +Test that C++ template classes that have integer parameters work correctly. + +We must reconstruct the types correctly so the template types are correct +and display correctly, and also make sure the expression parser works and +is able the find all needed functions when evaluating expressions +""" +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TemplateArgsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def prepareProcess(self): + self.build() + + # Create a target by the debugger. + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Set breakpoints inside and outside methods that take pointers to the containing struct. + line = line_number('main.cpp', '// Breakpoint 1') + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", line, num_expected_locations=1, loc_exact=True) + + arguments = None + environment = None + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (arguments, environment, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Get the thread of the process + self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + + # Get frame for current thread + return thread.GetSelectedFrame() + + def test_integer_args(self): + frame = self.prepareProcess() + + testpos = frame.FindVariable('testpos') + self.assertTrue(testpos.IsValid(), 'make sure we find a local variabble named "testpos"') + self.assertTrue(testpos.GetType().GetName() == 'TestObj<1>') + + expr_result = frame.EvaluateExpression("testpos.getArg()") + self.assertTrue(expr_result.IsValid(), 'got a valid expression result from expression "testpos.getArg()"'); + self.assertTrue(expr_result.GetValue() == "1", "testpos.getArg() == 1") + self.assertTrue(expr_result.GetType().GetName() == "int", 'expr_result.GetType().GetName() == "int"') + + testneg = frame.FindVariable('testneg') + self.assertTrue(testneg.IsValid(), 'make sure we find a local variabble named "testneg"') + self.assertTrue(testneg.GetType().GetName() == 'TestObj<-1>') + + expr_result = frame.EvaluateExpression("testneg.getArg()") + self.assertTrue(expr_result.IsValid(), 'got a valid expression result from expression "testneg.getArg()"'); + self.assertTrue(expr_result.GetValue() == "-1", "testneg.getArg() == -1") + self.assertTrue(expr_result.GetType().GetName() == "int", 'expr_result.GetType().GetName() == "int"') + + # Gcc does not generate the necessary DWARF attribute for enum template parameters. + @expectedFailureAll(bugnumber="llvm.org/pr28354", compiler="gcc") + def test_enum_args(self): + frame = self.prepareProcess() + + # Make sure "member" can be displayed and also used in an expression correctly + member = frame.FindVariable('member') + self.assertTrue(member.IsValid(), 'make sure we find a local variabble named "member"') + self.assertTrue(member.GetType().GetName() == 'EnumTemplate') + + expr_result = frame.EvaluateExpression("member.getMember()") + self.assertTrue(expr_result.IsValid(), 'got a valid expression result from expression "member.getMember()"'); + self.assertTrue(expr_result.GetValue() == "123", "member.getMember() == 123") + self.assertTrue(expr_result.GetType().GetName() == "int", 'expr_result.GetType().GetName() == "int"') + + # Make sure "subclass" can be displayed and also used in an expression correctly + subclass = frame.FindVariable('subclass') + self.assertTrue(subclass.IsValid(), 'make sure we find a local variabble named "subclass"') + self.assertTrue(subclass.GetType().GetName() == 'EnumTemplate') + + expr_result = frame.EvaluateExpression("subclass.getMember()") + self.assertTrue(expr_result.IsValid(), 'got a valid expression result from expression "subclass.getMember()"'); + self.assertTrue(expr_result.GetValue() == "246", "subclass.getMember() == 246") + self.assertTrue(expr_result.GetType().GetName() == "int", 'expr_result.GetType().GetName() == "int"') diff --git a/packages/Python/lldbsuite/test/lang/cpp/template/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/template/main.cpp new file mode 100644 index 000000000000..9c33a6420912 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/template/main.cpp @@ -0,0 +1,72 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +template +class TestObj +{ +public: + int getArg() + { + return Arg; + } +}; + +//---------------------------------------------------------------------- +// Define a template class that we can specialize with an enumeration +//---------------------------------------------------------------------- +enum class EnumType +{ + Member, + Subclass +}; + +template class EnumTemplate; + +//---------------------------------------------------------------------- +// Specialization for use when "Arg" is "EnumType::Member" +//---------------------------------------------------------------------- +template <> +class EnumTemplate +{ +public: + EnumTemplate(int m) : + m_member(m) + { + } + + int getMember() const + { + return m_member; + } + +protected: + int m_member; +}; + +//---------------------------------------------------------------------- +// Specialization for use when "Arg" is "EnumType::Subclass" +//---------------------------------------------------------------------- +template <> +class EnumTemplate : + public EnumTemplate +{ +public: + EnumTemplate(int m) : EnumTemplate(m) + { + } +}; + +int main(int argc, char **argv) +{ + TestObj<1> testpos; + TestObj<-1> testneg; + EnumTemplate member(123); + EnumTemplate subclass(123*2); + return testpos.getArg() - testneg.getArg() + member.getMember()*2 - subclass.getMember(); // Breakpoint 1 +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/this/TestCPPThis.py b/packages/Python/lldbsuite/test/lang/cpp/this/TestCPPThis.py index 07cc2e8e9788..5f89371aa85b 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/this/TestCPPThis.py +++ b/packages/Python/lldbsuite/test/lang/cpp/this/TestCPPThis.py @@ -2,19 +2,18 @@ Tests that C++ member and static variables are available where they should be. """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CPPThisTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) #rdar://problem/9962849 - @expectedFailureGcc # llvm.org/pr15439 The 'this' pointer isn't available during expression evaluation when stopped in an inlined member function. - @expectedFailureIcc # ICC doesn't emit correct DWARF inline debug info for inlined member functions - @expectedFailureWindows("llvm.org/pr24489: Name lookup not working correctly on Windows") - @expectedFailureWindows("llvm.org/pr24490: We shouldn't be using platform-specific names like `getpid` in tests") - @expectedFlakeyClang(bugnumber='llvm.org/pr23012', compiler_version=['>=','3.6']) # failed with totclang - clang3.7 + @expectedFailureAll(compiler="gcc", bugnumber="llvm.org/pr15439 The 'this' pointer isn't available during expression evaluation when stopped in an inlined member function") + @expectedFailureAll(compiler="icc", bugnumber="ICC doesn't emit correct DWARF inline debug info for inlined member functions.") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") def test_with_run_command(self): """Test that the appropriate member variables are available when stopped in C++ static, inline, and const methods""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/Makefile b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/Makefile new file mode 100644 index 000000000000..1476447db355 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp +CFLAGS := -g -O0 -std=c++11 + +clean: OBJECTS+=$(wildcard main.d.*) + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py new file mode 100644 index 000000000000..1ae133f0b078 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py @@ -0,0 +1,82 @@ +# coding=utf8 +""" +Test that the expression parser returns proper Unicode strings. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +# this test case fails because of rdar://12991846 +# the expression parser does not deal correctly with Unicode expressions +# e.g. +#(lldb) expr L"Hello" +#(const wchar_t [6]) $0 = { +# [0] = \0\0\0\0 +# [1] = \0\0\0\0 +# [2] = \0\0\0\0 +# [3] = \0\0\0\0 +# [4] = H\0\0\0 +# [5] = e\0\0\0 +#} + +class UnicodeLiteralsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") + def test_expr1(self): + """Test that the expression parser returns proper Unicode strings.""" + self.build() + self.rdar12991846(expr=1) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") + def test_expr2(self): + """Test that the expression parser returns proper Unicode strings.""" + self.build() + self.rdar12991846(expr=2) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows") + def test_expr3(self): + """Test that the expression parser returns proper Unicode strings.""" + self.build() + self.rdar12991846(expr=3) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.cpp. + self.source = 'main.cpp' + self.line = line_number(self.source, '// Set break point at this line.') + + def rdar12991846(self, expr=None): + """Test that the expression parser returns proper Unicode strings.""" + if self.getArchitecture() in ['i386']: + self.skipTest("Skipping because this test is known to crash on i386") + + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Break on the struct declration statement in main.cpp. + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.Launch() failed") + + if expr == 1: self.expect('expression L"hello"', substrs = ['hello']) + + if expr == 2: self.expect('expression u"hello"', substrs = ['hello']) + + if expr == 3: self.expect('expression U"hello"', substrs = ['hello']) diff --git a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/main.cpp new file mode 100644 index 000000000000..fda951a78991 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/main.cpp @@ -0,0 +1,21 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +int main (int argc, char const *argv[]) +{ + auto cs16 = u"hello world ྒྙྐ"; + auto cs32 = U"hello world ྒྙྐ"; + char16_t *s16 = (char16_t *)u"ﺸﺵۻ"; + char32_t *s32 = (char32_t *)U"ЕЙРГЖО"; + s32 = nullptr; // Set break point at this line. + s32 = (char32_t *)U"෴"; + s16 = (char16_t *)u"色ハ匂ヘト散リヌルヲ"; + return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/TestUnsignedTypes.py b/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/TestUnsignedTypes.py index c137592558ed..30aadb389680 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/TestUnsignedTypes.py +++ b/packages/Python/lldbsuite/test/lang/cpp/unsigned_types/TestUnsignedTypes.py @@ -9,6 +9,7 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * import lldbsuite.test.lldbutil as lldbutil @@ -22,6 +23,7 @@ class UnsignedTypesTestCase(TestBase): # Find the line number to break inside main(). self.line = line_number('main.cpp', '// Set break point at this line.') + @expectedFailureAll(oslist=["windows"]) def test(self): """Test that variables with unsigned types display correctly.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py index 1553a43e1a73..bee148773f03 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py +++ b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py @@ -7,8 +7,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil def Msg(expr, val): return "'expression %s' matches the output (from compiled code): %s" % (expr, val) @@ -21,9 +22,6 @@ class CppVirtualMadness(TestBase): # printf() stmts (see main.cpp). pattern = re.compile("^([^=]*) = '([^=]*)'$") - # Assert message. - PRINTF_OUTPUT_GROKKED = "The printf output from compiled code is parsed correctly" - def setUp(self): # Call super's setUp(). TestBase.setUp(self) @@ -31,7 +29,7 @@ class CppVirtualMadness(TestBase): self.source = 'main.cpp' self.line = line_number(self.source, '// Set first breakpoint here.') - @expectedFailureIcc('llvm.org/pr16808') # lldb does not call the correct virtual function with icc + @expectedFailureAll(compiler="icc", bugnumber="llvm.org/pr16808 lldb does not call the correct virtual function with icc.") @expectedFailureAll(oslist=['windows']) def test_virtual_madness(self): """Test that expression works correctly with virtual inheritance as well as virtual function.""" @@ -57,11 +55,13 @@ class CppVirtualMadness(TestBase): thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") - # First, capture the golden output from the program itself from the - # series of printf statements. - stdout = process.GetSTDOUT(1024) - - self.assertIsNotNone(stdout, "Encountered an error reading the process's output") + # First, capture the golden output from the program itself. + golden = thread.GetFrameAtIndex(0).FindVariable("golden") + self.assertTrue(golden.IsValid(), "Encountered an error reading the process's golden variable") + error = lldb.SBError() + golden_str = process.ReadCStringFromMemory(golden.AddressOf().GetValueAsUnsigned(), 4096, error); + self.assertTrue(error.Success()) + self.assertTrue("c_as_C" in golden_str) # This golden list contains a list of "my_expr = 'value' pairs extracted # from the golden output. @@ -71,7 +71,7 @@ class CppVirtualMadness(TestBase): # # my_expr = 'value' # - for line in stdout.split(os.linesep): + for line in golden_str.split(os.linesep): match = self.pattern.search(line) if match: my_expr, val = match.group(1), match.group(2) diff --git a/packages/Python/lldbsuite/test/lang/cpp/virtual/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/virtual/main.cpp index bed1422dcbdd..0adf41577314 100644 --- a/packages/Python/lldbsuite/test/lang/cpp/virtual/main.cpp +++ b/packages/Python/lldbsuite/test/lang/cpp/virtual/main.cpp @@ -84,17 +84,20 @@ int main (int argc, char const *argv[], char const *envp[]) C *c_as_C = new C(); A *c_as_A = c_as_C; - printf ("a_as_A->a() = '%s'\n", a_as_A->a()); - printf ("a_as_A->b() = '%s'\n", a_as_A->b()); - printf ("a_as_A->c() = '%s'\n", a_as_A->c()); - printf ("b_as_A->a() = '%s'\n", b_as_A->a()); - printf ("b_as_A->b() = '%s'\n", b_as_A->b()); - printf ("b_as_A->c() = '%s'\n", b_as_A->c()); - printf ("b_as_B->aa() = '%s'\n", b_as_B->aa()); - printf ("c_as_A->a() = '%s'\n", c_as_A->a()); - printf ("c_as_A->b() = '%s'\n", c_as_A->b()); - printf ("c_as_A->c() = '%s'\n", c_as_A->c()); - printf ("c_as_C->aa() = '%s'\n", c_as_C->aa()); + char golden[4096]; + char *p = golden; + char *end = p + sizeof golden; + p += snprintf(p, end-p, "a_as_A->a() = '%s'\n", a_as_A->a()); + p += snprintf(p, end-p, "a_as_A->b() = '%s'\n", a_as_A->b()); + p += snprintf(p, end-p, "a_as_A->c() = '%s'\n", a_as_A->c()); + p += snprintf(p, end-p, "b_as_A->a() = '%s'\n", b_as_A->a()); + p += snprintf(p, end-p, "b_as_A->b() = '%s'\n", b_as_A->b()); + p += snprintf(p, end-p, "b_as_A->c() = '%s'\n", b_as_A->c()); + p += snprintf(p, end-p, "b_as_B->aa() = '%s'\n", b_as_B->aa()); + p += snprintf(p, end-p, "c_as_A->a() = '%s'\n", c_as_A->a()); + p += snprintf(p, end-p, "c_as_A->b() = '%s'\n", c_as_A->b()); + p += snprintf(p, end-p, "c_as_A->c() = '%s'\n", c_as_A->c()); + p += snprintf(p, end-p, "c_as_C->aa() = '%s'\n", c_as_C->aa()); puts("");// Set first breakpoint here. // then evaluate: // expression a_as_A->a() diff --git a/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py b/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py index cbd244a7e056..f2e5613ffd61 100644 --- a/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py +++ b/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py @@ -3,8 +3,9 @@ import os, time import unittest2 import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGoUserExpression(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py b/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py index 8b869df4ef8f..2578742467d9 100644 --- a/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py +++ b/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py @@ -3,8 +3,9 @@ import os, time import unittest2 import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGoLanguage(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py b/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py index 35961ebd1d92..8aff2e514bb9 100644 --- a/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py +++ b/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGoASTContext(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime b/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime index 44797077a641..30381ccd24c0 100644 --- a/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime +++ b/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime @@ -11,7 +11,7 @@ class TestGoLanguageRuntime(TestBase): mydir = TestBase.compute_mydir(__file__) @python_api_test - @expectedFailureFreeBSD('llvm.org/pr24895') + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr24895') @skipIfRemote # Not remote test suite ready @skipUnlessGoInstalled def test_with_dsym_and_python_api(self): diff --git a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py index 8da31e9e81f7..bf7bc93a44b4 100644 --- a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py +++ b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGoASTContext(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/bitfield_ivars/TestBitfieldIvars.py b/packages/Python/lldbsuite/test/lang/objc/bitfield_ivars/TestBitfieldIvars.py new file mode 100644 index 000000000000..01bf241b0381 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/bitfield_ivars/TestBitfieldIvars.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIfFreeBSD,decorators.skipIfLinux,decorators.skipIfWindows, decorators.expectedFailureAll(bugnumber="rdar://problem/17990991")]) diff --git a/packages/Python/lldbsuite/test/lang/objc/bitfield_ivars/main.m b/packages/Python/lldbsuite/test/lang/objc/bitfield_ivars/main.m new file mode 100644 index 000000000000..9ee3bbe66770 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/bitfield_ivars/main.m @@ -0,0 +1,52 @@ +//===-- main.m -------------------------------------------*- Objective-C-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import + +@interface HasBitfield : NSObject { +@public + unsigned field1 : 1; + unsigned field2 : 1; +}; + +-(id)init; +@end + +@implementation HasBitfield +-(id)init { + self = [super init]; + field1 = 0; + field2 = 1; + return self; +} +@end + +@interface ContainsAHasBitfield : NSObject { +@public + HasBitfield *hb; +}; +-(id)init; +@end + +@implementation ContainsAHasBitfield +-(id)init { + self = [super init]; + hb = [[HasBitfield alloc] init]; + return self; +} + +@end + +int main(int argc, const char * argv[]) { + ContainsAHasBitfield *chb = [[ContainsAHasBitfield alloc] init]; + printf("%d\n", chb->hb->field2); //% self.expect("expression -- chb->hb->field1", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["= 0"]) + //% self.expect("expression -- chb->hb->field2", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["= 1"]) # this must happen second + return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objc/blocks/TestObjCIvarsInBlocks.py b/packages/Python/lldbsuite/test/lang/objc/blocks/TestObjCIvarsInBlocks.py index 6a1cde1a3cb3..9fa03071c598 100644 --- a/packages/Python/lldbsuite/test/lang/objc/blocks/TestObjCIvarsInBlocks.py +++ b/packages/Python/lldbsuite/test/lang/objc/blocks/TestObjCIvarsInBlocks.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestObjCIvarsInBlocks(TestBase): @@ -23,7 +24,7 @@ class TestObjCIvarsInBlocks(TestBase): @skipUnlessDarwin @add_test_categories(['pyapi']) - @expectedFailurei386 # This test requires the 2.0 runtime, so it will fail on i386. + @expectedFailureAll(archs=["i[3-6]86"], bugnumber="This test requires the 2.0 runtime, so it will fail on i386") def test_with_python_api(self): """Test printing the ivars of the self when captured in blocks""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py b/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py index 207518abc91b..c153f9856603 100644 --- a/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py +++ b/packages/Python/lldbsuite/test/lang/objc/forward-decl/TestForwardDecl.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ForwardDeclTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestConstStrings.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestConstStrings.py index a9298dd81cf8..4a62d6240d98 100644 --- a/packages/Python/lldbsuite/test/lang/objc/foundation/TestConstStrings.py +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestConstStrings.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ConstStringTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestFoundationDisassembly.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestFoundationDisassembly.py index 88db12e95931..0867eec62ebe 100644 --- a/packages/Python/lldbsuite/test/lang/objc/foundation/TestFoundationDisassembly.py +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestFoundationDisassembly.py @@ -9,8 +9,9 @@ from __future__ import print_function import unittest2 import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipUnlessDarwin class FoundationDisassembleTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py index 8358bd5e923f..2a8e80f6d76e 100644 --- a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods.py @@ -10,8 +10,9 @@ from __future__ import print_function import os, os.path, time import lldb import string +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil file_index = 0 @skipUnlessDarwin diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py index b61a7702f1fe..1ee01f7f35f6 100644 --- a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjCMethods2.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipUnlessDarwin class FoundationTestCase2(TestBase): @@ -89,6 +90,7 @@ class FoundationTestCase2(TestBase): patterns = ["\(int\) \$.* = 3"]) self.runCmd("process continue") + @expectedFailureAll(oslist=["macosx"], debug_info="gmodules", bugnumber="llvm.org/pr27861") def test_NSString_expr_commands(self): """Test expression commands for NSString.""" self.build() @@ -134,7 +136,7 @@ class FoundationTestCase2(TestBase): patterns = ["\(MyString\) \$.* = ", "\(MyBase\)", "\(NSObject\)", "\(Class\)"]) self.runCmd("process continue") - @expectedFailurei386 + @expectedFailureAll(archs=["i[3-6]86"]) def test_NSError_po(self): """Test that po of the result of an unknown method doesn't require a cast.""" self.build() diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjectDescriptionAPI.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjectDescriptionAPI.py index a85f0fec9636..13ef44f195bb 100644 --- a/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjectDescriptionAPI.py +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestObjectDescriptionAPI.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjectDescriptionAPITestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py index 8f191721d89b..8b37f9309ac6 100644 --- a/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestRuntimeTypes.py @@ -8,14 +8,16 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipUnlessDarwin class RuntimeTypesTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) + @expectedFailureAll(oslist=["macosx"], debug_info="gmodules", bugnumber="llvm.org/pr27862") def test_break(self): """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'.""" if self.getArchitecture() != 'x86_64': diff --git a/packages/Python/lldbsuite/test/lang/objc/foundation/TestSymbolTable.py b/packages/Python/lldbsuite/test/lang/objc/foundation/TestSymbolTable.py index 72952c1878b1..b75a874c8145 100644 --- a/packages/Python/lldbsuite/test/lang/objc/foundation/TestSymbolTable.py +++ b/packages/Python/lldbsuite/test/lang/objc/foundation/TestSymbolTable.py @@ -6,9 +6,13 @@ from __future__ import print_function -import os, time +import os +import time + import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil @skipUnlessDarwin class FoundationSymtabTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/global_ptrs/TestGlobalObjects.py b/packages/Python/lldbsuite/test/lang/objc/global_ptrs/TestGlobalObjects.py index c4c581b9240f..24ae1a8852b1 100644 --- a/packages/Python/lldbsuite/test/lang/objc/global_ptrs/TestGlobalObjects.py +++ b/packages/Python/lldbsuite/test/lang/objc/global_ptrs/TestGlobalObjects.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCGlobalVar(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/TestHiddenIvars.py b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/TestHiddenIvars.py index e85dd8f48dec..ee5589cb96cb 100644 --- a/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/TestHiddenIvars.py +++ b/packages/Python/lldbsuite/test/lang/objc/hidden-ivars/TestHiddenIvars.py @@ -5,11 +5,14 @@ from __future__ import print_function import unittest2 -import os, time +import os +import subprocess +import time + import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import subprocess +from lldbsuite.test import lldbutil class HiddenIvarsTestCase(TestBase): @@ -26,8 +29,7 @@ class HiddenIvarsTestCase(TestBase): self.shlib_names = ["InternalDefiner"] @skipUnlessDarwin - @skipIfDwarf # This test requires a stripped binary and a dSYM - @skipIfDWO # This test requires a stripped binary and a dSYM + @skipIf(debug_info=no_match("dsym"), bugnumber="This test requires a stripped binary and a dSYM") def test_expr_stripped(self): if self.getArchitecture() == 'i386': self.skipTest("requires modern objc runtime") @@ -44,8 +46,7 @@ class HiddenIvarsTestCase(TestBase): self.expr(False) @skipUnlessDarwin - @skipIfDwarf # This test requires a stripped binary and a dSYM - @skipIfDWO # This test requires a stripped binary and a dSYM + @skipIf(debug_info=no_match("dsym"), bugnumber="This test requires a stripped binary and a dSYM") def test_frame_variable_stripped(self): if self.getArchitecture() == 'i386': self.skipTest("requires modern objc runtime") diff --git a/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py index 9ed2bb98e6e1..b91725d57c60 100644 --- a/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py +++ b/packages/Python/lldbsuite/test/lang/objc/ivar-IMP/TestObjCiVarIMP.py @@ -8,10 +8,12 @@ from __future__ import print_function import os, time import re + import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.support import seven +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.support.seven as seven +from lldbsuite.test import lldbutil def execute_command (command): # print('%% %s' % (command)) diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/TestModulesAutoImport.py b/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/TestModulesAutoImport.py index 2c052aae3ba1..fece47625a84 100644 --- a/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/TestModulesAutoImport.py +++ b/packages/Python/lldbsuite/test/lang/objc/modules-auto-import/TestModulesAutoImport.py @@ -4,15 +4,15 @@ from __future__ import print_function +from distutils.version import StrictVersion import unittest2 import os, time import lldb import platform -import lldbsuite.test.lldbutil as lldbutil - -from distutils.version import StrictVersion +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCModulesAutoImportTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/TestIncompleteModules.py b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/TestIncompleteModules.py index 8667e628d464..56fcaa050782 100644 --- a/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/TestIncompleteModules.py +++ b/packages/Python/lldbsuite/test/lang/objc/modules-incomplete/TestIncompleteModules.py @@ -5,14 +5,12 @@ from __future__ import print_function import unittest2 -import os, time -import lldb import platform -import lldbsuite.test.lldbutil as lldbutil - from distutils.version import StrictVersion +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class IncompleteModulesTestCase(TestBase): @@ -27,6 +25,7 @@ class IncompleteModulesTestCase(TestBase): @skipUnlessDarwin @unittest2.expectedFailure("rdar://20416388") @unittest2.skipIf(platform.system() != "Darwin" or StrictVersion('12.0.0') > platform.release(), "Only supported on Darwin 12.0.0+") + @skipIfDarwin # llvm.org/pr26267 def test_expr(self): self.build() exe = os.path.join(os.getcwd(), "a.out") diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py index d9d94a8cf321..6a9d9b518e1c 100644 --- a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py +++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py @@ -4,15 +4,16 @@ from __future__ import print_function +from distutils.version import StrictVersion + import unittest2 import os, time -import lldb import platform -import lldbsuite.test.lldbutil as lldbutil - -from distutils.version import StrictVersion +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ModulesInlineFunctionsTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/modules/TestObjCModules.py b/packages/Python/lldbsuite/test/lang/objc/modules/TestObjCModules.py index 04fc07281811..0efdb305584b 100644 --- a/packages/Python/lldbsuite/test/lang/objc/modules/TestObjCModules.py +++ b/packages/Python/lldbsuite/test/lang/objc/modules/TestObjCModules.py @@ -6,13 +6,13 @@ from __future__ import print_function import unittest2 import os, time -import lldb import platform -import lldbsuite.test.lldbutil as lldbutil - from distutils.version import StrictVersion +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCModulesTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc++/TestObjCXX.py b/packages/Python/lldbsuite/test/lang/objc/objc++/TestObjCXX.py index 38ef853ae112..c702eafa1f22 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc++/TestObjCXX.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc++/TestObjCXX.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ObjCXXTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py b/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py index 5d2414eed8f5..fa390cb0ad73 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-baseclass-sbtype/TestObjCBaseClassSBType.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCDynamicValueTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py b/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py index f7ce2809081a..3ff76d4194d2 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-builtin-types/TestObjCBuiltinTypes.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCBuiltinTypes(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py b/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py index 533ec2f6b7c4..901d84fb96d9 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-checker/TestObjCCheckers.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCCheckerTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-class-method/TestObjCClassMethod.py b/packages/Python/lldbsuite/test/lang/objc/objc-class-method/TestObjCClassMethod.py index 2a978bc9c024..a5767562c077 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-class-method/TestObjCClassMethod.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-class-method/TestObjCClassMethod.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCClassMethod(TestBase): @@ -21,7 +22,7 @@ class TestObjCClassMethod(TestBase): self.break_line = line_number(self.main_source, '// Set breakpoint here.') @skipUnlessDarwin - @expectedFailurei386 + @expectedFailureAll(archs=["i[3-6]86"]) @add_test_categories(['pyapi']) #rdar://problem/9745789 "expression" can't call functions in class methods def test_with_python_api(self): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py index b9e84541e2df..fc8a8129fa3c 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dyn-sbtype/TestObjCDynamicSBType.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipUnlessDarwin class ObjCDynamicSBTypeTestCase(TestBase): @@ -25,7 +26,7 @@ class ObjCDynamicSBTypeTestCase(TestBase): self.main_source = "main.m" self.line = line_number(self.main_source, '// Set breakpoint here.') - @skipIfi386 + @skipIf(archs="i[3-6]86") def test_dyn(self): """Test that we are able to properly report a usable dynamic type.""" d = {'EXE': self.exe_name} diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py index acddfb8bd647..8720ede04cbf 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-dynamic-value/TestObjCDynamicValue.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCDynamicValueTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py index 6be1d379c8eb..049b41e08d08 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-offsets/TestObjCIvarOffsets.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestObjCIvarOffsets(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/TestIvarProtocols.py b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/TestIvarProtocols.py index 80305e303d03..791ce27dad00 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/TestIvarProtocols.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-protocols/TestIvarProtocols.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIfFreeBSD,decorators.skipIfLinux,decorators.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/TestObjCIvarStripped.py b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/TestObjCIvarStripped.py index 78c7123eefca..d9007c57bfb4 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/TestObjCIvarStripped.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-ivar-stripped/TestObjCIvarStripped.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestObjCIvarStripped(TestBase): @@ -21,8 +22,7 @@ class TestObjCIvarStripped(TestBase): self.stop_line = line_number(self.main_source, '// Set breakpoint here.') @skipUnlessDarwin - @skipIfDwarf # This test requires a stripped binary and a dSYM - @skipIfDWO # This test requires a stripped binary and a dSYM + @skipIf(debug_info=no_match("dsym"), bugnumber="This test requires a stripped binary and a dSYM") @add_test_categories(['pyapi']) def test_with_python_api(self): """Test that we can find stripped Objective-C ivars in the runtime""" diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py index ca77de261829..a0cf6a7a055d 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py @@ -6,13 +6,14 @@ from __future__ import print_function import unittest2 import os, time -import lldb import platform -import lldbsuite.test.lldbutil as lldbutil from distutils.version import StrictVersion +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCNewSyntaxTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-optimized/TestObjcOptimized.py b/packages/Python/lldbsuite/test/lang/objc/objc-optimized/TestObjcOptimized.py index a4a202e3f940..2c3ac27d418f 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-optimized/TestObjcOptimized.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-optimized/TestObjcOptimized.py @@ -13,10 +13,12 @@ from __future__ import print_function import os, time import lldb -from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil import re +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + # rdar://problem/9087739 # test failure: objc_optimized does not work for "-C clang -A i386" @skipUnlessDarwin diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-property/TestObjCProperty.py b/packages/Python/lldbsuite/test/lang/objc/objc-property/TestObjCProperty.py index c22a1f1ad532..22fe3136a511 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-property/TestObjCProperty.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-property/TestObjCProperty.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCPropertyTestCase(TestBase): @@ -112,3 +113,17 @@ class ObjCPropertyTestCase(TestBase): idWithProtocol_error = idWithProtocol_value.GetError() self.assertTrue (idWithProtocol_error.Success()) self.assertTrue (idWithProtocol_value.GetTypeName() == "id") + + # Make sure that class property getter works as expected + value = frame.EvaluateExpression("BaseClass.classInt", False) + self.assertTrue (value.GetError().Success()) + self.assertTrue (value.GetValueAsUnsigned (11111) == 123) + + # Make sure that class property setter works as expected + value = frame.EvaluateExpression("BaseClass.classInt = 234", False) + self.assertTrue (value.GetError().Success()) + + # Verify that setter above actually worked + value = frame.EvaluateExpression("BaseClass.classInt", False) + self.assertTrue (value.GetError().Success()) + self.assertTrue (value.GetValueAsUnsigned (11111) == 234) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-property/main.m b/packages/Python/lldbsuite/test/lang/objc/objc-property/main.m index 2ef142be9b00..8d14759fb384 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-property/main.m +++ b/packages/Python/lldbsuite/test/lang/objc/objc-property/main.m @@ -6,6 +6,8 @@ @end +static int _class_int = 123; + @interface BaseClass : NSObject { int _backedInt; @@ -25,6 +27,7 @@ @property(getter=myGetUnbackedInt,setter=mySetUnbackedInt:) int unbackedInt; @property int backedInt; @property (nonatomic, assign) id idWithProtocol; +@property(class) int classInt; @end @implementation BaseClass @@ -68,6 +71,16 @@ _access_count++; } ++ (int) classInt +{ + return _class_int; +} + ++ (void) setClassInt:(int) n +{ + _class_int = n; +} + - (int) getAccessCount { return _access_count; diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/TestRuntimeIvars.py b/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/TestRuntimeIvars.py index 80305e303d03..791ce27dad00 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/TestRuntimeIvars.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-runtime-ivars/TestRuntimeIvars.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIfFreeBSD,decorators.skipIfLinux,decorators.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/Makefile b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/Makefile index 81e7f12dea2b..6c5492dade11 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/Makefile +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/Makefile @@ -7,9 +7,10 @@ default: a.out.stripped a.out.stripped: a.out.dSYM strip -o a.out.stripped a.out + ln -sf a.out.dSYM a.out.stripped.dSYM clean:: rm -f a.out.stripped - rm -rf a.out.stripped.dSYM + rm -rf $(wildcard *.dSYM) include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/TestObjCStaticMethodStripped.py b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/TestObjCStaticMethodStripped.py index 4bcc10b8b882..7d88292a051c 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/TestObjCStaticMethodStripped.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method-stripped/TestObjCStaticMethodStripped.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCStaticMethodStripped(TestBase): @@ -22,15 +23,14 @@ class TestObjCStaticMethodStripped(TestBase): @skipUnlessDarwin @add_test_categories(['pyapi']) - @skipIfDwarf # This test requires a stripped binary and a dSYM - @skipIfDWO # This test requires a stripped binary and a dSYM + @skipIf(debug_info=no_match("dsym"), bugnumber="This test requires a stripped binary and a dSYM") # def test_with_python_api(self): """Test calling functions in static methods with a stripped binary.""" if self.getArchitecture() == 'i386': self.skipTest("requires modern objc runtime") self.build() - exe = os.path.join(os.getcwd(), "a.out.stripped") + exe = os.path.join(os.getcwd(), "a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-static-method/TestObjCStaticMethod.py b/packages/Python/lldbsuite/test/lang/objc/objc-static-method/TestObjCStaticMethod.py index 89ef1e7b6898..ccba42db4ebe 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-static-method/TestObjCStaticMethod.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-static-method/TestObjCStaticMethod.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCStaticMethod(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-stepping/TestObjCStepping.py b/packages/Python/lldbsuite/test/lang/objc/objc-stepping/TestObjCStepping.py index 1df416d45133..d035287cfa00 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-stepping/TestObjCStepping.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-stepping/TestObjCStepping.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCStepping(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/TestObjCStructArgument.py b/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/TestObjCStructArgument.py index 36cde21c9d66..b2f2af766325 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/TestObjCStructArgument.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-struct-argument/TestObjCStructArgument.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCStructArgument(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/TestObjCStructReturn.py b/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/TestObjCStructReturn.py index 010de2180825..5a8722e71a45 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/TestObjCStructReturn.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-struct-return/TestObjCStructReturn.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCClassMethod(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-super/TestObjCSuper.py b/packages/Python/lldbsuite/test/lang/objc/objc-super/TestObjCSuper.py index 84d147f632da..39a0fb716abe 100644 --- a/packages/Python/lldbsuite/test/lang/objc/objc-super/TestObjCSuper.py +++ b/packages/Python/lldbsuite/test/lang/objc/objc-super/TestObjCSuper.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestObjCSuperMethod(TestBase): @@ -21,7 +22,7 @@ class TestObjCSuperMethod(TestBase): self.break_line = line_number(self.main_source, '// Set breakpoint here.') @skipUnlessDarwin - @expectedFailurei386 + @expectedFailureAll(archs=["i[3-6]86"]) @add_test_categories(['pyapi']) def test_with_python_api(self): """Test calling methods on super.""" diff --git a/packages/Python/lldbsuite/test/lang/objc/print-obj/TestPrintObj.py b/packages/Python/lldbsuite/test/lang/objc/print-obj/TestPrintObj.py index 5c52cc0e0697..33f7a0519fa8 100644 --- a/packages/Python/lldbsuite/test/lang/objc/print-obj/TestPrintObj.py +++ b/packages/Python/lldbsuite/test/lang/objc/print-obj/TestPrintObj.py @@ -8,7 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil @skipUnlessDarwin class PrintObjTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/radar-9691614/TestObjCMethodReturningBOOL.py b/packages/Python/lldbsuite/test/lang/objc/radar-9691614/TestObjCMethodReturningBOOL.py index 38551f671a92..32f2e7c8d6dc 100644 --- a/packages/Python/lldbsuite/test/lang/objc/radar-9691614/TestObjCMethodReturningBOOL.py +++ b/packages/Python/lldbsuite/test/lang/objc/radar-9691614/TestObjCMethodReturningBOOL.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipUnlessDarwin class MethodReturningBOOLTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/TestRdar10967107.py b/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/TestRdar10967107.py index 0902527d424c..a4654d4bd1b4 100644 --- a/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/TestRdar10967107.py +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-10967107/TestRdar10967107.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipUnlessDarwin class Rdar10967107TestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/TestRdar11355592.py b/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/TestRdar11355592.py index 42120a57834c..f1d38f8b7d32 100644 --- a/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/TestRdar11355592.py +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-11355592/TestRdar11355592.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipUnlessDarwin class Rdar10967107TestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/TestRdar12408181.py b/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/TestRdar12408181.py index b95d95106032..7bc92595ef38 100644 --- a/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/TestRdar12408181.py +++ b/packages/Python/lldbsuite/test/lang/objc/rdar-12408181/TestRdar12408181.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil @skipUnlessDarwin class Rdar12408181TestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/TestRealDefinition.py b/packages/Python/lldbsuite/test/lang/objc/real-definition/TestRealDefinition.py index 30fd2a5b0f6d..c8f9a9c82c61 100644 --- a/packages/Python/lldbsuite/test/lang/objc/real-definition/TestRealDefinition.py +++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/TestRealDefinition.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestRealDefinition(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/self/TestObjCSelf.py b/packages/Python/lldbsuite/test/lang/objc/self/TestObjCSelf.py index 37db151f9ae3..004563c55be2 100644 --- a/packages/Python/lldbsuite/test/lang/objc/self/TestObjCSelf.py +++ b/packages/Python/lldbsuite/test/lang/objc/self/TestObjCSelf.py @@ -2,8 +2,9 @@ Tests that ObjC member variables are available where they should be. """ import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ObjCSelfTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/Makefile b/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/Makefile new file mode 100644 index 000000000000..ad3cb3fadcde --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/TestObjCSingleEntryDictionary.py b/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/TestObjCSingleEntryDictionary.py new file mode 100644 index 000000000000..7c294ef8cc64 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/TestObjCSingleEntryDictionary.py @@ -0,0 +1,68 @@ +"""Test that we properly vend children for a single entry NSDictionary""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import platform + +from distutils.version import StrictVersion + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ObjCSingleEntryDictionaryTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.m', '// break here') + + @skipUnlessDarwin + def test_single_entry_dict(self): + self.build() + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break inside the foo function which takes a bar_ptr argument. + lldbutil.run_break_set_by_file_and_line (self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) + + d1 = self.frame().FindVariable("d1") + d1.SetPreferSyntheticValue(True) + d1.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + + self.assertTrue(d1.GetNumChildren() == 1, "dictionary has != 1 child elements") + pair = d1.GetChildAtIndex(0) + pair.SetPreferSyntheticValue(True) + pair.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + + self.assertTrue(pair.GetNumChildren() == 2, "pair has != 2 child elements") + + key = pair.GetChildMemberWithName("key") + value = pair.GetChildMemberWithName("value") + + key.SetPreferSyntheticValue(True) + key.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + value.SetPreferSyntheticValue(True) + value.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + + self.assertTrue(key.GetSummary() == '@"key"', "key doesn't contain key") + self.assertTrue(value.GetSummary() == '@"value"', "value doesn't contain value") diff --git a/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/main.m b/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/main.m new file mode 100644 index 000000000000..be472fd43c3d --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/single-entry-dictionary/main.m @@ -0,0 +1,7 @@ +#import + +int main() { + NSDictionary *d1 = @{@"key" : @"value"}; + NSLog(@"%@\n", d1); // break here + return 0; +} diff --git a/packages/Python/lldbsuite/test/lang/objc/variadic_methods/TestVariadicMethods.py b/packages/Python/lldbsuite/test/lang/objc/variadic_methods/TestVariadicMethods.py new file mode 100644 index 000000000000..791ce27dad00 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/variadic_methods/TestVariadicMethods.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIfFreeBSD,decorators.skipIfLinux,decorators.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/lang/objc/variadic_methods/main.m b/packages/Python/lldbsuite/test/lang/objc/variadic_methods/main.m new file mode 100644 index 000000000000..f48710e880f3 --- /dev/null +++ b/packages/Python/lldbsuite/test/lang/objc/variadic_methods/main.m @@ -0,0 +1,31 @@ +//===-- main.m -------------------------------------------*- Objective-C-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import + +@interface VarClass : NSObject +- (id) lottaArgs: (id) first, ...; +@end + +@implementation VarClass +- (id) lottaArgs: (id) first, ... +{ + return first; +} +@end + +int +main() +{ + VarClass *my_var = [[VarClass alloc] init]; + id something = [my_var lottaArgs: @"111", @"222", nil]; + NSLog (@"%@ - %@", my_var, something); //% self.expect("expression -O -- [my_var lottaArgs:@\"111\", @\"222\", nil]", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["111"]) + return 0; +} + diff --git a/packages/Python/lldbsuite/test/lang/objcxx/objcxx-ivar-vector/TestIvarVector.py b/packages/Python/lldbsuite/test/lang/objcxx/objcxx-ivar-vector/TestIvarVector.py index 80305e303d03..49bc148dd579 100644 --- a/packages/Python/lldbsuite/test/lang/objcxx/objcxx-ivar-vector/TestIvarVector.py +++ b/packages/Python/lldbsuite/test/lang/objcxx/objcxx-ivar-vector/TestIvarVector.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import decorators +from lldbsuite.test import lldbinline -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIfFreeBSD,decorators.skipIfLinux,decorators.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py b/packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py index ea742341512c..483697789c3d 100644 --- a/packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py +++ b/packages/Python/lldbsuite/test/linux/builtin_trap/TestBuiltinTrap.py @@ -9,8 +9,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class BuiltinTrapTestCase(TestBase): @@ -24,6 +25,7 @@ class BuiltinTrapTestCase(TestBase): @expectedFailureAll("llvm.org/pr15936", compiler="gcc", compiler_version=["<=","4.6"]) @expectedFailureAll(archs="arm", compiler="gcc", triple=".*-android") # gcc generates incorrect linetable + @expectedFailureAll(oslist=['linux'], archs=['arm']) @skipIfWindows def test_with_run_command(self): """Test that LLDB handles a function with __builtin_trap correctly.""" diff --git a/packages/Python/lldbsuite/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py b/packages/Python/lldbsuite/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py index c6d9afb02003..8421a8d473e1 100644 --- a/packages/Python/lldbsuite/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py +++ b/packages/Python/lldbsuite/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py @@ -9,8 +9,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class CreateDuringInstructionStepTestCase(TestBase): @@ -22,6 +23,7 @@ class CreateDuringInstructionStepTestCase(TestBase): @skipUnlessPlatform(['linux']) @expectedFailureAndroid('llvm.org/pr24737', archs=['arm']) + @expectedFailureAll(oslist=["linux"], archs=["arm"], bugnumber="llvm.org/pr24737") def test_step_inst(self): self.build(dictionary=self.getBuildFlags()) exe = os.path.join(os.getcwd(), "a.out") diff --git a/packages/Python/lldbsuite/test/lldbinline.py b/packages/Python/lldbsuite/test/lldbinline.py index abde6e790ded..6a61b2eaf557 100644 --- a/packages/Python/lldbsuite/test/lldbinline.py +++ b/packages/Python/lldbsuite/test/lldbinline.py @@ -9,7 +9,9 @@ import os # LLDB modules import lldb from .lldbtest import * +from . import configuration from . import lldbutil +from .decorators import * def source_type(filename): _, extension = os.path.splitext(filename) @@ -116,8 +118,8 @@ class InlineTest(TestBase): if ('CXX_SOURCES' in list(categories.keys())): makefile.write("CXXFLAGS += -std=c++11\n") - makefile.write("\ncleanup:\n\trm -f Makefile *.d\n\n") makefile.write("include $(LEVEL)/Makefile.rules\n") + makefile.write("\ncleanup:\n\trm -f Makefile *.d\n\n") makefile.flush() makefile.close() @@ -140,6 +142,12 @@ class InlineTest(TestBase): self.buildDwo() self.do_test() + def __test_with_gmodules(self): + self.using_dsym = False + self.BuildMakefile() + self.buildGModules() + self.do_test() + def execute_user_command(self, __command): exec(__command, globals(), locals()) @@ -185,26 +193,39 @@ def ApplyDecoratorsToFunction(func, decorators): elif hasattr(decorators, '__call__'): tmp = decorators(tmp) return tmp - + def MakeInlineTest(__file, __globals, decorators=None): + # Adjust the filename if it ends in .pyc. We want filenames to + # reflect the source python file, not the compiled variant. + if __file is not None and __file.endswith(".pyc"): + # Strip the trailing "c" + __file = __file[0:-1] + # Derive the test name from the current file name file_basename = os.path.basename(__file) InlineTest.mydir = TestBase.compute_mydir(__file) test_name, _ = os.path.splitext(file_basename) - # Build the test case + # Build the test case test = type(test_name, (InlineTest,), {'using_dsym': None}) test.name = test_name - test.test_with_dsym = ApplyDecoratorsToFunction(test._InlineTest__test_with_dsym, decorators) - test.test_with_dwarf = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwarf, decorators) - test.test_with_dwo = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwo, decorators) + target_platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] + if test_categories.is_supported_on_platform("dsym", target_platform, configuration.compilers): + test.test_with_dsym = ApplyDecoratorsToFunction(test._InlineTest__test_with_dsym, decorators) + if test_categories.is_supported_on_platform("dwarf", target_platform, configuration.compilers): + test.test_with_dwarf = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwarf, decorators) + if test_categories.is_supported_on_platform("dwo", target_platform, configuration.compilers): + test.test_with_dwo = ApplyDecoratorsToFunction(test._InlineTest__test_with_dwo, decorators) + if test_categories.is_supported_on_platform("gmodules", target_platform, configuration.compilers): + test.test_with_gmodules = ApplyDecoratorsToFunction(test._InlineTest__test_with_gmodules, decorators) # Add the test case to the globals, and hide InlineTest __globals.update({test_name : test}) - # Store the name of the originating file.o + # Keep track of the original test filename so we report it + # correctly in test results. test.test_filename = __file return test diff --git a/packages/Python/lldbsuite/test/lldbpexpect.py b/packages/Python/lldbsuite/test/lldbpexpect.py index 55b958a55972..d37d6fa4f8cb 100644 --- a/packages/Python/lldbsuite/test/lldbpexpect.py +++ b/packages/Python/lldbsuite/test/lldbpexpect.py @@ -6,58 +6,64 @@ import os import sys # Third-party modules -import pexpect +import six # LLDB Modules import lldb from .lldbtest import * from . import lldbutil -class PExpectTest(TestBase): +if sys.platform.startswith('win32'): + class PExpectTest(TestBase): + pass +else: + import pexpect + + class PExpectTest(TestBase): - mydir = TestBase.compute_mydir(__file__) + mydir = TestBase.compute_mydir(__file__) - def setUp(self): - TestBase.setUp(self) + def setUp(self): + TestBase.setUp(self) - def launchArgs(self): - pass + def launchArgs(self): + pass + + def launch(self, timeout=None): + if timeout is None: timeout = 30 + logfile = sys.stdout if self.TraceOn() else None + self.child = pexpect.spawn('%s --no-use-colors %s' % (lldbtest_config.lldbExec, self.launchArgs()), logfile=logfile) + self.child.timeout = timeout + self.timeout = timeout + + def expect(self, patterns=None, timeout=None, exact=None): + if patterns is None: return None + if timeout is None: timeout = self.timeout + if exact is None: exact = False + if exact: + return self.child.expect_exact(patterns, timeout=timeout) + else: + return self.child.expect(patterns, timeout=timeout) + + def expectall(self, patterns=None, timeout=None, exact=None): + if patterns is None: return None + if timeout is None: timeout = self.timeout + if exact is None: exact = False + for pattern in patterns: + self.expect(pattern, timeout=timeout, exact=exact) + + def sendimpl(self, sender, command, patterns=None, timeout=None, exact=None): + sender(command) + return self.expect(patterns=patterns, timeout=timeout, exact=exact) + + def send(self, command, patterns=None, timeout=None, exact=None): + return self.sendimpl(self.child.send, command, patterns, timeout, exact) + + def sendline(self, command, patterns=None, timeout=None, exact=None): + return self.sendimpl(self.child.sendline, command, patterns, timeout, exact) - def launch(self, timeout=None): - if timeout is None: timeout = 30 - logfile = sys.stdout if self.TraceOn() else None - self.child = pexpect.spawn('%s %s' % (lldbtest_config.lldbExec, self.launchArgs()), logfile=logfile) - self.child.timeout = timeout - self.timeout = timeout - - def expect(self, patterns=None, timeout=None, exact=None): - if patterns is None: return None - if timeout is None: timeout = self.timeout - if exact is None: exact = False - if exact: - return self.child.expect_exact(patterns, timeout=timeout) - else: - return self.child.expect(patterns, timeout=timeout) - - def expectall(self, patterns=None, timeout=None, exact=None): - if patterns is None: return None - if timeout is None: timeout = self.timeout - if exact is None: exact = False - for pattern in patterns: - self.expect(pattern, timeout=timeout, exact=exact) - - def sendimpl(self, sender, command, patterns=None, timeout=None, exact=None): - sender(command) - return self.expect(patterns=patterns, timeout=timeout, exact=exact) - - def send(self, command, patterns=None, timeout=None, exact=None): - return self.sendimpl(self.child.send, command, patterns, timeout, exact) - - def sendline(self, command, patterns=None, timeout=None, exact=None): - return self.sendimpl(self.child.sendline, command, patterns, timeout, exact) - - def quit(self, gracefully=None): - if gracefully is None: gracefully = True - self.child.sendeof() - self.child.close(force=not gracefully) - self.child = None + def quit(self, gracefully=None): + if gracefully is None: gracefully = True + self.child.sendeof() + self.child.close(force=not gracefully) + self.child = None diff --git a/packages/Python/lldbsuite/test/lldbplatform.py b/packages/Python/lldbsuite/test/lldbplatform.py new file mode 100644 index 000000000000..33927df6c0f1 --- /dev/null +++ b/packages/Python/lldbsuite/test/lldbplatform.py @@ -0,0 +1,44 @@ +""" This module represents an abstraction of an lldb target / host platform. """ + +from __future__ import absolute_import + +# System modules +import itertools + +# Third-party modules +import six + +# LLDB modules +import use_lldb_suite +import lldb + +windows, linux, macosx, darwin, ios, darwin_all, freebsd, netbsd, bsd_all, android = range(10) + +__name_lookup = { + windows : ["windows"], + linux : ["linux"], + macosx : ["macosx"], + darwin : ["darwin"], + ios : ["ios"], + darwin_all : ["macosx", "darwin", "ios"], + freebsd : ["freebsd"], + netbsd : ["netbsd"], + bsd_all : ["freebsd", "netbsd"], + android : ["android"] +} + + +def translate(values): + + if isinstance(values, six.integer_types): + # This is a value from the platform enumeration, translate it. + return __name_lookup[values] + elif isinstance(values, six.string_types): + # This is a raw string, return it. + return [values] + elif hasattr(values, "__iter__"): + # This is an iterable, convert each item. + result = [translate(x) for x in values] + result = list(itertools.chain(*result)) + return result + return values diff --git a/packages/Python/lldbsuite/test/lldbplatformutil.py b/packages/Python/lldbsuite/test/lldbplatformutil.py index f51c016c13c2..e04a5404407f 100644 --- a/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -4,12 +4,19 @@ architecture and/or the platform dependent nature of the tests. """ from __future__ import absolute_import # System modules +import itertools +import re +import subprocess +import sys # Third-party modules +import six +from six.moves.urllib import parse as urlparse # LLDB modules - -import re +from . import configuration +import use_lldb_suite +import lldb def check_first_register_readable(test_case): arch = test_case.getArchitecture() @@ -22,6 +29,120 @@ def check_first_register_readable(test_case): test_case.expect("register read x0", substrs = ['x0 = 0x']) elif re.match("mips",arch): test_case.expect("register read zero", substrs = ['zero = 0x']) + elif arch in ['s390x']: + test_case.expect("register read r0", substrs = ['r0 = 0x']) else: # TODO: Add check for other architectures test_case.fail("Unsupported architecture for test case (arch: %s)" % test_case.getArchitecture()) + +def _run_adb_command(cmd, device_id): + device_id_args = [] + if device_id: + device_id_args = ["-s", device_id] + full_cmd = ["adb"] + device_id_args + cmd + p = subprocess.Popen(full_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + return p.returncode, stdout, stderr + +def _target_is_android(): + if not hasattr(_target_is_android, 'result'): + triple = lldb.DBG.GetSelectedPlatform().GetTriple() + match = re.match(".*-.*-.*-android", triple) + _target_is_android.result = match is not None + return _target_is_android.result + +def android_device_api(): + if not hasattr(android_device_api, 'result'): + assert configuration.lldb_platform_url is not None + device_id = None + parsed_url = urlparse.urlparse(configuration.lldb_platform_url) + host_name = parsed_url.netloc.split(":")[0] + if host_name != 'localhost': + device_id = host_name + if device_id.startswith('[') and device_id.endswith(']'): + device_id = device_id[1:-1] + retcode, stdout, stderr = _run_adb_command( + ["shell", "getprop", "ro.build.version.sdk"], device_id) + if retcode == 0: + android_device_api.result = int(stdout) + else: + raise LookupError( + ">>> Unable to determine the API level of the Android device.\n" + ">>> stdout:\n%s\n" + ">>> stderr:\n%s\n" % (stdout, stderr)) + return android_device_api.result + +def match_android_device(device_arch, valid_archs=None, valid_api_levels=None): + if not _target_is_android(): + return False + if valid_archs is not None and device_arch not in valid_archs: + return False + if valid_api_levels is not None and android_device_api() not in valid_api_levels: + return False + + return True + +def finalize_build_dictionary(dictionary): + if _target_is_android(): + if dictionary is None: + dictionary = {} + dictionary["OS"] = "Android" + if android_device_api() >= 16: + dictionary["PIE"] = 1 + return dictionary + +def getHostPlatform(): + """Returns the host platform running the test suite.""" + # Attempts to return a platform name matching a target Triple platform. + if sys.platform.startswith('linux'): + return 'linux' + elif sys.platform.startswith('win32'): + return 'windows' + elif sys.platform.startswith('darwin'): + return 'darwin' + elif sys.platform.startswith('freebsd'): + return 'freebsd' + elif sys.platform.startswith('netbsd'): + return 'netbsd' + else: + return sys.platform + + +def getDarwinOSTriples(): + return ['darwin', 'macosx', 'ios'] + +def getPlatform(): + """Returns the target platform which the tests are running on.""" + platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] + if platform.startswith('freebsd'): + platform = 'freebsd' + elif platform.startswith('netbsd'): + platform = 'netbsd' + return platform + +def platformIsDarwin(): + """Returns true if the OS triple for the selected platform is any valid apple OS""" + return getPlatform() in getDarwinOSTriples() + +class _PlatformContext(object): + """Value object class which contains platform-specific options.""" + + def __init__(self, shlib_environment_var, shlib_prefix, shlib_extension): + self.shlib_environment_var = shlib_environment_var + self.shlib_prefix = shlib_prefix + self.shlib_extension = shlib_extension + +def createPlatformContext(): + if platformIsDarwin(): + return _PlatformContext('DYLD_LIBRARY_PATH', 'lib', 'dylib') + elif getPlatform() in ("freebsd", "linux", "netbsd"): + return _PlatformContext('LD_LIBRARY_PATH', 'lib', 'so') + else: + return None + +def hasChattyStderr(test_case): + """Some targets produce garbage on the standard error output. This utility function + determines whether the tests can be strict about the expected stderr contents.""" + if match_android_device(test_case.getArchitecture(), ['aarch64'], [22]): + return True # The dynamic linker on the device will complain about unknown DT entries + return False diff --git a/packages/Python/lldbsuite/test/lldbtest.py b/packages/Python/lldbsuite/test/lldbtest.py index de8f57f63706..ee876bd11169 100644 --- a/packages/Python/lldbsuite/test/lldbtest.py +++ b/packages/Python/lldbsuite/test/lldbtest.py @@ -31,39 +31,43 @@ OK $ """ -from __future__ import print_function from __future__ import absolute_import +from __future__ import print_function # System modules import abc import collections -from distutils.version import LooseVersion +from functools import wraps import gc import glob import inspect -import os, sys, traceback +import io import os.path import re import signal from subprocess import * +import sys import time +import traceback import types # Third-party modules import unittest2 from six import add_metaclass from six import StringIO as SixStringIO -from six.moves.urllib import parse as urlparse import six # LLDB modules +import use_lldb_suite import lldb from . import configuration +from . import decorators +from . import lldbplatformutil from . import lldbtest_config from . import lldbutil from . import test_categories - -from .result_formatter import EventBuilder +from lldbsuite.support import encoded_file +from lldbsuite.support import funcutils # dosep.py starts lots and lots of dotest instances # This option helps you find if two (or more) dotest instances are using the same @@ -186,10 +190,11 @@ def COMPLETION_MSG(str_before, str_after): '''A generic message generator for the completion mechanism.''' return "'%s' successfully completes to '%s'" % (str_before, str_after) -def EXP_MSG(str, exe): +def EXP_MSG(str, actual, exe): '''A generic "'%s' returns expected result" message generator if exe. Otherwise, it generates "'%s' matches expected result" message.''' - return "'%s' %s expected result" % (str, 'returns' if exe else 'matches') + + return "'%s' %s expected result, got '%s'" % (str, 'returns' if exe else 'matches', actual.strip()) def SETTING_MSG(setting): '''A generic "Value of setting '%s' is correct" message generator.''' @@ -201,7 +206,7 @@ def EnvArray(): def line_number(filename, string_to_match): """Helper function to return the line number of the first matched string.""" - with open(filename, 'r') as f: + with io.open(filename, mode='r', encoding="utf-8") as f: for i, line in enumerate(f): if line.find(string_to_match) != -1: # Found our match. @@ -414,7 +419,14 @@ def system(commands, **kwargs): cmd = kwargs.get("args") if cmd is None: cmd = shellCommand - raise CalledProcessError(retcode, cmd) + cpe = CalledProcessError(retcode, cmd) + # Ensure caller can access the stdout/stderr. + cpe.lldb_extensions = { + "stdout_content": this_output, + "stderr_content": this_error, + "command": shellCommand + } + raise cpe output = output + this_output error = error + this_error return (output, error) @@ -435,804 +447,12 @@ def builder_module(): return __import__("builder_freebsd") if sys.platform.startswith("netbsd"): return __import__("builder_netbsd") + if sys.platform.startswith("linux"): + # sys.platform with Python-3.x returns 'linux', but with + # Python-2.x it returns 'linux2'. + return __import__("builder_linux") return __import__("builder_" + sys.platform) -def run_adb_command(cmd, device_id): - device_id_args = [] - if device_id: - device_id_args = ["-s", device_id] - full_cmd = ["adb"] + device_id_args + cmd - p = Popen(full_cmd, stdout=PIPE, stderr=PIPE) - stdout, stderr = p.communicate() - return p.returncode, stdout, stderr - -def append_android_envs(dictionary): - if dictionary is None: - dictionary = {} - dictionary["OS"] = "Android" - if android_device_api() >= 16: - dictionary["PIE"] = 1 - return dictionary - -def target_is_android(): - if not hasattr(target_is_android, 'result'): - triple = lldb.DBG.GetSelectedPlatform().GetTriple() - match = re.match(".*-.*-.*-android", triple) - target_is_android.result = match is not None - return target_is_android.result - -def android_device_api(): - if not hasattr(android_device_api, 'result'): - assert configuration.lldb_platform_url is not None - device_id = None - parsed_url = urlparse.urlparse(configuration.lldb_platform_url) - host_name = parsed_url.netloc.split(":")[0] - if host_name != 'localhost': - device_id = host_name - if device_id.startswith('[') and device_id.endswith(']'): - device_id = device_id[1:-1] - retcode, stdout, stderr = run_adb_command( - ["shell", "getprop", "ro.build.version.sdk"], device_id) - if retcode == 0: - android_device_api.result = int(stdout) - else: - raise LookupError( - ">>> Unable to determine the API level of the Android device.\n" - ">>> stdout:\n%s\n" - ">>> stderr:\n%s\n" % (stdout, stderr)) - return android_device_api.result - -def check_expected_version(comparison, expected, actual): - def fn_leq(x,y): return x <= y - def fn_less(x,y): return x < y - def fn_geq(x,y): return x >= y - def fn_greater(x,y): return x > y - def fn_eq(x,y): return x == y - def fn_neq(x,y): return x != y - - op_lookup = { - "==": fn_eq, - "=": fn_eq, - "!=": fn_neq, - "<>": fn_neq, - ">": fn_greater, - "<": fn_less, - ">=": fn_geq, - "<=": fn_leq - } - expected_str = '.'.join([str(x) for x in expected]) - actual_str = '.'.join([str(x) for x in actual]) - - return op_lookup[comparison](LooseVersion(actual_str), LooseVersion(expected_str)) - -# -# Decorators for categorizing test cases. -# -from functools import wraps - -def add_test_categories(cat): - """Add test categories to a TestCase method""" - cat = test_categories.validate(cat, True) - def impl(func): - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@add_test_categories can only be used to decorate a test method") - if hasattr(func, "categories"): - cat.extend(func.categories) - func.categories = cat - return func - - return impl - -def benchmarks_test(func): - """Decorate the item as a benchmarks test.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@benchmarks_test can only be used to decorate a test method") - @wraps(func) - def wrapper(self, *args, **kwargs): - self.skipTest("benchmarks test") - return func(self, *args, **kwargs) - - # Mark this function as such to separate them from the regular tests. - wrapper.__benchmarks_test__ = True - return wrapper - -def no_debug_info_test(func): - """Decorate the item as a test what don't use any debug info. If this annotation is specified - then the test runner won't generate a separate test for each debug info format. """ - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@no_debug_info_test can only be used to decorate a test method") - @wraps(func) - def wrapper(self, *args, **kwargs): - return func(self, *args, **kwargs) - - # Mark this function as such to separate them from the regular tests. - wrapper.__no_debug_info_test__ = True - return wrapper - -def debugserver_test(func): - """Decorate the item as a debugserver test.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@debugserver_test can only be used to decorate a test method") - @wraps(func) - def wrapper(self, *args, **kwargs): - if configuration.dont_do_debugserver_test: - self.skipTest("debugserver tests") - return func(self, *args, **kwargs) - - # Mark this function as such to separate them from the regular tests. - wrapper.__debugserver_test__ = True - return wrapper - -def llgs_test(func): - """Decorate the item as a lldb-server test.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@llgs_test can only be used to decorate a test method") - @wraps(func) - def wrapper(self, *args, **kwargs): - if configuration.dont_do_llgs_test: - self.skipTest("llgs tests") - return func(self, *args, **kwargs) - - # Mark this function as such to separate them from the regular tests. - wrapper.__llgs_test__ = True - return wrapper - -def not_remote_testsuite_ready(func): - """Decorate the item as a test which is not ready yet for remote testsuite.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@not_remote_testsuite_ready can only be used to decorate a test method") - @wraps(func) - def wrapper(self, *args, **kwargs): - if lldb.remote_platform: - self.skipTest("not ready for remote testsuite") - return func(self, *args, **kwargs) - - # Mark this function as such to separate them from the regular tests. - wrapper.__not_ready_for_remote_testsuite_test__ = True - return wrapper - -def expectedFailure(expected_fn, bugnumber=None): - def expectedFailure_impl(func): - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - if expected_fn(self): - if configuration.results_formatter_object is not None: - # Mark this test as expected to fail. - configuration.results_formatter_object.handle_event( - EventBuilder.event_for_mark_test_expected_failure(self)) - xfail_func = unittest2.expectedFailure(func) - xfail_func(*args, **kwargs) - else: - func(*args, **kwargs) - return wrapper - # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments - # return decorator in this case, so it will be used to decorating original method - if six.callable(bugnumber): - return expectedFailure_impl(bugnumber) - else: - return expectedFailure_impl - -# You can also pass not_in(list) to reverse the sense of the test for the arguments that -# are simple lists, namely oslist, compiler, and debug_info. - -def not_in(iterable): - return lambda x : x not in iterable - -def check_list_or_lambda(list_or_lambda, value): - if six.callable(list_or_lambda): - return list_or_lambda(value) - elif isinstance(list_or_lambda, list): - for item in list_or_lambda: - if value in item: - return True - return False - elif isinstance(list_or_lambda, str): - return value is None or value in list_or_lambda - else: - return list_or_lambda is None or value is None or list_or_lambda == value - -def matchArchitectures(archs, actual_arch): - retype = type(re.compile('hello, world')) - list_passes = isinstance(archs, list) and actual_arch in archs - basestring_passes = isinstance(archs, six.string_types) and actual_arch == archs - regex_passes = isinstance(archs, retype) and re.match(archs, actual_arch) - - return (list_passes or basestring_passes or regex_passes) - -# provide a function to xfail on defined oslist, compiler version, and archs -# if none is specified for any argument, that argument won't be checked and thus means for all -# for example, -# @expectedFailureAll, xfail for all platform/compiler/arch, -# @expectedFailureAll(compiler='gcc'), xfail for gcc on all platform/architecture -# @expectedFailureAll(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), xfail for gcc>=4.9 on linux with i386 -def expectedFailureAll(bugnumber=None, oslist=None, hostoslist=None, compiler=None, compiler_version=None, archs=None, triple=None, debug_info=None, swig_version=None, py_version=None): - def fn(self): - oslist_passes = check_list_or_lambda(oslist, self.getPlatform()) - hostoslist_passes = check_list_or_lambda(hostoslist, getHostPlatform()) - compiler_passes = check_list_or_lambda(self.getCompiler(), compiler) and self.expectedCompilerVersion(compiler_version) - arch_passes = check_list_or_lambda(archs, self.getArchitecture()) - triple_passes = triple is None or re.match(triple, lldb.DBG.GetSelectedPlatform().GetTriple()) - debug_info_passes = check_list_or_lambda(debug_info, self.debug_info) - swig_version_passes = (swig_version is None) or (not hasattr(lldb, 'swig_version')) or (check_expected_version(swig_version[0], swig_version[1], lldb.swig_version)) - py_version_passes = (py_version is None) or check_expected_version(py_version[0], py_version[1], sys.version_info) - - return (oslist_passes and - hostoslist_passes and - compiler_passes and - arch_passes and - triple_passes and - debug_info_passes and - swig_version_passes and - py_version_passes) - return expectedFailure(fn, bugnumber) - -def expectedFailureDwarf(bugnumber=None): - return expectedFailureAll(bugnumber=bugnumber, debug_info="dwarf") - -def expectedFailureDwo(bugnumber=None): - return expectedFailureAll(bugnumber=bugnumber, debug_info="dwo") - -def expectedFailureDsym(bugnumber=None): - return expectedFailureAll(bugnumber=bugnumber, debug_info="dsym") - -def expectedFailureCompiler(compiler, compiler_version=None, bugnumber=None): - if compiler_version is None: - compiler_version=['=', None] - return expectedFailureAll(bugnumber=bugnumber, compiler=compiler, compiler_version=compiler_version) - -# to XFAIL a specific clang versions, try this -# @expectedFailureClang('bugnumber', ['<=', '3.4']) -def expectedFailureClang(bugnumber=None, compiler_version=None): - return expectedFailureCompiler('clang', compiler_version, bugnumber) - -def expectedFailureGcc(bugnumber=None, compiler_version=None): - return expectedFailureCompiler('gcc', compiler_version, bugnumber) - -def expectedFailureIcc(bugnumber=None): - return expectedFailureCompiler('icc', None, bugnumber) - -def expectedFailureArch(arch, bugnumber=None): - def fn(self): - return arch in self.getArchitecture() - return expectedFailure(fn, bugnumber) - -def expectedFailurei386(bugnumber=None): - return expectedFailureArch('i386', bugnumber) - -def expectedFailurex86_64(bugnumber=None): - return expectedFailureArch('x86_64', bugnumber) - -def expectedFailureOS(oslist, bugnumber=None, compilers=None, debug_info=None, archs=None): - def fn(self): - return (self.getPlatform() in oslist and - self.expectedCompiler(compilers) and - (archs is None or self.getArchitecture() in archs) and - (debug_info is None or self.debug_info in debug_info)) - return expectedFailure(fn, bugnumber) - -def expectedFailureHostOS(oslist, bugnumber=None, compilers=None): - def fn(self): - return (getHostPlatform() in oslist and - self.expectedCompiler(compilers)) - return expectedFailure(fn, bugnumber) - -def expectedFailureDarwin(bugnumber=None, compilers=None, debug_info=None): - # For legacy reasons, we support both "darwin" and "macosx" as OS X triples. - return expectedFailureOS(getDarwinOSTriples(), bugnumber, compilers, debug_info=debug_info) - -def expectedFailureFreeBSD(bugnumber=None, compilers=None, debug_info=None): - return expectedFailureOS(['freebsd'], bugnumber, compilers, debug_info=debug_info) - -def expectedFailureLinux(bugnumber=None, compilers=None, debug_info=None, archs=None): - return expectedFailureOS(['linux'], bugnumber, compilers, debug_info=debug_info, archs=archs) - -def expectedFailureNetBSD(bugnumber=None, compilers=None, debug_info=None): - return expectedFailureOS(['netbsd'], bugnumber, compilers, debug_info=debug_info) - -def expectedFailureWindows(bugnumber=None, compilers=None, debug_info=None): - return expectedFailureOS(['windows'], bugnumber, compilers, debug_info=debug_info) - -def expectedFailureHostWindows(bugnumber=None, compilers=None): - return expectedFailureHostOS(['windows'], bugnumber, compilers) - -def matchAndroid(api_levels=None, archs=None): - def match(self): - if not target_is_android(): - return False - if archs is not None and self.getArchitecture() not in archs: - return False - if api_levels is not None and android_device_api() not in api_levels: - return False - return True - return match - - -def expectedFailureAndroid(bugnumber=None, api_levels=None, archs=None): - """ Mark a test as xfail for Android. - - Arguments: - bugnumber - The LLVM pr associated with the problem. - api_levels - A sequence of numbers specifying the Android API levels - for which a test is expected to fail. None means all API level. - arch - A sequence of architecture names specifying the architectures - for which a test is expected to fail. None means all architectures. - """ - return expectedFailure(matchAndroid(api_levels, archs), bugnumber) - -# Flakey tests get two chances to run. If they fail the first time round, the result formatter -# makes sure it is run one more time. -def expectedFlakey(expected_fn, bugnumber=None): - def expectedFailure_impl(func): - @wraps(func) - def wrapper(*args, **kwargs): - self = args[0] - if expected_fn(self): - # Send event marking test as explicitly eligible for rerunning. - if configuration.results_formatter_object is not None: - # Mark this test as rerunnable. - configuration.results_formatter_object.handle_event( - EventBuilder.event_for_mark_test_rerun_eligible(self)) - func(*args, **kwargs) - return wrapper - # if bugnumber is not-callable(incluing None), that means decorator function is called with optional arguments - # return decorator in this case, so it will be used to decorating original method - if six.callable(bugnumber): - return expectedFailure_impl(bugnumber) - else: - return expectedFailure_impl - -def expectedFlakeyDwarf(bugnumber=None): - def fn(self): - return self.debug_info == "dwarf" - return expectedFlakey(fn, bugnumber) - -def expectedFlakeyDsym(bugnumber=None): - def fn(self): - return self.debug_info == "dwarf" - return expectedFlakey(fn, bugnumber) - -def expectedFlakeyOS(oslist, bugnumber=None, compilers=None): - def fn(self): - return (self.getPlatform() in oslist and - self.expectedCompiler(compilers)) - return expectedFlakey(fn, bugnumber) - -def expectedFlakeyDarwin(bugnumber=None, compilers=None): - # For legacy reasons, we support both "darwin" and "macosx" as OS X triples. - return expectedFlakeyOS(getDarwinOSTriples(), bugnumber, compilers) - -def expectedFlakeyFreeBSD(bugnumber=None, compilers=None): - return expectedFlakeyOS(['freebsd'], bugnumber, compilers) - -def expectedFlakeyLinux(bugnumber=None, compilers=None): - return expectedFlakeyOS(['linux'], bugnumber, compilers) - -def expectedFlakeyNetBSD(bugnumber=None, compilers=None): - return expectedFlakeyOS(['netbsd'], bugnumber, compilers) - -def expectedFlakeyCompiler(compiler, compiler_version=None, bugnumber=None): - if compiler_version is None: - compiler_version=['=', None] - def fn(self): - return compiler in self.getCompiler() and self.expectedCompilerVersion(compiler_version) - return expectedFlakey(fn, bugnumber) - -# @expectedFlakeyClang('bugnumber', ['<=', '3.4']) -def expectedFlakeyClang(bugnumber=None, compiler_version=None): - return expectedFlakeyCompiler('clang', compiler_version, bugnumber) - -# @expectedFlakeyGcc('bugnumber', ['<=', '3.4']) -def expectedFlakeyGcc(bugnumber=None, compiler_version=None): - return expectedFlakeyCompiler('gcc', compiler_version, bugnumber) - -def expectedFlakeyAndroid(bugnumber=None, api_levels=None, archs=None): - return expectedFlakey(matchAndroid(api_levels, archs), bugnumber) - -def skipIfRemote(func): - """Decorate the item to skip tests if testing remotely.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfRemote can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - if lldb.remote_platform: - self = args[0] - self.skipTest("skip on remote platform") - else: - func(*args, **kwargs) - return wrapper - -def skipUnlessListedRemote(remote_list=None): - def myImpl(func): - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfRemote can only be used to decorate a " - "test method") - - @wraps(func) - def wrapper(*args, **kwargs): - if remote_list and lldb.remote_platform: - self = args[0] - triple = self.dbg.GetSelectedPlatform().GetTriple() - for r in remote_list: - if r in triple: - func(*args, **kwargs) - return - self.skipTest("skip on remote platform %s" % str(triple)) - else: - func(*args, **kwargs) - return wrapper - - return myImpl - -def skipIfRemoteDueToDeadlock(func): - """Decorate the item to skip tests if testing remotely due to the test deadlocking.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfRemote can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - if lldb.remote_platform: - self = args[0] - self.skipTest("skip on remote platform (deadlocks)") - else: - func(*args, **kwargs) - return wrapper - -def skipIfNoSBHeaders(func): - """Decorate the item to mark tests that should be skipped when LLDB is built with no SB API headers.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfNoSBHeaders can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - if sys.platform.startswith("darwin"): - header = os.path.join(os.environ["LLDB_LIB_DIR"], 'LLDB.framework', 'Versions','Current','Headers','LLDB.h') - else: - header = os.path.join(os.environ["LLDB_SRC"], "include", "lldb", "API", "LLDB.h") - platform = sys.platform - if not os.path.exists(header): - self.skipTest("skip because LLDB.h header not found") - else: - func(*args, **kwargs) - return wrapper - -def skipIfiOSSimulator(func): - """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" - return unittest2.skipIf(configuration.lldb_platform_name == 'ios-simulator', 'skip on the iOS Simulator')(func) - -def skipIfFreeBSD(func): - """Decorate the item to skip tests that should be skipped on FreeBSD.""" - return skipIfPlatform(["freebsd"])(func) - -def skipIfNetBSD(func): - """Decorate the item to skip tests that should be skipped on NetBSD.""" - return skipIfPlatform(["netbsd"])(func) - -def getDarwinOSTriples(): - return ['darwin', 'macosx', 'ios'] - -def skipIfDarwin(func): - """Decorate the item to skip tests that should be skipped on Darwin.""" - return skipIfPlatform(getDarwinOSTriples())(func) - -def skipIfLinux(func): - """Decorate the item to skip tests that should be skipped on Linux.""" - return skipIfPlatform(["linux"])(func) - -def skipUnlessHostLinux(func): - """Decorate the item to skip tests that should be skipped on any non Linux host.""" - return skipUnlessHostPlatform(["linux"])(func) - -def skipIfWindows(func): - """Decorate the item to skip tests that should be skipped on Windows.""" - return skipIfPlatform(["windows"])(func) - -def skipIfHostWindows(func): - """Decorate the item to skip tests that should be skipped on Windows.""" - return skipIfHostPlatform(["windows"])(func) - -def skipUnlessWindows(func): - """Decorate the item to skip tests that should be skipped on any non-Windows platform.""" - return skipUnlessPlatform(["windows"])(func) - -def skipUnlessDarwin(func): - """Decorate the item to skip tests that should be skipped on any non Darwin platform.""" - return skipUnlessPlatform(getDarwinOSTriples())(func) - -def skipUnlessGoInstalled(func): - """Decorate the item to skip tests when no Go compiler is available.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfGcc can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - compiler = self.getGoCompilerVersion() - if not compiler: - self.skipTest("skipping because go compiler not found") - else: - # Ensure the version is the minimum version supported by - # the LLDB go support. - match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler) - if not match_version: - # Couldn't determine version. - self.skipTest( - "skipping because go version could not be parsed " - "out of {}".format(compiler)) - else: - from distutils.version import StrictVersion - min_strict_version = StrictVersion("1.4.0") - compiler_strict_version = StrictVersion(match_version.group(1)) - if compiler_strict_version < min_strict_version: - self.skipTest( - "skipping because available go version ({}) does " - "not meet minimum required go version ({})".format( - compiler_strict_version, - min_strict_version)) - func(*args, **kwargs) - return wrapper - -def getPlatform(): - """Returns the target platform which the tests are running on.""" - platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] - if platform.startswith('freebsd'): - platform = 'freebsd' - elif platform.startswith('netbsd'): - platform = 'netbsd' - return platform - -def getHostPlatform(): - """Returns the host platform running the test suite.""" - # Attempts to return a platform name matching a target Triple platform. - if sys.platform.startswith('linux'): - return 'linux' - elif sys.platform.startswith('win32'): - return 'windows' - elif sys.platform.startswith('darwin'): - return 'darwin' - elif sys.platform.startswith('freebsd'): - return 'freebsd' - elif sys.platform.startswith('netbsd'): - return 'netbsd' - else: - return sys.platform - -def platformIsDarwin(): - """Returns true if the OS triple for the selected platform is any valid apple OS""" - return getPlatform() in getDarwinOSTriples() - -def skipIfHostIncompatibleWithRemote(func): - """Decorate the item to skip tests if binaries built on this host are incompatible.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfHostIncompatibleWithRemote can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - host_arch = self.getLldbArchitecture() - host_platform = getHostPlatform() - target_arch = self.getArchitecture() - target_platform = 'darwin' if self.platformIsDarwin() else self.getPlatform() - if not (target_arch == 'x86_64' and host_arch == 'i386') and host_arch != target_arch: - self.skipTest("skipping because target %s is not compatible with host architecture %s" % (target_arch, host_arch)) - elif target_platform != host_platform: - self.skipTest("skipping because target is %s but host is %s" % (target_platform, host_platform)) - else: - func(*args, **kwargs) - return wrapper - -def skipIfHostPlatform(oslist): - """Decorate the item to skip tests if running on one of the listed host platforms.""" - return unittest2.skipIf(getHostPlatform() in oslist, - "skip on %s" % (", ".join(oslist))) - -def skipUnlessHostPlatform(oslist): - """Decorate the item to skip tests unless running on one of the listed host platforms.""" - return unittest2.skipUnless(getHostPlatform() in oslist, - "requires on of %s" % (", ".join(oslist))) - -def skipUnlessArch(archs): - """Decorate the item to skip tests unless running on one of the listed architectures.""" - def myImpl(func): - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipUnlessArch can only be used to decorate a test method") - - @wraps(func) - def wrapper(*args, **kwargs): - self = args[0] - if not matchArchitectures(archs, self.getArchitecture()): - self.skipTest("skipping for architecture %s" % (self.getArchitecture())) - else: - func(*args, **kwargs) - return wrapper - - return myImpl - -def skipIfPlatform(oslist): - """Decorate the item to skip tests if running on one of the listed platforms.""" - return unittest2.skipIf(getPlatform() in oslist, - "skip on %s" % (", ".join(oslist))) - -def skipUnlessPlatform(oslist): - """Decorate the item to skip tests unless running on one of the listed platforms.""" - return unittest2.skipUnless(getPlatform() in oslist, - "requires on of %s" % (", ".join(oslist))) - -def skipIfLinuxClang(func): - """Decorate the item to skip tests that should be skipped if building on - Linux with clang. - """ - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfLinuxClang can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - compiler = self.getCompiler() - platform = self.getPlatform() - if "clang" in compiler and platform == "linux": - self.skipTest("skipping because Clang is used on Linux") - else: - func(*args, **kwargs) - return wrapper - -# provide a function to skip on defined oslist, compiler version, and archs -# if none is specified for any argument, that argument won't be checked and thus means for all -# for example, -# @skipIf, skip for all platform/compiler/arch, -# @skipIf(compiler='gcc'), skip for gcc on all platform/architecture -# @skipIf(bugnumber, ["linux"], "gcc", ['>=', '4.9'], ['i386']), skip for gcc>=4.9 on linux with i386 - -# TODO: refactor current code, to make skipIfxxx functions to call this function -def skipIf(bugnumber=None, oslist=None, compiler=None, compiler_version=None, archs=None, debug_info=None, swig_version=None, py_version=None, remote=None): - def fn(self): - oslist_passes = check_list_or_lambda(oslist, self.getPlatform()) - compiler_passes = check_list_or_lambda(self.getCompiler(), compiler) and self.expectedCompilerVersion(compiler_version) - arch_passes = check_list_or_lambda(archs, self.getArchitecture()) - debug_info_passes = check_list_or_lambda(debug_info, self.debug_info) - swig_version_passes = (swig_version is None) or (not hasattr(lldb, 'swig_version')) or (check_expected_version(swig_version[0], swig_version[1], lldb.swig_version)) - py_version_passes = (py_version is None) or check_expected_version(py_version[0], py_version[1], sys.version_info) - remote_passes = (remote is None) or (remote == (lldb.remote_platform is not None)) - - return (oslist_passes and - compiler_passes and - arch_passes and - debug_info_passes and - swig_version_passes and - py_version_passes and - remote_passes) - - local_vars = locals() - args = [x for x in inspect.getargspec(skipIf).args] - arg_vals = [eval(x, globals(), local_vars) for x in args] - args = [x for x in zip(args, arg_vals) if x[1] is not None] - reasons = ['%s=%s' % (x, str(y)) for (x,y) in args] - return skipTestIfFn(fn, bugnumber, skipReason='skipping because ' + ' && '.join(reasons)) - -def skipIfDebugInfo(bugnumber=None, debug_info=None): - return skipIf(bugnumber=bugnumber, debug_info=debug_info) - -def skipIfDWO(bugnumber=None): - return skipIfDebugInfo(bugnumber, ["dwo"]) - -def skipIfDwarf(bugnumber=None): - return skipIfDebugInfo(bugnumber, ["dwarf"]) - -def skipIfDsym(bugnumber=None): - return skipIfDebugInfo(bugnumber, ["dsym"]) - -def skipTestIfFn(expected_fn, bugnumber=None, skipReason=None): - def skipTestIfFn_impl(func): - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - if expected_fn(self): - self.skipTest(skipReason) - else: - func(*args, **kwargs) - return wrapper - if six.callable(bugnumber): - return skipTestIfFn_impl(bugnumber) - else: - return skipTestIfFn_impl - -def skipIfGcc(func): - """Decorate the item to skip tests that should be skipped if building with gcc .""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfGcc can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - compiler = self.getCompiler() - if "gcc" in compiler: - self.skipTest("skipping because gcc is the test compiler") - else: - func(*args, **kwargs) - return wrapper - -def skipIfIcc(func): - """Decorate the item to skip tests that should be skipped if building with icc .""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfIcc can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - compiler = self.getCompiler() - if "icc" in compiler: - self.skipTest("skipping because icc is the test compiler") - else: - func(*args, **kwargs) - return wrapper - -def skipIfi386(func): - """Decorate the item to skip tests that should be skipped if building 32-bit.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfi386 can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - if "i386" == self.getArchitecture(): - self.skipTest("skipping because i386 is not a supported architecture") - else: - func(*args, **kwargs) - return wrapper - -def skipIfTargetAndroid(api_levels=None, archs=None): - """Decorator to skip tests when the target is Android. - - Arguments: - api_levels - The API levels for which the test should be skipped. If - it is None, then the test will be skipped for all API levels. - arch - A sequence of architecture names specifying the architectures - for which a test is skipped. None means all architectures. - """ - def myImpl(func): - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipIfTargetAndroid can only be used to " - "decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - self = args[0] - if matchAndroid(api_levels, archs)(self): - self.skipTest("skiped on Android target with API %d and architecture %s" % - (android_device_api(), self.getArchitecture())) - func(*args, **kwargs) - return wrapper - return myImpl - -def skipUnlessCompilerRt(func): - """Decorate the item to skip tests if testing remotely.""" - if isinstance(func, type) and issubclass(func, unittest2.TestCase): - raise Exception("@skipUnless can only be used to decorate a test method") - @wraps(func) - def wrapper(*args, **kwargs): - from unittest2 import case - import os.path - compilerRtPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "llvm","projects","compiler-rt") - print(compilerRtPath) - if not os.path.exists(compilerRtPath): - self = args[0] - self.skipTest("skip if compiler-rt not found") - else: - func(*args, **kwargs) - return wrapper - -class _PlatformContext(object): - """Value object class which contains platform-specific options.""" - - def __init__(self, shlib_environment_var, shlib_prefix, shlib_extension): - self.shlib_environment_var = shlib_environment_var - self.shlib_prefix = shlib_prefix - self.shlib_extension = shlib_extension - class Base(unittest2.TestCase): """ @@ -1298,12 +518,7 @@ class Base(unittest2.TestCase): raise ioerror # Set platform context. - if platformIsDarwin(): - cls.platformContext = _PlatformContext('DYLD_LIBRARY_PATH', 'lib', 'dylib') - elif getPlatform() in ("freebsd", "linux", "netbsd"): - cls.platformContext = _PlatformContext('LD_LIBRARY_PATH', 'lib', 'so') - else: - cls.platformContext = None + cls.platformContext = lldbplatformutil.createPlatformContext() @classmethod def tearDownClass(cls): @@ -1368,7 +583,7 @@ class Base(unittest2.TestCase): else: categories = "default" - if channel == "gdb-remote": + if channel == "gdb-remote" and lldb.remote_platform is None: # communicate gdb-remote categories to debugserver os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories @@ -1377,15 +592,17 @@ class Base(unittest2.TestCase): raise Exception('log enable failed (check LLDB_LOG_OPTION env variable)') # Communicate log path name to debugserver & lldb-server - server_log_path = "{}-server.log".format(log_basename) - open(server_log_path, 'w').close() - os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path + # For remote debugging, these variables need to be set when starting the platform + # instance. + if lldb.remote_platform is None: + server_log_path = "{}-server.log".format(log_basename) + open(server_log_path, 'w').close() + os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path - # Communicate channels to lldb-server - os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config.channels) + # Communicate channels to lldb-server + os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config.channels) - if len(lldbtest_config.channels) == 0: - return + self.addTearDownHook(self.disableLogChannelsForCurrentTest) def disableLogChannelsForCurrentTest(self): # close all log files that we opened @@ -1396,6 +613,42 @@ class Base(unittest2.TestCase): if not self.res.Succeeded(): raise Exception('log disable failed (check LLDB_LOG_OPTION env variable)') + # Retrieve the server log (if any) from the remote system. It is assumed the server log + # is writing to the "server.log" file in the current test directory. This can be + # achieved by setting LLDB_DEBUGSERVER_LOG_FILE="server.log" when starting remote + # platform. If the remote logging is not enabled, then just let the Get() command silently + # fail. + if lldb.remote_platform: + lldb.remote_platform.Get(lldb.SBFileSpec("server.log"), + lldb.SBFileSpec(self.getLogBasenameForCurrentTest()+"-server.log")) + + def setPlatformWorkingDir(self): + if not lldb.remote_platform or not configuration.lldb_platform_working_dir: + return + + remote_test_dir = lldbutil.join_remote_paths( + configuration.lldb_platform_working_dir, + self.getArchitecture(), + str(self.test_number), + self.mydir) + error = lldb.remote_platform.MakeDirectory(remote_test_dir, 448) # 448 = 0o700 + if error.Success(): + lldb.remote_platform.SetWorkingDirectory(remote_test_dir) + + # This function removes all files from the current working directory while leaving + # the directories in place. The cleaup is required to reduce the disk space required + # by the test suit while leaving the directories untached is neccessary because + # sub-directories might belong to an other test + def clean_working_directory(): + # TODO: Make it working on Windows when we need it for remote debugging support + # TODO: Replace the heuristic to remove the files with a logic what collects the + # list of files we have to remove during test runs. + shell_cmd = lldb.SBPlatformShellCommand("rm %s/*" % remote_test_dir) + lldb.remote_platform.Run(shell_cmd) + self.addTearDownHook(clean_working_directory) + else: + print("error: making remote directory '%s': %s" % (remote_test_dir, error)) + def setUp(self): """Fixture for unittest test case setup. @@ -1458,7 +711,7 @@ class Base(unittest2.TestCase): session_file = "{}.log".format(self.log_basename) # Python 3 doesn't support unbuffered I/O in text mode. Open buffered. - self.session = open(session_file, "w") + self.session = encoded_file.open(session_file, "utf-8", mode="w") # Optimistically set __errored__, __failed__, __expected__ to False # initially. If the test errored/failed, the session info @@ -1501,6 +754,7 @@ class Base(unittest2.TestCase): # And the result object. self.res = lldb.SBCommandReturnObject() + self.setPlatformWorkingDir() self.enableLogChannelsForCurrentTest() #Initialize debug_info @@ -1652,11 +906,7 @@ class Base(unittest2.TestCase): for hook in reversed(self.hooks): with recording(self, traceAlways) as sbuf: print("Executing tearDown hook:", getsource_if_available(hook), file=sbuf) - import inspect - hook_argc = len(inspect.getargspec(hook).args) - if hook_argc == 0 or getattr(hook,'im_self',None): - hook() - elif hook_argc == 1: + if funcutils.requires_self(hook): hook(self) else: hook() # try the plain call and hope it works @@ -1673,8 +923,6 @@ class Base(unittest2.TestCase): for dict in reversed(self.dicts): self.cleanup(dictionary=dict) - self.disableLogChannelsForCurrentTest() - # ========================================================= # Various callbacks to allow introspection of test progress # ========================================================= @@ -1751,19 +999,27 @@ class Base(unittest2.TestCase): if not os.path.isdir(dname): os.mkdir(dname) - compiler = self.getCompiler() - - if compiler[1] == ':': - compiler = compiler[2:] - if os.path.altsep is not None: - compiler = compiler.replace(os.path.altsep, os.path.sep) - - fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), "_".join(compiler.split(os.path.sep))) - if len(fname) > 200: - fname = "{}-{}-{}".format(self.id(), self.getArchitecture(), compiler.split(os.path.sep)[-1]) - + components = [] if prefix is not None: - fname = "{}-{}".format(prefix, fname) + components.append(prefix) + for c in configuration.session_file_format: + if c == 'f': + components.append(self.__class__.__module__) + elif c == 'n': + components.append(self.__class__.__name__) + elif c == 'c': + compiler = self.getCompiler() + + if compiler[1] == ':': + compiler = compiler[2:] + if os.path.altsep is not None: + compiler = compiler.replace(os.path.altsep, os.path.sep) + components.extend([x for x in compiler.split(os.path.sep) if x != ""]) + elif c == 'a': + components.append(self.getArchitecture()) + elif c == 'm': + components.append(self.testMethodName) + fname = "-".join(components) return os.path.join(dname, fname) @@ -1844,23 +1100,13 @@ class Base(unittest2.TestCase): # it silently replaces the destination. Ultimately this means that atomic renames are not # guaranteed to be possible on Windows, but we need this to work anyway, so just remove the # destination first if it already exists. - os.remove(dst) + remove_file(dst) os.rename(src, dst) else: # success! (and we don't want log files) delete log files for log_file in log_files_for_this_test: - try: - os.unlink(log_file) - except: - # We've seen consistent unlink failures on Windows, perhaps because the - # just-created log file is being scanned by anti-virus. Empirically, this - # sleep-and-retry approach allows tests to succeed much more reliably. - # Attempts to figure out exactly what process was still holding a file handle - # have failed because running instrumentation like Process Monitor seems to - # slow things down enough that the problem becomes much less consistent. - time.sleep(0.5) - os.unlink(log_file) + remove_file(log_file) # ==================================================== # Config. methods supported through a plugin interface @@ -1912,11 +1158,10 @@ class Base(unittest2.TestCase): """ Returns a string that represents the compiler version. Supports: llvm, clang. """ - from .lldbutil import which version = 'unknown' compiler = self.getCompilerBinary() - version_output = system([[which(compiler), "-v"]])[1] + version_output = system([[compiler, "-v"]])[1] for line in version_output.split(os.linesep): m = re.search('version ([0-9\.]+)', line) if m: @@ -1937,11 +1182,11 @@ class Base(unittest2.TestCase): def platformIsDarwin(self): """Returns true if the OS triple for the selected platform is any valid apple OS""" - return platformIsDarwin() + return lldbplatformutil.platformIsDarwin() def getPlatform(self): """Returns the target platform the test suite is running on.""" - return getPlatform() + return lldbplatformutil.getPlatform() def isIntelCompiler(self): """ Returns true if using an Intel (ICC) compiler, false otherwise. """ @@ -2097,8 +1342,7 @@ class Base(unittest2.TestCase): def buildDefault(self, architecture=None, compiler=None, dictionary=None, clean=True): """Platform specific way to build the default binaries.""" module = builder_module() - if target_is_android(): - dictionary = append_android_envs(dictionary) + dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) if not module.buildDefault(self, architecture, compiler, dictionary, clean): raise Exception("Don't know how to build default binary") @@ -2111,19 +1355,23 @@ class Base(unittest2.TestCase): def buildDwarf(self, architecture=None, compiler=None, dictionary=None, clean=True): """Platform specific way to build binaries with dwarf maps.""" module = builder_module() - if target_is_android(): - dictionary = append_android_envs(dictionary) + dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) if not module.buildDwarf(self, architecture, compiler, dictionary, clean): raise Exception("Don't know how to build binary with dwarf") def buildDwo(self, architecture=None, compiler=None, dictionary=None, clean=True): """Platform specific way to build binaries with dwarf maps.""" module = builder_module() - if target_is_android(): - dictionary = append_android_envs(dictionary) + dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) if not module.buildDwo(self, architecture, compiler, dictionary, clean): raise Exception("Don't know how to build binary with dwo") + def buildGModules(self, architecture=None, compiler=None, dictionary=None, clean=True): + """Platform specific way to build binaries with gmodules info.""" + module = builder_module() + if not module.buildGModules(self, architecture, compiler, dictionary, clean): + raise Exception("Don't know how to build binary with gmodules") + def buildGo(self): """Build the default go binary. """ @@ -2221,9 +1469,15 @@ class Base(unittest2.TestCase): # Metaclass for TestBase to change the list of test metods when a new TestCase is loaded. # We change the test methods to create a new test method for each test for each debug info we are # testing. The name of the new test method will be '_' and with adding -# the new test method we remove the old method at the same time. +# the new test method we remove the old method at the same time. This functionality can be +# supressed by at test case level setting the class attribute NO_DEBUG_INFO_TESTCASE or at test +# level by using the decorator @no_debug_info_test. class LLDBTestCaseFactory(type): def __new__(cls, name, bases, attrs): + original_testcase = super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, attrs) + if original_testcase.NO_DEBUG_INFO_TESTCASE: + return original_testcase + newattrs = {} for attrname, attrvalue in attrs.items(): if attrname.startswith("test") and not getattr(attrvalue, "__no_debug_info_test__", False): @@ -2236,10 +1490,11 @@ class LLDBTestCaseFactory(type): if not categories: categories = all_dbginfo_categories - supported_categories = [x for x in categories - if test_categories.is_supported_on_platform(x, target_platform)] + supported_categories = [x for x in categories + if test_categories.is_supported_on_platform( + x, target_platform, configuration.compilers)] if "dsym" in supported_categories: - @add_test_categories(["dsym"]) + @decorators.add_test_categories(["dsym"]) @wraps(attrvalue) def dsym_test_method(self, attrvalue=attrvalue): self.debug_info = "dsym" @@ -2249,7 +1504,7 @@ class LLDBTestCaseFactory(type): newattrs[dsym_method_name] = dsym_test_method if "dwarf" in supported_categories: - @add_test_categories(["dwarf"]) + @decorators.add_test_categories(["dwarf"]) @wraps(attrvalue) def dwarf_test_method(self, attrvalue=attrvalue): self.debug_info = "dwarf" @@ -2259,7 +1514,7 @@ class LLDBTestCaseFactory(type): newattrs[dwarf_method_name] = dwarf_test_method if "dwo" in supported_categories: - @add_test_categories(["dwo"]) + @decorators.add_test_categories(["dwo"]) @wraps(attrvalue) def dwo_test_method(self, attrvalue=attrvalue): self.debug_info = "dwo" @@ -2267,6 +1522,17 @@ class LLDBTestCaseFactory(type): dwo_method_name = attrname + "_dwo" dwo_test_method.__name__ = dwo_method_name newattrs[dwo_method_name] = dwo_test_method + + if "gmodules" in supported_categories: + @decorators.add_test_categories(["gmodules"]) + @wraps(attrvalue) + def gmodules_test_method(self, attrvalue=attrvalue): + self.debug_info = "gmodules" + return attrvalue(self) + gmodules_method_name = attrname + "_gmodules" + gmodules_test_method.__name__ = gmodules_method_name + newattrs[gmodules_method_name] = gmodules_test_method + else: newattrs[attrname] = attrvalue return super(LLDBTestCaseFactory, cls).__new__(cls, name, bases, newattrs) @@ -2325,6 +1591,10 @@ class TestBase(Base): Mac OS X implementation is located in plugins/darwin.py. """ + # Subclasses can set this to true (if they don't depend on debug info) to avoid running the + # test multiple times with various debug info types. + NO_DEBUG_INFO_TESTCASE = False + # Maximum allowed attempts when launching the inferior process. # Can be overridden by the LLDB_MAX_LAUNCH_COUNT environment variable. maxLaunchCount = 3; @@ -2381,30 +1651,6 @@ class TestBase(Base): # And the result object. self.res = lldb.SBCommandReturnObject() - if lldb.remote_platform and configuration.lldb_platform_working_dir: - remote_test_dir = lldbutil.join_remote_paths( - configuration.lldb_platform_working_dir, - self.getArchitecture(), - str(self.test_number), - self.mydir) - error = lldb.remote_platform.MakeDirectory(remote_test_dir, 448) # 448 = 0o700 - if error.Success(): - lldb.remote_platform.SetWorkingDirectory(remote_test_dir) - - # This function removes all files from the current working directory while leaving - # the directories in place. The cleaup is required to reduce the disk space required - # by the test suit while leaving the directories untached is neccessary because - # sub-directories might belong to an other test - def clean_working_directory(): - # TODO: Make it working on Windows when we need it for remote debugging support - # TODO: Replace the heuristic to remove the files with a logic what collects the - # list of files we have to remove during test runs. - shell_cmd = lldb.SBPlatformShellCommand("rm %s/*" % remote_test_dir) - lldb.remote_platform.Run(shell_cmd) - self.addTearDownHook(clean_working_directory) - else: - print("error: making remote directory '%s': %s" % (remote_test_dir, error)) - def registerSharedLibrariesWithTarget(self, target, shlibs): '''If we are remotely running the test suite, register the shared libraries with the target so they get uploaded, otherwise do nothing @@ -2608,7 +1854,7 @@ class TestBase(Base): break self.assertTrue(matched if matching else not matched, - msg if msg else EXP_MSG(str, exe)) + msg if msg else EXP_MSG(str, output, exe)) return match_object @@ -2682,10 +1928,10 @@ class TestBase(Base): # Look for sub strings, if specified. keepgoing = matched if matching else not matched if substrs and keepgoing: - for str in substrs: - matched = output.find(str) != -1 + for substr in substrs: + matched = output.find(substr) != -1 with recording(self, trace) as sbuf: - print("%s sub string: %s" % (heading, str), file=sbuf) + print("%s sub string: %s" % (heading, substr), file=sbuf) print("Matched" if matched else "Not matched", file=sbuf) keepgoing = matched if matching else not matched if not keepgoing: @@ -2705,7 +1951,7 @@ class TestBase(Base): break self.assertTrue(matched if matching else not matched, - msg if msg else EXP_MSG(str, exe)) + msg if msg else EXP_MSG(str, output, exe)) def invoke(self, obj, name, trace=False): """Use reflection to call a method dynamically with no argument.""" @@ -2723,8 +1969,7 @@ class TestBase(Base): def build(self, architecture=None, compiler=None, dictionary=None, clean=True): """Platform specific way to build the default binaries.""" module = builder_module() - if target_is_android(): - dictionary = append_android_envs(dictionary) + dictionary = lldbplatformutil.finalize_build_dictionary(dictionary) if self.debug_info is None: return self.buildDefault(architecture, compiler, dictionary, clean) elif self.debug_info == "dsym": @@ -2733,9 +1978,17 @@ class TestBase(Base): return self.buildDwarf(architecture, compiler, dictionary, clean) elif self.debug_info == "dwo": return self.buildDwo(architecture, compiler, dictionary, clean) + elif self.debug_info == "gmodules": + return self.buildGModules(architecture, compiler, dictionary, clean) else: self.fail("Can't build for debug info: %s" % self.debug_info) + def run_platform_command(self, cmd): + platform = self.dbg.GetSelectedPlatform() + shell_command = lldb.SBPlatformShellCommand(cmd) + err = platform.Run(shell_command) + return (err, shell_command.GetStatus(), shell_command.GetOutput()) + # ================================================= # Misc. helper methods for debugging test execution # ================================================= @@ -2780,4 +2033,17 @@ class TestBase(Base): @classmethod def RemoveTempFile(cls, file): if os.path.exists(file): + remove_file(file) + +# On Windows, the first attempt to delete a recently-touched file can fail +# because of a race with antimalware scanners. This function will detect a +# failure and retry. +def remove_file(file, num_retries = 1, sleep_duration = 0.5): + for i in range(num_retries+1): + try: os.remove(file) + return True + except: + time.sleep(sleep_duration) + continue + return False diff --git a/packages/Python/lldbsuite/test/lldbutil.py b/packages/Python/lldbsuite/test/lldbutil.py index 339619dc4f74..45e9bb407d15 100644 --- a/packages/Python/lldbsuite/test/lldbutil.py +++ b/packages/Python/lldbsuite/test/lldbutil.py @@ -12,6 +12,7 @@ import collections import os import re import sys +import time # Third-party modules from six import StringIO as SixStringIO @@ -84,7 +85,7 @@ def int_to_bytearray(val, bytesize): return None packed = struct.pack(fmt, val) - return bytearray(list(map(ord, packed))) + return bytearray(packed) def bytearray_to_int(bytes, bytesize): """Utility function to convert a bytearray into an integer. @@ -108,7 +109,7 @@ def bytearray_to_int(bytes, bytesize): else: return None - unpacked = struct.unpack(fmt, str(bytes)) + unpacked = struct.unpack_from(fmt, bytes) return unpacked[0] @@ -548,7 +549,7 @@ def get_stopped_thread(process, reason): return None return threads[0] -def get_threads_stopped_at_breakpoint (process, bkpt): +def get_threads_stopped_at_breakpoint_id(process, bpid): """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt""" stopped_threads = [] threads = [] @@ -561,11 +562,26 @@ def get_threads_stopped_at_breakpoint (process, bkpt): for thread in stopped_threads: # Make sure we've hit our breakpoint... break_id = thread.GetStopReasonDataAtIndex (0) - if break_id == bkpt.GetID(): + if break_id == bpid: threads.append(thread) return threads +def get_threads_stopped_at_breakpoint (process, bkpt): + return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID()) + +def get_one_thread_stopped_at_breakpoint_id(process, bpid, require_exactly_one = True): + threads = get_threads_stopped_at_breakpoint_id(process, bpid) + if len(threads) == 0: + return None + if require_exactly_one and len(threads) != 1: + return None + + return threads[0] + +def get_one_thread_stopped_at_breakpoint(process, bkpt, require_exactly_one = True): + return get_one_thread_stopped_at_breakpoint_id(process, bkpt.GetID(), require_exactly_one) + def is_thread_crashed (test, thread): """In the test suite we dereference a null pointer to simulate a crash. The way this is reported depends on the platform.""" @@ -734,14 +750,15 @@ def print_stacktraces(process, string_buffer = False): if string_buffer: return output.getvalue() -def expect_state_changes(test, listener, states, timeout = 5): +def expect_state_changes(test, listener, process, states, timeout = 5): """Listens for state changed events on the listener and makes sure they match what we expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored.""" for expected_state in states: def get_next_event(): event = lldb.SBEvent() - if not listener.WaitForEvent(timeout, event): + if not listener.WaitForEventForBroadcasterWithType(timeout, process.GetBroadcaster(), + lldb.SBProcess.eBroadcastBitStateChanged, event): test.fail("Timed out while waiting for a transition to state %s" % lldb.SBDebugger.StateAsCString(expected_state)) return event @@ -1014,3 +1031,21 @@ def skip_if_library_missing(test, target, library): def find_library_callable(test): return find_library(target, library) return skip_if_callable(test, find_library_callable, "could not find library matching '%s' in target %s" % (library, target)) + +def wait_for_file_on_target(testcase, file_path, max_attempts = 6): + for i in range(max_attempts): + err, retcode, msg = testcase.run_platform_command("ls %s" % file_path) + if err.Success() and retcode == 0: + break + if i < max_attempts: + # Exponential backoff! + import time + time.sleep(pow(2, i) * 0.25) + else: + testcase.fail("File %s not found even after %d attempts." % (file_path, max_attempts)) + + err, retcode, data = testcase.run_platform_command("cat %s" % (file_path)) + + testcase.assertTrue(err.Success() and retcode == 0, + "Failed to read file %s: %s, retcode: %d" % (file_path, err.GetCString(), retcode)) + return data diff --git a/packages/Python/lldbsuite/test/logging/TestLogging.py b/packages/Python/lldbsuite/test/logging/TestLogging.py index f8558a758ee9..cba587e5d8a0 100644 --- a/packages/Python/lldbsuite/test/logging/TestLogging.py +++ b/packages/Python/lldbsuite/test/logging/TestLogging.py @@ -8,7 +8,9 @@ from __future__ import print_function import os, time, string import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class LogTestCase(TestBase): @@ -61,7 +63,7 @@ class LogTestCase(TestBase): f.close () os.remove (log_file) - self.assertTrue(log_lines > 0, "Something was written to the log file.") + self.assertGreater(len(log_lines), 0, "Something was written to the log file.") # Check that lldb truncates its log files @no_debug_info_test @@ -83,7 +85,7 @@ class LogTestCase(TestBase): contents = f.read () # check that it got removed - self.assertTrue(string.find(contents, "bacon") == -1) + self.assertEquals(contents.find("bacon"), -1) # Check that lldb can append to a log file @no_debug_info_test @@ -104,4 +106,4 @@ class LogTestCase(TestBase): contents = f.read () # check that it is still there - self.assertTrue(string.find(contents, "bacon") == 0) + self.assertEquals(contents.find("bacon"), 0) diff --git a/packages/Python/lldbsuite/test/macosx/add-dsym/TestAddDsymMidExecutionCommand.py b/packages/Python/lldbsuite/test/macosx/add-dsym/TestAddDsymMidExecutionCommand.py index 497f695d7cc7..f4f6e313a1f4 100644 --- a/packages/Python/lldbsuite/test/macosx/add-dsym/TestAddDsymMidExecutionCommand.py +++ b/packages/Python/lldbsuite/test/macosx/add-dsym/TestAddDsymMidExecutionCommand.py @@ -7,7 +7,9 @@ from __future__ import print_function import os, time import lldb import sys +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil @skipUnlessDarwin class AddDsymMidExecutionCommandCase(TestBase): diff --git a/packages/Python/lldbsuite/test/macosx/debug-info/apple_types/TestAppleTypesIsProduced.py b/packages/Python/lldbsuite/test/macosx/debug-info/apple_types/TestAppleTypesIsProduced.py index fad14db41003..afd933dc211f 100644 --- a/packages/Python/lldbsuite/test/macosx/debug-info/apple_types/TestAppleTypesIsProduced.py +++ b/packages/Python/lldbsuite/test/macosx/debug-info/apple_types/TestAppleTypesIsProduced.py @@ -8,7 +8,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil from lldbsuite.test.lldbutil import symbol_type_to_str class AppleTypesTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/macosx/indirect_symbol/TestIndirectSymbols.py b/packages/Python/lldbsuite/test/macosx/indirect_symbol/TestIndirectSymbols.py index 4f98865ca5a2..f8b884003ad2 100644 --- a/packages/Python/lldbsuite/test/macosx/indirect_symbol/TestIndirectSymbols.py +++ b/packages/Python/lldbsuite/test/macosx/indirect_symbol/TestIndirectSymbols.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestIndirectFunctions(TestBase): diff --git a/packages/Python/lldbsuite/test/macosx/nslog/Makefile b/packages/Python/lldbsuite/test/macosx/nslog/Makefile new file mode 100644 index 000000000000..de2b618b3d70 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/nslog/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m +LD_EXTRAS = -framework Foundation + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py b/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py new file mode 100644 index 000000000000..15d25bb713a5 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py @@ -0,0 +1,148 @@ +""" +Test DarwinLog "source include debug-level" functionality provided by the +StructuredDataDarwinLog plugin. + +These tests are currently only supported when running against Darwin +targets. +""" + +from __future__ import print_function + +import lldb +import os +import platform +import re +import sys + +from lldbsuite.test import decorators +from lldbsuite.test import lldbtest +from lldbsuite.test import lldbtest_config + +@decorators.skipUnlessDarwin +class DarwinNSLogOutputTestCase(lldbtest.TestBase): + NO_DEBUG_INFO_TESTCASE = True + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + super(DarwinNSLogOutputTestCase, self).setUp() + self.child = None + self.child_prompt = '(lldb) ' + self.strict_sources = False + + # Source filename. + self.source = 'main.m' + + # Output filename. + self.exe_name = 'a.out' + self.d = {'OBJC_SOURCES': self.source, 'EXE': self.exe_name} + + # Locate breakpoint. + self.line = lldbtest.line_number(self.source, '// break here') + + def tearDown(self): + # Shut down the process if it's still running. + if self.child: + self.runCmd('process kill') + self.expect_prompt() + self.runCmd('quit') + + # Let parent clean up + super(DarwinNSLogOutputTestCase, self).tearDown() + + def run_lldb_to_breakpoint(self, exe, source_file, line, + settings_commands=None): + # Set self.child_prompt, which is "(lldb) ". + prompt = self.child_prompt + + # So that the child gets torn down after the test. + import pexpect + self.child = pexpect.spawn('%s %s %s' % (lldbtest_config.lldbExec, + self.lldbOption, exe)) + child = self.child + + # Turn on logging for what the child sends back. + if self.TraceOn(): + child.logfile_read = sys.stdout + + # Disable showing of source lines at our breakpoint. + # This is necessary for the logging tests, because the very + # text we want to match for output from the running inferior + # will show up in the source as well. We don't want the source + # output to erroneously make a match with our expected output. + self.runCmd("settings set stop-line-count-before 0") + self.expect_prompt() + self.runCmd("settings set stop-line-count-after 0") + self.expect_prompt() + + # Run any test-specific settings commands now. + if settings_commands is not None: + for setting_command in settings_commands: + self.runCmd(setting_command) + self.expect_prompt() + + # Set the breakpoint, and run to it. + child.sendline('breakpoint set -f %s -l %d' % (source_file, line)) + child.expect_exact(prompt) + child.sendline('run') + child.expect_exact(prompt) + + # Ensure we stopped at a breakpoint. + self.runCmd("thread list") + self.expect(re.compile(r"stop reason = breakpoint")) + + def runCmd(self, cmd): + self.child.sendline(cmd) + + def expect_prompt(self, exactly=True): + self.expect(self.child_prompt, exactly=exactly) + + def expect(self, pattern, exactly=False, *args, **kwargs): + if exactly: + return self.child.expect_exact(pattern, *args, **kwargs) + return self.child.expect(pattern, *args, **kwargs) + + def do_test(self, expect_regexes=None, settings_commands=None): + """ Run a test. """ + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + + exe = os.path.join(os.getcwd(), self.exe_name) + self.run_lldb_to_breakpoint(exe, self.source, self.line, + settings_commands=settings_commands) + self.expect_prompt() + + # Now go. + self.runCmd("process continue") + self.expect(expect_regexes) + + def test_nslog_output_is_displayed(self): + """Test that NSLog() output shows up in the command-line debugger.""" + self.do_test(expect_regexes=[ + re.compile(r"(This is a message from NSLog)"), + re.compile(r"Process \d+ exited with status") + ]) + self.assertIsNotNone(self.child.match) + self.assertGreater(len(self.child.match.groups()), 0) + self.assertEqual("This is a message from NSLog", self.child.match.group(1)) + + def test_nslog_output_is_suppressed_with_env_var(self): + """Test that NSLog() output does not show up with the ignore env var.""" + # This test will only work properly on macOS 10.12+. Skip it on earlier versions. + # This will require some tweaking on iOS. + match = re.match(r"^\d+\.(\d+)", platform.mac_ver()[0]) + if match is None or int(match.group(1)) < 12: + self.skipTest("requires macOS 10.12 or higher") + + self.do_test( + expect_regexes=[ + re.compile(r"(This is a message from NSLog)"), + re.compile(r"Process \d+ exited with status") + ], + settings_commands=[ + "settings set target.env-vars " + "\"IDE_DISABLED_OS_ACTIVITY_DT_MODE=1\"" + ]) + self.assertIsNotNone(self.child.match) + self.assertEqual(len(self.child.match.groups()), 0) diff --git a/packages/Python/lldbsuite/test/macosx/nslog/main.m b/packages/Python/lldbsuite/test/macosx/nslog/main.m new file mode 100644 index 000000000000..dab4089e9273 --- /dev/null +++ b/packages/Python/lldbsuite/test/macosx/nslog/main.m @@ -0,0 +1,18 @@ +//===-- main.m --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +int main(int argc, char** argv) +{ + printf("About to log\n"); // break here + NSLog(@"This is a message from NSLog"); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/macosx/order/TestOrderFile.py b/packages/Python/lldbsuite/test/macosx/order/TestOrderFile.py index 6541169798ae..db2e071914c5 100644 --- a/packages/Python/lldbsuite/test/macosx/order/TestOrderFile.py +++ b/packages/Python/lldbsuite/test/macosx/order/TestOrderFile.py @@ -9,7 +9,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class OrderFileTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py b/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py index 492d1d3bda3a..b403db2f275d 100644 --- a/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py +++ b/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py @@ -7,8 +7,9 @@ from __future__ import print_function import unittest2 import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestQueues(TestBase): diff --git a/packages/Python/lldbsuite/test/macosx/safe-to-func-call/TestSafeFuncCalls.py b/packages/Python/lldbsuite/test/macosx/safe-to-func-call/TestSafeFuncCalls.py index 297223c3e84e..4e2dfb0eeb68 100644 --- a/packages/Python/lldbsuite/test/macosx/safe-to-func-call/TestSafeFuncCalls.py +++ b/packages/Python/lldbsuite/test/macosx/safe-to-func-call/TestSafeFuncCalls.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestSafeFuncCalls(TestBase): diff --git a/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py b/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py index 4b722b0c1d8e..70a83ea90792 100644 --- a/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py +++ b/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py @@ -7,8 +7,9 @@ from __future__ import print_function import unittest2 import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class UniversalTestCase(TestBase): @@ -18,7 +19,7 @@ class UniversalTestCase(TestBase): # Call super's setUp(). TestBase.setUp(self) # Find the line number to break inside main(). - self.line = line_number('main.c', '// Set break point at this line.') + self.line = line_number('main.c', '// Set break point at this line.') @add_test_categories(['pyapi']) @skipUnlessDarwin @@ -105,3 +106,51 @@ class UniversalTestCase(TestBase): substrs = ['Name: eax']) self.runCmd("continue") + + + @skipUnlessDarwin + @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in ['i386', 'x86_64'], + "requires i386 or x86_64") + def test_process_attach_with_wrong_arch(self): + """Test that when we attach to a binary from the wrong fork of a universal binary, we fix up the ABI correctly.""" + # Now keep the architecture at 32 bit, but switch the binary we launch to + # 64 bit, and make sure on attach we switch to the correct architecture. + + # Invoke the default build rule. + self.build() + + # Note that "testit" is a universal binary. + exe = os.path.join(os.getcwd(), "testit") + + + # Create a target by the debugger. + target = self.dbg.CreateTargetWithFileAndTargetTriple(exe, "i386-apple-macosx") + self.assertTrue(target, VALID_TARGET) + pointer_size = target.GetAddressByteSize() + self.assertTrue(pointer_size == 4, "Initially we were 32 bit.") + + bkpt = target.BreakpointCreateBySourceRegex("sleep", lldb.SBFileSpec("main.c")) + self.assertTrue (bkpt.IsValid(), "Valid breakpoint") + self.assertTrue(bkpt.GetNumLocations() >= 1, "Our main breakpoint has locations.") + + popen = self.spawnSubprocess(exe, ["keep_waiting"]) + self.addTearDownHook(self.cleanupSubprocesses) + + error = lldb.SBError() + empty_listener = lldb.SBListener() + process = target.AttachToProcessWithID(empty_listener, popen.pid, error) + self.assertTrue(error.Success(), "Attached to process.") + + pointer_size = target.GetAddressByteSize() + self.assertTrue(pointer_size == 8, "We switched to 64 bit.") + + # It may seem odd that I am checking the number of frames, but the bug that + # motivated this test was that we eventually fixed the architecture, but we + # left the ABI set to the original value. In that case, if you asked the + # process for its architecture, it would look right, but since the ABI was + # wrong, backtracing failed. + + threads = lldbutil.continue_to_breakpoint(process, bkpt) + self.assertTrue(len(threads) == 1) + thread = threads[0] + self.assertTrue(thread.GetNumFrames() > 1, "We were able to backtrace.") diff --git a/packages/Python/lldbsuite/test/macosx/universal/main.c b/packages/Python/lldbsuite/test/macosx/universal/main.c index 9351c77f7146..3edab51b1f6a 100644 --- a/packages/Python/lldbsuite/test/macosx/universal/main.c +++ b/packages/Python/lldbsuite/test/macosx/universal/main.c @@ -1,7 +1,21 @@ #include +#include +#include + +void +call_me() +{ + sleep(1); +} + int main (int argc, char **argv) { printf ("Hello there!\n"); // Set break point at this line. + if (argc == 2 && strcmp(argv[1], "keep_waiting") == 0) + while (1) + { + call_me(); + } return 0; } diff --git a/packages/Python/lldbsuite/test/make/Makefile.rules b/packages/Python/lldbsuite/test/make/Makefile.rules index e753317e9398..c37ef745e8b4 100644 --- a/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/packages/Python/lldbsuite/test/make/Makefile.rules @@ -168,6 +168,10 @@ else override ARCH := override ARCHFLAG := endif + ifeq "$(ARCH)" "s390x" + override ARCH := + override ARCHFLAG := + endif ifeq "$(findstring mips,$(ARCH))" "mips" override ARCHFLAG := - endif @@ -179,9 +183,11 @@ endif LIMIT_DEBUG_INFO_FLAGS = NO_LIMIT_DEBUG_INFO_FLAGS = +MODULE_DEBUG_INFO_FLAGS = ifneq (,$(findstring clang,$(CC))) LIMIT_DEBUG_INFO_FLAGS += -flimit-debug-info NO_LIMIT_DEBUG_INFO_FLAGS += -fno-limit-debug-info + MODULE_DEBUG_INFO_FLAGS += -gmodules endif DEBUG_INFO_FLAG ?= -g @@ -206,8 +212,13 @@ ifeq "$(MAKE_DWO)" "YES" CFLAGS += -gsplit-dwarf endif +ifeq "$(MAKE_GMODULES)" "YES" + CFLAGS += -fmodules -gmodules +endif + CXXFLAGS += -std=c++11 -CXXFLAGS += $(CFLAGS) +# FIXME: C++ modules aren't supported on all platforms. +CXXFLAGS += $(subst -fmodules,, $(CFLAGS)) LD = $(CC) LDFLAGS ?= $(CFLAGS) LDFLAGS += $(LD_EXTRAS) @@ -300,7 +311,7 @@ endif ifeq (1,$(USE_LIBSTDCPP)) # Clang requires an extra flag: -stdlib=libstdc++ ifneq (,$(findstring clang,$(CC))) - CXXFLAGS += -stdlib=libstdc++ + CXXFLAGS += -stdlib=libstdc++ -DLLDB_USING_LIBSTDCPP LDFLAGS += -stdlib=libstdc++ endif endif @@ -339,6 +350,14 @@ ifneq "$(strip $(DYLIB_CXX_SOURCES))" "" LD = $(call cxx_linker,$(CC)) endif +#---------------------------------------------------------------------- +# Check if we have a precompiled header +#---------------------------------------------------------------------- +ifneq "$(strip $(PCH_CXX_SOURCE))" "" + PCH_OUTPUT = $(PCH_CXX_SOURCE:.h=.h.pch) + PCHFLAGS = -include $(PCH_CXX_SOURCE) +endif + #---------------------------------------------------------------------- # Check if we have any C source files #---------------------------------------------------------------------- @@ -497,6 +516,17 @@ ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" endif endif +#---------------------------------------------------------------------- +# Make the precompiled header and compile C++ sources against it +#---------------------------------------------------------------------- + +#ifneq "$(PCH_OUTPUT)" "" +$(PCH_OUTPUT) : $(PCH_CXX_SOURCE) + $(CXX) $(CXXFLAGS) -x c++-header -o $(PCH_OUTPUT) $(PCH_CXX_SOURCE) +%.o : %.cpp $(PCH_OUTPUT) + $(CXX) $(PCHFLAGS) $(CXXFLAGS) -c -o $@ $< +#endif + #---------------------------------------------------------------------- # Automatic variables based on items already entered. Below we create # an object's lists from the list of sources by replacing all entries @@ -570,6 +600,9 @@ ifneq "$(DYLIB_NAME)" "" $(RM) -r $(DYLIB_FILENAME).dSYM $(RM) $(DYLIB_OBJECTS) $(DYLIB_PREREQS) $(DYLIB_PREREQS:.d=.d.tmp) $(DYLIB_DWOS) $(DYLIB_FILENAME) $(DYLIB_FILENAME).debug endif +ifneq "$(PCH_OUTPUT)" "" + $(RM) $(PCH_OUTPUT) +endif ifneq "$(DSYM)" "" $(RM) -r "$(DSYM)" endif diff --git a/packages/Python/lldbsuite/test/make/test_common.h b/packages/Python/lldbsuite/test/make/test_common.h index a1ed364574e3..b0151afb892e 100644 --- a/packages/Python/lldbsuite/test/make/test_common.h +++ b/packages/Python/lldbsuite/test/make/test_common.h @@ -26,7 +26,14 @@ #if defined(__linux__) #include -#if defined(PR_SET_PTRACER) && defined(PR_SET_PTRACER_ANY) +// Android API <= 16 does not have these defined. +#ifndef PR_SET_PTRACER +#define PR_SET_PTRACER 0x59616d61 +#endif +#ifndef PR_SET_PTRACER_ANY +#define PR_SET_PTRACER_ANY ((unsigned long)-1) +#endif + // For now we execute on best effort basis. If this fails for some reason, so be it. #define lldb_enable_attach() \ do \ @@ -35,10 +42,39 @@ (void)prctl_result; \ } while (0) -#endif - #else // not linux #define lldb_enable_attach() #endif + +#if defined(__APPLE__) && defined(LLDB_USING_LIBSTDCPP) + +// on Darwin, libstdc++ is missing , so this would cause any test to fail building +// since this header file is being included in every C-family test case, we need to not include it +// on Darwin, most tests use libc++ by default, so this will only affect tests that explicitly require libstdc++ + +#else +#ifdef __cplusplus +#include + +// Note that although hogging the CPU while waiting for a variable to change +// would be terrible in production code, it's great for testing since it +// avoids a lot of messy context switching to get multiple threads synchronized. + +typedef std::atomic pseudo_barrier_t; +#define pseudo_barrier_wait(barrier) \ + do \ + { \ + --(barrier); \ + while ((barrier).load() > 0) \ + ; \ + } while (0) + +#define pseudo_barrier_init(barrier, count) \ + do \ + { \ + (barrier) = (count); \ + } while (0) +#endif // __cplusplus +#endif // defined(__APPLE__) && defined(LLDB_USING_LIBSTDCPP) diff --git a/packages/Python/lldbsuite/test/plugins/builder_base.py b/packages/Python/lldbsuite/test/plugins/builder_base.py index c4e3dff5301c..a467a458d5de 100644 --- a/packages/Python/lldbsuite/test/plugins/builder_base.py +++ b/packages/Python/lldbsuite/test/plugins/builder_base.py @@ -12,9 +12,16 @@ Same idea holds for LLDB_ARCH environment variable, which maps to the ARCH make variable. """ -import os, sys +# System imports +import os import platform +import subprocess +import sys + +# Our imports import lldbsuite.test.lldbtest as lldbtest +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test_event import build_exception def getArchitecture(): """Returns the architecture in effect the test suite is running with.""" @@ -22,7 +29,9 @@ def getArchitecture(): def getCompiler(): """Returns the compiler in effect the test suite is running with.""" - return os.environ["CC"] if "CC" in os.environ else "clang" + compiler = os.environ.get("CC", "clang") + compiler = lldbutil.which(compiler) + return os.path.realpath(compiler) def getArchFlag(): """Returns the flag required to specify the arch""" @@ -90,6 +99,16 @@ def getCmdLine(d): return cmdline +def runBuildCommands(commands, sender): + try: + lldbtest.system(commands, sender=sender) + except subprocess.CalledProcessError as called_process_error: + # Convert to a build-specific error. + # We don't do that in lldbtest.system() since that + # is more general purpose. + raise build_exception.BuildError(called_process_error) + + def buildDefault(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): """Build the binaries the default way.""" commands = [] @@ -97,7 +116,7 @@ def buildDefault(sender=None, architecture=None, compiler=None, dictionary=None, commands.append([getMake(), "clean", getCmdLine(dictionary)]) commands.append([getMake(), getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)]) - lldbtest.system(commands, sender=sender) + runBuildCommands(commands, sender=sender) # True signifies that we can handle building default. return True @@ -109,7 +128,7 @@ def buildDwarf(sender=None, architecture=None, compiler=None, dictionary=None, c commands.append([getMake(), "clean", getCmdLine(dictionary)]) commands.append([getMake(), "MAKE_DSYM=NO", getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)]) - lldbtest.system(commands, sender=sender) + runBuildCommands(commands, sender=sender) # True signifies that we can handle building dwarf. return True @@ -120,10 +139,21 @@ def buildDwo(sender=None, architecture=None, compiler=None, dictionary=None, cle commands.append([getMake(), "clean", getCmdLine(dictionary)]) commands.append([getMake(), "MAKE_DSYM=NO", "MAKE_DWO=YES", getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)]) - lldbtest.system(commands, sender=sender) + runBuildCommands(commands, sender=sender) # True signifies that we can handle building dwo. return True +def buildGModules(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): + """Build the binaries with dwarf debug info.""" + commands = [] + if clean: + commands.append([getMake(), "clean", getCmdLine(dictionary)]) + commands.append([getMake(), "MAKE_DSYM=NO", "MAKE_GMODULES=YES", getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)]) + + lldbtest.system(commands, sender=sender) + # True signifies that we can handle building with gmodules. + return True + def cleanup(sender=None, dictionary=None): """Perform a platform-specific cleanup after the test.""" #import traceback @@ -132,6 +162,6 @@ def cleanup(sender=None, dictionary=None): if os.path.isfile("Makefile"): commands.append([getMake(), "clean", getCmdLine(dictionary)]) - lldbtest.system(commands, sender=sender) + runBuildCommands(commands, sender=sender) # True signifies that we can handle cleanup. return True diff --git a/packages/Python/lldbsuite/test/plugins/builder_darwin.py b/packages/Python/lldbsuite/test/plugins/builder_darwin.py index dd07206e323b..8a907ccec2da 100644 --- a/packages/Python/lldbsuite/test/plugins/builder_darwin.py +++ b/packages/Python/lldbsuite/test/plugins/builder_darwin.py @@ -5,8 +5,6 @@ import lldbsuite.test.lldbtest as lldbtest from builder_base import * -#print("Hello, darwin plugin!") - def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): """Build the binaries with dsym debug info.""" commands = [] @@ -15,7 +13,7 @@ def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None, cl commands.append(["make", "clean", getCmdLine(dictionary)]) commands.append(["make", "MAKE_DSYM=YES", getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)]) - lldbtest.system(commands, sender=sender) + runBuildCommands(commands, sender=sender) # True signifies that we can handle building dsym. return True diff --git a/packages/Python/lldbsuite/test/plugins/builder_linux.py b/packages/Python/lldbsuite/test/plugins/builder_linux.py new file mode 100644 index 000000000000..e56be429823e --- /dev/null +++ b/packages/Python/lldbsuite/test/plugins/builder_linux.py @@ -0,0 +1,4 @@ +from builder_base import * + +def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): + return False diff --git a/packages/Python/lldbsuite/test/plugins/builder_linux2.py b/packages/Python/lldbsuite/test/plugins/builder_linux2.py deleted file mode 100644 index e56be429823e..000000000000 --- a/packages/Python/lldbsuite/test/plugins/builder_linux2.py +++ /dev/null @@ -1,4 +0,0 @@ -from builder_base import * - -def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None, clean=True): - return False diff --git a/packages/Python/lldbsuite/test/python_api/breakpoint/TestBreakpointAPI.py b/packages/Python/lldbsuite/test/python_api/breakpoint/TestBreakpointAPI.py index 1f4fa20b8304..a3dd91fe8802 100644 --- a/packages/Python/lldbsuite/test/python_api/breakpoint/TestBreakpointAPI.py +++ b/packages/Python/lldbsuite/test/python_api/breakpoint/TestBreakpointAPI.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class BreakpointAPITestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/class_members/TestSBTypeClassMembers.py b/packages/Python/lldbsuite/test/python_api/class_members/TestSBTypeClassMembers.py index e1d5520bcc3d..3d9309e26cec 100644 --- a/packages/Python/lldbsuite/test/python_api/class_members/TestSBTypeClassMembers.py +++ b/packages/Python/lldbsuite/test/python_api/class_members/TestSBTypeClassMembers.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SBTypeMemberFunctionsTest(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/debugger/TestDebuggerAPI.py b/packages/Python/lldbsuite/test/python_api/debugger/TestDebuggerAPI.py index 98feda859ae9..d8ac342f4754 100644 --- a/packages/Python/lldbsuite/test/python_api/debugger/TestDebuggerAPI.py +++ b/packages/Python/lldbsuite/test/python_api/debugger/TestDebuggerAPI.py @@ -4,7 +4,10 @@ Test Debugger APIs. import os import lldb + +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class DebuggerAPITestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py b/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py index aa3a6141326a..3e2ff2ffa9dd 100644 --- a/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py @@ -18,8 +18,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class APIDefaultConstructorTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassembleRawData.py b/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassembleRawData.py index 31ba44928794..311791cca014 100644 --- a/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassembleRawData.py +++ b/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassembleRawData.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class DisassembleRawDataTestCase(TestBase): @@ -18,6 +19,7 @@ class DisassembleRawDataTestCase(TestBase): @add_test_categories(['pyapi']) @no_debug_info_test + @skipIfRemote def test_disassemble_raw_data(self): """Test disassembling raw bytes with the API.""" # Create a target from the debugger. diff --git a/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py b/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py index e24b2ee5613a..f991ab329a89 100644 --- a/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py +++ b/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py @@ -9,14 +9,15 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class Disassemble_VST1_64(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipIf(True) # llvm.org/pr24575: all tests get ERRORs in dotest.py after this + @skipTestIfFn(lambda : True, "llvm.org/pr24575: all tests get ERRORs in dotest.py after this") @add_test_categories(['pyapi']) @no_debug_info_test def test_disassemble_invalid_vst_1_64_raw_data(self): diff --git a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py index 51c924b2aff1..1c23f50e9d4d 100644 --- a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py +++ b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py @@ -9,10 +9,10 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil -@skipIfDarwin # llvm.org/pr25924, sometimes generating SIGSEGV @skipIfLinux # llvm.org/pr25924, sometimes generating SIGSEGV class EventAPITestCase(TestBase): @@ -25,7 +25,7 @@ class EventAPITestCase(TestBase): self.line = line_number('main.c', '// Find the line number of function "c" here.') @add_test_categories(['pyapi']) - @expectedFailureLinux("llvm.org/pr23730") # Flaky, fails ~1/10 cases + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr23730 Flaky, fails ~1/10 cases") def test_listen_for_and_print_event(self): """Exercise SBEvent API.""" self.build() @@ -85,6 +85,7 @@ class EventAPITestCase(TestBase): if traceOn: print("timeout occurred waiting for event...") count = count + 1 + listener.Clear() return # Let's start the listening thread to retrieve the events. @@ -102,8 +103,11 @@ class EventAPITestCase(TestBase): # Wait until the 'MyListeningThread' terminates. my_thread.join() + # Shouldn't we be testing against some kind of expectation here? + @add_test_categories(['pyapi']) @expectedFlakeyLinux("llvm.org/pr23730") # Flaky, fails ~1/100 cases + @expectedFlakeyOS(oslist=["windows"]) def test_wait_for_event(self): """Exercise SBListener.WaitForEvent() API.""" self.build() @@ -154,10 +158,11 @@ class EventAPITestCase(TestBase): #print("Got a valid event:", event) #print("Event data flavor:", event.GetDataFlavor()) #print("Event type:", lldbutil.state_type_to_str(event.GetType())) + listener.Clear() return count = count + 1 print("Timeout: listener.WaitForEvent") - + listener.Clear() return # Use Python API to kill the process. The listening thread should be @@ -176,8 +181,8 @@ class EventAPITestCase(TestBase): @skipIfFreeBSD # llvm.org/pr21325 @add_test_categories(['pyapi']) - @expectedFailureLinux("llvm.org/pr23617") # Flaky, fails ~1/10 cases - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr23617 Flaky, fails ~1/10 cases") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_add_listener_to_broadcaster(self): """Exercise some SBBroadcaster APIs.""" self.build() @@ -265,7 +270,7 @@ class EventAPITestCase(TestBase): count = count + 1 if count > 6: break - + listener.Clear() return # Use Python API to continue the process. The listening thread should be diff --git a/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py b/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py index 80305e303d03..49bc148dd579 100644 --- a/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py +++ b/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import decorators +from lldbsuite.test import lldbinline -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIfFreeBSD,decorators.skipIfLinux,decorators.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/python_api/findvalue_duplist/TestSBFrameFindValue.py b/packages/Python/lldbsuite/test/python_api/findvalue_duplist/TestSBFrameFindValue.py index 96d4f51fd097..9c1fd1e7bef7 100644 --- a/packages/Python/lldbsuite/test/python_api/findvalue_duplist/TestSBFrameFindValue.py +++ b/packages/Python/lldbsuite/test/python_api/findvalue_duplist/TestSBFrameFindValue.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, sys, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SBFrameFindValueTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/formatters/TestFormattersSBAPI.py b/packages/Python/lldbsuite/test/python_api/formatters/TestFormattersSBAPI.py index de7f15f76faf..babae237b8ce 100644 --- a/packages/Python/lldbsuite/test/python_api/formatters/TestFormattersSBAPI.py +++ b/packages/Python/lldbsuite/test/python_api/formatters/TestFormattersSBAPI.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, sys, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SBFormattersAPITestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py index 7cc976fc6aa3..0b1e12b08fcb 100644 --- a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py +++ b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py @@ -10,15 +10,16 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class FrameAPITestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_get_arg_vals_for_call_stack(self): """Exercise SBFrame.GetVariables() API to get argument vals.""" self.build() @@ -49,7 +50,8 @@ class FrameAPITestCase(TestBase): from six import StringIO as SixStringIO session = SixStringIO() while process.GetState() == lldb.eStateStopped: - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # Inspect at most 3 frames. numFrames = min(3, thread.GetNumFrames()) for i in range(numFrames): @@ -134,7 +136,8 @@ class FrameAPITestCase(TestBase): self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) - thread = process.GetThreadAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) frame = thread.GetFrameAtIndex(0) if self.TraceOn(): print("frame:", frame) @@ -173,8 +176,8 @@ class FrameAPITestCase(TestBase): self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) - thread = process.GetThreadAtIndex(0) - self.assertTrue(thread) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) frameEntered = thread.GetFrameAtIndex(0) if self.TraceOn(): diff --git a/packages/Python/lldbsuite/test/python_api/frame/get-variables/Makefile b/packages/Python/lldbsuite/test/python_api/frame/get-variables/Makefile new file mode 100644 index 000000000000..b09a579159d4 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/get-variables/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/frame/get-variables/TestGetVariables.py b/packages/Python/lldbsuite/test/python_api/frame/get-variables/TestGetVariables.py new file mode 100644 index 000000000000..914c3d25fd5d --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/get-variables/TestGetVariables.py @@ -0,0 +1,190 @@ +""" +Test that SBFrame::GetVariables() calls work correctly. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbutil + +def get_names_from_value_list(value_list): + names = list() + for value in value_list: + names.append(value.GetName()) + return names + +class TestGetVariables(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.source = 'main.c' + + def verify_variable_names(self, description, value_list, names): + copy_names = list(names) + actual_names = get_names_from_value_list(value_list) + for name in actual_names: + if name in copy_names: + copy_names.remove(name) + else: + self.assertTrue(False, "didn't find '%s' in %s" % (name, copy_names)) + self.assertEqual(len(copy_names), 0, "%s: we didn't find variables: %s in value list (%s)" % (description, copy_names, actual_names)) + + def test (self): + self.build () + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + # Create a target by the debugger. + exe = os.path.join(os.getcwd(), "a.out") + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + line1 = line_number(self.source, '// breakpoint 1') + line2 = line_number(self.source, '// breakpoint 2') + line3 = line_number(self.source, '// breakpoint 3') + + breakpoint1 = target.BreakpointCreateByLocation (self.source, line1); + breakpoint2 = target.BreakpointCreateByLocation (self.source, line2); + breakpoint3 = target.BreakpointCreateByLocation (self.source, line3); + + self.assertTrue(breakpoint1.GetNumLocations() >= 1, PROCESS_IS_VALID) + self.assertTrue(breakpoint2.GetNumLocations() >= 1, PROCESS_IS_VALID) + self.assertTrue(breakpoint3.GetNumLocations() >= 1, PROCESS_IS_VALID) + + # Register our shared libraries for remote targets so they get automatically uploaded + arguments = None + environment = None + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (arguments, environment, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint1) + self.assertEqual(len(threads), 1, "There should be a thread stopped at breakpoint 1") + + thread = threads[0] + self.assertTrue(thread.IsValid(), "Thread must be valid") + frame = thread.GetFrameAtIndex(0) + self.assertTrue(frame.IsValid(), "Frame must be valid") + + arg_names = ['argc', 'argv'] + local_names = ['i', 'j', 'k'] + static_names = ['static_var', 'g_global_var', 'g_static_var'] + breakpoint1_locals = ['i'] + breakpoint1_statics = ['static_var'] + num_args = len(arg_names) + num_locals = len(local_names) + num_statics = len(static_names) + args_yes = True + args_no = False + locals_yes = True + locals_no = False + statics_yes = True + statics_no = False + in_scopy_only = True + ignore_scope = False + + # Verify if we ask for only arguments that we got what we expect + vars = frame.GetVariables(args_yes, locals_no, statics_no, ignore_scope) + self.assertEqual(vars.GetSize(), num_args, "There should be %i arguments, but we are reporting %i" % (num_args, vars.GetSize())) + self.verify_variable_names("check names of arguments", vars, arg_names) + self.assertEqual(len(arg_names), num_args, "make sure verify_variable_names() didn't mutate list") + + # Verify if we ask for only locals that we got what we expect + vars = frame.GetVariables(args_no, locals_yes, statics_no, ignore_scope) + self.assertEqual(vars.GetSize(), num_locals, "There should be %i local variables, but we are reporting %i" % (num_locals, vars.GetSize())) + self.verify_variable_names("check names of locals", vars, local_names) + + # Verify if we ask for only statics that we got what we expect + vars = frame.GetVariables(args_no, locals_no, statics_yes, ignore_scope) + print('statics: ', str(vars)) + self.assertEqual(vars.GetSize(), num_statics, "There should be %i static variables, but we are reporting %i" % (num_statics, vars.GetSize())) + self.verify_variable_names("check names of statics", vars, static_names) + + # Verify if we ask for arguments and locals that we got what we expect + vars = frame.GetVariables(args_yes, locals_yes, statics_no, ignore_scope) + desc = 'arguments + locals' + names = arg_names + local_names + count = len(names) + self.assertEqual(vars.GetSize(), count, "There should be %i %s (%s) but we are reporting %i (%s)" % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars))) + self.verify_variable_names("check names of %s" % (desc), vars, names) + + # Verify if we ask for arguments and statics that we got what we expect + vars = frame.GetVariables(args_yes, locals_no, statics_yes, ignore_scope) + desc = 'arguments + statics' + names = arg_names + static_names + count = len(names) + self.assertEqual(vars.GetSize(), count, "There should be %i %s (%s) but we are reporting %i (%s)" % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars))) + self.verify_variable_names("check names of %s" % (desc), vars, names) + + # Verify if we ask for locals and statics that we got what we expect + vars = frame.GetVariables(args_no, locals_yes, statics_yes, ignore_scope) + desc = 'locals + statics' + names = local_names + static_names + count = len(names) + self.assertEqual(vars.GetSize(), count, "There should be %i %s (%s) but we are reporting %i (%s)" % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars))) + self.verify_variable_names("check names of %s" % (desc), vars, names) + + # Verify if we ask for arguments, locals and statics that we got what we expect + vars = frame.GetVariables(args_yes, locals_yes, statics_yes, ignore_scope) + desc = 'arguments + locals + statics' + names = arg_names + local_names + static_names + count = len(names) + self.assertEqual(vars.GetSize(), count, "There should be %i %s (%s) but we are reporting %i (%s)" % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars))) + self.verify_variable_names("check names of %s" % (desc), vars, names) + + # Verify if we ask for in scope locals that we got what we expect + vars = frame.GetVariables(args_no, locals_yes, statics_no, in_scopy_only) + desc = 'in scope locals at breakpoint 1' + names = ['i'] + count = len(names) + self.assertEqual(vars.GetSize(), count, "There should be %i %s (%s) but we are reporting %i (%s)" % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars))) + self.verify_variable_names("check names of %s" % (desc), vars, names) + + # Continue to breakpoint 2 + process.Continue() + + threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint2) + self.assertEqual(len(threads), 1, "There should be a thread stopped at breakpoint 2") + + thread = threads[0] + self.assertTrue(thread.IsValid(), "Thread must be valid") + frame = thread.GetFrameAtIndex(0) + self.assertTrue(frame.IsValid(), "Frame must be valid") + + # Verify if we ask for in scope locals that we got what we expect + vars = frame.GetVariables(args_no, locals_yes, statics_no, in_scopy_only) + desc = 'in scope locals at breakpoint 2' + names = ['i', 'j'] + count = len(names) + self.assertEqual(vars.GetSize(), count, "There should be %i %s (%s) but we are reporting %i (%s)" % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars))) + self.verify_variable_names("check names of %s" % (desc), vars, names) + + # Continue to breakpoint 3 + process.Continue() + + threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint3) + self.assertEqual(len(threads), 1, "There should be a thread stopped at breakpoint 3") + + thread = threads[0] + self.assertTrue(thread.IsValid(), "Thread must be valid") + frame = thread.GetFrameAtIndex(0) + self.assertTrue(frame.IsValid(), "Frame must be valid") + + # Verify if we ask for in scope locals that we got what we expect + vars = frame.GetVariables(args_no, locals_yes, statics_no, in_scopy_only) + desc = 'in scope locals at breakpoint 3' + names = ['i', 'j', 'k'] + count = len(names) + self.assertEqual(vars.GetSize(), count, "There should be %i %s (%s) but we are reporting %i (%s)" % (count, desc, names, vars.GetSize(), get_names_from_value_list(vars))) + self.verify_variable_names("check names of %s" % (desc), vars, names) diff --git a/packages/Python/lldbsuite/test/python_api/frame/get-variables/main.c b/packages/Python/lldbsuite/test/python_api/frame/get-variables/main.c new file mode 100644 index 000000000000..7fecfc0293c3 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/get-variables/main.c @@ -0,0 +1,29 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +int g_global_var = 123; +static int g_static_var = 123; + +int main (int argc, char const *argv[]) +{ + static int static_var = 123; + g_static_var = 123; // clang bug. Need to touch this variable, otherwise it disappears. + int i = 0; // breakpoint 1 + for (i=0; i<1; ++i) + { + int j = i*2; + printf("i = %i, j = %i\n", i, j); // breakpoint 2 + { + int k = i*j*3; + printf("i = %i, j = %i\n", i, j); // breakpoint 3 + } + } + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/frame/inlines/TestInlinedFrame.py b/packages/Python/lldbsuite/test/python_api/frame/inlines/TestInlinedFrame.py index d4cf8fe30ccd..ee6c33f54314 100644 --- a/packages/Python/lldbsuite/test/python_api/frame/inlines/TestInlinedFrame.py +++ b/packages/Python/lldbsuite/test/python_api/frame/inlines/TestInlinedFrame.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class InlinedFrameAPITestCase(TestBase): @@ -60,7 +61,10 @@ class InlinedFrameAPITestCase(TestBase): # # outer_inline (argc); # - frame0 = process.GetThreadAtIndex(0).GetFrameAtIndex(0) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) + + frame0 = thread.GetFrameAtIndex(0) if frame0.IsInlined(): filename = frame0.GetLineEntry().GetFileSpec().GetFilename() self.assertTrue(filename == self.source) diff --git a/packages/Python/lldbsuite/test/python_api/function_symbol/TestDisasmAPI.py b/packages/Python/lldbsuite/test/python_api/function_symbol/TestDisasmAPI.py index c9876a8c8954..9a763b89c27f 100644 --- a/packages/Python/lldbsuite/test/python_api/function_symbol/TestDisasmAPI.py +++ b/packages/Python/lldbsuite/test/python_api/function_symbol/TestDisasmAPI.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class DisasmAPITestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/function_symbol/TestSymbolAPI.py b/packages/Python/lldbsuite/test/python_api/function_symbol/TestSymbolAPI.py index 187ba69def0e..35d73e494270 100644 --- a/packages/Python/lldbsuite/test/python_api/function_symbol/TestSymbolAPI.py +++ b/packages/Python/lldbsuite/test/python_api/function_symbol/TestSymbolAPI.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SymbolAPITestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py index 47c3ba146cef..a8beaa903293 100644 --- a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py +++ b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py @@ -4,10 +4,14 @@ from __future__ import print_function -import os, sys, time -import lldb +import os +import sys import time + +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class HelloWorldTestCase(TestBase): @@ -64,18 +68,14 @@ class HelloWorldTestCase(TestBase): process = target.GetProcess() self.assertTrue(process, PROCESS_IS_VALID) - thread = process.GetThreadAtIndex(0) - if thread.GetStopReason() != lldb.eStopReasonBreakpoint: - from lldbsuite.test.lldbutil import stop_reason_to_str - self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % - stop_reason_to_str(thread.GetStopReason())) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) # The breakpoint should have a hit count of 1. - self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE) + self.assertEqual(breakpoint.GetHitCount(), 1, BREAKPOINT_HIT_ONCE) @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24600") - @expectedFailurei386("llvm.org/pr25338") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24600") @skipIfiOSSimulator def test_with_attach_to_process_with_id_api(self): """Create target, spawn a process, and attach to it with process id.""" @@ -104,8 +104,7 @@ class HelloWorldTestCase(TestBase): '(int)argc=3']) @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24600") - @expectedFailurei386("llvm.org/pr25338") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24600") @skipIfiOSSimulator def test_with_attach_to_process_with_name_api(self): """Create target, spawn a process, and attach to it with process name.""" diff --git a/packages/Python/lldbsuite/test/python_api/interpreter/TestCommandInterpreterAPI.py b/packages/Python/lldbsuite/test/python_api/interpreter/TestCommandInterpreterAPI.py index faff11818da7..d39984adb732 100644 --- a/packages/Python/lldbsuite/test/python_api/interpreter/TestCommandInterpreterAPI.py +++ b/packages/Python/lldbsuite/test/python_api/interpreter/TestCommandInterpreterAPI.py @@ -6,7 +6,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class CommandInterpreterAPICase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/frame/TestFrameUtils.py b/packages/Python/lldbsuite/test/python_api/lldbutil/frame/TestFrameUtils.py index 2cde05af0c39..09a5bc126571 100644 --- a/packages/Python/lldbsuite/test/python_api/lldbutil/frame/TestFrameUtils.py +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/frame/TestFrameUtils.py @@ -8,7 +8,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class FrameUtilsTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py index 07177c1fae4a..90f879d37610 100644 --- a/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py @@ -9,7 +9,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class LLDBIteratorTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestRegistersIterator.py b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestRegistersIterator.py index 1645ae1f2a5d..84ef44d2dd73 100644 --- a/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestRegistersIterator.py +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestRegistersIterator.py @@ -9,7 +9,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class RegistersIteratorTestCase(TestBase): @@ -22,7 +24,7 @@ class RegistersIteratorTestCase(TestBase): self.line1 = line_number('main.cpp', '// Set break point at this line.') @add_test_categories(['pyapi']) - @expectedFailureWindows # Test crashes + @expectedFailureAll(oslist=["windows"]) def test_iter_registers(self): """Test iterator works correctly for lldbutil.iter_registers().""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py b/packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py index 97bfa3956f6c..fafd05fd92c8 100644 --- a/packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py @@ -9,7 +9,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ThreadsStackTracesTestCase(TestBase): @@ -26,7 +28,9 @@ class ThreadsStackTracesTestCase(TestBase): #The __thread_start function in libc doesn't contain any epilogue and prologue instructions #hence unwinding fail when we are stopped in __thread_start @expectedFailureAll(triple = 'mips*') - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + @expectedFlakeyAndroid("llvm.org/26492", archs=["arm"]) + @expectedFlakeyLinux("llvm.org/pr27687") @add_test_categories(['pyapi']) def test_stack_traces(self): """Test SBprocess and SBThread APIs with printing of the stack traces.""" diff --git a/packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py b/packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py index 2de026c54eef..859edd80ee83 100644 --- a/packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py +++ b/packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py @@ -9,7 +9,9 @@ from __future__ import print_function import os, time import re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil from lldbsuite.test.lldbutil import symbol_type_to_str class ModuleAndSectionAPIsTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/objc_type/TestObjCType.py b/packages/Python/lldbsuite/test/python_api/objc_type/TestObjCType.py index e9b29b90e1a6..b81c422863cb 100644 --- a/packages/Python/lldbsuite/test/python_api/objc_type/TestObjCType.py +++ b/packages/Python/lldbsuite/test/python_api/objc_type/TestObjCType.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ObjCSBTypeTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py b/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py index f312bc8a9247..d5f407155b29 100644 --- a/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py +++ b/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb -from lldbsuite.test.lldbutil import get_stopped_thread, state_type_to_str +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test.lldbutil import get_stopped_thread, state_type_to_str class ProcessAPITestCase(TestBase): @@ -56,7 +57,7 @@ class ProcessAPITestCase(TestBase): self.expect(content, "Result from SBProcess.ReadMemory() matches our expected output: 'x'", exe=False, - startstr = 'x') + startstr = b'x') # Read (char *)my_char_ptr. val = frame.FindValue("my_char_ptr", lldb.eValueTypeVariableGlobal) @@ -154,7 +155,7 @@ class ProcessAPITestCase(TestBase): self.expect(content, "Result from SBProcess.ReadMemory() matches our expected output: 'a'", exe=False, - startstr = 'a') + startstr = b'a') @add_test_categories(['pyapi']) def test_access_my_int(self): @@ -206,9 +207,8 @@ class ProcessAPITestCase(TestBase): # But we want to use the WriteMemory() API to assign 256 to the variable. # Now use WriteMemory() API to write 256 into the global variable. - new_value = str(bytes) error = lldb.SBError() - result = process.WriteMemory(location, new_value, error) + result = process.WriteMemory(location, bytes, error) if not error.Success() or result != byteSize: self.fail("SBProcess.WriteMemory() failed") @@ -230,20 +230,18 @@ class ProcessAPITestCase(TestBase): if not error.Success(): self.fail("SBProcess.ReadMemory() failed") - # Use "ascii" as the encoding because each element of 'content' is in the range [0..255]. - new_bytes = bytearray(content, "ascii") - # The bytearray_to_int utility function expects a little endian bytearray. if byteOrder == lldb.eByteOrderBig: - new_bytes.reverse() + content = bytearray(content, 'ascii') + content.reverse() - new_value = bytearray_to_int(new_bytes, byteSize) + new_value = bytearray_to_int(content, byteSize) if new_value != 256: self.fail("Memory content read from 'my_int' does not match (int)256") # Dump the memory content.... if self.TraceOn(): - for i in new_bytes: + for i in content: print("byte:", i) @add_test_categories(['pyapi']) diff --git a/packages/Python/lldbsuite/test/python_api/process/io/TestProcessIO.py b/packages/Python/lldbsuite/test/python_api/process/io/TestProcessIO.py index 2944ee78acf1..1a194035f4de 100644 --- a/packages/Python/lldbsuite/test/python_api/process/io/TestProcessIO.py +++ b/packages/Python/lldbsuite/test/python_api/process/io/TestProcessIO.py @@ -6,8 +6,9 @@ from __future__ import print_function import os, sys, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class ProcessIOTestCase(TestBase): @@ -29,6 +30,7 @@ class ProcessIOTestCase(TestBase): @skipIfWindows # stdio manipulation unsupported on Windows @add_test_categories(['pyapi']) + @expectedFlakeyLinux(bugnumber="llvm.org/pr26437") def test_stdin_by_api(self): """Exercise SBProcess.PutSTDIN().""" self.build() @@ -39,6 +41,7 @@ class ProcessIOTestCase(TestBase): @skipIfWindows # stdio manipulation unsupported on Windows @add_test_categories(['pyapi']) + @expectedFlakeyLinux(bugnumber="llvm.org/pr26437") def test_stdin_redirection(self): """Exercise SBLaunchInfo::AddOpenFileAction() for STDIN without specifying STDOUT or STDERR.""" self.build() @@ -50,6 +53,7 @@ class ProcessIOTestCase(TestBase): @skipIfWindows # stdio manipulation unsupported on Windows @add_test_categories(['pyapi']) + @expectedFlakeyLinux(bugnumber="llvm.org/pr26437") def test_stdout_redirection(self): """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT without specifying STDIN or STDERR.""" self.build() @@ -62,6 +66,7 @@ class ProcessIOTestCase(TestBase): @skipIfWindows # stdio manipulation unsupported on Windows @add_test_categories(['pyapi']) + @expectedFlakeyLinux(bugnumber="llvm.org/pr26437") def test_stderr_redirection(self): """Exercise SBLaunchInfo::AddOpenFileAction() for STDERR without specifying STDIN or STDOUT.""" self.build() @@ -74,6 +79,7 @@ class ProcessIOTestCase(TestBase): @skipIfWindows # stdio manipulation unsupported on Windows @add_test_categories(['pyapi']) + @expectedFlakeyLinux(bugnumber="llvm.org/pr26437") def test_stdout_stderr_redirection(self): """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT and STDERR without redirecting STDIN.""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/sbdata/TestSBData.py b/packages/Python/lldbsuite/test/python_api/sbdata/TestSBData.py index 2ff516e10d8e..d8e9515973f7 100644 --- a/packages/Python/lldbsuite/test/python_api/sbdata/TestSBData.py +++ b/packages/Python/lldbsuite/test/python_api/sbdata/TestSBData.py @@ -4,11 +4,12 @@ from __future__ import print_function +from math import fabs import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from math import fabs -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SBDataAPICase(TestBase): @@ -38,8 +39,9 @@ class SBDataAPICase(TestBase): target = self.dbg.GetSelectedTarget() process = target.GetProcess() - - thread = process.GetThreadAtIndex(0) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertIsNotNone(thread) frame = thread.GetSelectedFrame() if self.TraceOn(): @@ -184,7 +186,10 @@ class SBDataAPICase(TestBase): self.assertTrue(new_object.GetValue() == "1", 'new_object == 1') - data.SetData(error, 'A\0\0\0', data.GetByteOrder(), data.GetAddressByteSize()) + if data.GetByteOrder() == lldb.eByteOrderBig: + data.SetData(error, '\0\0\0A', data.GetByteOrder(), data.GetAddressByteSize()) + else: + data.SetData(error, 'A\0\0\0', data.GetByteOrder(), data.GetAddressByteSize()) self.assertTrue(error.Success()) data2 = lldb.SBData() @@ -309,8 +314,8 @@ class SBDataAPICase(TestBase): self.assert_data(data2.GetSignedInt32, 4, -2) data2.SetDataFromSInt64Array([2, -2]) - self.assert_data(data2.GetSignedInt32, 0, 2) - self.assert_data(data2.GetSignedInt32, 8, -2) + self.assert_data(data2.GetSignedInt64, 0, 2) + self.assert_data(data2.GetSignedInt64, 8, -2) data2.SetDataFromUInt32Array([1,2,3,4,5]) self.assert_data(data2.GetUnsignedInt32, 0, 1) diff --git a/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/TestSBTypeTypeClass.py b/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/TestSBTypeTypeClass.py index 80305e303d03..49bc148dd579 100644 --- a/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/TestSBTypeTypeClass.py +++ b/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/TestSBTypeTypeClass.py @@ -1,4 +1,4 @@ -import lldbsuite.test.lldbinline as lldbinline -import lldbsuite.test.lldbtest as lldbtest +from lldbsuite.test import decorators +from lldbsuite.test import lldbinline -lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIfFreeBSD,decorators.skipIfLinux,decorators.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/TestSBValuePersist.py b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/TestSBValuePersist.py index 6edbbda4c112..e726db7c2d08 100644 --- a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/TestSBValuePersist.py +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/TestSBValuePersist.py @@ -6,15 +6,16 @@ from __future__ import print_function import os, sys, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SBValuePersistTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24772") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24772") def test(self): """Test SBValue::Persist""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/section/TestSectionAPI.py b/packages/Python/lldbsuite/test/python_api/section/TestSectionAPI.py index 587216468f06..29e089f6b84d 100644 --- a/packages/Python/lldbsuite/test/python_api/section/TestSectionAPI.py +++ b/packages/Python/lldbsuite/test/python_api/section/TestSectionAPI.py @@ -5,8 +5,9 @@ Test SBSection APIs. from __future__ import print_function - +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SectionAPITestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/signals/TestSignalsAPI.py b/packages/Python/lldbsuite/test/python_api/signals/TestSignalsAPI.py index 9825c553cce9..733b0c9d6764 100644 --- a/packages/Python/lldbsuite/test/python_api/signals/TestSignalsAPI.py +++ b/packages/Python/lldbsuite/test/python_api/signals/TestSignalsAPI.py @@ -8,14 +8,15 @@ from __future__ import print_function import os, time import lldb -from lldbsuite.test.lldbutil import get_stopped_thread, state_type_to_str +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +from lldbsuite.test.lldbutil import get_stopped_thread, state_type_to_str class SignalsAPITestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) - @expectedFlakeyLinux # this test fails 1/100 dosep runs @skipIfWindows # Windows doesn't have signals def test_ignore_signal(self): """Test Python SBUnixSignals.Suppress/Stop/Notify() API.""" diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/TestSymbolContext.py b/packages/Python/lldbsuite/test/python_api/symbol-context/TestSymbolContext.py index 2fec8dba0365..5d0d01d7a2b6 100644 --- a/packages/Python/lldbsuite/test/python_api/symbol-context/TestSymbolContext.py +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/TestSymbolContext.py @@ -6,11 +6,14 @@ from __future__ import print_function -import os, time +import os import re +import time + import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SymbolContextAPITestCase(TestBase): @@ -23,7 +26,7 @@ class SymbolContextAPITestCase(TestBase): self.line = line_number('main.c', '// Find the line number of function "c" here.') @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test(self): """Exercise SBSymbolContext API extensively.""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/Makefile b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/Makefile new file mode 100644 index 000000000000..650a8b261bea --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := file1.cpp file2.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/TestSymbolContextTwoFiles.py b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/TestSymbolContextTwoFiles.py new file mode 100644 index 000000000000..1d8d70114573 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/TestSymbolContextTwoFiles.py @@ -0,0 +1,36 @@ +""" +Test SBSymbolContext APIs. +""" + +from __future__ import print_function + +import os + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class SymbolContextTwoFilesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @expectedFailureAll(oslist=["windows"]) + def test_lookup_by_address(self): + """Test lookup by address in a module with multiple compilation units""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + module = target.GetModuleAtIndex(0) + self.assertTrue(module.IsValid()) + for symbol_name in ["struct1::f()", "struct2::f()"]: + sc_list = module.FindFunctions(symbol_name, lldb.eSymbolTypeCode) + self.assertTrue(1, sc_list.GetSize()) + symbol_address = sc_list.GetContextAtIndex(0).GetSymbol().GetStartAddress() + self.assertTrue(symbol_address.IsValid()) + sc_by_address = module.ResolveSymbolContextForAddress(symbol_address, lldb.eSymbolContextFunction) + self.assertEqual(symbol_name, sc_by_address.GetFunction().GetName()) diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/decls.h b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/decls.h new file mode 100644 index 000000000000..0cb685622cd0 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/decls.h @@ -0,0 +1,11 @@ +struct struct1 +{ + static void + f(); +}; + +struct struct2 +{ + static void + f(); +}; diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/file1.cpp b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/file1.cpp new file mode 100644 index 000000000000..16c8ce7d9488 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/file1.cpp @@ -0,0 +1,13 @@ +#include "decls.h" + +void +struct1::f() +{ +} + +int main() +{ + struct1::f(); + struct2::f(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/file2.cpp b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/file2.cpp new file mode 100644 index 000000000000..3bd1aaf95a73 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/two-files/file2.cpp @@ -0,0 +1,6 @@ +#include "decls.h" + +void +struct2::f() +{ +} diff --git a/packages/Python/lldbsuite/test/python_api/target/TestTargetAPI.py b/packages/Python/lldbsuite/test/python_api/target/TestTargetAPI.py index 0231d285ecf9..1278742675f3 100644 --- a/packages/Python/lldbsuite/test/python_api/target/TestTargetAPI.py +++ b/packages/Python/lldbsuite/test/python_api/target/TestTargetAPI.py @@ -10,8 +10,9 @@ import unittest2 import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TargetAPITestCase(TestBase): @@ -41,7 +42,7 @@ class TargetAPITestCase(TestBase): self.find_global_variables('b.out') @add_test_categories(['pyapi']) - @expectedFailureWindows("llvm.org/pr24778") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_find_functions(self): """Exercise SBTarget.FindFunctions() API.""" d = {'EXE': 'b.out'} diff --git a/packages/Python/lldbsuite/test/python_api/thread/TestThreadAPI.py b/packages/Python/lldbsuite/test/python_api/thread/TestThreadAPI.py index dad829a48f2f..588aa66cf53e 100644 --- a/packages/Python/lldbsuite/test/python_api/thread/TestThreadAPI.py +++ b/packages/Python/lldbsuite/test/python_api/thread/TestThreadAPI.py @@ -8,8 +8,10 @@ from __future__ import print_function import os, time import lldb -from lldbsuite.test.lldbutil import get_stopped_thread, get_caller_symbol +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +from lldbsuite.test.lldbutil import get_stopped_thread, get_caller_symbol class ThreadAPITestCase(TestBase): @@ -37,8 +39,8 @@ class ThreadAPITestCase(TestBase): self.run_to_address(self.exe_name) @add_test_categories(['pyapi']) - @expectedFailureFreeBSD # llvm.org/pr20476 - @expectedFailureWindows # Test crashes + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr20476') + @expectedFailureAll(oslist=["windows"]) def test_step_out_of_malloc_into_function_b(self): """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" # We build a different executable than the default build() does. diff --git a/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py b/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py index d9e5719844e2..20e899beee45 100644 --- a/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py +++ b/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py @@ -6,11 +6,14 @@ from __future__ import print_function -import os, time +import os import re +import time + import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TypeAndTypeListTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py index 77ff07ea6488..2a53177d28af 100644 --- a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py +++ b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py @@ -4,13 +4,14 @@ Test some SBValue APIs. from __future__ import print_function - - -import os, time +import os import re +import time + import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ValueAPITestCase(TestBase): @@ -24,7 +25,7 @@ class ValueAPITestCase(TestBase): # Find the line number to of function 'c'. self.line = line_number('main.c', '// Break at this line') - @expectedFailureWindows("llvm.org/pr24772") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24772") @add_test_categories(['pyapi']) def test(self): """Exercise some SBValue APIs.""" @@ -133,3 +134,12 @@ class ValueAPITestCase(TestBase): val_a = target.EvaluateExpression('a') self.assertTrue(val_s.GetChildMemberWithName('a').AddressOf(), VALID_VARIABLE) self.assertTrue(val_a.Cast(val_i.GetType()).AddressOf(), VALID_VARIABLE) + + self.assertTrue(int(lldb.value(frame0.FindVariable('uinthex'))) == 3768803088, 'uinthex == 3768803088') + self.assertTrue(int(lldb.value(frame0.FindVariable('sinthex'))) == -526164208, 'sinthex == -526164208') + + self.assertTrue(frame0.FindVariable('uinthex').GetValueAsUnsigned() == 3768803088, 'unsigned uinthex == 3768803088') + self.assertTrue(frame0.FindVariable('sinthex').GetValueAsUnsigned() == 3768803088, 'unsigned sinthex == 3768803088') + + self.assertTrue(frame0.FindVariable('uinthex').GetValueAsSigned() == -526164208, 'signed uinthex == -526164208') + self.assertTrue(frame0.FindVariable('sinthex').GetValueAsSigned() == -526164208, 'signed sinthex == -526164208') diff --git a/packages/Python/lldbsuite/test/python_api/value/change_values/TestChangeValueAPI.py b/packages/Python/lldbsuite/test/python_api/value/change_values/TestChangeValueAPI.py index f8ad97277f05..52c91e0b2621 100644 --- a/packages/Python/lldbsuite/test/python_api/value/change_values/TestChangeValueAPI.py +++ b/packages/Python/lldbsuite/test/python_api/value/change_values/TestChangeValueAPI.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ChangeValueAPITestCase(TestBase): @@ -26,9 +27,9 @@ class ChangeValueAPITestCase(TestBase): self.check_line = line_number('main.c', '// Stop here and check values') self.end_line = line_number ('main.c', '// Set a breakpoint here at the end') - @expectedFailureWindows("llvm.org/pr24772") @add_test_categories(['pyapi']) @expectedFlakeyLinux("llvm.org/pr25652") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24772") def test_change_value(self): """Exercise the SBValue::SetValueFromCString API.""" d = {'EXE': self.exe_name} diff --git a/packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py b/packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py index 8b60be97bdc2..879efd186d68 100644 --- a/packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py +++ b/packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py @@ -10,8 +10,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class ValueAsLinkedListTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/value/main.c b/packages/Python/lldbsuite/test/python_api/value/main.c index a00795750de0..2ebe3ad303cf 100644 --- a/packages/Python/lldbsuite/test/python_api/value/main.c +++ b/packages/Python/lldbsuite/test/python_api/value/main.c @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// #include +#include // This simple program is to test the lldb Python API SBValue.GetChildAtIndex(). @@ -38,6 +39,9 @@ struct MyStruct int main (int argc, char const *argv[]) { + uint32_t uinthex = 0xE0A35F10; + int32_t sinthex = 0xE0A35F10; + int i; MyInt a = 12345; struct MyStruct s = { 11, 22 }; diff --git a/packages/Python/lldbsuite/test/python_api/value_var_update/TestValueVarUpdate.py b/packages/Python/lldbsuite/test/python_api/value_var_update/TestValueVarUpdate.py index 251bbcf4b24d..8620117386f9 100644 --- a/packages/Python/lldbsuite/test/python_api/value_var_update/TestValueVarUpdate.py +++ b/packages/Python/lldbsuite/test/python_api/value_var_update/TestValueVarUpdate.py @@ -7,7 +7,9 @@ from __future__ import print_function import os, sys, time import lldb import time +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class HelloWorldTestCase(TestBase): diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py b/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py index 264e21240dd9..bedf286e199b 100644 --- a/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SetWatchpointAPITestCase(TestBase): @@ -26,7 +27,8 @@ class SetWatchpointAPITestCase(TestBase): @add_test_categories(['pyapi']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ def test_watch_val(self): """Exercise SBValue.Watch() API to set a watchpoint.""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py b/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py index a15e73347030..d7b45a533e39 100644 --- a/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class WatchpointIgnoreCountTestCase(TestBase): @@ -26,7 +27,8 @@ class WatchpointIgnoreCountTestCase(TestBase): @add_test_categories(['pyapi']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") + @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ def test_set_watch_ignore_count(self): """Test SBWatchpoint.SetIgnoreCount() API.""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py b/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py index 315450280675..8bbb93af07e5 100644 --- a/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py @@ -6,11 +6,14 @@ from __future__ import print_function -import os, time +import os import re +import time + import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class WatchpointIteratorTestCase(TestBase): @@ -26,7 +29,7 @@ class WatchpointIteratorTestCase(TestBase): @add_test_categories(['pyapi']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watch_iter(self): """Exercise SBTarget.watchpoint_iter() API to iterate on the available watchpoints.""" self.build() @@ -55,7 +58,7 @@ class WatchpointIteratorTestCase(TestBase): # Watch 'global' for read and write. value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal) error = lldb.SBError(); - watchpoint = value.Watch(True, True, True, error) + watchpoint = value.Watch(True, False, True, error) self.assertTrue(value and watchpoint, "Successfully found the variable and set a watchpoint") self.DebugSBValue(value) diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/condition/TestWatchpointConditionAPI.py b/packages/Python/lldbsuite/test/python_api/watchpoint/condition/TestWatchpointConditionAPI.py index f30bf856aa07..b368cc066615 100644 --- a/packages/Python/lldbsuite/test/python_api/watchpoint/condition/TestWatchpointConditionAPI.py +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/condition/TestWatchpointConditionAPI.py @@ -8,8 +8,9 @@ from __future__ import print_function import os, time import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class WatchpointConditionAPITestCase(TestBase): @@ -29,6 +30,7 @@ class WatchpointConditionAPITestCase(TestBase): self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureAll(oslist=["linux"], archs=["aarch64"], bugnumber="llvm.org/pr27710") @skipIfWindows # Watchpoints not supported on Windows, and this test hangs def test_watchpoint_cond_api(self): """Test watchpoint condition API.""" diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py index 5a4a464657d6..d0a2c2fff128 100644 --- a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py @@ -6,11 +6,14 @@ from __future__ import print_function -import os, time +import os import re +import time + import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SetWatchlocationAPITestCase(TestBase): @@ -28,7 +31,7 @@ class SetWatchlocationAPITestCase(TestBase): @add_test_categories(['pyapi']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watch_location(self): """Exercise SBValue.WatchPointee() API to set a watchpoint.""" self.build() diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py index 6facbaa8f2e9..468f3131f337 100644 --- a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py @@ -9,8 +9,9 @@ from __future__ import print_function import os, time import re import lldb -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TargetWatchAddressAPITestCase(TestBase): @@ -28,7 +29,7 @@ class TargetWatchAddressAPITestCase(TestBase): @add_test_categories(['pyapi']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported - @expectedFailureWindows("llvm.org/pr24446") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows") def test_watch_address(self): """Exercise SBTarget.WatchAddress() API to set a watchpoint.""" self.build() @@ -92,6 +93,7 @@ class TargetWatchAddressAPITestCase(TestBase): @add_test_categories(['pyapi']) @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported @skipIf(archs=['mips', 'mipsel', 'mips64', 'mips64el']) # No size constraint on MIPS for watches + @skipIf(archs=['s390x']) # Likewise on SystemZ def test_watch_address_with_invalid_watch_size(self): """Exercise SBTarget.WatchAddress() API but pass an invalid watch_size.""" self.build() diff --git a/packages/Python/lldbsuite/test/result_formatter.py b/packages/Python/lldbsuite/test/result_formatter.py deleted file mode 100644 index 44474918895e..000000000000 --- a/packages/Python/lldbsuite/test/result_formatter.py +++ /dev/null @@ -1,1304 +0,0 @@ -""" - The LLVM Compiler Infrastructure - -This file is distributed under the University of Illinois Open Source -License. See LICENSE.TXT for details. - -Provides classes used by the test results reporting infrastructure -within the LLDB test suite. -""" - -from __future__ import print_function -from __future__ import absolute_import - -# System modules -import argparse -import importlib -import inspect -import os -import pprint -import socket -import sys -import threading -import time -import traceback - -# Third-party modules -import six -from six.moves import cPickle - -# LLDB modules -from . import configuration - -import lldbsuite - - -# Ignore method count on DTOs. -# pylint: disable=too-few-public-methods -class FormatterConfig(object): - """Provides formatter configuration info to create_results_formatter().""" - def __init__(self): - self.filename = None - self.port = None - self.formatter_name = None - self.formatter_options = None - - -# Ignore method count on DTOs. -# pylint: disable=too-few-public-methods -class CreatedFormatter(object): - """Provides transfer object for returns from create_results_formatter().""" - def __init__(self, formatter, cleanup_func): - self.formatter = formatter - self.cleanup_func = cleanup_func - - -def create_results_formatter(config): - """Sets up a test results formatter. - - @param config an instance of FormatterConfig - that indicates how to setup the ResultsFormatter. - - @return an instance of CreatedFormatter. - """ - def create_socket(port): - """Creates a socket to the localhost on the given port. - - @param port the port number of the listenering port on - the localhost. - - @return (socket object, socket closing function) - """ - def socket_closer(open_sock): - """Close down an opened socket properly.""" - open_sock.shutdown(socket.SHUT_RDWR) - open_sock.close() - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect(("localhost", port)) - return (sock, lambda: socket_closer(sock)) - - default_formatter_name = None - results_file_object = None - cleanup_func = None - - if config.filename: - # Open the results file for writing. - if config.filename == 'stdout': - results_file_object = sys.stdout - cleanup_func = None - elif config.filename == 'stderr': - results_file_object = sys.stderr - cleanup_func = None - else: - results_file_object = open(config.filename, "w") - cleanup_func = results_file_object.close - default_formatter_name = ( - "lldbsuite.test.xunit_formatter.XunitFormatter") - elif config.port: - # Connect to the specified localhost port. - results_file_object, cleanup_func = create_socket(config.port) - default_formatter_name = ( - "lldbsuite.test.result_formatter.RawPickledFormatter") - - # If we have a results formatter name specified and we didn't specify - # a results file, we should use stdout. - if config.formatter_name is not None and results_file_object is None: - # Use stdout. - results_file_object = sys.stdout - cleanup_func = None - - if results_file_object: - # We care about the formatter. Choose user-specified or, if - # none specified, use the default for the output type. - if config.formatter_name: - formatter_name = config.formatter_name - else: - formatter_name = default_formatter_name - - # Create an instance of the class. - # First figure out the package/module. - components = formatter_name.split(".") - module = importlib.import_module(".".join(components[:-1])) - - # Create the class name we need to load. - cls = getattr(module, components[-1]) - - # Handle formatter options for the results formatter class. - formatter_arg_parser = cls.arg_parser() - if config.formatter_options and len(config.formatter_options) > 0: - command_line_options = config.formatter_options - else: - command_line_options = [] - - formatter_options = formatter_arg_parser.parse_args( - command_line_options) - - # Create the TestResultsFormatter given the processed options. - results_formatter_object = cls(results_file_object, formatter_options) - - def shutdown_formatter(): - """Shuts down the formatter when it is no longer needed.""" - # Tell the formatter to write out anything it may have - # been saving until the very end (e.g. xUnit results - # can't complete its output until this point). - results_formatter_object.send_terminate_as_needed() - - # And now close out the output file-like object. - if cleanup_func is not None: - cleanup_func() - - return CreatedFormatter( - results_formatter_object, - shutdown_formatter) - else: - return None - - -class EventBuilder(object): - """Helper class to build test result event dictionaries.""" - - BASE_DICTIONARY = None - - # Test Event Types - TYPE_JOB_RESULT = "job_result" - TYPE_TEST_RESULT = "test_result" - TYPE_TEST_START = "test_start" - TYPE_MARK_TEST_RERUN_ELIGIBLE = "test_eligible_for_rerun" - TYPE_MARK_TEST_EXPECTED_FAILURE = "test_expected_failure" - TYPE_SESSION_TERMINATE = "terminate" - - RESULT_TYPES = set([ - TYPE_JOB_RESULT, - TYPE_TEST_RESULT - ]) - - # Test/Job Status Tags - STATUS_EXCEPTIONAL_EXIT = "exceptional_exit" - STATUS_SUCCESS = "success" - STATUS_FAILURE = "failure" - STATUS_EXPECTED_FAILURE = "expected_failure" - STATUS_EXPECTED_TIMEOUT = "expected_timeout" - STATUS_UNEXPECTED_SUCCESS = "unexpected_success" - STATUS_SKIP = "skip" - STATUS_ERROR = "error" - STATUS_TIMEOUT = "timeout" - - """Test methods or jobs with a status matching any of these - status values will cause a testrun failure, unless - the test methods rerun and do not trigger an issue when rerun.""" - TESTRUN_ERROR_STATUS_VALUES = set([ - STATUS_ERROR, - STATUS_EXCEPTIONAL_EXIT, - STATUS_FAILURE, - STATUS_TIMEOUT - ]) - - @staticmethod - def _get_test_name_info(test): - """Returns (test-class-name, test-method-name) from a test case instance. - - @param test a unittest.TestCase instance. - - @return tuple containing (test class name, test method name) - """ - test_class_components = test.id().split(".") - test_class_name = ".".join(test_class_components[:-1]) - test_name = test_class_components[-1] - return (test_class_name, test_name) - - @staticmethod - def bare_event(event_type): - """Creates an event with default additions, event type and timestamp. - - @param event_type the value set for the "event" key, used - to distinguish events. - - @returns an event dictionary with all default additions, the "event" - key set to the passed in event_type, and the event_time value set to - time.time(). - """ - if EventBuilder.BASE_DICTIONARY is not None: - # Start with a copy of the "always include" entries. - event = dict(EventBuilder.BASE_DICTIONARY) - else: - event = {} - - event.update({ - "event": event_type, - "event_time": time.time() - }) - return event - - @staticmethod - def _event_dictionary_common(test, event_type): - """Returns an event dictionary setup with values for the given event type. - - @param test the unittest.TestCase instance - - @param event_type the name of the event type (string). - - @return event dictionary with common event fields set. - """ - test_class_name, test_name = EventBuilder._get_test_name_info(test) - - # Determine the filename for the test case. If there is an attribute - # for it, use it. Otherwise, determine from the TestCase class path. - if hasattr(test, "test_filename"): - test_filename = test.test_filename - else: - test_filename = inspect.getfile(test.__class__) - - event = EventBuilder.bare_event(event_type) - event.update({ - "test_class": test_class_name, - "test_name": test_name, - "test_filename": test_filename - }) - - return event - - @staticmethod - def _error_tuple_class(error_tuple): - """Returns the unittest error tuple's error class as a string. - - @param error_tuple the error tuple provided by the test framework. - - @return the error type (typically an exception) raised by the - test framework. - """ - type_var = error_tuple[0] - module = inspect.getmodule(type_var) - if module: - return "{}.{}".format(module.__name__, type_var.__name__) - else: - return type_var.__name__ - - @staticmethod - def _error_tuple_message(error_tuple): - """Returns the unittest error tuple's error message. - - @param error_tuple the error tuple provided by the test framework. - - @return the error message provided by the test framework. - """ - return str(error_tuple[1]) - - @staticmethod - def _error_tuple_traceback(error_tuple): - """Returns the unittest error tuple's error message. - - @param error_tuple the error tuple provided by the test framework. - - @return the error message provided by the test framework. - """ - return error_tuple[2] - - @staticmethod - def _event_dictionary_test_result(test, status): - """Returns an event dictionary with common test result fields set. - - @param test a unittest.TestCase instance. - - @param status the status/result of the test - (e.g. "success", "failure", etc.) - - @return the event dictionary - """ - event = EventBuilder._event_dictionary_common( - test, EventBuilder.TYPE_TEST_RESULT) - event["status"] = status - return event - - @staticmethod - def _event_dictionary_issue(test, status, error_tuple): - """Returns an event dictionary with common issue-containing test result - fields set. - - @param test a unittest.TestCase instance. - - @param status the status/result of the test - (e.g. "success", "failure", etc.) - - @param error_tuple the error tuple as reported by the test runner. - This is of the form (type, error). - - @return the event dictionary - """ - event = EventBuilder._event_dictionary_test_result(test, status) - event["issue_class"] = EventBuilder._error_tuple_class(error_tuple) - event["issue_message"] = EventBuilder._error_tuple_message(error_tuple) - backtrace = EventBuilder._error_tuple_traceback(error_tuple) - if backtrace is not None: - event["issue_backtrace"] = traceback.format_tb(backtrace) - return event - - @staticmethod - def event_for_start(test): - """Returns an event dictionary for the test start event. - - @param test a unittest.TestCase instance. - - @return the event dictionary - """ - return EventBuilder._event_dictionary_common( - test, EventBuilder.TYPE_TEST_START) - - @staticmethod - def event_for_success(test): - """Returns an event dictionary for a successful test. - - @param test a unittest.TestCase instance. - - @return the event dictionary - """ - return EventBuilder._event_dictionary_test_result( - test, EventBuilder.STATUS_SUCCESS) - - @staticmethod - def event_for_unexpected_success(test, bugnumber): - """Returns an event dictionary for a test that succeeded but was - expected to fail. - - @param test a unittest.TestCase instance. - - @param bugnumber the issue identifier for the bug tracking the - fix request for the test expected to fail (but is in fact - passing here). - - @return the event dictionary - - """ - event = EventBuilder._event_dictionary_test_result( - test, EventBuilder.STATUS_UNEXPECTED_SUCCESS) - if bugnumber: - event["bugnumber"] = str(bugnumber) - return event - - @staticmethod - def event_for_failure(test, error_tuple): - """Returns an event dictionary for a test that failed. - - @param test a unittest.TestCase instance. - - @param error_tuple the error tuple as reported by the test runner. - This is of the form (type, error). - - @return the event dictionary - """ - return EventBuilder._event_dictionary_issue( - test, EventBuilder.STATUS_FAILURE, error_tuple) - - @staticmethod - def event_for_expected_failure(test, error_tuple, bugnumber): - """Returns an event dictionary for a test that failed as expected. - - @param test a unittest.TestCase instance. - - @param error_tuple the error tuple as reported by the test runner. - This is of the form (type, error). - - @param bugnumber the issue identifier for the bug tracking the - fix request for the test expected to fail. - - @return the event dictionary - - """ - event = EventBuilder._event_dictionary_issue( - test, EventBuilder.STATUS_EXPECTED_FAILURE, error_tuple) - if bugnumber: - event["bugnumber"] = str(bugnumber) - return event - - @staticmethod - def event_for_skip(test, reason): - """Returns an event dictionary for a test that was skipped. - - @param test a unittest.TestCase instance. - - @param reason the reason why the test is being skipped. - - @return the event dictionary - """ - event = EventBuilder._event_dictionary_test_result( - test, EventBuilder.STATUS_SKIP) - event["skip_reason"] = reason - return event - - @staticmethod - def event_for_error(test, error_tuple): - """Returns an event dictionary for a test that hit a test execution error. - - @param test a unittest.TestCase instance. - - @param error_tuple the error tuple as reported by the test runner. - This is of the form (type, error). - - @return the event dictionary - """ - return EventBuilder._event_dictionary_issue( - test, EventBuilder.STATUS_ERROR, error_tuple) - - @staticmethod - def event_for_cleanup_error(test, error_tuple): - """Returns an event dictionary for a test that hit a test execution error - during the test cleanup phase. - - @param test a unittest.TestCase instance. - - @param error_tuple the error tuple as reported by the test runner. - This is of the form (type, error). - - @return the event dictionary - """ - event = EventBuilder._event_dictionary_issue( - test, EventBuilder.STATUS_ERROR, error_tuple) - event["issue_phase"] = "cleanup" - return event - - @staticmethod - def event_for_job_exceptional_exit( - pid, worker_index, exception_code, exception_description, - test_filename, command_line): - """Creates an event for a job (i.e. process) exit due to signal. - - @param pid the process id for the job that failed - @param worker_index optional id for the job queue running the process - @param exception_code optional code - (e.g. SIGTERM integer signal number) - @param exception_description optional string containing symbolic - representation of the issue (e.g. "SIGTERM") - @param test_filename the path to the test filename that exited - in some exceptional way. - @param command_line the Popen-style list provided as the command line - for the process that timed out. - - @return an event dictionary coding the job completion description. - """ - event = EventBuilder.bare_event(EventBuilder.TYPE_JOB_RESULT) - event["status"] = EventBuilder.STATUS_EXCEPTIONAL_EXIT - if pid is not None: - event["pid"] = pid - if worker_index is not None: - event["worker_index"] = int(worker_index) - if exception_code is not None: - event["exception_code"] = exception_code - if exception_description is not None: - event["exception_description"] = exception_description - if test_filename is not None: - event["test_filename"] = test_filename - if command_line is not None: - event["command_line"] = command_line - return event - - @staticmethod - def event_for_job_timeout(pid, worker_index, test_filename, command_line): - """Creates an event for a job (i.e. process) timeout. - - @param pid the process id for the job that timed out - @param worker_index optional id for the job queue running the process - @param test_filename the path to the test filename that timed out. - @param command_line the Popen-style list provided as the command line - for the process that timed out. - - @return an event dictionary coding the job completion description. - """ - event = EventBuilder.bare_event(EventBuilder.TYPE_JOB_RESULT) - event["status"] = "timeout" - if pid is not None: - event["pid"] = pid - if worker_index is not None: - event["worker_index"] = int(worker_index) - if test_filename is not None: - event["test_filename"] = test_filename - if command_line is not None: - event["command_line"] = command_line - return event - - @staticmethod - def event_for_mark_test_rerun_eligible(test): - """Creates an event that indicates the specified test is explicitly - eligible for rerun. - - Note there is a mode that will enable test rerun eligibility at the - global level. These markings for explicit rerun eligibility are - intended for the mode of running where only explicitly rerunnable - tests are rerun upon hitting an issue. - - @param test the TestCase instance to which this pertains. - - @return an event that specifies the given test as being eligible to - be rerun. - """ - event = EventBuilder._event_dictionary_common( - test, - EventBuilder.TYPE_MARK_TEST_RERUN_ELIGIBLE) - return event - - @staticmethod - def event_for_mark_test_expected_failure(test): - """Creates an event that indicates the specified test is expected - to fail. - - @param test the TestCase instance to which this pertains. - - @return an event that specifies the given test is expected to fail. - """ - event = EventBuilder._event_dictionary_common( - test, - EventBuilder.TYPE_MARK_TEST_EXPECTED_FAILURE) - return event - - @staticmethod - def add_entries_to_all_events(entries_dict): - """Specifies a dictionary of entries to add to all test events. - - This provides a mechanism for, say, a parallel test runner to - indicate to each inferior dotest.py that it should add a - worker index to each. - - Calling this method replaces all previous entries added - by a prior call to this. - - Event build methods will overwrite any entries that collide. - Thus, the passed in dictionary is the base, which gets merged - over by event building when keys collide. - - @param entries_dict a dictionary containing key and value - pairs that should be merged into all events created by the - event generator. May be None to clear out any extra entries. - """ - EventBuilder.BASE_DICTIONARY = dict(entries_dict) - - -class ResultsFormatter(object): - """Provides interface to formatting test results out to a file-like object. - - This class allows the LLDB test framework's raw test-realted - events to be processed and formatted in any manner desired. - Test events are represented by python dictionaries, formatted - as in the EventBuilder class above. - - ResultFormatter instances are given a file-like object in which - to write their results. - - ResultFormatter lifetime looks like the following: - - # The result formatter is created. - # The argparse options dictionary is generated from calling - # the SomeResultFormatter.arg_parser() with the options data - # passed to dotest.py via the "--results-formatter-options" - # argument. See the help on that for syntactic requirements - # on getting that parsed correctly. - formatter = SomeResultFormatter(file_like_object, argpared_options_dict) - - # Single call to session start, before parsing any events. - formatter.begin_session() - - formatter.handle_event({"event":"initialize",...}) - - # Zero or more calls specified for events recorded during the test session. - # The parallel test runner manages getting results from all the inferior - # dotest processes, so from a new format perspective, don't worry about - # that. The formatter will be presented with a single stream of events - # sandwiched between a single begin_session()/end_session() pair in the - # parallel test runner process/thread. - for event in zero_or_more_test_events(): - formatter.handle_event(event) - - # Single call to terminate/wrap-up. Formatters that need all the - # data before they can print a correct result (e.g. xUnit/JUnit), - # this is where the final report can be generated. - formatter.handle_event({"event":"terminate",...}) - - It is not the formatter's responsibility to close the file_like_object. - (i.e. do not close it). - - The lldb test framework passes these test events in real time, so they - arrive as they come in. - - In the case of the parallel test runner, the dotest inferiors - add a 'pid' field to the dictionary that indicates which inferior - pid generated the event. - - Note more events may be added in the future to support richer test - reporting functionality. One example: creating a true flaky test - result category so that unexpected successes really mean the test - is marked incorrectly (either should be marked flaky, or is indeed - passing consistently now and should have the xfail marker - removed). In this case, a flaky_success and flaky_fail event - likely will be added to capture these and support reporting things - like percentages of flaky test passing so we can see if we're - making some things worse/better with regards to failure rates. - - Another example: announcing all the test methods that are planned - to be run, so we can better support redo operations of various kinds - (redo all non-run tests, redo non-run tests except the one that - was running [perhaps crashed], etc.) - - Implementers are expected to override all the public methods - provided in this class. See each method's docstring to see - expectations about when the call should be chained. - - """ - @classmethod - def arg_parser(cls): - """@return arg parser used to parse formatter-specific options.""" - parser = argparse.ArgumentParser( - description='{} options'.format(cls.__name__), - usage=('dotest.py --results-formatter-options=' - '"--option1 value1 [--option2 value2 [...]]"')) - parser.add_argument( - "--dump-results", - action="store_true", - help=('dump the raw results data after printing ' - 'the summary output.')) - return parser - - def __init__(self, out_file, options): - super(ResultsFormatter, self).__init__() - self.out_file = out_file - self.options = options - self.using_terminal = False - if not self.out_file: - raise Exception("ResultsFormatter created with no file object") - self.start_time_by_test = {} - self.terminate_called = False - - # Store counts of test_result events by status. - self.result_status_counts = { - EventBuilder.STATUS_SUCCESS: 0, - EventBuilder.STATUS_EXPECTED_FAILURE: 0, - EventBuilder.STATUS_EXPECTED_TIMEOUT: 0, - EventBuilder.STATUS_SKIP: 0, - EventBuilder.STATUS_UNEXPECTED_SUCCESS: 0, - EventBuilder.STATUS_FAILURE: 0, - EventBuilder.STATUS_ERROR: 0, - EventBuilder.STATUS_TIMEOUT: 0, - EventBuilder.STATUS_EXCEPTIONAL_EXIT: 0 - } - - # Track the most recent test start event by worker index. - # We'll use this to assign TIMEOUT and exceptional - # exits to the most recent test started on a given - # worker index. - self.started_tests_by_worker = {} - - # Store the most recent test_method/job status. - self.result_events = {} - - # Track the number of test method reruns. - self.test_method_rerun_count = 0 - - # Lock that we use while mutating inner state, like the - # total test count and the elements. We minimize how - # long we hold the lock just to keep inner state safe, not - # entirely consistent from the outside. - self.lock = threading.RLock() - - # Keeps track of the test base filenames for tests that - # are expected to timeout. If a timeout occurs in any test - # basename that matches this list, that result should be - # converted into a non-issue. We'll create an expected - # timeout test status for this. - self.expected_timeouts_by_basename = set() - - # Tests which have reported that they are expecting to fail. These will - # be marked as expected failures even if they return a failing status, - # probably because they crashed or deadlocked. - self.expected_failures = set() - - # Keep track of rerun-eligible tests. - # This is a set that contains tests saved as: - # {test_filename}:{test_class}:{test_name} - self.rerun_eligible_tests = set() - - # A dictionary of test files that had a failing - # test, in the format of: - # key = test path, value = array of test methods that need rerun - self.tests_for_rerun = {} - - @classmethod - def _make_key(cls, result_event): - """Creates a key from a test or job result event. - - This key attempts to be as unique as possible. For - test result events, it will be unique per test method. - For job events (ones not promoted to a test result event), - it will be unique per test case file. - - @return a string-based key of the form - {test_filename}:{test_class}.{test_name} - """ - if result_event is None: - return None - component_count = 0 - if "test_filename" in result_event: - key = result_event["test_filename"] - component_count += 1 - if "test_class" in result_event: - if component_count > 0: - key += ":" - key += result_event["test_class"] - component_count += 1 - if "test_name" in result_event: - if component_count > 0: - key += "." - key += result_event["test_name"] - component_count += 1 - return key - - def _mark_test_as_expected_failure(self, test_result_event): - key = self._make_key(test_result_event) - if key is not None: - self.expected_failures.add(key) - else: - sys.stderr.write( - "\nerror: test marked as expected failure but " - "failed to create key.\n") - - def _mark_test_for_rerun_eligibility(self, test_result_event): - key = self._make_key(test_result_event) - if key is not None: - self.rerun_eligible_tests.add(key) - else: - sys.stderr.write( - "\nerror: test marked for re-run eligibility but " - "failed to create key.\n") - - def _maybe_add_test_to_rerun_list(self, result_event): - key = self._make_key(result_event) - if key is not None: - if (key in self.rerun_eligible_tests or - configuration.rerun_all_issues): - test_filename = result_event.get("test_filename", None) - if test_filename is not None: - test_name = result_event.get("test_name", None) - if test_filename not in self.tests_for_rerun: - self.tests_for_rerun[test_filename] = [] - if test_name is not None: - self.tests_for_rerun[test_filename].append(test_name) - else: - sys.stderr.write( - "\nerror: couldn't add testrun-failing test to rerun " - "list because no eligibility key could be created.\n") - - def _maybe_remap_job_result_event(self, test_event): - """Remaps timeout/exceptional exit job results to last test method running. - - @param test_event the job_result test event. This is an in/out - parameter. It will be modified if it can be mapped to a test_result - of the same status, using details from the last-running test method - known to be most recently started on the same worker index. - """ - test_start = None - - job_status = test_event["status"] - if job_status in [ - EventBuilder.STATUS_TIMEOUT, - EventBuilder.STATUS_EXCEPTIONAL_EXIT]: - worker_index = test_event.get("worker_index", None) - if worker_index is not None: - test_start = self.started_tests_by_worker.get( - worker_index, None) - - # If we have a test start to remap, do it here. - if test_start is not None: - test_event["event"] = EventBuilder.TYPE_TEST_RESULT - - # Fill in all fields from test start not present in - # job status message. - for (start_key, start_value) in test_start.items(): - if start_key not in test_event: - test_event[start_key] = start_value - - def _maybe_remap_expected_timeout(self, event): - if event is None: - return - - status = event.get("status", None) - if status is None or status != EventBuilder.STATUS_TIMEOUT: - return - - # Check if the timeout test's basename is in the expected timeout - # list. If so, convert to an expected timeout. - basename = os.path.basename(event.get("test_filename", "")) - if basename in self.expected_timeouts_by_basename: - # Convert to an expected timeout. - event["status"] = EventBuilder.STATUS_EXPECTED_TIMEOUT - - def _maybe_remap_expected_failure(self, event): - if event is None: - return - - key = self._make_key(event) - if key not in self.expected_failures: - return - - status = event.get("status", None) - if status in EventBuilder.TESTRUN_ERROR_STATUS_VALUES: - event["status"] = EventBuilder.STATUS_EXPECTED_FAILURE - elif status == EventBuilder.STATUS_SUCCESS: - event["status"] = EventBuilder.STATUS_UNEXPECTED_SUCCESS - - def handle_event(self, test_event): - """Handles the test event for collection into the formatter output. - - Derived classes may override this but should call down to this - implementation first. - - @param test_event the test event as formatted by one of the - event_for_* calls. - """ - with self.lock: - # Keep track of whether terminate was received. We do this so - # that a process can call the 'terminate' event on its own, to - # close down a formatter at the appropriate time. Then the - # atexit() cleanup can call the "terminate if it hasn't been - # called yet". - if test_event is not None: - event_type = test_event.get("event", "") - # We intentionally allow event_type to be checked anew - # after this check below since this check may rewrite - # the event type - if event_type == EventBuilder.TYPE_JOB_RESULT: - # Possibly convert the job status (timeout, exceptional exit) - # to an appropriate test_result event. - self._maybe_remap_job_result_event(test_event) - event_type = test_event.get("event", "") - - # Remap timeouts to expected timeouts. - if event_type in EventBuilder.RESULT_TYPES: - self._maybe_remap_expected_timeout(test_event) - self._maybe_remap_expected_failure(test_event) - event_type = test_event.get("event", "") - - if event_type == "terminate": - self.terminate_called = True - elif event_type in EventBuilder.RESULT_TYPES: - # Keep track of event counts per test/job result status type. - # The only job (i.e. inferior process) results that make it - # here are ones that cannot be remapped to the most recently - # started test for the given worker index. - status = test_event["status"] - self.result_status_counts[status] += 1 - # Clear the most recently started test for the related worker. - worker_index = test_event.get("worker_index", None) - if worker_index is not None: - self.started_tests_by_worker.pop(worker_index, None) - - if status in EventBuilder.TESTRUN_ERROR_STATUS_VALUES: - # A test/job status value in any of those status values - # causes a testrun failure. If such a test fails, check - # whether it can be rerun. If it can be rerun, add it - # to the rerun job. - self._maybe_add_test_to_rerun_list(test_event) - - # Build the test key. - test_key = self._make_key(test_event) - if test_key is None: - raise Exception( - "failed to find test filename for " - "test event {}".format(test_event)) - - # Save the most recent test event for the test key. - # This allows a second test phase to overwrite the most - # recent result for the test key (unique per method). - # We do final reporting at the end, so we'll report based - # on final results. - # We do this so that a re-run caused by, perhaps, the need - # to run a low-load, single-worker test run can have the final - # run's results to always be used. - if test_key in self.result_events: - # We are replacing the result of something that was - # already counted by the base class. Remove the double - # counting by reducing by one the count for the test - # result status. - old_status = self.result_events[test_key]["status"] - self.result_status_counts[old_status] -= 1 - self.test_method_rerun_count += 1 - self.result_events[test_key] = test_event - elif event_type == EventBuilder.TYPE_TEST_START: - # Track the start time for the test method. - self.track_start_time( - test_event["test_class"], - test_event["test_name"], - test_event["event_time"]) - # Track of the most recent test method start event - # for the related worker. This allows us to figure - # out whether a process timeout or exceptional exit - # can be charged (i.e. assigned) to a test method. - worker_index = test_event.get("worker_index", None) - if worker_index is not None: - self.started_tests_by_worker[worker_index] = test_event - - elif event_type == EventBuilder.TYPE_MARK_TEST_RERUN_ELIGIBLE: - self._mark_test_for_rerun_eligibility(test_event) - elif event_type == EventBuilder.TYPE_MARK_TEST_EXPECTED_FAILURE: - self._mark_test_as_expected_failure(test_event) - - def set_expected_timeouts_by_basename(self, basenames): - """Specifies a list of test file basenames that are allowed to timeout - without being called out as a timeout issue. - - These fall into a new status category called STATUS_EXPECTED_TIMEOUT. - """ - if basenames is not None: - for basename in basenames: - self.expected_timeouts_by_basename.add(basename) - - def track_start_time(self, test_class, test_name, start_time): - """tracks the start time of a test so elapsed time can be computed. - - this alleviates the need for test results to be processed serially - by test. it will save the start time for the test so that - elapsed_time_for_test() can compute the elapsed time properly. - """ - if test_class is None or test_name is None: - return - - test_key = "{}.{}".format(test_class, test_name) - self.start_time_by_test[test_key] = start_time - - def elapsed_time_for_test(self, test_class, test_name, end_time): - """returns the elapsed time for a test. - - this function can only be called once per test and requires that - the track_start_time() method be called sometime prior to calling - this method. - """ - if test_class is None or test_name is None: - return -2.0 - - test_key = "{}.{}".format(test_class, test_name) - if test_key not in self.start_time_by_test: - return -1.0 - else: - start_time = self.start_time_by_test[test_key] - del self.start_time_by_test[test_key] - return end_time - start_time - - def is_using_terminal(self): - """returns true if this results formatter is using the terminal and - output should be avoided.""" - return self.using_terminal - - def send_terminate_as_needed(self): - """sends the terminate event if it hasn't been received yet.""" - if not self.terminate_called: - terminate_event = EventBuilder.bare_event("terminate") - self.handle_event(terminate_event) - - # Derived classes may require self access - # pylint: disable=no-self-use - def replaces_summary(self): - """Returns whether the results formatter includes a summary - suitable to replace the old lldb test run results. - - @return True if the lldb test runner can skip its summary - generation when using this results formatter; False otherwise. - """ - return False - - def counts_by_test_result_status(self, status): - """Returns number of test method results for the given status. - - @status_result a test result status (e.g. success, fail, skip) - as defined by the EventBuilder.STATUS_* class members. - - @return an integer returning the number of test methods matching - the given test result status. - """ - return self.result_status_counts[status] - - @classmethod - def _event_sort_key(cls, event): - """Returns the sort key to be used for a test event. - - This method papers over the differences in a test method result vs. a - job (i.e. inferior process) result. - - @param event a test result or job result event. - @return a key useful for sorting events by name (test name preferably, - then by test filename). - """ - if "test_name" in event: - return event["test_name"] - else: - return event.get("test_filename", None) - - def _partition_results_by_status(self, categories): - """Partitions the captured test results by event status. - - This permits processing test results by the category ids. - - @param categories the list of categories on which to partition. - Follows the format described in _report_category_details(). - - @return a dictionary where each key is the test result status, - and each entry is a list containing all the test result events - that matched that test result status. Result status IDs with - no matching entries will have a zero-length list. - """ - partitioned_events = {} - for category in categories: - result_status_id = category[0] - matching_events = [ - [key, event] for (key, event) in self.result_events.items() - if event.get("status", "") == result_status_id] - partitioned_events[result_status_id] = sorted( - matching_events, - key=lambda x: self._event_sort_key(x[1])) - return partitioned_events - - def _print_banner(self, out_file, banner_text): - """Prints an ASCII banner around given text. - - Output goes to the out file for the results formatter. - - @param out_file a file-like object where output will be written. - @param banner_text the text to display, with a banner - of '=' around the line above and line below. - """ - banner_separator = "".ljust(len(banner_text), "=") - - out_file.write("\n{}\n{}\n{}\n".format( - banner_separator, - banner_text, - banner_separator)) - - def _print_summary_counts( - self, out_file, categories, result_events_by_status, extra_rows): - """Prints summary counts for all categories. - - @param out_file a file-like object used to print output. - - @param categories the list of categories on which to partition. - Follows the format described in _report_category_details(). - - @param result_events_by_status the partitioned list of test - result events in a dictionary, with the key set to the test - result status id and the value set to the list of test method - results that match the status id. - """ - - # Get max length for category printed name - category_with_max_printed_name = max( - categories, key=lambda x: len(x[1])) - max_category_name_length = len(category_with_max_printed_name[1]) - - # If we are provided with extra rows, consider these row name lengths. - if extra_rows is not None: - for row in extra_rows: - name_length = len(row[0]) - if name_length > max_category_name_length: - max_category_name_length = name_length - - self._print_banner(out_file, "Test Result Summary") - - # Prepend extra rows - if extra_rows is not None: - for row in extra_rows: - extra_label = "{}:".format(row[0]).ljust( - max_category_name_length + 1) - out_file.write("{} {:4}\n".format(extra_label, row[1])) - - for category in categories: - result_status_id = category[0] - result_label = "{}:".format(category[1]).ljust( - max_category_name_length + 1) - count = len(result_events_by_status[result_status_id]) - out_file.write("{} {:4}\n".format( - result_label, - count)) - - @classmethod - def _has_printable_details(cls, categories, result_events_by_status): - """Returns whether there are any test result details that need to be printed. - - This will spin through the results and see if any result in a category - that is printable has any results to print. - - @param categories the list of categories on which to partition. - Follows the format described in _report_category_details(). - - @param result_events_by_status the partitioned list of test - result events in a dictionary, with the key set to the test - result status id and the value set to the list of test method - results that match the status id. - - @return True if there are any details (i.e. test results - for failures, errors, unexpected successes); False otherwise. - """ - for category in categories: - result_status_id = category[0] - print_matching_tests = category[2] - if print_matching_tests: - if len(result_events_by_status[result_status_id]) > 0: - # We found a printable details test result status - # that has details to print. - return True - # We didn't find any test result category with printable - # details. - return False - - def _report_category_details(self, out_file, category, result_events_by_status): - """Reports all test results matching the given category spec. - - @param out_file a file-like object used to print output. - - @param category a category spec of the format [test_event_name, - printed_category_name, print_matching_entries?] - - @param result_events_by_status the partitioned list of test - result events in a dictionary, with the key set to the test - result status id and the value set to the list of test method - results that match the status id. - """ - result_status_id = category[0] - print_matching_tests = category[2] - detail_label = category[3] - - if print_matching_tests: - # Sort by test name - for (_, event) in result_events_by_status[result_status_id]: - # Convert full test path into test-root-relative. - test_relative_path = os.path.relpath( - os.path.realpath(event["test_filename"]), - lldbsuite.lldb_test_root) - - # Create extra info component (used for exceptional exit info) - if result_status_id == EventBuilder.STATUS_EXCEPTIONAL_EXIT: - extra_info = "[EXCEPTIONAL EXIT {} ({})] ".format( - event["exception_code"], - event["exception_description"]) - else: - extra_info = "" - - # Figure out the identity we will use for this test. - if configuration.verbose and ("test_class" in event): - test_id = "{}.{}".format( - event["test_class"], event["test_name"]) - elif "test_name" in event: - test_id = event["test_name"] - else: - test_id = "" - - # Display the info. - out_file.write("{}: {}{} ({})\n".format( - detail_label, - extra_info, - test_id, - test_relative_path)) - - def print_results(self, out_file): - """Writes the test result report to the output file. - - @param out_file a file-like object used for printing summary - results. This is different than self.out_file, which might - be something else for non-summary data. - """ - extra_results = [ - # Total test methods processed, excluding reruns. - ["Test Methods", len(self.result_events)], - ["Reruns", self.test_method_rerun_count]] - - # Output each of the test result entries. - categories = [ - # result id, printed name, print matching tests?, detail label - [EventBuilder.STATUS_SUCCESS, - "Success", False, None], - [EventBuilder.STATUS_EXPECTED_FAILURE, - "Expected Failure", False, None], - [EventBuilder.STATUS_FAILURE, - "Failure", True, "FAIL"], - [EventBuilder.STATUS_ERROR, - "Error", True, "ERROR"], - [EventBuilder.STATUS_EXCEPTIONAL_EXIT, - "Exceptional Exit", True, "ERROR"], - [EventBuilder.STATUS_UNEXPECTED_SUCCESS, - "Unexpected Success", True, "UNEXPECTED SUCCESS"], - [EventBuilder.STATUS_SKIP, "Skip", False, None], - [EventBuilder.STATUS_TIMEOUT, - "Timeout", True, "TIMEOUT"], - [EventBuilder.STATUS_EXPECTED_TIMEOUT, - # Intentionally using the unusual hyphenation in TIME-OUT to - # prevent buildbots from thinking it is an issue when scanning - # for TIMEOUT. - "Expected Timeout", True, "EXPECTED TIME-OUT"] - ] - - # Partition all the events by test result status - result_events_by_status = self._partition_results_by_status( - categories) - - # Print the details - have_details = self._has_printable_details( - categories, result_events_by_status) - if have_details: - self._print_banner(out_file, "Issue Details") - for category in categories: - self._report_category_details( - out_file, category, result_events_by_status) - - # Print the summary - self._print_summary_counts( - out_file, categories, result_events_by_status, extra_results) - - if self.options.dump_results: - # Debug dump of the key/result info for all categories. - self._print_banner("Results Dump") - for status, events_by_key in result_events_by_status.items(): - out_file.write("\nSTATUS: {}\n".format(status)) - for key, event in events_by_key: - out_file.write("key: {}\n".format(key)) - out_file.write("event: {}\n".format(event)) - - -class RawPickledFormatter(ResultsFormatter): - """Formats events as a pickled stream. - - The parallel test runner has inferiors pickle their results and send them - over a socket back to the parallel test. The parallel test runner then - aggregates them into the final results formatter (e.g. xUnit). - """ - - @classmethod - def arg_parser(cls): - """@return arg parser used to parse formatter-specific options.""" - parser = super(RawPickledFormatter, cls).arg_parser() - return parser - - def __init__(self, out_file, options): - super(RawPickledFormatter, self).__init__(out_file, options) - self.pid = os.getpid() - - def handle_event(self, test_event): - super(RawPickledFormatter, self).handle_event(test_event) - - # Convert initialize/terminate events into job_begin/job_end events. - event_type = test_event["event"] - if event_type is None: - return - - if event_type == "initialize": - test_event["event"] = "job_begin" - elif event_type == "terminate": - test_event["event"] = "job_end" - - # Tack on the pid. - test_event["pid"] = self.pid - - # Send it as {serialized_length_of_serialized_bytes}{serialized_bytes} - import struct - msg = cPickle.dumps(test_event) - packet = struct.pack("!I%ds" % len(msg), len(msg), msg) - self.out_file.send(packet) - - -class DumpFormatter(ResultsFormatter): - """Formats events to the file as their raw python dictionary format.""" - - def handle_event(self, test_event): - super(DumpFormatter, self).handle_event(test_event) - self.out_file.write("\n" + pprint.pformat(test_event) + "\n") diff --git a/packages/Python/lldbsuite/test/settings/TestSettings.py b/packages/Python/lldbsuite/test/settings/TestSettings.py index 1d1912495551..9592fa9d6dfb 100644 --- a/packages/Python/lldbsuite/test/settings/TestSettings.py +++ b/packages/Python/lldbsuite/test/settings/TestSettings.py @@ -8,7 +8,9 @@ from __future__ import print_function import os, time, re import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SettingsCommandTestCase(TestBase): @@ -174,7 +176,7 @@ class SettingsCommandTestCase(TestBase): self.expect("settings show auto-confirm", SETTING_MSG("auto-confirm"), startstr = "auto-confirm (boolean) = false") - @skipUnlessArch(['x86_64', 'i386', 'i686']) + @skipIf(archs=no_match(['x86_64', 'i386', 'i686'])) def test_disassembler_settings(self): """Test that user options for the disassembler take effect.""" self.build() @@ -208,7 +210,6 @@ class SettingsCommandTestCase(TestBase): self.expect("disassemble -n numberfn", substrs = ["5ah"]) - @expectedFailureWindows("llvm.org/pr24579") def test_run_args_and_env_vars(self): """Test that run-args and env-vars are passed to the launched process.""" self.build() @@ -311,8 +312,11 @@ class SettingsCommandTestCase(TestBase): with open('stderr.txt', 'r') as f: output = f.read() - self.expect(output, exe=False, - startstr = "This message should go to standard error.") + message = "This message should go to standard error." + if lldbplatformutil.hasChattyStderr(self): + self.expect(output, exe=False, substrs = [message]) + else: + self.expect(output, exe=False, startstr = message) # The 'stdout.txt' file should now exist. self.assertTrue(os.path.isfile("stdout.txt"), diff --git a/packages/Python/lldbsuite/test/settings/quoting/TestQuoting.py b/packages/Python/lldbsuite/test/settings/quoting/TestQuoting.py index 878fc8a50675..67c535d649fd 100644 --- a/packages/Python/lldbsuite/test/settings/quoting/TestQuoting.py +++ b/packages/Python/lldbsuite/test/settings/quoting/TestQuoting.py @@ -6,9 +6,14 @@ from __future__ import print_function -import os, time, re +import os +import re +import time + import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class SettingsCommandTestCase(TestBase): @@ -23,7 +28,7 @@ class SettingsCommandTestCase(TestBase): def test_no_quote(self): self.do_test_args("a b c", "a\0b\0c\0") - @expectedFailureWindows("http://llvm.org/pr24557") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24557") @no_debug_info_test def test_single_quote(self): self.do_test_args("'a b c'", "a b c\0") @@ -32,17 +37,17 @@ class SettingsCommandTestCase(TestBase): def test_double_quote(self): self.do_test_args('"a b c"', "a b c\0") - @expectedFailureWindows("http://llvm.org/pr24557") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24557") @no_debug_info_test def test_single_quote_escape(self): self.do_test_args("'a b\\' c", "a b\\\0c\0") - @expectedFailureWindows("http://llvm.org/pr24557") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24557") @no_debug_info_test def test_double_quote_escape(self): self.do_test_args('"a b\\" c"', 'a b" c\0') - @expectedFailureWindows("http://llvm.org/pr24557") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24557") @no_debug_info_test def test_double_quote_escape2(self): self.do_test_args('"a b\\\\" c', 'a b\\\0c\0') @@ -51,7 +56,7 @@ class SettingsCommandTestCase(TestBase): def test_single_in_double(self): self.do_test_args('"a\'b"', "a'b\0") - @expectedFailureWindows("http://llvm.org/pr24557") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24557") @no_debug_info_test def test_double_in_single(self): self.do_test_args("'a\"b'", 'a"b\0') @@ -64,7 +69,7 @@ class SettingsCommandTestCase(TestBase): def test_bare_single(self): self.do_test_args("a\\'b", "a'b\0") - @expectedFailureWindows("http://llvm.org/pr24557") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24557") @no_debug_info_test def test_bare_double(self): self.do_test_args('a\\"b', 'a"b\0') diff --git a/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py b/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py index b4e7541a709a..93e1789103ce 100644 --- a/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py +++ b/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py @@ -14,8 +14,9 @@ from __future__ import print_function import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class SourceManagerTestCase(TestBase): @@ -80,13 +81,17 @@ class SourceManagerTestCase(TestBase): main_c_hidden = os.path.join("hidden", main_c) os.rename(main_c, main_c_hidden) + # Restore main.c after the test. + self.addTearDownHook(lambda: os.rename(main_c_hidden, main_c)) + if self.TraceOn(): system([["ls"]]) system([["ls", "hidden"]]) - # Restore main.c after the test. - self.addTearDownHook(lambda: os.rename(main_c_hidden, main_c)) - + # Set source remapping with invalid replace path and verify we get an error + self.expect("settings set target.source-map /a/b/c/d/e /q/r/s/t/u", error=True, + substrs = ['''error: the replacement path doesn't exist: "/q/r/s/t/u"''']) + # Set target.source-map settings. self.runCmd("settings set target.source-map %s %s" % (os.getcwd(), os.path.join(os.getcwd(), "hidden"))) # And verify that the settings work. @@ -133,7 +138,7 @@ class SourceManagerTestCase(TestBase): self.assertTrue(int(m.group(1)) > 0) # Read the main.c file content. - with open('main.c', 'r') as f: + with io.open('main.c', 'r', newline='\n') as f: original_content = f.read() if self.TraceOn(): print("original content:", original_content) @@ -145,7 +150,7 @@ class SourceManagerTestCase(TestBase): def restore_file(): #print("os.path.getmtime() before restore:", os.path.getmtime('main.c')) time.sleep(1) - with open('main.c', 'wb') as f: + with io.open('main.c', 'w', newline='\n') as f: f.write(original_content) if self.TraceOn(): with open('main.c', 'r') as f: @@ -156,9 +161,8 @@ class SourceManagerTestCase(TestBase): print("os.path.getmtime() after restore:", os.path.getmtime('main.c')) - # Modify the source code file. - with open('main.c', 'wb') as f: + with io.open('main.c', 'w', newline='\n') as f: time.sleep(1) f.write(new_content) if self.TraceOn(): @@ -170,3 +174,21 @@ class SourceManagerTestCase(TestBase): # Display the source code again. We should see the updated line. self.expect("source list -f main.c -l %d" % self.line, SOURCE_DISPLAYED_CORRECTLY, substrs = ['Hello lldb']) + + def test_set_breakpoint_with_absolute_path(self): + self.build() + self.runCmd("settings set target.source-map %s %s" % (os.getcwd(), os.path.join(os.getcwd(), "hidden"))) + + exe = os.path.join(os.getcwd(), "a.out") + main = os.path.join(os.getcwd(), "hidden", "main.c") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, main, self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'main.c:%d' % self.line, + 'stop reason = breakpoint']) diff --git a/packages/Python/lldbsuite/test/terminal/TestSTTYBeforeAndAfter.py b/packages/Python/lldbsuite/test/terminal/TestSTTYBeforeAndAfter.py index 335042737d44..6644681d2ca1 100644 --- a/packages/Python/lldbsuite/test/terminal/TestSTTYBeforeAndAfter.py +++ b/packages/Python/lldbsuite/test/terminal/TestSTTYBeforeAndAfter.py @@ -8,7 +8,9 @@ from __future__ import print_function import os import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestSTTYBeforeAndAfter(TestBase): @@ -22,7 +24,7 @@ class TestSTTYBeforeAndAfter(TestBase): cls.RemoveTempFile("child_send2.txt") cls.RemoveTempFile("child_read2.txt") - @expectedFailureHostWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(hostoslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @no_debug_info_test def test_stty_dash_a_before_and_afetr_invoking_lldb_command(self): """Test that 'stty -a' displays the same output before and after running the lldb command.""" diff --git a/packages/Python/lldbsuite/test/test_categories.py b/packages/Python/lldbsuite/test/test_categories.py index 72b7afdf7241..0a85293109e7 100644 --- a/packages/Python/lldbsuite/test/test_categories.py +++ b/packages/Python/lldbsuite/test/test_categories.py @@ -11,9 +11,11 @@ import sys # Third-party modules # LLDB modules +from lldbsuite.support import gmodules + debug_info_categories = [ - 'dwarf', 'dwo', 'dsym' + 'dwarf', 'dwo', 'dsym', 'gmodules' ] all_categories = { @@ -21,6 +23,7 @@ all_categories = { 'dwarf' : 'Tests that can be run with DWARF debug information', 'dwo' : 'Tests that can be run with DWO debug information', 'dsym' : 'Tests that can be run with DSYM debug information', + 'gmodules' : 'Tests that can be run with -gmodules debug information', 'expression' : 'Tests related to the expression parser', 'objc' : 'Tests related to the Objective-C programming language support', 'pyapi' : 'Tests related to the Python API', @@ -42,12 +45,27 @@ def unique_string_match(yourentry, list): candidate = item return candidate -def is_supported_on_platform(category, platform): + +def is_supported_on_platform(category, platform, compiler_paths): if category == "dwo": # -gsplit-dwarf is not implemented by clang on Windows. return platform in ["linux", "freebsd"] elif category == "dsym": return platform in ["darwin", "macosx", "ios"] + elif category == "gmodules": + # First, check to see if the platform can even support gmodules. + if platform not in ["linux", "freebsd", "darwin", "macosx", "ios"]: + return False + # If all compilers specified support gmodules, we'll enable it. + for compiler_path in compiler_paths: + if not gmodules.is_compiler_clang_with_gmodules(compiler_path): + # Ideally in a multi-compiler scenario during a single test run, this would + # allow gmodules on compilers that support it and not on ones that don't. + # However, I didn't see an easy way for all the callers of this to know + # the compiler being used for a test invocation. As we tend to run with + # a single compiler per test run, this shouldn't be a major issue. + return False + return True return True def validate(categories, exact_match): diff --git a/packages/Python/lldbsuite/test/test_result.py b/packages/Python/lldbsuite/test/test_result.py index 9665d672a79a..01db1f691636 100644 --- a/packages/Python/lldbsuite/test/test_result.py +++ b/packages/Python/lldbsuite/test/test_result.py @@ -13,15 +13,15 @@ from __future__ import print_function # System modules import inspect +import os # Third-party modules import unittest2 # LLDB Modules -import lldbsuite from . import configuration -from .result_formatter import EventBuilder - +from lldbsuite.test_event.event_builder import EventBuilder +from lldbsuite.test_event import build_exception class LLDBTestResult(unittest2.TextTestResult): """ @@ -113,8 +113,6 @@ class LLDBTestResult(unittest2.TextTestResult): def hardMarkAsSkipped(self,test): getattr(test, test._testMethodName).__func__.__unittest_skip__ = True getattr(test, test._testMethodName).__func__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" - test.__class__.__unittest_skip__ = True - test.__class__.__unittest_skip_why__ = "test case does not fall in any category of interest for this run" def startTest(self, test): if configuration.shouldSkipBecauseOfCategories(self.getCategoriesForTest(test)): @@ -140,17 +138,48 @@ class LLDBTestResult(unittest2.TextTestResult): self.results_formatter.handle_event( EventBuilder.event_for_success(test)) + def _isBuildError(self, err_tuple): + exception = err_tuple[1] + return isinstance(exception, build_exception.BuildError) + + def _getTestPath(self, test): + if test is None: + return "" + elif hasattr(test, "test_filename"): + return test.test_filename + else: + return inspect.getsourcefile(test.__class__) + + + def _saveBuildErrorTuple(self, test, err): + # Adjust the error description so it prints the build command and build error + # rather than an uninformative Python backtrace. + build_error = err[1] + error_description = "{}\nTest Directory:\n{}".format( + str(build_error), + os.path.dirname(self._getTestPath(test))) + self.errors.append((test, error_description)) + self._mirrorOutput = True + def addError(self, test, err): configuration.sdir_has_content = True - super(LLDBTestResult, self).addError(test, err) + if self._isBuildError(err): + self._saveBuildErrorTuple(test, err) + else: + super(LLDBTestResult, self).addError(test, err) + method = getattr(test, "markError", None) if method: method() if configuration.parsable: self.stream.write("FAIL: LLDB (%s) :: %s\n" % (self._config_string(test), str(test))) if self.results_formatter: - self.results_formatter.handle_event( - EventBuilder.event_for_error(test, err)) + # Handle build errors as a separate event type + if self._isBuildError(err): + error_event = EventBuilder.event_for_build_error(test, err) + else: + error_event = EventBuilder.event_for_error(test, err) + self.results_formatter.handle_event(error_event) def addCleanupError(self, test, err): configuration.sdir_has_content = True diff --git a/packages/Python/lldbsuite/test/test_runner/__init__.py b/packages/Python/lldbsuite/test/test_runner/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/Python/lldbsuite/test/test_runner/lib/lldb_utils.py b/packages/Python/lldbsuite/test/test_runner/lib/lldb_utils.py deleted file mode 100644 index e469bbf12207..000000000000 --- a/packages/Python/lldbsuite/test/test_runner/lib/lldb_utils.py +++ /dev/null @@ -1,66 +0,0 @@ -""" -The LLVM Compiler Infrastructure - -This file is distributed under the University of Illinois Open Source -License. See LICENSE.TXT for details. - -Provides classes used by the test results reporting infrastructure -within the LLDB test suite. - - -This module contains utilities used by the lldb test framwork. -""" - - -class OptionalWith(object): - # pylint: disable=too-few-public-methods - # This is a wrapper - it is not meant to provide any extra methods. - """Provides a wrapper for objects supporting "with", allowing None. - - This lets a user use the "with object" syntax for resource usage - (e.g. locks) even when the wrapped with object is None. - - e.g. - - wrapped_lock = OptionalWith(thread.Lock()) - with wrapped_lock: - # Do something while the lock is obtained. - pass - - might_be_none = None - wrapped_none = OptionalWith(might_be_none) - with wrapped_none: - # This code here still works. - pass - - This prevents having to write code like this when - a lock is optional: - - if lock: - lock.acquire() - - try: - code_fragament_always_run() - finally: - if lock: - lock.release() - - And I'd posit it is safer, as it becomes impossible to - forget the try/finally using OptionalWith(), since - the with syntax can be used. - """ - def __init__(self, wrapped_object): - self.wrapped_object = wrapped_object - - def __enter__(self): - if self.wrapped_object is not None: - return self.wrapped_object.__enter__() - else: - return self - - def __exit__(self, the_type, value, traceback): - if self.wrapped_object is not None: - return self.wrapped_object.__exit__(the_type, value, traceback) - else: - # Don't suppress any exceptions - return False diff --git a/packages/Python/lldbsuite/test/test_runner/lib/process_control.py b/packages/Python/lldbsuite/test/test_runner/lib/process_control.py deleted file mode 100644 index a7e639e4b8b6..000000000000 --- a/packages/Python/lldbsuite/test/test_runner/lib/process_control.py +++ /dev/null @@ -1,705 +0,0 @@ -""" -The LLVM Compiler Infrastructure - -This file is distributed under the University of Illinois Open Source -License. See LICENSE.TXT for details. - -Provides classes used by the test results reporting infrastructure -within the LLDB test suite. - - -This module provides process-management support for the LLDB test -running infrasructure. -""" - -# System imports -import os -import re -import signal -import subprocess -import sys -import threading - - -class CommunicatorThread(threading.Thread): - """Provides a thread class that communicates with a subprocess.""" - def __init__(self, process, event, output_file): - super(CommunicatorThread, self).__init__() - # Don't let this thread prevent shutdown. - self.daemon = True - self.process = process - self.pid = process.pid - self.event = event - self.output_file = output_file - self.output = None - - def run(self): - try: - # Communicate with the child process. - # This will not complete until the child process terminates. - self.output = self.process.communicate() - except Exception as exception: # pylint: disable=broad-except - if self.output_file: - self.output_file.write( - "exception while using communicate() for pid: {}\n".format( - exception)) - finally: - # Signal that the thread's run is complete. - self.event.set() - - -# Provides a regular expression for matching gtimeout-based durations. -TIMEOUT_REGEX = re.compile(r"(^\d+)([smhd])?$") - - -def timeout_to_seconds(timeout): - """Converts timeout/gtimeout timeout values into seconds. - - @param timeout a timeout in the form of xm representing x minutes. - - @return None if timeout is None, or the number of seconds as a float - if a valid timeout format was specified. - """ - if timeout is None: - return None - else: - match = TIMEOUT_REGEX.match(timeout) - if match: - value = float(match.group(1)) - units = match.group(2) - if units is None: - # default is seconds. No conversion necessary. - return value - elif units == 's': - # Seconds. No conversion necessary. - return value - elif units == 'm': - # Value is in minutes. - return 60.0 * value - elif units == 'h': - # Value is in hours. - return (60.0 * 60.0) * value - elif units == 'd': - # Value is in days. - return 24 * (60.0 * 60.0) * value - else: - raise Exception("unexpected units value '{}'".format(units)) - else: - raise Exception("could not parse TIMEOUT spec '{}'".format( - timeout)) - - -class ProcessHelper(object): - """Provides an interface for accessing process-related functionality. - - This class provides a factory method that gives the caller a - platform-specific implementation instance of the class. - - Clients of the class should stick to the methods provided in this - base class. - - @see ProcessHelper.process_helper() - """ - def __init__(self): - super(ProcessHelper, self).__init__() - - @classmethod - def process_helper(cls): - """Returns a platform-specific ProcessHelper instance. - @return a ProcessHelper instance that does the right thing for - the current platform. - """ - - # If you add a new platform, create an instance here and - # return it. - if os.name == "nt": - return WindowsProcessHelper() - else: - # For all POSIX-like systems. - return UnixProcessHelper() - - def create_piped_process(self, command, new_process_group=True): - # pylint: disable=no-self-use,unused-argument - # As expected. We want derived classes to implement this. - """Creates a subprocess.Popen-based class with I/O piped to the parent. - - @param command the command line list as would be passed to - subprocess.Popen(). Use the list form rather than the string form. - - @param new_process_group indicates if the caller wants the - process to be created in its own process group. Each OS handles - this concept differently. It provides a level of isolation and - can simplify or enable terminating the process tree properly. - - @return a subprocess.Popen-like object. - """ - raise Exception("derived class must implement") - - def supports_soft_terminate(self): - # pylint: disable=no-self-use - # As expected. We want derived classes to implement this. - """Indicates if the platform supports soft termination. - - Soft termination is the concept of a terminate mechanism that - allows the target process to shut down nicely, but with the - catch that the process might choose to ignore it. - - Platform supporter note: only mark soft terminate as supported - if the target process has some way to evade the soft terminate - request; otherwise, just support the hard terminate method. - - @return True if the platform supports a soft terminate mechanism. - """ - # By default, we do not support a soft terminate mechanism. - return False - - def soft_terminate(self, popen_process, log_file=None, want_core=True): - # pylint: disable=no-self-use,unused-argument - # As expected. We want derived classes to implement this. - """Attempts to terminate the process in a polite way. - - This terminate method is intended to give the child process a - chance to clean up and exit on its own, possibly with a request - to drop a core file or equivalent (i.e. [mini-]crashdump, crashlog, - etc.) If new_process_group was set in the process creation method - and the platform supports it, this terminate call will attempt to - kill the whole process tree rooted in this child process. - - @param popen_process the subprocess.Popen-like object returned - by one of the process-creation methods of this class. - - @param log_file file-like object used to emit error-related - logging info. May be None if no error-related info is desired. - - @param want_core True if the caller would like to get a core - dump (or the analogous crash report) from the terminated process. - """ - popen_process.terminate() - - def hard_terminate(self, popen_process, log_file=None): - # pylint: disable=no-self-use,unused-argument - # As expected. We want derived classes to implement this. - """Attempts to terminate the process immediately. - - This terminate method is intended to kill child process in - a manner in which the child process has no ability to block, - and also has no ability to clean up properly. If new_process_group - was specified when creating the process, and if the platform - implementation supports it, this will attempt to kill the - whole process tree rooted in the child process. - - @param popen_process the subprocess.Popen-like object returned - by one of the process-creation methods of this class. - - @param log_file file-like object used to emit error-related - logging info. May be None if no error-related info is desired. - """ - popen_process.kill() - - def was_soft_terminate(self, returncode, with_core): - # pylint: disable=no-self-use,unused-argument - # As expected. We want derived classes to implement this. - """Returns if Popen-like object returncode matches soft terminate. - - @param returncode the returncode from the Popen-like object that - terminated with a given return code. - - @param with_core indicates whether the returncode should match - a core-generating return signal. - - @return True when the returncode represents what the system would - issue when a soft_terminate() with the given with_core arg occurred; - False otherwise. - """ - if not self.supports_soft_terminate(): - # If we don't support soft termination on this platform, - # then this should always be False. - return False - else: - # Once a platform claims to support soft terminate, it - # needs to be able to identify it by overriding this method. - raise Exception("platform needs to implement") - - def was_hard_terminate(self, returncode): - # pylint: disable=no-self-use,unused-argument - # As expected. We want derived classes to implement this. - """Returns if Popen-like object returncode matches that of a hard - terminate attempt. - - @param returncode the returncode from the Popen-like object that - terminated with a given return code. - - @return True when the returncode represents what the system would - issue when a hard_terminate() occurred; False - otherwise. - """ - raise Exception("platform needs to implement") - - def soft_terminate_signals(self): - # pylint: disable=no-self-use - """Retrieve signal numbers that can be sent to soft terminate. - @return a list of signal numbers that can be sent to soft terminate - a process, or None if not applicable. - """ - return None - - def is_exceptional_exit(self, popen_status): - """Returns whether the program exit status is exceptional. - - Returns whether the return code from a Popen process is exceptional - (e.g. signals on POSIX systems). - - Derived classes should override this if they can detect exceptional - program exit. - - @return True if the given popen_status represents an exceptional - program exit; False otherwise. - """ - return False - - def exceptional_exit_details(self, popen_status): - """Returns the normalized exceptional exit code and a description. - - Given an exceptional exit code, returns the integral value of the - exception (e.g. signal number for POSIX) and a description (e.g. - signal name on POSIX) for the result. - - Derived classes should override this if they can detect exceptional - program exit. - - It is fine to not implement this so long as is_exceptional_exit() - always returns False. - - @return (normalized exception code, symbolic exception description) - """ - raise Exception("exception_exit_details() called on unsupported class") - - -class UnixProcessHelper(ProcessHelper): - """Provides a ProcessHelper for Unix-like operating systems. - - This implementation supports anything that looks Posix-y - (e.g. Darwin, Linux, *BSD, etc.) - """ - def __init__(self): - super(UnixProcessHelper, self).__init__() - - @classmethod - def _create_new_process_group(cls): - """Creates a new process group for the calling process.""" - os.setpgid(os.getpid(), os.getpid()) - - def create_piped_process(self, command, new_process_group=True): - # Determine what to run after the fork but before the exec. - if new_process_group: - preexec_func = self._create_new_process_group - else: - preexec_func = None - - # Create the process. - process = subprocess.Popen( - command, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True, # Elicits automatic byte -> string decoding in Py3 - close_fds=True, - preexec_fn=preexec_func) - - # Remember whether we're using process groups for this - # process. - process.using_process_groups = new_process_group - return process - - def supports_soft_terminate(self): - # POSIX does support a soft terminate via: - # * SIGTERM (no core requested) - # * SIGQUIT (core requested if enabled, see ulimit -c) - return True - - @classmethod - def _validate_pre_terminate(cls, popen_process, log_file): - # Validate args. - if popen_process is None: - raise ValueError("popen_process is None") - - # Ensure we have something that looks like a valid process. - if popen_process.pid < 1: - if log_file: - log_file.write("skipping soft_terminate(): no process id") - return False - - # We only do the process liveness check if we're not using - # process groups. With process groups, checking if the main - # inferior process is dead and short circuiting here is no - # good - children of it in the process group could still be - # alive, and they should be killed during a timeout. - if not popen_process.using_process_groups: - # Don't kill if it's already dead. - popen_process.poll() - if popen_process.returncode is not None: - # It has a returncode. It has already stopped. - if log_file: - log_file.write( - "requested to terminate pid {} but it has already " - "terminated, returncode {}".format( - popen_process.pid, popen_process.returncode)) - # Move along... - return False - - # Good to go. - return True - - def _kill_with_signal(self, popen_process, log_file, signum): - # Validate we're ready to terminate this. - if not self._validate_pre_terminate(popen_process, log_file): - return - - # Choose kill mechanism based on whether we're targeting - # a process group or just a process. - if popen_process.using_process_groups: - # if log_file: - # log_file.write( - # "sending signum {} to process group {} now\n".format( - # signum, popen_process.pid)) - os.killpg(popen_process.pid, signum) - else: - # if log_file: - # log_file.write( - # "sending signum {} to process {} now\n".format( - # signum, popen_process.pid)) - os.kill(popen_process.pid, signum) - - def soft_terminate(self, popen_process, log_file=None, want_core=True): - # Choose signal based on desire for core file. - if want_core: - # SIGQUIT will generate core by default. Can be caught. - signum = signal.SIGQUIT - else: - # SIGTERM is the traditional nice way to kill a process. - # Can be caught, doesn't generate a core. - signum = signal.SIGTERM - - self._kill_with_signal(popen_process, log_file, signum) - - def hard_terminate(self, popen_process, log_file=None): - self._kill_with_signal(popen_process, log_file, signal.SIGKILL) - - def was_soft_terminate(self, returncode, with_core): - if with_core: - return returncode == -signal.SIGQUIT - else: - return returncode == -signal.SIGTERM - - def was_hard_terminate(self, returncode): - return returncode == -signal.SIGKILL - - def soft_terminate_signals(self): - return [signal.SIGQUIT, signal.SIGTERM] - - def is_exceptional_exit(self, popen_status): - return popen_status < 0 - - @classmethod - def _signal_names_by_number(cls): - return dict( - (k, v) for v, k in reversed(sorted(signal.__dict__.items())) - if v.startswith('SIG') and not v.startswith('SIG_')) - - def exceptional_exit_details(self, popen_status): - signo = -popen_status - signal_names_by_number = self._signal_names_by_number() - signal_name = signal_names_by_number.get(signo, "") - return (signo, signal_name) - -class WindowsProcessHelper(ProcessHelper): - """Provides a Windows implementation of the ProcessHelper class.""" - def __init__(self): - super(WindowsProcessHelper, self).__init__() - - def create_piped_process(self, command, new_process_group=True): - if new_process_group: - # We need this flag if we want os.kill() to work on the subprocess. - creation_flags = subprocess.CREATE_NEW_PROCESS_GROUP - else: - creation_flags = 0 - - return subprocess.Popen( - command, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - universal_newlines=True, # Elicits automatic byte -> string decoding in Py3 - creationflags=creation_flags) - - def was_hard_terminate(self, returncode): - return returncode != 0 - - -class ProcessDriver(object): - """Drives a child process, notifies on important events, and can timeout. - - Clients are expected to derive from this class and override the - on_process_started and on_process_exited methods if they want to - hook either of those. - - This class supports timing out the child process in a platform-agnostic - way. The on_process_exited method is informed if the exit was natural - or if it was due to a timeout. - """ - def __init__(self, soft_terminate_timeout=10.0): - super(ProcessDriver, self).__init__() - self.process_helper = ProcessHelper.process_helper() - self.pid = None - # Create the synchronization event for notifying when the - # inferior dotest process is complete. - self.done_event = threading.Event() - self.io_thread = None - self.process = None - # Number of seconds to wait for the soft terminate to - # wrap up, before moving to more drastic measures. - # Might want this longer if core dumps are generated and - # take a long time to write out. - self.soft_terminate_timeout = soft_terminate_timeout - # Number of seconds to wait for the hard terminate to - # wrap up, before giving up on the io thread. This should - # be fast. - self.hard_terminate_timeout = 5.0 - self.returncode = None - - # ============================================= - # Methods for subclasses to override if desired. - # ============================================= - - def on_process_started(self): - pass - - def on_process_exited(self, command, output, was_timeout, exit_status): - pass - - def write(self, content): - # pylint: disable=no-self-use - # Intended - we want derived classes to be able to override - # this and use any self state they may contain. - sys.stdout.write(content) - - # ============================================================== - # Operations used to drive processes. Clients will want to call - # one of these. - # ============================================================== - - def run_command(self, command): - # Start up the child process and the thread that does the - # communication pump. - self._start_process_and_io_thread(command) - - # Wait indefinitely for the child process to finish - # communicating. This indicates it has closed stdout/stderr - # pipes and is done. - self.io_thread.join() - self.returncode = self.process.wait() - if self.returncode is None: - raise Exception( - "no exit status available for pid {} after the " - " inferior dotest.py should have completed".format( - self.process.pid)) - - # Notify of non-timeout exit. - self.on_process_exited( - command, - self.io_thread.output, - False, - self.returncode) - - def run_command_with_timeout(self, command, timeout, want_core): - # Figure out how many seconds our timeout description is requesting. - timeout_seconds = timeout_to_seconds(timeout) - - # Start up the child process and the thread that does the - # communication pump. - self._start_process_and_io_thread(command) - - self._wait_with_timeout(timeout_seconds, command, want_core) - - # ================ - # Internal details. - # ================ - - def _start_process_and_io_thread(self, command): - # Create the process. - self.process = self.process_helper.create_piped_process(command) - self.pid = self.process.pid - self.on_process_started() - - # Ensure the event is cleared that is used for signaling - # from the communication() thread when communication is - # complete (i.e. the inferior process has finished). - self.done_event.clear() - - self.io_thread = CommunicatorThread( - self.process, self.done_event, self.write) - self.io_thread.start() - - def _attempt_soft_kill(self, want_core): - # The inferior dotest timed out. Attempt to clean it - # with a non-drastic method (so it can clean up properly - # and/or generate a core dump). Often the OS can't guarantee - # that the process will really terminate after this. - self.process_helper.soft_terminate( - self.process, - want_core=want_core, - log_file=self) - - # Now wait up to a certain timeout period for the io thread - # to say that the communication ended. If that wraps up - # within our soft terminate timeout, we're all done here. - self.io_thread.join(self.soft_terminate_timeout) - if not self.io_thread.is_alive(): - # stdout/stderr were closed on the child process side. We - # should be able to wait and reap the child process here. - self.returncode = self.process.wait() - # We terminated, and the done_trying result is n/a - terminated = True - done_trying = None - else: - self.write("soft kill attempt of process {} timed out " - "after {} seconds\n".format( - self.process.pid, self.soft_terminate_timeout)) - terminated = False - done_trying = False - return terminated, done_trying - - def _attempt_hard_kill(self): - # Instruct the process to terminate and really force it to - # happen. Don't give the process a chance to ignore. - self.process_helper.hard_terminate( - self.process, - log_file=self) - - # Reap the child process. This should not hang as the - # hard_kill() mechanism is supposed to really kill it. - # Improvement option: - # If this does ever hang, convert to a self.process.poll() - # loop checking on self.process.returncode until it is not - # None or the timeout occurs. - self.returncode = self.process.wait() - - # Wait a few moments for the io thread to finish... - self.io_thread.join(self.hard_terminate_timeout) - if self.io_thread.is_alive(): - # ... but this is not critical if it doesn't end for some - # reason. - self.write( - "hard kill of process {} timed out after {} seconds waiting " - "for the io thread (ignoring)\n".format( - self.process.pid, self.hard_terminate_timeout)) - - # Set if it terminated. (Set up for optional improvement above). - terminated = self.returncode is not None - # Nothing else to try. - done_trying = True - - return terminated, done_trying - - def _attempt_termination(self, attempt_count, want_core): - if self.process_helper.supports_soft_terminate(): - # When soft termination is supported, we first try to stop - # the process with a soft terminate. Failing that, we try - # the hard terminate option. - if attempt_count == 1: - return self._attempt_soft_kill(want_core) - elif attempt_count == 2: - return self._attempt_hard_kill() - else: - # We don't have anything else to try. - terminated = self.returncode is not None - done_trying = True - return terminated, done_trying - else: - # We only try the hard terminate option when there - # is no soft terminate available. - if attempt_count == 1: - return self._attempt_hard_kill() - else: - # We don't have anything else to try. - terminated = self.returncode is not None - done_trying = True - return terminated, done_trying - - def _wait_with_timeout(self, timeout_seconds, command, want_core): - # Allow up to timeout seconds for the io thread to wrap up. - # If that completes, the child process should be done. - completed_normally = self.done_event.wait(timeout_seconds) - if completed_normally: - # Reap the child process here. - self.returncode = self.process.wait() - else: - # Prepare to stop the process - process_terminated = completed_normally - terminate_attempt_count = 0 - - # Try as many attempts as we support for trying to shut down - # the child process if it's not already shut down. - while not process_terminated: - terminate_attempt_count += 1 - # Attempt to terminate. - process_terminated, done_trying = self._attempt_termination( - terminate_attempt_count, want_core) - # Check if there's nothing more to try. - if done_trying: - # Break out of our termination attempt loop. - break - - # At this point, we're calling it good. The process - # finished gracefully, was shut down after one or more - # attempts, or we failed but gave it our best effort. - self.on_process_exited( - command, - self.io_thread.output, - not completed_normally, - self.returncode) - - -def patched_init(self, *args, **kwargs): - self.original_init(*args, **kwargs) - # Initialize our condition variable that protects wait()/poll(). - self.wait_condition = threading.Condition() - - -def patched_wait(self, *args, **kwargs): - self.wait_condition.acquire() - try: - result = self.original_wait(*args, **kwargs) - # The process finished. Signal the condition. - self.wait_condition.notify_all() - return result - finally: - self.wait_condition.release() - - -def patched_poll(self, *args, **kwargs): - self.wait_condition.acquire() - try: - result = self.original_poll(*args, **kwargs) - if self.returncode is not None: - # We did complete, and we have the return value. - # Signal the event to indicate we're done. - self.wait_condition.notify_all() - return result - finally: - self.wait_condition.release() - - -def patch_up_subprocess_popen(): - subprocess.Popen.original_init = subprocess.Popen.__init__ - subprocess.Popen.__init__ = patched_init - - subprocess.Popen.original_wait = subprocess.Popen.wait - subprocess.Popen.wait = patched_wait - - subprocess.Popen.original_poll = subprocess.Popen.poll - subprocess.Popen.poll = patched_poll - -# Replace key subprocess.Popen() threading-unprotected methods with -# threading-protected versions. -patch_up_subprocess_popen() diff --git a/packages/Python/lldbsuite/test/test_runner/process_control.py b/packages/Python/lldbsuite/test/test_runner/process_control.py new file mode 100644 index 000000000000..a7e639e4b8b6 --- /dev/null +++ b/packages/Python/lldbsuite/test/test_runner/process_control.py @@ -0,0 +1,705 @@ +""" +The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. + +Provides classes used by the test results reporting infrastructure +within the LLDB test suite. + + +This module provides process-management support for the LLDB test +running infrasructure. +""" + +# System imports +import os +import re +import signal +import subprocess +import sys +import threading + + +class CommunicatorThread(threading.Thread): + """Provides a thread class that communicates with a subprocess.""" + def __init__(self, process, event, output_file): + super(CommunicatorThread, self).__init__() + # Don't let this thread prevent shutdown. + self.daemon = True + self.process = process + self.pid = process.pid + self.event = event + self.output_file = output_file + self.output = None + + def run(self): + try: + # Communicate with the child process. + # This will not complete until the child process terminates. + self.output = self.process.communicate() + except Exception as exception: # pylint: disable=broad-except + if self.output_file: + self.output_file.write( + "exception while using communicate() for pid: {}\n".format( + exception)) + finally: + # Signal that the thread's run is complete. + self.event.set() + + +# Provides a regular expression for matching gtimeout-based durations. +TIMEOUT_REGEX = re.compile(r"(^\d+)([smhd])?$") + + +def timeout_to_seconds(timeout): + """Converts timeout/gtimeout timeout values into seconds. + + @param timeout a timeout in the form of xm representing x minutes. + + @return None if timeout is None, or the number of seconds as a float + if a valid timeout format was specified. + """ + if timeout is None: + return None + else: + match = TIMEOUT_REGEX.match(timeout) + if match: + value = float(match.group(1)) + units = match.group(2) + if units is None: + # default is seconds. No conversion necessary. + return value + elif units == 's': + # Seconds. No conversion necessary. + return value + elif units == 'm': + # Value is in minutes. + return 60.0 * value + elif units == 'h': + # Value is in hours. + return (60.0 * 60.0) * value + elif units == 'd': + # Value is in days. + return 24 * (60.0 * 60.0) * value + else: + raise Exception("unexpected units value '{}'".format(units)) + else: + raise Exception("could not parse TIMEOUT spec '{}'".format( + timeout)) + + +class ProcessHelper(object): + """Provides an interface for accessing process-related functionality. + + This class provides a factory method that gives the caller a + platform-specific implementation instance of the class. + + Clients of the class should stick to the methods provided in this + base class. + + @see ProcessHelper.process_helper() + """ + def __init__(self): + super(ProcessHelper, self).__init__() + + @classmethod + def process_helper(cls): + """Returns a platform-specific ProcessHelper instance. + @return a ProcessHelper instance that does the right thing for + the current platform. + """ + + # If you add a new platform, create an instance here and + # return it. + if os.name == "nt": + return WindowsProcessHelper() + else: + # For all POSIX-like systems. + return UnixProcessHelper() + + def create_piped_process(self, command, new_process_group=True): + # pylint: disable=no-self-use,unused-argument + # As expected. We want derived classes to implement this. + """Creates a subprocess.Popen-based class with I/O piped to the parent. + + @param command the command line list as would be passed to + subprocess.Popen(). Use the list form rather than the string form. + + @param new_process_group indicates if the caller wants the + process to be created in its own process group. Each OS handles + this concept differently. It provides a level of isolation and + can simplify or enable terminating the process tree properly. + + @return a subprocess.Popen-like object. + """ + raise Exception("derived class must implement") + + def supports_soft_terminate(self): + # pylint: disable=no-self-use + # As expected. We want derived classes to implement this. + """Indicates if the platform supports soft termination. + + Soft termination is the concept of a terminate mechanism that + allows the target process to shut down nicely, but with the + catch that the process might choose to ignore it. + + Platform supporter note: only mark soft terminate as supported + if the target process has some way to evade the soft terminate + request; otherwise, just support the hard terminate method. + + @return True if the platform supports a soft terminate mechanism. + """ + # By default, we do not support a soft terminate mechanism. + return False + + def soft_terminate(self, popen_process, log_file=None, want_core=True): + # pylint: disable=no-self-use,unused-argument + # As expected. We want derived classes to implement this. + """Attempts to terminate the process in a polite way. + + This terminate method is intended to give the child process a + chance to clean up and exit on its own, possibly with a request + to drop a core file or equivalent (i.e. [mini-]crashdump, crashlog, + etc.) If new_process_group was set in the process creation method + and the platform supports it, this terminate call will attempt to + kill the whole process tree rooted in this child process. + + @param popen_process the subprocess.Popen-like object returned + by one of the process-creation methods of this class. + + @param log_file file-like object used to emit error-related + logging info. May be None if no error-related info is desired. + + @param want_core True if the caller would like to get a core + dump (or the analogous crash report) from the terminated process. + """ + popen_process.terminate() + + def hard_terminate(self, popen_process, log_file=None): + # pylint: disable=no-self-use,unused-argument + # As expected. We want derived classes to implement this. + """Attempts to terminate the process immediately. + + This terminate method is intended to kill child process in + a manner in which the child process has no ability to block, + and also has no ability to clean up properly. If new_process_group + was specified when creating the process, and if the platform + implementation supports it, this will attempt to kill the + whole process tree rooted in the child process. + + @param popen_process the subprocess.Popen-like object returned + by one of the process-creation methods of this class. + + @param log_file file-like object used to emit error-related + logging info. May be None if no error-related info is desired. + """ + popen_process.kill() + + def was_soft_terminate(self, returncode, with_core): + # pylint: disable=no-self-use,unused-argument + # As expected. We want derived classes to implement this. + """Returns if Popen-like object returncode matches soft terminate. + + @param returncode the returncode from the Popen-like object that + terminated with a given return code. + + @param with_core indicates whether the returncode should match + a core-generating return signal. + + @return True when the returncode represents what the system would + issue when a soft_terminate() with the given with_core arg occurred; + False otherwise. + """ + if not self.supports_soft_terminate(): + # If we don't support soft termination on this platform, + # then this should always be False. + return False + else: + # Once a platform claims to support soft terminate, it + # needs to be able to identify it by overriding this method. + raise Exception("platform needs to implement") + + def was_hard_terminate(self, returncode): + # pylint: disable=no-self-use,unused-argument + # As expected. We want derived classes to implement this. + """Returns if Popen-like object returncode matches that of a hard + terminate attempt. + + @param returncode the returncode from the Popen-like object that + terminated with a given return code. + + @return True when the returncode represents what the system would + issue when a hard_terminate() occurred; False + otherwise. + """ + raise Exception("platform needs to implement") + + def soft_terminate_signals(self): + # pylint: disable=no-self-use + """Retrieve signal numbers that can be sent to soft terminate. + @return a list of signal numbers that can be sent to soft terminate + a process, or None if not applicable. + """ + return None + + def is_exceptional_exit(self, popen_status): + """Returns whether the program exit status is exceptional. + + Returns whether the return code from a Popen process is exceptional + (e.g. signals on POSIX systems). + + Derived classes should override this if they can detect exceptional + program exit. + + @return True if the given popen_status represents an exceptional + program exit; False otherwise. + """ + return False + + def exceptional_exit_details(self, popen_status): + """Returns the normalized exceptional exit code and a description. + + Given an exceptional exit code, returns the integral value of the + exception (e.g. signal number for POSIX) and a description (e.g. + signal name on POSIX) for the result. + + Derived classes should override this if they can detect exceptional + program exit. + + It is fine to not implement this so long as is_exceptional_exit() + always returns False. + + @return (normalized exception code, symbolic exception description) + """ + raise Exception("exception_exit_details() called on unsupported class") + + +class UnixProcessHelper(ProcessHelper): + """Provides a ProcessHelper for Unix-like operating systems. + + This implementation supports anything that looks Posix-y + (e.g. Darwin, Linux, *BSD, etc.) + """ + def __init__(self): + super(UnixProcessHelper, self).__init__() + + @classmethod + def _create_new_process_group(cls): + """Creates a new process group for the calling process.""" + os.setpgid(os.getpid(), os.getpid()) + + def create_piped_process(self, command, new_process_group=True): + # Determine what to run after the fork but before the exec. + if new_process_group: + preexec_func = self._create_new_process_group + else: + preexec_func = None + + # Create the process. + process = subprocess.Popen( + command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, # Elicits automatic byte -> string decoding in Py3 + close_fds=True, + preexec_fn=preexec_func) + + # Remember whether we're using process groups for this + # process. + process.using_process_groups = new_process_group + return process + + def supports_soft_terminate(self): + # POSIX does support a soft terminate via: + # * SIGTERM (no core requested) + # * SIGQUIT (core requested if enabled, see ulimit -c) + return True + + @classmethod + def _validate_pre_terminate(cls, popen_process, log_file): + # Validate args. + if popen_process is None: + raise ValueError("popen_process is None") + + # Ensure we have something that looks like a valid process. + if popen_process.pid < 1: + if log_file: + log_file.write("skipping soft_terminate(): no process id") + return False + + # We only do the process liveness check if we're not using + # process groups. With process groups, checking if the main + # inferior process is dead and short circuiting here is no + # good - children of it in the process group could still be + # alive, and they should be killed during a timeout. + if not popen_process.using_process_groups: + # Don't kill if it's already dead. + popen_process.poll() + if popen_process.returncode is not None: + # It has a returncode. It has already stopped. + if log_file: + log_file.write( + "requested to terminate pid {} but it has already " + "terminated, returncode {}".format( + popen_process.pid, popen_process.returncode)) + # Move along... + return False + + # Good to go. + return True + + def _kill_with_signal(self, popen_process, log_file, signum): + # Validate we're ready to terminate this. + if not self._validate_pre_terminate(popen_process, log_file): + return + + # Choose kill mechanism based on whether we're targeting + # a process group or just a process. + if popen_process.using_process_groups: + # if log_file: + # log_file.write( + # "sending signum {} to process group {} now\n".format( + # signum, popen_process.pid)) + os.killpg(popen_process.pid, signum) + else: + # if log_file: + # log_file.write( + # "sending signum {} to process {} now\n".format( + # signum, popen_process.pid)) + os.kill(popen_process.pid, signum) + + def soft_terminate(self, popen_process, log_file=None, want_core=True): + # Choose signal based on desire for core file. + if want_core: + # SIGQUIT will generate core by default. Can be caught. + signum = signal.SIGQUIT + else: + # SIGTERM is the traditional nice way to kill a process. + # Can be caught, doesn't generate a core. + signum = signal.SIGTERM + + self._kill_with_signal(popen_process, log_file, signum) + + def hard_terminate(self, popen_process, log_file=None): + self._kill_with_signal(popen_process, log_file, signal.SIGKILL) + + def was_soft_terminate(self, returncode, with_core): + if with_core: + return returncode == -signal.SIGQUIT + else: + return returncode == -signal.SIGTERM + + def was_hard_terminate(self, returncode): + return returncode == -signal.SIGKILL + + def soft_terminate_signals(self): + return [signal.SIGQUIT, signal.SIGTERM] + + def is_exceptional_exit(self, popen_status): + return popen_status < 0 + + @classmethod + def _signal_names_by_number(cls): + return dict( + (k, v) for v, k in reversed(sorted(signal.__dict__.items())) + if v.startswith('SIG') and not v.startswith('SIG_')) + + def exceptional_exit_details(self, popen_status): + signo = -popen_status + signal_names_by_number = self._signal_names_by_number() + signal_name = signal_names_by_number.get(signo, "") + return (signo, signal_name) + +class WindowsProcessHelper(ProcessHelper): + """Provides a Windows implementation of the ProcessHelper class.""" + def __init__(self): + super(WindowsProcessHelper, self).__init__() + + def create_piped_process(self, command, new_process_group=True): + if new_process_group: + # We need this flag if we want os.kill() to work on the subprocess. + creation_flags = subprocess.CREATE_NEW_PROCESS_GROUP + else: + creation_flags = 0 + + return subprocess.Popen( + command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, # Elicits automatic byte -> string decoding in Py3 + creationflags=creation_flags) + + def was_hard_terminate(self, returncode): + return returncode != 0 + + +class ProcessDriver(object): + """Drives a child process, notifies on important events, and can timeout. + + Clients are expected to derive from this class and override the + on_process_started and on_process_exited methods if they want to + hook either of those. + + This class supports timing out the child process in a platform-agnostic + way. The on_process_exited method is informed if the exit was natural + or if it was due to a timeout. + """ + def __init__(self, soft_terminate_timeout=10.0): + super(ProcessDriver, self).__init__() + self.process_helper = ProcessHelper.process_helper() + self.pid = None + # Create the synchronization event for notifying when the + # inferior dotest process is complete. + self.done_event = threading.Event() + self.io_thread = None + self.process = None + # Number of seconds to wait for the soft terminate to + # wrap up, before moving to more drastic measures. + # Might want this longer if core dumps are generated and + # take a long time to write out. + self.soft_terminate_timeout = soft_terminate_timeout + # Number of seconds to wait for the hard terminate to + # wrap up, before giving up on the io thread. This should + # be fast. + self.hard_terminate_timeout = 5.0 + self.returncode = None + + # ============================================= + # Methods for subclasses to override if desired. + # ============================================= + + def on_process_started(self): + pass + + def on_process_exited(self, command, output, was_timeout, exit_status): + pass + + def write(self, content): + # pylint: disable=no-self-use + # Intended - we want derived classes to be able to override + # this and use any self state they may contain. + sys.stdout.write(content) + + # ============================================================== + # Operations used to drive processes. Clients will want to call + # one of these. + # ============================================================== + + def run_command(self, command): + # Start up the child process and the thread that does the + # communication pump. + self._start_process_and_io_thread(command) + + # Wait indefinitely for the child process to finish + # communicating. This indicates it has closed stdout/stderr + # pipes and is done. + self.io_thread.join() + self.returncode = self.process.wait() + if self.returncode is None: + raise Exception( + "no exit status available for pid {} after the " + " inferior dotest.py should have completed".format( + self.process.pid)) + + # Notify of non-timeout exit. + self.on_process_exited( + command, + self.io_thread.output, + False, + self.returncode) + + def run_command_with_timeout(self, command, timeout, want_core): + # Figure out how many seconds our timeout description is requesting. + timeout_seconds = timeout_to_seconds(timeout) + + # Start up the child process and the thread that does the + # communication pump. + self._start_process_and_io_thread(command) + + self._wait_with_timeout(timeout_seconds, command, want_core) + + # ================ + # Internal details. + # ================ + + def _start_process_and_io_thread(self, command): + # Create the process. + self.process = self.process_helper.create_piped_process(command) + self.pid = self.process.pid + self.on_process_started() + + # Ensure the event is cleared that is used for signaling + # from the communication() thread when communication is + # complete (i.e. the inferior process has finished). + self.done_event.clear() + + self.io_thread = CommunicatorThread( + self.process, self.done_event, self.write) + self.io_thread.start() + + def _attempt_soft_kill(self, want_core): + # The inferior dotest timed out. Attempt to clean it + # with a non-drastic method (so it can clean up properly + # and/or generate a core dump). Often the OS can't guarantee + # that the process will really terminate after this. + self.process_helper.soft_terminate( + self.process, + want_core=want_core, + log_file=self) + + # Now wait up to a certain timeout period for the io thread + # to say that the communication ended. If that wraps up + # within our soft terminate timeout, we're all done here. + self.io_thread.join(self.soft_terminate_timeout) + if not self.io_thread.is_alive(): + # stdout/stderr were closed on the child process side. We + # should be able to wait and reap the child process here. + self.returncode = self.process.wait() + # We terminated, and the done_trying result is n/a + terminated = True + done_trying = None + else: + self.write("soft kill attempt of process {} timed out " + "after {} seconds\n".format( + self.process.pid, self.soft_terminate_timeout)) + terminated = False + done_trying = False + return terminated, done_trying + + def _attempt_hard_kill(self): + # Instruct the process to terminate and really force it to + # happen. Don't give the process a chance to ignore. + self.process_helper.hard_terminate( + self.process, + log_file=self) + + # Reap the child process. This should not hang as the + # hard_kill() mechanism is supposed to really kill it. + # Improvement option: + # If this does ever hang, convert to a self.process.poll() + # loop checking on self.process.returncode until it is not + # None or the timeout occurs. + self.returncode = self.process.wait() + + # Wait a few moments for the io thread to finish... + self.io_thread.join(self.hard_terminate_timeout) + if self.io_thread.is_alive(): + # ... but this is not critical if it doesn't end for some + # reason. + self.write( + "hard kill of process {} timed out after {} seconds waiting " + "for the io thread (ignoring)\n".format( + self.process.pid, self.hard_terminate_timeout)) + + # Set if it terminated. (Set up for optional improvement above). + terminated = self.returncode is not None + # Nothing else to try. + done_trying = True + + return terminated, done_trying + + def _attempt_termination(self, attempt_count, want_core): + if self.process_helper.supports_soft_terminate(): + # When soft termination is supported, we first try to stop + # the process with a soft terminate. Failing that, we try + # the hard terminate option. + if attempt_count == 1: + return self._attempt_soft_kill(want_core) + elif attempt_count == 2: + return self._attempt_hard_kill() + else: + # We don't have anything else to try. + terminated = self.returncode is not None + done_trying = True + return terminated, done_trying + else: + # We only try the hard terminate option when there + # is no soft terminate available. + if attempt_count == 1: + return self._attempt_hard_kill() + else: + # We don't have anything else to try. + terminated = self.returncode is not None + done_trying = True + return terminated, done_trying + + def _wait_with_timeout(self, timeout_seconds, command, want_core): + # Allow up to timeout seconds for the io thread to wrap up. + # If that completes, the child process should be done. + completed_normally = self.done_event.wait(timeout_seconds) + if completed_normally: + # Reap the child process here. + self.returncode = self.process.wait() + else: + # Prepare to stop the process + process_terminated = completed_normally + terminate_attempt_count = 0 + + # Try as many attempts as we support for trying to shut down + # the child process if it's not already shut down. + while not process_terminated: + terminate_attempt_count += 1 + # Attempt to terminate. + process_terminated, done_trying = self._attempt_termination( + terminate_attempt_count, want_core) + # Check if there's nothing more to try. + if done_trying: + # Break out of our termination attempt loop. + break + + # At this point, we're calling it good. The process + # finished gracefully, was shut down after one or more + # attempts, or we failed but gave it our best effort. + self.on_process_exited( + command, + self.io_thread.output, + not completed_normally, + self.returncode) + + +def patched_init(self, *args, **kwargs): + self.original_init(*args, **kwargs) + # Initialize our condition variable that protects wait()/poll(). + self.wait_condition = threading.Condition() + + +def patched_wait(self, *args, **kwargs): + self.wait_condition.acquire() + try: + result = self.original_wait(*args, **kwargs) + # The process finished. Signal the condition. + self.wait_condition.notify_all() + return result + finally: + self.wait_condition.release() + + +def patched_poll(self, *args, **kwargs): + self.wait_condition.acquire() + try: + result = self.original_poll(*args, **kwargs) + if self.returncode is not None: + # We did complete, and we have the return value. + # Signal the event to indicate we're done. + self.wait_condition.notify_all() + return result + finally: + self.wait_condition.release() + + +def patch_up_subprocess_popen(): + subprocess.Popen.original_init = subprocess.Popen.__init__ + subprocess.Popen.__init__ = patched_init + + subprocess.Popen.original_wait = subprocess.Popen.wait + subprocess.Popen.wait = patched_wait + + subprocess.Popen.original_poll = subprocess.Popen.poll + subprocess.Popen.poll = patched_poll + +# Replace key subprocess.Popen() threading-unprotected methods with +# threading-protected versions. +patch_up_subprocess_popen() diff --git a/packages/Python/lldbsuite/test/test_runner/test/__init__.py b/packages/Python/lldbsuite/test/test_runner/test/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/Python/lldbsuite/test/test_runner/test/process_control_tests.py b/packages/Python/lldbsuite/test/test_runner/test/process_control_tests.py deleted file mode 100755 index 354506d65812..000000000000 --- a/packages/Python/lldbsuite/test/test_runner/test/process_control_tests.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python -""" -The LLVM Compiler Infrastructure - -This file is distributed under the University of Illinois Open Source -License. See LICENSE.TXT for details. - -Provides classes used by the test results reporting infrastructure -within the LLDB test suite. - - -Tests the process_control module. -""" - -# System imports. -import os -import platform -import unittest -import sys -import threading - -# Add lib dir to pythonpath -sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'lib')) - -# Our imports. -import process_control - - -class TestInferiorDriver(process_control.ProcessDriver): - def __init__(self, soft_terminate_timeout=None): - super(TestInferiorDriver, self).__init__( - soft_terminate_timeout=soft_terminate_timeout) - self.started_event = threading.Event() - self.started_event.clear() - - self.completed_event = threading.Event() - self.completed_event.clear() - - self.was_timeout = False - self.returncode = None - self.output = None - - def write(self, content): - # We'll swallow this to keep tests non-noisy. - # Uncomment the following line if you want to see it. - # sys.stdout.write(content) - pass - - def on_process_started(self): - self.started_event.set() - - def on_process_exited(self, command, output, was_timeout, exit_status): - self.returncode = exit_status - self.was_timeout = was_timeout - self.output = output - self.returncode = exit_status - self.completed_event.set() - - -class ProcessControlTests(unittest.TestCase): - @classmethod - def _suppress_soft_terminate(cls, command): - # Do the right thing for your platform here. - # Right now only POSIX-y systems are reporting - # soft terminate support, so this is set up for - # those. - helper = process_control.ProcessHelper.process_helper() - signals = helper.soft_terminate_signals() - if signals is not None: - for signum in helper.soft_terminate_signals(): - command.extend(["--ignore-signal", str(signum)]) - - @classmethod - def inferior_command( - cls, - ignore_soft_terminate=False, - options=None): - - # Base command. - command = ([sys.executable, "inferior.py"]) - - if ignore_soft_terminate: - cls._suppress_soft_terminate(command) - - # Handle options as string or list. - if isinstance(options, str): - command.extend(options.split()) - elif isinstance(options, list): - command.extend(options) - - # Return full command. - return command - - -class ProcessControlNoTimeoutTests(ProcessControlTests): - """Tests the process_control module.""" - def test_run_completes(self): - """Test that running completes and gets expected stdout/stderr.""" - driver = TestInferiorDriver() - driver.run_command(self.inferior_command()) - self.assertTrue( - driver.completed_event.wait(5), "process failed to complete") - self.assertEqual(driver.returncode, 0, "return code does not match") - - def test_run_completes_with_code(self): - """Test that running completes and gets expected stdout/stderr.""" - driver = TestInferiorDriver() - driver.run_command(self.inferior_command(options="-r10")) - self.assertTrue( - driver.completed_event.wait(5), "process failed to complete") - self.assertEqual(driver.returncode, 10, "return code does not match") - - -class ProcessControlTimeoutTests(ProcessControlTests): - def test_run_completes(self): - """Test that running completes and gets expected return code.""" - driver = TestInferiorDriver() - timeout_seconds = 5 - driver.run_command_with_timeout( - self.inferior_command(), - "{}s".format(timeout_seconds), - False) - self.assertTrue( - driver.completed_event.wait(2*timeout_seconds), - "process failed to complete") - self.assertEqual(driver.returncode, 0) - - def _soft_terminate_works(self, with_core): - # Skip this test if the platform doesn't support soft ti - helper = process_control.ProcessHelper.process_helper() - if not helper.supports_soft_terminate(): - self.skipTest("soft terminate not supported by platform") - - driver = TestInferiorDriver() - timeout_seconds = 5 - - driver.run_command_with_timeout( - # Sleep twice as long as the timeout interval. This - # should force a timeout. - self.inferior_command( - options="--sleep {}".format(timeout_seconds*2)), - "{}s".format(timeout_seconds), - with_core) - - # We should complete, albeit with a timeout. - self.assertTrue( - driver.completed_event.wait(2*timeout_seconds), - "process failed to complete") - - # Ensure we received a timeout. - self.assertTrue(driver.was_timeout, "expected to end with a timeout") - - self.assertTrue( - helper.was_soft_terminate(driver.returncode, with_core), - ("timeout didn't return expected returncode " - "for soft terminate with core: {}").format(driver.returncode)) - - def test_soft_terminate_works_core(self): - """Driver uses soft terminate (with core request) when process times out. - """ - self._soft_terminate_works(True) - - def test_soft_terminate_works_no_core(self): - """Driver uses soft terminate (no core request) when process times out. - """ - self._soft_terminate_works(False) - - def test_hard_terminate_works(self): - """Driver falls back to hard terminate when soft terminate is ignored. - """ - - driver = TestInferiorDriver(soft_terminate_timeout=2.0) - timeout_seconds = 1 - - driver.run_command_with_timeout( - # Sleep much longer than the timeout interval,forcing a - # timeout. Do whatever is needed to have the inferior - # ignore soft terminate calls. - self.inferior_command( - ignore_soft_terminate=True, - options="--never-return"), - "{}s".format(timeout_seconds), - True) - - # We should complete, albeit with a timeout. - self.assertTrue( - driver.completed_event.wait(60), - "process failed to complete") - - # Ensure we received a timeout. - self.assertTrue(driver.was_timeout, "expected to end with a timeout") - - helper = process_control.ProcessHelper.process_helper() - self.assertTrue( - helper.was_hard_terminate(driver.returncode), - ("timeout didn't return expected returncode " - "for hard teriminate: {} ({})").format( - driver.returncode, - driver.output)) - - def test_inferior_exits_with_live_child_shared_handles(self): - """inferior exit detected when inferior children are live with shared - stdout/stderr handles. - """ - # Requires review D13362 or equivalent to be implemented. - self.skipTest("http://reviews.llvm.org/D13362") - - driver = TestInferiorDriver() - - # Create the inferior (I1), and instruct it to create a child (C1) - # that shares the stdout/stderr handles with the inferior. - # C1 will then loop forever. - driver.run_command_with_timeout( - self.inferior_command( - options="--launch-child-share-handles --return-code 3"), - "5s", - False) - - # We should complete without a timetout. I1 should end - # immediately after launching C1. - self.assertTrue( - driver.completed_event.wait(5), - "process failed to complete") - - # Ensure we didn't receive a timeout. - self.assertFalse( - driver.was_timeout, "inferior should have completed normally") - - self.assertEqual( - driver.returncode, 3, - "expected inferior process to end with expected returncode") - - -if __name__ == "__main__": - unittest.main() diff --git a/packages/Python/lldbsuite/test/test_runner/test/test_process_control.py b/packages/Python/lldbsuite/test/test_runner/test/test_process_control.py new file mode 100755 index 000000000000..817c83c4fb55 --- /dev/null +++ b/packages/Python/lldbsuite/test/test_runner/test/test_process_control.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python +""" +The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. + +Provides classes used by the test results reporting infrastructure +within the LLDB test suite. + + +Tests the process_control module. +""" + +from __future__ import print_function + +# System imports. +import os +import os.path +import platform +import unittest +import sys +import threading + +# Our imports. +from test_runner import process_control + + +class TestInferiorDriver(process_control.ProcessDriver): + def __init__(self, soft_terminate_timeout=None): + super(TestInferiorDriver, self).__init__( + soft_terminate_timeout=soft_terminate_timeout) + self.started_event = threading.Event() + self.started_event.clear() + + self.completed_event = threading.Event() + self.completed_event.clear() + + self.was_timeout = False + self.returncode = None + self.output = None + + def write(self, content): + # We'll swallow this to keep tests non-noisy. + # Uncomment the following line if you want to see it. + # sys.stdout.write(content) + pass + + def on_process_started(self): + self.started_event.set() + + def on_process_exited(self, command, output, was_timeout, exit_status): + self.returncode = exit_status + self.was_timeout = was_timeout + self.output = output + self.returncode = exit_status + self.completed_event.set() + + +class ProcessControlTests(unittest.TestCase): + @classmethod + def _suppress_soft_terminate(cls, command): + # Do the right thing for your platform here. + # Right now only POSIX-y systems are reporting + # soft terminate support, so this is set up for + # those. + helper = process_control.ProcessHelper.process_helper() + signals = helper.soft_terminate_signals() + if signals is not None: + for signum in helper.soft_terminate_signals(): + command.extend(["--ignore-signal", str(signum)]) + + @classmethod + def inferior_command( + cls, + ignore_soft_terminate=False, + options=None): + + # Base command. + script_name = "{}/inferior.py".format(os.path.dirname(__file__)) + if not os.path.exists(script_name): + raise Exception("test inferior python script not found: {}".format(script_name)) + command = ([sys.executable, script_name]) + + if ignore_soft_terminate: + cls._suppress_soft_terminate(command) + + # Handle options as string or list. + if isinstance(options, str): + command.extend(options.split()) + elif isinstance(options, list): + command.extend(options) + + # Return full command. + return command + + +class ProcessControlNoTimeoutTests(ProcessControlTests): + """Tests the process_control module.""" + def test_run_completes(self): + """Test that running completes and gets expected stdout/stderr.""" + driver = TestInferiorDriver() + driver.run_command(self.inferior_command()) + self.assertTrue( + driver.completed_event.wait(5), "process failed to complete") + self.assertEqual(driver.returncode, 0, "return code does not match") + + def test_run_completes_with_code(self): + """Test that running completes and gets expected stdout/stderr.""" + driver = TestInferiorDriver() + driver.run_command(self.inferior_command(options="-r10")) + self.assertTrue( + driver.completed_event.wait(5), "process failed to complete") + self.assertEqual(driver.returncode, 10, "return code does not match") + + +class ProcessControlTimeoutTests(ProcessControlTests): + def test_run_completes(self): + """Test that running completes and gets expected return code.""" + driver = TestInferiorDriver() + timeout_seconds = 5 + driver.run_command_with_timeout( + self.inferior_command(), + "{}s".format(timeout_seconds), + False) + self.assertTrue( + driver.completed_event.wait(2*timeout_seconds), + "process failed to complete") + self.assertEqual(driver.returncode, 0) + + def _soft_terminate_works(self, with_core): + # Skip this test if the platform doesn't support soft ti + helper = process_control.ProcessHelper.process_helper() + if not helper.supports_soft_terminate(): + self.skipTest("soft terminate not supported by platform") + + driver = TestInferiorDriver() + timeout_seconds = 5 + + driver.run_command_with_timeout( + # Sleep twice as long as the timeout interval. This + # should force a timeout. + self.inferior_command( + options="--sleep {}".format(timeout_seconds*2)), + "{}s".format(timeout_seconds), + with_core) + + # We should complete, albeit with a timeout. + self.assertTrue( + driver.completed_event.wait(2*timeout_seconds), + "process failed to complete") + + # Ensure we received a timeout. + self.assertTrue(driver.was_timeout, "expected to end with a timeout") + + self.assertTrue( + helper.was_soft_terminate(driver.returncode, with_core), + ("timeout didn't return expected returncode " + "for soft terminate with core: {}").format(driver.returncode)) + + def test_soft_terminate_works_core(self): + """Driver uses soft terminate (with core request) when process times out. + """ + self._soft_terminate_works(True) + + def test_soft_terminate_works_no_core(self): + """Driver uses soft terminate (no core request) when process times out. + """ + self._soft_terminate_works(False) + + def test_hard_terminate_works(self): + """Driver falls back to hard terminate when soft terminate is ignored. + """ + + driver = TestInferiorDriver(soft_terminate_timeout=2.0) + timeout_seconds = 1 + + driver.run_command_with_timeout( + # Sleep much longer than the timeout interval,forcing a + # timeout. Do whatever is needed to have the inferior + # ignore soft terminate calls. + self.inferior_command( + ignore_soft_terminate=True, + options="--never-return"), + "{}s".format(timeout_seconds), + True) + + # We should complete, albeit with a timeout. + self.assertTrue( + driver.completed_event.wait(60), + "process failed to complete") + + # Ensure we received a timeout. + self.assertTrue(driver.was_timeout, "expected to end with a timeout") + + helper = process_control.ProcessHelper.process_helper() + self.assertTrue( + helper.was_hard_terminate(driver.returncode), + ("timeout didn't return expected returncode " + "for hard teriminate: {} ({})").format( + driver.returncode, + driver.output)) + + def test_inferior_exits_with_live_child_shared_handles(self): + """inferior exit detected when inferior children are live with shared + stdout/stderr handles. + """ + # Requires review D13362 or equivalent to be implemented. + self.skipTest("http://reviews.llvm.org/D13362") + + driver = TestInferiorDriver() + + # Create the inferior (I1), and instruct it to create a child (C1) + # that shares the stdout/stderr handles with the inferior. + # C1 will then loop forever. + driver.run_command_with_timeout( + self.inferior_command( + options="--launch-child-share-handles --return-code 3"), + "5s", + False) + + # We should complete without a timetout. I1 should end + # immediately after launching C1. + self.assertTrue( + driver.completed_event.wait(5), + "process failed to complete") + + # Ensure we didn't receive a timeout. + self.assertFalse( + driver.was_timeout, "inferior should have completed normally") + + self.assertEqual( + driver.returncode, 3, + "expected inferior process to end with expected returncode") + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiExit.py b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiExit.py index 86a0a65b05a7..6f814c13ec83 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiExit.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiExit.py @@ -4,16 +4,16 @@ Test that the lldb-mi driver exits properly. from __future__ import print_function - - import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiExitTestCase(lldbmi_testcase.MiTestCaseBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_gdb_exit(self): """Test that '-gdb-exit' terminates local debug session and exits.""" @@ -37,7 +37,7 @@ class MiExitTestCase(lldbmi_testcase.MiTestCaseBase): import pexpect self.expect(pexpect.EOF) - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_quit(self): """Test that 'quit' exits immediately.""" @@ -60,7 +60,7 @@ class MiExitTestCase(lldbmi_testcase.MiTestCaseBase): import pexpect self.expect(pexpect.EOF) - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_q(self): """Test that 'q' exits immediately.""" diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiFile.py b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiFile.py index 8b4eac156362..99a06f2711fa 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiFile.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiFile.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiFileTestCase(lldbmi_testcase.MiTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiGdbSetShow.py b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiGdbSetShow.py index ab3eb1fb37de..9898ad4398fb 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiGdbSetShow.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiGdbSetShow.py @@ -8,13 +8,15 @@ from __future__ import print_function import unittest2 import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): mydir = TestBase.compute_mydir(__file__) - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_gdb_set_target_async_default(self): """Test that 'lldb-mi --interpreter' switches to async mode by default.""" @@ -33,7 +35,7 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): self.runCmd("-gdb-show target-async") self.expect("\^done,value=\"on\"") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @expectedFlakeyLinux("llvm.org/pr26028") # Fails in ~1% of cases def test_lldbmi_gdb_set_target_async_on(self): @@ -62,9 +64,9 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): self.expect("\*running") self.expect("@\"argc=1") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races - @expectedFailureLinux # Failing in ~11/600 dosep runs (build 3120-3122) + @expectedFailureAll(oslist=["linux"], bugnumber="Failing in ~11/600 dosep runs (build 3120-3122)") def test_lldbmi_gdb_set_target_async_off(self): """Test that 'lldb-mi --interpreter' can execute commands in sync mode.""" @@ -87,7 +89,7 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): if it < len(unexpected): self.fail("unexpected found: %s" % unexpected[it]) - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_gdb_show_target_async(self): """Test that 'lldb-mi --interpreter' in async mode by default.""" @@ -98,7 +100,7 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): self.runCmd("-gdb-show target-async") self.expect("\^done,value=\"on\"") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_gdb_show_language(self): """Test that 'lldb-mi --interpreter' can get current language.""" @@ -120,7 +122,7 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): self.runCmd("-gdb-show language") self.expect("\^done,value=\"c\+\+\"") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @unittest2.expectedFailure("-gdb-set ignores unknown properties") def test_lldbmi_gdb_set_unknown(self): """Test that 'lldb-mi --interpreter' fails when setting an unknown property.""" @@ -131,7 +133,7 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): self.runCmd("-gdb-set unknown some_value") self.expect("\^error") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @unittest2.expectedFailure("-gdb-show ignores unknown properties") def test_lldbmi_gdb_show_unknown(self): """Test that 'lldb-mi --interpreter' fails when showing an unknown property.""" @@ -143,7 +145,7 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): self.expect("\^error") - @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races @skipIfLinux # llvm.org/pr22841: lldb-mi tests fail on all Linux buildbots def test_lldbmi_gdb_set_ouptut_radix(self): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiLibraryLoaded.py b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiLibraryLoaded.py index 4d9c935576df..8e1d72aa19c6 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiLibraryLoaded.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiLibraryLoaded.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiLibraryLoadedTestCase(lldbmi_testcase.MiTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiPrompt.py b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiPrompt.py index d810267d9489..50e108e9fa20 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiPrompt.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/TestMiPrompt.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiPromptTestCase(lldbmi_testcase.MiTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/breakpoint/TestMiBreak.py b/packages/Python/lldbsuite/test/tools/lldb-mi/breakpoint/TestMiBreak.py index 020954ff9b41..c4a801c991a4 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/breakpoint/TestMiBreak.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/breakpoint/TestMiBreak.py @@ -5,10 +5,11 @@ Test lldb-mi -break-xxx commands. from __future__ import print_function - import unittest2 import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiBreakTestCase(lldbmi_testcase.MiTestCaseBase): @@ -16,6 +17,7 @@ class MiBreakTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races + @expectedFlakeyLinux("llvm.org/pr24717") def test_lldbmi_break_insert_function_pending(self): """Test that 'lldb-mi --interpreter' works for pending function breakpoints.""" @@ -244,3 +246,48 @@ class MiBreakTestCase(lldbmi_testcase.MiTestCaseBase): self.runCmd("-exec-continue") self.expect("\^running") self.expect("\*stopped,reason=\"exited-normally\"") + + @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows + @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races + def test_lldbmi_break_enable_disable(self): + """Test that 'lldb-mi --interpreter' works for enabling / disabling breakpoints.""" + + self.spawnLldbMi(args = None) + + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + self.runCmd("-break-insert main") + self.expect("\^done,bkpt={number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"main\"") + self.expect("=breakpoint-modified,bkpt={number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"main\",file=\"main\.cpp\",fullname=\".+?main\.cpp\",line=\"\d+\",times=\"0\",original-location=\"main\"}") + + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("=breakpoint-modified,bkpt={number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"main\",file=\"main\.cpp\",fullname=\".+?main\.cpp\",line=\"\d+\",times=\"0\",original-location=\"main\"}") + self.expect("\*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"1\"") + + self.runCmd("-break-insert ns::foo1") + self.expect("\^done,bkpt={number=\"2\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"ns::foo1\(\)\"") + self.expect("=breakpoint-modified,bkpt={number=\"2\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"ns::foo1\(\)\",file=\"main\.cpp\",fullname=\".+?main\.cpp\",line=\"\d+\",times=\"0\",original-location=\"ns::foo1\"}") + + self.runCmd("-break-insert ns::foo2") + self.expect("\^done,bkpt={number=\"3\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"ns::foo2\(\)\"") + self.expect("=breakpoint-modified,bkpt={number=\"3\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"ns::foo2\(\)\",file=\"main\.cpp\",fullname=\".+?main\.cpp\",line=\"\d+\",times=\"0\",original-location=\"ns::foo2\"}") + + # disable the 2nd breakpoint + self.runCmd("-break-disable 2") + self.expect("\^done") + self.expect("=breakpoint-modified,bkpt={number=\"2\",type=\"breakpoint\",disp=\"keep\",enabled=\"n\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"ns::foo1\(\)\",file=\"main\.cpp\",fullname=\".+?main\.cpp\",line=\"\d+\",times=\"0\",original-location=\"ns::foo1\"}") + + # disable the 3rd breakpoint and re-enable + self.runCmd("-break-disable 3") + self.expect("\^done") + self.expect("=breakpoint-modified,bkpt={number=\"3\",type=\"breakpoint\",disp=\"keep\",enabled=\"n\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"ns::foo2\(\)\",file=\"main\.cpp\",fullname=\".+?main\.cpp\",line=\"\d+\",times=\"0\",original-location=\"ns::foo2\"}") + + self.runCmd("-break-enable 3") + self.expect("\^done") + self.expect("=breakpoint-modified,bkpt={number=\"3\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"(?!0xffffffffffffffff)0x[0-9a-f]+\",func=\"ns::foo2\(\)\",file=\"main\.cpp\",fullname=\".+?main\.cpp\",line=\"\d+\",times=\"0\",original-location=\"ns::foo2\"}") + + self.runCmd("-exec-continue") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"3\"") diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py b/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py index 742bbc8af6bd..a62b9a25400c 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiExecTestCase(lldbmi_testcase.MiTestCaseBase): @@ -15,7 +17,7 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races - @expectedFailureLinux # llvm.org/pr25000: lldb-mi does not receive broadcasted notification from Core/Process about process stopped + @expectedFailureAll(oslist=["linux"], bugnumber="llvm.org/pr25000: lldb-mi does not receive broadcasted notification from Core/Process about process stopped") def test_lldbmi_exec_run(self): """Test that 'lldb-mi --interpreter' can stop at entry.""" @@ -204,7 +206,7 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races - @expectedFailurei386 #xfail to get buildbot green, failing config: i386 binary running on ubuntu 14.04 x86_64 + @expectedFailureAll(archs=["i[3-6]86"], bugnumber="xfail to get buildbot green, failing config: i386 binary running on ubuntu 14.04 x86_64") def test_lldbmi_exec_next_instruction(self): """Test that 'lldb-mi --interpreter' works for instruction stepping.""" @@ -232,18 +234,20 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase): # Test that --thread is optional self.runCmd("-exec-next-instruction --frame 0") self.expect("\^running") - self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"28\"") + # Depending on compiler, it can stop at different line + self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"(28|29)\"") # Test that --frame is optional self.runCmd("-exec-next-instruction --thread 1") self.expect("\^running") - self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"29\"") + # Depending on compiler, it can stop at different line + self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"(29|30)\"") # Test that both --thread and --frame are optional self.runCmd("-exec-next-instruction") self.expect("\^running") # Depending on compiler, it can stop at different line - self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"(29|30)\"") + self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"(29|30|31)\"") # Test that an invalid --thread is handled self.runCmd("-exec-next-instruction --thread 0") diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/data/TestMiData.py b/packages/Python/lldbsuite/test/tools/lldb-mi/data/TestMiData.py index df9f54110f4b..a19387627c49 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/data/TestMiData.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/data/TestMiData.py @@ -8,7 +8,9 @@ from __future__ import print_function import unittest2 import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiDataTestCase(lldbmi_testcase.MiTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiCliSupport.py b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiCliSupport.py index 562be912fbc1..d80bc7f94a65 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiCliSupport.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiCliSupport.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiCliSupportTestCase(lldbmi_testcase.MiTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py index 93d9f25683b0..2bcaaad38f45 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @@ -55,7 +57,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races - @expectedFailureLinux # Failing in ~9/600 dosep runs (build 3120-3122) + @expectedFlakeyLinux(bugnumber="llvm.org/pr25470") def test_lldbmi_settings_set_target_run_args_before(self): """Test that 'lldb-mi --interpreter' can set target arguments by 'setting set target.run-args' command before than target was created.""" @@ -87,7 +89,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races - @expectedFailureLinux # Failing in ~9/600 dosep runs (build 3120-3122) + @expectedFailureAll(oslist=["linux"], bugnumber="Failing in ~9/600 dosep runs (build 3120-3122)") def test_lldbmi_settings_set_target_run_args_after(self): """Test that 'lldb-mi --interpreter' can set target arguments by 'setting set target.run-args' command after than target was created.""" diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/signal/TestMiSignal.py b/packages/Python/lldbsuite/test/tools/lldb-mi/signal/TestMiSignal.py index 11e7b8a82f68..197bfa80b3a0 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/signal/TestMiSignal.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/signal/TestMiSignal.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiSignalTestCase(lldbmi_testcase.MiTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/stack/TestMiStack.py b/packages/Python/lldbsuite/test/tools/lldb-mi/stack/TestMiStack.py index 14dab38bb338..54ed91951333 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/stack/TestMiStack.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/stack/TestMiStack.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiStackTestCase(lldbmi_testcase.MiTestCaseBase): @@ -199,7 +201,20 @@ class MiStackTestCase(lldbmi_testcase.MiTestCaseBase): self.expect("\^done,locals=\[{name=\"test_str\",type=\"const char \*\",value=\".*?Rakaposhi.*?\"},{name=\"var_e\",type=\"int\",value=\"24\"},{name=\"ptr\",type=\"int \*\",value=\".*?\"}\]") self.runCmd("-stack-list-locals --simple-values") self.expect("\^done,locals=\[{name=\"test_str\",type=\"const char \*\",value=\".*?Rakaposhi.*?\"},{name=\"var_e\",type=\"int\",value=\"24\"},{name=\"ptr\",type=\"int \*\",value=\".*?\"}\]") + + # Test -stack-list-locals in a function with catch clause, + # having unnamed parameter + # Run to BP_catch_unnamed + line = line_number('main.cpp', '// BP_catch_unnamed') + self.runCmd("-break-insert --file main.cpp:%d" % line) + self.expect("\^done,bkpt={number=\"6\"") + self.runCmd("-exec-continue") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + # Test -stack-list-locals: use --no-values + self.runCmd("-stack-list-locals --no-values") + self.expect("\^done,locals=\[name=\"i\",name=\"j\"\]") @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_stack_list_variables(self): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/stack/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-mi/stack/main.cpp index e11f83e108ec..32db32d2fd16 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/stack/main.cpp +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/stack/main.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include + struct inner { int var_d; @@ -114,6 +116,18 @@ int do_tests_with_args() return 0; } +void catch_unnamed_test() +{ + try + { + int i = 1, j = 2; + throw std::exception(); // BP_catch_unnamed + } + catch(std::exception&) + { + } +} + int main(int argc, char const *argv[]) { @@ -121,6 +135,7 @@ main(int argc, char const *argv[]) local_struct_test(); local_array_test(); local_pointer_test(); + catch_unnamed_test(); do_tests_with_args(); return 0; diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py index 8f02f1c1eca8..8ddb6b3a1509 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py @@ -4,10 +4,10 @@ Test lldb-mi startup options. from __future__ import print_function - - import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/symbol/TestMiSymbol.py b/packages/Python/lldbsuite/test/tools/lldb-mi/symbol/TestMiSymbol.py index 3566b2f220c2..859c096e336d 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/symbol/TestMiSymbol.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/symbol/TestMiSymbol.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiSymbolTestCase(lldbmi_testcase.MiTestCaseBase): @@ -15,7 +17,7 @@ class MiSymbolTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races - @expectedFailureLinux # new failure after r256863 + @expectedFailureAll(oslist=["linux"], bugnumber="new failure after r256863") def test_lldbmi_symbol_list_lines_file(self): """Test that 'lldb-mi --interpreter' works for -symbol-list-lines when file exists.""" diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py b/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py index f8a6743eb16d..a40e49f70e7e 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiSyntaxTestCase(lldbmi_testcase.MiTestCaseBase): @@ -61,7 +63,7 @@ class MiSyntaxTestCase(lldbmi_testcase.MiTestCaseBase): @skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races - @expectedFailureLinux # Failing in ~6/600 dosep runs (build 3120-3122) + @expectedFailureAll(oslist=["linux"], bugnumber="Failing in ~6/600 dosep runs (build 3120-3122)") def test_lldbmi_process_output(self): """Test that 'lldb-mi --interpreter' wraps process output correctly.""" diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/target/TestMiTarget.py b/packages/Python/lldbsuite/test/tools/lldb-mi/target/TestMiTarget.py index 73ef913691cf..2d47db03637c 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/target/TestMiTarget.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/target/TestMiTarget.py @@ -4,10 +4,10 @@ Test lldb-mi -target-xxx commands. from __future__ import print_function - - import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiTargetTestCase(lldbmi_testcase.MiTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/Makefile b/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/Makefile new file mode 100644 index 000000000000..b6fad6778428 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../../make + +CXX_SOURCES := test_threadinfo.cpp + +ENABLE_THREADS := YES + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/TestMiThreadInfo.py b/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/TestMiThreadInfo.py new file mode 100644 index 000000000000..7226f2e8d320 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/TestMiThreadInfo.py @@ -0,0 +1,39 @@ +""" +Test lldb-mi -thread-info command. +""" + +from __future__ import print_function + +import lldbmi_testcase +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class MiThreadInfoTestCase(lldbmi_testcase.MiTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIfWindows # pthreads not supported on Windows + @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races + def test_lldbmi_thread_info(self): + """Test that -thread-info prints thread info and the current-thread-id""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + self.runCmd("-break-insert ThreadProc") + self.expect("\^done") + + # Run to the breakpoint + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + self.runCmd("-thread-info") + self.expect("\^done,threads=\[\{id=\"1\",(.*)\},\{id=\"2\",(.*)\],current-thread-id=\"2\"") + + self.runCmd("-gdb-quit") + diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/test_threadinfo.cpp b/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/test_threadinfo.cpp new file mode 100644 index 000000000000..1f444ece8c21 --- /dev/null +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/threadinfo/test_threadinfo.cpp @@ -0,0 +1,21 @@ +#include +#include +#include + +using namespace std; + +void +ThreadProc() +{ + int i = 0; + i++; +} + +int +main() +{ + thread t(ThreadProc); + t.join(); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py b/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py index 067df6408bd4..5ce2b99bbdee 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py @@ -8,7 +8,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): @@ -108,7 +110,7 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): self.expect("\^error,msg=\"The request ''print' expects option-name and \"on\" or \"off\"' failed.\"") @skipIfWindows #llvm.org/pr24452: Get lldb-mi working on Windows - @expectedFailureGcc("https://llvm.org/bugs/show_bug.cgi?id=23357") + @expectedFailureAll(compiler="gcc", bugnumber="llvm.org/pr23357") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_gdb_set_show_print_expand_aggregates(self): """Test that 'lldb-mi --interpreter' can expand aggregates everywhere.""" @@ -167,7 +169,7 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): self.expect("\^error,msg=\"The request ''print' expects option-name and \"on\" or \"off\"' failed.\"") @skipIfWindows #llvm.org/pr24452: Get lldb-mi working on Windows - @expectedFailureGcc("https://llvm.org/bugs/show_bug.cgi?id=23357") + @expectedFailureAll(compiler="gcc", bugnumber="llvm.org/pr23357") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_gdb_set_show_print_aggregate_field_names(self): """Test that 'lldb-mi --interpreter' can expand aggregates everywhere.""" diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py b/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py index 26f3a9c63bdc..51f02b9e4a74 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py +++ b/packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py @@ -7,7 +7,9 @@ from __future__ import print_function import lldbmi_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class MiVarTestCase(lldbmi_testcase.MiTestCaseBase): @@ -34,9 +36,9 @@ class MiVarTestCase(lldbmi_testcase.MiTestCaseBase): # Print non-existant variable self.runCmd("-var-create var1 * undef") - self.expect("\^error,msg=\"error: error: use of undeclared identifier \'undef\'\\\\nerror: 1 errors parsing expression\\\\n\"") + self.expect("\^error,msg=\"error: use of undeclared identifier \'undef\'\\\\n\"") self.runCmd("-data-evaluate-expression undef") - self.expect("\^error,msg=\"Could not evaluate expression\"") + self.expect("\^error,msg=\"error: use of undeclared identifier \'undef\'\\\\n\"") # Print global "g_MyVar", modify, delete and create again self.runCmd("-data-evaluate-expression g_MyVar") diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGDBRemoteMemoryRead.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGDBRemoteMemoryRead.py index 7b974e548a58..1296d513b917 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGDBRemoteMemoryRead.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGDBRemoteMemoryRead.py @@ -6,18 +6,21 @@ from __future__ import print_function +import binascii import os + import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil -import binascii +from lldbsuite.test import lldbutil +from lldbsuite.test import lldbplatformutil class MemoryReadTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipUnlessPlatform(getDarwinOSTriples()+["linux"]) + @skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples()+["linux"]) def test_memory_read(self): self.build() exe = os.path.join (os.getcwd(), "a.out") @@ -34,7 +37,8 @@ class MemoryReadTestCase(TestBase): error = lldb.SBError() memory = process.ReadMemory(pc, size, error) self.assertTrue(error.Success()) - self.match("process plugin packet send x%x,%x" % (pc, size), ["response:", memory]) + # Results in trying to write non-printable characters to the session log. + # self.match("process plugin packet send x%x,%x" % (pc, size), ["response:", memory]) self.match("process plugin packet send m%x,%x" % (pc, size), ["response:", binascii.hexlify(memory)]) process.Continue() diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteAttach.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteAttach.py index ca96a9a837b9..5460b21382ec 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteAttach.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteAttach.py @@ -4,8 +4,9 @@ from __future__ import print_function import gdbremote_testcase import lldbgdbserverutils - +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteAttach(gdbremote_testcase.GdbRemoteTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteAuxvSupport.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteAuxvSupport.py index 1ce5779e7897..e70ad5f570a7 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteAuxvSupport.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteAuxvSupport.py @@ -3,7 +3,9 @@ from __future__ import print_function import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase): @@ -23,7 +25,7 @@ class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase): # Start the inferior... "read packet: $c#63", # ... match output.... - { "type":"output_match", "regex":r"^message:main entered\r\n$" }, + { "type":"output_match", "regex":self.maybe_strict_output_regex(r"message:main entered\r\n") }, ], True) # ... then interrupt. self.add_interrupt_packets() diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteExpeditedRegisters.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteExpeditedRegisters.py index 6535ce40475d..7daae871caf6 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteExpeditedRegisters.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteExpeditedRegisters.py @@ -3,7 +3,9 @@ from __future__ import print_function import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteExpeditedRegisters(gdbremote_testcase.GdbRemoteTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteKill.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteKill.py index b253254c78ed..560da9d41429 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteKill.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteKill.py @@ -4,8 +4,9 @@ from __future__ import print_function import gdbremote_testcase import lldbgdbserverutils - +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteKill(gdbremote_testcase.GdbRemoteTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py index a11167b87c25..f26b62043613 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py @@ -1,12 +1,13 @@ from __future__ import print_function +import sys import gdbremote_testcase import lldbgdbserverutils -import sys - +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteProcessInfo(gdbremote_testcase.GdbRemoteTestCaseBase): @@ -51,7 +52,7 @@ class TestGdbRemoteProcessInfo(gdbremote_testcase.GdbRemoteTestCaseBase): self.add_process_info_collection_packets() # Run the stream - context = self.expect_gdbremote_sequence() + context = self.expect_gdbremote_sequence(timeout_seconds = 8) self.assertIsNotNone(context) # Gather process info response diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteRegisterState.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteRegisterState.py index a36b4ae781ad..63a8995c6729 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteRegisterState.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteRegisterState.py @@ -3,7 +3,9 @@ from __future__ import print_function import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteRegisterState(gdbremote_testcase.GdbRemoteTestCaseBase): """Test QSaveRegisterState/QRestoreRegisterState support.""" @@ -24,7 +26,7 @@ class TestGdbRemoteRegisterState(gdbremote_testcase.GdbRemoteTestCaseBase): # Start the inferior... "read packet: $c#63", # ... match output.... - { "type":"output_match", "regex":r"^message:main entered\r\n$" }, + { "type":"output_match", "regex":self.maybe_strict_output_regex(r"message:main entered\r\n") }, ], True) # ... then interrupt. self.add_interrupt_packets() diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteSingleStep.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteSingleStep.py index 3b008249f557..31d53bed2593 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteSingleStep.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteSingleStep.py @@ -3,7 +3,9 @@ from __future__ import print_function import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteSingleStep(gdbremote_testcase.GdbRemoteTestCaseBase): @@ -17,7 +19,8 @@ class TestGdbRemoteSingleStep(gdbremote_testcase.GdbRemoteTestCaseBase): self.single_step_only_steps_one_instruction(use_Hc_packet=True, step_instruction="s") @llgs_test - @expectedFailureAndroid(bugnumber="llvm.com/pr24739", archs=["arm", "aarch64"]) + @expectedFailureAndroid(bugnumber="llvm.org/pr24739", archs=["arm", "aarch64"]) + @expectedFailureAll(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr24739") def test_single_step_only_steps_one_instruction_with_s_llgs(self): self.init_llgs_test() self.build() diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py index a7938795b9bf..d55416569ac4 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteThreadsInStopReply.py @@ -1,9 +1,9 @@ from __future__ import print_function - - import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteThreadsInStopReply(gdbremote_testcase.GdbRemoteTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py index cce484451de4..b2b54e3f0394 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_qThreadStopInfo.py @@ -6,7 +6,9 @@ import sys import unittest2 import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemote_qThreadStopInfo(gdbremote_testcase.GdbRemoteTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vCont.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vCont.py index 579e99d6d774..335d96c2b074 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vCont.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vCont.py @@ -1,9 +1,9 @@ from __future__ import print_function - - import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase): @@ -93,7 +93,8 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase): self.single_step_only_steps_one_instruction(use_Hc_packet=True, step_instruction="vCont;s") @llgs_test - @expectedFailureAndroid(bugnumber="llvm.com/pr24739", archs=["arm", "aarch64"]) + @expectedFailureAndroid(bugnumber="llvm.org/pr24739", archs=["arm", "aarch64"]) + @expectedFailureAll(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr24739") def test_single_step_only_steps_one_instruction_with_Hc_vCont_s_llgs(self): self.init_llgs_test() self.build() @@ -108,7 +109,8 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase): self.single_step_only_steps_one_instruction(use_Hc_packet=False, step_instruction="vCont;s:{thread}") @llgs_test - @expectedFailureAndroid(bugnumber="llvm.com/pr24739", archs=["arm", "aarch64"]) + @expectedFailureAndroid(bugnumber="llvm.org/pr24739", archs=["arm", "aarch64"]) + @expectedFailureAll(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr24739") def test_single_step_only_steps_one_instruction_with_vCont_s_thread_llgs(self): self.init_llgs_test() self.build() diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py index aec040c50569..c01cc7a17250 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py @@ -19,7 +19,9 @@ import gdbremote_testcase import lldbgdbserverutils import platform import signal +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): @@ -230,7 +232,7 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): self.add_verified_launch_packets(launch_args) self.test_sequence.add_log_lines( ["read packet: $vCont;c#a8", - {"type":"output_match", "regex":r"^hello, world\r\n$" }, + {"type":"output_match", "regex": self.maybe_strict_output_regex(r"hello, world\r\n")}, "send packet: $W00#00"], True) @@ -244,6 +246,7 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): self.inferior_print_exit() @llgs_test + @expectedFlakeyLinux("llvm.org/pr25652") def test_inferior_print_exit_llgs(self): self.init_llgs_test() self.build() @@ -865,7 +868,8 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): "read packet: $c#63", # Match output line that prints the memory address of the message buffer within the inferior. # Note we require launch-only testing so we can get inferior otuput. - { "type":"output_match", "regex":r"^data address: 0x([0-9a-fA-F]+)\r\n$", "capture":{ 1:"message_address"} }, + { "type":"output_match", "regex":self.maybe_strict_output_regex(r"data address: 0x([0-9a-fA-F]+)\r\n"), + "capture":{ 1:"message_address"} }, # Now stop the inferior. "read packet: {}".format(chr(3)), # And wait for the stop notification. @@ -947,7 +951,8 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): "read packet: $c#63", # Match output line that prints the memory address of the message buffer within the inferior. # Note we require launch-only testing so we can get inferior otuput. - { "type":"output_match", "regex":r"^code address: 0x([0-9a-fA-F]+)\r\n$", "capture":{ 1:"code_address"} }, + { "type":"output_match", "regex":self.maybe_strict_output_regex(r"code address: 0x([0-9a-fA-F]+)\r\n"), + "capture":{ 1:"code_address"} }, # Now stop the inferior. "read packet: {}".format(chr(3)), # And wait for the stop notification. @@ -1008,7 +1013,8 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): "read packet: $c#63", # Match output line that prints the memory address of the message buffer within the inferior. # Note we require launch-only testing so we can get inferior otuput. - { "type":"output_match", "regex":r"^stack address: 0x([0-9a-fA-F]+)\r\n$", "capture":{ 1:"stack_address"} }, + { "type":"output_match", "regex":self.maybe_strict_output_regex(r"stack address: 0x([0-9a-fA-F]+)\r\n"), + "capture":{ 1:"stack_address"} }, # Now stop the inferior. "read packet: {}".format(chr(3)), # And wait for the stop notification. @@ -1069,7 +1075,8 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): "read packet: $c#63", # Match output line that prints the memory address of the message buffer within the inferior. # Note we require launch-only testing so we can get inferior otuput. - { "type":"output_match", "regex":r"^heap address: 0x([0-9a-fA-F]+)\r\n$", "capture":{ 1:"heap_address"} }, + { "type":"output_match", "regex":self.maybe_strict_output_regex(r"heap address: 0x([0-9a-fA-F]+)\r\n"), + "capture":{ 1:"heap_address"} }, # Now stop the inferior. "read packet: {}".format(chr(3)), # And wait for the stop notification. @@ -1132,7 +1139,8 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): "read packet: $c#63", # Match output line that prints the memory address of the function call entry point. # Note we require launch-only testing so we can get inferior otuput. - { "type":"output_match", "regex":r"^code address: 0x([0-9a-fA-F]+)\r\n$", "capture":{ 1:"function_address"} }, + { "type":"output_match", "regex":self.maybe_strict_output_regex(r"code address: 0x([0-9a-fA-F]+)\r\n"), + "capture":{ 1:"function_address"} }, # Now stop the inferior. "read packet: {}".format(chr(3)), # And wait for the stop notification. @@ -1230,6 +1238,7 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): self.software_breakpoint_set_and_remove_work() @llgs_test + @expectedFlakeyLinux("llvm.org/pr25652") def test_software_breakpoint_set_and_remove_work_llgs(self): self.init_llgs_test() self.build() @@ -1275,7 +1284,8 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): "read packet: $c#63", # Match output line that prints the memory address of the message buffer within the inferior. # Note we require launch-only testing so we can get inferior otuput. - { "type":"output_match", "regex":r"^data address: 0x([0-9a-fA-F]+)\r\n$", "capture":{ 1:"message_address"} }, + { "type":"output_match", "regex":self.maybe_strict_output_regex(r"data address: 0x([0-9a-fA-F]+)\r\n"), + "capture":{ 1:"message_address"} }, # Now stop the inferior. "read packet: {}".format(chr(3)), # And wait for the stop notification. @@ -1316,6 +1326,7 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): self.written_M_content_reads_back_correctly() @llgs_test + @expectedFlakeyLinux("llvm.org/pr25652") def test_written_M_content_reads_back_correctly_llgs(self): self.init_llgs_test() self.build() diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubReverseConnect.py b/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubReverseConnect.py index 9035237b982a..6894d1ceacc6 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubReverseConnect.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubReverseConnect.py @@ -6,7 +6,9 @@ import re import select import socket import time +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestStubReverseConnect(gdbremote_testcase.GdbRemoteTestCaseBase): diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubSetSID.py b/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubSetSID.py index 2b2b0e82379b..bda93155d27e 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubSetSID.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/commandline/TestStubSetSID.py @@ -8,7 +8,9 @@ import os import select import tempfile import time +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestStubSetSIDTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): @@ -47,7 +49,7 @@ class TestStubSetSIDTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): @llgs_test @skipIfRemote # --setsid not used on remote platform and currently it is also impossible to get the sid of lldb-platform running on a remote target - @expectedFailureFreeBSD() + @expectedFailureAll(oslist=['freebsd']) def test_sid_is_same_without_setsid_llgs(self): self.init_llgs_test() self.set_inferior_startup_launch() diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py index 113e01e36ba7..d63ddbe39998 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py @@ -24,14 +24,16 @@ from lldbsuite.test.lldbtest import * from lldbgdbserverutils import * import logging +class _ConnectionRefused(IOError): + pass + class GdbRemoteTestCaseBase(TestBase): - _TIMEOUT_SECONDS = 5 + NO_DEBUG_INFO_TESTCASE = True - _GDBREMOTE_KILL_PACKET = "$k#6b" + _TIMEOUT_SECONDS = 7 - _LOGGING_LEVEL = logging.WARNING - # _LOGGING_LEVEL = logging.DEBUG + _GDBREMOTE_KILL_PACKET = "$k#6b" # Start the inferior separately, attach to the inferior on the stub command line. _STARTUP_ATTACH = "attach" @@ -48,12 +50,44 @@ class GdbRemoteTestCaseBase(TestBase): TARGET_EXC_SOFTWARE = 0x95 TARGET_EXC_BREAKPOINT = 0x96 + _verbose_log_handler = None + _log_formatter = logging.Formatter(fmt='%(asctime)-15s %(levelname)-8s %(message)s') + + def setUpBaseLogging(self): + self.logger = logging.getLogger(__name__) + + if len(self.logger.handlers) > 0: + return # We have set up this handler already + + self.logger.propagate = False + self.logger.setLevel(logging.DEBUG) + + # log all warnings to stderr + handler = logging.StreamHandler() + handler.setLevel(logging.WARNING) + handler.setFormatter(self._log_formatter) + self.logger.addHandler(handler) + + + def isVerboseLoggingRequested(self): + # We will report our detailed logs if the user requested that the "gdb-remote" channel is + # logged. + return any(("gdb-remote" in channel) for channel in lldbtest_config.channels) + def setUp(self): TestBase.setUp(self) - FORMAT = '%(asctime)-15s %(levelname)-8s %(message)s' - logging.basicConfig(format=FORMAT) - self.logger = logging.getLogger(__name__) - self.logger.setLevel(self._LOGGING_LEVEL) + + self.setUpBaseLogging() + self.debug_monitor_extra_args = [] + self._pump_queues = socket_packet_pump.PumpQueues() + + if self.isVerboseLoggingRequested(): + # If requested, full logs go to a log file + self._verbose_log_handler = logging.FileHandler(self.log_basename + "-host.log") + self._verbose_log_handler.setFormatter(self._log_formatter) + self._verbose_log_handler.setLevel(logging.DEBUG) + self.logger.addHandler(self._verbose_log_handler) + self.test_sequence = GdbRemoteTestSequence(self.logger) self.set_inferior_startup_launch() self.port = self.get_next_port() @@ -76,6 +110,31 @@ class GdbRemoteTestCaseBase(TestBase): else: self.stub_hostname = "localhost" + def tearDown(self): + self._pump_queues.verify_queues_empty() + + self.logger.removeHandler(self._verbose_log_handler) + self._verbose_log_handler = None + TestBase.tearDown(self) + + def getLocalServerLogFile(self): + return self.log_basename + "-server.log" + + def setUpServerLogging(self, is_llgs): + if len(lldbtest_config.channels) == 0: + return # No logging requested + + if lldb.remote_platform: + log_file = lldbutil.join_remote_paths(lldb.remote_platform.GetWorkingDirectory(), "server.log") + else: + log_file = self.getLocalServerLogFile() + + if is_llgs: + self.debug_monitor_extra_args.append("--log-file=" + log_file) + self.debug_monitor_extra_args.append("--log-channels={}".format(":".join(lldbtest_config.channels))) + else: + self.debug_monitor_extra_args = ["--log-file=" + self.log_file, "--log-flags=0x800000"] + def get_next_port(self): return 12000 + random.randint(0,3999) @@ -147,30 +206,21 @@ class GdbRemoteTestCaseBase(TestBase): return stub_port - def run_shell_cmd(self, cmd): - platform = self.dbg.GetSelectedPlatform() - shell_cmd = lldb.SBPlatformShellCommand(cmd) - err = platform.Run(shell_cmd) - if err.Fail() or shell_cmd.GetStatus(): - m = "remote_platform.RunShellCommand('%s') failed:\n" % cmd - m += ">>> return code: %d\n" % shell_cmd.GetStatus() - if err.Fail(): - m += ">>> %s\n" % str(err).strip() - m += ">>> %s\n" % (shell_cmd.GetOutput() or - "Command generated no output.") - raise Exception(m) - return shell_cmd.GetOutput().strip() - def init_llgs_test(self, use_named_pipe=True): if lldb.remote_platform: # Remote platforms don't support named pipe based port negotiation use_named_pipe = False # Grab the ppid from /proc/[shell pid]/stat - shell_stat = self.run_shell_cmd("cat /proc/$$/stat") + err, retcode, shell_stat = self.run_platform_command("cat /proc/$$/stat") + self.assertTrue(err.Success() and retcode == 0, + "Failed to read file /proc/$$/stat: %s, retcode: %d" % (err.GetCString(), retcode)) + # [pid] ([executable]) [state] [*ppid*] pid = re.match(r"^\d+ \(.+\) . (\d+)", shell_stat).group(1) - ls_output = self.run_shell_cmd("ls -l /proc/%s/exe" % pid) + err, retcode, ls_output = self.run_platform_command("ls -l /proc/%s/exe" % pid) + self.assertTrue(err.Success() and retcode == 0, + "Failed to read file /proc/%s/exe: %s, retcode: %d" % (pid, err.GetCString(), retcode)) exe = ls_output.split()[-1] # If the binary has been deleted, the link name has " (deleted)" appended. @@ -182,10 +232,7 @@ class GdbRemoteTestCaseBase(TestBase): self.skipTest("lldb-server exe not found") self.debug_monitor_extra_args = ["gdbserver"] - - if len(lldbtest_config.channels) > 0: - self.debug_monitor_extra_args.append("--log-file={}-server.log".format(self.log_basename)) - self.debug_monitor_extra_args.append("--log-channels={}".format(":".join(lldbtest_config.channels))) + self.setUpServerLogging(is_llgs=True) if use_named_pipe: (self.named_pipe_path, self.named_pipe, self.named_pipe_fd) = self.create_named_pipe() @@ -194,7 +241,7 @@ class GdbRemoteTestCaseBase(TestBase): self.debug_monitor_exe = get_debugserver_exe() if not self.debug_monitor_exe: self.skipTest("debugserver exe not found") - self.debug_monitor_extra_args = ["--log-file={}-server.log".format(self.log_basename), "--log-flags=0x800000"] + self.setUpServerLogging(is_llgs=False) if use_named_pipe: (self.named_pipe_path, self.named_pipe, self.named_pipe_fd) = self.create_named_pipe() # The debugserver stub has a race on handling the 'k' command, so it sends an X09 right away, then sends the real X notification @@ -209,6 +256,22 @@ class GdbRemoteTestCaseBase(TestBase): subprocess.call(adb + [ "tcp:%d" % source, "tcp:%d" % target]) self.addTearDownHook(remove_port_forward) + def _verify_socket(self, sock): + # Normally, when the remote stub is not ready, we will get ECONNREFUSED during the + # connect() attempt. However, due to the way how ADB forwarding works, on android targets + # the connect() will always be successful, but the connection will be immediately dropped + # if ADB could not connect on the remote side. This function tries to detect this + # situation, and report it as "connection refused" so that the upper layers attempt the + # connection again. + triple = self.dbg.GetSelectedPlatform().GetTriple() + if not re.match(".*-.*-.*-android", triple): + return # Not android. + can_read, _, _ = select.select([sock], [], [], 0.1) + if sock not in can_read: + return # Data is not available, but the connection is alive. + if len(sock.recv(1, socket.MSG_PEEK)) == 0: + raise _ConnectionRefused() # Got EOF, connection dropped. + def create_socket(self): sock = socket.socket() logger = self.logger @@ -217,8 +280,14 @@ class GdbRemoteTestCaseBase(TestBase): if re.match(".*-.*-.*-android", triple): self.forward_adb_port(self.port, self.port, "forward", self.stub_device) + logger.info("Connecting to debug monitor on %s:%d", self.stub_hostname, self.port) connect_info = (self.stub_hostname, self.port) - sock.connect(connect_info) + try: + sock.connect(connect_info) + except socket.error as serr: + if serr.errno == errno.ECONNREFUSED: + raise _ConnectionRefused() + raise serr def shutdown_socket(): if sock: @@ -235,6 +304,8 @@ class GdbRemoteTestCaseBase(TestBase): self.addTearDownHook(shutdown_socket) + self._verify_socket(sock) + return sock def set_inferior_startup_launch(self): @@ -258,12 +329,6 @@ class GdbRemoteTestCaseBase(TestBase): commandline_args += ["--named-pipe", self.named_pipe_path] return commandline_args - def run_platform_command(self, cmd): - platform = self.dbg.GetSelectedPlatform() - shell_command = lldb.SBPlatformShellCommand(cmd) - err = platform.Run(shell_command) - return (err, shell_command.GetOutput()) - def launch_debug_monitor(self, attach_pid=None, logfile=None): # Create the command line. commandline_args = self.get_debug_monitor_command_line_args(attach_pid=attach_pid) @@ -322,12 +387,12 @@ class GdbRemoteTestCaseBase(TestBase): while connect_attemps < MAX_CONNECT_ATTEMPTS: # Create a socket to talk to the server try: + logger.info("Connect attempt %d", connect_attemps+1) self.sock = self.create_socket() return server - except socket.error as serr: - # We're only trying to handle connection refused. - if serr.errno != errno.ECONNREFUSED: - raise serr + except _ConnectionRefused as serr: + # Ignore, and try again. + pass time.sleep(0.5) connect_attemps += 1 @@ -546,7 +611,8 @@ class GdbRemoteTestCaseBase(TestBase): def expect_gdbremote_sequence(self, timeout_seconds=None): if not timeout_seconds: timeout_seconds = self._TIMEOUT_SECONDS - return expect_lldb_gdbserver_replay(self, self.sock, self.test_sequence, timeout_seconds, self.logger) + return expect_lldb_gdbserver_replay(self, self.sock, self.test_sequence, + self._pump_queues, timeout_seconds, self.logger) _KNOWN_REGINFO_KEYS = [ "name", @@ -556,6 +622,7 @@ class GdbRemoteTestCaseBase(TestBase): "encoding", "format", "set", + "gcc", "ehframe", "dwarf", "generic", @@ -1281,6 +1348,9 @@ class GdbRemoteTestCaseBase(TestBase): #MIPS required "3" (ADDIU, SB, LD) machine instructions for updation of variable value if re.match("mips",arch): expected_step_count = 3 + #S390X requires "2" (LARL, MVI) machine instructions for updation of variable value + if re.match("s390x",arch): + expected_step_count = 2 self.assertEqual(step_count, expected_step_count) # Verify we hit the next state. @@ -1297,3 +1367,6 @@ class GdbRemoteTestCaseBase(TestBase): self.assertTrue(state_reached) self.assertEqual(step_count, expected_step_count) + def maybe_strict_output_regex(self, regex): + return '.*'+regex+'.*' if lldbplatformutil.hasChattyStderr(self) else '^'+regex+'$' + diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/TestGdbRemoteAbort.py b/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/TestGdbRemoteAbort.py index d13433252e12..8bd00a3f1b21 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/TestGdbRemoteAbort.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/TestGdbRemoteAbort.py @@ -4,7 +4,9 @@ from __future__ import print_function import gdbremote_testcase import signal +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteAbort(gdbremote_testcase.GdbRemoteTestCaseBase): mydir = TestBase.compute_mydir(__file__) diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/TestGdbRemoteSegFault.py b/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/TestGdbRemoteSegFault.py index 6618d8f75fc9..949b00b0f614 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/TestGdbRemoteSegFault.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/inferior-crash/TestGdbRemoteSegFault.py @@ -4,7 +4,9 @@ from __future__ import print_function import gdbremote_testcase import signal +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class TestGdbRemoteSegFault(gdbremote_testcase.GdbRemoteTestCaseBase): mydir = TestBase.compute_mydir(__file__) diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py b/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py index c0ea841e2a03..0c73bed9ea0a 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/lldbgdbserverutils.py @@ -154,6 +154,7 @@ def expect_lldb_gdbserver_replay( asserter, sock, test_sequence, + pump_queues, timeout_seconds, logger=None): """Replay socket communication with lldb-gdbserver and verify responses. @@ -193,7 +194,7 @@ def expect_lldb_gdbserver_replay( return {} context = {"O_count":0, "O_content":""} - with socket_packet_pump.SocketPacketPump(sock, logger) as pump: + with socket_packet_pump.SocketPacketPump(sock, pump_queues, logger) as pump: # Grab the first sequence entry. sequence_entry = test_sequence.entries.pop(0) @@ -220,14 +221,14 @@ def expect_lldb_gdbserver_replay( if sequence_entry.is_output_matcher(): try: # Grab next entry from the output queue. - content = pump.output_queue().get(True, timeout_seconds) + content = pump_queues.output_queue().get(True, timeout_seconds) except queue.Empty: if logger: logger.warning("timeout waiting for stub output (accumulated output:{})".format(pump.get_accumulated_output())) raise Exception("timed out while waiting for output match (accumulated output: {})".format(pump.get_accumulated_output())) else: try: - content = pump.packet_queue().get(True, timeout_seconds) + content = pump_queues.packet_queue().get(True, timeout_seconds) except queue.Empty: if logger: logger.warning("timeout waiting for packet match (receive buffer: {})".format(pump.get_receive_buffer())) @@ -386,7 +387,10 @@ def pack_register_hex(endian, value, byte_size=None): return retval elif endian == 'big': - retval = value.encode("hex") + retval = "" + while value != 0: + retval = "{:02x}".format(value & 0xff) + retval + value = value >> 8 if byte_size: # Add zero-fill to the left/front (MSB side) of the value. retval = ("00" * (byte_size - len(retval)/2)) + retval @@ -783,7 +787,7 @@ class GdbRemoteTestSequence(object): regex = line.get("regex", None) # Compile the regex. if regex and (type(regex) == str): - regex = re.compile(regex) + regex = re.compile(regex, re.DOTALL) regex_mode = line.get("regex_mode", "match") capture = line.get("capture", None) diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py b/packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py index b50a03015462..5c28d288db53 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py @@ -1,8 +1,11 @@ from __future__ import print_function +import time + import gdbremote_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test import lldbutil class TestPlatformProcessConnect(gdbremote_testcase.GdbRemoteTestCaseBase): mydir = TestBase.compute_mydir(__file__) @@ -21,11 +24,22 @@ class TestPlatformProcessConnect(gdbremote_testcase.GdbRemoteTestCaseBase): if err.Fail(): raise RuntimeError("Unable copy '%s' to '%s'.\n>>> %s" % (f, wd, err.GetCString())) + m = re.search("^(.*)://([^:/]*)", configuration.lldb_platform_url) + protocol = m.group(1) + hostname = m.group(2) + unix_protocol = protocol.startswith("unix-") + if unix_protocol: + p = re.search("^(.*)-connect", protocol) + listen_url = "%s://%s" % (p.group(1), os.path.join(working_dir, "platform-%d.sock" % int(time.time()))) + else: + listen_url = "*:0" + port_file = "%s/port" % working_dir - commandline_args = ["platform", "--listen", "*:0", "--socket-file", port_file, "--", "%s/a.out" % working_dir, "foo"] + commandline_args = ["platform", "--listen", listen_url, "--socket-file", port_file, "--", "%s/a.out" % working_dir, "foo"] self.spawnSubprocess(self.debug_monitor_exe, commandline_args, install_remote=False) self.addTearDownHook(self.cleanupSubprocesses) - new_port = self.run_shell_cmd("while [ ! -f %s ]; do sleep 0.25; done && cat %s" % (port_file, port_file)) + + socket_id = lldbutil.wait_for_file_on_target(self, port_file) new_debugger = lldb.SBDebugger.Create() new_debugger.SetAsync(False) @@ -37,8 +51,12 @@ class TestPlatformProcessConnect(gdbremote_testcase.GdbRemoteTestCaseBase): new_debugger.SetSelectedPlatform(new_platform) new_interpreter = new_debugger.GetCommandInterpreter() - m = re.search("(.*):[0-9]+", configuration.lldb_platform_url) - command = "platform connect %s:%s" % (m.group(1), new_port) + if unix_protocol: + connect_url = "%s://%s%s" % (protocol, hostname, socket_id) + else: + connect_url = "%s://%s:%s" % (protocol, hostname, socket_id) + + command = "platform connect %s" % (connect_url) result = lldb.SBCommandReturnObject() new_interpreter.HandleCommand(command, result) self.assertTrue(result.Succeeded(), "platform process connect failed: %s" % result.GetOutput()) diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/socket_packet_pump.py b/packages/Python/lldbsuite/test/tools/lldb-server/socket_packet_pump.py index 795a8c6652d0..9f594b7df73c 100644 --- a/packages/Python/lldbsuite/test/tools/lldb-server/socket_packet_pump.py +++ b/packages/Python/lldbsuite/test/tools/lldb-server/socket_packet_pump.py @@ -26,6 +26,33 @@ def _dump_queue(the_queue): print(codecs.encode(the_queue.get(True), "string_escape")) print("\n") +class PumpQueues(object): + def __init__(self): + self._output_queue = queue.Queue() + self._packet_queue = queue.Queue() + + def output_queue(self): + return self._output_queue + + def packet_queue(self): + return self._packet_queue + + def verify_queues_empty(self): + # Warn if there is any content left in any of the queues. + # That would represent unmatched packets. + if not self.output_queue().empty(): + print("warning: output queue entries still exist:") + _dump_queue(self.output_queue()) + print("from here:") + traceback.print_stack() + + if not self.packet_queue().empty(): + print("warning: packet queue entries still exist:") + _dump_queue(self.packet_queue()) + print("from here:") + traceback.print_stack() + + class SocketPacketPump(object): """A threaded packet reader that partitions packets into two streams. @@ -40,18 +67,17 @@ class SocketPacketPump(object): _GDB_REMOTE_PACKET_REGEX = re.compile(r'^\$([^\#]*)#[0-9a-fA-F]{2}') - def __init__(self, pump_socket, logger=None): + def __init__(self, pump_socket, pump_queues, logger=None): if not pump_socket: raise Exception("pump_socket cannot be None") - self._output_queue = queue.Queue() - self._packet_queue = queue.Queue() self._thread = None self._stop_thread = False self._socket = pump_socket self._logger = logger self._receive_buffer = "" self._accumulated_output = "" + self._pump_queues = pump_queues def __enter__(self): """Support the python 'with' statement. @@ -66,20 +92,6 @@ class SocketPacketPump(object): Shut down the pump thread.""" self.stop_pump_thread() - # Warn if there is any content left in any of the queues. - # That would represent unmatched packets. - if not self.output_queue().empty(): - print("warning: output queue entries still exist:") - _dump_queue(self.output_queue()) - print("from here:") - traceback.print_stack() - - if not self.packet_queue().empty(): - print("warning: packet queue entries still exist:") - _dump_queue(self.packet_queue()) - print("from here:") - traceback.print_stack() - def start_pump_thread(self): if self._thread: raise Exception("pump thread is already running") @@ -92,12 +104,6 @@ class SocketPacketPump(object): if self._thread: self._thread.join() - def output_queue(self): - return self._output_queue - - def packet_queue(self): - return self._packet_queue - def _process_new_bytes(self, new_bytes): if not new_bytes: return @@ -114,7 +120,7 @@ class SocketPacketPump(object): has_more = False # handle '+' ack elif self._receive_buffer[0] == "+": - self._packet_queue.put("+") + self._pump_queues.packet_queue().put("+") self._receive_buffer = self._receive_buffer[1:] if self._logger: self._logger.debug( @@ -132,10 +138,10 @@ class SocketPacketPump(object): if new_output_content: # This was an $O packet with new content. self._accumulated_output += new_output_content - self._output_queue.put(self._accumulated_output) + self._pump_queues.output_queue().put(self._accumulated_output) else: # Any packet other than $O. - self._packet_queue.put(packet_match.group(0)) + self._pump_queues.packet_queue().put(packet_match.group(0)) # Remove the parsed packet from the receive # buffer. @@ -173,7 +179,7 @@ class SocketPacketPump(object): # Likely a closed socket. Done with the pump thread. if self._logger: self._logger.debug( - "socket read failed, stopping pump read thread") + "socket read failed, stopping pump read thread\n" + traceback.format_exc(3)) break self._process_new_bytes(new_bytes) diff --git a/packages/Python/lldbsuite/test/types/TestFloatTypes.py b/packages/Python/lldbsuite/test/types/TestFloatTypes.py index 01fd4a267804..9fb555943b81 100644 --- a/packages/Python/lldbsuite/test/types/TestFloatTypes.py +++ b/packages/Python/lldbsuite/test/types/TestFloatTypes.py @@ -7,9 +7,12 @@ from __future__ import print_function import AbstractBase -import lldb import sys + +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class FloatTypesTestCase(AbstractBase.GenericTester): diff --git a/packages/Python/lldbsuite/test/types/TestFloatTypesExpr.py b/packages/Python/lldbsuite/test/types/TestFloatTypesExpr.py index a825a92c66cc..188033fffa33 100644 --- a/packages/Python/lldbsuite/test/types/TestFloatTypesExpr.py +++ b/packages/Python/lldbsuite/test/types/TestFloatTypesExpr.py @@ -5,11 +5,13 @@ Test that variable expressions of floating point types are evaluated correctly. from __future__ import print_function - import AbstractBase -import lldb import sys + +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class FloatTypesExprTestCase(AbstractBase.GenericTester): diff --git a/packages/Python/lldbsuite/test/types/TestIntegerTypes.py b/packages/Python/lldbsuite/test/types/TestIntegerTypes.py index 4b979df51db3..c1eab7183070 100644 --- a/packages/Python/lldbsuite/test/types/TestIntegerTypes.py +++ b/packages/Python/lldbsuite/test/types/TestIntegerTypes.py @@ -4,12 +4,13 @@ Test that variables of integer basic types are displayed correctly. from __future__ import print_function - - import AbstractBase -import lldb import sys + +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class IntegerTypesTestCase(AbstractBase.GenericTester): diff --git a/packages/Python/lldbsuite/test/types/TestIntegerTypesExpr.py b/packages/Python/lldbsuite/test/types/TestIntegerTypesExpr.py index c6dda91ad13e..2c3edea7adac 100644 --- a/packages/Python/lldbsuite/test/types/TestIntegerTypesExpr.py +++ b/packages/Python/lldbsuite/test/types/TestIntegerTypesExpr.py @@ -5,11 +5,13 @@ Test that variable expressions of integer basic types are evaluated correctly. from __future__ import print_function - import AbstractBase -import lldb import sys + +import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil class IntegerTypesExprTestCase(AbstractBase.GenericTester): diff --git a/packages/Python/lldbsuite/test/warnings/uuid/TestAddDsymCommand.py b/packages/Python/lldbsuite/test/warnings/uuid/TestAddDsymCommand.py index 002a7aef0c76..5010309e8944 100644 --- a/packages/Python/lldbsuite/test/warnings/uuid/TestAddDsymCommand.py +++ b/packages/Python/lldbsuite/test/warnings/uuid/TestAddDsymCommand.py @@ -6,7 +6,9 @@ from __future__ import print_function import os, time import lldb +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil @skipUnlessDarwin class AddDsymCommandCase(TestBase): diff --git a/packages/Python/lldbsuite/test/xunit_formatter.py b/packages/Python/lldbsuite/test/xunit_formatter.py deleted file mode 100644 index 35fdba449a0c..000000000000 --- a/packages/Python/lldbsuite/test/xunit_formatter.py +++ /dev/null @@ -1,565 +0,0 @@ -""" - The LLVM Compiler Infrastructure - -This file is distributed under the University of Illinois Open Source -License. See LICENSE.TXT for details. - -Provides an xUnit ResultsFormatter for integrating the LLDB -test suite with the Jenkins xUnit aggregator and other xUnit-compliant -test output processors. -""" -from __future__ import print_function -from __future__ import absolute_import - -# System modules -import re -import sys -import xml.sax.saxutils - -# Third-party modules -import six - -# Local modules -from .result_formatter import EventBuilder -from .result_formatter import ResultsFormatter - - -class XunitFormatter(ResultsFormatter): - """Provides xUnit-style formatted output. - """ - - # Result mapping arguments - RM_IGNORE = 'ignore' - RM_SUCCESS = 'success' - RM_FAILURE = 'failure' - RM_PASSTHRU = 'passthru' - - @staticmethod - def _build_illegal_xml_regex(): - """Contructs a regex to match all illegal xml characters. - - Expects to be used against a unicode string.""" - # Construct the range pairs of invalid unicode chareacters. - illegal_chars_u = [ - (0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F), (0x7F, 0x84), - (0x86, 0x9F), (0xFDD0, 0xFDDF), (0xFFFE, 0xFFFF)] - - # For wide builds, we have more. - if sys.maxunicode >= 0x10000: - illegal_chars_u.extend( - [(0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF), (0x3FFFE, 0x3FFFF), - (0x4FFFE, 0x4FFFF), (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF), - (0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF), (0x9FFFE, 0x9FFFF), - (0xAFFFE, 0xAFFFF), (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF), - (0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF), (0xFFFFE, 0xFFFFF), - (0x10FFFE, 0x10FFFF)]) - - # Build up an array of range expressions. - illegal_ranges = [ - "%s-%s" % (six.unichr(low), six.unichr(high)) - for (low, high) in illegal_chars_u] - - # Compile the regex - return re.compile(six.u('[%s]') % six.u('').join(illegal_ranges)) - - @staticmethod - def _quote_attribute(text): - """Returns the given text in a manner safe for usage in an XML attribute. - - @param text the text that should appear within an XML attribute. - @return the attribute-escaped version of the input text. - """ - return xml.sax.saxutils.quoteattr(text) - - def _replace_invalid_xml(self, str_or_unicode): - """Replaces invalid XML characters with a '?'. - - @param str_or_unicode a string to replace invalid XML - characters within. Can be unicode or not. If not unicode, - assumes it is a byte string in utf-8 encoding. - - @returns a utf-8-encoded byte string with invalid - XML replaced with '?'. - """ - # Get the content into unicode - if isinstance(str_or_unicode, str): - unicode_content = str_or_unicode.decode('utf-8') - else: - unicode_content = str_or_unicode - return self.invalid_xml_re.sub( - six.u('?'), unicode_content).encode('utf-8') - - @classmethod - def arg_parser(cls): - """@return arg parser used to parse formatter-specific options.""" - parser = super(XunitFormatter, cls).arg_parser() - - # These are valid choices for results mapping. - results_mapping_choices = [ - XunitFormatter.RM_IGNORE, - XunitFormatter.RM_SUCCESS, - XunitFormatter.RM_FAILURE, - XunitFormatter.RM_PASSTHRU] - parser.add_argument( - "--assert-on-unknown-events", - action="store_true", - help=('cause unknown test events to generate ' - 'a python assert. Default is to ignore.')) - parser.add_argument( - "--ignore-skip-name", - "-n", - metavar='PATTERN', - action="append", - dest='ignore_skip_name_patterns', - help=('a python regex pattern, where ' - 'any skipped test with a test method name where regex ' - 'matches (via search) will be ignored for xUnit test ' - 'result purposes. Can be specified multiple times.')) - parser.add_argument( - "--ignore-skip-reason", - "-r", - metavar='PATTERN', - action="append", - dest='ignore_skip_reason_patterns', - help=('a python regex pattern, where ' - 'any skipped test with a skip reason where the regex ' - 'matches (via search) will be ignored for xUnit test ' - 'result purposes. Can be specified multiple times.')) - parser.add_argument( - "--xpass", action="store", choices=results_mapping_choices, - default=XunitFormatter.RM_FAILURE, - help=('specify mapping from unexpected success to jUnit/xUnit ' - 'result type')) - parser.add_argument( - "--xfail", action="store", choices=results_mapping_choices, - default=XunitFormatter.RM_IGNORE, - help=('specify mapping from expected failure to jUnit/xUnit ' - 'result type')) - return parser - - @staticmethod - def _build_regex_list_from_patterns(patterns): - """Builds a list of compiled regexes from option value. - - @param option string containing a comma-separated list of regex - patterns. Zero-length or None will produce an empty regex list. - - @return list of compiled regular expressions, empty if no - patterns provided. - """ - regex_list = [] - if patterns is not None: - for pattern in patterns: - regex_list.append(re.compile(pattern)) - return regex_list - - def __init__(self, out_file, options): - """Initializes the XunitFormatter instance. - @param out_file file-like object where formatted output is written. - @param options_dict specifies a dictionary of options for the - formatter. - """ - # Initialize the parent - super(XunitFormatter, self).__init__(out_file, options) - self.text_encoding = "UTF-8" - self.invalid_xml_re = XunitFormatter._build_illegal_xml_regex() - self.total_test_count = 0 - self.ignore_skip_name_regexes = ( - XunitFormatter._build_regex_list_from_patterns( - options.ignore_skip_name_patterns)) - self.ignore_skip_reason_regexes = ( - XunitFormatter._build_regex_list_from_patterns( - options.ignore_skip_reason_patterns)) - - self.elements = { - "successes": [], - "errors": [], - "failures": [], - "skips": [], - "unexpected_successes": [], - "expected_failures": [], - "all": [] - } - - self.status_handlers = { - EventBuilder.STATUS_SUCCESS: self._handle_success, - EventBuilder.STATUS_FAILURE: self._handle_failure, - EventBuilder.STATUS_ERROR: self._handle_error, - EventBuilder.STATUS_SKIP: self._handle_skip, - EventBuilder.STATUS_EXPECTED_FAILURE: - self._handle_expected_failure, - EventBuilder.STATUS_EXPECTED_TIMEOUT: - self._handle_expected_timeout, - EventBuilder.STATUS_UNEXPECTED_SUCCESS: - self._handle_unexpected_success, - EventBuilder.STATUS_EXCEPTIONAL_EXIT: - self._handle_exceptional_exit, - EventBuilder.STATUS_TIMEOUT: - self._handle_timeout - } - - RESULT_TYPES = set( - [EventBuilder.TYPE_TEST_RESULT, - EventBuilder.TYPE_JOB_RESULT]) - - def handle_event(self, test_event): - super(XunitFormatter, self).handle_event(test_event) - - event_type = test_event["event"] - if event_type is None: - return - - if event_type == "terminate": - # Process all the final result events into their - # XML counterparts. - for result_event in self.result_events.values(): - self._process_test_result(result_event) - self._finish_output() - else: - # This is an unknown event. - if self.options.assert_on_unknown_events: - raise Exception("unknown event type {} from {}\n".format( - event_type, test_event)) - - def _handle_success(self, test_event): - """Handles a test success. - @param test_event the test event to handle. - """ - result = self._common_add_testcase_entry(test_event) - with self.lock: - self.elements["successes"].append(result) - - def _handle_failure(self, test_event): - """Handles a test failure. - @param test_event the test event to handle. - """ - message = self._replace_invalid_xml(test_event["issue_message"]) - backtrace = self._replace_invalid_xml( - "".join(test_event.get("issue_backtrace", []))) - - result = self._common_add_testcase_entry( - test_event, - inner_content=( - ''.format( - XunitFormatter._quote_attribute(test_event["issue_class"]), - XunitFormatter._quote_attribute(message), - backtrace) - )) - with self.lock: - self.elements["failures"].append(result) - - def _handle_error(self, test_event): - """Handles a test error. - @param test_event the test event to handle. - """ - message = self._replace_invalid_xml(test_event["issue_message"]) - backtrace = self._replace_invalid_xml( - "".join(test_event.get("issue_backtrace", []))) - - result = self._common_add_testcase_entry( - test_event, - inner_content=( - ''.format( - XunitFormatter._quote_attribute(test_event["issue_class"]), - XunitFormatter._quote_attribute(message), - backtrace) - )) - with self.lock: - self.elements["errors"].append(result) - - def _handle_exceptional_exit(self, test_event): - """Handles an exceptional exit. - @param test_event the test method or job result event to handle. - """ - if "test_name" in test_event: - name = test_event["test_name"] - else: - name = test_event.get("test_filename", "") - - message_text = "ERROR: {} ({}): {}".format( - test_event.get("exception_code", 0), - test_event.get("exception_description", ""), - name) - message = self._replace_invalid_xml(message_text) - - result = self._common_add_testcase_entry( - test_event, - inner_content=( - ''.format( - "exceptional_exit", - XunitFormatter._quote_attribute(message)) - )) - with self.lock: - self.elements["errors"].append(result) - - def _handle_timeout(self, test_event): - """Handles a test method or job timeout. - @param test_event the test method or job result event to handle. - """ - if "test_name" in test_event: - name = test_event["test_name"] - else: - name = test_event.get("test_filename", "") - - message_text = "TIMEOUT: {}".format(name) - message = self._replace_invalid_xml(message_text) - - result = self._common_add_testcase_entry( - test_event, - inner_content=( - ''.format( - "timeout", - XunitFormatter._quote_attribute(message)) - )) - with self.lock: - self.elements["errors"].append(result) - - @staticmethod - def _ignore_based_on_regex_list(test_event, test_key, regex_list): - """Returns whether to ignore a test event based on patterns. - - @param test_event the test event dictionary to check. - @param test_key the key within the dictionary to check. - @param regex_list a list of zero or more regexes. May contain - zero or more compiled regexes. - - @return True if any o the regex list match based on the - re.search() method; false otherwise. - """ - for regex in regex_list: - match = regex.search(test_event.get(test_key, '')) - if match: - return True - return False - - def _handle_skip(self, test_event): - """Handles a skipped test. - @param test_event the test event to handle. - """ - - # Are we ignoring this test based on test name? - if XunitFormatter._ignore_based_on_regex_list( - test_event, 'test_name', self.ignore_skip_name_regexes): - return - - # Are we ignoring this test based on skip reason? - if XunitFormatter._ignore_based_on_regex_list( - test_event, 'skip_reason', self.ignore_skip_reason_regexes): - return - - # We're not ignoring this test. Process the skip. - reason = self._replace_invalid_xml(test_event.get("skip_reason", "")) - result = self._common_add_testcase_entry( - test_event, - inner_content=''.format( - XunitFormatter._quote_attribute(reason))) - with self.lock: - self.elements["skips"].append(result) - - def _handle_expected_failure(self, test_event): - """Handles a test that failed as expected. - @param test_event the test event to handle. - """ - if self.options.xfail == XunitFormatter.RM_PASSTHRU: - # This is not a natively-supported junit/xunit - # testcase mode, so it might fail a validating - # test results viewer. - if "bugnumber" in test_event: - bug_id_attribute = 'bug-id={} '.format( - XunitFormatter._quote_attribute(test_event["bugnumber"])) - else: - bug_id_attribute = '' - - result = self._common_add_testcase_entry( - test_event, - inner_content=( - ''.format( - bug_id_attribute, - XunitFormatter._quote_attribute( - test_event["issue_class"]), - XunitFormatter._quote_attribute( - test_event["issue_message"])) - )) - with self.lock: - self.elements["expected_failures"].append(result) - elif self.options.xfail == XunitFormatter.RM_SUCCESS: - result = self._common_add_testcase_entry(test_event) - with self.lock: - self.elements["successes"].append(result) - elif self.options.xfail == XunitFormatter.RM_FAILURE: - result = self._common_add_testcase_entry( - test_event, - inner_content=''.format( - XunitFormatter._quote_attribute(test_event["issue_class"]), - XunitFormatter._quote_attribute( - test_event["issue_message"]))) - with self.lock: - self.elements["failures"].append(result) - elif self.options.xfail == XunitFormatter.RM_IGNORE: - pass - else: - raise Exception( - "unknown xfail option: {}".format(self.options.xfail)) - - def _handle_expected_timeout(self, test_event): - """Handles expected_timeout. - @param test_event the test event to handle. - """ - # We don't do anything with expected timeouts, not even report. - pass - - def _handle_unexpected_success(self, test_event): - """Handles a test that passed but was expected to fail. - @param test_event the test event to handle. - """ - if self.options.xpass == XunitFormatter.RM_PASSTHRU: - # This is not a natively-supported junit/xunit - # testcase mode, so it might fail a validating - # test results viewer. - result = self._common_add_testcase_entry( - test_event, - inner_content=("")) - with self.lock: - self.elements["unexpected_successes"].append(result) - elif self.options.xpass == XunitFormatter.RM_SUCCESS: - # Treat the xpass as a success. - result = self._common_add_testcase_entry(test_event) - with self.lock: - self.elements["successes"].append(result) - elif self.options.xpass == XunitFormatter.RM_FAILURE: - # Treat the xpass as a failure. - if "bugnumber" in test_event: - message = "unexpected success (bug_id:{})".format( - test_event["bugnumber"]) - else: - message = "unexpected success (bug_id:none)" - result = self._common_add_testcase_entry( - test_event, - inner_content=''.format( - XunitFormatter._quote_attribute("unexpected_success"), - XunitFormatter._quote_attribute(message))) - with self.lock: - self.elements["failures"].append(result) - elif self.options.xpass == XunitFormatter.RM_IGNORE: - # Ignore the xpass result as far as xUnit reporting goes. - pass - else: - raise Exception("unknown xpass option: {}".format( - self.options.xpass)) - - def _process_test_result(self, test_event): - """Processes the test_event known to be a test result. - - This categorizes the event appropriately and stores the data needed - to generate the final xUnit report. This method skips events that - cannot be represented in xUnit output. - """ - if "status" not in test_event: - raise Exception("test event dictionary missing 'status' key") - - status = test_event["status"] - if status not in self.status_handlers: - raise Exception("test event status '{}' unsupported".format( - status)) - - # Call the status handler for the test result. - self.status_handlers[status](test_event) - - def _common_add_testcase_entry(self, test_event, inner_content=None): - """Registers a testcase result, and returns the text created. - - The caller is expected to manage failure/skip/success counts - in some kind of appropriate way. This call simply constructs - the XML and appends the returned result to the self.all_results - list. - - @param test_event the test event dictionary. - - @param inner_content if specified, gets included in the - inner section, at the point before stdout and stderr would be - included. This is where a , , , etc. - could go. - - @return the text of the xml testcase element. - """ - - # Get elapsed time. - test_class = test_event["test_class"] - test_name = test_event["test_name"] - event_time = test_event["event_time"] - time_taken = self.elapsed_time_for_test( - test_class, test_name, event_time) - - # Plumb in stdout/stderr once we shift over to only test results. - test_stdout = '' - test_stderr = '' - - # Formulate the output xml. - if not inner_content: - inner_content = "" - result = ( - '' - '{}{}{}'.format( - test_class, - test_name, - time_taken, - inner_content, - test_stdout, - test_stderr)) - - # Save the result, update total test count. - with self.lock: - self.total_test_count += 1 - self.elements["all"].append(result) - - return result - - def _finish_output_no_lock(self): - """Flushes out the report of test executions to form valid xml output. - - xUnit output is in XML. The reporting system cannot complete the - formatting of the output without knowing when there is no more input. - This call addresses notifcation of the completed test run and thus is - when we can finish off the report output. - """ - - # Figure out the counts line for the testsuite. If we have - # been counting either unexpected successes or expected - # failures, we'll output those in the counts, at the risk of - # being invalidated by a validating test results viewer. - # These aren't counted by default so they won't show up unless - # the user specified a formatter option to include them. - xfail_count = len(self.elements["expected_failures"]) - xpass_count = len(self.elements["unexpected_successes"]) - if xfail_count > 0 or xpass_count > 0: - extra_testsuite_attributes = ( - ' expected-failures="{}"' - ' unexpected-successes="{}"'.format(xfail_count, xpass_count)) - else: - extra_testsuite_attributes = "" - - # Output the header. - self.out_file.write( - '\n' - '' - '\n'.format( - self.text_encoding, - "LLDB test suite", - self.total_test_count, - len(self.elements["errors"]), - len(self.elements["failures"]), - len(self.elements["skips"]), - extra_testsuite_attributes)) - - # Output each of the test result entries. - for result in self.elements["all"]: - self.out_file.write(result + '\n') - - # Close off the test suite. - self.out_file.write('\n') - - def _finish_output(self): - """Finish writing output as all incoming events have arrived.""" - with self.lock: - self._finish_output_no_lock() diff --git a/packages/Python/lldbsuite/test_event/__init__.py b/packages/Python/lldbsuite/test_event/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/Python/lldbsuite/test_event/build_exception.py b/packages/Python/lldbsuite/test_event/build_exception.py new file mode 100644 index 000000000000..4a7c5f4a9d38 --- /dev/null +++ b/packages/Python/lldbsuite/test_event/build_exception.py @@ -0,0 +1,14 @@ +class BuildError(Exception): + def __init__(self, called_process_error): + super(BuildError, self).__init__("Error when building test subject") + self.command = called_process_error.lldb_extensions.get("command", "") + self.build_error = called_process_error.lldb_extensions.get("stderr_content", "") + + def __str__(self): + return self.format_build_error(self.command, self.build_error) + + @staticmethod + def format_build_error(command, command_output): + return "Error when building test subject.\n\nBuild Command:\n{}\n\nBuild Command Output:\n{}".format( + command, + command_output) diff --git a/packages/Python/lldbsuite/test_event/dotest_channels.py b/packages/Python/lldbsuite/test_event/dotest_channels.py new file mode 100644 index 000000000000..d69720e4f66a --- /dev/null +++ b/packages/Python/lldbsuite/test_event/dotest_channels.py @@ -0,0 +1,207 @@ +""" + The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. + +Sync lldb and related source from a local machine to a remote machine. + +This facilitates working on the lldb sourcecode on multiple machines +and multiple OS types, verifying changes across all. + + +This module provides asyncore channels used within the LLDB test +framework. +""" + +from __future__ import print_function +from __future__ import absolute_import + + +# System modules +import asyncore +import socket + +# Third-party modules +from six.moves import cPickle + +# LLDB modules + + +class UnpicklingForwardingReaderChannel(asyncore.dispatcher): + """Provides an unpickling, forwarding asyncore dispatch channel reader. + + Inferior dotest.py processes with side-channel-based test results will + send test result event data in a pickled format, one event at a time. + This class supports reconstructing the pickled data and forwarding it + on to its final destination. + + The channel data is written in the form: + {num_payload_bytes}#{payload_bytes} + + The bulk of this class is devoted to reading and parsing out + the payload bytes. + """ + def __init__(self, file_object, async_map, forwarding_func): + asyncore.dispatcher.__init__(self, sock=file_object, map=async_map) + + self.header_contents = b"" + self.packet_bytes_remaining = 0 + self.reading_header = True + self.ibuffer = b'' + self.forwarding_func = forwarding_func + if forwarding_func is None: + # This whole class is useless if we do nothing with the + # unpickled results. + raise Exception("forwarding function must be set") + + # Initiate all connections by sending an ack. This allows + # the initiators of the socket to await this to ensure + # that this end is up and running (and therefore already + # into the async map). + ack_bytes = b'*' + file_object.send(ack_bytes) + + def deserialize_payload(self): + """Unpickles the collected input buffer bytes and forwards.""" + if len(self.ibuffer) > 0: + self.forwarding_func(cPickle.loads(self.ibuffer)) + self.ibuffer = b'' + + def consume_header_bytes(self, data): + """Consumes header bytes from the front of data. + @param data the incoming data stream bytes + @return any data leftover after consuming header bytes. + """ + # We're done if there is no content. + if not data or (len(data) == 0): + return None + + full_header_len = 4 + + assert len(self.header_contents) < full_header_len + + bytes_avail = len(data) + bytes_needed = full_header_len - len(self.header_contents) + header_bytes_avail = min(bytes_needed, bytes_avail) + self.header_contents += data[:header_bytes_avail] + if len(self.header_contents) == full_header_len: + import struct + # End of header. + self.packet_bytes_remaining = struct.unpack( + "!I", self.header_contents)[0] + self.header_contents = b"" + self.reading_header = False + return data[header_bytes_avail:] + + # If we made it here, we've exhausted the data and + # we're still parsing header content. + return None + + def consume_payload_bytes(self, data): + """Consumes payload bytes from the front of data. + @param data the incoming data stream bytes + @return any data leftover after consuming remaining payload bytes. + """ + if not data or (len(data) == 0): + # We're done and there's nothing to do. + return None + + data_len = len(data) + if data_len <= self.packet_bytes_remaining: + # We're consuming all the data provided. + self.ibuffer += data + self.packet_bytes_remaining -= data_len + + # If we're no longer waiting for payload bytes, + # we flip back to parsing header bytes and we + # unpickle the payload contents. + if self.packet_bytes_remaining < 1: + self.reading_header = True + self.deserialize_payload() + + # We're done, no more data left. + return None + else: + # We're only consuming a portion of the data since + # the data contains more than the payload amount. + self.ibuffer += data[:self.packet_bytes_remaining] + data = data[self.packet_bytes_remaining:] + + # We now move on to reading the header. + self.reading_header = True + self.packet_bytes_remaining = 0 + + # And we can deserialize the payload. + self.deserialize_payload() + + # Return the remaining data. + return data + + def handle_read(self): + # Read some data from the socket. + try: + data = self.recv(8192) + # print('driver socket READ: %d bytes' % len(data)) + except socket.error as socket_error: + print( + "\nINFO: received socket error when reading data " + "from test inferior:\n{}".format(socket_error)) + raise + except Exception as general_exception: + print( + "\nERROR: received non-socket error when reading data " + "from the test inferior:\n{}".format(general_exception)) + raise + + # Consume the message content. + while data and (len(data) > 0): + # If we're reading the header, gather header bytes. + if self.reading_header: + data = self.consume_header_bytes(data) + else: + data = self.consume_payload_bytes(data) + + def handle_close(self): + # print("socket reader: closing port") + self.close() + + +class UnpicklingForwardingListenerChannel(asyncore.dispatcher): + """Provides a socket listener asyncore channel for unpickling/forwarding. + + This channel will listen on a socket port (use 0 for host-selected). Any + client that connects will have an UnpicklingForwardingReaderChannel handle + communication over the connection. + + The dotest parallel test runners, when collecting test results, open the + test results side channel over a socket. This channel handles connections + from inferiors back to the test runner. Each worker fires up a listener + for each inferior invocation. This simplifies the asyncore.loop() usage, + one of the reasons for implementing with asyncore. This listener shuts + down once a single connection is made to it. + """ + def __init__(self, async_map, host, port, backlog_count, forwarding_func): + asyncore.dispatcher.__init__(self, map=async_map) + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.set_reuse_addr() + self.bind((host, port)) + self.address = self.socket.getsockname() + self.listen(backlog_count) + self.handler = None + self.async_map = async_map + self.forwarding_func = forwarding_func + if forwarding_func is None: + # This whole class is useless if we do nothing with the + # unpickled results. + raise Exception("forwarding function must be set") + + def handle_accept(self): + (sock, addr) = self.socket.accept() + if sock and addr: + # print('Incoming connection from %s' % repr(addr)) + self.handler = UnpicklingForwardingReaderChannel( + sock, self.async_map, self.forwarding_func) + + def handle_close(self): + self.close() diff --git a/packages/Python/lldbsuite/test_event/event_builder.py b/packages/Python/lldbsuite/test_event/event_builder.py new file mode 100644 index 000000000000..aabbd986bd70 --- /dev/null +++ b/packages/Python/lldbsuite/test_event/event_builder.py @@ -0,0 +1,475 @@ +""" + The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. + +Provides a class to build Python test event data structures. +""" + +from __future__ import print_function +from __future__ import absolute_import + +# System modules +import inspect +import time +import traceback + +# Third-party modules + +# LLDB modules +from . import build_exception + +class EventBuilder(object): + """Helper class to build test result event dictionaries.""" + + BASE_DICTIONARY = None + + # Test Event Types + TYPE_JOB_RESULT = "job_result" + TYPE_TEST_RESULT = "test_result" + TYPE_TEST_START = "test_start" + TYPE_MARK_TEST_RERUN_ELIGIBLE = "test_eligible_for_rerun" + TYPE_MARK_TEST_EXPECTED_FAILURE = "test_expected_failure" + TYPE_SESSION_TERMINATE = "terminate" + + RESULT_TYPES = {TYPE_JOB_RESULT, TYPE_TEST_RESULT} + + # Test/Job Status Tags + STATUS_EXCEPTIONAL_EXIT = "exceptional_exit" + STATUS_SUCCESS = "success" + STATUS_FAILURE = "failure" + STATUS_EXPECTED_FAILURE = "expected_failure" + STATUS_EXPECTED_TIMEOUT = "expected_timeout" + STATUS_UNEXPECTED_SUCCESS = "unexpected_success" + STATUS_SKIP = "skip" + STATUS_ERROR = "error" + STATUS_TIMEOUT = "timeout" + + """Test methods or jobs with a status matching any of these + status values will cause a testrun failure, unless + the test methods rerun and do not trigger an issue when rerun.""" + TESTRUN_ERROR_STATUS_VALUES = { + STATUS_ERROR, + STATUS_EXCEPTIONAL_EXIT, + STATUS_FAILURE, + STATUS_TIMEOUT} + + @staticmethod + def _get_test_name_info(test): + """Returns (test-class-name, test-method-name) from a test case instance. + + @param test a unittest.TestCase instance. + + @return tuple containing (test class name, test method name) + """ + test_class_components = test.id().split(".") + test_class_name = ".".join(test_class_components[:-1]) + test_name = test_class_components[-1] + return test_class_name, test_name + + @staticmethod + def bare_event(event_type): + """Creates an event with default additions, event type and timestamp. + + @param event_type the value set for the "event" key, used + to distinguish events. + + @returns an event dictionary with all default additions, the "event" + key set to the passed in event_type, and the event_time value set to + time.time(). + """ + if EventBuilder.BASE_DICTIONARY is not None: + # Start with a copy of the "always include" entries. + event = dict(EventBuilder.BASE_DICTIONARY) + else: + event = {} + + event.update({ + "event": event_type, + "event_time": time.time() + }) + return event + + @staticmethod + def _assert_is_python_sourcefile(test_filename): + if test_filename is not None: + if not test_filename.endswith(".py"): + raise Exception("source python filename has unexpected extension: {}".format(test_filename)) + return test_filename + + @staticmethod + def _event_dictionary_common(test, event_type): + """Returns an event dictionary setup with values for the given event type. + + @param test the unittest.TestCase instance + + @param event_type the name of the event type (string). + + @return event dictionary with common event fields set. + """ + test_class_name, test_name = EventBuilder._get_test_name_info(test) + + # Determine the filename for the test case. If there is an attribute + # for it, use it. Otherwise, determine from the TestCase class path. + if hasattr(test, "test_filename"): + test_filename = EventBuilder._assert_is_python_sourcefile(test.test_filename) + else: + test_filename = EventBuilder._assert_is_python_sourcefile(inspect.getsourcefile(test.__class__)) + + event = EventBuilder.bare_event(event_type) + event.update({ + "test_class": test_class_name, + "test_name": test_name, + "test_filename": test_filename + }) + + return event + + @staticmethod + def _error_tuple_class(error_tuple): + """Returns the unittest error tuple's error class as a string. + + @param error_tuple the error tuple provided by the test framework. + + @return the error type (typically an exception) raised by the + test framework. + """ + type_var = error_tuple[0] + module = inspect.getmodule(type_var) + if module: + return "{}.{}".format(module.__name__, type_var.__name__) + else: + return type_var.__name__ + + @staticmethod + def _error_tuple_message(error_tuple): + """Returns the unittest error tuple's error message. + + @param error_tuple the error tuple provided by the test framework. + + @return the error message provided by the test framework. + """ + return str(error_tuple[1]) + + @staticmethod + def _error_tuple_traceback(error_tuple): + """Returns the unittest error tuple's error message. + + @param error_tuple the error tuple provided by the test framework. + + @return the error message provided by the test framework. + """ + return error_tuple[2] + + @staticmethod + def _event_dictionary_test_result(test, status): + """Returns an event dictionary with common test result fields set. + + @param test a unittest.TestCase instance. + + @param status the status/result of the test + (e.g. "success", "failure", etc.) + + @return the event dictionary + """ + event = EventBuilder._event_dictionary_common( + test, EventBuilder.TYPE_TEST_RESULT) + event["status"] = status + return event + + @staticmethod + def _event_dictionary_issue(test, status, error_tuple): + """Returns an event dictionary with common issue-containing test result + fields set. + + @param test a unittest.TestCase instance. + + @param status the status/result of the test + (e.g. "success", "failure", etc.) + + @param error_tuple the error tuple as reported by the test runner. + This is of the form (type, error). + + @return the event dictionary + """ + event = EventBuilder._event_dictionary_test_result(test, status) + event["issue_class"] = EventBuilder._error_tuple_class(error_tuple) + event["issue_message"] = EventBuilder._error_tuple_message(error_tuple) + backtrace = EventBuilder._error_tuple_traceback(error_tuple) + if backtrace is not None: + event["issue_backtrace"] = traceback.format_tb(backtrace) + return event + + @staticmethod + def event_for_start(test): + """Returns an event dictionary for the test start event. + + @param test a unittest.TestCase instance. + + @return the event dictionary + """ + return EventBuilder._event_dictionary_common( + test, EventBuilder.TYPE_TEST_START) + + @staticmethod + def event_for_success(test): + """Returns an event dictionary for a successful test. + + @param test a unittest.TestCase instance. + + @return the event dictionary + """ + return EventBuilder._event_dictionary_test_result( + test, EventBuilder.STATUS_SUCCESS) + + @staticmethod + def event_for_unexpected_success(test, bugnumber): + """Returns an event dictionary for a test that succeeded but was + expected to fail. + + @param test a unittest.TestCase instance. + + @param bugnumber the issue identifier for the bug tracking the + fix request for the test expected to fail (but is in fact + passing here). + + @return the event dictionary + + """ + event = EventBuilder._event_dictionary_test_result( + test, EventBuilder.STATUS_UNEXPECTED_SUCCESS) + if bugnumber: + event["bugnumber"] = str(bugnumber) + return event + + @staticmethod + def event_for_failure(test, error_tuple): + """Returns an event dictionary for a test that failed. + + @param test a unittest.TestCase instance. + + @param error_tuple the error tuple as reported by the test runner. + This is of the form (type, error). + + @return the event dictionary + """ + return EventBuilder._event_dictionary_issue( + test, EventBuilder.STATUS_FAILURE, error_tuple) + + @staticmethod + def event_for_expected_failure(test, error_tuple, bugnumber): + """Returns an event dictionary for a test that failed as expected. + + @param test a unittest.TestCase instance. + + @param error_tuple the error tuple as reported by the test runner. + This is of the form (type, error). + + @param bugnumber the issue identifier for the bug tracking the + fix request for the test expected to fail. + + @return the event dictionary + + """ + event = EventBuilder._event_dictionary_issue( + test, EventBuilder.STATUS_EXPECTED_FAILURE, error_tuple) + if bugnumber: + event["bugnumber"] = str(bugnumber) + return event + + @staticmethod + def event_for_skip(test, reason): + """Returns an event dictionary for a test that was skipped. + + @param test a unittest.TestCase instance. + + @param reason the reason why the test is being skipped. + + @return the event dictionary + """ + event = EventBuilder._event_dictionary_test_result( + test, EventBuilder.STATUS_SKIP) + event["skip_reason"] = reason + return event + + @staticmethod + def event_for_error(test, error_tuple): + """Returns an event dictionary for a test that hit a test execution error. + + @param test a unittest.TestCase instance. + + @param error_tuple the error tuple as reported by the test runner. + This is of the form (type, error). + + @return the event dictionary + """ + event = EventBuilder._event_dictionary_issue( + test, EventBuilder.STATUS_ERROR, error_tuple) + event["issue_phase"] = "test" + return event + + @staticmethod + def event_for_build_error(test, error_tuple): + """Returns an event dictionary for a test that hit a test execution error + during the test cleanup phase. + + @param test a unittest.TestCase instance. + + @param error_tuple the error tuple as reported by the test runner. + This is of the form (type, error). + + @return the event dictionary + """ + event = EventBuilder._event_dictionary_issue( + test, EventBuilder.STATUS_ERROR, error_tuple) + event["issue_phase"] = "build" + + build_error = error_tuple[1] + event["build_command"] = build_error.command + event["build_error"] = build_error.build_error + return event + + @staticmethod + def event_for_cleanup_error(test, error_tuple): + """Returns an event dictionary for a test that hit a test execution error + during the test cleanup phase. + + @param test a unittest.TestCase instance. + + @param error_tuple the error tuple as reported by the test runner. + This is of the form (type, error). + + @return the event dictionary + """ + event = EventBuilder._event_dictionary_issue( + test, EventBuilder.STATUS_ERROR, error_tuple) + event["issue_phase"] = "cleanup" + return event + + @staticmethod + def event_for_job_test_add_error(test_filename, exception, backtrace): + event = EventBuilder.bare_event(EventBuilder.TYPE_JOB_RESULT) + event["status"] = EventBuilder.STATUS_ERROR + if test_filename is not None: + event["test_filename"] = EventBuilder._assert_is_python_sourcefile(test_filename) + if exception is not None and "__class__" in dir(exception): + event["issue_class"] = exception.__class__ + event["issue_message"] = exception + if backtrace is not None: + event["issue_backtrace"] = backtrace + return event + + @staticmethod + def event_for_job_exceptional_exit( + pid, worker_index, exception_code, exception_description, + test_filename, command_line): + """Creates an event for a job (i.e. process) exit due to signal. + + @param pid the process id for the job that failed + @param worker_index optional id for the job queue running the process + @param exception_code optional code + (e.g. SIGTERM integer signal number) + @param exception_description optional string containing symbolic + representation of the issue (e.g. "SIGTERM") + @param test_filename the path to the test filename that exited + in some exceptional way. + @param command_line the Popen()-style list provided as the command line + for the process that timed out. + + @return an event dictionary coding the job completion description. + """ + event = EventBuilder.bare_event(EventBuilder.TYPE_JOB_RESULT) + event["status"] = EventBuilder.STATUS_EXCEPTIONAL_EXIT + if pid is not None: + event["pid"] = pid + if worker_index is not None: + event["worker_index"] = int(worker_index) + if exception_code is not None: + event["exception_code"] = exception_code + if exception_description is not None: + event["exception_description"] = exception_description + if test_filename is not None: + event["test_filename"] = EventBuilder._assert_is_python_sourcefile(test_filename) + if command_line is not None: + event["command_line"] = command_line + return event + + @staticmethod + def event_for_job_timeout(pid, worker_index, test_filename, command_line): + """Creates an event for a job (i.e. process) timeout. + + @param pid the process id for the job that timed out + @param worker_index optional id for the job queue running the process + @param test_filename the path to the test filename that timed out. + @param command_line the Popen-style list provided as the command line + for the process that timed out. + + @return an event dictionary coding the job completion description. + """ + event = EventBuilder.bare_event(EventBuilder.TYPE_JOB_RESULT) + event["status"] = "timeout" + if pid is not None: + event["pid"] = pid + if worker_index is not None: + event["worker_index"] = int(worker_index) + if test_filename is not None: + event["test_filename"] = EventBuilder._assert_is_python_sourcefile(test_filename) + if command_line is not None: + event["command_line"] = command_line + return event + + @staticmethod + def event_for_mark_test_rerun_eligible(test): + """Creates an event that indicates the specified test is explicitly + eligible for rerun. + + Note there is a mode that will enable test rerun eligibility at the + global level. These markings for explicit rerun eligibility are + intended for the mode of running where only explicitly re-runnable + tests are rerun upon hitting an issue. + + @param test the TestCase instance to which this pertains. + + @return an event that specifies the given test as being eligible to + be rerun. + """ + event = EventBuilder._event_dictionary_common( + test, + EventBuilder.TYPE_MARK_TEST_RERUN_ELIGIBLE) + return event + + @staticmethod + def event_for_mark_test_expected_failure(test): + """Creates an event that indicates the specified test is expected + to fail. + + @param test the TestCase instance to which this pertains. + + @return an event that specifies the given test is expected to fail. + """ + event = EventBuilder._event_dictionary_common( + test, + EventBuilder.TYPE_MARK_TEST_EXPECTED_FAILURE) + return event + + @staticmethod + def add_entries_to_all_events(entries_dict): + """Specifies a dictionary of entries to add to all test events. + + This provides a mechanism for, say, a parallel test runner to + indicate to each inferior dotest.py that it should add a + worker index to each. + + Calling this method replaces all previous entries added + by a prior call to this. + + Event build methods will overwrite any entries that collide. + Thus, the passed in dictionary is the base, which gets merged + over by event building when keys collide. + + @param entries_dict a dictionary containing key and value + pairs that should be merged into all events created by the + event generator. May be None to clear out any extra entries. + """ + EventBuilder.BASE_DICTIONARY = dict(entries_dict) diff --git a/packages/Python/lldbsuite/test_event/formatter/__init__.py b/packages/Python/lldbsuite/test_event/formatter/__init__.py new file mode 100644 index 000000000000..556370ebb9de --- /dev/null +++ b/packages/Python/lldbsuite/test_event/formatter/__init__.py @@ -0,0 +1,162 @@ +""" + The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. +""" + +from __future__ import print_function +from __future__ import absolute_import + +# System modules +import importlib +import socket +import sys + +# Third-party modules + +# LLDB modules + + +# Ignore method count on DTOs. +# pylint: disable=too-few-public-methods +class FormatterConfig(object): + """Provides formatter configuration info to create_results_formatter().""" + + def __init__(self): + self.filename = None + self.port = None + self.formatter_name = None + self.formatter_options = None + + +# Ignore method count on DTOs. +# pylint: disable=too-few-public-methods +class CreatedFormatter(object): + """Provides transfer object for returns from create_results_formatter().""" + + def __init__(self, formatter, cleanup_func): + self.formatter = formatter + self.cleanup_func = cleanup_func + + +def create_results_formatter(config): + """Sets up a test results formatter. + + @param config an instance of FormatterConfig + that indicates how to setup the ResultsFormatter. + + @return an instance of CreatedFormatter. + """ + + def create_socket(port): + """Creates a socket to the localhost on the given port. + + @param port the port number of the listening port on + the localhost. + + @return (socket object, socket closing function) + """ + + def socket_closer(open_sock): + """Close down an opened socket properly.""" + open_sock.shutdown(socket.SHUT_RDWR) + open_sock.close() + + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect(("localhost", port)) + + # Wait for the ack from the listener side. + # This is needed to prevent a race condition + # in the main dosep.py processing loop: we + # can't allow a worker queue thread to die + # that has outstanding messages to a listener + # socket before the listener socket asyncore + # listener socket gets spun up; otherwise, + # we lose the test result info. + read_bytes = sock.recv(1) + if read_bytes is None or (len(read_bytes) < 1) or (read_bytes != b'*'): + raise Exception("listening socket did not respond with ack byte: response={}".format(read_bytes)) + + return sock, lambda: socket_closer(sock) + + default_formatter_name = None + results_file_object = None + cleanup_func = None + + file_is_stream = False + if config.filename: + # Open the results file for writing. + if config.filename == 'stdout': + results_file_object = sys.stdout + cleanup_func = None + elif config.filename == 'stderr': + results_file_object = sys.stderr + cleanup_func = None + else: + results_file_object = open(config.filename, "w") + cleanup_func = results_file_object.close + default_formatter_name = ( + "lldbsuite.test_event.formatter.xunit.XunitFormatter") + elif config.port: + # Connect to the specified localhost port. + results_file_object, cleanup_func = create_socket(config.port) + default_formatter_name = ( + "lldbsuite.test_event.formatter.pickled.RawPickledFormatter") + file_is_stream = True + + # If we have a results formatter name specified and we didn't specify + # a results file, we should use stdout. + if config.formatter_name is not None and results_file_object is None: + # Use stdout. + results_file_object = sys.stdout + cleanup_func = None + + if results_file_object: + # We care about the formatter. Choose user-specified or, if + # none specified, use the default for the output type. + if config.formatter_name: + formatter_name = config.formatter_name + else: + formatter_name = default_formatter_name + + # Create an instance of the class. + # First figure out the package/module. + components = formatter_name.split(".") + module = importlib.import_module(".".join(components[:-1])) + + # Create the class name we need to load. + cls = getattr(module, components[-1]) + + # Handle formatter options for the results formatter class. + formatter_arg_parser = cls.arg_parser() + if config.formatter_options and len(config.formatter_options) > 0: + command_line_options = config.formatter_options + else: + command_line_options = [] + + formatter_options = formatter_arg_parser.parse_args( + command_line_options) + + # Create the TestResultsFormatter given the processed options. + results_formatter_object = cls( + results_file_object, + formatter_options, + file_is_stream) + + def shutdown_formatter(): + """Shuts down the formatter when it is no longer needed.""" + # Tell the formatter to write out anything it may have + # been saving until the very end (e.g. xUnit results + # can't complete its output until this point). + results_formatter_object.send_terminate_as_needed() + + # And now close out the output file-like object. + if cleanup_func is not None: + cleanup_func() + + return CreatedFormatter( + results_formatter_object, + shutdown_formatter) + else: + return None diff --git a/packages/Python/lldbsuite/test_event/formatter/curses.py b/packages/Python/lldbsuite/test_event/formatter/curses.py new file mode 100644 index 000000000000..4e89fa9bf01e --- /dev/null +++ b/packages/Python/lldbsuite/test_event/formatter/curses.py @@ -0,0 +1,229 @@ +""" + The LLVM Compiler Infrastructure + + This file is distributed under the University of Illinois Open Source + License. See LICENSE.TXT for details. +""" + +from __future__ import absolute_import +from __future__ import print_function + +# System modules +import curses +import datetime +import math +import sys +import time + +# Third-party modules + +# LLDB modules +from lldbsuite.test import lldbcurses + +from . import results_formatter +from ..event_builder import EventBuilder + + +class Curses(results_formatter.ResultsFormatter): + """Receives live results from tests that are running and reports them to the terminal in a curses GUI""" + + def __init__(self, out_file, options, file_is_stream): + # Initialize the parent + super(Curses, self).__init__(out_file, options, file_is_stream) + self.using_terminal = True + self.have_curses = True + self.initialize_event = None + self.jobs = [None] * 64 + self.job_tests = [None] * 64 + self.results = list() + try: + self.main_window = lldbcurses.intialize_curses() + self.main_window.add_key_action('\t', self.main_window.select_next_first_responder, "Switch between views that can respond to keyboard input") + self.main_window.refresh() + self.job_panel = None + self.results_panel = None + self.status_panel = None + self.info_panel = None + self.hide_status_list = list() + self.start_time = time.time() + except: + self.have_curses = False + lldbcurses.terminate_curses() + self.using_terminal = False + print("Unexpected error:", sys.exc_info()[0]) + raise + + self.line_dict = dict() + # self.events_file = open("/tmp/events.txt", "w") + # self.formatters = list() + # if tee_results_formatter: + # self.formatters.append(tee_results_formatter) + + def status_to_short_str(self, status, test_event): + if status == EventBuilder.STATUS_SUCCESS: + return '.' + elif status == EventBuilder.STATUS_FAILURE: + return 'F' + elif status == EventBuilder.STATUS_UNEXPECTED_SUCCESS: + return '?' + elif status == EventBuilder.STATUS_EXPECTED_FAILURE: + return 'X' + elif status == EventBuilder.STATUS_SKIP: + return 'S' + elif status == EventBuilder.STATUS_ERROR: + if test_event.get("issue_phase", None) == "build": + # Build failure + return 'B' + else: + return 'E' + elif status == EventBuilder.STATUS_TIMEOUT: + return 'T' + elif status == EventBuilder.STATUS_EXPECTED_TIMEOUT: + return 't' + else: + return status + + def show_info_panel(self): + selected_idx = self.results_panel.get_selected_idx() + if selected_idx >= 0 and selected_idx < len(self.results): + if self.info_panel is None: + info_frame = self.results_panel.get_contained_rect(top_inset=10, left_inset=10, right_inset=10, height=30) + self.info_panel = lldbcurses.BoxedPanel(info_frame, "Result Details") + # Add a key action for any key that will hide this panel when any key is pressed + self.info_panel.add_key_action(-1, self.hide_info_panel, 'Hide the info panel') + self.info_panel.top() + else: + self.info_panel.show() + + self.main_window.push_first_responder(self.info_panel) + test_start = self.results[selected_idx][0] + test_result = self.results[selected_idx][1] + self.info_panel.set_line(0, "File: %s" % (test_start['test_filename'])) + self.info_panel.set_line(1, "Test: %s.%s" % (test_start['test_class'], test_start['test_name'])) + self.info_panel.set_line(2, "Time: %s" % (test_result['elapsed_time'])) + self.info_panel.set_line(3, "Status: %s" % (test_result['status'])) + + def hide_info_panel(self): + self.main_window.pop_first_responder(self.info_panel) + self.info_panel.hide() + self.main_window.refresh() + + def toggle_status(self, status): + if status: + # Toggle showing and hiding results whose status matches "status" in "Results" window + if status in self.hide_status_list: + self.hide_status_list.remove(status) + else: + self.hide_status_list.append(status) + self.update_results() + + def update_results(self, update=True): + '''Called after a category of test have been show/hidden to update the results list with + what the user desires to see.''' + self.results_panel.clear(update=False) + for result in self.results: + test_result = result[1] + status = test_result['status'] + if status in self.hide_status_list: + continue + name = test_result['test_class'] + '.' + test_result['test_name'] + self.results_panel.append_line('%s (%6.2f sec) %s' % (self.status_to_short_str(status, test_result), test_result['elapsed_time'], name)) + if update: + self.main_window.refresh() + + def handle_event(self, test_event): + with self.lock: + super(Curses, self).handle_event(test_event) + # for formatter in self.formatters: + # formatter.process_event(test_event) + if self.have_curses: + worker_index = -1 + if 'worker_index' in test_event: + worker_index = test_event['worker_index'] + if 'event' in test_event: + check_for_one_key = True + #print(str(test_event), file=self.events_file) + event = test_event['event'] + if self.status_panel: + self.status_panel.update_status('time', str(datetime.timedelta(seconds=math.floor(time.time() - self.start_time)))) + if event == 'test_start': + name = test_event['test_class'] + '.' + test_event['test_name'] + self.job_tests[worker_index] = test_event + if 'pid' in test_event: + line = 'pid: %5d ' % (test_event['pid']) + name + else: + line = name + self.job_panel.set_line(worker_index, line) + self.main_window.refresh() + elif event == 'test_result': + status = test_event['status'] + self.status_panel.increment_status(status) + if 'pid' in test_event: + line = 'pid: %5d ' % (test_event['pid']) + else: + line = '' + self.job_panel.set_line(worker_index, line) + name = test_event['test_class'] + '.' + test_event['test_name'] + elapsed_time = test_event['event_time'] - self.job_tests[worker_index]['event_time'] + if not status in self.hide_status_list: + self.results_panel.append_line('%s (%6.2f sec) %s' % (self.status_to_short_str(status, test_event), elapsed_time, name)) + self.main_window.refresh() + # Append the result pairs + test_event['elapsed_time'] = elapsed_time + self.results.append([self.job_tests[worker_index], test_event]) + self.job_tests[worker_index] = '' + elif event == 'job_begin': + self.jobs[worker_index] = test_event + if 'pid' in test_event: + line = 'pid: %5d ' % (test_event['pid']) + else: + line = '' + self.job_panel.set_line(worker_index, line) + elif event == 'job_end': + self.jobs[worker_index] = '' + self.job_panel.set_line(worker_index, '') + elif event == 'initialize': + self.initialize_event = test_event + num_jobs = test_event['worker_count'] + job_frame = self.main_window.get_contained_rect(height=num_jobs+2) + results_frame = self.main_window.get_contained_rect(top_inset=num_jobs+2, bottom_inset=1) + status_frame = self.main_window.get_contained_rect(height=1, top_inset=self.main_window.get_size().h-1) + self.job_panel = lldbcurses.BoxedPanel(frame=job_frame, title="Jobs") + self.results_panel = lldbcurses.BoxedPanel(frame=results_frame, title="Results") + + self.results_panel.add_key_action(curses.KEY_UP, self.results_panel.select_prev , "Select the previous list entry") + self.results_panel.add_key_action(curses.KEY_DOWN, self.results_panel.select_next , "Select the next list entry") + self.results_panel.add_key_action(curses.KEY_HOME, self.results_panel.scroll_begin , "Scroll to the start of the list") + self.results_panel.add_key_action(curses.KEY_END, self.results_panel.scroll_end , "Scroll to the end of the list") + self.results_panel.add_key_action(curses.KEY_ENTER, self.show_info_panel , "Display info for the selected result item") + self.results_panel.add_key_action('.', lambda : self.toggle_status(EventBuilder.STATUS_SUCCESS) , "Toggle showing/hiding tests whose status is 'success'") + self.results_panel.add_key_action('e', lambda : self.toggle_status(EventBuilder.STATUS_ERROR) , "Toggle showing/hiding tests whose status is 'error'") + self.results_panel.add_key_action('f', lambda : self.toggle_status(EventBuilder.STATUS_FAILURE) , "Toggle showing/hiding tests whose status is 'failure'") + self.results_panel.add_key_action('s', lambda : self.toggle_status(EventBuilder.STATUS_SKIP) , "Toggle showing/hiding tests whose status is 'skip'") + self.results_panel.add_key_action('x', lambda : self.toggle_status(EventBuilder.STATUS_EXPECTED_FAILURE) , "Toggle showing/hiding tests whose status is 'expected_failure'") + self.results_panel.add_key_action('?', lambda : self.toggle_status(EventBuilder.STATUS_UNEXPECTED_SUCCESS), "Toggle showing/hiding tests whose status is 'unexpected_success'") + self.status_panel = lldbcurses.StatusPanel(frame=status_frame) + + self.main_window.add_child(self.job_panel) + self.main_window.add_child(self.results_panel) + self.main_window.add_child(self.status_panel) + self.main_window.set_first_responder(self.results_panel) + + self.status_panel.add_status_item(name="time", title="Elapsed", format="%s", width=20, value="0:00:00", update=False) + self.status_panel.add_status_item(name=EventBuilder.STATUS_SUCCESS, title="Success", format="%u", width=20, value=0, update=False) + self.status_panel.add_status_item(name=EventBuilder.STATUS_FAILURE, title="Failure", format="%u", width=20, value=0, update=False) + self.status_panel.add_status_item(name=EventBuilder.STATUS_ERROR, title="Error", format="%u", width=20, value=0, update=False) + self.status_panel.add_status_item(name=EventBuilder.STATUS_SKIP, title="Skipped", format="%u", width=20, value=0, update=True) + self.status_panel.add_status_item(name=EventBuilder.STATUS_EXPECTED_FAILURE, title="Expected Failure", format="%u", width=30, value=0, update=False) + self.status_panel.add_status_item(name=EventBuilder.STATUS_UNEXPECTED_SUCCESS, title="Unexpected Success", format="%u", width=30, value=0, update=False) + self.main_window.refresh() + elif event == 'terminate': + #self.main_window.key_event_loop() + lldbcurses.terminate_curses() + check_for_one_key = False + self.using_terminal = False + # Check for 1 keypress with no delay + + # Check for 1 keypress with no delay + if check_for_one_key: + self.main_window.key_event_loop(0, 1) diff --git a/packages/Python/lldbsuite/test_event/formatter/dump_formatter.py b/packages/Python/lldbsuite/test_event/formatter/dump_formatter.py new file mode 100644 index 000000000000..d42dcb18bb4f --- /dev/null +++ b/packages/Python/lldbsuite/test_event/formatter/dump_formatter.py @@ -0,0 +1,23 @@ +""" + The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. +""" + +from __future__ import print_function +from __future__ import absolute_import + +# System modules +import pprint + +# Our modules +from .results_formatter import ResultsFormatter + + +class DumpFormatter(ResultsFormatter): + """Formats events to the file as their raw python dictionary format.""" + + def handle_event(self, test_event): + super(DumpFormatter, self).handle_event(test_event) + self.out_file.write("\n" + pprint.pformat(test_event) + "\n") diff --git a/packages/Python/lldbsuite/test_event/formatter/pickled.py b/packages/Python/lldbsuite/test_event/formatter/pickled.py new file mode 100644 index 000000000000..6d800f6c8baa --- /dev/null +++ b/packages/Python/lldbsuite/test_event/formatter/pickled.py @@ -0,0 +1,72 @@ +""" + The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. +""" + +from __future__ import print_function +from __future__ import absolute_import + +# System modules +import os + +# Our modules +from .results_formatter import ResultsFormatter +from six.moves import cPickle + + +class RawPickledFormatter(ResultsFormatter): + """Formats events as a pickled stream. + + The parallel test runner has inferiors pickle their results and send them + over a socket back to the parallel test. The parallel test runner then + aggregates them into the final results formatter (e.g. xUnit). + """ + + @classmethod + def arg_parser(cls): + """@return arg parser used to parse formatter-specific options.""" + parser = super(RawPickledFormatter, cls).arg_parser() + return parser + + class StreamSerializer(object): + @staticmethod + def serialize(test_event, out_file): + # Send it as {serialized_length_of_serialized_bytes}{serialized_bytes} + import struct + msg = cPickle.dumps(test_event) + packet = struct.pack("!I%ds" % len(msg), len(msg), msg) + out_file.send(packet) + + class BlockSerializer(object): + @staticmethod + def serialize(test_event, out_file): + cPickle.dump(test_event, out_file) + + def __init__(self, out_file, options, file_is_stream): + super(RawPickledFormatter, self).__init__(out_file, options, file_is_stream) + self.pid = os.getpid() + if file_is_stream: + self.serializer = self.StreamSerializer() + else: + self.serializer = self.BlockSerializer() + + def handle_event(self, test_event): + super(RawPickledFormatter, self).handle_event(test_event) + + # Convert initialize/terminate events into job_begin/job_end events. + event_type = test_event["event"] + if event_type is None: + return + + if event_type == "initialize": + test_event["event"] = "job_begin" + elif event_type == "terminate": + test_event["event"] = "job_end" + + # Tack on the pid. + test_event["pid"] = self.pid + + # Serialize the test event. + self.serializer.serialize(test_event, self.out_file) diff --git a/packages/Python/lldbsuite/test_event/formatter/results_formatter.py b/packages/Python/lldbsuite/test_event/formatter/results_formatter.py new file mode 100644 index 000000000000..3bf389b97266 --- /dev/null +++ b/packages/Python/lldbsuite/test_event/formatter/results_formatter.py @@ -0,0 +1,717 @@ +""" + The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. + +Provides classes used by the test results reporting infrastructure +within the LLDB test suite. +""" + +from __future__ import print_function +from __future__ import absolute_import + +# System modules +import argparse +import os +import sys +import threading + +# Third-party modules + + +# LLDB modules +from lldbsuite.test import configuration +from ..event_builder import EventBuilder + +import lldbsuite + + +class ResultsFormatter(object): + """Provides interface to formatting test results out to a file-like object. + + This class allows the LLDB test framework's raw test-related + events to be processed and formatted in any manner desired. + Test events are represented by python dictionaries, formatted + as in the EventBuilder class above. + + ResultFormatter instances are given a file-like object in which + to write their results. + + ResultFormatter lifetime looks like the following: + + # The result formatter is created. + # The argparse options dictionary is generated from calling + # the SomeResultFormatter.arg_parser() with the options data + # passed to dotest.py via the "--results-formatter-options" + # argument. See the help on that for syntactic requirements + # on getting that parsed correctly. + formatter = SomeResultFormatter(file_like_object, argparse_options_dict) + + # Single call to session start, before parsing any events. + formatter.begin_session() + + formatter.handle_event({"event":"initialize",...}) + + # Zero or more calls specified for events recorded during the test session. + # The parallel test runner manages getting results from all the inferior + # dotest processes, so from a new format perspective, don't worry about + # that. The formatter will be presented with a single stream of events + # sandwiched between a single begin_session()/end_session() pair in the + # parallel test runner process/thread. + for event in zero_or_more_test_events(): + formatter.handle_event(event) + + # Single call to terminate/wrap-up. For formatters that need all the + # data before they can print a correct result (e.g. xUnit/JUnit), + # this is where the final report can be generated. + formatter.handle_event({"event":"terminate",...}) + + It is not the formatter's responsibility to close the file_like_object. + (i.e. do not close it). + + The lldb test framework passes these test events in real time, so they + arrive as they come in. + + In the case of the parallel test runner, the dotest inferiors + add a 'pid' field to the dictionary that indicates which inferior + pid generated the event. + + Note more events may be added in the future to support richer test + reporting functionality. One example: creating a true flaky test + result category so that unexpected successes really mean the test + is marked incorrectly (either should be marked flaky, or is indeed + passing consistently now and should have the xfail marker + removed). In this case, a flaky_success and flaky_fail event + likely will be added to capture these and support reporting things + like percentages of flaky test passing so we can see if we're + making some things worse/better with regards to failure rates. + + Another example: announcing all the test methods that are planned + to be run, so we can better support redo operations of various kinds + (redo all non-run tests, redo non-run tests except the one that + was running [perhaps crashed], etc.) + + Implementers are expected to override all the public methods + provided in this class. See each method's docstring to see + expectations about when the call should be chained. + + """ + @classmethod + def arg_parser(cls): + """@return arg parser used to parse formatter-specific options.""" + parser = argparse.ArgumentParser( + description='{} options'.format(cls.__name__), + usage=('dotest.py --results-formatter-options=' + '"--option1 value1 [--option2 value2 [...]]"')) + parser.add_argument( + "--dump-results", + action="store_true", + help=('dump the raw results data after printing ' + 'the summary output.')) + return parser + + def __init__(self, out_file, options, file_is_stream): + super(ResultsFormatter, self).__init__() + self.out_file = out_file + self.options = options + self.using_terminal = False + if not self.out_file: + raise Exception("ResultsFormatter created with no file object") + self.start_time_by_test = {} + self.terminate_called = False + self.file_is_stream = file_is_stream + + # Store counts of test_result events by status. + self.result_status_counts = { + EventBuilder.STATUS_SUCCESS: 0, + EventBuilder.STATUS_EXPECTED_FAILURE: 0, + EventBuilder.STATUS_EXPECTED_TIMEOUT: 0, + EventBuilder.STATUS_SKIP: 0, + EventBuilder.STATUS_UNEXPECTED_SUCCESS: 0, + EventBuilder.STATUS_FAILURE: 0, + EventBuilder.STATUS_ERROR: 0, + EventBuilder.STATUS_TIMEOUT: 0, + EventBuilder.STATUS_EXCEPTIONAL_EXIT: 0 + } + + # Track the most recent test start event by worker index. + # We'll use this to assign TIMEOUT and exceptional + # exits to the most recent test started on a given + # worker index. + self.started_tests_by_worker = {} + + # Store the most recent test_method/job status. + self.result_events = {} + + # Track the number of test method reruns. + self.test_method_rerun_count = 0 + + # Lock that we use while mutating inner state, like the + # total test count and the elements. We minimize how + # long we hold the lock just to keep inner state safe, not + # entirely consistent from the outside. + self.lock = threading.RLock() + + # Keeps track of the test base filenames for tests that + # are expected to timeout. If a timeout occurs in any test + # basename that matches this list, that result should be + # converted into a non-issue. We'll create an expected + # timeout test status for this. + self.expected_timeouts_by_basename = set() + + # Tests which have reported that they are expecting to fail. These will + # be marked as expected failures even if they return a failing status, + # probably because they crashed or deadlocked. + self.expected_failures = set() + + # Keep track of rerun-eligible tests. + # This is a set that contains tests saved as: + # {test_filename}:{test_class}:{test_name} + self.rerun_eligible_tests = set() + + # A dictionary of test files that had a failing + # test, in the format of: + # key = test path, value = array of test methods that need rerun + self.tests_for_rerun = {} + + @classmethod + def _make_key(cls, result_event): + """Creates a key from a test or job result event. + + This key attempts to be as unique as possible. For + test result events, it will be unique per test method. + For job events (ones not promoted to a test result event), + it will be unique per test case file. + + @return a string-based key of the form + {test_filename}:{test_class}.{test_name} + """ + if result_event is None: + return None + component_count = 0 + if "test_filename" in result_event: + key = result_event["test_filename"] + component_count += 1 + else: + key = "" + if "test_class" in result_event: + if component_count > 0: + key += ":" + key += result_event["test_class"] + component_count += 1 + if "test_name" in result_event: + if component_count > 0: + key += "." + key += result_event["test_name"] + component_count += 1 + return key + + def _mark_test_as_expected_failure(self, test_result_event): + key = self._make_key(test_result_event) + if key is not None: + self.expected_failures.add(key) + else: + sys.stderr.write( + "\nerror: test marked as expected failure but " + "failed to create key.\n") + + def _mark_test_for_rerun_eligibility(self, test_result_event): + key = self._make_key(test_result_event) + if key is not None: + self.rerun_eligible_tests.add(key) + else: + sys.stderr.write( + "\nerror: test marked for re-run eligibility but " + "failed to create key.\n") + + def _maybe_add_test_to_rerun_list(self, result_event): + key = self._make_key(result_event) + if key is not None: + if (key in self.rerun_eligible_tests or + configuration.rerun_all_issues): + test_filename = result_event.get("test_filename", None) + if test_filename is not None: + test_name = result_event.get("test_name", None) + if test_filename not in self.tests_for_rerun: + self.tests_for_rerun[test_filename] = [] + if test_name is not None: + self.tests_for_rerun[test_filename].append(test_name) + else: + sys.stderr.write( + "\nerror: couldn't add testrun-failing test to rerun " + "list because no eligibility key could be created.\n") + + def _maybe_remap_job_result_event(self, test_event): + """Remaps timeout/exceptional exit job results to last test method running. + + @param test_event the job_result test event. This is an in/out + parameter. It will be modified if it can be mapped to a test_result + of the same status, using details from the last-running test method + known to be most recently started on the same worker index. + """ + test_start = None + + job_status = test_event["status"] + if job_status in [ + EventBuilder.STATUS_TIMEOUT, + EventBuilder.STATUS_EXCEPTIONAL_EXIT]: + worker_index = test_event.get("worker_index", None) + if worker_index is not None: + test_start = self.started_tests_by_worker.get( + worker_index, None) + + # If we have a test start to remap, do it here. + if test_start is not None: + test_event["event"] = EventBuilder.TYPE_TEST_RESULT + + # Fill in all fields from test start not present in + # job status message. + for (start_key, start_value) in test_start.items(): + if start_key not in test_event: + test_event[start_key] = start_value + + def _maybe_remap_expected_timeout(self, event): + if event is None: + return + + status = event.get("status", None) + if status is None or status != EventBuilder.STATUS_TIMEOUT: + return + + # Check if the timeout test's basename is in the expected timeout + # list. If so, convert to an expected timeout. + basename = os.path.basename(event.get("test_filename", "")) + if basename in self.expected_timeouts_by_basename: + # Convert to an expected timeout. + event["status"] = EventBuilder.STATUS_EXPECTED_TIMEOUT + + def _maybe_remap_expected_failure(self, event): + if event is None: + return + + key = self._make_key(event) + if key not in self.expected_failures: + return + + status = event.get("status", None) + if status in EventBuilder.TESTRUN_ERROR_STATUS_VALUES: + event["status"] = EventBuilder.STATUS_EXPECTED_FAILURE + elif status == EventBuilder.STATUS_SUCCESS: + event["status"] = EventBuilder.STATUS_UNEXPECTED_SUCCESS + + def handle_event(self, test_event): + """Handles the test event for collection into the formatter output. + + Derived classes may override this but should call down to this + implementation first. + + @param test_event the test event as formatted by one of the + event_for_* calls. + """ + with self.lock: + # Keep track of whether terminate was received. We do this so + # that a process can call the 'terminate' event on its own, to + # close down a formatter at the appropriate time. Then the + # atexit() cleanup can call the "terminate if it hasn't been + # called yet". + if test_event is not None: + event_type = test_event.get("event", "") + # We intentionally allow event_type to be checked anew + # after this check below since this check may rewrite + # the event type + if event_type == EventBuilder.TYPE_JOB_RESULT: + # Possibly convert the job status (timeout, exceptional exit) + # to an appropriate test_result event. + self._maybe_remap_job_result_event(test_event) + event_type = test_event.get("event", "") + + # Remap timeouts to expected timeouts. + if event_type in EventBuilder.RESULT_TYPES: + self._maybe_remap_expected_timeout(test_event) + self._maybe_remap_expected_failure(test_event) + event_type = test_event.get("event", "") + + if event_type == "terminate": + self.terminate_called = True + elif event_type in EventBuilder.RESULT_TYPES: + # Keep track of event counts per test/job result status type. + # The only job (i.e. inferior process) results that make it + # here are ones that cannot be remapped to the most recently + # started test for the given worker index. + status = test_event["status"] + self.result_status_counts[status] += 1 + # Clear the most recently started test for the related worker. + worker_index = test_event.get("worker_index", None) + if worker_index is not None: + self.started_tests_by_worker.pop(worker_index, None) + + if status in EventBuilder.TESTRUN_ERROR_STATUS_VALUES: + # A test/job status value in any of those status values + # causes a testrun failure. If such a test fails, check + # whether it can be rerun. If it can be rerun, add it + # to the rerun job. + self._maybe_add_test_to_rerun_list(test_event) + + # Build the test key. + test_key = self._make_key(test_event) + if test_key is None: + raise Exception( + "failed to find test filename for " + "test event {}".format(test_event)) + + # Save the most recent test event for the test key. + # This allows a second test phase to overwrite the most + # recent result for the test key (unique per method). + # We do final reporting at the end, so we'll report based + # on final results. + # We do this so that a re-run caused by, perhaps, the need + # to run a low-load, single-worker test run can have the final + # run's results to always be used. + if test_key in self.result_events: + # We are replacing the result of something that was + # already counted by the base class. Remove the double + # counting by reducing by one the count for the test + # result status. + old_status = self.result_events[test_key]["status"] + self.result_status_counts[old_status] -= 1 + self.test_method_rerun_count += 1 + self.result_events[test_key] = test_event + elif event_type == EventBuilder.TYPE_TEST_START: + # Track the start time for the test method. + self.track_start_time( + test_event["test_class"], + test_event["test_name"], + test_event["event_time"]) + # Track of the most recent test method start event + # for the related worker. This allows us to figure + # out whether a process timeout or exceptional exit + # can be charged (i.e. assigned) to a test method. + worker_index = test_event.get("worker_index", None) + if worker_index is not None: + self.started_tests_by_worker[worker_index] = test_event + + elif event_type == EventBuilder.TYPE_MARK_TEST_RERUN_ELIGIBLE: + self._mark_test_for_rerun_eligibility(test_event) + elif event_type == EventBuilder.TYPE_MARK_TEST_EXPECTED_FAILURE: + self._mark_test_as_expected_failure(test_event) + + def set_expected_timeouts_by_basename(self, basenames): + """Specifies a list of test file basenames that are allowed to timeout + without being called out as a timeout issue. + + These fall into a new status category called STATUS_EXPECTED_TIMEOUT. + """ + if basenames is not None: + for basename in basenames: + self.expected_timeouts_by_basename.add(basename) + + def track_start_time(self, test_class, test_name, start_time): + """tracks the start time of a test so elapsed time can be computed. + + this alleviates the need for test results to be processed serially + by test. it will save the start time for the test so that + elapsed_time_for_test() can compute the elapsed time properly. + """ + if test_class is None or test_name is None: + return + + test_key = "{}.{}".format(test_class, test_name) + self.start_time_by_test[test_key] = start_time + + def elapsed_time_for_test(self, test_class, test_name, end_time): + """returns the elapsed time for a test. + + this function can only be called once per test and requires that + the track_start_time() method be called sometime prior to calling + this method. + """ + if test_class is None or test_name is None: + return -2.0 + + test_key = "{}.{}".format(test_class, test_name) + if test_key not in self.start_time_by_test: + return -1.0 + else: + start_time = self.start_time_by_test[test_key] + del self.start_time_by_test[test_key] + return end_time - start_time + + def is_using_terminal(self): + """returns true if this results formatter is using the terminal and + output should be avoided.""" + return self.using_terminal + + def send_terminate_as_needed(self): + """sends the terminate event if it hasn't been received yet.""" + if not self.terminate_called: + terminate_event = EventBuilder.bare_event("terminate") + self.handle_event(terminate_event) + + # Derived classes may require self access + # pylint: disable=no-self-use + # noinspection PyMethodMayBeStatic,PyMethodMayBeStatic + def replaces_summary(self): + """Returns whether the results formatter includes a summary + suitable to replace the old lldb test run results. + + @return True if the lldb test runner can skip its summary + generation when using this results formatter; False otherwise. + """ + return False + + def counts_by_test_result_status(self, status): + """Returns number of test method results for the given status. + + @status_result a test result status (e.g. success, fail, skip) + as defined by the EventBuilder.STATUS_* class members. + + @return an integer returning the number of test methods matching + the given test result status. + """ + return self.result_status_counts[status] + + @classmethod + def _event_sort_key(cls, event): + """Returns the sort key to be used for a test event. + + This method papers over the differences in a test method result vs. a + job (i.e. inferior process) result. + + @param event a test result or job result event. + @return a key useful for sorting events by name (test name preferably, + then by test filename). + """ + if "test_name" in event: + return event["test_name"] + else: + return event.get("test_filename", None) + + def _partition_results_by_status(self, categories): + """Partitions the captured test results by event status. + + This permits processing test results by the category ids. + + @param categories the list of categories on which to partition. + Follows the format described in _report_category_details(). + + @return a dictionary where each key is the test result status, + and each entry is a list containing all the test result events + that matched that test result status. Result status IDs with + no matching entries will have a zero-length list. + """ + partitioned_events = {} + for category in categories: + result_status_id = category[0] + matching_events = [ + [key, event] for (key, event) in self.result_events.items() + if event.get("status", "") == result_status_id] + partitioned_events[result_status_id] = sorted( + matching_events, + key=lambda x: self._event_sort_key(x[1])) + return partitioned_events + + @staticmethod + def _print_banner(out_file, banner_text): + """Prints an ASCII banner around given text. + + Output goes to the out file for the results formatter. + + @param out_file a file-like object where output will be written. + @param banner_text the text to display, with a banner + of '=' around the line above and line below. + """ + banner_separator = "".ljust(len(banner_text), "=") + + out_file.write("\n{}\n{}\n{}\n".format( + banner_separator, + banner_text, + banner_separator)) + + def _print_summary_counts( + self, out_file, categories, result_events_by_status, extra_rows): + """Prints summary counts for all categories. + + @param out_file a file-like object used to print output. + + @param categories the list of categories on which to partition. + Follows the format described in _report_category_details(). + + @param result_events_by_status the partitioned list of test + result events in a dictionary, with the key set to the test + result status id and the value set to the list of test method + results that match the status id. + """ + + # Get max length for category printed name + category_with_max_printed_name = max( + categories, key=lambda x: len(x[1])) + max_category_name_length = len(category_with_max_printed_name[1]) + + # If we are provided with extra rows, consider these row name lengths. + if extra_rows is not None: + for row in extra_rows: + name_length = len(row[0]) + if name_length > max_category_name_length: + max_category_name_length = name_length + + self._print_banner(out_file, "Test Result Summary") + + # Prepend extra rows + if extra_rows is not None: + for row in extra_rows: + extra_label = "{}:".format(row[0]).ljust( + max_category_name_length + 1) + out_file.write("{} {:4}\n".format(extra_label, row[1])) + + for category in categories: + result_status_id = category[0] + result_label = "{}:".format(category[1]).ljust( + max_category_name_length + 1) + count = len(result_events_by_status[result_status_id]) + out_file.write("{} {:4}\n".format( + result_label, + count)) + + @classmethod + def _has_printable_details(cls, categories, result_events_by_status): + """Returns whether there are any test result details that need to be printed. + + This will spin through the results and see if any result in a category + that is printable has any results to print. + + @param categories the list of categories on which to partition. + Follows the format described in _report_category_details(). + + @param result_events_by_status the partitioned list of test + result events in a dictionary, with the key set to the test + result status id and the value set to the list of test method + results that match the status id. + + @return True if there are any details (i.e. test results + for failures, errors, unexpected successes); False otherwise. + """ + for category in categories: + result_status_id = category[0] + print_matching_tests = category[2] + if print_matching_tests: + if len(result_events_by_status[result_status_id]) > 0: + # We found a printable details test result status + # that has details to print. + return True + # We didn't find any test result category with printable + # details. + return False + + @staticmethod + def _report_category_details(out_file, category, result_events_by_status): + """Reports all test results matching the given category spec. + + @param out_file a file-like object used to print output. + + @param category a category spec of the format [test_event_name, + printed_category_name, print_matching_entries?] + + @param result_events_by_status the partitioned list of test + result events in a dictionary, with the key set to the test + result status id and the value set to the list of test method + results that match the status id. + """ + result_status_id = category[0] + print_matching_tests = category[2] + detail_label = category[3] + + if print_matching_tests: + # Sort by test name + for (_, event) in result_events_by_status[result_status_id]: + # Convert full test path into test-root-relative. + test_relative_path = os.path.relpath( + os.path.realpath(event["test_filename"]), + lldbsuite.lldb_test_root) + + # Create extra info component (used for exceptional exit info) + if result_status_id == EventBuilder.STATUS_EXCEPTIONAL_EXIT: + extra_info = "[EXCEPTIONAL EXIT {} ({})] ".format( + event["exception_code"], + event["exception_description"]) + else: + extra_info = "" + + # Figure out the identity we will use for this test. + if configuration.verbose and ("test_class" in event): + test_id = "{}.{}".format( + event["test_class"], event["test_name"]) + elif "test_name" in event: + test_id = event["test_name"] + else: + test_id = "" + + # Display the info. + out_file.write("{}: {}{} ({})\n".format( + detail_label, + extra_info, + test_id, + test_relative_path)) + + def print_results(self, out_file): + """Writes the test result report to the output file. + + @param out_file a file-like object used for printing summary + results. This is different than self.out_file, which might + be something else for non-summary data. + """ + extra_results = [ + # Total test methods processed, excluding reruns. + ["Test Methods", len(self.result_events)], + ["Reruns", self.test_method_rerun_count]] + + # Output each of the test result entries. + categories = [ + # result id, printed name, print matching tests?, detail label + [EventBuilder.STATUS_SUCCESS, + "Success", False, None], + [EventBuilder.STATUS_EXPECTED_FAILURE, + "Expected Failure", False, None], + [EventBuilder.STATUS_FAILURE, + "Failure", True, "FAIL"], + [EventBuilder.STATUS_ERROR, + "Error", True, "ERROR"], + [EventBuilder.STATUS_EXCEPTIONAL_EXIT, + "Exceptional Exit", True, "ERROR"], + [EventBuilder.STATUS_UNEXPECTED_SUCCESS, + "Unexpected Success", True, "UNEXPECTED SUCCESS"], + [EventBuilder.STATUS_SKIP, "Skip", False, None], + [EventBuilder.STATUS_TIMEOUT, + "Timeout", True, "TIMEOUT"], + [EventBuilder.STATUS_EXPECTED_TIMEOUT, + # Intentionally using the unusual hyphenation in TIME-OUT to + # prevent buildbots from thinking it is an issue when scanning + # for TIMEOUT. + "Expected Timeout", True, "EXPECTED TIME-OUT"] + ] + + # Partition all the events by test result status + result_events_by_status = self._partition_results_by_status( + categories) + + # Print the details + have_details = self._has_printable_details( + categories, result_events_by_status) + if have_details: + self._print_banner(out_file, "Issue Details") + for category in categories: + self._report_category_details( + out_file, category, result_events_by_status) + + # Print the summary + self._print_summary_counts( + out_file, categories, result_events_by_status, extra_results) + + if self.options.dump_results: + # Debug dump of the key/result info for all categories. + self._print_banner(out_file, "Results Dump") + for status, events_by_key in result_events_by_status.items(): + out_file.write("\nSTATUS: {}\n".format(status)) + for key, event in events_by_key: + out_file.write("key: {}\n".format(key)) + out_file.write("event: {}\n".format(event)) diff --git a/packages/Python/lldbsuite/test_event/formatter/xunit.py b/packages/Python/lldbsuite/test_event/formatter/xunit.py new file mode 100644 index 000000000000..b3682f8fb107 --- /dev/null +++ b/packages/Python/lldbsuite/test_event/formatter/xunit.py @@ -0,0 +1,592 @@ +""" + The LLVM Compiler Infrastructure + +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. + +Provides an xUnit ResultsFormatter for integrating the LLDB +test suite with the Jenkins xUnit aggregator and other xUnit-compliant +test output processors. +""" +from __future__ import absolute_import +from __future__ import print_function + +# System modules +import re +import sys +import xml.sax.saxutils + +# Third-party modules +import six + +# Local modules +from ..event_builder import EventBuilder +from ..build_exception import BuildError +from .results_formatter import ResultsFormatter + + +class XunitFormatter(ResultsFormatter): + """Provides xUnit-style formatted output. + """ + + # Result mapping arguments + RM_IGNORE = 'ignore' + RM_SUCCESS = 'success' + RM_FAILURE = 'failure' + RM_PASSTHRU = 'passthru' + + @staticmethod + def _build_illegal_xml_regex(): + """Constructs a regex to match all illegal xml characters. + + Expects to be used against a unicode string.""" + # Construct the range pairs of invalid unicode characters. + illegal_chars_u = [ + (0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F), (0x7F, 0x84), + (0x86, 0x9F), (0xFDD0, 0xFDDF), (0xFFFE, 0xFFFF)] + + # For wide builds, we have more. + if sys.maxunicode >= 0x10000: + illegal_chars_u.extend( + [(0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF), (0x3FFFE, 0x3FFFF), + (0x4FFFE, 0x4FFFF), (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF), + (0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF), (0x9FFFE, 0x9FFFF), + (0xAFFFE, 0xAFFFF), (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF), + (0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF), (0xFFFFE, 0xFFFFF), + (0x10FFFE, 0x10FFFF)]) + + # Build up an array of range expressions. + illegal_ranges = [ + "%s-%s" % (six.unichr(low), six.unichr(high)) + for (low, high) in illegal_chars_u] + + # Compile the regex + return re.compile(six.u('[%s]') % six.u('').join(illegal_ranges)) + + @staticmethod + def _quote_attribute(text): + """Returns the given text in a manner safe for usage in an XML attribute. + + @param text the text that should appear within an XML attribute. + @return the attribute-escaped version of the input text. + """ + return xml.sax.saxutils.quoteattr(text) + + def _replace_invalid_xml(self, str_or_unicode): + """Replaces invalid XML characters with a '?'. + + @param str_or_unicode a string to replace invalid XML + characters within. Can be unicode or not. If not unicode, + assumes it is a byte string in utf-8 encoding. + + @returns a utf-8-encoded byte string with invalid + XML replaced with '?'. + """ + # Get the content into unicode + if isinstance(str_or_unicode, str): + unicode_content = str_or_unicode.decode('utf-8') + else: + unicode_content = str_or_unicode + return self.invalid_xml_re.sub( + six.u('?'), unicode_content).encode('utf-8') + + @classmethod + def arg_parser(cls): + """@return arg parser used to parse formatter-specific options.""" + parser = super(XunitFormatter, cls).arg_parser() + + # These are valid choices for results mapping. + results_mapping_choices = [ + XunitFormatter.RM_IGNORE, + XunitFormatter.RM_SUCCESS, + XunitFormatter.RM_FAILURE, + XunitFormatter.RM_PASSTHRU] + parser.add_argument( + "--assert-on-unknown-events", + action="store_true", + help=('cause unknown test events to generate ' + 'a python assert. Default is to ignore.')) + parser.add_argument( + "--ignore-skip-name", + "-n", + metavar='PATTERN', + action="append", + dest='ignore_skip_name_patterns', + help=('a python regex pattern, where ' + 'any skipped test with a test method name where regex ' + 'matches (via search) will be ignored for xUnit test ' + 'result purposes. Can be specified multiple times.')) + parser.add_argument( + "--ignore-skip-reason", + "-r", + metavar='PATTERN', + action="append", + dest='ignore_skip_reason_patterns', + help=('a python regex pattern, where ' + 'any skipped test with a skip reason where the regex ' + 'matches (via search) will be ignored for xUnit test ' + 'result purposes. Can be specified multiple times.')) + parser.add_argument( + "--xpass", action="store", choices=results_mapping_choices, + default=XunitFormatter.RM_FAILURE, + help=('specify mapping from unexpected success to jUnit/xUnit ' + 'result type')) + parser.add_argument( + "--xfail", action="store", choices=results_mapping_choices, + default=XunitFormatter.RM_IGNORE, + help=('specify mapping from expected failure to jUnit/xUnit ' + 'result type')) + return parser + + @staticmethod + def _build_regex_list_from_patterns(patterns): + """Builds a list of compiled regular expressions from option value. + + @param patterns contains a list of regular expression + patterns. + + @return list of compiled regular expressions, empty if no + patterns provided. + """ + regex_list = [] + if patterns is not None: + for pattern in patterns: + regex_list.append(re.compile(pattern)) + return regex_list + + def __init__(self, out_file, options, file_is_stream): + """Initializes the XunitFormatter instance. + @param out_file file-like object where formatted output is written. + @param options specifies a dictionary of options for the + formatter. + """ + # Initialize the parent + super(XunitFormatter, self).__init__(out_file, options, file_is_stream) + self.text_encoding = "UTF-8" + self.invalid_xml_re = XunitFormatter._build_illegal_xml_regex() + self.total_test_count = 0 + self.ignore_skip_name_regexes = ( + XunitFormatter._build_regex_list_from_patterns( + options.ignore_skip_name_patterns)) + self.ignore_skip_reason_regexes = ( + XunitFormatter._build_regex_list_from_patterns( + options.ignore_skip_reason_patterns)) + + self.elements = { + "successes": [], + "errors": [], + "failures": [], + "skips": [], + "unexpected_successes": [], + "expected_failures": [], + "all": [] + } + + self.status_handlers = { + EventBuilder.STATUS_SUCCESS: self._handle_success, + EventBuilder.STATUS_FAILURE: self._handle_failure, + EventBuilder.STATUS_ERROR: self._handle_error, + EventBuilder.STATUS_SKIP: self._handle_skip, + EventBuilder.STATUS_EXPECTED_FAILURE: + self._handle_expected_failure, + EventBuilder.STATUS_EXPECTED_TIMEOUT: + self._handle_expected_timeout, + EventBuilder.STATUS_UNEXPECTED_SUCCESS: + self._handle_unexpected_success, + EventBuilder.STATUS_EXCEPTIONAL_EXIT: + self._handle_exceptional_exit, + EventBuilder.STATUS_TIMEOUT: + self._handle_timeout + } + + RESULT_TYPES = {EventBuilder.TYPE_TEST_RESULT, EventBuilder.TYPE_JOB_RESULT} + + def handle_event(self, test_event): + super(XunitFormatter, self).handle_event(test_event) + + event_type = test_event["event"] + if event_type is None: + return + + if event_type == "terminate": + # Process all the final result events into their + # XML counterparts. + for result_event in self.result_events.values(): + self._process_test_result(result_event) + self._finish_output() + else: + # This is an unknown event. + if self.options.assert_on_unknown_events: + raise Exception("unknown event type {} from {}\n".format( + event_type, test_event)) + + def _handle_success(self, test_event): + """Handles a test success. + @param test_event the test event to handle. + """ + result = self._common_add_testcase_entry(test_event) + with self.lock: + self.elements["successes"].append(result) + + def _handle_failure(self, test_event): + """Handles a test failure. + @param test_event the test event to handle. + """ + message = self._replace_invalid_xml(test_event["issue_message"]) + backtrace = self._replace_invalid_xml( + "".join(test_event.get("issue_backtrace", []))) + + result = self._common_add_testcase_entry( + test_event, + inner_content=( + ''.format( + XunitFormatter._quote_attribute(test_event["issue_class"]), + XunitFormatter._quote_attribute(message), + backtrace) + )) + with self.lock: + self.elements["failures"].append(result) + + def _handle_error_build(self, test_event): + """Handles a test error. + @param test_event the test event to handle. + """ + message = self._replace_invalid_xml(test_event["issue_message"]) + build_issue_description = self._replace_invalid_xml( + BuildError.format_build_error( + test_event.get("build_command", ""), + test_event.get("build_error", ""))) + + result = self._common_add_testcase_entry( + test_event, + inner_content=( + ''.format( + XunitFormatter._quote_attribute(test_event["issue_class"]), + XunitFormatter._quote_attribute(message), + build_issue_description) + )) + with self.lock: + self.elements["errors"].append(result) + + def _handle_error_standard(self, test_event): + """Handles a test error. + @param test_event the test event to handle. + """ + message = self._replace_invalid_xml(test_event["issue_message"]) + backtrace = self._replace_invalid_xml( + "".join(test_event.get("issue_backtrace", []))) + + result = self._common_add_testcase_entry( + test_event, + inner_content=( + ''.format( + XunitFormatter._quote_attribute(test_event["issue_class"]), + XunitFormatter._quote_attribute(message), + backtrace) + )) + with self.lock: + self.elements["errors"].append(result) + + def _handle_error(self, test_event): + if test_event.get("issue_phase", None) == "build": + self._handle_error_build(test_event) + else: + self._handle_error_standard(test_event) + + def _handle_exceptional_exit(self, test_event): + """Handles an exceptional exit. + @param test_event the test method or job result event to handle. + """ + if "test_name" in test_event: + name = test_event["test_name"] + else: + name = test_event.get("test_filename", "") + + message_text = "ERROR: {} ({}): {}".format( + test_event.get("exception_code", 0), + test_event.get("exception_description", ""), + name) + message = self._replace_invalid_xml(message_text) + + result = self._common_add_testcase_entry( + test_event, + inner_content=( + ''.format( + "exceptional_exit", + XunitFormatter._quote_attribute(message)) + )) + with self.lock: + self.elements["errors"].append(result) + + def _handle_timeout(self, test_event): + """Handles a test method or job timeout. + @param test_event the test method or job result event to handle. + """ + if "test_name" in test_event: + name = test_event["test_name"] + else: + name = test_event.get("test_filename", "") + + message_text = "TIMEOUT: {}".format(name) + message = self._replace_invalid_xml(message_text) + + result = self._common_add_testcase_entry( + test_event, + inner_content=( + ''.format( + "timeout", + XunitFormatter._quote_attribute(message)) + )) + with self.lock: + self.elements["errors"].append(result) + + @staticmethod + def _ignore_based_on_regex_list(test_event, test_key, regex_list): + """Returns whether to ignore a test event based on patterns. + + @param test_event the test event dictionary to check. + @param test_key the key within the dictionary to check. + @param regex_list a list of zero or more regexes. May contain + zero or more compiled regexes. + + @return True if any o the regex list match based on the + re.search() method; false otherwise. + """ + for regex in regex_list: + match = regex.search(test_event.get(test_key, '')) + if match: + return True + return False + + def _handle_skip(self, test_event): + """Handles a skipped test. + @param test_event the test event to handle. + """ + + # Are we ignoring this test based on test name? + if XunitFormatter._ignore_based_on_regex_list( + test_event, 'test_name', self.ignore_skip_name_regexes): + return + + # Are we ignoring this test based on skip reason? + if XunitFormatter._ignore_based_on_regex_list( + test_event, 'skip_reason', self.ignore_skip_reason_regexes): + return + + # We're not ignoring this test. Process the skip. + reason = self._replace_invalid_xml(test_event.get("skip_reason", "")) + result = self._common_add_testcase_entry( + test_event, + inner_content=''.format( + XunitFormatter._quote_attribute(reason))) + with self.lock: + self.elements["skips"].append(result) + + def _handle_expected_failure(self, test_event): + """Handles a test that failed as expected. + @param test_event the test event to handle. + """ + if self.options.xfail == XunitFormatter.RM_PASSTHRU: + # This is not a natively-supported junit/xunit + # testcase mode, so it might fail a validating + # test results viewer. + if "bugnumber" in test_event: + bug_id_attribute = 'bug-id={} '.format( + XunitFormatter._quote_attribute(test_event["bugnumber"])) + else: + bug_id_attribute = '' + + result = self._common_add_testcase_entry( + test_event, + inner_content=( + ''.format( + bug_id_attribute, + XunitFormatter._quote_attribute( + test_event["issue_class"]), + XunitFormatter._quote_attribute( + test_event["issue_message"])) + )) + with self.lock: + self.elements["expected_failures"].append(result) + elif self.options.xfail == XunitFormatter.RM_SUCCESS: + result = self._common_add_testcase_entry(test_event) + with self.lock: + self.elements["successes"].append(result) + elif self.options.xfail == XunitFormatter.RM_FAILURE: + result = self._common_add_testcase_entry( + test_event, + inner_content=''.format( + XunitFormatter._quote_attribute(test_event["issue_class"]), + XunitFormatter._quote_attribute( + test_event["issue_message"]))) + with self.lock: + self.elements["failures"].append(result) + elif self.options.xfail == XunitFormatter.RM_IGNORE: + pass + else: + raise Exception( + "unknown xfail option: {}".format(self.options.xfail)) + + @staticmethod + def _handle_expected_timeout(test_event): + """Handles expected_timeout. + @param test_event the test event to handle. + """ + # We don't do anything with expected timeouts, not even report. + pass + + def _handle_unexpected_success(self, test_event): + """Handles a test that passed but was expected to fail. + @param test_event the test event to handle. + """ + if self.options.xpass == XunitFormatter.RM_PASSTHRU: + # This is not a natively-supported junit/xunit + # testcase mode, so it might fail a validating + # test results viewer. + result = self._common_add_testcase_entry( + test_event, + inner_content="") + with self.lock: + self.elements["unexpected_successes"].append(result) + elif self.options.xpass == XunitFormatter.RM_SUCCESS: + # Treat the xpass as a success. + result = self._common_add_testcase_entry(test_event) + with self.lock: + self.elements["successes"].append(result) + elif self.options.xpass == XunitFormatter.RM_FAILURE: + # Treat the xpass as a failure. + if "bugnumber" in test_event: + message = "unexpected success (bug_id:{})".format( + test_event["bugnumber"]) + else: + message = "unexpected success (bug_id:none)" + result = self._common_add_testcase_entry( + test_event, + inner_content=''.format( + XunitFormatter._quote_attribute("unexpected_success"), + XunitFormatter._quote_attribute(message))) + with self.lock: + self.elements["failures"].append(result) + elif self.options.xpass == XunitFormatter.RM_IGNORE: + # Ignore the xpass result as far as xUnit reporting goes. + pass + else: + raise Exception("unknown xpass option: {}".format( + self.options.xpass)) + + def _process_test_result(self, test_event): + """Processes the test_event known to be a test result. + + This categorizes the event appropriately and stores the data needed + to generate the final xUnit report. This method skips events that + cannot be represented in xUnit output. + """ + if "status" not in test_event: + raise Exception("test event dictionary missing 'status' key") + + status = test_event["status"] + if status not in self.status_handlers: + raise Exception("test event status '{}' unsupported".format( + status)) + + # Call the status handler for the test result. + self.status_handlers[status](test_event) + + def _common_add_testcase_entry(self, test_event, inner_content=None): + """Registers a testcase result, and returns the text created. + + The caller is expected to manage failure/skip/success counts + in some kind of appropriate way. This call simply constructs + the XML and appends the returned result to the self.all_results + list. + + @param test_event the test event dictionary. + + @param inner_content if specified, gets included in the + inner section, at the point before stdout and stderr would be + included. This is where a , , , etc. + could go. + + @return the text of the xml testcase element. + """ + + # Get elapsed time. + test_class = test_event.get("test_class", "") + test_name = test_event.get("test_name", "") + event_time = test_event["event_time"] + time_taken = self.elapsed_time_for_test( + test_class, test_name, event_time) + + # Plumb in stdout/stderr once we shift over to only test results. + test_stdout = '' + test_stderr = '' + + # Formulate the output xml. + if not inner_content: + inner_content = "" + result = ( + '' + '{}{}{}'.format( + test_class, + test_name, + time_taken, + inner_content, + test_stdout, + test_stderr)) + + # Save the result, update total test count. + with self.lock: + self.total_test_count += 1 + self.elements["all"].append(result) + + return result + + def _finish_output_no_lock(self): + """Flushes out the report of test executions to form valid xml output. + + xUnit output is in XML. The reporting system cannot complete the + formatting of the output without knowing when there is no more input. + This call addresses notification of the completed test run and thus is + when we can finish off the report output. + """ + + # Figure out the counts line for the testsuite. If we have + # been counting either unexpected successes or expected + # failures, we'll output those in the counts, at the risk of + # being invalidated by a validating test results viewer. + # These aren't counted by default so they won't show up unless + # the user specified a formatter option to include them. + xfail_count = len(self.elements["expected_failures"]) + xpass_count = len(self.elements["unexpected_successes"]) + if xfail_count > 0 or xpass_count > 0: + extra_testsuite_attributes = ( + ' expected-failures="{}"' + ' unexpected-successes="{}"'.format(xfail_count, xpass_count)) + else: + extra_testsuite_attributes = "" + + # Output the header. + self.out_file.write( + '\n' + '' + '\n'.format( + self.text_encoding, + "LLDB test suite", + self.total_test_count, + len(self.elements["errors"]), + len(self.elements["failures"]), + len(self.elements["skips"]), + extra_testsuite_attributes)) + + # Output each of the test result entries. + for result in self.elements["all"]: + self.out_file.write(result + '\n') + + # Close off the test suite. + self.out_file.write('\n') + + def _finish_output(self): + """Finish writing output as all incoming events have arrived.""" + with self.lock: + self._finish_output_no_lock() diff --git a/packages/Python/lldbsuite/test_event/test/resources/invalid_decorator/TestInvalidDecorator.py b/packages/Python/lldbsuite/test_event/test/resources/invalid_decorator/TestInvalidDecorator.py new file mode 100644 index 000000000000..7f5c4cb79cf5 --- /dev/null +++ b/packages/Python/lldbsuite/test_event/test/resources/invalid_decorator/TestInvalidDecorator.py @@ -0,0 +1,13 @@ +from __future__ import print_function +from lldbsuite.test import lldbtest +from lldbsuite.test import decorators + + +class NonExistentDecoratorTestCase(lldbtest.TestBase): + + mydir = lldbtest.TestBase.compute_mydir(__file__) + + @decorators.nonExistentDecorator(bugnumber="yt/1300") + def test(self): + """Verify non-existent decorators are picked up by test runner.""" + pass diff --git a/packages/Python/lldbsuite/test_event/test/src/TestCatchInvalidDecorator.py b/packages/Python/lldbsuite/test_event/test/src/TestCatchInvalidDecorator.py new file mode 100644 index 000000000000..56814416c333 --- /dev/null +++ b/packages/Python/lldbsuite/test_event/test/src/TestCatchInvalidDecorator.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +""" +Tests that the event system reports issues during decorator +handling as errors. +""" +# System-provided imports +import os +import unittest + +# Local-provided imports +import event_collector + + +class TestCatchInvalidDecorator(unittest.TestCase): + + TEST_DIR = os.path.join( + os.path.dirname(__file__), + os.path.pardir, + "resources", + "invalid_decorator") + + def test_with_whole_file(self): + """ + Test that a non-existent decorator generates a test-event error + when running all tests in the file. + """ + # Determine the test case file we're using. + test_file = os.path.join(self.TEST_DIR, "TestInvalidDecorator.py") + + # Collect all test events generated for this file. + error_results = _filter_error_results( + event_collector.collect_events_whole_file(test_file)) + + self.assertGreater( + len(error_results), + 0, + "At least one job or test error result should have been returned") + + def test_with_function_filter(self): + """ + Test that a non-existent decorator generates a test-event error + when running a filtered test. + """ + # Collect all test events generated during running of tests + # in a given directory using a test name filter. Internally, + # this runs through a different code path that needs to be + # set up to catch exceptions. + error_results = _filter_error_results( + event_collector.collect_events_for_directory_with_filter( + self.TEST_DIR, + "NonExistentDecoratorTestCase.test")) + + self.assertGreater( + len(error_results), + 0, + "At least one job or test error result should have been returned") + + +def _filter_error_results(events): + # Filter out job result events. + return [ + event + for event in events + if event.get("event", None) in ["job_result", "test_result"] and + event.get("status", None) == "error" + ] + + +if __name__ == "__main__": + unittest.main() diff --git a/packages/Python/lldbsuite/test_event/test/src/event_collector.py b/packages/Python/lldbsuite/test_event/test/src/event_collector.py new file mode 100644 index 000000000000..35d132066898 --- /dev/null +++ b/packages/Python/lldbsuite/test_event/test/src/event_collector.py @@ -0,0 +1,85 @@ +from __future__ import absolute_import +from __future__ import print_function + +import os +import subprocess +import sys +import tempfile + +# noinspection PyUnresolvedReferences +from six.moves import cPickle + + +def path_to_dotest_py(): + return os.path.join( + os.path.dirname(__file__), + os.path.pardir, + os.path.pardir, + os.path.pardir, + os.path.pardir, + os.path.pardir, + os.path.pardir, + "test", + "dotest.py") + + +def _make_pickled_events_filename(): + with tempfile.NamedTemporaryFile( + prefix="lldb_test_event_pickled_event_output", + delete=False) as temp_file: + return temp_file.name + + +def _collect_events_with_command(command, events_filename): + # Run the single test with dotest.py, outputting + # the raw pickled events to a temp file. + with open(os.devnull, 'w') as dev_null_file: + subprocess.call( + command, + stdout=dev_null_file, + stderr=dev_null_file) + + # Unpickle the events + events = [] + if os.path.exists(events_filename): + with open(events_filename, "rb") as events_file: + while True: + try: + # print("reading event") + event = cPickle.load(events_file) + # print("read event: {}".format(event)) + if event: + events.append(event) + except EOFError: + # This is okay. + break + os.remove(events_filename) + return events + + +def collect_events_whole_file(test_filename): + events_filename = _make_pickled_events_filename() + command = [ + sys.executable, + path_to_dotest_py(), + "--inferior", + "--results-formatter=lldbsuite.test_event.formatter.pickled.RawPickledFormatter", + "--results-file={}".format(events_filename), + "-p", os.path.basename(test_filename), + os.path.dirname(test_filename) + ] + return _collect_events_with_command(command, events_filename) + + +def collect_events_for_directory_with_filter(test_filename, filter_desc): + events_filename = _make_pickled_events_filename() + command = [ + sys.executable, + path_to_dotest_py(), + "--inferior", + "--results-formatter=lldbsuite.test_event.formatter.pickled.RawPickledFormatter", + "--results-file={}".format(events_filename), + "-f", filter_desc, + os.path.dirname(test_filename) + ] + return _collect_events_with_command(command, events_filename) -- cgit v1.2.3