package com.ibm.streamsx.topology.tester.spl; import java.util.ArrayList; import java.util.List; import com.ibm.streams.operator.StreamSchema; import com.ibm.streams.operator.Tuple; import com.ibm.streams.operator.Type.MetaType; import com.ibm.streams.operator.types.RString; import com.ibm.streamsx.topology.spl.SPLStream; import com.ibm.streamsx.topology.tester.Condition; import com.ibm.streamsx.topology.tester.Tester; /** * List of expected tuples. * Utility class to build a list * of expected SPL tuples for testing. * */ public class ExpectedTuples { private final Tuple[] EMPTY = new Tuple[0]; private final StreamSchema schema; private final List<Tuple> tuples = new ArrayList<>(); /** * Create an initially empty ExpectedTuples. * @param schema */ public ExpectedTuples(StreamSchema schema) { this.schema = schema; } /** * Get the schema of the tuples. * @return schema of the tuples. */ public StreamSchema getSchema() { return schema; } /** * Get the current of tuples. * Modifying the returned list modifies * the expected tuples. * * @return list of expected tuples. */ public List<Tuple> getTuples() { return tuples; } /** * Add a tuple to expected list. * The schema of the tuple must be the * same as {@link #getSchema()}. * @param tuple Tuple to be added to expected list. * @return This. */ public ExpectedTuples add(Tuple tuple) { checkSchema(tuple.getStreamSchema()); getTuples().add(tuple); return this; } /** * Add a tuple to expected list. * Equivalent to: * {@code add(getSchema().getTuple(values))} * with the exception that if an attribute is * of type {@code rstring} then a String object may be used. * <P> * Calls can be chained together to add multiple tuples. * For example with a schema of {@code tuple<rstring id, int32 value>} * this may be used to add two tuples: * <pre> * <code> * ExpectedTuples expected = new ExpectedTuples(schema); * * expected.addAsTuple("a21", 33).addAsTuple("c43", 932); * </code> * </pre> * </P> * @param values Attribute values for the tuple. * @return This. */ public ExpectedTuples addAsTuple(Object ...values) { for (int i = 0; i < values.length; i++) { if (getSchema().getAttribute(i).getType().getMetaType() == MetaType.RSTRING) { if (values[i] instanceof String) values[i] = new RString(values[i].toString()); } } return add(getSchema().getTuple(values)); } private void checkSchema(StreamSchema schema) { if (!getSchema().equals(schema)) throw new IllegalArgumentException("Mismatched schemas, expecting " + getSchema() + " passed " + schema); } /** * Create a condition for {@code stream} having the tuples * {@link #getTuples()} in the same order. * {@code stream.getSchema()} must be equal to {@link #getSchema()}. * * @param stream Stream the condition is for. * @return Condition that will be valid if {@code stream} has the same tuples as {@link #getTuples()}. * * @see Tester#tupleContents(SPLStream, Tuple...) */ public Condition<List<Tuple>> contents(SPLStream stream) { checkSchema(stream.getSchema()); return stream.topology().getTester().tupleContents(stream, getTuples().toArray(EMPTY)); } }