Continuing removing GUAVA dependencies from junitrunner (junit.runner.sharding
& util).

Bazel users that are using a different Guava version than the one in the
junitrunner jar are getting an IncompatibleClassChangeError. Rewriting
parts of junitrunner code so it won't depend on Guava anymore.

Continuing progress on issue #1150.

Removing most of Guava dependencies from junit.runner.sharding. A more
significant change regards rewriting Guava method
assertThat().containsExactlyElementsIn().

Also removing previous trailing spaces.

--
MOS_MIGRATED_REVID=129992951
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/HashBackedShardingFilter.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/HashBackedShardingFilter.java
index aa641a4..331e147 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/HashBackedShardingFilter.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/HashBackedShardingFilter.java
@@ -14,8 +14,6 @@
 
 package com.google.testing.junit.runner.sharding;
 
-import com.google.common.base.Preconditions;
-
 import org.junit.runner.Description;
 import org.junit.runner.manipulation.Filter;
 
@@ -28,8 +26,9 @@
   private final int totalShards;
 
   public HashBackedShardingFilter(int shardIndex, int totalShards) {
-    Preconditions.checkArgument(shardIndex >= 0);
-    Preconditions.checkArgument(totalShards > shardIndex);
+    if (shardIndex < 0 || totalShards <= shardIndex) {
+      throw new IllegalArgumentException();
+    }
     this.shardIndex = shardIndex;
     this.totalShards = totalShards;
   }
@@ -43,7 +42,9 @@
     if (mod < 0) {
       mod += totalShards;
     }
-    Preconditions.checkState(mod >= 0 && mod < totalShards);
+    if (mod < 0 || mod >= totalShards) {
+      throw new IllegalStateException();
+    }
 
     return mod == shardIndex;
   }
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/RoundRobinShardingFilter.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/RoundRobinShardingFilter.java
index 09c9e31..d754436 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/RoundRobinShardingFilter.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/RoundRobinShardingFilter.java
@@ -14,12 +14,6 @@
 
 package com.google.testing.junit.runner.sharding;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-
-import org.junit.runner.Description;
-import org.junit.runner.manipulation.Filter;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -27,6 +21,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
 
 /**
  * Implements the round-robin sharding strategy.
@@ -40,17 +36,18 @@
  * sharding, but are done so that this filter can be compared in tests.
  */
 public final class RoundRobinShardingFilter extends Filter {
-  @VisibleForTesting
+  // VisibleForTesting
   final Map<Description, Integer> testToShardMap;
-  @VisibleForTesting
+  // VisibleForTesting
   final int shardIndex;
-  @VisibleForTesting
+  // VisibleForTesting
   final int totalShards;
 
   public RoundRobinShardingFilter(Collection<Description> testDescriptions,
       int shardIndex, int totalShards) {
-    Preconditions.checkArgument(shardIndex >= 0);
-    Preconditions.checkArgument(totalShards > shardIndex);
+    if (shardIndex < 0 || totalShards <= shardIndex) {
+      throw new IllegalArgumentException();
+    }
     this.testToShardMap = buildTestToShardMap(testDescriptions);
     this.shardIndex = shardIndex;
     this.totalShards = totalShards;
@@ -74,9 +71,10 @@
     // same shard.
     int index = 0;
     for (Description description : sortedDescriptions) {
-      Preconditions.checkArgument(description.isTest(),
-          "Test suite should not be included in the set of tests to shard: %s",
-          description.getDisplayName());
+      if (!description.isTest()) {
+        throw new IllegalArgumentException("Test suite should not be included in the set of tests "
+            + "to shard: " + description.getDisplayName());
+      }
       map.put(description, index);
       index++;
     }
@@ -102,7 +100,7 @@
     return "round robin sharding filter";
   }
 
-  @VisibleForTesting
+  // VisibleForTesting
   static class DescriptionComparator implements Comparator<Description> {
     @Override
     public int compare(Description d1, Description d2) {
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/ShardingEnvironment.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/ShardingEnvironment.java
index 366f25a..dcdbedb 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/ShardingEnvironment.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/ShardingEnvironment.java
@@ -14,12 +14,8 @@
 
 package com.google.testing.junit.runner.sharding;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.io.Files;
-
 import java.io.File;
 import java.io.IOException;
-
 import javax.inject.Inject;
 
 /**
@@ -76,11 +72,13 @@
     touchShardFile(shardFile);
   }
 
-  @VisibleForTesting
+  // VisibleForTesting
   static void touchShardFile(File shardFile) {
     if (shardFile != null) {
       try {
-        Files.touch(shardFile);
+        if (!shardFile.createNewFile() && !shardFile.setLastModified(System.currentTimeMillis())) {
+          throw new IOException("Unable to update modification time of " + shardFile);
+        }
       } catch (IOException e) {
         throw new RuntimeException("Error writing shard file " + shardFile, e);
       }
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/testing/ShardingFilterTestCase.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/testing/ShardingFilterTestCase.java
index 668c790..2d30acc 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/testing/ShardingFilterTestCase.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/sharding/testing/ShardingFilterTestCase.java
@@ -14,23 +14,22 @@
 
 package com.google.testing.junit.runner.sharding.testing;
 
-import static com.google.common.truth.Truth.assertThat;
-
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ListMultimap;
 import com.google.testing.junit.runner.sharding.api.ShardingFilterFactory;
-
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
 import junit.framework.TestCase;
-
 import org.junit.Test;
 import org.junit.runner.Description;
 import org.junit.runner.manipulation.Filter;
 
-import java.util.Deque;
-import java.util.LinkedList;
-import java.util.List;
-
 /**
  * Common base class for all sharding filter tests.
  */
@@ -42,7 +41,7 @@
    * shard index, and total number of shards.
    */
   protected abstract ShardingFilterFactory createShardingFilterFactory();
-  
+
   public final void testShardingIsCompleteAndPartitioned_oneShard() {
     assertShardingIsCompleteAndPartitioned(createFilters(TEST_DESCRIPTIONS, 1), TEST_DESCRIPTIONS);
   }
@@ -90,11 +89,11 @@
         .build();
     assertShardingIsStable(createFilters(descriptions, 7), descriptions);
   }
-  
-  public final void testShouldRunTestSuite() {    
-    Description testSuiteDescription = createTestSuiteDescription();   
-    Filter filter = createShardingFilterFactory().createFilter(TEST_DESCRIPTIONS, 0, 1); 
-    assertTrue(filter.shouldRun(testSuiteDescription));    
+
+  public final void testShouldRunTestSuite() {
+    Description testSuiteDescription = createTestSuiteDescription();
+    Filter filter = createShardingFilterFactory().createFilter(TEST_DESCRIPTIONS, 0, 1);
+    assertTrue(filter.shouldRun(testSuiteDescription));
   }
 
   /**
@@ -109,7 +108,7 @@
     }
     return builder.build();
   }
-  
+
   protected static final List<Filter> createFilters(List<Description> descriptions, int numShards,
       ShardingFilterFactory factory) {
     ImmutableList.Builder<Filter> builder = ImmutableList.builder();
@@ -118,7 +117,7 @@
     }
     return builder.build();
   }
-  
+
   protected final List<Filter> createFilters(List<Description> descriptions, int numShards) {
     return createFilters(descriptions, numShards, createShardingFilterFactory());
   }
@@ -199,10 +198,10 @@
   protected static void assertShardingIsCompleteAndPartitioned(List<Filter> filters,
       List<Description> descriptions) {
     ListMultimap<Filter, Description> run = simulateTestRun(filters, descriptions);
-    assertThat(run.values()).containsExactlyElementsIn(descriptions);
+    assertThatCollectionContainsExactlyElementsInList(run.values(), descriptions);
 
     simulateSelfRandomizingTestRun(filters, descriptions);
-    assertThat(run.values()).containsExactlyElementsIn(descriptions);
+    assertThatCollectionContainsExactlyElementsInList(run.values(), descriptions);
   }
 
   /**
@@ -223,4 +222,49 @@
         simulateSelfRandomizingTestRun(filters, descriptions);
     assertEquals(randomizedRun1, randomizedRun2);
   }
+
+  /**
+   * Returns whether the Collection and the List contain exactly the same elements with the same
+   * frequency, ignoring the ordering.
+   */
+  private static void assertThatCollectionContainsExactlyElementsInList(
+      Collection<Description> actual, List<Description> expectedDescriptions) {
+    String basicAssertionMessage = "Elements of collection " + actual + " are not the same as the "
+        + "elements of expected list " + expectedDescriptions + ". ";
+    if (actual.size() != expectedDescriptions.size()) {
+      throw new AssertionError(basicAssertionMessage + "The number of elements is different.");
+    }
+
+    List<Description> actualDescriptions = new ArrayList<Description>(actual);
+    // Keeps track of already reviewed descriptions, so they won't be checked again when next
+    // encountered.
+    // Note: this algorithm has O(n^2) time complexity and will be slow for large inputs.
+    Set<Description> reviewedDescriptions = new HashSet<>();
+    for (int i = 0; i < actual.size(); i++) {
+      Description currDescription = actualDescriptions.get(i);
+      // If already reviewed, skip.
+      if (reviewedDescriptions.contains(currDescription)) {
+        continue;
+      }
+      int actualFreq = 0;
+      int expectedFreq = 0;
+      // Count the frequency of the current description in both lists.
+      for (int j = 0; j < actual.size(); j++) {
+        if (currDescription.equals(actualDescriptions.get(j))) {
+          actualFreq++;
+        }
+        if (currDescription.equals(expectedDescriptions.get(j))) {
+          expectedFreq++;
+        }
+      }
+      if (actualFreq < expectedFreq) {
+        throw new AssertionError(basicAssertionMessage + "There are " + (expectedFreq - actualFreq)
+            + " missing occurrences of " + currDescription + ".");
+      } else if (actualFreq > expectedFreq) {
+        throw new AssertionError(basicAssertionMessage + "There are " + (actualFreq - expectedFreq)
+            + " unexpected occurrences of " + currDescription + ".");
+      }
+      reviewedDescriptions.add(currDescription);
+    }
+  }
 }
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/GoogleTestSecurityManager.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/GoogleTestSecurityManager.java
index 623b1e6..d8f6426 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/GoogleTestSecurityManager.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/util/GoogleTestSecurityManager.java
@@ -14,8 +14,6 @@
 
 package com.google.testing.junit.runner.util;
 
-import com.google.common.annotations.VisibleForTesting;
-
 import java.security.Permission;
 
 /**
@@ -68,7 +66,7 @@
   }
 
   public boolean isEnabled() { return enabled; }
-  
+
   /**
    * If {@code GoogleTestSecurityManager} is the current security manager,
    * uninstall it.
@@ -78,7 +76,7 @@
     if (securityManager instanceof GoogleTestSecurityManager) {
       GoogleTestSecurityManager testSecurityManager = (GoogleTestSecurityManager) securityManager;
       boolean wasEnabled = testSecurityManager.isEnabled();
-      
+
       try {
         testSecurityManager.setEnabled(false);
         System.setSecurityManager(null);
@@ -92,7 +90,8 @@
    * The security manager can be disabled by the test runner (or any other
    * class in the same package) to allow it to exit with a meaningful result
    * code.
+   *
+   * VisibleForTesting
    */
-  @VisibleForTesting
   synchronized void setEnabled(boolean enabled) { this.enabled = enabled; }
 }