/* Copyright (c) 2005 Ricebridge. All Rights Reserved.
 *
 * This file is available under the terms and conditions of the
 * Ricebridge "Open Source API" policy; Ricebridge grants use of this
 * copyrighted work under the terms of a BSD-style license only. See
 * http://www.opensource.org/licenses/bsd-license.php for more
 * information.
 * 
 * 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 Ricebridge 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 com.ricebridge.xmlman.test;


import com.ricebridge.xmlman.*;
import com.ricebridge.xmlman.in.*;
import com.ricebridge.xmlman.in.test.*;
import com.ricebridge.xmlman.log.*;

import com.ricebridge.util.RBTestUtil;

import org.jostraca.util.*;

import junit.framework.*;
import junit.textui.*;

import org.xml.sax.InputSource;

import java.util.*;
import java.io.*;
import java.text.*;


/** Test cases for {@link com.ricebridge.xmlman.BadRecord} handling.
 *    <p>Test files are <a href="badrec.xml">badrec.xml</a>, <a href="badxml.xml">badxml.xml</a>.</p> 
 *    <p>The <b><a href="BadRecordsTest.java.html">Source Code</a></b> of this Java class 
 *    is available under a <a href="http://www.opensource.org/licenses/bsd-license.php">BSD-style license</a>.</p>
 */
public class BadRecordsTest extends TestCase {

  // test framework
  
  public BadRecordsTest( String pName ) {
    super( pName );
  }

  public static TestSuite suite() {
    return new TestSuite( BadRecordsTest.class );
  }

  public static void main( String[] pArgs ) {
    TestRunner.run( suite() );
  }

  

  // test cases

  public void testBadXml() throws Exception {
    File xf = RBTestUtil.findTestFile("com/ricebridge/xmlman/test/badxml.xml");    
    RecordSpec rs = new RecordSpec( "/root/record", new String[] {"@name","foo","bar"}  );
    XmlManager xm = new XmlManager();
    
    try {
      xm.loadAsLists( xf, rs );
      fail();
    }
    catch( XmlManagerException xme ) {
      // XML error creates no bad records
      assertEquals( XmlManagerException.CODE_bad_xml_file, xme.getCode() );
      assertEquals( 1, xm.getStats().getTotalRecords() );
      assertEquals( 0, xm.getStats().getTotalBadRecords() );
      assertEquals( 0, xm.getBadRecords().size() );
    }

    try {
      // XML syntax halts processing in all cases
      xm.getXmlSpec().setIgnoreBadRecords( true );
      xm.loadAsLists( xf, rs );
      fail();
    }
    catch( XmlManagerException xme ) {
      // XML error creates no bad records
      assertEquals( XmlManagerException.CODE_bad_xml_file, xme.getCode() );
      assertEquals( 1, xm.getStats().getTotalRecords() );
      assertEquals( 0, xm.getStats().getTotalBadRecords() );
      assertEquals( 0, xm.getBadRecords().size() );
    }
  }

  public void testBadRecord() {
    BadRecord br = new BadRecord();
    assertEquals( "[BadRecord:SEMANTIC,tag=,recnum=0,fields=[],msg=,context=null]", br.toString() );
    assertEquals( BadRecord.SEMANTIC, br.getType() );
    assertEquals( 0, br.getRecordNumber() );
    assertEquals( "", br.getMessage() );
    assertEquals( null, br.getContext() );
    assertEquals( "[]", ""+Arrays.asList(br.getRecord()) ); 

    br = new BadRecord( "01", 1, new String[] {"f1","f2"}, "msg1" );
    assertEquals( "[BadRecord:SEMANTIC,tag=01,recnum=1,fields=[f1, f2],msg=msg1,context=null]", br.toString() );
    assertEquals( BadRecord.SEMANTIC, br.getType() );
    assertEquals( 1, br.getRecordNumber() );
    assertEquals( "msg1", br.getMessage() );
    assertEquals( null, br.getContext() );
    assertEquals( "[f1, f2]", ""+Arrays.asList(br.getRecord()) ); 

    br = new BadRecord( "02", 2, new String[] {"f3","f4"}, "msg2", BadRecord.UNEXPECTED );
    assertEquals( "[BadRecord:UNEXPECTED,tag=02,recnum=2,fields=[f3, f4],msg=msg2,context=null]", br.toString() );
    assertEquals( BadRecord.UNEXPECTED, br.getType() );
    assertEquals( 2, br.getRecordNumber() );
    assertEquals( "msg2", br.getMessage() );
    assertEquals( null, br.getContext() );
    assertEquals( "[f3, f4]", ""+Arrays.asList(br.getRecord()) ); 

    Exception ex1 = new Exception("ex1");
    br = new BadRecord( "03", 3, new String[] {"f5","f6"}, "msg3", ex1 );
    assertEquals( "[BadRecord:SEMANTIC,tag=03,recnum=3,fields=[f5, f6],msg=msg3,context=java.lang.Exception: ex1]", br.toString() );
    assertEquals( BadRecord.SEMANTIC, br.getType() );
    assertEquals( 3, br.getRecordNumber() );
    assertEquals( "msg3", br.getMessage() );
    assertEquals( ex1, br.getContext() );
    assertEquals( "[f5, f6]", ""+Arrays.asList(br.getRecord()) ); 

    BadRecordContext brc1 = new BadRecordContext("brc1");
    br = new BadRecord( "04", 4, new String[] {"f7","f8"}, "msg4", brc1 );
    assertEquals( "[BadRecord:SEMANTIC,tag=04,recnum=4,fields=[f7, f8],msg=msg4,context=BadRecordContext:brc1]", br.toString() );
    assertEquals( BadRecord.SEMANTIC, br.getType() );
    assertEquals( 4, br.getRecordNumber() );
    assertEquals( "msg4", br.getMessage() );
    assertEquals( brc1, br.getContext() );
    assertEquals( "[f7, f8]", ""+Arrays.asList(br.getRecord()) ); 

    Exception ex2 = new Exception("ex2");
    br = new BadRecord( "05", 5, new String[] {"f9","f10"}, "msg5", ex2, BadRecord.UNEXPECTED );
    assertEquals( "[BadRecord:UNEXPECTED,tag=05,recnum=5,fields=[f9, f10],msg=msg5,context=java.lang.Exception: ex2]", br.toString() );
    assertEquals( BadRecord.UNEXPECTED, br.getType() );
    assertEquals( 5, br.getRecordNumber() );
    assertEquals( "msg5", br.getMessage() );
    assertEquals( ex2, br.getContext() );
    assertEquals( "[f9, f10]", ""+Arrays.asList(br.getRecord()) ); 

    BadRecordContext brc2 = new BadRecordContext("brc2");
    br = new BadRecord( "06", 6, new String[] {"f11","f12"}, "msg6", brc2, BadRecord.UNEXPECTED );
    assertEquals( "[BadRecord:UNEXPECTED,tag=06,recnum=6,fields=[f11, f12],msg=msg6,context=BadRecordContext:brc2]", br.toString() );
    assertEquals( BadRecord.UNEXPECTED, br.getType() );
    assertEquals( 6, br.getRecordNumber() );
    assertEquals( "msg6", br.getMessage() );
    assertEquals( brc2, br.getContext() );
    assertEquals( "[f11, f12]", ""+Arrays.asList(br.getRecord()) ); 
  }


  public void testFailFast() throws Exception {
    File       xf = RBTestUtil.findTestFile("com/ricebridge/xmlman/test/badrec.xml");
    RecordSpec rs = new RecordSpec( "//que", 
                                    new String[] {"@rec","@q","//h:p[@class='t']"} );
    XmlManager xm = new XmlManager();
    xm.getXmlSpec().addNamespace("h","html");

    try {
      xm.load( xf, rs, new FailingRecordListener() );
    }
    catch( XmlManagerException xme ) {
      assertTrue( XmlManagerException.CODE_bad_record == xme.getCode() );
      assertEquals( "An invalid record was encountered and processing was halted; record number: 2, record: [bad, q2, t2], message: bad.", xme.getUserMessage() );
      BadRecord br = xme.getBadRecord();
      assertEquals( "[BadRecord:SEMANTIC,tag=que,recnum=2,fields=[bad, q2, t2],msg=bad,context=null]", br.toString() );

      Stats stats = xm.getStats();
      assertEquals( 2, stats.getTotalRecords() );
      assertEquals( 1, stats.getTotalBadRecords() );
    }
    catch( Exception e ) {
      fail();
    }


    BadRecordContext brc1 = new BadRecordContext("brc1");
    try {
      xm.load( xf, rs, new FailingRecordListener( brc1 ) );
    }
    catch( XmlManagerException xme ) {
      assertTrue( XmlManagerException.CODE_bad_record == xme.getCode() );
      assertEquals( "An invalid record was encountered and processing was halted; record number: 2, record: [bad, q2, t2], message: bad.", xme.getUserMessage() );
      BadRecord br = xme.getBadRecord();
      assertEquals( "[BadRecord:SEMANTIC,tag=que,recnum=2,fields=[bad, q2, t2],msg=bad,context=BadRecordContext:brc1]", br.toString() );
      assertEquals( brc1, br.getContext() );

      Stats stats = xm.getStats();
      assertEquals( 2, stats.getTotalRecords() );
      assertEquals( 1, stats.getTotalBadRecords() );
    }
    catch( Exception e ) {
      fail();
    }

  }


  public void testCollect() throws Exception {
    File       xf = RBTestUtil.findTestFile("com/ricebridge/xmlman/test/badrec.xml");
    RecordSpec rs = new RecordSpec( "//que", 
                                    new String[] {"@rec","@q","//h:p[@class='t']"} );
    XmlManager xm = new XmlManager();
    XmlSpec    xs = xm.getXmlSpec(); 
    xs.setIgnoreBadRecords( true );
    xs.addNamespace("h","html");

    try {
      xm.load( xf, rs, new FailingRecordListener() );
    }
    catch( Exception e ) {
      fail();
    }

    Stats stats = xm.getStats();
    assertEquals( 5, stats.getTotalRecords() );
    assertEquals( 3, stats.getTotalBadRecords() );

    List badrecs = xm.getBadRecords();
    assertEquals( "[[BadRecord:SEMANTIC,tag=que,recnum=2,fields=[bad, q2, t2],msg=bad,context=null], [BadRecord:SEMANTIC,tag=que,recnum=4,fields=[bad, q4, t4],msg=bad,context=null], [BadRecord:SEMANTIC,tag=que,recnum=5,fields=[bad, q5, t5],msg=bad,context=null]]", badrecs.toString() );


    BadRecordContext brc2 = new BadRecordContext("brc2");
    try {
      xm.load( xf, rs, new FailingRecordListener(brc2) );
    }
    catch( Exception e ) {
      fail();
    }

    stats = xm.getStats();
    assertEquals( 5, stats.getTotalRecords() );
    assertEquals( 3, stats.getTotalBadRecords() );

    badrecs = xm.getBadRecords();
    assertEquals( "[[BadRecord:SEMANTIC,tag=que,recnum=2,fields=[bad, q2, t2],msg=bad,context=BadRecordContext:brc2], [BadRecord:SEMANTIC,tag=que,recnum=4,fields=[bad, q4, t4],msg=bad,context=BadRecordContext:brc2], [BadRecord:SEMANTIC,tag=que,recnum=5,fields=[bad, q5, t5],msg=bad,context=BadRecordContext:brc2]]", badrecs.toString() );

  }



  public void testListener() throws Exception {
    File       xf = RBTestUtil.findTestFile("com/ricebridge/xmlman/test/badrec.xml");
    RecordSpec rs = new RecordSpec( "//que", 
                                    new String[] {"@rec","@q","//h:p[@class='t']"} );
    XmlManager xm = new XmlManager();
    XmlSpec    xs = xm.getXmlSpec(); 
    xs.addNamespace("h","html");

    SimpleBadRecordListener sbrl = new SimpleBadRecordListener();
    xm.setBadRecordListener( sbrl );
    try {
      xm.load( xf, rs, new FailingRecordListener() );
    }
    catch( XmlManagerException xme ) {
      assertTrue( XmlManagerException.CODE_bad_record == xme.getCode() );      
      BadRecord br = xme.getBadRecord();

      Stats stats = xm.getStats();
      assertEquals( 2, stats.getTotalRecords() );
      assertEquals( 1, stats.getTotalBadRecords() );

      List badrecs = xm.getBadRecords();
      assertEquals( "["+br+"]", badrecs.toString() );
    
      badrecs = sbrl.getBadRecords();
      assertEquals( "["+br+"]", badrecs.toString() );
    }
    catch( Exception e ) {
      fail();
    }

    
    BadRecordContext brc3 = new BadRecordContext("brc3");
    sbrl = new SimpleBadRecordListener();
    xm.setBadRecordListener( sbrl );
    xs.setIgnoreBadRecords( true );
    try {
      xm.load( xf, rs, new FailingRecordListener(brc3) );
    }
    catch( Exception e ) {
      fail();
    }

    Stats stats = xm.getStats();
    assertEquals( 5, stats.getTotalRecords() );
    assertEquals( 3, stats.getTotalBadRecords() );

    String brs = "[[BadRecord:SEMANTIC,tag=que,recnum=2,fields=[bad, q2, t2],msg=bad,context=BadRecordContext:brc3], [BadRecord:SEMANTIC,tag=que,recnum=4,fields=[bad, q4, t4],msg=bad,context=BadRecordContext:brc3], [BadRecord:SEMANTIC,tag=que,recnum=5,fields=[bad, q5, t5],msg=bad,context=BadRecordContext:brc3]]";

    List badrecs = xm.getBadRecords();
    assertEquals( brs, badrecs.toString() );
    
    badrecs = sbrl.getBadRecords();
    assertEquals( brs, badrecs.toString() );
  }



  // tests for BadRecordListener

  public static class BadRecordContext {
    public String iValue;
    public BadRecordContext( String pValue ) { iValue = pValue; } 
    public String toString() { return "BadRecordContext:"+iValue; }
  }


  public static class FailingRecordListener extends RecordListenerSupport {

    private BadRecordContext iBRC = null;

    public FailingRecordListener() {}

    public FailingRecordListener( BadRecordContext pBRC) { iBRC = pBRC; }

    public BadRecord handleRecordImpl( String[] pRecord, long pRecordNumber ) {
      if( "bad".equals(pRecord[0]) ) {
        if( null == iBRC ) {
          return new BadRecord( "que", pRecordNumber, pRecord, "bad");
        }
        else {
          return new BadRecord( "que", pRecordNumber, pRecord, "bad", iBRC );
        }
      }

      return null;
    }
  }


  public static class SimpleBadRecordListener extends CollectingBadRecordListener {
    private ArrayList iBadRecs = new ArrayList();
    protected void handleBadRecordImpl( BadRecord pBadRecord ) {
      iBadRecs.add( pBadRecord );
    }
    protected List getBadRecordsImpl() {
      return iBadRecs;
    }
  }

}





Syntax Highlighting created using the com.Ostermiller.Syntax package.
Thursday, February 23 2006 at 16:47