1 /******************************************************************************* 2 * Copyright (c) Mar 12, 2016 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.jdt.debug.tests.variables; 15 16 import org.eclipse.debug.core.model.IValue; 17 import org.eclipse.debug.ui.IValueDetailListener; 18 import org.eclipse.jdt.core.IJavaProject; 19 import org.eclipse.jdt.core.Signature; 20 import org.eclipse.jdt.debug.core.IJavaThread; 21 import org.eclipse.jdt.debug.core.IJavaValue; 22 import org.eclipse.jdt.debug.core.IJavaVariable; 23 import org.eclipse.jdt.debug.tests.AbstractDebugTest; 24 import org.eclipse.jdt.internal.debug.ui.DetailFormatter; 25 import org.eclipse.jdt.internal.debug.ui.JavaDetailFormattersManager; 26 27 /** 28 * Tests detail formatters 29 * 30 * @since 3.8.100 31 */ 32 public class DetailFormatterTests extends AbstractDebugTest { 33 34 class TestListener implements IValueDetailListener { 35 IValue value; 36 String result; 37 38 @Override detailComputed(IValue value, String result)39 public void detailComputed(IValue value, String result) { 40 this.value = value; 41 this.result = result; 42 } 43 reset()44 void reset() { 45 value = null; 46 result = null; 47 } 48 } 49 50 TestListener fListener = new TestListener(); 51 52 /** 53 * @param name 54 */ DetailFormatterTests(String name)55 public DetailFormatterTests(String name) { 56 super(name); 57 } 58 59 @Override getProjectContext()60 protected IJavaProject getProjectContext() { 61 return get15Project(); 62 } 63 64 @Override tearDown()65 protected void tearDown() throws Exception { 66 fListener.reset(); 67 super.tearDown(); 68 } 69 70 /** 71 * Tests a detail formatter made from a large compound expression 72 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028 73 * @throws Exception 74 */ testCompoundDetails1()75 public void testCompoundDetails1() throws Exception { 76 IJavaThread thread = null; 77 DetailFormatter formatter = null; 78 JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault(); 79 try { 80 String typename = "a.b.c.bug403028"; 81 createLineBreakpoint(10, typename); 82 thread = launchToBreakpoint(typename); 83 assertNotNull("The program did not suspend", thread); 84 String snippet = "StringBuilder buf = new StringBuilder();\n" 85 + "buf.append(\"{\");\n" 86 + "Iterator i = this.entrySet().iterator();\n" 87 + "boolean hasNext = i.hasNext();\n" 88 + "while (hasNext) {\n" 89 + " Entry e = (Entry) (i.next());\n" 90 + " Object key = e.getKey();\n" 91 + " Object value = e.getValue();\n" 92 + " buf.append((key == this ? \"(this Map)\" : key) + \"=\" + \n" 93 + " (value == this ? \"(this Map)\": value));\n" 94 + " hasNext = i.hasNext();\n" 95 + " if (hasNext)\n" 96 + " buf.append(\"\n,\");\n" 97 + "}\n" 98 + "buf.append(\"}\");\n" 99 + "return buf.toString();"; 100 formatter = new DetailFormatter("java.util.HashMap", snippet, true); 101 jdfm.setAssociatedDetailFormatter(formatter); 102 IJavaVariable var = thread.findVariable("map"); 103 assertNotNull("the variable 'map' must exist in the frame", var); 104 jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener); 105 long timeout = System.currentTimeMillis()+5000; 106 while(fListener.value == null && System.currentTimeMillis() < timeout) { 107 Thread.sleep(100); 108 } 109 assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value); 110 assertTrue("The map should be an instance of java.util.LinkedHashMap", 111 Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap")); 112 assertNotNull("The computed value of the detail should not be null", fListener.result); 113 } 114 finally { 115 jdfm.removeAssociatedDetailFormatter(formatter); 116 terminateAndRemove(thread); 117 removeAllBreakpoints(); 118 } 119 } 120 121 /** 122 * Tests a detail formatter made from a small compound expression 123 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028 124 * @throws Exception 125 */ testCompoundDetails2()126 public void testCompoundDetails2() throws Exception { 127 IJavaThread thread = null; 128 DetailFormatter formatter = null; 129 JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault(); 130 try { 131 String typename = "a.b.c.bug403028"; 132 createLineBreakpoint(10, typename); 133 thread = launchToBreakpoint(typename); 134 assertNotNull("The program did not suspend", thread); 135 String snippet = "StringBuilder buf = new StringBuilder();\n" 136 + "buf.append(this);\n" 137 + "return buf.toString();"; 138 formatter = new DetailFormatter("java.util.HashMap", snippet, true); 139 jdfm.setAssociatedDetailFormatter(formatter); 140 IJavaVariable var = thread.findVariable("map"); 141 assertNotNull("the variable 'map' must exist in the frame", var); 142 jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener); 143 long timeout = System.currentTimeMillis()+5000; 144 while(fListener.value == null && System.currentTimeMillis() < timeout) { 145 Thread.sleep(100); 146 } 147 assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value); 148 assertTrue("The map should be an instance of java.util.LinkedHashMap", 149 Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap")); 150 assertNotNull("The computed value of the detail should not be null", fListener.result); 151 } 152 finally { 153 jdfm.removeAssociatedDetailFormatter(formatter); 154 terminateAndRemove(thread); 155 removeAllBreakpoints(); 156 } 157 } 158 159 /** 160 * Tests a detail formatter made from a small compound expression 161 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028 162 * @throws Exception 163 */ testSimpleDetails1()164 public void testSimpleDetails1() throws Exception { 165 IJavaThread thread = null; 166 DetailFormatter formatter = null; 167 JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault(); 168 try { 169 String typename = "a.b.c.bug403028"; 170 createLineBreakpoint(10, typename); 171 thread = launchToBreakpoint(typename); 172 assertNotNull("The program did not suspend", thread); 173 String snippet = "return toString();"; 174 formatter = new DetailFormatter("java.util.HashMap", snippet, true); 175 jdfm.setAssociatedDetailFormatter(formatter); 176 IJavaVariable var = thread.findVariable("map"); 177 assertNotNull("the variable 'map' must exist in the frame", var); 178 jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener); 179 long timeout = System.currentTimeMillis()+5000; 180 while(fListener.value == null && System.currentTimeMillis() < timeout) { 181 Thread.sleep(100); 182 } 183 assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value); 184 assertTrue("The map should be an instance of java.util.LinkedHashMap", 185 Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap")); 186 assertNotNull("The computed value of the detail should not be null", fListener.result); 187 } 188 finally { 189 jdfm.removeAssociatedDetailFormatter(formatter); 190 terminateAndRemove(thread); 191 removeAllBreakpoints(); 192 } 193 } 194 195 /** 196 * Tests a detail formatter made from a small compound expression 197 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028 198 * @throws Exception 199 */ testSimpleDetails2()200 public void testSimpleDetails2() throws Exception { 201 IJavaThread thread = null; 202 DetailFormatter formatter = null; 203 JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault(); 204 try { 205 String typename = "a.b.c.bug403028"; 206 createLineBreakpoint(10, typename); 207 thread = launchToBreakpoint(typename); 208 assertNotNull("The program did not suspend", thread); 209 String snippet = "return \"map test detail formatter [\" + toString() + \"]\";"; 210 formatter = new DetailFormatter("java.util.HashMap", snippet, true); 211 jdfm.setAssociatedDetailFormatter(formatter); 212 IJavaVariable var = thread.findVariable("map"); 213 assertNotNull("the variable 'map' must exist in the frame", var); 214 jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener); 215 long timeout = System.currentTimeMillis()+5000; 216 while(fListener.value == null && System.currentTimeMillis() < timeout) { 217 Thread.sleep(100); 218 } 219 assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value); 220 assertTrue("The map should be an instance of java.util.LinkedHashMap", 221 Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap")); 222 assertNotNull("The computed value of the detail should not be null", fListener.result); 223 } 224 finally { 225 jdfm.removeAssociatedDetailFormatter(formatter); 226 terminateAndRemove(thread); 227 removeAllBreakpoints(); 228 } 229 } 230 231 /** 232 * Tests a detail formatter made from an infix expression 233 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028 234 * @throws Exception 235 */ testInfixDetails1()236 public void testInfixDetails1() throws Exception { 237 IJavaThread thread = null; 238 DetailFormatter formatter = null; 239 JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault(); 240 try { 241 String typename = "a.b.c.bug403028"; 242 createLineBreakpoint(10, typename); 243 thread = launchToBreakpoint(typename); 244 assertNotNull("The program did not suspend", thread); 245 String snippet = "return (true && true || !(false&&true) || !(true==true||true!=true&&true));"; 246 formatter = new DetailFormatter("java.util.HashMap", snippet, true); 247 jdfm.setAssociatedDetailFormatter(formatter); 248 IJavaVariable var = thread.findVariable("map"); 249 assertNotNull("the variable 'map' must exist in the frame", var); 250 jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener); 251 long timeout = System.currentTimeMillis()+5000; 252 while(fListener.value == null && System.currentTimeMillis() < timeout) { 253 Thread.sleep(100); 254 } 255 assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value); 256 assertTrue("The map should be an instance of java.util.LinkedHashMap", 257 Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap")); 258 assertNotNull("The computed value of the detail should not be null", fListener.result); 259 assertTrue("The returned value from (true && true || !(false&&true) || !(true==true||true!=true&&true)) should be true", 260 Boolean.parseBoolean(fListener.result)); 261 } 262 finally { 263 jdfm.removeAssociatedDetailFormatter(formatter); 264 terminateAndRemove(thread); 265 removeAllBreakpoints(); 266 } 267 } 268 269 /** 270 * Tests a detail formatter made from an infix expression 271 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028 272 * @throws Exception 273 */ testInfixDetails2()274 public void testInfixDetails2() throws Exception { 275 IJavaThread thread = null; 276 DetailFormatter formatter = null; 277 JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault(); 278 try { 279 String typename = "a.b.c.bug403028"; 280 createLineBreakpoint(10, typename); 281 thread = launchToBreakpoint(typename); 282 assertNotNull("The program did not suspend", thread); 283 String snippet = "return !true;"; 284 formatter = new DetailFormatter("java.util.HashMap", snippet, true); 285 jdfm.setAssociatedDetailFormatter(formatter); 286 IJavaVariable var = thread.findVariable("map"); 287 assertNotNull("the variable 'map' must exist in the frame", var); 288 jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener); 289 long timeout = System.currentTimeMillis()+5000; 290 while(fListener.value == null && System.currentTimeMillis() < timeout) { 291 Thread.sleep(100); 292 } 293 assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value); 294 assertTrue("The map should be an instance of java.util.LinkedHashMap", 295 Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap")); 296 assertNotNull("The computed value of the detail should not be null", fListener.result); 297 assertFalse("The returned value from !true should be false", Boolean.parseBoolean(fListener.result)); 298 } 299 finally { 300 jdfm.removeAssociatedDetailFormatter(formatter); 301 terminateAndRemove(thread); 302 removeAllBreakpoints(); 303 } 304 } 305 306 /** 307 * Tests a detail formatter made from an infix expression 308 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028 309 * @throws Exception 310 */ testInfixDetails3()311 public void testInfixDetails3() throws Exception { 312 IJavaThread thread = null; 313 DetailFormatter formatter = null; 314 JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault(); 315 try { 316 String typename = "a.b.c.bug403028"; 317 createLineBreakpoint(10, typename); 318 thread = launchToBreakpoint(typename); 319 assertNotNull("The program did not suspend", thread); 320 String snippet = "return !(true==true||true!=true&&true);"; 321 formatter = new DetailFormatter("java.util.HashMap", snippet, true); 322 jdfm.setAssociatedDetailFormatter(formatter); 323 IJavaVariable var = thread.findVariable("map"); 324 assertNotNull("the variable 'map' must exist in the frame", var); 325 jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener); 326 long timeout = System.currentTimeMillis()+5000; 327 while(fListener.value == null && System.currentTimeMillis() < timeout) { 328 Thread.sleep(100); 329 } 330 assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value); 331 assertTrue("The map should be an instance of java.util.LinkedHashMap", 332 Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap")); 333 assertNotNull("The computed value of the detail should not be null", fListener.result); 334 assertFalse("The returned value from !(true==true||true!=true&&true) should be false", Boolean.parseBoolean(fListener.result)); 335 } 336 finally { 337 jdfm.removeAssociatedDetailFormatter(formatter); 338 terminateAndRemove(thread); 339 removeAllBreakpoints(); 340 } 341 } 342 343 /** 344 * Tests a detail formatter made from an collection with no type arguments 345 * 346 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=484686 347 * @throws Exception 348 */ testHoverWithNoTypeArguments()349 public void testHoverWithNoTypeArguments() throws Exception { 350 IJavaThread thread = null; 351 DetailFormatter formatter = null; 352 JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault(); 353 try { 354 String typename = "a.b.c.bug484686"; 355 createLineBreakpoint(8, typename); 356 thread = launchToBreakpoint(typename); 357 assertNotNull("The program did not suspend", thread); 358 String snippet = "StringBuilder sb = new StringBuilder();\n" + "for (Object obj : this) { \n" + "sb.append(obj).append(\"\\n\"); }\n" 359 + "return sb.toString();"; 360 formatter = new DetailFormatter("java.util.Collection", snippet, true); 361 jdfm.setAssociatedDetailFormatter(formatter); 362 IJavaVariable var = thread.findVariable("coll"); 363 assertNotNull("the variable 'coll' must exist in the frame", var); 364 jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener); 365 long timeout = System.currentTimeMillis() + 5000; 366 while (fListener.value == null && System.currentTimeMillis() < timeout) { 367 Thread.sleep(100); 368 } 369 assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value); 370 assertNotNull("The computed value of the detail should not be null", fListener.result); 371 } 372 finally { 373 jdfm.removeAssociatedDetailFormatter(formatter); 374 terminateAndRemove(thread); 375 removeAllBreakpoints(); 376 } 377 } 378 } 379