package com.yahoo.dtf.range; import com.yahoo.dtf.range.EnumeratedRange; import com.yahoo.dtf.range.RandomListRange; import com.yahoo.dtf.range.Range; import com.yahoo.dtf.range.RangeJoin; import com.yahoo.dtf.range.SequentialRange; import com.yahoo.dtf.exception.DTFException; /** * @dtf.feature Range Expressions * @dtf.feature.group Ranges * * @dtf.feature.desc * Range expressions are used to create/define properties with values that * iterate over a collection of values or randomly choose from a collection of * values. These ranges are used in some of the looping mechanisms within DTF * and can be very useful for defining special identifiers to be used during * the looping that can make your test much easier to write. The table below * explains each type of range expression and has an example on how to use it. * * <table border='1'> * <tr><th>Name</th><th>Description</th><th>Example</th></tr> * <tr> * <td>Sequential</td> * <td><p> * Defines a list of elements using only the boundary elements and * allows for a more condensed representation of a n interval. The * syntax is: <b>lowerlimit..upperlimit</b> where lowerlimit is an * integer representing the first element in the list and upperlimit * is an integer representing the last element. All other elements * are generated by adding 1 to the current element. * </p> * </td> * <td> * {@dtf.xml * <for property="prop" range="1..10"> * <log>Prop: ${prop}</log> * </for>} * <p> * The above example will just print out each of those values that are * separated by a coma. * </p> * </td> * </tr> * * <tr> * <td>Random</td> * <td><p>The range expression will iterate randomly over the range * expression defined as an argument. The syntax is * random(your_expression), where your_expression can be any of * the already existing range expressions. Now this expression is * a little trickier to use because since it will select elements * in a random order it doesn't really have an end or a beginning * so you want to use it carefully.</p> * </td> * <td> * {@dtf.xml * <sequence> * <createrange name="range" value="random(a,b,c,d1,e)"/> * <for property="prop" range="1..5"> * <log>Prop: ${range}</log> * </for> * </sequence>} * <p>The above example will print out 5 randomly chosen elements form * the expression defined in the random expression.</p> * </td> * <tr> * * <tr> * <td>Aggregate</td> * <td><p>There is a simple way of aggregating ranges with the use of * the square brackets. By wrapping an existing range expression * in those brackets you create a sub-expression, like so: * [expression1][expression2]. With this new syntax you can * create ranges with fixed parts that iterate over a value of * possible numbers. Like in the examples.</p> * </td> * <td> * {@dtf.xml * <createrange name="range" value="[client][1..10]"/>} * <p>The above range would have the values client1,client2,client3...client10.</p> * </td> * </tr> * </table> */ public class RangeFactory { public static Range getRange(String regexp) throws DTFException { RangeJoin range = new RangeJoin(); if (!regexp.startsWith("[")) regexp = "[" + regexp + "]"; int start = -1; int startcnt = 0; int endcnt = 0; for (int i = 0; i < regexp.length(); i++) { if ( regexp.charAt(i) == '[' ) { startcnt++; if ( start == -1 ) start = i; } else if ( start != -1 && regexp.charAt(i) == ']' && (++endcnt == startcnt) ) { Range aux = null; String expression = regexp.substring(start+1,i); // more restrictive range expression first if ( XMLDataRange.matches(expression) ) { aux = new XMLDataRange(expression); } else if ( JSONDataRange.matches(expression) ) { aux = new JSONDataRange(expression); } else if ( RandomListRange.matches(expression) ) { aux = new RandomListRange(expression); } else if ( SequentialRange.matches(expression) ) { aux = new SequentialRange(expression); } else { // everything defaults to an enumerated range aux = new EnumeratedRange(expression); } range.addRange(aux); start = -1; startcnt = 0; endcnt = 0; } } return range; } }