import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.regex.Pattern;

import org.junit.Assert;
import org.junit.Test;
import org.mitre.synthea.TestHelper;
import org.mitre.synthea.engine.Generator;
import org.mitre.synthea.helpers.Config;

public class AppTest {

  @Test
  public void testApp() throws Exception {
    TestHelper.exportOff();
    String[] args = {"-s", "0", "-p", "3", "Massachusetts", "Bedford"};
    final PrintStream original = System.out;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final PrintStream print = new PrintStream(out, true);
    System.setOut(print);
    App.main(args);
    out.flush();
    String output = out.toString();
    Assert.assertTrue(output.contains("Running with options:"));
    Assert.assertTrue(output.contains("Population:"));
    Assert.assertTrue(output.contains("Seed:"));
    Assert.assertTrue(output.contains("Location:"));
    Assert.assertTrue(output.contains("alive=3"));
    Assert.assertTrue(output.contains("dead="));
    Assert.assertTrue(output.contains("Location: Bedford, Massachusetts"));
    System.setOut(original);
  }

  @Test
  public void testAppWithGender() throws Exception {
    TestHelper.exportOff();
    String[] args = {"-s", "0", "-p", "4", "-g", "M"};
    final PrintStream original = System.out;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final PrintStream print = new PrintStream(out, true);
    System.setOut(print);
    App.main(args);
    out.flush();
    String output = out.toString();
    Assert.assertTrue(output.contains("Running with options:"));
    Assert.assertTrue(output.contains("Gender: M"));
    Assert.assertTrue(output.contains("Seed:"));
    Assert.assertTrue(output.contains("alive=4"));
    Assert.assertTrue(output.contains("dead="));
    Assert.assertFalse(output.contains("y/o F"));
    Assert.assertTrue(output.contains("Location: " + Generator.DEFAULT_STATE));
    System.setOut(original);
  }

  @Test
  public void testAppWithAges() throws Exception {
    TestHelper.exportOff();
    String[] args = {"-s", "0", "-p", "3", "-a", "30-39"};
    final PrintStream original = System.out;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final PrintStream print = new PrintStream(out, true);
    System.setOut(print);
    App.main(args);
    out.flush();
    String output = out.toString();
    Assert.assertTrue(output.contains("Running with options:"));
    Assert.assertTrue(output.contains("Seed:"));
    Assert.assertTrue(output.contains("alive=3"));
    Assert.assertTrue(output.contains("Location: " + Generator.DEFAULT_STATE));
    String regex = "(.\n)*(3[0-9] y/o)(.\n)*";
    Assert.assertTrue(Pattern.compile(regex).matcher(output).find());
    regex = "(.\n)*(\\(([0-9]|[0-2][0-9]|[4-9][0-9]) y/o)(.\n)*";
    Assert.assertFalse(output.matches(regex));
    System.setOut(original);
  }


  @Test
  public void testAppWithDifferentLocation() throws Exception {
    TestHelper.exportOff();
    String[] args = {"-s", "0", "-p", "3", "Utah", "Salt Lake City"};
    final PrintStream original = System.out;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final PrintStream print = new PrintStream(out, true);
    System.setOut(print);
    App.main(args);
    out.flush();
    String output = out.toString();
    Assert.assertTrue(output.contains("Running with options:"));
    Assert.assertTrue(output.contains("Seed:"));
    Assert.assertTrue(output.contains("alive=3"));
    Assert.assertTrue(output.contains("Location: Salt Lake City, Utah"));
    System.setOut(original);
  }
  
  @Test
  public void testAppWithConfigSetting() throws Exception {
    TestHelper.exportOff();
    Config.set("test_key", "pre-test value");
    String[] args = {"-s", "0", "-p", "0",
        "--test_key", "changed value", "--exporter.fhir.export=true"};
    App.main(args);
    
    Assert.assertEquals("changed value", Config.get("test_key"));
    Assert.assertEquals("true", Config.get("exporter.fhir.export"));
  }
  
  @Test
  public void testInvalidArgs() throws Exception {
    String[] args = {"-s", "foo", "-p", "foo", "Massachusetts", "Bedford"};
    final PrintStream original = System.out;
    final PrintStream originalErr = System.err;
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final PrintStream print = new PrintStream(out, true);
    System.setOut(print);
    System.setErr(print);
    App.main(args);
    out.flush();
    String output = out.toString();
    Assert.assertTrue(output.contains("Usage"));
    Assert.assertFalse(output.contains("Running with options:"));
    System.setOut(original);
    System.setErr(originalErr);
  }

}

@@ -51,32 +51,64 @@
 io.PrintStream;%0A
+import java.util.regex.Matcher;%0A
 import java.util
@@ -3646,26 +3646,891 @@
 ginal);%0A  %7D%0A
+%0A
   
+@Test%0A  public void testAppWithOverflow() throws Exception %7B%0A    TestHelper.exportOff();%0A    String%5B%5D args = %7B%22-s%22, %221%22, %22-p%22, %223%22, %22-o%22, %22false%22%7D;%0A    final PrintStream original = System.out;%0A    final ByteArrayOutputStream out = new ByteArrayOutputStream();%0A    final PrintStream print = new PrintStream(out, true);%0A    System.setOut(print);%0A    App.main(args);%0A    out.flush();%0A    String output = out.toString();%0A    Assert.assertTrue(output.contains(%22Running with options:%22));%0A    Assert.assertTrue(output.contains(%22Seed:%22));%0A    String regex = %22%5C%5C%7Balive=(%5C%5Cd+), dead=(%5C%5Cd+)%5C%5C%7D%22;%0A    Matcher matches = Pattern.compile(regex).matcher(output);%0A    Assert.assertTrue(matches.find());%0A    int alive = Integer.parseInt(matches.group(1));%0A    int dead = Integer.parseInt(matches.group(2));%0A    Assert.assertEquals(alive + dead, 3);%0A    System.setOut(original);%0A  %7D%0A
 %0A  @Test%0A  p

Test the new overflow parameter