@Test
  public void verifyPathsThatAreNotFilesAreCorrectlyReported() throws CmdLineException {
    // All files will be directories now
    FakeProjectFilesystem filesystem =
        new FakeProjectFilesystem() {
          @Override
          public File getFileForRelativePath(String pathRelativeToProjectRoot) {
            return new ExistingDirectoryFile(getProjectRoot(), pathRelativeToProjectRoot);
          }
        };

    // Empty graph
    MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<BuildRule>();
    DependencyGraph graph = new DependencyGraph(mutableGraph);

    // Inputs that should be treated as "non-files", i.e. as directories
    String[] args =
        new String[] {"java/somefolder/badfolder", "java/somefolder", "com/test/subtest"};
    ImmutableSet<String> inputs = ImmutableSet.copyOf(args);

    // Create options
    AuditOwnerOptions options = getOptions(args);

    // Create command under test
    AuditOwnerCommand command = createAuditOwnerCommand(filesystem);

    // Generate report and verify nonFileInputs are filled in as expected.
    AuditOwnerCommand.OwnersReport report = command.generateOwnersReport(graph, options);
    assertTrue(report.owners.isEmpty());
    assertTrue(report.nonExistentInputs.isEmpty());
    assertTrue(report.inputsWithNoOwners.isEmpty());
    assertEquals(inputs, report.nonFileInputs);
  }
  /** Verify that owners are correctly detected: - one owner, multiple inputs, json output */
  @Test
  public void verifyInputsWithOneOwnerAreCorrectlyReportedInJson()
      throws CmdLineException, IOException {
    // All files will be directories now
    FakeProjectFilesystem filesystem =
        new FakeProjectFilesystem() {
          @Override
          public File getFileForRelativePath(String pathRelativeToProjectRoot) {
            return new ExistingFile(getProjectRoot(), pathRelativeToProjectRoot);
          }
        };

    // Create inputs
    String[] args =
        new String[] {
          "java/somefolder/badfolder/somefile.java",
          "java/somefolder/perfect.java",
          "com/test/subtest/random.java"
        };
    ImmutableSortedSet<Path> inputs = MorePaths.asPaths(ImmutableSortedSet.copyOf(args));

    // Build rule that owns all inputs
    BuildTarget target = new BuildTarget("//base/name", "name");
    BuildRule ownerRule = new StubBuildRule(target, inputs);

    // Create graph
    MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<BuildRule>();
    mutableGraph.addNode(ownerRule);

    DependencyGraph graph = new DependencyGraph(mutableGraph);

    // Create options
    AuditOwnerOptions options = getOptions(args);

    // Create command under test
    AuditOwnerCommand command = createAuditOwnerCommand(filesystem);

    // Generate report and verify nonFileInputs are filled in as expected.
    AuditOwnerCommand.OwnersReport report = command.generateOwnersReport(graph, options);
    command.printOwnersOnlyJsonReport(report);

    String expectedJson =
        Joiner.on("")
            .join(
                "{",
                "\"com/test/subtest/random.java\":[\"//base/name:name\"],",
                "\"java/somefolder/badfolder/somefile.java\":[\"//base/name:name\"],",
                "\"java/somefolder/perfect.java\":[\"//base/name:name\"]",
                "}");

    assertEquals(expectedJson, console.getTextWrittenToStdOut());
    assertEquals("", console.getTextWrittenToStdErr());
  }
  /** Verify that owners are correctly detected: - inputs that belong to multiple targets */
  @Test
  public void verifyInputsWithMultipleOwnersAreCorrectlyReported() throws CmdLineException {
    // All files will be directories now
    FakeProjectFilesystem filesystem =
        new FakeProjectFilesystem() {
          @Override
          public File getFileForRelativePath(String pathRelativeToProjectRoot) {
            return new ExistingFile(getProjectRoot(), pathRelativeToProjectRoot);
          }
        };

    // Create inputs
    String[] args =
        new String[] {
          "java/somefolder/badfolder/somefile.java",
          "java/somefolder/perfect.java",
          "com/test/subtest/random.java"
        };
    ImmutableSortedSet<InputRule> inputs =
        InputRule.inputPathsAsInputRules(ImmutableSortedSet.copyOf(args));

    // Build rule that owns all inputs
    BuildTarget target1 = BuildTargetFactory.newInstance("//base/name1", "name1");
    BuildTarget target2 = BuildTargetFactory.newInstance("//base/name2", "name2");
    BuildRule owner1Rule = new StubBuildRule(target1, inputs);
    BuildRule owner2Rule = new StubBuildRule(target2, inputs);

    // Create graph
    MutableDirectedGraph<BuildRule> mutableGraph = new MutableDirectedGraph<BuildRule>();
    mutableGraph.addNode(owner1Rule);
    mutableGraph.addNode(owner2Rule);

    DependencyGraph graph = new DependencyGraph(mutableGraph);

    // Create options
    AuditOwnerOptions options = getOptions(args);

    // Create command under test
    AuditOwnerCommand command = createAuditOwnerCommand(filesystem);

    // Generate report and verify nonFileInputs are filled in as expected.
    AuditOwnerCommand.OwnersReport report = command.generateOwnersReport(graph, options);
    assertTrue(report.nonFileInputs.isEmpty());
    assertTrue(report.nonExistentInputs.isEmpty());
    assertTrue(report.inputsWithNoOwners.isEmpty());

    assertTrue(report.owners.containsKey(owner1Rule));
    assertTrue(report.owners.containsKey(owner2Rule));
    assertEquals(owner1Rule.getInputs(), report.owners.get(owner1Rule));
    assertEquals(owner2Rule.getInputs(), report.owners.get(owner2Rule));
  }
  /** Verify that owners are correctly detected: - one owner, multiple inputs */
  @Test
  public void verifyInputsWithOneOwnerAreCorrectlyReported()
      throws CmdLineException, IOException, InterruptedException {
    FakeProjectFilesystem filesystem =
        new FakeProjectFilesystem() {
          @Override
          public File getFileForRelativePath(String pathRelativeToProjectRoot) {
            return new ExistingFile(getRootPath(), pathRelativeToProjectRoot);
          }
        };

    ImmutableSet<String> inputs =
        ImmutableSet.of(
            "java/somefolder/badfolder/somefile.java",
            "java/somefolder/perfect.java",
            "com/test/subtest/random.java");
    ImmutableSet<Path> inputPaths = MorePaths.asPaths(inputs);

    BuildTarget target = BuildTargetFactory.newInstance("//base:name");
    TargetNode<?> targetNode = createTargetNode(target, inputPaths);

    CommandRunnerParams params = createAuditOwnerCommandRunnerParams(filesystem);
    AuditOwnerCommand.OwnersReport report =
        AuditOwnerCommand.generateOwnersReport(params, targetNode, inputs, false);
    assertTrue(report.nonFileInputs.isEmpty());
    assertTrue(report.nonExistentInputs.isEmpty());
    assertTrue(report.inputsWithNoOwners.isEmpty());

    assertEquals(inputs.size(), report.owners.size());
    assertTrue(report.owners.containsKey(targetNode));
    assertEquals(targetNode.getInputs(), report.owners.get(targetNode));
  }
  @Test
  public void verifyMissingFilesAreCorrectlyReported()
      throws CmdLineException, IOException, InterruptedException {
    // All files will be directories now
    FakeProjectFilesystem filesystem =
        new FakeProjectFilesystem() {
          @Override
          public File getFileForRelativePath(String pathRelativeToProjectRoot) {
            return new MissingFile(getRootPath(), pathRelativeToProjectRoot);
          }
        };

    // Inputs that should be treated as missing files
    ImmutableSet<String> inputs =
        ImmutableSet.of(
            "java/somefolder/badfolder/somefile.java",
            "java/somefolder/perfect.java",
            "com/test/subtest/random.java");

    BuildTarget target = BuildTargetFactory.newInstance("//base:name");
    TargetNode<?> targetNode = createTargetNode(target, ImmutableSet.<Path>of());

    CommandRunnerParams params = createAuditOwnerCommandRunnerParams(filesystem);
    AuditOwnerCommand.OwnersReport report =
        AuditOwnerCommand.generateOwnersReport(params, targetNode, inputs, false);
    assertTrue(report.owners.isEmpty());
    assertTrue(report.nonFileInputs.isEmpty());
    assertTrue(report.inputsWithNoOwners.isEmpty());
    assertEquals(inputs, report.nonExistentInputs);
  }
 @Override
 public ImmutableSet<QueryTarget> getFileOwners(ImmutableList<String> files)
     throws InterruptedException, QueryException {
   try {
     AuditOwnerCommand.OwnersReport report =
         AuditOwnerCommand.buildOwnersReport(
             params, parserConfig, buildFileTree, files, /* guessForDeletedEnabled */ false);
     return getTargetsFromBuildTargetsContainer(report.owners.keySet());
   } catch (BuildFileParseException | BuildTargetException | IOException e) {
     throw new QueryException("Could not parse build targets.\n%s", e.getMessage());
   }
 }
  /** Verify that owners are correctly detected: - one owner, multiple inputs, json output */
  @Test
  public void verifyInputsWithOneOwnerAreCorrectlyReportedInJson()
      throws CmdLineException, IOException, InterruptedException {
    FakeProjectFilesystem filesystem =
        new FakeProjectFilesystem() {
          @Override
          public File getFileForRelativePath(String pathRelativeToProjectRoot) {
            return new ExistingFile(getRootPath(), pathRelativeToProjectRoot);
          }
        };

    ImmutableSet<String> inputs =
        ImmutableSet.of(
            "java/somefolder/badfolder/somefile.java",
            "java/somefolder/perfect.java",
            "com/test/subtest/random.java");
    ImmutableSortedSet<Path> inputPaths = MorePaths.asPaths(inputs);

    BuildTarget target = BuildTargetFactory.newInstance("//base/name:name");
    TargetNode<?> targetNode = createTargetNode(target, inputPaths);

    AuditOwnerCommand command = new AuditOwnerCommand();
    CommandRunnerParams params = createAuditOwnerCommandRunnerParams(filesystem);
    AuditOwnerCommand.OwnersReport report =
        AuditOwnerCommand.generateOwnersReport(params, targetNode, inputs, false);
    command.printOwnersOnlyJsonReport(params, report);

    String expectedJson =
        Joiner.on("")
            .join(
                "{",
                "\"com/test/subtest/random.java\":[\"//base/name:name\"],",
                "\"java/somefolder/badfolder/somefile.java\":[\"//base/name:name\"],",
                "\"java/somefolder/perfect.java\":[\"//base/name:name\"]",
                "}");

    assertEquals(expectedJson, console.getTextWrittenToStdOut());
    assertEquals("", console.getTextWrittenToStdErr());
  }