f80f2332a5ded9e48d3a48bec7edfab5707772d8
[mdsal.git] / binding / mdsal-binding-test-utils / src / main / java / org / opendaylight / mdsal / binding / testutils / AssertDataObjects.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.testutils;
9
10 import ch.vorburger.xtendbeans.AssertBeans;
11 import com.github.difflib.algorithm.DiffException;
12 import java.util.Objects;
13 import org.junit.ComparisonFailure;
14 import org.opendaylight.yangtools.yang.binding.DataObject;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17
18 /**
19  * Assertion utilities for YANG {@link DataObject}s.
20  *
21  * <p>This compares two {@link DataObject}s using their {@link Object#equals(Object)} methods, but
22  * prepares a view of their contents in text form which allows easy comparison of the expected and
23  * actual values using the thrown {@link ComparisonFailure}.
24  *
25  * <p>The syntax used happens to be valid Xtend code, and as such could be directly copy/pasted
26  * into an *.xtend source file of an expected object definition.  This is optional though; this
27  * utility can very well be used with any object, not necessarily created by Xtend source code.
28  *
29  * <p>This also works for any Java object that is not a {@link DataObject},
30  * like the {@link AssertBeans} which this is based upon.
31  *
32  * @see AssertBeans for more background
33  *
34  * @author Michael Vorburger
35  */
36 public final class AssertDataObjects {
37
38     private static final Logger LOG = LoggerFactory.getLogger(AssertDataObjects.class);
39
40     private static final XtendYangBeanGenerator GENERATOR = new XtendYangBeanGenerator();
41
42     private AssertDataObjects() {
43     }
44
45     /**
46      * Assert that an actual YANG DataObject (DataContainer) is equals to an expected one.
47      *
48      * <p>The argument types are intentionally of type Object instead of YANG DataContainer or DataObject.
49      * This is important so that this can be directly used on e.g. a List or Map etc. of DataObjects.
50      *
51      * @param expected the expected object
52      * @param actual the actual object to check against <code>expected</code>
53      *
54      * @see AssertBeans#assertEqualBeans(Object, Object)
55      */
56     public static void assertEqualBeans(Object expected, Object actual) throws ComparisonFailure {
57         if (!Objects.equals(expected, actual)) {
58             String expectedText = GENERATOR.getExpression(expected);
59             assertEqualByText(expectedText, actual);
60             throw new ComparisonFailure(
61                     "Expected and actual beans are not equal according to their equals() implementations, but their "
62                             + "textual representations are identical (there might be a bug in XtendBeans)",
63                     expected.toString(), actual.toString());
64         }
65     }
66
67     // package local method used only in the self tests of this utility (not intended for usage by client code)
68     static void assertEqualByText(String expectedText, Object actual) throws ComparisonFailure {
69         String actualText = GENERATOR.getExpression(actual);
70         if (!expectedText.equals(actualText)) {
71             try {
72                 String diff = DiffUtil.diff(expectedText, actualText);
73                 LOG.warn("diff for ComparisonFailure about to be thrown:\n{}", diff);
74             } catch (DiffException e) {
75                 LOG.error("Error generating a comparison diff", e);
76             }
77             throw new ComparisonFailure("Expected and actual beans do not match", expectedText, actualText);
78         }
79     }
80
81 }