// Path: src/main/java/immanix/matchers/AtLeastButFiniteMatcher.java
// public class AtLeastButFiniteMatcher<T> extends StaxMatcher<List<T>> {
//     private final StaxMatcher<T> delegate;
//     private final int n;
// 
//     public AtLeastButFiniteMatcher(StaxMatcher<T> delegate, int n) {
//         this.delegate = delegate;
//         this.n = n;
//     }
// 
//     @Override
//     public MatcherResult<List<T>> match(EventReader reader) throws XMLStreamException {
//         List<T> res = new ArrayList<T>();
//         List<XMLEvent> consumedEvents = new ArrayList<XMLEvent>();
// 
//         for (int i = 0; i < n; i++) {
//             MatcherResult<T> partialRes = delegate.match(reader);
//             if (partialRes.isFailure()) {
//                 return MatcherResult.failure(new BacktrackEventReader(consumedEvents, partialRes.reader),
//                         partialRes.errorMessage + "\n" +
//                                 toString() + " failed as its delegate matcher failed to match after " + (i + 1) + " iterations with the previous error");
//             } else {
//                 res.add(partialRes.data);
//                 consumedEvents.addAll(partialRes.consumedEvents);
//                 reader = partialRes.reader;
//             }
//         }
//         MatcherResult<T> partialRes = null;
//         while (!(partialRes = delegate.match(reader)).isFailure()) {
//             res.add(partialRes.data);
//             consumedEvents.addAll(partialRes.consumedEvents);
//             reader = partialRes.reader;
//         }
//         return MatcherResult.success(res, partialRes.reader, consumedEvents);
//     }
// 
//     @Override
//     public String toString() {
//         return "(AtLeastButFinite(" + n + ") " + delegate + ")";
//     }
// }
// 
// Path: src/main/java/immanix/readers/ReplayEventReader.java
// @SuppressWarnings("restriction")
// public class ReplayEventReader implements EventReader {
// 
//     private Iterator<? extends XMLEvent> events;
// 
//     public ReplayEventReader(List<? extends XMLEvent> events) {
//         super();
//         this.events = new ArrayList(events).iterator();
//     }
// 
//     public boolean hasNext() {
//         return events.hasNext();
//     }
// 
//     public XMLEvent next() throws XMLStreamException {
//         return events.next();
//     }
// 
//     public EventReader unwrap() {
//         return this;
//     }
// 
//     @Override
//     public String toString() {
//         return "Replayer";
//     }
// }
// 
// Path: src/test/java/immanix/utils/FullPacman.java
// public class FullPacman extends StaxMatcher<Object> {
//     int count;
// 
//     public FullPacman(int count) {
//         this.count = count;
//     }
// 
//     @Override
//     public MatcherResult<Object> match(EventReader reader) throws XMLStreamException {
//         if (count-- > 0) {
//             return MatcherResult.<Object>success("S", reader, Collections.EMPTY_LIST);
//         } else {
//             return MatcherResult.failure(reader, "Pacman is full");
//         }
//     }
// }
// 
// Path: src/test/java/immanix/utils/HungryPacman.java
// public class HungryPacman extends StaxMatcher<Object> {
//     int count;
// 
//     public HungryPacman(int count) {
//         this.count = count;
//     }
// 
//     @Override
//     public MatcherResult<Object> match(EventReader reader) throws XMLStreamException {
//         if (count-- > 0) {
//             return MatcherResult.<Object>success("S", reader, Arrays.asList(reader.next()));
//         } else {
//             return MatcherResult.failure(reader, "Pacman is full");
//         }
//     }
// }
// 
// Path: src/test/java/immanix/utils/XMLEventsUtils.java
// public static XMLEvent c(String val) {
//     return eventFactory.createCharacters(val);
// }


import org.junit.Test;
import immanix.matchers.AtLeastButFiniteMatcher;
import immanix.readers.ReplayEventReader;
import immanix.utils.FullPacman;
import immanix.utils.HungryPacman;
import javax.xml.stream.events.XMLEvent;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static immanix.utils.XMLEventsUtils.c;
package immanix;




public class AtLeastButFiniteMatcherTest {

    @Test
    public void testDelegateMatcherIsCalledCorrectly() throws Exception {
        StaxMatcher< Object> delegateMatcher = new FullPacman(6);
        StaxMatcher<Object> spyDelegateMatcher = spy(delegateMatcher);

        AtLeastButFiniteMatcher<Object> m = new AtLeastButFiniteMatcher<Object>(spyDelegateMatcher, 4);
        AtLeastButFiniteMatcher<Object> sm = spy(m);

        sm.match(null);

        verify(spyDelegateMatcher, times(7)).match(null);
    }

    @Test
    public void testReaderIsRestoredInCaseOfFailure() throws Exception {
        StaxMatcher<Object> delegateMatcher = new HungryPacman(3);

        AtLeastButFiniteMatcher<Object> m = new AtLeastButFiniteMatcher<Object>(delegateMatcher, 4);
        AtLeastButFiniteMatcher<Object> sm = spy(m);
        List<XMLEvent> events = Arrays.<XMLEvent>asList(c("_1"), c("_2"), c("c"), c("d"), c("e"), c("f"));
        ReplayEventReader reader = new ReplayEventReader(events);
        MatcherResult<List<Object>> res = sm.match(reader);


        assertTrue(res.reader.hasNext());
        assertEquals(c("_1"), res.reader.next());
    }

    @Test
    public void testReaderStateInCaseOfSuccess() throws Exception {
        StaxMatcher<Object> delegateMatcher = new HungryPacman(5);

        AtLeastButFiniteMatcher<Object> m = new AtLeastButFiniteMatcher<Object>(delegateMatcher, 4);
        AtLeastButFiniteMatcher<Object> sm = spy(m);
// Path: src/main/java/immanix/matchers/AtLeastButFiniteMatcher.java
// public class AtLeastButFiniteMatcher<T> extends StaxMatcher<List<T>> {
//     private final StaxMatcher<T> delegate;
//     private final int n;
// 
//     public AtLeastButFiniteMatcher(StaxMatcher<T> delegate, int n) {
//         this.delegate = delegate;
//         this.n = n;
//     }
// 
//     @Override
//     public MatcherResult<List<T>> match(EventReader reader) throws XMLStreamException {
//         List<T> res = new ArrayList<T>();
//         List<XMLEvent> consumedEvents = new ArrayList<XMLEvent>();
// 
//         for (int i = 0; i < n; i++) {
//             MatcherResult<T> partialRes = delegate.match(reader);
//             if (partialRes.isFailure()) {
//                 return MatcherResult.failure(new BacktrackEventReader(consumedEvents, partialRes.reader),
//                         partialRes.errorMessage + "\n" +
//                                 toString() + " failed as its delegate matcher failed to match after " + (i + 1) + " iterations with the previous error");
//             } else {
//                 res.add(partialRes.data);
//                 consumedEvents.addAll(partialRes.consumedEvents);
//                 reader = partialRes.reader;
//             }
//         }
//         MatcherResult<T> partialRes = null;
//         while (!(partialRes = delegate.match(reader)).isFailure()) {
//             res.add(partialRes.data);
//             consumedEvents.addAll(partialRes.consumedEvents);
//             reader = partialRes.reader;
//         }
//         return MatcherResult.success(res, partialRes.reader, consumedEvents);
//     }
// 
//     @Override
//     public String toString() {
//         return "(AtLeastButFinite(" + n + ") " + delegate + ")";
//     }
// }
// 
// Path: src/main/java/immanix/readers/ReplayEventReader.java
// @SuppressWarnings("restriction")
// public class ReplayEventReader implements EventReader {
// 
//     private Iterator<? extends XMLEvent> events;
// 
//     public ReplayEventReader(List<? extends XMLEvent> events) {
//         super();
//         this.events = new ArrayList(events).iterator();
//     }
// 
//     public boolean hasNext() {
//         return events.hasNext();
//     }
// 
//     public XMLEvent next() throws XMLStreamException {
//         return events.next();
//     }
// 
//     public EventReader unwrap() {
//         return this;
//     }
// 
//     @Override
//     public String toString() {
//         return "Replayer";
//     }
// }
// 
// Path: src/test/java/immanix/utils/FullPacman.java
// public class FullPacman extends StaxMatcher<Object> {
//     int count;
// 
//     public FullPacman(int count) {
//         this.count = count;
//     }
// 
//     @Override
//     public MatcherResult<Object> match(EventReader reader) throws XMLStreamException {
//         if (count-- > 0) {
//             return MatcherResult.<Object>success("S", reader, Collections.EMPTY_LIST);
//         } else {
//             return MatcherResult.failure(reader, "Pacman is full");
//         }
//     }
// }
// 
// Path: src/test/java/immanix/utils/HungryPacman.java
// public class HungryPacman extends StaxMatcher<Object> {
//     int count;
// 
//     public HungryPacman(int count) {
//         this.count = count;
//     }
// 
//     @Override
//     public MatcherResult<Object> match(EventReader reader) throws XMLStreamException {
//         if (count-- > 0) {
//             return MatcherResult.<Object>success("S", reader, Arrays.asList(reader.next()));
//         } else {
//             return MatcherResult.failure(reader, "Pacman is full");
//         }
//     }
// }
// 
// Path: src/test/java/immanix/utils/XMLEventsUtils.java
// public static XMLEvent c(String val) {
//     return eventFactory.createCharacters(val);
// }


// Path: src/test/java/immanix/AtLeastButFiniteMatcherTest.java
import org.junit.Test;
import immanix.matchers.AtLeastButFiniteMatcher;
import immanix.readers.ReplayEventReader;
import immanix.utils.FullPacman;
import immanix.utils.HungryPacman;
import javax.xml.stream.events.XMLEvent;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static immanix.utils.XMLEventsUtils.c;

package immanix;




public class AtLeastButFiniteMatcherTest {

    @Test
    public void testDelegateMatcherIsCalledCorrectly() throws Exception {
        StaxMatcher< Object> delegateMatcher = new FullPacman(6);
        StaxMatcher<Object> spyDelegateMatcher = spy(delegateMatcher);

        AtLeastButFiniteMatcher<Object> m = new AtLeastButFiniteMatcher<Object>(spyDelegateMatcher, 4);
        AtLeastButFiniteMatcher<Object> sm = spy(m);

        sm.match(null);

        verify(spyDelegateMatcher, times(7)).match(null);
    }

    @Test
    public void testReaderIsRestoredInCaseOfFailure() throws Exception {
        StaxMatcher<Object> delegateMatcher = new HungryPacman(3);

        AtLeastButFiniteMatcher<Object> m = new AtLeastButFiniteMatcher<Object>(delegateMatcher, 4);
        AtLeastButFiniteMatcher<Object> sm = spy(m);
        List<XMLEvent> events = Arrays.<XMLEvent>asList(c("_1"), c("_2"), c("c"), c("d"), c("e"), c("f"));
        ReplayEventReader reader = new ReplayEventReader(events);
        MatcherResult<List<Object>> res = sm.match(reader);


        assertTrue(res.reader.hasNext());
        assertEquals(c("_1"), res.reader.next());
    }

    @Test
    public void testReaderStateInCaseOfSuccess() throws Exception {
        StaxMatcher<Object> delegateMatcher = new HungryPacman(5);

        AtLeastButFiniteMatcher<Object> m = new AtLeastButFiniteMatcher<Object>(delegateMatcher, 4);
        AtLeastButFiniteMatcher<Object> sm = spy(m);
        List<XMLEvent> events = Arrays.<XMLEvent>asList(c("_1"), c("_2"), c("c"), c("d"), c("e"), c("f"));