changeset 554:b54118ccc0e0

HttpSequenceFilter - in progress
author Devel 1
date Tue, 19 Sep 2017 11:25:18 +0200
parents 80af3ca1b618
children 7b10dfafe23a
files stress-tester/src/main/java/com/passus/st/client/http/filter/HttpHostRewriterFilter.java stress-tester/src/main/java/com/passus/st/client/http/filter/HttpLogoutFilter.java stress-tester/src/main/java/com/passus/st/client/http/filter/HttpSequenceFilter.java stress-tester/src/test/java/com/passus/st/client/http/filter/HttpSequenceFilterTest.java
diffstat 4 files changed, 188 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpHostRewriterFilter.java	Mon Sep 18 12:27:16 2017 +0200
+++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpHostRewriterFilter.java	Tue Sep 19 11:25:18 2017 +0200
@@ -164,7 +164,7 @@
         @Override
         public NodeDefinition create() {
             return mapDef(
-                    tupleDef("hostMap", new MappingNodeDefinition())
+                    tupleDef("hostMap", new MappingNodeDefinition().setMinNumberOfValues(1))
             );
         }
     }
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpLogoutFilter.java	Mon Sep 18 12:27:16 2017 +0200
+++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpLogoutFilter.java	Tue Sep 19 11:25:18 2017 +0200
@@ -11,14 +11,9 @@
 import com.passus.net.http.HttpRequest;
 import com.passus.net.http.HttpResponse;
 import com.passus.st.ParametersBag;
-import com.passus.st.client.credentials.CredentialsProvider;
-import com.passus.st.client.http.HttpConsts;
 import static com.passus.st.client.http.HttpConsts.PARAM_USERNAME;
 import static com.passus.st.client.http.HttpConsts.TAG_SESSION_ID;
 import com.passus.st.client.http.HttpFlowContext;
-import com.passus.st.client.http.filter.HttpFilter;
-import com.passus.st.client.http.filter.HttpFilterMessagePredicateNodeDefinition;
-import com.passus.st.client.http.filter.HttpMessagePredicate;
 import com.passus.st.plugin.PluginConstants;
 
 /**
--- a/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpSequenceFilter.java	Mon Sep 18 12:27:16 2017 +0200
+++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpSequenceFilter.java	Tue Sep 19 11:25:18 2017 +0200
@@ -1,11 +1,30 @@
 package com.passus.st.client.http.filter;
 
 import com.passus.commons.annotations.Plugin;
+import com.passus.config.CMapNode;
+import com.passus.config.CNode;
+import com.passus.config.CTupleNode;
+import com.passus.config.CValueNode;
+import com.passus.config.Configuration;
+import com.passus.config.annotations.NodeDefinitionCreate;
+import static com.passus.config.schema.ConfigurationSchemaBuilder.mapDef;
+import static com.passus.config.schema.ConfigurationSchemaBuilder.tupleDef;
+import static com.passus.config.schema.ConfigurationSchemaBuilder.valueDef;
+import com.passus.config.schema.ListNodeDefinition;
+import com.passus.config.schema.MapNodeDefinition;
+import com.passus.config.schema.MappingNodeDefinition;
+import com.passus.config.schema.NodeDefinition;
+import com.passus.config.schema.NodeDefinitionCreator;
+import com.passus.config.schema.NodeTransformer;
+import com.passus.config.validation.Errors;
 import com.passus.filter.ValueExtractor;
+import com.passus.filter.ValueExtractorParser;
+import com.passus.filter.config.PredicateNodeTransformer;
 import com.passus.net.http.HttpRequest;
 import com.passus.net.http.HttpResponse;
 import com.passus.st.client.http.HttpFlowContext;
 import com.passus.st.plugin.PluginConstants;
+import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -18,6 +37,7 @@
  *
  * @author mikolaj.podbielski
  */
+@NodeDefinitionCreate(HttpSequenceFilter.NodeDefCreator.class)
 @Plugin(name = HttpSequenceFilter.TYPE, category = PluginConstants.CATEGORY_HTTP_FILTER)
 public class HttpSequenceFilter extends HttpFilter {
 
@@ -26,15 +46,23 @@
         private final Predicate predicate;
         private boolean mustOccur = true;
         private long time = 10_000;
-        private final int num;
+        private int num;
         private String alias;
         private String[] aliases;
 
         public SequenceItem(Predicate predicate, int num) {
+            this(predicate);
+            this.num = num;
+        }
+
+        public SequenceItem(Predicate predicate) {
             if (predicate == null) {
                 throw new NullPointerException();
             }
             this.predicate = predicate;
+        }
+
+        public void setNum(int num) {
             this.num = num;
         }
 
@@ -213,14 +241,26 @@
     private SequenceItem[] seqItems;
     private Map<String, ValueExtractor> values = Collections.EMPTY_MAP;
 
+    public HttpSequenceListener getListener() {
+        return listener;
+    }
+
     public void setListener(HttpSequenceListener listener) {
         this.listener = listener;
     }
 
+    public SequenceItem[] getSeqItems() {
+        return seqItems;
+    }
+
     public void setSeqItems(SequenceItem[] seqItems) {
         this.seqItems = seqItems;
     }
 
+    public Map<String, ValueExtractor> getValues() {
+        return values;
+    }
+
     public void setValues(Map<String, ValueExtractor> values) {
         this.values = values;
     }
@@ -313,4 +353,124 @@
         return filter;
     }
 
+    @Override
+    public void configure(Configuration config) {
+        List<SequenceItem> itemsList = (List<SequenceItem>) config.get("sequence");
+        seqItems = itemsList.toArray(new SequenceItem[itemsList.size()]);
+        for (int i = 0; i < seqItems.length; ++i) {
+            //TODO: refactor
+            seqItems[i].setNum(i);
+        }
+
+        this.values = (Map<String, ValueExtractor>) config.get("values", Collections.EMPTY_MAP);
+    }
+
+    public static class NodeDefCreator implements NodeDefinitionCreator {
+
+        @Override
+        public NodeDefinition create() {
+            MapNodeDefinition elementDef = mapDef(
+                    tupleDef("match", new HttpFilterMessagePredicateNodeDefinition()),
+                    tupleDef("mustOccur", valueDef(Boolean.class)).setRequired(false),
+                    tupleDef("time", valueDef(Long.class)).setRequired(false),
+                    tupleDef("alias", valueDef()).setRequired(false)
+            );
+            elementDef.setTransformer(new SequencesNodeTransformer());
+            // TODO: mustOccur and time required in all steps but first
+
+            return mapDef(
+                    tupleDef("sequence", new ListNodeDefinition(elementDef).setMinNumberOfValues(2)),
+                    tupleDef("values", new MappingNodeDefinition().setTransformer(new ValuesNodeTransformer())).setRequired(false)
+            );
+        }
+
+    }
+
+    private static class SequencesNodeTransformer implements NodeTransformer<CNode> {
+
+        private static final PredicateNodeTransformer TRANSFORMER = new PredicateNodeTransformer();
+
+        @Override
+        public CNode transform(CNode node, Errors errors) {
+            try {
+                CMapNode mapNode = (CMapNode) node;
+                List<CTupleNode> tupleNodes = mapNode.getChildren();
+
+                Predicate predicate = null;
+                boolean mustOccur = true;
+                long time = 0;
+                String alias = null;
+                for (CTupleNode tupleNode : tupleNodes) {
+                    String name = tupleNode.getName();
+                    CNode valueNode = tupleNode.getNode();
+                    switch (name) {
+                        case "match":
+                            predicate = TRANSFORMER.transform(valueNode);
+                            break;
+                        case "mustOccur":
+                            mustOccur = (Boolean) getValue(valueNode);
+                            break;
+                        case "time":
+                            time = (Long) getValue(valueNode);
+                            break;
+                        case "alias":
+                            alias = (String) getValue(valueNode);
+                            break;
+                    }
+                }
+                SequenceItem item = new SequenceItem(predicate);
+                if (time > 0) {
+                    item.setTime(time);
+                }
+                item.setMustOccur(mustOccur);
+                item.setAlias(alias);
+                return new CValueNode(item);
+            } catch (Exception ex) {
+                return node;
+            }
+        }
+
+        @Override
+        public CNode reverseTransform(CNode node, Errors errors) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+    }
+
+    private static class ValuesNodeTransformer implements NodeTransformer<CNode> {
+
+        @Override
+        public CNode transform(CNode node, Errors errors) {
+            Map<String, ValueExtractor> result = new HashMap<>();
+
+            CMapNode mapNode = (CMapNode) node;
+            List<CTupleNode> tupleNodes = mapNode.getChildren();
+            for (CTupleNode tupleNode : tupleNodes) {
+                String name = tupleNode.getName();
+                CValueNode valueNode = (CValueNode) tupleNode.getNode();
+                String value = (String) valueNode.getValue();
+                try {
+                    errors.pushNestedPath(name);
+                    ValueExtractor extractor = ValueExtractorParser.DEFAULT.parse(value);
+                    result.put(name, extractor);
+                } catch (ParseException ex) {
+                    errors.reject(tupleNode, "Invalid expression: \"%s\"", value);
+                } finally {
+                    errors.popNestedPath();
+                }
+            }
+            return new CValueNode(result);
+        }
+
+        @Override
+        public CNode reverseTransform(CNode node, Errors errors) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+    }
+
+    private static Object getValue(CNode node) {
+        CValueNode valueNode = (CValueNode) node;
+        return valueNode.getValue();
+    }
 }
--- a/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpSequenceFilterTest.java	Mon Sep 18 12:27:16 2017 +0200
+++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpSequenceFilterTest.java	Tue Sep 19 11:25:18 2017 +0200
@@ -1,5 +1,7 @@
 package com.passus.st.client.http.filter;
 
+import com.passus.commons.utils.ResourceUtils;
+import com.passus.config.validation.Errors;
 import com.passus.filter.ValueExtractor;
 import com.passus.filter.ValueExtractorParser;
 import com.passus.filter.config.PredicateNodeTransformer;
@@ -9,9 +11,13 @@
 import com.passus.net.http.HttpResponseBuilder;
 import com.passus.st.AppUtils;
 import com.passus.st.client.http.filter.HttpSequenceFilter.SequenceItem;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.function.Predicate;
 import static org.testng.AssertJUnit.*;
@@ -83,6 +89,26 @@
         return ValueExtractorParser.DEFAULT.parse(s);
     }
 
+    @Test
+    public void testConfigure() throws Exception {
+        File file = ResourceUtils.getFile("com/passus/st/client/http/filter/sequence.yml");
+        String filterConfig = new String(Files.readAllBytes(Paths.get(file.toURI())));
+
+        Errors errors = new Errors();
+        List<HttpFilter> filters = HttpFiltersConfigurator.getFilters(filterConfig, errors);
+        HttpFilterTestUtils.printErrors(errors);
+
+        assertEquals(0, errors.getErrorCount());
+        assertEquals(1, filters.size());
+        assertTrue(filters.get(0) instanceof HttpSequenceFilter);
+
+        HttpSequenceFilter filter = (HttpSequenceFilter) filters.get(0);
+        filter.getSeqItems();
+        filter.getValues();
+
+        System.out.println("");
+    }
+
     public static class TestHttpSequenceListener implements HttpSequenceListener {
 
         ArrayList<HttpSequenceEvent> events = new ArrayList<>();