| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 1 | """ | 
|  | 2 | Set breakpoints on objective-c class and instance methods in foundation. | 
|  | 3 | Also lookup objective-c data types and evaluate expressions. | 
|  | 4 | """ | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 5 |  | 
|  | 6 | import os, time | 
|  | 7 | import unittest2 | 
|  | 8 | import lldb | 
|  | 9 | from lldbtest import * | 
|  | 10 |  | 
|  | 11 | @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") | 
|  | 12 | class FoundationTestCase(TestBase): | 
|  | 13 |  | 
|  | 14 | mydir = "foundation" | 
|  | 15 |  | 
| Johnny Chen | b219d28 | 2010-09-17 21:14:02 +0000 | [diff] [blame] | 16 | def test_break_with_dsym(self): | 
| Johnny Chen | 2756d60 | 2010-09-16 23:57:33 +0000 | [diff] [blame] | 17 | """Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'.""" | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 18 | self.buildDsym() | 
|  | 19 | self.break_on_objc_methods() | 
|  | 20 |  | 
| Johnny Chen | b219d28 | 2010-09-17 21:14:02 +0000 | [diff] [blame] | 21 | def test_break_with_dwarf(self): | 
| Johnny Chen | 2756d60 | 2010-09-16 23:57:33 +0000 | [diff] [blame] | 22 | """Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'.""" | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 23 | self.buildDwarf() | 
|  | 24 | self.break_on_objc_methods() | 
|  | 25 |  | 
| Johnny Chen | 2769a42 | 2010-10-15 23:35:32 +0000 | [diff] [blame] | 26 | #@unittest2.expectedFailure | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 27 | # rdar://problem/8542091 | 
| Johnny Chen | 8eb3850 | 2010-09-29 17:58:12 +0000 | [diff] [blame] | 28 | # rdar://problem/8492646 | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 29 | def test_data_type_and_expr_with_dsym(self): | 
|  | 30 | """Lookup objective-c data types and evaluate expressions.""" | 
|  | 31 | self.buildDsym() | 
|  | 32 | self.data_type_and_expr_objc() | 
|  | 33 |  | 
| Johnny Chen | 2769a42 | 2010-10-15 23:35:32 +0000 | [diff] [blame] | 34 | #@unittest2.expectedFailure | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 35 | # rdar://problem/8542091 | 
| Johnny Chen | 8eb3850 | 2010-09-29 17:58:12 +0000 | [diff] [blame] | 36 | # rdar://problem/8492646 | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 37 | def test_data_type_and_expr_with_dwarf(self): | 
|  | 38 | """Lookup objective-c data types and evaluate expressions.""" | 
|  | 39 | self.buildDwarf() | 
|  | 40 | self.data_type_and_expr_objc() | 
|  | 41 |  | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 42 | def break_on_objc_methods(self): | 
| Johnny Chen | 2756d60 | 2010-09-16 23:57:33 +0000 | [diff] [blame] | 43 | """Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'.""" | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 44 | exe = os.path.join(os.getcwd(), "a.out") | 
|  | 45 | self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) | 
|  | 46 |  | 
|  | 47 | # Stop at +[NSString stringWithFormat:]. | 
|  | 48 | self.expect("regexp-break +[NSString stringWithFormat:]", BREAKPOINT_CREATED, | 
| Johnny Chen | f062c2f | 2010-10-12 19:29:49 +0000 | [diff] [blame] | 49 | substrs = ["Breakpoint created: 1: name = '+[NSString stringWithFormat:]', locations = 1"]) | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 50 |  | 
| Johnny Chen | 2756d60 | 2010-09-16 23:57:33 +0000 | [diff] [blame] | 51 | # Stop at -[MyString initWithNSString:]. | 
|  | 52 | self.expect("breakpoint set -n '-[MyString initWithNSString:]'", BREAKPOINT_CREATED, | 
|  | 53 | startstr = "Breakpoint created: 2: name = '-[MyString initWithNSString:]', locations = 1") | 
|  | 54 |  | 
|  | 55 | # Stop at the "description" selector. | 
|  | 56 | self.expect("breakpoint set -S description", BREAKPOINT_CREATED, | 
|  | 57 | startstr = "Breakpoint created: 3: name = 'description', locations = 1") | 
|  | 58 |  | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 59 | # Stop at -[NSAutoreleasePool release]. | 
|  | 60 | self.expect("regexp-break -[NSAutoreleasePool release]", BREAKPOINT_CREATED, | 
| Johnny Chen | f062c2f | 2010-10-12 19:29:49 +0000 | [diff] [blame] | 61 | substrs = ["Breakpoint created: 4: name = '-[NSAutoreleasePool release]', locations = 1"]) | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 62 |  | 
|  | 63 | self.runCmd("run", RUN_SUCCEEDED) | 
|  | 64 |  | 
|  | 65 | # First stop is +[NSString stringWithFormat:]. | 
|  | 66 | self.expect("thread backtrace", "Stop at +[NSString stringWithFormat:]", | 
|  | 67 | substrs = ["Foundation`+[NSString stringWithFormat:]"]) | 
|  | 68 |  | 
|  | 69 | self.runCmd("process continue") | 
|  | 70 |  | 
| Johnny Chen | 2756d60 | 2010-09-16 23:57:33 +0000 | [diff] [blame] | 71 | # Followed by a.out`-[MyString initWithNSString:]. | 
|  | 72 | self.expect("thread backtrace", "Stop at a.out`-[MyString initWithNSString:]", | 
|  | 73 | substrs = ["a.out`-[MyString initWithNSString:]"]) | 
|  | 74 |  | 
|  | 75 | self.runCmd("process continue") | 
|  | 76 |  | 
|  | 77 | # Followed by -[MyString description]. | 
|  | 78 | self.expect("thread backtrace", "Stop at -[MyString description]", | 
|  | 79 | substrs = ["a.out`-[MyString description]"]) | 
|  | 80 |  | 
|  | 81 | self.runCmd("process continue") | 
|  | 82 |  | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 83 | # Followed by -[NSAutoreleasePool release]. | 
|  | 84 | self.expect("thread backtrace", "Stop at -[NSAutoreleasePool release]", | 
|  | 85 | substrs = ["Foundation`-[NSAutoreleasePool release]"]) | 
|  | 86 |  | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 87 | def setUp(self): | 
| Johnny Chen | aadcef5 | 2010-10-14 17:31:24 +0000 | [diff] [blame] | 88 | # Call super's setUp(). | 
|  | 89 | TestBase.setUp(self) | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 90 | # Find the line number to break inside main(). | 
|  | 91 | self.line = line_number('main.m', '// Set break point at this line.') | 
|  | 92 |  | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 93 | def data_type_and_expr_objc(self): | 
|  | 94 | """Lookup objective-c data types and evaluate expressions.""" | 
|  | 95 | exe = os.path.join(os.getcwd(), "a.out") | 
|  | 96 | self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) | 
|  | 97 |  | 
|  | 98 | # Stop at -[MyString description]. | 
|  | 99 | self.expect("breakpoint set -n '-[MyString description]", BREAKPOINT_CREATED, | 
|  | 100 | startstr = "Breakpoint created: 1: name = '-[MyString description]', locations = 1") | 
|  | 101 |  | 
|  | 102 | self.runCmd("run", RUN_SUCCEEDED) | 
|  | 103 |  | 
|  | 104 | # The backtrace should show we stop at -[MyString description]. | 
|  | 105 | self.expect("thread backtrace", "Stop at -[MyString description]", | 
|  | 106 | substrs = ["a.out`-[MyString description]"]) | 
|  | 107 |  | 
|  | 108 | # Lookup objc data type MyString and evaluate some expressions. | 
|  | 109 |  | 
|  | 110 | self.expect("image lookup -t NSString", DATA_TYPES_DISPLAYED_CORRECTLY, | 
| Johnny Chen | 620f9d1 | 2010-09-29 17:50:35 +0000 | [diff] [blame] | 111 | substrs = ['name = "NSString"', | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 112 | 'clang_type = "@interface NSString']) | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 113 |  | 
|  | 114 | self.expect("image lookup -t MyString", DATA_TYPES_DISPLAYED_CORRECTLY, | 
| Johnny Chen | 620f9d1 | 2010-09-29 17:50:35 +0000 | [diff] [blame] | 115 | substrs = ['name = "MyString"', | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 116 | 'clang_type = "@interface MyString', | 
|  | 117 | 'NSString * str;', | 
|  | 118 | 'NSDate * date;']) | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 119 |  | 
| Johnny Chen | 456c9c3 | 2010-10-13 19:22:50 +0000 | [diff] [blame] | 120 | self.expect("frame variable -t -s", VARIABLES_DISPLAYED_CORRECTLY, | 
| Johnny Chen | 7fce877 | 2010-10-01 23:34:28 +0000 | [diff] [blame] | 121 | substrs = ["ARG: (MyString *) self"], | 
|  | 122 | patterns = ["ARG: \(.*\) _cmd", | 
|  | 123 | "(struct objc_selector *)|(SEL)"]) | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 124 |  | 
| Johnny Chen | 07f06c4 | 2010-11-11 19:15:04 +0000 | [diff] [blame^] | 125 | # rdar://problem/8651752 | 
|  | 126 | # don't crash trying to ask clang how many children an empty record has | 
|  | 127 | self.runCmd("frame variable *_cmd") | 
|  | 128 |  | 
| Johnny Chen | 8eb3850 | 2010-09-29 17:58:12 +0000 | [diff] [blame] | 129 | # rdar://problem/8492646 | 
|  | 130 | # test/foundation fails after updating to tot r115023 | 
|  | 131 | # self->str displays nothing as output | 
| Johnny Chen | 456c9c3 | 2010-10-13 19:22:50 +0000 | [diff] [blame] | 132 | self.expect("frame variable -t self->str", VARIABLES_DISPLAYED_CORRECTLY, | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 133 | startstr = "(NSString *) self->str") | 
|  | 134 |  | 
|  | 135 | # rdar://problem/8447030 | 
|  | 136 | # 'frame variable self->date' displays the wrong data member | 
| Johnny Chen | 456c9c3 | 2010-10-13 19:22:50 +0000 | [diff] [blame] | 137 | self.expect("frame variable -t self->date", VARIABLES_DISPLAYED_CORRECTLY, | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 138 | startstr = "(NSDate *) self->date") | 
|  | 139 |  | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 140 | # This should display the str and date member fields as well. | 
| Johnny Chen | 456c9c3 | 2010-10-13 19:22:50 +0000 | [diff] [blame] | 141 | self.expect("frame variable -t *self", VARIABLES_DISPLAYED_CORRECTLY, | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 142 | substrs = ["(MyString *) self", | 
|  | 143 | "(NSString *) str", | 
|  | 144 | "(NSDate *) date"]) | 
|  | 145 |  | 
|  | 146 | # This should fail expectedly. | 
| Johnny Chen | a8807f9 | 2010-10-19 00:52:07 +0000 | [diff] [blame] | 147 | self.expect("expression self->non_existent_member", | 
|  | 148 | COMMAND_FAILED_AS_EXPECTED, error=True, | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 149 | startstr = "error: 'MyString' does not have a member named 'non_existent_member'") | 
|  | 150 |  | 
|  | 151 | # This currently fails. | 
|  | 152 | # rdar://problem/8492646 | 
|  | 153 | # | 
|  | 154 | # Use expression parser. | 
| Johnny Chen | a8807f9 | 2010-10-19 00:52:07 +0000 | [diff] [blame] | 155 | #self.runCmd("expression self->str") | 
|  | 156 | #self.runCmd("expression self->date") | 
| Johnny Chen | 2e566e0 | 2010-09-29 18:05:03 +0000 | [diff] [blame] | 157 |  | 
| Johnny Chen | a8807f9 | 2010-10-19 00:52:07 +0000 | [diff] [blame] | 158 | # (lldb) expression self->str | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 159 | # error: instance variable 'str' is protected | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 160 | # error: 1 errors parsing expression | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 161 | # | 
| Johnny Chen | a8807f9 | 2010-10-19 00:52:07 +0000 | [diff] [blame] | 162 | # (lldb) expression self->date | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 163 | # error: instance variable 'date' is protected | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 164 | # error: 1 errors parsing expression | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 165 | # | 
|  | 166 |  | 
| Johnny Chen | 7987c61 | 2010-10-15 19:29:15 +0000 | [diff] [blame] | 167 | self.runCmd("breakpoint delete 1") | 
| Johnny Chen | f8afe89 | 2010-10-12 21:20:11 +0000 | [diff] [blame] | 168 | self.expect("breakpoint set -f main.m -l %d" % self.line, | 
|  | 169 | BREAKPOINT_CREATED, | 
|  | 170 | startstr = "Breakpoint created: 2: file ='main.m', line = %d, locations = 1" % | 
|  | 171 | self.line) | 
|  | 172 | self.runCmd("process continue") | 
|  | 173 |  | 
|  | 174 | # This currently fails. | 
|  | 175 | # rdar://problem/8542091 | 
|  | 176 | # test/foundation: expr -o -- my not working? | 
|  | 177 | # | 
|  | 178 | # Test new feature with r115115: | 
|  | 179 | # Add "-o" option to "expression" which prints the object description if available. | 
| Johnny Chen | a8807f9 | 2010-10-19 00:52:07 +0000 | [diff] [blame] | 180 | self.expect("expression -o -- my", "Object description displayed correctly", | 
| Johnny Chen | 2769a42 | 2010-10-15 23:35:32 +0000 | [diff] [blame] | 181 | patterns = ["Hello from.*a.out.*with timestamp: "]) | 
| Johnny Chen | b330786 | 2010-09-17 22:28:51 +0000 | [diff] [blame] | 182 |  | 
| Johnny Chen | 6c17c08 | 2010-09-16 20:54:06 +0000 | [diff] [blame] | 183 |  | 
|  | 184 | if __name__ == '__main__': | 
|  | 185 | import atexit | 
|  | 186 | lldb.SBDebugger.Initialize() | 
|  | 187 | atexit.register(lambda: lldb.SBDebugger.Terminate()) | 
|  | 188 | unittest2.main() |