/* * JBoss, Home of Professional Open Source * Copyright 2010-2016, Red Hat, Inc. and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.richfaces.tests.metamer; import static org.testng.Assert.assertEquals; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.richfaces.tests.metamer.bean.rich.RichTreeModelRecursiveAdaptorBean; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.io.ByteStreams; /** * @author <a href="mailto:lfryc@redhat.com">Lukas Fryc</a> * @version $Revision: 22848 $ */ public class TestRichTreeModelRecursiveAdaptorBeanSerialization { private PrintStream sysout; private Set<Integer> notEquals = new TreeSet<Integer>(); @BeforeClass public void redirectOut() { sysout = System.out; System.setOut(new PrintStream(ByteStreams.nullOutputStream())); } @AfterClass(alwaysRun = true) public void returnOut() { System.setOut(sysout); } @Test public void testBeanSerialization() throws IOException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException { RichTreeModelRecursiveAdaptorBean bean = new RichTreeModelRecursiveAdaptorBean(); bean.init(); Object obj1 = bean; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream); outputStream.writeObject(obj1); byte[] bytes = byteArrayOutputStream.toByteArray(); ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bytes)); Object obj2 = inputStream.readObject(); verifyEqualsDeeply(obj1, obj2); } public void verifyEqualsDeeply(Object obj1, Object obj2) throws IllegalArgumentException, IllegalAccessException { if (obj1 == null) { if (obj2 == null) { return; } throw new AssertionError("obj1 is null, but obj2 is not null"); } Class<?> classO = obj1.getClass(); assertEquals(obj2.getClass(), classO, "Both objects should be instances of the same class"); if (obj1.equals(obj2)) { return; } int hash = cohash(obj1, obj2); if (notEquals.contains(hash)) { return; } notEquals.add(hash); if (Collection.class.isAssignableFrom(classO)) { Collection<?> col1 = (Collection<?>) obj1; Collection<?> col2 = (Collection<?>) obj2; assertEquals(col1.toArray(new Object[col1.size()]), col2.toArray(new Object[col2.size()])); } else if (Map.class.isAssignableFrom(classO)) { Map map1 = (Map) obj1; Map map2 = (Map) obj2; Object[] array1 = map1.keySet().toArray(new Object[map1.size()]); Arrays.sort(array1, new HashCodeComparator()); Object[] array2 = map2.keySet().toArray(new Object[map2.size()]); Arrays.sort(array2, new HashCodeComparator()); assertEquals(array1, array2); array1 = map1.values().toArray(new Object[map1.size()]); Arrays.sort(array1, new HashCodeComparator()); array2 = map2.values().toArray(new Object[map2.size()]); Arrays.sort(array2, new HashCodeComparator()); assertEquals(array1, array2); } else { for (Field field : classO.getDeclaredFields()) { if (Modifier.isStatic(field.getModifiers())) { continue; } if (Modifier.isTransient(field.getModifiers())) { continue; } boolean accessible = field.isAccessible(); if (!accessible) { field.setAccessible(true); } Object nObj1 = field.get(obj1); Object nObj2 = field.get(obj2); if (!accessible) { field.setAccessible(false); } verifyEqualsDeeply(nObj1, nObj2); } } } public int cohash(Object obj1, Object obj2) { return 17 * obj1.hashCode() * obj2.hashCode() + obj2.hashCode() + 11; } public class HashCodeComparator implements Comparator<Object> { @Override public int compare(Object o1, Object o2) { return o1.hashCode() - o2.hashCode(); } } }