@Test
public void testGroupCountAndMore() throws Exception {

    String input = "1234567890123451xx2yy5aa6bb";
    String regex = "(1xx(2yy((4zz)|(5aa)))(6bb))";
    Matcher matcher = Pattern.compile(regex).matcher(input);
    assertTrue(matcher.find());
    assertEquals(6, matcher.groupCount());
    {
        // offset = 0 -> "1xx2yy5aa6bb" will be the match result
        MatchResultWithOffset mo = new MatchResultWithOffset(matcher, 0);
        assertGroup(-1, "1xx2yy5aa6bb", 15, 27, mo);
        assertGroup(0, "1xx2yy5aa6bb", 15, 27, mo);
        assertGroup(1, "1xx2yy5aa6bb", 15, 27, mo);
        assertGroup(2, "2yy5aa", 18, 24, mo);
        assertGroup(3, "5aa", 21, 24, mo);
        assertGroup(4, null, -1, -1, mo);
        assertGroup(5, "5aa", 21, 24, mo);
        assertGroup(6, "6bb", 24, 27, mo);
        assertEquals(6, mo.groupCount());
    }
    {
        // offset = 1 -> "1xx2yy5aa6bb" will be the match result
        MatchResultWithOffset mo = new MatchResultWithOffset(matcher, 1);
        assertGroup(-1, "1xx2yy5aa6bb", 15, 27, mo);
        assertGroup(0, "1xx2yy5aa6bb", 15, 27, mo);
        assertGroup(1, "2yy5aa", 18, 24, mo);
        assertGroup(2, "5aa", 21, 24, mo);
        assertGroup(3, null, -1, -1, mo);
        assertGroup(4, "5aa", 21, 24, mo);
        assertGroup(5, "6bb", 24, 27, mo);
        assertEquals(5, mo.groupCount());
    }
    {
        // offset = 2 -> "2yy5aa" will be the match result
        MatchResultWithOffset mo = new MatchResultWithOffset(matcher, 2);
        assertEquals("2yy5aa", input.substring(18, 24));
        assertGroup(-1, "2yy5aa", 18, 24, mo);
        assertGroup(0, "2yy5aa", 18, 24, mo);
        assertGroup(1, "5aa", 21, 24, mo);
        assertGroup(2, null, -1, -1, mo);
        assertGroup(3, "5aa", 21, 24, mo);
        assertEquals(3, mo.groupCount());
    }
    {
        // offset = 3 -> "5aa" will be the match result
        MatchResultWithOffset mo = new MatchResultWithOffset(matcher, 3);
        assertGroup(-1, "5aa", 21, 24, mo);
        assertGroup(0, "5aa", 21, 24, mo);
        assertGroup(1, null, -1, -1, mo);
        assertGroup(2, "5aa", 21, 24, mo);
        assertEquals(2, mo.groupCount());
    }
    {
        // offset = 4 -> null will be the match result
        MatchResultWithOffset mo = new MatchResultWithOffset(matcher, 4);
        assertGroup(-1, null, -1, -1, mo);
        assertEquals(0, mo.groupCount());
    }
    {
        // offset = 5 -> "5aa" will be the match result
        MatchResultWithOffset mo = new MatchResultWithOffset(matcher, 5);
        assertGroup(-1, "5aa", 21, 24, mo);
        assertGroup(0, "5aa", 21, 24, mo);
        assertEquals(0, mo.groupCount());
    }
    {
        // offset = 6 -> "6bb" will be the match result
        MatchResultWithOffset mo = new MatchResultWithOffset(matcher, 6);
        assertGroup(-1, "6bb", 24, 27, mo);
        assertGroup(0, "6bb", 24, 27, mo);
        assertEquals(0, mo.groupCount());
    }
    {
        // offset = 7 -> invalid group
        try {
            new MatchResultWithOffset(matcher, 7);
            fail("IndexOutOfBoundsException expected");
        } catch (IndexOutOfBoundsException e) {
            assertEquals("No group 7", e.getMessage());
        }
    }
    {
        // offset = -1 -> invalid group
        try {
            new MatchResultWithOffset(matcher, -1);
            fail("IndexOutOfBoundsException expected");
        } catch (IndexOutOfBoundsException e) {
            assertEquals("No group -1", e.getMessage());
        }
    }
}