changeset 646:cbf6caefb2f6

HttpCounterFilter
author Devel 1
date Thu, 09 Nov 2017 11:04:26 +0100
parents 588ad36681a1
children a60392f31cf0
files stress-tester/src/main/java/com/passus/st/client/http/filter/HttpCounterFilter.java stress-tester/src/main/java/com/passus/st/client/http/filter/HttpCounterListener.java stress-tester/src/test/java/com/passus/st/client/http/filter/HttpCounterFilterTest.java
diffstat 3 files changed, 213 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpCounterFilter.java	Thu Nov 09 11:04:26 2017 +0100
@@ -0,0 +1,113 @@
+package com.passus.st.client.http.filter;
+
+import com.passus.commons.annotations.Plugin;
+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 static com.passus.config.schema.ConfigurationSchemaBuilder.valueDefInteger;
+import com.passus.config.schema.NodeDefinition;
+import com.passus.config.schema.NodeDefinitionCreator;
+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.util.concurrent.atomic.AtomicInteger;
+
+/**
+ *
+ * @author mikolaj.podbielski
+ */
+@NodeDefinitionCreate(HttpCounterFilter.NodeDefCreator.class)
+@Plugin(name = HttpCounterFilter.TYPE, category = PluginConstants.CATEGORY_HTTP_FILTER)
+public class HttpCounterFilter extends HttpFilter {
+
+    public static final String TYPE = "counter";
+
+    private static final AtomicInteger ID = new AtomicInteger();
+
+    private HttpMessagePredicate predicate;
+    private String name;
+    private int limit;
+    private HttpCounterListener listener = (e) -> {
+    };
+
+    private int count;
+
+    HttpMessagePredicate getPredicate() {
+        return predicate;
+    }
+
+    void setPredicate(HttpMessagePredicate predicate) {
+        this.predicate = predicate;
+    }
+
+    String getName() {
+        return name;
+    }
+
+    void setName(String name) {
+        this.name = name;
+    }
+
+    int getLimit() {
+        return limit;
+    }
+
+    void setLimit(int limit) {
+        this.limit = limit;
+    }
+
+    HttpCounterListener getListener() {
+        return listener;
+    }
+
+    void setListener(HttpCounterListener listener) {
+        this.listener = listener;
+    }
+
+    @Override
+    public void configure(Configuration config) {
+        predicate = (HttpMessagePredicate) config.get("applyIf");
+        limit = config.getInteger("limit");
+        name = config.getString("name", "counter_" + ID.getAndIncrement());
+        // TODO:
+        listener = (e) -> {
+            System.out.println(e);
+        };
+    }
+
+    @Override
+    public int filterInbound(HttpRequest req, HttpResponse resp, HttpFlowContext context) {
+        if (predicate.test(req, resp, context)) {
+            if (++count >= limit) {
+                listener.limitReached(new HttpCounterListener.Event(this));
+            }
+        }
+        return DUNNO;
+    }
+
+    @Override
+    public HttpCounterFilter instanceForWorker(int index) {
+        HttpCounterFilter filter = new HttpCounterFilter();
+        filter.predicate = predicate;
+        filter.name = name;
+        filter.limit = limit;
+        filter.listener = listener;
+        return filter;
+    }
+
+    public static class NodeDefCreator implements NodeDefinitionCreator {
+
+        @Override
+        public NodeDefinition create() {
+            return mapDef(
+                    tupleDef("applyIf", new HttpFilterMessagePredicateNodeDefinition()),
+                    tupleDef("limit", valueDefInteger()),
+                    tupleDef("name", valueDef()).setRequired(false)
+            );
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpCounterListener.java	Thu Nov 09 11:04:26 2017 +0100
@@ -0,0 +1,20 @@
+package com.passus.st.client.http.filter;
+
+/**
+ *
+ * @author mikolaj.podbielski
+ */
+public interface HttpCounterListener {
+    
+    public void limitReached(Event event);
+    
+    public static final class Event {
+        private final HttpCounterFilter filter;
+//        HttpRequest req
+
+        public Event(HttpCounterFilter filter) {
+            this.filter = filter;
+        }
+        
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/test/java/com/passus/st/client/http/filter/HttpCounterFilterTest.java	Thu Nov 09 11:04:26 2017 +0100
@@ -0,0 +1,80 @@
+package com.passus.st.client.http.filter;
+
+import com.passus.config.validation.Errors;
+import com.passus.filter.AndPredicate;
+import com.passus.filter.ComparisonOperator;
+import com.passus.filter.ComparisonPredicate;
+import com.passus.net.http.HttpRequest;
+import com.passus.net.http.HttpRequestBuilder;
+import com.passus.net.http.HttpResponse;
+import com.passus.net.http.HttpResponseBuilder;
+import com.passus.net.http.HttpStatus;
+import java.util.ArrayList;
+import java.util.List;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author mikolaj.podbielski
+ */
+public class HttpCounterFilterTest {
+
+    @Test
+    public void testFilterInbound() {
+        HttpRequest req = HttpRequestBuilder.get("http://example.com").build();
+        HttpResponse resp = HttpResponseBuilder.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
+
+        TestListener listener = new TestListener();
+
+        HttpMessagePredicate predicate = HttpFilterTestUtils.createPredicate("{resp.status.code: 500}");
+        HttpCounterFilter filter = new HttpCounterFilter();
+        filter.setLimit(2);
+        filter.setName("filter status code 500");
+        filter.setPredicate(predicate);
+        filter.setListener(listener);
+
+        filter.filterInbound(req, resp, null);
+        assertEquals(0, listener.events.size());
+        filter.filterInbound(req, resp, null);
+        assertEquals(1, listener.events.size());
+    }
+
+    @Test
+    public void testConfigure() throws Exception {
+        String filterConfig = "filters:\n"
+                + "    - type: counter\n"
+                + "      name: 'filter x'\n"
+                + "      limit: 3\n"
+                + "      applyIf: {resp.status.code: 404}\n";
+
+        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 HttpCounterFilter);
+
+        HttpCounterFilter filter = (HttpCounterFilter) filters.get(0);
+        assertEquals(3, filter.getLimit());
+        assertEquals("filter x", filter.getName());
+
+        AndPredicate<? extends Object> andPredicate = (AndPredicate) filter.getPredicate().getPredicate();
+        assertEquals(1, andPredicate.getSubPredicates().size());
+        ComparisonPredicate predicate = (ComparisonPredicate) andPredicate.getSubPredicates().get(0);
+        assertEquals("resp.status.code", predicate.getFieldName());
+        assertEquals(ComparisonOperator.EQUAL, predicate.getOperator());
+    }
+
+    private static class TestListener implements HttpCounterListener {
+
+        private final ArrayList<Event> events = new ArrayList<>();
+
+        @Override
+        public void limitReached(Event event) {
+            events.add(event);
+        }
+
+    }
+}