changeset 937:6d35ff7ba9c0

Generators
author Devel 2
date Tue, 05 Jun 2018 14:11:32 +0200
parents d49c6a6c308a
children fe4efd63b757
files stress-tester/src/main/java/com/passus/st/config/FieldValueExtractorTransformer.java stress-tester/src/main/java/com/passus/st/filter/Transformers.java stress-tester/src/main/java/com/passus/st/generator/Generator.java stress-tester/src/main/java/com/passus/st/generator/GeneratorFactory.java stress-tester/src/main/java/com/passus/st/generator/GeneratorValueExtractor.java stress-tester/src/main/java/com/passus/st/generator/GeneratorValueExtractorTransformer.java stress-tester/src/main/java/com/passus/st/generator/RandomBooleanGenerator.java stress-tester/src/main/java/com/passus/st/generator/RandomNumberGenerator.java stress-tester/src/main/java/com/passus/st/generator/RandomStringGenerator.java stress-tester/src/main/java/com/passus/st/plugin/PluginConstants.java stress-tester/src/main/java/com/passus/st/utils/ConfigurationContextConsts.java stress-tester/src/test/java/com/passus/st/client/http/HttpClientTest.java stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageModificationFilterTransformerTest.java stress-tester/src/test/java/com/passus/st/generator/RandomNumberGeneratorTest.java
diffstat 14 files changed, 603 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/stress-tester/src/main/java/com/passus/st/config/FieldValueExtractorTransformer.java	Mon May 07 15:00:01 2018 +0200
+++ b/stress-tester/src/main/java/com/passus/st/config/FieldValueExtractorTransformer.java	Tue Jun 05 14:11:32 2018 +0200
@@ -7,10 +7,11 @@
 import com.passus.filter.config.ValueExtractorTransformer;
 import com.passus.lookup.filter.LookupValueExtractorTransformer;
 import com.passus.st.filter.Transformers;
+import com.passus.st.generator.GeneratorValueExtractorTransformer;
 
 public class FieldValueExtractorTransformer implements ValueExtractorTransformer<ValueExtractor> {
 
-    public static final String[] OPERATORS = {"$expr", "$lookup"};
+    public static final String[] OPERATORS = {"$expr", "$lookup", "$gen"};
 
     @Override
     public String[] getOperators() {
@@ -21,6 +22,7 @@
     public ValueExtractor transform(CNode node, Errors errors, ConfigurationContext context) {
         final ExpressionNodeTransformer expressionNodeTransformer = Transformers.expressionNodeTransformer(context);
         final LookupValueExtractorTransformer lookupValueTransformer = Transformers.lookupValueTransformer(context);
+        final GeneratorValueExtractorTransformer generatorValueTransformer = Transformers.generatorTransformer(context);
 
         NodeType type = node.getType();
         ValueExtractor valueExtractor = null;
@@ -48,9 +50,14 @@
             } else if (opName.equals("$lookup")) {
                 CNode valNode = tupleNode.getNode();
                 try {
-                    valueExtractor = (ValueExtractor) lookupValueTransformer.transform(valNode);
-                } catch (NodeConversionException e) {
-                    errors.reject(valNode, "Invalid lookup definition. " + e.getMessage());
+                    valueExtractor = lookupValueTransformer.transform(valNode, errors, context);
+                } catch (Exception e) {
+                    errors.reject(valNode, "Invalid lookup definition.");
+                }
+            } else if (opName.equals("$gen")) {
+                CNode valNode = tupleNode.getNode();
+                try {
+                    valueExtractor = generatorValueTransformer.transform(valNode, errors, context);
                 } catch (Exception e) {
                     errors.reject(valNode, "Invalid lookup definition.");
                 }
--- a/stress-tester/src/main/java/com/passus/st/filter/Transformers.java	Mon May 07 15:00:01 2018 +0200
+++ b/stress-tester/src/main/java/com/passus/st/filter/Transformers.java	Tue Jun 05 14:11:32 2018 +0200
@@ -11,6 +11,7 @@
 import com.passus.lookup.filter.LookupKeyExistsLeftOperatorTransformer;
 import com.passus.lookup.filter.LookupValueExtractorTransformer;
 import com.passus.st.config.FieldValueExtractorTransformer;
+import com.passus.st.generator.GeneratorValueExtractorTransformer;
 import com.passus.st.utils.ConfigurationContextConsts;
 import com.passus.st.vars.VarsExtractorResolver;
 
@@ -77,5 +78,14 @@
         return new LookupKeyExistsLeftOperatorTransformer(lookups, LOOKUP_HELPER);
     }
 
+    public static GeneratorValueExtractorTransformer generatorTransformer(ConfigurationContext context) {
+        List<Lookup> lookups;
+        if (context == null) {
+            lookups = Collections.EMPTY_LIST;
+        } else {
+            lookups = context.get(ConfigurationContextConsts.GENERATORS, Collections.EMPTY_LIST);
+        }
 
+        return new GeneratorValueExtractorTransformer();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/generator/Generator.java	Tue Jun 05 14:11:32 2018 +0200
@@ -0,0 +1,12 @@
+package com.passus.st.generator;
+
+import com.passus.commons.service.Service;
+import com.passus.config.Configurable;
+
+public interface Generator extends Configurable {
+
+    public String getType();
+
+    public Object generate();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/generator/GeneratorFactory.java	Tue Jun 05 14:11:32 2018 +0200
@@ -0,0 +1,22 @@
+package com.passus.st.generator;
+
+import com.passus.commons.plugin.PluginFactory;
+
+import static com.passus.st.plugin.PluginConstants.CATEGORY_GENERATOR;
+
+public class GeneratorFactory extends PluginFactory<Generator> {
+
+    private static GeneratorFactory instance;
+
+    public GeneratorFactory() {
+        super(CATEGORY_GENERATOR, Generator.class);
+    }
+
+    public static synchronized GeneratorFactory getInstance() {
+        if (instance == null) {
+            instance = new GeneratorFactory();
+        }
+
+        return instance;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/generator/GeneratorValueExtractor.java	Tue Jun 05 14:11:32 2018 +0200
@@ -0,0 +1,19 @@
+package com.passus.st.generator;
+
+import com.passus.commons.Assert;
+import com.passus.filter.ValueExtractor;
+
+public class GeneratorValueExtractor implements ValueExtractor {
+
+    private final Generator generator;
+
+    public GeneratorValueExtractor(Generator generator) {
+        Assert.notNull(generator, "generator");
+        this.generator = generator;
+    }
+
+    @Override
+    public Object extract(Object object) {
+        return generator.generate();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/generator/GeneratorValueExtractorTransformer.java	Tue Jun 05 14:11:32 2018 +0200
@@ -0,0 +1,127 @@
+package com.passus.st.generator;
+
+import com.passus.commons.Assert;
+import com.passus.commons.plugin.PluginFactory;
+import com.passus.commons.plugin.PluginInfo;
+import com.passus.config.*;
+import com.passus.config.annotations.NodeDefinitionCreate;
+import com.passus.config.schema.ImmutableNodeDefinitionCreator;
+import com.passus.config.schema.MapNodeDefinition;
+import com.passus.config.schema.NodeDefinitionCreator;
+import com.passus.config.validation.Errors;
+import com.passus.filter.config.ValueExtractorTransformer;
+
+import java.util.List;
+
+import static com.passus.config.schema.ConfigurationSchemaBuilder.mapDef;
+
+public class GeneratorValueExtractorTransformer implements ValueExtractorTransformer<GeneratorValueExtractor> {
+
+    public static final String[] OPERATORS = {"$gen"};
+
+    private final PluginFactory<Generator> pluginFactory;
+
+    public GeneratorValueExtractorTransformer() {
+        this(GeneratorFactory.getInstance());
+    }
+
+    public GeneratorValueExtractorTransformer(PluginFactory<Generator> pluginFactory) {
+        Assert.notNull(pluginFactory, "pluginFactory");
+        this.pluginFactory = pluginFactory;
+    }
+
+    @Override
+    public String[] getOperators() {
+        return OPERATORS;
+    }
+
+    public Generator transformToGenerator(CNode node, Errors errors, ConfigurationContext context) {
+        try {
+            ConfigurationUtils.validateType(node, NodeType.MAP);
+            List<CTupleNode> tuples = ((CMapNode) node).getChildren();
+
+            PluginInfo plugin = null;
+            CMapNode configNodes = new CMapNode();
+            for (CTupleNode tuple : tuples) {
+                CNode valueNode = tuple.getNode();
+                String attrName = tuple.getName();
+
+                switch (attrName.toLowerCase()) {
+                    case "name":
+                        String genName = ConfigurationUtils.extractString(valueNode);
+                        if (genName == null) {
+                            errors.reject(valueNode, "Value of attribute 'name' cannot be null.");
+                            return null;
+                        } else if (!pluginFactory.containsName(genName)) {
+                            errors.reject(valueNode, "Unknown generator '" + genName + "'.");
+                            return null;
+                        }
+
+                        plugin = pluginFactory.get(genName);
+                        break;
+                    default:
+                        configNodes.add(tuple);
+                }
+            }
+
+            if (plugin == null) {
+                errors.reject(node, "Attribute 'name' required.");
+            } else {
+                final Class<?> pluginClass = plugin.getPluginClass();
+                NodeDefinitionCreate nodeDefCreate = pluginClass.getAnnotation(NodeDefinitionCreate.class);
+
+                NodeDefinitionCreator creator;
+                if (nodeDefCreate == null) {
+                    creator = new ImmutableNodeDefinitionCreator(mapDef());
+                } else {
+                    try {
+                        creator = nodeDefCreate.value().newInstance();
+                    } catch (Exception ex) {
+                        throw new RuntimeException(ex.getMessage(), ex);
+                    }
+                }
+
+                MapNodeDefinition childDef = (MapNodeDefinition) creator.create();
+                childDef.validate(configNodes, errors, context);
+                if (errors.hasError()) {
+                    return null;
+                }
+
+                childDef.transform(configNodes, errors, context);
+                if (errors.hasError()) {
+                    return null;
+                }
+
+                Generator generator;
+                try {
+                    generator = (Generator) pluginClass.newInstance();
+                } catch (InstantiationException | IllegalAccessException ex) {
+                    throw new RuntimeException("Unable to create instance of " + pluginClass.getName(), ex);
+                }
+
+                Configuration config = new ConfigurationImpl(configNodes);
+                generator.configure(config, context);
+                return generator;
+            }
+        } catch (Exception e) {
+            errors.reject(e.getMessage());
+        }
+
+        return null;
+    }
+
+    @Override
+    public GeneratorValueExtractor transform(CNode node, Errors errors, ConfigurationContext context) {
+        Generator generator = transformToGenerator(node, errors, context);
+        if (generator == null) {
+            return null;
+        }
+
+        return new GeneratorValueExtractor(generator);
+    }
+
+    @Override
+    public CNode reverseTransform(GeneratorValueExtractor transformer, Errors errors, ConfigurationContext context) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/generator/RandomBooleanGenerator.java	Tue Jun 05 14:11:32 2018 +0200
@@ -0,0 +1,30 @@
+package com.passus.st.generator;
+
+import com.passus.commons.annotations.Plugin;
+import com.passus.config.Configuration;
+import com.passus.config.ConfigurationContext;
+import com.passus.st.plugin.PluginConstants;
+import org.apache.commons.lang3.RandomUtils;
+
+@Plugin(name = RandomBooleanGenerator.TYPE, category = PluginConstants.CATEGORY_GENERATOR)
+public class RandomBooleanGenerator implements Generator {
+
+    public static final String TYPE = "randomBoolean";
+
+    @Override
+    public String getType() {
+        return TYPE;
+    }
+
+    @Override
+    public void configure(Configuration config, ConfigurationContext context) {
+
+    }
+
+    @Override
+    public Object generate() {
+        return RandomUtils.nextBoolean();
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/generator/RandomNumberGenerator.java	Tue Jun 05 14:11:32 2018 +0200
@@ -0,0 +1,136 @@
+package com.passus.st.generator;
+
+import com.passus.commons.Assert;
+import com.passus.commons.annotations.Plugin;
+import com.passus.config.Configuration;
+import com.passus.config.ConfigurationContext;
+import com.passus.config.annotations.NodeDefinitionCreate;
+import com.passus.config.schema.NodeDefinition;
+import com.passus.config.schema.NodeDefinitionCreator;
+import com.passus.config.schema.NumberTransformer;
+import com.passus.config.schema.ValueNodeDefinition;
+import com.passus.config.validation.DoubleValidator;
+import com.passus.st.plugin.PluginConstants;
+import org.apache.commons.lang3.RandomUtils;
+
+import static com.passus.config.schema.ConfigurationSchemaBuilder.*;
+
+@NodeDefinitionCreate(RandomNumberGenerator.RandomNumberNodeDefCreator.class)
+@Plugin(name = RandomNumberGenerator.TYPE, category = PluginConstants.CATEGORY_GENERATOR)
+public class RandomNumberGenerator implements Generator {
+
+    public static final String TYPE = "randomNumber";
+
+    public enum ReturnType {
+        INT, LONG, FLOAT, DOUBLE
+    }
+
+    private static final ReturnType DEFAULT_RETURN_TYPE = ReturnType.INT;
+
+    private static final Number DEFAULT_MIN_VALUE = new Integer(0);
+
+    private static final Number DEFAULT_MAX_VALUE = Integer.MAX_VALUE;
+
+    private ReturnType returnType = DEFAULT_RETURN_TYPE;
+
+    private Number minValue = DEFAULT_MIN_VALUE;
+
+    private Number maxValue = DEFAULT_MAX_VALUE;
+
+    @Override
+    public String getType() {
+        return TYPE;
+    }
+
+    public ReturnType getReturnType() {
+        return returnType;
+    }
+
+    public void setReturnType(ReturnType returnType) {
+        Assert.notNull(returnType, "returnType");
+        this.returnType = returnType;
+    }
+
+    public Number getMinValue() {
+        return minValue;
+    }
+
+    public void setMinValue(Number minValue) {
+        Assert.greaterOrEqualZero(minValue, "minValue");
+        this.minValue = minValue;
+    }
+
+    public Number getMaxValue() {
+        return maxValue;
+    }
+
+    public void setMaxValue(Number maxValue) {
+        Assert.greaterOrEqualZero(maxValue, "maxValue");
+        this.maxValue = maxValue;
+    }
+
+    @Override
+    public void configure(Configuration config, ConfigurationContext context) {
+        this.setReturnType(config.get("returnType", DEFAULT_RETURN_TYPE));
+        this.setMinValue(config.get("minValue", DEFAULT_MIN_VALUE));
+        this.setMaxValue(config.get("maxValue", DEFAULT_MAX_VALUE));
+    }
+
+    @Override
+    public Object generate() {
+        switch (returnType) {
+            case LONG: {
+                long minValue = this.minValue.longValue();
+                long maxValue = this.maxValue.longValue();
+                if (minValue > maxValue) {
+                    return 0L;
+                }
+
+                return RandomUtils.nextLong(minValue, maxValue);
+            }
+            case FLOAT: {
+                float minValue = this.minValue.floatValue();
+                float maxValue = this.maxValue.floatValue();
+                if (minValue > maxValue) {
+                    return 0.0F;
+                }
+
+                return RandomUtils.nextFloat(minValue, maxValue);
+            }
+            case DOUBLE: {
+                double minValue = this.minValue.doubleValue();
+                double maxValue = this.maxValue.doubleValue();
+                if (minValue > maxValue) {
+                    return 0.0;
+                }
+
+                return RandomUtils.nextDouble(minValue, maxValue);
+            }
+            default: {
+                int minValue = this.minValue.intValue();
+                int maxValue = this.maxValue.intValue();
+                if (minValue > maxValue) {
+                    return 0;
+                }
+
+                return RandomUtils.nextInt(minValue, maxValue);
+            }
+        }
+    }
+
+    public static final class RandomNumberNodeDefCreator implements NodeDefinitionCreator {
+
+        @Override
+        public NodeDefinition create() {
+            ValueNodeDefinition lengthDef = valueDef(Number.class, new NumberTransformer())
+                    .addValidator(DoubleValidator.GREATER_EQUAL_ZERO);
+
+            return mapDef(
+                    tupleDef("returnType", enumDef(RandomNumberGenerator.ReturnType.class)).setRequired(false),
+                    tupleDef("minValue", lengthDef).setRequired(false),
+                    tupleDef("maxValue", lengthDef).setRequired(false)
+            ).setCanBeEmpty(true);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/generator/RandomStringGenerator.java	Tue Jun 05 14:11:32 2018 +0200
@@ -0,0 +1,145 @@
+package com.passus.st.generator;
+
+import com.passus.commons.Assert;
+import com.passus.commons.annotations.Plugin;
+import com.passus.config.Configuration;
+import com.passus.config.ConfigurationContext;
+import com.passus.config.annotations.NodeDefinitionCreate;
+import com.passus.config.schema.NodeDefinition;
+import com.passus.config.schema.NodeDefinitionCreator;
+import com.passus.config.schema.ValueNodeDefinition;
+import com.passus.config.validation.LongValidator;
+import com.passus.st.plugin.PluginConstants;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import static com.passus.config.schema.ConfigurationSchemaBuilder.*;
+
+@NodeDefinitionCreate(RandomStringGenerator.RandomStringGeneratorNodeDefCreator.class)
+@Plugin(name = RandomStringGenerator.TYPE, category = PluginConstants.CATEGORY_GENERATOR)
+public class RandomStringGenerator implements Generator {
+
+    public static final String TYPE = "randomString";
+
+    public enum CharactersSet {
+        ASCII, LETTERS, NUMBERS, LETTERS_NUMBERS, CUSTOM
+    }
+
+    private static final CharactersSet DEFAULT_CHARACTERS_SET = CharactersSet.ASCII;
+
+    private static final int DEFAULT_MIN_LENGTH = 32;
+
+    private static final int DEFAULT_MAX_LENGTH = 32;
+
+    private CharactersSet charactersSet = DEFAULT_CHARACTERS_SET;
+
+    private int minLength = DEFAULT_MIN_LENGTH;
+
+    private int maxLength = DEFAULT_MAX_LENGTH;
+
+    private char[] chars;
+
+    @Override
+    public String getType() {
+        return TYPE;
+    }
+
+    public CharactersSet getCharactersSet() {
+        return charactersSet;
+    }
+
+    public void setCharactersSet(CharactersSet charactersSet) {
+        Assert.notNull(charactersSet, "charactersSet");
+        this.charactersSet = charactersSet;
+    }
+
+    public int getMinLength() {
+        return minLength;
+    }
+
+    public void setMinLength(int minLength) {
+        Assert.greaterOrEqualZero(minLength, "minLength");
+        this.minLength = minLength;
+    }
+
+    public int getMaxLength() {
+        return maxLength;
+    }
+
+    public void setMaxLength(int maxLength) {
+        Assert.greaterOrEqualZero(maxLength, "maxLength");
+        this.maxLength = maxLength;
+    }
+
+    public char[] getChars() {
+        return chars;
+    }
+
+    public void setChars(char[] chars) {
+        this.chars = chars;
+    }
+
+    @Override
+    public void configure(Configuration config, ConfigurationContext context) {
+        this.setCharactersSet((CharactersSet) config.get("charactersSet", DEFAULT_CHARACTERS_SET));
+        this.setMinLength(config.getInteger("minLength", DEFAULT_MIN_LENGTH));
+        this.setMaxLength(config.getInteger("maxLength", DEFAULT_MAX_LENGTH));
+
+        String charsStr = config.getString("chars", null);
+        if (charsStr != null) {
+            this.setChars(charsStr.toCharArray());
+        } else {
+            this.setChars(null);
+        }
+    }
+
+    private int randCount() {
+        if (minLength == maxLength) {
+            return minLength;
+        } else if (minLength < maxLength) {
+            return RandomUtils.nextInt(minLength, maxLength);
+        }
+
+        return 0;
+    }
+
+    @Override
+    public Object generate() {
+        int count = randCount();
+
+        switch (charactersSet) {
+            case ASCII:
+                return RandomStringUtils.randomAscii(count);
+            case LETTERS:
+                return RandomStringUtils.randomAlphabetic(count);
+            case NUMBERS:
+                return RandomStringUtils.randomNumeric(count);
+            case LETTERS_NUMBERS:
+                return RandomStringUtils.randomAlphanumeric(count);
+            case CUSTOM:
+                if (chars == null) {
+                    return StringUtils.EMPTY;
+                }
+
+                return RandomStringUtils.random(count, 0, 0, true, true, chars);
+        }
+
+        return StringUtils.EMPTY;
+    }
+
+    public static final class RandomStringGeneratorNodeDefCreator implements NodeDefinitionCreator {
+
+        @Override
+        public NodeDefinition create() {
+            ValueNodeDefinition lengthDef = valueDefInteger().addValidator(LongValidator.GREATER_EQUAL_ZERO);
+
+            return mapDef(
+                    tupleDef("charactersSet", enumDef(RandomStringGenerator.CharactersSet.class)).setRequired(false),
+                    tupleDef("minLength", lengthDef).setRequired(false),
+                    tupleDef("maxLength", lengthDef).setRequired(false),
+                    tupleDef("chars", valueDef()).setRequired(false)
+            ).setCanBeEmpty(true);
+        }
+    }
+}
--- a/stress-tester/src/main/java/com/passus/st/plugin/PluginConstants.java	Mon May 07 15:00:01 2018 +0200
+++ b/stress-tester/src/main/java/com/passus/st/plugin/PluginConstants.java	Tue Jun 05 14:11:32 2018 +0200
@@ -27,6 +27,8 @@
 
     public static final String CATEGORY_REPORTER_DESTINATION = "ReporterDestination";
 
+    public static final String CATEGORY_GENERATOR = "Generator";
+
     private PluginConstants() {
     }
 
--- a/stress-tester/src/main/java/com/passus/st/utils/ConfigurationContextConsts.java	Mon May 07 15:00:01 2018 +0200
+++ b/stress-tester/src/main/java/com/passus/st/utils/ConfigurationContextConsts.java	Tue Jun 05 14:11:32 2018 +0200
@@ -44,6 +44,8 @@
 
     public static final String LOOKUPS = "lookups";
 
+    public static final String GENERATORS = "generators";
+
     public static final String APP_VARS = "appVars";
 
     private ConfigurationContextConsts() {
--- a/stress-tester/src/test/java/com/passus/st/client/http/HttpClientTest.java	Mon May 07 15:00:01 2018 +0200
+++ b/stress-tester/src/test/java/com/passus/st/client/http/HttpClientTest.java	Tue Jun 05 14:11:32 2018 +0200
@@ -1,9 +1,5 @@
 package com.passus.st.client.http;
 
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.post;
-import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
 import com.passus.commons.service.ServiceUtils;
 import com.passus.st.AbstractWireMockTest;
 import com.passus.st.client.Event;
@@ -14,12 +10,16 @@
 import com.passus.st.emitter.RuleBasedSessionMapper;
 import com.passus.st.emitter.nio.NioEmitter;
 import com.passus.st.utils.EventUtils;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
-import static org.testng.AssertJUnit.*;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
 
 /**
  *
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageModificationFilterTransformerTest.java	Mon May 07 15:00:01 2018 +0200
+++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpMessageModificationFilterTransformerTest.java	Tue Jun 05 14:11:32 2018 +0200
@@ -9,6 +9,7 @@
 import com.passus.lookup.LookupList;
 import com.passus.lookup.filter.LookupValueExtractor;
 import com.passus.st.client.http.filter.HttpMessageModificationOperations.*;
+import com.passus.st.generator.GeneratorValueExtractor;
 import com.passus.st.utils.ConfigurationContextConsts;
 import org.testng.annotations.Test;
 
@@ -297,6 +298,7 @@
         String config = "operations:\n"
                 + "  setHeader:\n"
                 + "    H2: {$lookup: {name: 'test', keys: {col1: test}}}\n";
+
         CTupleNode node = read(config);
         Errors errors = new Errors();
         CValueNode value = transformer.transform(node.getNode(), errors, context);
@@ -311,6 +313,29 @@
         assertSame(lookup, lookupValueExtractor.getLookup());
     }
 
+    @Test
+    public void testTransform_generators() throws Exception {
+        String config = "operations:\n"
+                + "  setHeader:\n"
+                + "    H2: {$gen: {name: 'randomString', minLength: 10, maxLength: 10}}\n";
+
+        CTupleNode node = read(config);
+
+        ConfigurationContextImpl context = new ConfigurationContextImpl();
+        Errors errors = new Errors();
+        CValueNode value = transformer.transform(node.getNode(), errors, context);
+
+        errors.getAllErrors().forEach(System.out::println);
+        assertEquals(0, errors.getErrorCount());
+
+        List<Operation> operations = (List) value.getValue();
+        SetHeaderOperation operation = (SetHeaderOperation) operations.get(0);
+        assertTrue(operation.getValueExtractor() instanceof GeneratorValueExtractor);
+
+        GeneratorValueExtractor valueExtractor = (GeneratorValueExtractor) operation.getValueExtractor();
+        assertEquals(10, valueExtractor.extract(null).toString().length());
+    }
+
     private static boolean getReplacerEscape(Operation o) {
         return ReflectionUtils.getFieldByPath(o, "replacer.escape");
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/test/java/com/passus/st/generator/RandomNumberGeneratorTest.java	Tue Jun 05 14:11:32 2018 +0200
@@ -0,0 +1,55 @@
+package com.passus.st.generator;
+
+import com.passus.config.Configuration;
+import com.passus.config.ConfigurationContext;
+import com.passus.config.ConfigurationContextImpl;
+import com.passus.config.YamlConfigurationReader;
+import com.passus.config.validation.Errors;
+import org.testng.annotations.Test;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
+
+public class RandomNumberGeneratorTest {
+
+    private RandomNumberGenerator transformToGenerator(String configStr) throws Exception {
+        GeneratorValueExtractorTransformer transformer = new GeneratorValueExtractorTransformer();
+        Configuration config = YamlConfigurationReader.readFromString(configStr);
+
+        Errors errors = new Errors();
+        ConfigurationContext context = new ConfigurationContextImpl();
+        RandomNumberGenerator generator = (RandomNumberGenerator) transformer.transformToGenerator(config.getRootNode(), errors, context);
+        if (errors.hasError()) {
+            throw new Exception(errors.getAllErrors().get(0).toString());
+        }
+
+        return generator;
+    }
+
+    @Test
+    public void testGenerate_Integer() {
+        RandomNumberGenerator gen = new RandomNumberGenerator();
+        gen.setReturnType(RandomNumberGenerator.ReturnType.INT);
+        gen.setMinValue(5.2);
+        gen.setMaxValue(5.2);
+
+        Number res = (Number) gen.generate();
+        assertTrue(res instanceof Integer);
+        assertEquals(5, res);
+    }
+
+
+    @Test
+    public void testConfigure() throws Exception {
+        String configStr = "{name: 'randomNumber', minValue: 5.2, maxValue: 5, returnType: LONG}";
+        RandomNumberGenerator generator = transformToGenerator(configStr);
+
+        assertEquals(RandomNumberGenerator.ReturnType.LONG, generator.getReturnType());
+        assertEquals(5.2, generator.getMinValue());
+        assertEquals(5L, generator.getMaxValue());
+
+        Number res = (Number) generator.generate();
+        assertTrue(res instanceof Long);
+        assertEquals(5L, res);
+    }
+}
\ No newline at end of file