All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.abstracta.jmeter.javadsl.http.AutoEnabledHttpConfigElement Maven / Gradle / Ivy

Go to download

Simple API to run JMeter performance tests in an VCS and programmers friendly way.

There is a newer version: 028
Show newest version
package us.abstracta.jmeter.javadsl.http;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.jmeter.gui.JMeterGUIComponent;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.collections.HashTree;
import us.abstracta.jmeter.javadsl.codegeneration.MethodCall;
import us.abstracta.jmeter.javadsl.codegeneration.MethodCallContext;
import us.abstracta.jmeter.javadsl.codegeneration.SingleTestElementCallBuilder;
import us.abstracta.jmeter.javadsl.core.BuildTreeContext;
import us.abstracta.jmeter.javadsl.core.BuildTreeContext.TreeContextEndListener;
import us.abstracta.jmeter.javadsl.core.configs.BaseConfigElement;

public abstract class AutoEnabledHttpConfigElement extends BaseConfigElement {

  protected boolean enabled = true;

  protected AutoEnabledHttpConfigElement(String name,
      Class guiClass) {
    super(name, guiClass);
  }

  public void registerDependency(BuildTreeContext context) {
    registerEndListener(context, getOrCreateContextEntry(context));
  }

  public BuildContextEntry getOrCreateContextEntry(BuildTreeContext context) {
    return context.getOrCreateEntry(getClass().getSimpleName(), BuildContextEntry::new);
  }

  private static class BuildContextEntry {

    private Boolean enabled;
    private boolean registeredListener;
    private final Map pendingResolution = new LinkedHashMap<>();
    private boolean hasDisabledChild;

  }

  private void registerEndListener(BuildTreeContext context, BuildContextEntry entry) {
    if (!entry.registeredListener) {
      entry.registeredListener = true;
      context.addEndListener(buildEndListener());
    }
  }

  public TreeContextEndListener buildEndListener() {
    return (context, tree) -> {
      BuildTreeContext parent = context.getParent();
      BuildContextEntry entry = getOrCreateContextEntry(context);
      if (parent == null) {
        endRootElement(context, tree, entry);
      } else if (entry.enabled == null) {
        endUnsolvedElement(context, tree, entry, parent);
      } else if (entry.enabled) {
        endEnabledElement(context, tree, entry);
      } else {
        endDisabledElement(parent);
      }
    };
  }

  private void endRootElement(BuildTreeContext context, HashTree tree,
      BuildContextEntry contextEntry) {
    if (contextEntry.hasDisabledChild) {
      addConfigToPendingResolutionChildren(contextEntry);
    } else if (contextEntry.enabled == null || contextEntry.enabled) {
      super.buildTreeUnder(tree, context);
    }
  }

  private void addConfigToPendingResolutionChildren(BuildContextEntry contextEntry) {
    contextEntry.pendingResolution.forEach(super::buildTreeUnder);
  }

  private void endUnsolvedElement(BuildTreeContext context, HashTree tree,
      BuildContextEntry entry, BuildTreeContext parent) {
    BuildContextEntry parentEntry = getOrCreateContextEntry(parent);
    if (entry.hasDisabledChild) {
      addConfigToPendingResolutionChildren(entry);
      parentEntry.hasDisabledChild = true;
    } else {
      parentEntry.pendingResolution.put(tree, context);
    }
    registerEndListener(parent, parentEntry);
  }

  private void endEnabledElement(BuildTreeContext context, HashTree tree, BuildContextEntry entry) {
    if (entry.hasDisabledChild) {
      addConfigToPendingResolutionChildren(entry);
    } else {
      super.buildTreeUnder(tree, context);
    }
  }

  private void endDisabledElement(BuildTreeContext parent) {
    BuildContextEntry parentEntry = getOrCreateContextEntry(parent);
    parentEntry.hasDisabledChild = true;
    registerEndListener(parent, parentEntry);
  }

  @Override
  public HashTree buildTreeUnder(HashTree parent, BuildTreeContext context) {
    BuildTreeContext parentContext = context.getParent();
    BuildContextEntry entry = getOrCreateContextEntry(parentContext);
    entry.enabled = enabled;
    registerEndListener(parentContext, entry);
    return parent;
  }

  public abstract static class CodeBuilder extends
      SingleTestElementCallBuilder {

    public CodeBuilder(Class testElementClass,
        List builderMethods) {
      super(testElementClass, builderMethods);
    }

    public void registerDependency(MethodCallContext context, MethodCall call) {
      if (!findConfigElementInSamplerScope(context)) {
        registerPendingDisableConfig(context, call);
      }
    }

    private boolean findConfigElementInSamplerScope(MethodCallContext samplerContext) {
      MethodCallContext parent = samplerContext.getParent();
      return samplerContext.getChildrenTree().list().stream()
          .anyMatch(testElementClass::isInstance)
          || parent != null && findConfigElementInSamplerScope(parent);
    }

    private void registerPendingDisableConfig(MethodCallContext context, MethodCall call) {
      MethodCallContext parentContext = context.getParent();
      if (parentContext == null) {
        addDisabledChild(call);
        return;
      }
      CallContextEntry parentEntry = getOrCreateContextEntry(parentContext);
      parentEntry.pendingDisableConfigs.add(call);
      if (parentEntry.endListenerRegistered) {
        return;
      }
      parentEntry.endListenerRegistered = true;
      parentContext.addEndListener((ctx, listenerCall) -> {
        if (parentEntry.hasChildWithConfig) {
          parentEntry.pendingDisableConfigs.forEach(this::addDisabledChild);
        } else {
          registerPendingDisableConfig(ctx, listenerCall);
        }
      });
    }

    private void addDisabledChild(MethodCall call) {
      call.child(buildMethodCall().chain("disable"));
    }

    private CallContextEntry getOrCreateContextEntry(MethodCallContext context) {
      CallContextEntry ctx = (CallContextEntry) context.getEntry(getClass());
      if (ctx == null) {
        ctx = new CallContextEntry();
        context.setEntry(getClass(), ctx);
      }
      return ctx;
    }

    @Override
    protected MethodCall buildMethodCall(T testElement, MethodCallContext context) {
      if (findSamplerInConfigScope(context)) {
        MethodCallContext parent = context.getParent();
        while (parent != null) {
          getOrCreateContextEntry(parent).hasChildWithConfig = true;
          parent = parent.getParent();
        }
        return MethodCall.emptyCall();
      } else {
        return buildMethodCall();
      }
    }

    private boolean findSamplerInConfigScope(MethodCallContext context) {
      MethodCallContext parent = context.getParent();
      return parent.getTestElement() instanceof HTTPSamplerProxy || findSamplerInTree(
          parent.getChildrenTree());
    }

    private boolean findSamplerInTree(HashTree tree) {
      return tree != null && tree.list().stream()
          .anyMatch(c -> c instanceof HTTPSamplerProxy || findSamplerInTree(tree.getTree(c)));
    }

    private static class CallContextEntry {

      private final List pendingDisableConfigs = new ArrayList<>();
      private boolean endListenerRegistered;
      private boolean hasChildWithConfig;

    }

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy