@CanIgnoreReturnValue
  public final Ordered containsAtLeastElementsIn(@Nullable Iterable<?> expectedIterable) {
    List<?> actual = Lists.newLinkedList(checkNotNull(this.actual));
    Collection<?> expected = iterableToCollection(expectedIterable);

    List<@Nullable Object> missing = newArrayList();
    List<@Nullable Object> actualNotInOrder = newArrayList();

    boolean ordered = true;
    // step through the expected elements...
    for (Object e : expected) {
      int index = actual.indexOf(e);
      if (index != -1) { // if we find the element in the actual list...
        // drain all the elements that come before that element into actualNotInOrder
        moveElements(actual, actualNotInOrder, index);
        // and remove the element from the actual list
        actual.remove(0);
      } else { // otherwise try removing it from actualNotInOrder...
        if (actualNotInOrder.remove(e)) { // if it was in actualNotInOrder, we're not in order
          ordered = false;
        } else { // if it's not in actualNotInOrder, we're missing an expected element
          missing.add(e);
        }
      }
    }
    // if we have any missing expected elements, fail
    if (!missing.isEmpty()) {
      return failAtLeast(expected, missing);
    }

    return ordered
        ? IN_ORDER
        : new Ordered() {
          @Override
          public void inOrder() {
            ImmutableList.Builder<Fact> facts = ImmutableList.builder();
            facts.add(simpleFact("required elements were all found, but order was wrong"));
            facts.add(fact("expected order for required elements", expected));
            List<Object> actualOrder =
                Lists.newArrayList(checkNotNull(IterableSubject.this.actual));
            if (actualOrder.retainAll(expected)) {
              facts.add(fact("but order was", actualOrder));
              facts.add(fullContents());
              failWithoutActual(facts.build());
            } else {
              failWithActual(facts.build());
            }
          }
        };
  }
@Test
  @SuppressWarnings("ContainsAllElementsInWithVarArgsToContainsAtLeast")
  public void iterableContainsAtLeastElementsInCanUseFactPerElement() {
    expectFailureWhenTestingThat(asList("abc"))
        .containsAtLeastElementsIn(asList("123\n456", "789"));
    assertFailureKeys("missing (2)", "#1", "#2", "---", "expected to contain at least", "but was");
    assertFailureValue("#1", "123\n456");
    assertFailureValue("#2", "789");
  }