/*
 * @(#)ClassMarkSetUTest.java
 *
 * Copyright (C) 2003 Matt Albrecht
 * groboclown@users.sourceforge.net
 * http://groboutils.sourceforge.net
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the 
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in 
 *  all copies or substantial portions of the Software. 
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 *  DEALINGS IN THE SOFTWARE.
 */

package net.sourceforge.groboutils.codecoverage.v2.report;

import java.util.ArrayList;
import java.util.List;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import net.sourceforge.groboutils.autodoc.v1.AutoDoc;
import net.sourceforge.groboutils.codecoverage.v2.CCCreatorUtil;
import net.sourceforge.groboutils.codecoverage.v2.IAnalysisMetaData;
import net.sourceforge.groboutils.codecoverage.v2.IAnalysisModule;
import net.sourceforge.groboutils.codecoverage.v2.IChannelLogRecord;
import net.sourceforge.groboutils.codecoverage.v2.datastore.ClassRecord;
import net.sourceforge.groboutils.codecoverage.v2.datastore.MarkRecord;
import net.sourceforge.groboutils.codecoverage.v2.logger.DefaultChannelLogRecord;


/**
 * Tests the ClassMarkSet class.
 *
 * @author    Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
 * @version   $Date: 2004/04/15 05:48:29 $
 * @since     January 22, 2003
 */
public class ClassMarkSetUTest extends TestCase
{
    //-------------------------------------------------------------------------
    // Standard JUnit Class-specific declarations
    
    private static final Class THIS_CLASS = ClassMarkSetUTest.class;
    private static final AutoDoc DOC = new AutoDoc( THIS_CLASS );
    
    public ClassMarkSetUTest( String name )
    {
        super( name );
    }


    //-------------------------------------------------------------------------
    // Tests
    
    
    public void testConstructor1()
    {
        try
        {
            new ClassMarkSet( null, null, null, null );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException ex)
        {
            // test exception
        }
    }
    
    
    public void testConstructor2()
    {
        try
        {
            new ClassMarkSet( "a", new String[] { "1", "2" },
                new MarkRecord[] {
                    createMarkRecord( 0, "1", "2", 3 ),
                }, null );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException ex)
        {
            // test exception
        }
    }
    
    
    public void testConstructor3()
    {
        try
        {
            new ClassMarkSet( "a", new String[] { "1", "2" },
                null,
                new IChannelLogRecord[] {
                    createChannelLogRecord( "a.M", 0, 0 ),
                } );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException ex)
        {
            // test exception
        }
    }
    
    
    public void testConstructor4()
    {
        try
        {
            new ClassMarkSet( "a", new String[] { "1", "2" },
                new MarkRecord[ 1 ],
                new IChannelLogRecord[ 1 ] );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException ex)
        {
            // test exception
        }
    }
    
    
    public void testConstructor5()
    {
        try
        {
            new ClassMarkSet( "a.Name", new String[] { "1", "2" },
                processMarks( "a.Name", new MarkRecord[] {
                    createMarkRecord( 0, "1", "2", 3 ),
                } ),
                new IChannelLogRecord[ 1 ] );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException ex)
        {
            // test exception
        }
    }
    
    
    public void testConstructor5a()
    {
        try
        {
            new ClassMarkSet( "a", new String[] { "1", "2" },
                new MarkRecord[] {
                    createMarkRecord( 0, "1", "2", 3 ),
                },
                new IChannelLogRecord[ 1 ] );
            fail( "Did not throw IllegalStateException." );
        }
        catch (IllegalStateException ex)
        {
            // test exception
            assertTrue(
                "Did not fail due to process.",
                ex.getMessage().indexOf( "process" ) >= 0 );
        }
    }
    
    
    public void testConstructor6()
    {
        try
        {
            new ClassMarkSet( "a", new String[] { "1", "2" },
                new MarkRecord[ 1 ],
                new IChannelLogRecord[] {
                    createChannelLogRecord( "a.M", 0, 0 ),
                } );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException ex)
        {
            // test exception
        }
    //ClassMarkSet( MarkRecord[] marks, IChannelLogRecord[] classLogs )
    }
    
    
    public void testConstructor7()
    {
        try
        {
            new ClassMarkSet( "a.M", new String[] { "1", "2" },
                processMarks( "a.M", new MarkRecord[] {
                    createMarkRecord( 0, "1", "2", 10 ),
                } ),
                new IChannelLogRecord[] {
                    createChannelLogRecord( "a.M", 0, 0 ),
                } );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException iae)
        {
            /*
            assertTrue(
                "Did not mention mark 0 ["+iae.getMessage()+"].",
                iae.getMessage().indexOf( "mark 0" ) >= 0 );
            */
        }
    }
    
    
    public void testConstructor8()
    {
        new ClassMarkSet( "a.M", new String[] { "2", "1" },
            processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "2", 0 ),
            } ),
            new IChannelLogRecord[] {
                createChannelLogRecord( "a.M", 0, 0 ),
            } );
    }
    
    
    public void testConstructor9()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m1()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 1 ),
            } );
        try
        {
            new ClassMarkSet( "a.M", new String[] { "m1()V", "m2()V" },
                mr, new IChannelLogRecord[] {
                    createChannelLogRecord( "a.M", 0, 1 ),
                } );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException iae)
        {
            assertTrue(
                "Did not mention mark 1 ["+iae.getMessage()+"].",
                iae.getMessage().indexOf( "mark 1" ) >= 0 );
        }
    }
    
    
    public void testConstructor10()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m1()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 1 ),
            } );
        try
        {
            new ClassMarkSet( "a.M", new String[] { "m1()V", "m2()V" },
                mr, new IChannelLogRecord[] {
                    createChannelLogRecord( "a.M", 0, 1 ),
                    createChannelLogRecord( "a.M", 0, 5 ),
                } );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException iae)
        {
            assertTrue(
                "Did not mention mark 1 or 5 ["+iae.getMessage()+"].",
                iae.getMessage().indexOf( "mark 1" ) >= 0 ||
                iae.getMessage().indexOf( "mark 5" ) >= 0 );
        }
    }
    
    
    public void testConstructor11()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m1()V", 1 ),
                createMarkRecord( 0, "1", "m1()V", 2 ),
                createMarkRecord( 0, "1", "m1()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 1 ),
                createMarkRecord( 0, "1", "m2()V", 2 ),
                createMarkRecord( 0, "1", "m2()V", 3 ),
            } );
        try
        {
            new ClassMarkSet( "a.M", new String[] { "m1()V", "m2()V" },
                mr, new IChannelLogRecord[] {
                    createChannelLogRecord( "a.M", 0, 3 ),
                    createChannelLogRecord( "a.M", 0, 4 ),
                    createChannelLogRecord( "a.M", 1, 1 ),
                    createChannelLogRecord( "a.M", 1, 2 ),
                } );
            fail( "Did not throw IllegalArgumentException." );
        }
        catch (IllegalArgumentException iae)
        {
            assertTrue(
                "Did not mention mark 4 ["+iae.getMessage()+"].",
                iae.getMessage().indexOf( "mark 4" ) >= 0 );
        }
    }
    
    
    public void testGetMethodSignatures1()
    {
        ClassMarkSet cms = new ClassMarkSet( "a.M",
            new String[] {},
            new MarkRecord[0], new IChannelLogRecord[ 0 ] );
        String[] methods = cms.getMethodSignatures();
        assertNotNull(
            "Returned null method signature list.",
            methods );
        assertEquals(
            "Created methods out of nothing.",
            0,
            methods.length );
    }
    
    
    public void testGetMethodSignatures1a()
    {
        try
        {
            ClassMarkSet cms = new ClassMarkSet(
                "a.M", new String[] { "m1()V", "m2()V" },
                new MarkRecord[0], new IChannelLogRecord[] {
                    createChannelLogRecord( "a.M", 0, 1 ),
                } );
        }
        catch (IllegalArgumentException ex)
        {
            /*
            assertTrue(
                "Did not mention method 0 ["+ex.getMessage()+"].",
                ex.getMessage().indexOf( "method 0" ) >= 0 );
            assertTrue(
                "Did not mention mark 1 ["+ex.getMessage()+"].",
                ex.getMessage().indexOf( "mark 1" ) >= 0 );
            */
        }
    }
    
    
    public void testGetMethodSignatures2()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m()V", 0 ),
            } );
        ClassMarkSet cms = new ClassMarkSet("a.M",
            new String[] { "m()V" },
            mr, new IChannelLogRecord[] {
                createChannelLogRecord( "a.M", 0, 0 ),
            } );
        
        String[] methods = cms.getMethodSignatures();
        assertEquals(
            "Did not return the right number of methods.",
            1,
            methods.length );
        assertEquals(
            "Did not return the right method.",
            "m()V",
            methods[0] );
    }
    
    
    public void testGetMethodSignatures3()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m1()V", 0 ),
                createMarkRecord( 0, "1", "m1()V", 1 ),
                createMarkRecord( 0, "1", "m1()V", 2 ),
                createMarkRecord( 0, "1", "m2()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 2 ),
                createMarkRecord( 0, "1", "m2()V", 1 ),
                createMarkRecord( 0, "1", "m2()V", 0 ),
            } );
        ClassMarkSet cms = new ClassMarkSet(
            "a.M", new String[] { "m1()V", "m2()V" },
            mr, new IChannelLogRecord[] {
                createChannelLogRecord( "a.M", 1, 1 ),
            } );
        
        String[] methods = cms.getMethodSignatures();
        assertEquals(
            "Did not return the right number of methods.",
            2,
            methods.length );
        assertTrue(
            "Did not return the right methods.",
            (
                methods[0].equals( "m1()V" ) && methods[1].equals( "m2()V" )
            ) ||
            (
                methods[0].equals( "m2()V" ) && methods[1].equals( "m1()V" )
            ) );
    }
    
    
    public void testGetMethodSignatures4()
    {
        ClassMarkSet cms = new ClassMarkSet( "a.M",
            new String[] { "1", "2" },
            new MarkRecord[0], new IChannelLogRecord[ 0 ] );
        String[] methods = cms.getMethodSignatures();
        assertNotNull(
            "Returned null method signature list.",
            methods );
        assertEquals(
            "Did not return right methods.",
            2,
            methods.length );
    }
    
    
    public void testGetCoveredMarksForMethod3()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m1()V", 0 ),
                createMarkRecord( 0, "1", "m1()V", 1 ),
                createMarkRecord( 0, "1", "m1()V", 2 ),
                createMarkRecord( 0, "1", "m1()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 0 ),
                createMarkRecord( 0, "1", "m2()V", 1 ),
                createMarkRecord( 0, "1", "m2()V", 2 ),
                createMarkRecord( 0, "1", "m2()V", 3 ),
            } );
        ClassMarkSet cms = new ClassMarkSet(
            "a.M", new String[] { "m1()V", "m2()V" },
            mr, new IChannelLogRecord[] {
                createChannelLogRecord( "a.M", 0, 3 ),
            } );
        MarkRecord covered[] = cms.getCoveredMarksForMethod( "m1()V" );
        assertEquals(
            "Returned incorrect coverage list.",
            1,
            covered.length );
        assertEquals(
            "Returned bad mark method.",
            "m1()V",
            covered[0].getMethodSignature() );
        assertEquals(
            "Returned bad mark id.",
            (short)3,
            covered[0].getMarkIndex() );
    }
    
    
    public void testGetCoveredMarksForMethod4()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m1()V", 0 ),
                createMarkRecord( 0, "1", "m1()V", 1 ),
                createMarkRecord( 0, "1", "m1()V", 2 ),
                createMarkRecord( 0, "1", "m1()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 0 ),
                createMarkRecord( 0, "1", "m2()V", 1 ),
                createMarkRecord( 0, "1", "m2()V", 2 ),
                createMarkRecord( 0, "1", "m2()V", 3 ),
            } );
        ClassMarkSet cms = new ClassMarkSet(
            "a.M", new String[] { "m1()V", "m2()V" },
            mr, new IChannelLogRecord[] {
                createChannelLogRecord( "a.M", 0, 3 ),
                //createChannelLogRecord( "a.M", 0, 4 ),
                createChannelLogRecord( "a.M", 1, 1 ),
                createChannelLogRecord( "a.M", 1, 2 ),
            } );
        MarkRecord covered[] = cms.getCoveredMarksForMethod( "m2()V" );
        assertEquals(
            "Returned incorrect coverage list.",
            2,
            covered.length );
        assertEquals(
            "Returned bad mark method [0].",
            "m2()V",
            covered[0].getMethodSignature() );
        assertEquals(
            "Returned bad mark method [1].",
            "m2()V",
            covered[1].getMethodSignature() );
        
        assertTrue(
            "Returned bad mark ids.",
            (
                covered[0].getMarkIndex() == (short)1 &&
                covered[1].getMarkIndex() == (short)2
            ) ||
            (
                covered[0].getMarkIndex() == (short)2 &&
                covered[1].getMarkIndex() == (short)1
            ) );
    }
    
    
    public void testGetNotCoveredMarksForMethod1()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m1()V", 0 ),
                createMarkRecord( 0, "1", "m1()V", 1 ),
                createMarkRecord( 0, "1", "m1()V", 2 ),
                createMarkRecord( 0, "1", "m1()V", 3 ),
                createMarkRecord( 0, "1", "m2()V", 0 ),
                createMarkRecord( 0, "1", "m2()V", 1 ),
                createMarkRecord( 0, "1", "m2()V", 2 ),
                createMarkRecord( 0, "1", "m2()V", 3 ),
            } );
        ClassMarkSet cms = new ClassMarkSet(
            "a.M", new String[] { "m1()V", "m2()V" },
            mr, new IChannelLogRecord[] {
                createChannelLogRecord( "a.M", 0, 3 ),
                //createChannelLogRecord( "a.M", 0, 4 ),
                createChannelLogRecord( "a.M", 1, 0 ),
                createChannelLogRecord( "a.M", 1, 1 ),
                createChannelLogRecord( "a.M", 1, 2 ),
            } );
        MarkRecord nc[] = cms.getNotCoveredMarksForMethod( "m2()V" );
        assertEquals(
            "Returned incorrect coverage list.",
            1,
            nc.length );
        assertEquals(
            "Returned bad mark method.",
            "m2()V",
            nc[0].getMethodSignature() );
        assertEquals(
            "Returned bad mark id.",
            (short)3,
            nc[0].getMarkIndex() );
    }
    
    
    public void testGetNotCoveredMarksForMethod2()
    {
        MarkRecord mr[] = processMarks( "a.M", new MarkRecord[] {
                createMarkRecord( 0, "1", "m1()V", 0 ),
                createMarkRecord( 0, "1", "m1()V", 1 ),
                createMarkRecord( 0, "1", "m1()V", 2 ),
                createMarkRecord( 0, "1", "m1()V", 3 ),
            } );
        ClassMarkSet cms = new ClassMarkSet(
            "a.M", new String[] { "m1()V", "m2()V" },
            mr, new IChannelLogRecord[] {
                createChannelLogRecord( "a.M", 0, 0 ),
                createChannelLogRecord( "a.M", 0, 1 ),
                createChannelLogRecord( "a.M", 0, 2 ),
                createChannelLogRecord( "a.M", 0, 3 ),
                //createChannelLogRecord( "a.M", 0, 4 ),
            } );
        MarkRecord nc[] = cms.getNotCoveredMarksForMethod( "m1()V" );
        assertNotNull(
            "Returned null not-covered list.",
            nc );
        assertEquals(
            "Returned incorrect not-coverage list length.",
            0,
            nc.length );
    }
    
    
    //-------------------------------------------------------------------------
    // Helpers
    
    
    protected IAnalysisMetaData createAnalysisMetaData( int weight )
    {
        return CCCreatorUtil.createIAnalysisMetaData( "a", "b", (byte)weight );
    }
    
    
    protected MarkRecord createMarkRecord( int metaDataWeight, String am,
            String methSig, int markId )
    {
        MarkRecord mr = new MarkRecord( createAnalysisMetaData( metaDataWeight ),
            am, methSig, (short)markId, 1 );
        return mr;
    }
    
    
    protected MarkRecord[] processMarks( String className, MarkRecord mr[] )
    {
        // don't use a real set so we can keep the original order
        List methodSet = new ArrayList();
        List measureSet = new ArrayList();
        for (int i = 0; i < mr.length; ++i)
        {
            if (!methodSet.contains( mr[i].getMethodSignature() ))
            {
                methodSet.add( mr[i].getMethodSignature() );
            }
            if (!measureSet.contains( mr[i].getAnalysisModule() ))
            {
                measureSet.add( mr[i].getAnalysisModule() );
            }
        }
        
        // create measures
        IAnalysisModule modules[] = new IAnalysisModule[ measureSet.size() ];
        for (int i = 0; i < modules.length; ++i)
        {
            modules[i] = CCCreatorUtil.createIAnalysisModule(
                (String)measureSet.get( i ), "a", "b" );
        }
        String methods[] = (String[])methodSet.toArray( new String[
            methodSet.size() ] );
        
        ClassRecord cr = new ClassRecord( className, 100L, "a", methods,
            CCCreatorUtil.createAnalysisModuleSet( modules ) );
        for (int i = 0; i < mr.length; ++i)
        {
            cr.addMark( mr[i] );
        }
        
        return mr;
    }
    
    
    protected IChannelLogRecord createChannelLogRecord( String classSig,
            int methodIndex, int markIndex )
    {
        return new DefaultChannelLogRecord( classSig, (short)methodIndex,
            (short)markIndex );
    }
    
    
    //-------------------------------------------------------------------------
    // Standard JUnit declarations
    
    
    public static Test suite()
    {
        TestSuite suite = new TestSuite( THIS_CLASS );
        
        return suite;
    }
    
    public static void main( String[] args )
    {
        String[] name = { THIS_CLASS.getName() };
        
        // junit.textui.TestRunner.main( name );
        // junit.swingui.TestRunner.main( name );
        
        junit.textui.TestRunner.main( name );
    }
    
    
    /**
     * 
     * @exception Exception thrown under any exceptional condition.
     */
    protected void setUp() throws Exception
    {
        super.setUp();

       
        // set ourself up
    }
    
    
    /**
     * 
     * @exception Exception thrown under any exceptional condition.
     */
    protected void tearDown() throws Exception
    {
        // tear ourself down
        
        
        super.tearDown();
    }
}

