public void expectLogMessage(int level, String tag, Matcher<String> messageMatcher) {
    expectLog(level, tag, messageMatcher, null);
  }
@Test
  public void testExpectedLogMessageFailureOutput() {
    Log.e("Mytag", "message1");
    Log.e("Mytag", "message2"); // Not expected
    rule.expectLogMessage(Log.ERROR, "Mytag", "message1");
    rule.expectLogMessage(Log.ERROR, "Mytag", "message3"); // Not logged

    expectedException.expect(
        new TypeSafeMatcher<AssertionError>() {
          @Override
          protected boolean matchesSafely(AssertionError error) {
            return error
                    .getMessage()
                    .matches(
                        "[\\s\\S]*Expected, and observed:\\s+\\[LogItem\\{"
                            + "\\s+timeString='.+'"
                            + "\\s+type=6"
                            + "\\s+tag='Mytag'"
                            + "\\s+msg='message1'"
                            + "\\s+throwable=null"
                            + "\\s+}]"
                            + "[\\s\\S]*")
                && error
                    .getMessage()
                    .matches(
                        "[\\s\\S]*Observed, but not expected:\\s+\\[LogItem\\{"
                            + "\\s+timeString='.+'"
                            + "\\s+type=6"
                            + "\\s+tag='Mytag'"
                            + "\\s+msg='message2'"
                            + "\\s+throwable=null"
                            + "\\s+}][\\s\\S]*")
                && error
                    .getMessage()
                    .matches(
                        "[\\s\\S]*Expected, but not observed: \\[ExpectedLogItem\\{timeString='.+',"
                            + " type=6, tag='Mytag', msg='message3'}]"
                            + "[\\s\\S]*");
          }

          @Override
          public void describeTo(Description description) {
            description.appendText("Matches ExpectedLogMessagesRule");
          }
        });
  }