1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5package org.mockito.internal.junit.util;
6
7import java.lang.reflect.Field;
8import org.junit.runner.notification.Failure;
9import org.mockito.internal.exceptions.ExceptionIncludingMockitoWarnings;
10
11@Deprecated
12public class JUnitFailureHacker {
13
14    public void appendWarnings(Failure failure, String warnings) {
15        if (isEmpty(warnings)) {
16            return;
17        }
18        //TODO: this has to protect the use in case jUnit changes and this internal state logic fails
19        Throwable throwable = (Throwable) getInternalState(failure, "fThrownException");
20
21        String newMessage = "contains both: actual test failure *and* Mockito warnings.\n" +
22                warnings + "\n *** The actual failure is because of: ***\n";
23
24        ExceptionIncludingMockitoWarnings e = new ExceptionIncludingMockitoWarnings(newMessage, throwable);
25        e.setStackTrace(throwable.getStackTrace());
26        setInternalState(failure, "fThrownException", e);
27    }
28
29    private boolean isEmpty(String warnings) {
30        return warnings == null || "".equals(warnings); // isEmpty() is in JDK 6+
31    }
32
33    private static Object getInternalState(Object target, String field) {
34        Class<?> c = target.getClass();
35        try {
36            Field f = getFieldFromHierarchy(c, field);
37            f.setAccessible(true);
38            return f.get(target);
39        } catch (Exception e) {
40            throw new RuntimeException("Unable to get internal state on a private field. Please report to mockito mailing list.", e);
41        }
42    }
43
44    private static void setInternalState(Object target, String field, Object value) {
45        Class<?> c = target.getClass();
46        try {
47            Field f = getFieldFromHierarchy(c, field);
48            f.setAccessible(true);
49            f.set(target, value);
50        } catch (Exception e) {
51            throw new RuntimeException("Unable to set internal state on a private field. Please report to mockito mailing list.", e);
52        }
53    }
54
55    private static Field getFieldFromHierarchy(Class<?> clazz, String field) {
56        Field f = getField(clazz, field);
57        while (f == null && clazz != Object.class) {
58            clazz = clazz.getSuperclass();
59            f = getField(clazz, field);
60        }
61        if (f == null) {
62            throw new RuntimeException(
63                    "You want me to get this field: '" + field +
64                            "' on this class: '" + clazz.getSimpleName() +
65                            "' but this field is not declared within the hierarchy of this class!");
66        }
67        return f;
68    }
69
70    private static Field getField(Class<?> clazz, String field) {
71        try {
72            return clazz.getDeclaredField(field);
73        } catch (NoSuchFieldException e) {
74            return null;
75        }
76    }
77}
78