Home | History | Annotate | Download | only in targets
      1 /*******************************************************************************
      2  * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *    Evgeny Mandrikov - initial API and implementation
     10  *
     11  *******************************************************************************/
     12 package org.jacoco.core.test.filter.targets;
     13 
     14 import static org.jacoco.core.test.validation.targets.Stubs.f;
     15 import static org.jacoco.core.test.validation.targets.Stubs.nop;
     16 
     17 import java.io.Closeable;
     18 import java.io.IOException;
     19 
     20 /**
     21  * This test target is a try-with-resources statement.
     22  */
     23 public class TryWithResources {
     24 
     25 	private static class Resource implements Closeable {
     26 		@Override
     27 		public void close() {
     28 		}
     29 	}
     30 
     31 	/**
     32 	 * Closing performed using {@link org.objectweb.asm.Opcodes#INVOKEVIRTUAL}
     33 	 * or {@link org.objectweb.asm.Opcodes#INVOKEINTERFACE} depending on a class
     34 	 * of resource.
     35 	 */
     36 	private static Object test() throws Exception {
     37 		nop(); // $line-test.before$
     38 		try ( // $line-test.try$
     39 				Resource r1 = new Resource(); // $line-test.open1$
     40 				Closeable r2 = new Resource(); // $line-test.open2$
     41 				AutoCloseable r3 = new Resource() // $line-test.open3$
     42 		) {
     43 			return read(r1, r2, r3); // $line-test.body$
     44 		} // $line-test.close$
     45 		catch (Exception e) {
     46 			nop(); // $line-test.catch$
     47 			throw e;
     48 		} finally {
     49 			nop(); // $line-test.finally$
     50 		}
     51 	}
     52 
     53 	private static void test2() throws Exception {
     54 		nop(); // $line-test2.before$
     55 		try ( // $line-test2.try$
     56 				Resource r1 = new Resource(); // $line-test2.open1$
     57 				Closeable r2 = new Resource(); // $line-test2.open2$
     58 				AutoCloseable r3 = new Resource() // $line-test2.open3$
     59 		) {
     60 			read(r1, r2, r3); // $line-test2.body$
     61 		} // $line-test2.close$
     62 		catch (Exception e) {
     63 			nop(); // $line-test2.catch$
     64 		} finally {
     65 			nop(); // $line-test2.finally$
     66 		}
     67 		nop(); // $line-test2.after$
     68 	}
     69 
     70 	private static Object returnInBody() throws IOException {
     71 		try ( // $line-returnInBody.try$
     72 				Closeable r = new Resource() // $line-returnInBody.open$
     73 		) {
     74 			return read(r); // $line-returnInBody.return$
     75 		} // $line-returnInBody.close$
     76 	}
     77 
     78 	private static void nested() {
     79 		try ( // $line-nested.try1$
     80 				Resource r1 = new Resource() // $line-nested.open1$
     81 		) {
     82 
     83 			try ( // $line-nested.try2$
     84 					Resource r2 = new Resource() // $line-nested.open2$
     85 			) {
     86 				nop(r1.toString() + r2.toString()); // $line-nested.body$
     87 			} // $line-nested.close2$
     88 			catch (Exception e) {
     89 				nop(); // $line-nested.catch2$
     90 			} finally {
     91 				nop(); // $line-nested.finally2$
     92 			}
     93 
     94 		} // $line-nested.close1$
     95 		catch (Exception e) {
     96 			nop(); // $line-nested.catch1$
     97 		} finally {
     98 
     99 			try ( // $line-nested.try3$
    100 					Resource r2 = new Resource() // $line-nested.open3$
    101 			) {
    102 				nop(r2); // $line-nested.body3$
    103 			} // $line-nested.close3$
    104 			catch (Exception e) {
    105 				nop(); // $line-nested.catch3$
    106 			} finally {
    107 				nop(); // $line-nested.finally3$
    108 			}
    109 
    110 		}
    111 	}
    112 
    113 	/**
    114 	 * In this case bytecode will contain 3 copies of <code>finally</code>
    115 	 * block, each containing 2 branches, resulting in 6 branches in total. One
    116 	 * could think that this is artifact of try-with-resources, but the same
    117 	 * happens without it.
    118 	 */
    119 	private static Object returnInCatch() {
    120 		try ( // $line-returnInCatch.try1$
    121 				Resource r = new Resource() // $line-returnInCatch.open$
    122 		) {
    123 			read(r);
    124 		} // $line-returnInCatch.close$
    125 		catch (Exception e) {
    126 			return null;
    127 		} finally {
    128 			nop(!f()); // $line-returnInCatch.finally1$
    129 		}
    130 
    131 		try { // $line-returnInCatch.try2$
    132 			read(new Resource());
    133 		} catch (Exception e) {
    134 			return null;
    135 		} finally {
    136 			nop(!f()); // $line-returnInCatch.finally2$
    137 		}
    138 
    139 		return null;
    140 	}
    141 
    142 	private static Object read(Object r1, Object r2, Object r3) {
    143 		return r1.toString() + r2.toString() + r3.toString();
    144 	}
    145 
    146 	private static Object read(Object r1) {
    147 		return r1.toString();
    148 	}
    149 
    150 	public static void main(String[] args) throws Exception {
    151 		test();
    152 		test2();
    153 		returnInBody();
    154 		nested();
    155 
    156 		returnInCatch();
    157 
    158 		empty();
    159 		handwritten();
    160 	}
    161 
    162 	/*
    163 	 * Corner cases
    164 	 */
    165 
    166 	private static void empty() throws Exception {
    167 		try ( // $line-empty.try$
    168 				Closeable r = new Resource() // $line-empty.open$
    169 		) {
    170 		} // $line-empty.close$
    171 	}
    172 
    173 	private static void handwritten() throws IOException {
    174 		Closeable r = new Resource();
    175 		Throwable primaryExc = null;
    176 		try {
    177 			nop(r);
    178 		} catch (Throwable t) {
    179 			primaryExc = t;
    180 			throw t;
    181 		} finally {
    182 			if (r != null) { // $line-handwritten$
    183 				if (primaryExc != null) {
    184 					try {
    185 						r.close();
    186 					} catch (Throwable suppressedExc) {
    187 						primaryExc.addSuppressed(suppressedExc);
    188 					}
    189 				} else {
    190 					r.close();
    191 				}
    192 			}
    193 		}
    194 	}
    195 
    196 	private static void throwInBody() throws IOException {
    197 		try ( // $line-throwInBody.try$
    198 				Closeable r = new Resource()) {
    199 			nop(r);
    200 			throw new RuntimeException();
    201 		} // $line-throwInBody.close$
    202 	}
    203 
    204 }
    205