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