/*
 *                    BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 *
 */
package org.biojava.nbio.sequencing.io.fastq;

import junit.framework.TestCase;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * Unit test for Fastq.
 */
public final class FastqTest
	extends TestCase
{

	public void testImmutable()
	{
		Class<Fastq> cls = Fastq.class;
		assertTrue(Modifier.isPublic(cls.getModifiers()));
		assertTrue(Modifier.isFinal(cls.getModifiers()));
		Field[] fields = cls.getDeclaredFields();
		for (Field field : fields)
		{
			assertTrue(Modifier.isPrivate(field.getModifiers()));
			assertTrue(Modifier.isFinal(field.getModifiers()) ||
					(Modifier.isVolatile(field.getModifiers()) && Modifier.isTransient(field.getModifiers())));
		}
	}

	public void testConstructor()
	{
		Fastq fastq = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);
		assertNotNull(fastq);

		try
		{
			new Fastq(null, "sequence", "quality_", FastqVariant.FASTQ_SANGER);
			fail("ctr(null description) expected IllegalArgumentException");
		}
		catch (IllegalArgumentException e)
		{
			// expected
		}
		try
		{
			new Fastq("description", null, "quality_", FastqVariant.FASTQ_SANGER);
			fail("ctr(null sequence) expected IllegalArgumentException");
		}
		catch (IllegalArgumentException e)
		{
			// expected
		}
		try
		{
			new Fastq("description", "sequence", null, FastqVariant.FASTQ_SANGER);
			fail("ctr(null quality) expected IllegalArgumentException");
		}
		catch (IllegalArgumentException e)
		{
			// expected
		}
		try
		{
			new Fastq("description", "sequence", "quality_", null);
			fail("ctr(null variant) expected IllegalArgumentException");
		}
		catch (IllegalArgumentException e)
		{
			// expected
		}
	}

	public void testDescription()
	{
		Fastq fastq = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);
		assertTrue(fastq.getDescription() != null);
		assertEquals("description", fastq.getDescription());
	}

	public void testSequence()
	{
		Fastq fastq = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);
		assertTrue(fastq.getSequence() != null);
		assertEquals("sequence", fastq.getSequence());
	}

	public void testQuality()
	{
		Fastq fastq = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);
		assertTrue(fastq.getQuality() != null);
		assertEquals("quality_", fastq.getQuality());
	}

	public void testVariant()
	{
		Fastq fastq = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);
		assertTrue(fastq.getVariant() != null);
		assertEquals(FastqVariant.FASTQ_SANGER, fastq.getVariant());
	}

	public void testBuilder()
	{
		assertNotNull(Fastq.builder());
	}

	public void testEquals()
	{
		Fastq fastq0 = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);
		Fastq fastq1 = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);

		assertFalse(fastq0.equals(null));
		assertFalse(fastq1.equals(null));
		assertFalse(fastq0.equals(new Object()));
		assertFalse(fastq1.equals(new Object()));
		assertTrue(fastq0.equals(fastq0));
		assertTrue(fastq1.equals(fastq1));
		assertFalse(fastq0 == fastq1);
		assertFalse(fastq0.equals(fastq1));
		assertFalse(fastq1.equals(fastq0));
	}

	public void testHashCode()
	{
		Fastq fastq0 = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);
		Fastq fastq1 = new Fastq("description", "sequence", "quality_", FastqVariant.FASTQ_SANGER);

		assertEquals(fastq0.hashCode(), fastq0.hashCode());
		assertEquals(fastq1.hashCode(), fastq1.hashCode());
		if (fastq0.equals(fastq1))
		{
			assertEquals(fastq0.hashCode(), fastq1.hashCode());
			assertEquals(fastq1.hashCode(), fastq0.hashCode());
		}
		if (fastq1.equals(fastq0))
		{
			assertEquals(fastq0.hashCode(), fastq1.hashCode());
			assertEquals(fastq1.hashCode(), fastq0.hashCode());
		}
	}
}
