// Path: src/main/java/org/reactivestreams/ISetupSubscriptionsTest.java
// public interface ISetupSubscriptionsTest {
//     void toBe(String... marbles);
// }
// 
// Path: src/main/java/org/reactivestreams/ISetupTest.java
// public interface ISetupTest {
// 
//     void toBe(String marble,
//               Map<String, ?> values,
//               Exception errorValue);
// 
//     void toBe(String marble,
//               Map<String, ?> values);
// 
//     void toBe(String marble);
// 
// }
// 
// Path: src/main/java/org/reactivestreams/SubscriptionLog.java
// public class SubscriptionLog {
//     public final long subscribe;
//     public final long unsubscribe;
// 
//     public SubscriptionLog(long subscribe) {
//         this.subscribe = subscribe;
//         this.unsubscribe = Long.MAX_VALUE;
//     }
// 
//     public SubscriptionLog(long subscribe, long unsubscribe) {
//         this.subscribe = subscribe;
//         this.unsubscribe = unsubscribe;
//     }
// 
//     public boolean doesNeverEnd() {
//         return unsubscribe == Long.MAX_VALUE;
//     }
// 
//     @Override
//     public String toString() {
//         return "SubscriptionLog{" +
//                 "subscribe=" + subscribe +
//                 ", unsubscribe=" + unsubscribe +
//                 '}';
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         SubscriptionLog that = (SubscriptionLog) o;
// 
//         if (subscribe != that.subscribe) return false;
//         return unsubscribe == that.unsubscribe;
// 
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = (int) (subscribe ^ (subscribe >>> 32));
//         result = 31 * result + (int) (unsubscribe ^ (unsubscribe >>> 32));
//         return result;
//     }
// }


import io.reactivex.*;
import io.reactivex.marble.*;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.reactivestreams.ISetupSubscriptionsTest;
import org.reactivestreams.ISetupTest;
import org.reactivestreams.SubscriptionLog;
import java.util.List;
import java.util.Map;
package io.reactivex.marble.junit;




public class MarbleRule implements TestRule {

    private static ThreadLocal<MarbleScheduler> schedulerHolder = new ThreadLocal<>();

    public final MarbleScheduler scheduler;

    public MarbleRule() {
        scheduler = new MarbleScheduler();
    }

    public MarbleRule(long frameTimeFactor) {
        scheduler = new MarbleScheduler(frameTimeFactor);
    }

    public static <T> HotObservable<T> hot(String marbles, Map<String, T> values) {
        return schedulerHolder.get().createHotObservable(marbles, values);
    }

    public static HotObservable<String> hot(String marbles) {
        return schedulerHolder.get().createHotObservable(marbles);
    }

    public static <T> ColdObservable<T> cold(String marbles, Map<String, T> values) {
        return schedulerHolder.get().createColdObservable(marbles, values);
    }

    public static ColdObservable<String> cold(String marbles) {
        return schedulerHolder.get().createColdObservable(marbles);
    }

// Path: src/main/java/org/reactivestreams/ISetupSubscriptionsTest.java
// public interface ISetupSubscriptionsTest {
//     void toBe(String... marbles);
// }
// 
// Path: src/main/java/org/reactivestreams/ISetupTest.java
// public interface ISetupTest {
// 
//     void toBe(String marble,
//               Map<String, ?> values,
//               Exception errorValue);
// 
//     void toBe(String marble,
//               Map<String, ?> values);
// 
//     void toBe(String marble);
// 
// }
// 
// Path: src/main/java/org/reactivestreams/SubscriptionLog.java
// public class SubscriptionLog {
//     public final long subscribe;
//     public final long unsubscribe;
// 
//     public SubscriptionLog(long subscribe) {
//         this.subscribe = subscribe;
//         this.unsubscribe = Long.MAX_VALUE;
//     }
// 
//     public SubscriptionLog(long subscribe, long unsubscribe) {
//         this.subscribe = subscribe;
//         this.unsubscribe = unsubscribe;
//     }
// 
//     public boolean doesNeverEnd() {
//         return unsubscribe == Long.MAX_VALUE;
//     }
// 
//     @Override
//     public String toString() {
//         return "SubscriptionLog{" +
//                 "subscribe=" + subscribe +
//                 ", unsubscribe=" + unsubscribe +
//                 '}';
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         SubscriptionLog that = (SubscriptionLog) o;
// 
//         if (subscribe != that.subscribe) return false;
//         return unsubscribe == that.unsubscribe;
// 
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = (int) (subscribe ^ (subscribe >>> 32));
//         result = 31 * result + (int) (unsubscribe ^ (unsubscribe >>> 32));
//         return result;
//     }
// }


// Path: src/main/java/io/reactivex/marble/junit/MarbleRule.java
import io.reactivex.*;
import io.reactivex.marble.*;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.reactivestreams.ISetupSubscriptionsTest;
import org.reactivestreams.ISetupTest;
import org.reactivestreams.SubscriptionLog;
import java.util.List;
import java.util.Map;

package io.reactivex.marble.junit;




public class MarbleRule implements TestRule {

    private static ThreadLocal<MarbleScheduler> schedulerHolder = new ThreadLocal<>();

    public final MarbleScheduler scheduler;

    public MarbleRule() {
        scheduler = new MarbleScheduler();
    }

    public MarbleRule(long frameTimeFactor) {
        scheduler = new MarbleScheduler(frameTimeFactor);
    }

    public static <T> HotObservable<T> hot(String marbles, Map<String, T> values) {
        return schedulerHolder.get().createHotObservable(marbles, values);
    }

    public static HotObservable<String> hot(String marbles) {
        return schedulerHolder.get().createHotObservable(marbles);
    }

    public static <T> ColdObservable<T> cold(String marbles, Map<String, T> values) {
        return schedulerHolder.get().createColdObservable(marbles, values);
    }

    public static ColdObservable<String> cold(String marbles) {
        return schedulerHolder.get().createColdObservable(marbles);
    }

    public static ISetupTest expectObservable(Observable<?> actual) {