package com.yahoo.dtf.actions.conditionals; import com.yahoo.dtf.actions.conditionals.Condition; import com.yahoo.dtf.exception.DTFException; import com.yahoo.dtf.exception.ParseException; /** * @dtf.tag similar * @dtf.skip.index * * @dtf.since 1.0 * @dtf.author Rodney Gomes * * @dtf.tag.desc * <p> * Evaluates if op1 and op2 are within the tolerance level of similarity that is * desired for these two pieces of data. The value of tolerance can be expressed * like so: * </p> * <br/> * <pre> * 50% - op1 is at least 50% similar to op2 * 0.15 - op1 is at least 15% similar to op2 * </pre> * <p> * The actual similarity is calculated based on how many bytes are actually the * same between the two pieces of data. There is no attempt to calculate if * the data has been shifted and therefore the comparison is a direct position * to position comparison. * </p> * * @dtf.tag.example * <if> * <similar op1="AAAAAAA" op2="AAAAAAB" value="15%"/> * <else> * <fail>The average value is more than 5% off from previous value</fail> * </else> * </if> * */ public class Similar extends Condition { private String value = null; public Similar() { } public boolean evaluate() throws DTFException { String op1 = getOp1(); String op2 = getOp2(); double value = getValue(); boolean result = true; byte[] bytes1 = op1.getBytes(); byte[] bytes2 = op2.getBytes(); double similarity = similarity(bytes1,bytes2); if ( similarity < value ) { String msg = op1 + " is not " + value + "% similar to " + op2; registerContext(ASSERT_EXP_CTX, msg); result = false; } return result; } public static double similarity(byte[] s, byte[] t) { double diff = 0; double count = 0; int m = s.length; int n = t.length; int i = 0, j = 0; // figure out what are the actual differences while(i < m && j < n) { count++; if (s[i] != t[j]) diff++; i++; j++; } // go through the remaining values of the longest array while( i < m || j < n ) { count++; if (i == m) { // in s but not in t j++; } else if (j == n) { // in t but not in s i++; } diff++; } return (count-diff)/count; } public double getValue() throws ParseException { double result = 0; String perc = replaceProperties(value); if (perc.indexOf('%') != -1) { perc = perc.substring(0,perc.indexOf('%')); result = toDouble("value", perc)/100.0f; } else { result = toDouble("value", perc); } return result; } public void setValue(String value) { this.value = value; } }