blob: 3ac9ac3988586da574e1682687ccba39c4a4f54e [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Pavlin Radoslavovd26f57a2014-10-23 17:19:45 -070019package org.onlab.junit;
Jonathan Hart20d8e512014-10-16 11:05:52 -070020
21import java.lang.reflect.Constructor;
22import java.lang.reflect.Field;
23import java.lang.reflect.InvocationTargetException;
24import java.lang.reflect.Method;
25
26
27/**
28 * Utilities for testing.
29 */
30public final class TestUtils {
31
32 /**
33 * Sets the field, bypassing scope restriction.
34 *
35 * @param subject Object where the field belongs
36 * @param fieldName name of the field to set
37 * @param value value to set to the field.
38 * @param <T> subject type
39 * @param <U> value type
40 * @throws TestUtilsException if there are reflection errors while setting
41 * the field
42 */
43 public static <T, U> void setField(T subject, String fieldName, U value)
44 throws TestUtilsException {
45 @SuppressWarnings("unchecked")
46 Class<T> clazz = (Class<T>) subject.getClass();
47 try {
48 Field field = clazz.getDeclaredField(fieldName);
49 field.setAccessible(true);
50 field.set(subject, value);
51 } catch (NoSuchFieldException | SecurityException |
52 IllegalArgumentException | IllegalAccessException e) {
53 throw new TestUtilsException("setField failed", e);
54 }
55 }
56
57 /**
58 * Gets the field, bypassing scope restriction.
59 *
60 * @param subject Object where the field belongs
61 * @param fieldName name of the field to get
62 * @return value of the field.
63 * @param <T> subject type
64 * @param <U> field value type
65 * @throws TestUtilsException if there are reflection errors while getting
66 * the field
67 */
68 public static <T, U> U getField(T subject, String fieldName)
69 throws TestUtilsException {
70 try {
71 @SuppressWarnings("unchecked")
72 Class<T> clazz = (Class<T>) subject.getClass();
73 Field field = clazz.getDeclaredField(fieldName);
74 field.setAccessible(true);
75
76 @SuppressWarnings("unchecked")
77 U result = (U) field.get(subject);
78 return result;
79 } catch (NoSuchFieldException | SecurityException |
80 IllegalArgumentException | IllegalAccessException e) {
81 throw new TestUtilsException("getField failed", e);
82 }
83 }
84
85 /**
86 * Calls the method, bypassing scope restriction.
87 *
88 * @param subject Object where the method belongs
89 * @param methodName name of the method to call
90 * @param paramTypes formal parameter type array
91 * @param args arguments
92 * @return return value or null if void
93 * @param <T> subject type
94 * @param <U> return value type
95 * @throws TestUtilsException if there are reflection errors while calling
96 * the method
97 */
98 public static <T, U> U callMethod(T subject, String methodName,
99 Class<?>[] paramTypes, Object...args) throws TestUtilsException {
100
101 try {
102 @SuppressWarnings("unchecked")
103 Class<T> clazz = (Class<T>) subject.getClass();
104 final Method method;
105 if (paramTypes == null || paramTypes.length == 0) {
106 method = clazz.getDeclaredMethod(methodName);
107 } else {
108 method = clazz.getDeclaredMethod(methodName, paramTypes);
109 }
110 method.setAccessible(true);
111
112 @SuppressWarnings("unchecked")
113 U result = (U) method.invoke(subject, args);
114 return result;
115 } catch (NoSuchMethodException | SecurityException |
116 IllegalAccessException | IllegalArgumentException |
117 InvocationTargetException e) {
118 throw new TestUtilsException("callMethod failed", e);
119 }
120 }
121
122 /**
123 * Calls the method, bypassing scope restriction.
124 *
125 * @param subject Object where the method belongs
126 * @param methodName name of the method to call
127 * @param paramType formal parameter type
128 * @param arg argument
129 * @return return value or null if void
130 * @param <T> subject type
131 * @param <U> return value type
132 * @throws TestUtilsException if there are reflection errors while calling
133 * the method
134 */
135 public static <T, U> U callMethod(T subject, String methodName,
136 Class<?> paramType, Object arg) throws TestUtilsException {
137 return callMethod(subject, methodName, new Class<?>[]{paramType}, arg);
138 }
139
140 /**
141 * Triggers an allocation of an object of type <T> and forces a call to
142 * the private constructor.
143 *
144 * @param constructor Constructor to call
145 * @param <T> type of the object to create
146 * @return created object of type <T>
147 * @throws TestUtilsException if there are reflection errors while calling
148 * the constructor
149 */
150 public static <T> T callConstructor(Constructor<T> constructor)
151 throws TestUtilsException {
152 try {
153 constructor.setAccessible(true);
154 return constructor.newInstance();
155 } catch (InstantiationException | IllegalAccessException |
156 InvocationTargetException error) {
157 throw new TestUtilsException("callConstructor failed", error);
158 }
159 }
160
161 /**
162 * Avoid instantiation.
163 */
164 private TestUtils() {}
165
166 /**
167 * Exception that can be thrown if problems are encountered while executing
168 * the utility method. These are usually problems accessing fields/methods
169 * through reflection. The original exception can be found by examining the
170 * cause.
171 */
172 public static class TestUtilsException extends Exception {
173
174 private static final long serialVersionUID = 1L;
175
176 /**
177 * Constructs a new exception with the specified detail message and
178 * cause.
179 *
180 * @param message the detail message
181 * @param cause the original cause of this exception
182 */
183 public TestUtilsException(String message, Throwable cause) {
184 super(message, cause);
185 }
186 }
187}