package expectj;

import java.util.Date;
import java.util.concurrent.TimeoutException;

import junit.framework.TestCase;
import expectj.test.StagedSpawnable;

/**
 * Verify that the different expect() methods of {@link SpawnedProcess} work as expected.
 * @author johan.walles@gmail.com
 */
public class TestExpect extends TestCase
{
    /**
     * Generate a SpawnedProcess producing the indicated output on stdout.
     * @param strings The strings to print to stdout.  Strings will be produced with
     * 500ms between each.
     * @return A new SpawnedProcess.
     * @throws Exception when things go wrong.
     */
    private SpawnedProcess getSpawnedProcess(final String ... strings)
    throws Exception
    {
        return new ExpectJ("/dev/null", -1).spawn(new StagedSpawnable(strings));
    }
    
    /**
     * Test that we can find simple strings.
     * @throws Exception if things go wrong.
     */
    public void testExpectStrings()
    throws Exception
    {
        SpawnedProcess testMe = getSpawnedProcess("flaska", "gris");
        testMe.expect("flaska");
        testMe.expect("gris");
    }

    /**
     * Test that we can find simple strings with an unexpected string in between.
     * @throws Exception if things go wrong.
     */
    public void testExpectStringsWithExtraData()
    throws Exception
    {
        SpawnedProcess testMe = getSpawnedProcess("flaska", "nyckel", "gris");
        testMe.expect("flaska");
        testMe.expect("gris");
    }
    
    /**
     * Test that we time out properly when we don't find what we're looking for.
     * @throws Exception if things go wrong.
     */
    public void testTimeout()
    throws Exception 
    {
        // Test longer duration output than timeout
        SpawnedProcess testMe = getSpawnedProcess("flaska", "nyckel", "gris", "hink");
        Date beforeTimeout = new Date();
        try {
            testMe.expect("klubba", 1);
            fail("Test should have timed out");
        } catch (TimeoutException expected) {
            // Ignoring expected exception
        }
        Date afterTimeout = new Date();
        
        long msElapsed = afterTimeout.getTime() - beforeTimeout.getTime();
        if (msElapsed < 900 || msElapsed > 1100) {
            fail("Should have timed out after 1s, timed out in " + msElapsed + "ms");
        }
    }
}

@@ -1486,32 +1486,311 @@
  %7D%0A    %0A    /**%0A
+     * Test that we get notified about closes.%0A     * @throws Exception if things go wrong.%0A     */%0A    public void testExpectClose()%0A    throws Exception%0A    %7B%0A        SpawnedProcess testMe = getSpawnedProcess(%22flaska%22, %22gris%22);%0A        testMe.expectClose();%0A    %7D%0A    %0A    /**%0A
      * Test that
@@ -1854,16 +1854,16 @@
 ng for.%0A
-
      * @
@@ -2040,32 +2040,44 @@
 Process testMe =
+%0A           
  getSpawnedProce
@@ -2113,16 +2113,32 @@
 , %22hink%22
+, %22bil%22, %22stork%22
 );%0A     
@@ -2245,20 +2245,24 @@
   fail(%22
-Test
+expect()
  should 
@@ -2575,66 +2575,669 @@
 il(%22
-Should have timed out after 1s, timed out in %22 + msElapsed
+expect() should have timed out after 1s, timed out in %22%0A                 + msElapsed%0A                 + %22ms%22);%0A        %7D%0A        %0A        beforeTimeout = new Date();%0A        try %7B%0A            testMe.expectClose(1);%0A            fail(%22expectClose() should have timed out%22);%0A        %7D catch (TimeoutException expected) %7B%0A            // Ignoring expected exception%0A        %7D%0A        afterTimeout = new Date();%0A        %0A        msElapsed = afterTimeout.getTime() - beforeTimeout.getTime();%0A        if (msElapsed %3C 900 %7C%7C msElapsed %3E 1100) %7B%0A            fail(%22expectClose() should have timed out after 1s, timed out in %22%0A                 + msElapsed %0A                
  + %22

Test expectClose().