// Path: src/main/java/immanix/matchers/UntilButFiniteMatcher.java
// public class UntilButFiniteMatcher<T> extends StaxMatcher<T> {
//     private final StaxMatcher<T> delegate;
//     private final int giveUpBarrier;
// 
//     public UntilButFiniteMatcher(StaxMatcher<T> delegate, int giveUpBarrier) {
//         this.delegate = delegate;
//         this.giveUpBarrier = giveUpBarrier;
//     }
// 
//     @Override
//     public MatcherResult<T> match(EventReader reader) throws XMLStreamException {
//         MatcherResult<T> res = null;
//         List<XMLEvent> consumedEvents = new ArrayList<XMLEvent>();
//         while ((res = delegate.match(reader)).isFailure()) {
//             reader = res.reader.unwrap();
//             if (reader.hasNext() && consumedEvents.size() < giveUpBarrier) {
//                 consumedEvents.add(reader.next());
//             } else {
//                 return MatcherResult.failure(new BacktrackEventReader(consumedEvents, reader),
//                         toString() + " failed: the stream was consumed without the delegate matcher '" + delegate +
//                                 "' matching");
//             }
// 
//         }
//         consumedEvents.addAll(res.consumedEvents);
//         return MatcherResult.success(res.data, res.reader, consumedEvents);
//     }
// 
// 
//     @Override
//     public String toString() {
//         return "(UntilButFinite " + 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/LatentPacman.java
// public class LatentPacman extends StaxMatcher<Object> {
//     int count;
// 
//     public LatentPacman(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, "");
//         }
//     }
// }
// 
// Path: src/test/java/immanix/utils/XMLEventsUtils.java
// public class XMLEventsUtils {
//     private static XMLEventFactory eventFactory = XMLEventFactory.newInstance();
// 
//     public static XMLEvent a(String name, String val) {
//         return eventFactory.createAttribute(name, val);
//     }
// 
//     public static XMLEvent c(String val) {
//         return eventFactory.createCharacters(val);
//     }
// 
//     public static XMLEvent se(String name) {
//         return eventFactory.createStartElement(new QName(name), null, null);
//     }
// 
//     public static XMLEvent se(String namespaceURI, String name) {
//         return eventFactory.createStartElement(new QName(namespaceURI, name), null, null);
//     }
// 
//     public static XMLEvent ee(String name) {
//         return eventFactory.createEndElement(new QName(name), null);
//     }
// 
//     public static XMLEvent ee(String namespaceURI, String name) {
//         return eventFactory.createEndElement(new QName(namespaceURI, name), null);
//     }
// 
//     public static List<XMLEvent> evts(XMLEvent... items) {
//         return Arrays.asList(items);
//     }
// 
//     public static List<XMLEvent> close(List<XMLEvent> start) {
//         List<XMLEvent> res = new ArrayList<XMLEvent>();
//         for (int i = start.size() - 1; i >= 0; i--) {
//             if (start.get(i).isStartElement()) {
//                 res.add(ee(start.get(i).asStartElement().getName()
//                         .getLocalPart()));
//             }
//         }
//         return res;
//     }
// }


import immanix.matchers.UntilButFiniteMatcher;
import immanix.readers.ReplayEventReader;
import immanix.utils.LatentPacman;
import org.junit.Test;
import javax.xml.stream.events.XMLEvent;
import java.util.Arrays;
import java.util.List;
import static immanix.utils.XMLEventsUtils.*;
import static org.junit.Assert.*;
package immanix;




public class UntilButFiniteMatcherTest {
    @Test
    public void testSuccessMatch() throws Exception {
        UntilButFiniteMatcher<Object> m = new UntilButFiniteMatcher<Object>(new LatentPacman(2), 10);
        List<XMLEvent> events = Arrays.asList(se("42"), c("hi"), se("remains"));
        ReplayEventReader reader = new ReplayEventReader(events);
        MatcherResult<Object> res = m.match(reader);
        //must match
        assertFalse(res.isFailure());

        assertEquals("S", res.data);
        //reader must return next element
        assertTrue(res.reader.hasNext());
        assertEquals(se("remains"), res.reader.next());
    }

    @Test
    public void testFailureAtEOF() throws Exception {
// Path: src/main/java/immanix/matchers/UntilButFiniteMatcher.java
// public class UntilButFiniteMatcher<T> extends StaxMatcher<T> {
//     private final StaxMatcher<T> delegate;
//     private final int giveUpBarrier;
// 
//     public UntilButFiniteMatcher(StaxMatcher<T> delegate, int giveUpBarrier) {
//         this.delegate = delegate;
//         this.giveUpBarrier = giveUpBarrier;
//     }
// 
//     @Override
//     public MatcherResult<T> match(EventReader reader) throws XMLStreamException {
//         MatcherResult<T> res = null;
//         List<XMLEvent> consumedEvents = new ArrayList<XMLEvent>();
//         while ((res = delegate.match(reader)).isFailure()) {
//             reader = res.reader.unwrap();
//             if (reader.hasNext() && consumedEvents.size() < giveUpBarrier) {
//                 consumedEvents.add(reader.next());
//             } else {
//                 return MatcherResult.failure(new BacktrackEventReader(consumedEvents, reader),
//                         toString() + " failed: the stream was consumed without the delegate matcher '" + delegate +
//                                 "' matching");
//             }
// 
//         }
//         consumedEvents.addAll(res.consumedEvents);
//         return MatcherResult.success(res.data, res.reader, consumedEvents);
//     }
// 
// 
//     @Override
//     public String toString() {
//         return "(UntilButFinite " + 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/LatentPacman.java
// public class LatentPacman extends StaxMatcher<Object> {
//     int count;
// 
//     public LatentPacman(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, "");
//         }
//     }
// }
// 
// Path: src/test/java/immanix/utils/XMLEventsUtils.java
// public class XMLEventsUtils {
//     private static XMLEventFactory eventFactory = XMLEventFactory.newInstance();
// 
//     public static XMLEvent a(String name, String val) {
//         return eventFactory.createAttribute(name, val);
//     }
// 
//     public static XMLEvent c(String val) {
//         return eventFactory.createCharacters(val);
//     }
// 
//     public static XMLEvent se(String name) {
//         return eventFactory.createStartElement(new QName(name), null, null);
//     }
// 
//     public static XMLEvent se(String namespaceURI, String name) {
//         return eventFactory.createStartElement(new QName(namespaceURI, name), null, null);
//     }
// 
//     public static XMLEvent ee(String name) {
//         return eventFactory.createEndElement(new QName(name), null);
//     }
// 
//     public static XMLEvent ee(String namespaceURI, String name) {
//         return eventFactory.createEndElement(new QName(namespaceURI, name), null);
//     }
// 
//     public static List<XMLEvent> evts(XMLEvent... items) {
//         return Arrays.asList(items);
//     }
// 
//     public static List<XMLEvent> close(List<XMLEvent> start) {
//         List<XMLEvent> res = new ArrayList<XMLEvent>();
//         for (int i = start.size() - 1; i >= 0; i--) {
//             if (start.get(i).isStartElement()) {
//                 res.add(ee(start.get(i).asStartElement().getName()
//                         .getLocalPart()));
//             }
//         }
//         return res;
//     }
// }


// Path: src/test/java/immanix/UntilButFiniteMatcherTest.java
import immanix.matchers.UntilButFiniteMatcher;
import immanix.readers.ReplayEventReader;
import immanix.utils.LatentPacman;
import org.junit.Test;
import javax.xml.stream.events.XMLEvent;
import java.util.Arrays;
import java.util.List;
import static immanix.utils.XMLEventsUtils.*;
import static org.junit.Assert.*;

package immanix;




public class UntilButFiniteMatcherTest {
    @Test
    public void testSuccessMatch() throws Exception {
        UntilButFiniteMatcher<Object> m = new UntilButFiniteMatcher<Object>(new LatentPacman(2), 10);
        List<XMLEvent> events = Arrays.asList(se("42"), c("hi"), se("remains"));
        ReplayEventReader reader = new ReplayEventReader(events);
        MatcherResult<Object> res = m.match(reader);
        //must match
        assertFalse(res.isFailure());

        assertEquals("S", res.data);
        //reader must return next element
        assertTrue(res.reader.hasNext());
        assertEquals(se("remains"), res.reader.next());
    }

    @Test
    public void testFailureAtEOF() throws Exception {
        UntilButFiniteMatcher<Object> m = new UntilButFiniteMatcher<Object>(new LatentPacman(3), 10);