content: package com.google.javascript.clutz;
  
  import static com.google.common.truth.Truth.assertThat;
  import static org.junit.Assert.*;
  
  import com.google.javascript.jscomp.CompilerOptions;
  import java.io.ByteArrayOutputStream;
  import java.io.PrintStream;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.junit.runners.JUnit4;
  import org.kohsuke.args4j.CmdLineException;
  
  @RunWith(JUnit4.class)
  public class OptionsTest {
  
    @Test
    public void testFullUsage() throws Exception {
      Options opts =
          new Options(
              new String[] {"foo.js", "--externs", "extern1.js", "extern2.js", "-o", "output.d.ts"});
      assertThat(opts.arguments).containsExactly("foo.js");
      assertThat(opts.externs).containsExactly("extern1.js", "extern2.js").inOrder();
      assertThat(opts.output).isEqualTo("output.d.ts");
    }
  
    @Test
    public void testFilterSourcesDepgraphs() throws Exception {
      Options opts =
          new Options(
              new String[] {
                "javascript/closure/other_file_not_in_depgraph.js",
                "javascript/closure/string/string.js",
                "blaze-out/blah/my/blaze-out-file.js",
                "--depgraphs",
                DepgraphTest.DEPGRAPH_PATH.toFile().toString(),
                "--depgraphs_filter_sources",
              });
      // Arguments are filtered by what appears in the depgraph.
      assertThat(opts.arguments)
          .containsExactly(
              "javascript/closure/string/string.js", // kept as a root in depgraph
              "blaze-out/blah/my/blaze-out-file.js") // kept as a non-root in depgraph
          .inOrder();
    }
  
    @Test
    public void testFilterSourcesWithExternsInDepgraphs() throws Exception {
      Options opts =
          new Options(
              new String[] {
                "javascript/closure/string/string.js",
                "--externs",
                "extern1.js",
                "extern2.js",
                "--depgraphs",
                DepgraphTest.DEPGRAPH_PATH.toFile().toString(),
                "--depgraphs_filter_sources",
              });
      // All depgraph externs are added to the externs list.
      assertThat(opts.externs)
          .containsExactly("my/root/extern.js", "my/nonroot/extern.js", "extern1.js", "extern2.js")
          .inOrder();
    }
  
    @Test
    public void testClosureEntryPoint() throws Exception {
      Options opts =
          new Options(
              new String[] {
                "foo.js",
                "--closure_entry_points",
                "ns.entryPoint1",
                "ns.entryPoint2",
                "--externs",
                "extern1.js",
                "extern2.js",
                "-o",
                "output.d.ts"
              });
      assertThat(opts.arguments).containsExactly("foo.js");
      assertThat(opts.entryPoints).containsExactly("ns.entryPoint1", "ns.entryPoint2");
      assertThat(opts.externs).containsExactly("extern1.js", "extern2.js").inOrder();
      assertThat(opts.output).isEqualTo("output.d.ts");
    }
  
    @Test
    public void testHandleEmptyCommandLine() throws Exception {
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      System.setErr(new PrintStream(out));
      try {
        new Options(new String[0]);
        fail("Should throw");
      } catch (CmdLineException expected) {
        assertThat(expected.getMessage()).isEqualTo("No files or externs were given");
      }
    }
  
    @Test
    public void testShouldSupportExternsOnly() throws Exception {
      Options opts = new Options(new String[] {"--externs", "extern1.js"});
      assertThat(opts.externs).containsExactly("extern1.js");
    }
  
    @Test
    public void testShouldPruneRepeatedExterns() throws Exception {
      Options opts =
          new Options(new String[] {"a.js", "extern1.js", "--externs", "extern1.js", "extern2.js"});
      assertThat(opts.externs).containsExactly("extern1.js", "extern2.js");
      assertThat(opts.arguments).containsExactly("a.js");
    }
  
    @Test
    public void testExternsShouldBeUnique() throws Exception {
      Options opts =
          new Options(
              new String[] {
                "--externs",
                "my/root/extern.js",
                "--depgraphs",
                // Depgraph also has my/root/extern.js, and additionally my/nonroot/extern.js.
                DepgraphTest.DEPGRAPH_PATH.toFile().toString(),
              });
      assertThat(opts.externs).containsExactly("my/root/extern.js", "my/nonroot/extern.js");
    }
  
    @Test
    public void testShouldSupportFilePathsWithSpaces() throws Exception {
      Options opts =
          new Options(
              new String[] {
                "--externs", "dir with spaces/common/dom.js", "--externs", "common/browser api.js",
              });
      assertThat(opts.externs)
          .containsExactly("dir with spaces/common/dom.js", "common/browser api.js");
    }
  
    @Test
    public void testPartialInputIgnoresDepgraphNonRootExterns() throws Exception {
      Options opts =
          new Options(
              new String[] {
                "--partialInput",
                // a random file from the depgraph. Not relevant to the test, but we need at least
                // one input.
                "my/thing/static/js/0-bootstrap.js",
                "--depgraphs",
                DepgraphTest.DEPGRAPH_PATH.toFile().toString(),
              });
      assertThat(opts.externs).isEmpty();
    }
  
    @Test
    public void testClosureEnvCustom() throws Exception {
      Options opts =
          new Options(
              new String[] {
                "my/thing/static/js/0-bootstrap.js", "--closure_env", "CUSTOM",
              });
      assertThat(opts.closureEnv).isEqualTo(CompilerOptions.Environment.CUSTOM);
      assertThat(opts.getCompilerOptions().getEnvironment())
          .isEqualTo(CompilerOptions.Environment.CUSTOM);
    }
  
    @Test
    public void testPartialInputIgnoresDepgraphRootExternsIfNotPassedToExterns() throws Exception {
      // Due to "exported" libraries, what the depgraph considers "root" can be incorrect for the
      // purposes of incremental clutz. Arguments and Externs lists should only be filtered down
      // with depgraph info and never extended.
      Options opts =
          new Options(
              new String[] {
                "--partialInput",
                // a random file from the depgraph. Not relevant to the test, but we need at least
                // one input.
                "my/thing/static/js/0-bootstrap.js",
                "--depgraphs",
                DepgraphTest.DEPGRAPH_PATH.toFile().toString(),
              });
      assertThat(opts.externs).isEmpty();
    }
  
    @Test
    public void testStopOption() throws Exception {
      Options opts =
          new Options(
              new String[] {"--externs", "extern1.js", "extern2.js", "--", "foo.js", "bar.js"});
      assertThat(opts.arguments).containsExactly("foo.js", "bar.js").inOrder();
      assertThat(opts.externs).containsExactly("extern1.js", "extern2.js").inOrder();
    }
  }
  