private static void validateAnalyzerMessage(
     Map<IssueAttribute, String> attrs, AnalyzerMessage analyzerMessage) {
   Double effortToFix = analyzerMessage.getCost();
   if (effortToFix != null) {
     assertEquals(Integer.toString(effortToFix.intValue()), attrs, IssueAttribute.EFFORT_TO_FIX);
   }
   AnalyzerMessage.TextSpan textSpan = analyzerMessage.primaryLocation();
   assertEquals(normalizeColumn(textSpan.startCharacter), attrs, IssueAttribute.START_COLUMN);
   assertEquals(Integer.toString(textSpan.endLine), attrs, IssueAttribute.END_LINE);
   assertEquals(normalizeColumn(textSpan.endCharacter), attrs, IssueAttribute.END_COLUMN);
   if (attrs.containsKey(IssueAttribute.SECONDARY_LOCATIONS)) {
     List<AnalyzerMessage> secondaryLocations = analyzerMessage.secondaryLocations;
     Multiset<String> actualLines = HashMultiset.create();
     for (AnalyzerMessage secondaryLocation : secondaryLocations) {
       actualLines.add(Integer.toString(secondaryLocation.getLine()));
     }
     List<String> expected =
         Lists.newArrayList(
             Splitter.on(",")
                 .omitEmptyStrings()
                 .trimResults()
                 .split(attrs.get(IssueAttribute.SECONDARY_LOCATIONS)));
     List<String> unexpected = new ArrayList<>();
     for (String actualLine : actualLines) {
       if (expected.contains(actualLine)) {
         expected.remove(actualLine);
       } else {
         unexpected.add(actualLine);
       }
     }
     if (!expected.isEmpty() || !unexpected.isEmpty()) {
       Fail.fail("Secondary locations: expected: " + expected + " unexpected:" + unexpected);
     }
   }
 }
 private void assertSingleIssue(Set<AnalyzerMessage> issues) {
   Preconditions.checkState(
       issues.size() == 1, "A single issue is expected with line " + expectFileIssueOnline);
   AnalyzerMessage issue = Iterables.getFirst(issues, null);
   assertThat(issue.getLine()).isEqualTo(expectFileIssueOnline);
   assertThat(issue.getMessage()).isEqualTo(expectFileIssue);
 }
 private static void validateIssue(
     Multimap<Integer, Map<IssueAttribute, String>> expected,
     List<Integer> unexpectedLines,
     AnalyzerMessage issue,
     boolean isLinear) {
   int line = issue.getLine();
   if (expected.containsKey(line)) {
     Map<IssueAttribute, String> attrs = Iterables.getLast(expected.get(line));
     assertEquals(issue.getMessage(), attrs, IssueAttribute.MESSAGE);
     Double cost = issue.getCost();
     if (cost != null) {
       assertEquals(Integer.toString(cost.intValue()), attrs, IssueAttribute.EFFORT_TO_FIX);
     } else if (isLinear) {
       Fail.fail("A cost should be provided for a rule with linear remediation function");
     }
     validateAnalyzerMessage(attrs, issue);
     expected.remove(line, attrs);
   } else {
     unexpectedLines.add(line);
   }
 }