/* * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sf.json.test; import java.util.Iterator; import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.lang.StringUtils; import junit.framework.Assert; import net.sf.ezmorph.Morpher; import net.sf.ezmorph.object.IdentityObjectMorpher; import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONException; import net.sf.json.JSONFunction; import net.sf.json.JSONNull; import net.sf.json.JSONObject; import net.sf.json.JSONSerializer; import net.sf.json.util.JSONUtils; /** * Provides assertions on equality for JSON strings and JSON types. * * @author Andres Almiray <aalmiray@users.sourceforge.net> */ public class JSONAssert extends Assert { /** * Asserts that two JSON values are equal. */ public static void assertEquals( JSON expected, JSON actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONArrays are equal. */ public static void assertEquals( JSONArray expected, JSONArray actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONArrays are equal. */ public static void assertEquals( JSONArray expected, String actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONFunctions are equal. */ public static void assertEquals( JSONFunction expected, String actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONNulls are equal. */ public static void assertEquals( JSONNull expected, String actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONObjects are equal. */ public static void assertEquals( JSONObject expected, JSONObject actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONObjects are equal. */ public static void assertEquals( JSONObject expected, String actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSON values are equal. */ public static void assertEquals( String message, JSON expected, JSON actual ) { String header = message == null ? "" : message + ": "; if( expected == null ){ fail( header + "expected was null" ); } if( actual == null ){ fail( header + "actual was null" ); } if( expected == actual || expected.equals( actual ) ){ return; } if( expected instanceof JSONArray ){ if( actual instanceof JSONArray ){ assertEquals( header, (JSONArray) expected, (JSONArray) actual ); }else{ fail( header + "actual is not a JSONArray" ); } }else if( expected instanceof JSONObject ){ if( actual instanceof JSONObject ){ assertEquals( header, (JSONObject) expected, (JSONObject) actual ); }else{ fail( header + "actual is not a JSONObject" ); } }else if( expected instanceof JSONNull ){ if( actual instanceof JSONNull ){ return; }else{ fail( header + "actual is not a JSONNull" ); } } } /** * Asserts that two JSONArrays are equal. */ public static void assertEquals( String expected, JSONArray actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONArrays are equal. */ public static void assertEquals( String message, JSONArray expected, JSONArray actual ) { String header = message == null ? "" : message + ": "; if( expected == null ){ fail( header + "expected array was null" ); } if( actual == null ){ fail( header + "actual array was null" ); } if( expected == actual || expected.equals( actual ) ){ return; } if( actual.size() != expected.size() ){ fail( header + "arrays sizes differed, expected.length()=" + expected.size() + " actual.length()=" + actual.size() ); } int max = expected.size(); for( int i = 0; i < max; i++ ){ Object o1 = expected.get( i ); Object o2 = actual.get( i ); // handle nulls if( JSONNull.getInstance() .equals( o1 ) ){ if( JSONNull.getInstance() .equals( o2 ) ){ continue; }else{ fail( header + "arrays first differed at element [" + i + "];" ); } }else{ if( JSONNull.getInstance() .equals( o2 ) ){ fail( header + "arrays first differed at element [" + i + "];" ); } } if( o1 instanceof JSONArray && o2 instanceof JSONArray ){ JSONArray e = (JSONArray) o1; JSONArray a = (JSONArray) o2; assertEquals( header + "arrays first differed at element " + i + ";", e, a ); }else{ if( o1 instanceof String && o2 instanceof JSONFunction ){ assertEquals( header + "arrays first differed at element [" + i + "];", (String) o1, (JSONFunction) o2 ); }else if( o1 instanceof JSONFunction && o2 instanceof String ){ assertEquals( header + "arrays first differed at element [" + i + "];", (JSONFunction) o1, (String) o2 ); }else if( o1 instanceof JSONObject && o2 instanceof JSONObject ){ assertEquals( header + "arrays first differed at element [" + i + "];", (JSONObject) o1, (JSONObject) o2 ); }else if( o1 instanceof JSONArray && o2 instanceof JSONArray ){ assertEquals( header + "arrays first differed at element [" + i + "];", (JSONArray) o1, (JSONArray) o2 ); }else if( o1 instanceof JSONFunction && o2 instanceof JSONFunction ){ assertEquals( header + "arrays first differed at element [" + i + "];", (JSONFunction) o1, (JSONFunction) o2 ); }else{ if( o1 instanceof String ){ assertEquals( header + "arrays first differed at element [" + i + "];", (String) o1, String.valueOf( o2 ) ); }else if( o2 instanceof String ){ assertEquals( header + "arrays first differed at element [" + i + "];", String.valueOf( o1 ), (String) o2 ); }else{ Morpher m1 = JSONUtils.getMorpherRegistry() .getMorpherFor( o1.getClass() ); Morpher m2 = JSONUtils.getMorpherRegistry() .getMorpherFor( o2.getClass() ); if( m1 != null && m1 != IdentityObjectMorpher.getInstance() ){ assertEquals( header + "arrays first differed at element [" + i + "];", o1, JSONUtils.getMorpherRegistry() .morph( o1.getClass(), o2 ) ); }else if( m2 != null && m2 != IdentityObjectMorpher.getInstance() ){ assertEquals( header + "arrays first differed at element [" + i + "];", JSONUtils.getMorpherRegistry() .morph( o1.getClass(), o1 ), o2 ); }else{ assertEquals( header + "arrays first differed at element [" + i + "];", o1, o2 ); } } } } } } /** * Asserts that two JSONArrays are equal. */ public static void assertEquals( String message, JSONArray expected, String actual ) { try{ assertEquals( message, expected, JSONArray.fromObject( actual ) ); }catch( JSONException e ){ String header = message == null ? "" : message + ": "; fail( header + "actual is not a JSONArray" ); } } /** * Asserts that two JSONFunctions are equal. */ public static void assertEquals( String expected, JSONFunction actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONFunctions are equal. */ public static void assertEquals( String message, JSONFunction expected, String actual ) { String header = message == null ? "" : message + ": "; if( expected == null ){ fail( header + "expected function was null" ); } if( actual == null ){ fail( header + "actual string was null" ); } try{ assertEquals( header, expected, JSONFunction.parse( actual ) ); }catch( JSONException jsone ){ fail( header + "'" + actual + "' is not a function" ); } } /** * Asserts that two JSONNulls are equal. */ public static void assertEquals( String expected, JSONNull actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONNulls are equal. */ public static void assertEquals( String message, JSONNull expected, String actual ) { String header = message == null ? "" : message + ": "; if( actual == null ){ fail( header + "actual string was null" ); }else if( expected == null ){ assertEquals( header, "null", actual ); }else{ assertEquals( header, expected.toString(), actual ); } } /** * Asserts that two JSONObjects are equal. */ public static void assertEquals( String expected, JSONObject actual ) { assertEquals( null, expected, actual ); } /** * Asserts that two JSONObjects are equal. */ public static void assertEquals( String message, JSONObject expected, JSONObject actual ) { String header = message == null ? "" : message + ": "; if( expected == null ){ fail( header + "expected object was null" ); } if( actual == null ){ fail( header + "actual object was null" ); } if( expected == actual /* || expected.equals( actual ) */){ return; } if( expected.isNullObject() ){ if( actual.isNullObject() ){ return; }else{ fail( header + "actual is not a null JSONObject" ); } }else{ if( actual.isNullObject() ){ fail( header + "actual is a null JSONObject" ); } } if( expected.names().size() != actual.names().size() ){ fail( header + missingAndUnexpectedNames( expected, actual )); } for( Iterator keys = expected.keys(); keys.hasNext(); ){ String key = (String) keys.next(); Object o1 = expected.opt( key ); Object o2 = actual.opt( key ); if( JSONNull.getInstance() .equals( o1 ) ){ if( JSONNull.getInstance() .equals( o2 ) ){ continue; }else{ fail( header + "objects differed at key [" + key + "];" ); } }else{ if( JSONNull.getInstance() .equals( o2 ) ){ fail( header + "objects differed at key [" + key + "];" ); } } if( o1 instanceof String && o2 instanceof JSONFunction ){ assertEquals( header + "objects differed at key [" + key + "];", (String) o1, (JSONFunction) o2 ); }else if( o1 instanceof JSONFunction && o2 instanceof String ){ assertEquals( header + "objects differed at key [" + key + "];", (JSONFunction) o1, (String) o2 ); }else if( o1 instanceof JSONObject && o2 instanceof JSONObject ){ assertEquals( header + "objects differed at key [" + key + "];", (JSONObject) o1, (JSONObject) o2 ); }else if( o1 instanceof JSONArray && o2 instanceof JSONArray ){ assertEquals( header + "objects differed at key [" + key + "];", (JSONArray) o1, (JSONArray) o2 ); }else if( o1 instanceof JSONFunction && o2 instanceof JSONFunction ){ assertEquals( header + "objects differed at key [" + key + "];", (JSONFunction) o1, (JSONFunction) o2 ); }else{ if( o1 instanceof String ){ assertEquals( header + "objects differed at key [" + key + "];", (String) o1, String.valueOf( o2 ) ); }else if( o2 instanceof String ){ assertEquals( header + "objects differed at key [" + key + "];", String.valueOf( o1 ), (String) o2 ); }else{ Morpher m1 = JSONUtils.getMorpherRegistry() .getMorpherFor( o1.getClass() ); Morpher m2 = JSONUtils.getMorpherRegistry() .getMorpherFor( o2.getClass() ); if( m1 != null && m1 != IdentityObjectMorpher.getInstance() ){ assertEquals( header + "objects differed at key [" + key + "];", o1, JSONUtils.getMorpherRegistry() .morph( o1.getClass(), o2 ) ); }else if( m2 != null && m2 != IdentityObjectMorpher.getInstance() ){ assertEquals( header + "objects differed at key [" + key + "];", JSONUtils.getMorpherRegistry() .morph( o1.getClass(), o1 ), o2 ); }else{ assertEquals( header + "objects differed at key [" + key + "];", o1, o2 ); } } } } } private static String missingAndUnexpectedNames(JSONObject expected, JSONObject actual) { String missingExpectedNames = missingExpectedNames( expected, actual ); String unexpectedNames = unexpectedNames( expected, actual ); if( missingExpectedNames != null && unexpectedNames != null ){ return missingExpectedNames + ", " + unexpectedNames; }else if( missingExpectedNames != null ){ return missingExpectedNames; }else{ return unexpectedNames; } } private static String missingExpectedNames(JSONObject expected, JSONObject actual) { SortedSet keysInExpectedButNotInActual = new TreeSet( expected.keySet() ); keysInExpectedButNotInActual.removeAll( actual.keySet() ); if ( keysInExpectedButNotInActual.isEmpty() ) { return null; } else { return "missing expected names: [" + StringUtils.join( keysInExpectedButNotInActual, ", " ) + "]"; } } private static String unexpectedNames(JSONObject expected, JSONObject actual) { SortedSet keysInActualButNotInExpected = new TreeSet( actual.keySet() ); keysInActualButNotInExpected.removeAll( expected.keySet() ); if ( keysInActualButNotInExpected.isEmpty() ) { return null; } else { return "unexpected names: [" + StringUtils.join( keysInActualButNotInExpected, ", " ) + "]"; } } /** * Asserts that two JSONObjects are equal. */ public static void assertEquals( String message, JSONObject expected, String actual ) { try{ assertEquals( message, expected, JSONObject.fromObject( actual ) ); }catch( JSONException e ){ String header = message == null ? "" : message + ": "; fail( header + "actual is not a JSONObject" ); } } /** * Asserts that two JSONArrays are equal. */ public static void assertEquals( String message, String expected, JSONArray actual ) { try{ assertEquals( message, JSONArray.fromObject( expected ), actual ); }catch( JSONException e ){ String header = message == null ? "" : message + ": "; fail( header + "expected is not a JSONArray" ); } } /** * Asserts that two JSONFunctions are equal. */ public static void assertEquals( String message, String expected, JSONFunction actual ) { String header = message == null ? "" : message + ": "; if( expected == null ){ fail( header + "expected string was null" ); } if( actual == null ){ fail( header + "actual function was null" ); } try{ assertEquals( header, JSONFunction.parse( expected ), actual ); }catch( JSONException jsone ){ fail( header + "'" + expected + "' is not a function" ); } } /** * Asserts that two JSONNulls are equal. */ public static void assertEquals( String message, String expected, JSONNull actual ) { String header = message == null ? "" : message + ": "; if( expected == null ){ fail( header + "expected was null" ); }else if( actual == null ){ assertEquals( header, expected, "null" ); }else{ assertEquals( header, expected, actual.toString() ); } } /** * Asserts that two JSONObjects are equal. */ public static void assertEquals( String message, String expected, JSONObject actual ) { try{ assertEquals( message, JSONObject.fromObject( expected ), actual ); }catch( JSONException e ){ String header = message == null ? "" : message + ": "; fail( header + "expected is not a JSONObject" ); } } /** * Asserts that two JSON strings are equal. */ public static void assertJsonEquals( String expected, String actual ) { assertJsonEquals( null, expected, actual ); } /** * Asserts that two JSON strings are equal. */ public static void assertJsonEquals( String message, String expected, String actual ) { String header = message == null ? "" : message + ": "; if( expected == null ){ fail( header + "expected was null" ); } if( actual == null ){ fail( header + "actual was null" ); } JSON json1 = null; JSON json2 = null; try{ json1 = JSONSerializer.toJSON( expected ); }catch( JSONException jsone ){ fail( header + "expected is not a valid JSON string" ); } try{ json2 = JSONSerializer.toJSON( actual ); }catch( JSONException jsone ){ fail( header + "actual is not a valid JSON string" ); } assertEquals( header, json1, json2 ); } /** * Asserts that a JSON value is not null.<br> * Fails if: * <ul> * <li>JSONNull.getInstance().equals( json )</li> * <li>((JSONObject) json).isNullObject()</li> * </ul> */ public static void assertNotNull( JSON json ) { assertNotNull( null, json ); } /** * Asserts that a JSON value is not null.<br> * Fails if: * <ul> * <li>JSONNull.getInstance().equals( json )</li> * <li>((JSONObject) json).isNullObject()</li> * </ul> */ public static void assertNotNull( String message, JSON json ) { String header = message == null ? "" : message + ": "; if( json instanceof JSONObject ){ assertFalse( header + "Object is null", ((JSONObject) json).isNullObject() ); }else if( JSONNull.getInstance() .equals( json ) ){ fail( header + "Object is null" ); } } /** * Asserts that a JSON value is null.<br> * Fails if: * <ul> * <li>!JSONNull.getInstance().equals( json )</li> * <li>!((JSONObject) json).isNullObject()</li> * </ul> */ public static void assertNull( JSON json ) { assertNull( null, json ); } /** * Asserts that a JSON value is null.<br> * Fails if: * <ul> * <li>!JSONNull.getInstance().equals( json )</li> * <li>!((JSONObject) json).isNullObject()</li> * </ul> */ public static void assertNull( String message, JSON json ) { String header = message == null ? "" : message + ": "; if( json instanceof JSONObject ){ assertTrue( header + "Object is not null", ((JSONObject) json).isNullObject() ); }else if( !JSONNull.getInstance() .equals( json ) ){ fail( header + "Object is not null" ); } } }