package org.androiddaisyreader.model; import org.xml.sax.helpers.AttributesImpl; import junit.framework.TestCase; /** * Unit tests to ensure we can parse timing values correctly from SMIL files. * files. * * The specifications are unclear on how large numbers need be formatted, so I * expect to refine the tests, and the underlying code based on the contents * of actual DAISY books. * * @author Julian Harty * */ public class ExtractTimingValuesTest extends TestCase { private static final String INVALID_NUMBER_WITH_2_DECIMAL_POINTS = "npt=456.12.34s"; private static final String NUMBER_WITHOUT_DECIMAL_POINT = "npt=10s"; private static final String CDATA = "CDATA"; private static final String CLIP_BEGIN = "clip-begin"; private static final String CLIP_BEGIN30 = "clipBegin"; private static final int DAISYFORMAT202 = 202; private static final int DAISYFORMAT30 = 30; private AttributesImpl attributes; protected void setUp() { attributes = new AttributesImpl(); } //Test valid timing for daisy 202 public void testValidTiming() { attributes.addAttribute("", CLIP_BEGIN, "", CDATA, "npt=12.345s"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN, attributes, DAISYFORMAT202); assertEquals("Expected the extracted timing should match", 12345, result); } public void testLargeValidTiming() { attributes.addAttribute("", CLIP_BEGIN, "", CDATA, "npt=123456.789s"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN, attributes, DAISYFORMAT202); assertEquals("Expected the extracted timing should match", 123456789, result); } public void testNumberWithOneDecimalPlace() { attributes.addAttribute("", CLIP_BEGIN, "", CDATA, "npt=456.7s"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN, attributes, DAISYFORMAT202); assertEquals("Expected the extracted timing should match", 456700, result); } public void testNumberWithTwoDecimalPlaces() { attributes.addAttribute("", CLIP_BEGIN, "", CDATA, "npt=456.89s"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN, attributes, DAISYFORMAT202); assertEquals("Expected the extracted timing should match", 456890, result); } public void testNumberWithFourDecimalPlacesIsTrimmedToThree() { attributes.addAttribute("", CLIP_BEGIN, "", CDATA, "npt=456.1234s"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN, attributes, DAISYFORMAT202); assertEquals("Expected the extracted timing should match", 456123, result); } public void testInvalidFormatRaisesNFE() { attributes.addAttribute("", CLIP_BEGIN, "", CDATA, INVALID_NUMBER_WITH_2_DECIMAL_POINTS); try { @SuppressWarnings("unused") int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN, attributes, DAISYFORMAT202); fail("Expected a NumberFormatException for a number with 2 decimal points. Number = " + INVALID_NUMBER_WITH_2_DECIMAL_POINTS); } catch (NumberFormatException nfe) { // Nothing to do, this is the expected behaviour. } } /** * The DAISY 2.02 specification says all numbers should be in SS.S format. * * However, I've ended up writing the code to also accept numbers without * the decimal point. Doing so makes the application more tolerant and * shouldn't adversely affect the behaviour AFAIK. * * This is the relevant test of the new behaviour :) */ public void testNumberWithoutDecimal () { attributes.addAttribute("", CLIP_BEGIN, "", CDATA, NUMBER_WITHOUT_DECIMAL_POINT); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN, attributes, DAISYFORMAT202); assertEquals("Number without a decimal point should be accepted.", 10000, result); } //Test valid timing for daisy 30 public void testNumberWithMilliseconds() { attributes.addAttribute("", CLIP_BEGIN30, "", CDATA, "00:00.00"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN30, attributes, DAISYFORMAT30); assertEquals("Expected the extracted timing should match", 0, result); } public void testNumberWithMilliseconds1() { attributes.addAttribute("", CLIP_BEGIN30, "", CDATA, "00:01.610"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN30, attributes, DAISYFORMAT30); assertEquals("Expected the extracted timing should match", 1610, result); } public void testNumberWithBothMinutesAndMilliseconds() { attributes.addAttribute("", CLIP_BEGIN30, "", CDATA, "01:14.133"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN30, attributes, DAISYFORMAT30); assertEquals("Expected the extracted timing should match", 74133, result); } public void testNumberWithFullFormat() { attributes.addAttribute("", CLIP_BEGIN30, "", CDATA, "01:01:04.100"); int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN30, attributes, DAISYFORMAT30); assertEquals("Expected the extracted timing should match", 3664100, result); } public void testNumberWithInvalidFormat() { attributes.addAttribute("", CLIP_BEGIN30, "", CDATA, "01:01:04.10.0"); try { @SuppressWarnings("unused") int result = ExtractTimingValues.extractTimingAsMilliSeconds(CLIP_BEGIN30, attributes, DAISYFORMAT30); fail("Expected a NumberFormatException for a number with 2 decimal points. Number = " + "01:01:04.10.0"); } catch (NumberFormatException e) { } } }