--- /dev/null
+/*
+ * Copyright 2005-2010 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 org.wamblee.reflection;
+
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.derby.impl.sql.execute.OnceResultSet;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.wamblee.reflection.ObjectTraversal.ObjectVisitor;
+
+import static junit.framework.TestCase.*;
+
+public class ObjectTraversalTest {
+
+ @Mock
+ private ObjectVisitor visitor;
+
+ private ObjectTraversal traversal;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ traversal = new ObjectTraversal(visitor);
+
+ when(visitor.mustVisit(any(Class.class))).thenReturn(true);
+ when(visitor.mustVisit(any(Field.class))).thenReturn(true);
+ when(visitor.mustVisit(any(Method.class))).thenReturn(true);
+
+ when(visitor.visitPlainObject(any())).thenReturn(true);
+ when(visitor.visitArray(any())).thenReturn(true);
+ when(visitor.visitList(any(List.class))).thenReturn(true);
+ when(visitor.visitMap(any(Map.class))).thenReturn(true);
+ when(visitor.visitSet(any(Set.class))).thenReturn(true);
+
+ }
+
+ public static class X1 {
+
+ }
+
+ public static class X2 {
+ private X1 x;
+ }
+
+
+ @Test
+ public void testTraverseFields() throws Exception {
+ X2 x2 = new X2();
+ X1 x1 = new X1();
+ x2.x = x1;
+ traversal.accept(x2);
+ verify(visitor).mustVisit(X2.class);
+ verify(visitor).mustVisit(X1.class);
+ verify(visitor).mustVisit(eq(X2.class.getDeclaredField("x")));
+ verify(visitor).visitPlainObject(same(x2));
+ verify(visitor).visitPlainObject(same(x1));
+ verifyNoMoreInteractions(visitor);
+ }
+
+ public static class TraversalNonTraversedFields {
+ private int x;
+ private Object y = new Object();
+ }
+
+ @Test
+ public void testNonTraversedFields() throws Exception {
+ TraversalNonTraversedFields obj =new TraversalNonTraversedFields();
+ traversal.accept(obj);
+ verify(visitor).mustVisit(TraversalNonTraversedFields.class);
+ verify(visitor).mustVisit(eq(TraversalNonTraversedFields.class.getDeclaredField("x")));
+ verify(visitor).mustVisit(eq(TraversalNonTraversedFields.class.getDeclaredField("y")));
+ verify(visitor).visitPlainObject(same(obj));
+ }
+
+ public static class X3 {
+
+ }
+
+ public static class X4 {
+ public X3 getX3() {
+ return new X3();
+ }
+ }
+
+
+ @Test
+ public void testTraverseMethods() throws Exception {
+ X4 x4 = new X4();
+ traversal.accept(x4);
+ verify(visitor).mustVisit(X4.class);
+ verify(visitor).mustVisit(X3.class);
+ verify(visitor).mustVisit(eq(X4.class.getDeclaredMethod("getX3")));
+ verify(visitor).visitPlainObject(same(x4));
+ verify(visitor).visitPlainObject(isA(X3.class));
+ verifyNoMoreInteractions(visitor);
+ }
+
+ @Test
+ public void testTraverseList() {
+ List list = new ArrayList();
+ list.add(new X1());
+ list.add(new X3());
+ traversal.accept(list);
+ verify(visitor).visitList(same(list));
+ verify(visitor).visitPlainObject(isA(X1.class));
+ verify(visitor).visitPlainObject(isA(X3.class));
+ }
+
+ @Test
+ public void testTraverseMap() {
+ Map<String,Object> map = new HashMap<String,Object>();
+ map.put("x1", new X1());
+ map.put("x3", new X3());
+ traversal.accept(map);
+ verify(visitor).visitMap(same(map));
+ verify(visitor).visitPlainObject(isA(X1.class));
+ verify(visitor).visitPlainObject(isA(X3.class));
+ }
+
+ @Test
+ public void testTraverseSet() {
+ Set set = new HashSet();
+ set.add(new X1());
+ set.add(new X3());
+ traversal.accept(set);
+ verify(visitor).visitSet(same(set));
+ verify(visitor).visitPlainObject(isA(X1.class));
+ verify(visitor).visitPlainObject(isA(X3.class));
+ }
+
+ @Test
+ public void testTraverseArray() {
+ Object[] obj = new Object[2];
+ obj[0] = new X1();
+ obj[1] = new X3();
+ traversal.accept(obj);
+ verify(visitor).visitArray(same(obj));
+ verify(visitor).visitPlainObject(isA(X1.class));
+ verify(visitor).visitPlainObject(isA(X3.class));
+ }
+
+ @Test
+ public void testExcludeClasses() {
+ X2 x2 = new X2();
+ x2.x = new X1();
+ when(visitor.mustVisit(X1.class)).thenReturn(false);
+ traversal.accept(x2);
+ verify(visitor).visitPlainObject(same(x2));
+ verify(visitor, never()).visitPlainObject(same(x2.x));
+ }
+
+ @Test
+ public void testExcludeFields() {
+ X2 x2 = new X2();
+ x2.x = new X1();
+ when(visitor.mustVisit(any(Field.class))).thenReturn(false);
+ traversal.accept(x2);
+ verify(visitor).visitPlainObject(same(x2));
+ verify(visitor, never()).visitPlainObject(same(x2.x));
+ }
+
+ @Test
+ public void testExcludeMethods() {
+ X4 x4 = new X4();
+ when(visitor.mustVisit(any(Method.class))).thenReturn(false);
+ traversal.accept(x4);
+ verify(visitor).visitPlainObject(same(x4));
+ verify(visitor, never()).visitPlainObject(isA(X3.class));
+ }
+
+ public static class X5 {
+ private X6 x6;
+ }
+
+ public static class X6 {
+ private X5 x5;
+ }
+
+ @Test
+ public void testCyclic() {
+ X6 x6 = new X6();
+ X5 x5 = new X5();
+ x6.x5 = x5;
+ x5.x6 = x6;
+ traversal.accept(x6);
+ verify(visitor).visitPlainObject(same(x6));
+ verify(visitor).visitPlainObject(same(x5));
+ }
+
+ @Test
+ public void testCyclicList() {
+ List list = new ArrayList();
+ list.add(list);
+ traversal.accept(list);
+ verify(visitor, times(1)).visitList(same(list));
+ }
+
+ @Test
+ public void testCyclicMap() {
+ Map map = new HashMap();
+ map.put("x", map);
+ traversal.accept(map);
+ verify(visitor, times(1)).visitMap(same(map));
+ }
+
+ @Test
+ public void testCyclicSet() {
+ Set set = new HashSet();
+ set.add(set);
+ traversal.accept(set);
+ verify(visitor, times(1)).visitSet(same(set));
+ }
+
+ @Test
+ public void testCyclicArray() {
+ Object[] obj = new Object[1];
+ obj[0] = obj;
+ traversal.accept(obj);
+ verify(visitor, times(1)).visitArray(same(obj));
+ }
+
+ @Test
+ public void testVisitNull() {
+ traversal.accept(null);
+ }
+
+ @Test
+ public void testExcludeFieldByReturningFalseInVisit() {
+ X2 x2 = new X2();
+ x2.x = new X1();
+ when(visitor.visitPlainObject(any())).thenReturn(false);
+ traversal.accept(x2);
+ verify(visitor).visitPlainObject(same(x2));
+ verify(visitor, never()).visitPlainObject(same(x2.x));
+ }
+
+ @Test
+ public void testTraverseListExcludeElements() {
+ List list = new ArrayList();
+ list.add(new X1());
+ list.add(new X3());
+ when(visitor.visitList(any(List.class))).thenReturn(false);
+ traversal.accept(list);
+ verify(visitor).visitList(same(list));
+ verify(visitor, never()).visitPlainObject(any());
+ }
+
+ @Test
+ public void testTraverseMapExcludeElements() {
+ Map<String,Object> map = new HashMap<String,Object>();
+ map.put("x1", new X1());
+ map.put("x3", new X3());
+ when(visitor.visitMap(any(Map.class))).thenReturn(false);
+ traversal.accept(map);
+ verify(visitor).visitMap(same(map));
+ verify(visitor, never()).visitPlainObject(any());
+ }
+
+ @Test
+ public void testTraverseSetExcludeElements() {
+ Set set = new HashSet();
+ set.add(new X1());
+ set.add(new X3());
+ when(visitor.visitSet(any(Set.class))).thenReturn(false);
+
+ traversal.accept(set);
+ verify(visitor).visitSet(same(set));
+ verify(visitor, never()).visitPlainObject(any());
+ }
+
+ @Test
+ public void testTraverseArrayExcludeElements() {
+ Object[] obj = new Object[2];
+ obj[0] = new X1();
+ obj[1] = new X3();
+ when(visitor.visitArray(any())).thenReturn(false);
+
+ traversal.accept(obj);
+ verify(visitor).visitArray(same(obj));
+ verify(visitor, never()).visitPlainObject(any());
+ }
+
+}