/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.flink.api.common.typeutils;

import java.io.IOException;
import org.apache.flink.api.common.ExecutionConfig;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.util.InstantiationUtil;
import org.apache.flink.util.TestLogger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;

/**
 * Abstract test base for type information.
 */
public abstract class TypeInformationTestBase<T extends TypeInformation<?>> extends TestLogger {

	protected abstract T[] getTestData();

	@Test
	public void testHashcodeAndEquals() throws Exception {
		final T[] testData = getTestData();
		final TypeInformation<?> unrelatedTypeInfo = new UnrelatedTypeInfo();

		for (T typeInfo : testData) {
			// check for implemented hashCode and equals
			if (typeInfo.getClass().getMethod("hashCode").getDeclaringClass() == Object.class) {
				throw new AssertionError("Type information does not implement own hashCode method: " +
					typeInfo.getClass().getCanonicalName());
			}
			if (typeInfo.getClass().getMethod("equals", Object.class).getDeclaringClass() == Object.class) {
				throw new AssertionError("Type information does not implement own equals method: " +
					typeInfo.getClass().getCanonicalName());
			}

			// compare among test data
			for (T otherTypeInfo : testData) {
				assertTrue("canEqual() returns inconsistent results.", typeInfo.canEqual(otherTypeInfo));
				// test equality
				if (typeInfo == otherTypeInfo) {
					assertTrue("hashCode() returns inconsistent results.", typeInfo.hashCode() == otherTypeInfo.hashCode());
					assertEquals("equals() is false for same object.", typeInfo, otherTypeInfo);
				}
				// test inequality
				else {
					assertNotEquals("equals() returned true for different objects.", typeInfo, otherTypeInfo);
				}
			}

			// compare with unrelated type
			assertFalse("Type information allows to compare with unrelated type.", typeInfo.canEqual(unrelatedTypeInfo));
			assertNotEquals(typeInfo, unrelatedTypeInfo);
		}
	}

	@Test
	public void testSerialization() {
		final T[] testData = getTestData();

		for (T typeInfo : testData) {
			final byte[] serialized;
			try {
				serialized = InstantiationUtil.serializeObject(typeInfo);
			} catch (IOException e) {
				throw new AssertionError("Could not serialize type information: " + typeInfo, e);
			}
			final T deserialized;
			try {
				deserialized = InstantiationUtil.deserializeObject(serialized, getClass().getClassLoader());
			} catch (IOException | ClassNotFoundException e) {
				throw new AssertionError("Could not deserialize type information: " + typeInfo, e);
			}
			if (typeInfo.hashCode() != deserialized.hashCode() || !typeInfo.equals(deserialized)) {
				throw new AssertionError("Deserialized type information differs from original one.");
			}
		}
	}

	private static class UnrelatedTypeInfo extends TypeInformation<Object> {

		@Override
		public boolean isBasicType() {
			return false;
		}

		@Override
		public boolean isTupleType() {
			return false;
		}

		@Override
		public int getArity() {
			return 0;
		}

		@Override
		public int getTotalFields() {
			return 0;
		}

		@Override
		public Class<Object> getTypeClass() {
			return null;
		}

		@Override
		public boolean isKeyType() {
			return false;
		}

		@Override
		public TypeSerializer<Object> createSerializer(ExecutionConfig config) {
			return null;
		}

		@Override
		public String toString() {
			return null;
		}

		@Override
		public boolean equals(Object obj) {
			return false;
		}

		@Override
		public int hashCode() {
			return 0;
		}

		@Override
		public boolean canEqual(Object obj) {
			return false;
		}
	}
}
