/*
 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.internal.storage.file;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;

import java.io.File;
import java.util.Iterator;
import java.util.NoSuchElementException;

import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.storage.file.PackIndex;
import org.eclipse.jgit.internal.storage.file.PackIndex.MutableEntry;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.junit.Test;

public abstract class PackIndexTestCase extends RepositoryTestCase {

	PackIndex smallIdx;

	PackIndex denseIdx;

	public void setUp() throws Exception {
		super.setUp();
		smallIdx = PackIndex.open(getFileForPack34be9032());
		denseIdx = PackIndex.open(getFileForPackdf2982f28());
	}

	/**
	 * Return file with appropriate index version for prepared pack.
	 *
	 * @return file with index
	 */
	public abstract File getFileForPack34be9032();

	/**
	 * Return file with appropriate index version for prepared pack.
	 *
	 * @return file with index
	 */
	public abstract File getFileForPackdf2982f28();

	/**
	 * Verify CRC32 support.
	 *
	 * @throws MissingObjectException
	 * @throws UnsupportedOperationException
	 */
	public abstract void testCRC32() throws MissingObjectException,
			UnsupportedOperationException;

	/**
	 * Test contracts of Iterator methods and this implementation remove()
	 * limitations.
	 */
	@Test
	public void testIteratorMethodsContract() {
		Iterator<PackIndex.MutableEntry> iter = smallIdx.iterator();
		while (iter.hasNext()) {
			iter.next();
		}

		try {
			iter.next();
			fail("next() unexpectedly returned element");
		} catch (NoSuchElementException x) {
			// expected
		}

		try {
			iter.remove();
			fail("remove() shouldn't be implemented");
		} catch (UnsupportedOperationException x) {
			// expected
		}
	}

	/**
	 * Test results of iterator comparing to content of well-known (prepared)
	 * small index.
	 */
	@Test
	public void testIteratorReturnedValues1() {
		Iterator<PackIndex.MutableEntry> iter = smallIdx.iterator();
		assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904", iter.next()
				.name());
		assertEquals("540a36d136cf413e4b064c2b0e0a4db60f77feab", iter.next()
				.name());
		assertEquals("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259", iter.next()
				.name());
		assertEquals("6ff87c4664981e4397625791c8ea3bbb5f2279a3", iter.next()
				.name());
		assertEquals("82c6b885ff600be425b4ea96dee75dca255b69e7", iter.next()
				.name());
		assertEquals("902d5476fa249b7abc9d84c611577a81381f0327", iter.next()
				.name());
		assertEquals("aabf2ffaec9b497f0950352b3e582d73035c2035", iter.next()
				.name());
		assertEquals("c59759f143fb1fe21c197981df75a7ee00290799", iter.next()
				.name());
		assertFalse(iter.hasNext());
	}

	/**
	 * Compare offset from iterator entries with output of findOffset() method.
	 */
	@Test
	public void testCompareEntriesOffsetsWithFindOffsets() {
		for (MutableEntry me : smallIdx) {
			assertEquals(smallIdx.findOffset(me.toObjectId()), me.getOffset());
		}
		for (MutableEntry me : denseIdx) {
			assertEquals(denseIdx.findOffset(me.toObjectId()), me.getOffset());
		}
	}

	/**
	 * Compare offset from iterator entries with output of getOffset() method.
	 */
	@Test
	public void testCompareEntriesOffsetsWithGetOffsets() {
		int i = 0;
		for (MutableEntry me : smallIdx) {
			assertEquals(smallIdx.getOffset(i++), me.getOffset());
		}
		int j = 0;
		for (MutableEntry me : denseIdx) {
			assertEquals(denseIdx.getOffset(j++), me.getOffset());
		}
	}

	/**
	 * Test partial results of iterator comparing to content of well-known
	 * (prepared) dense index, that may need multi-level indexing.
	 */
	@Test
	public void testIteratorReturnedValues2() {
		Iterator<PackIndex.MutableEntry> iter = denseIdx.iterator();
		while (!iter.next().name().equals(
				"0a3d7772488b6b106fb62813c4d6d627918d9181")) {
			// just iterating
		}
		assertEquals("1004d0d7ac26fbf63050a234c9b88a46075719d3", iter.next()
				.name()); // same level-1
		assertEquals("10da5895682013006950e7da534b705252b03be6", iter.next()
				.name()); // same level-1
		assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8", iter.next()
				.name());
	}

}
