Skip to content

Commit

Permalink
refactor: extend logging for happy cases (#66)
Browse files Browse the repository at this point in the history
<!-- Please describe your pull request here. -->

## References

#65

<!-- References to relevant GitHub issues and pull requests, esp.
upstream and downstream changes -->

## Submitter checklist

- [ ] Recommended: Join [WireMock Slack](https://slack.wiremock.org/) to
get any help in `#help-contributing` or a project-specific channel like
`#wiremock-java`
- [ ] Recommended: If you participate in Hacktoberfest 2023, make sure
you're [signed up](https://wiremock.org/events/hacktoberfest/) there and
in the WireMock form
- [ ] The PR request is well described and justified, including the body
and the references
- [ ] The PR title represents the desired changelog entry
- [ ] The repository's code style is followed (see the contributing
guide)
- [ ] Test coverage that demonstrates that the change works as expected
- [ ] For new features, there's necessary documentation in this pull
request or in a subsequent PR to
[wiremock.org](https://github.com/wiremock/wiremock.org)

<!--
Put an `x` into the [ ] to show you have filled the information.
The template comes from
https://github.com/wiremock/.github/blob/main/.github/pull_request_template.md
You can override it by creating .github/pull_request_template.md in your
own repository
-->
  • Loading branch information
dirkbolte authored Oct 18, 2023
1 parent 65b5230 commit 9150161
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.util.Objects;
import java.util.Optional;

import static org.wiremock.extensions.state.internal.ExtensionLogger.logger;

/**
* Event listener to trigger state context deletion.
* <p>
Expand Down Expand Up @@ -75,41 +77,63 @@ public void beforeResponseSent(ServeEvent serveEvent, Parameters parameters) {

private void handleListDeletion(DeleteStateParameters.ListParameters listConfig, String contextName, Map<String, Object> model) {
if (Boolean.TRUE.equals(listConfig.getDeleteFirst())) {
contextManager.createOrUpdateContextList(contextName, maps -> {
if (!maps.isEmpty()) maps.removeFirst();
});
deleteFirst(contextName);
} else if (Boolean.TRUE.equals(listConfig.getDeleteLast())) {
contextManager.createOrUpdateContextList(contextName, maps -> {
if (!maps.isEmpty()) maps.removeLast();
});
deleteLast(contextName);
} else if (StringUtils.isNotBlank(listConfig.getDeleteIndex())) {
try {
var index = Integer.parseInt(renderTemplate(model, listConfig.getDeleteIndex()));
contextManager.createOrUpdateContextList(contextName, list -> list.remove(index));
} catch (IndexOutOfBoundsException | NumberFormatException e) {
throw createConfigurationError("List index '%s' does not exist or cannot be parsed: %s", listConfig.getDeleteIndex(), e.getMessage());
}
deleteIndex(listConfig, contextName, model);
} else if (listConfig.getDeleteWhere() != null &&
listConfig.getDeleteWhere().getProperty() != null &&
listConfig.getDeleteWhere().getValue() != null
) {
var property = renderTemplate(model, listConfig.getDeleteWhere().getProperty());
var value = renderTemplate(model, listConfig.getDeleteWhere().getValue());
deleteWhere(listConfig, contextName, model);
} else {
throw createConfigurationError("Missing/invalid configuration for list: ");
}
}

private Long deleteFirst(String contextName) {
return contextManager.createOrUpdateContextList(contextName, maps -> {
if (!maps.isEmpty()) maps.removeFirst();
logger().info(contextName, "list::deleteFirst");
});
}

private void deleteLast(String contextName) {
contextManager.createOrUpdateContextList(contextName, maps -> {
if (!maps.isEmpty()) maps.removeLast();
logger().info(contextName, "list::deleteLast");
});
}

private void deleteIndex(DeleteStateParameters.ListParameters listConfig, String contextName, Map<String, Object> model) {
try {
var index = Integer.parseInt(renderTemplate(model, listConfig.getDeleteIndex()));
contextManager.createOrUpdateContextList(contextName, list -> {
var iterator = list.iterator();
while (iterator.hasNext()) {
var element = iterator.next();
if (Objects.equals(element.getOrDefault(property, null), value)) {
iterator.remove();
break;
}
}
list.remove(index);
logger().info(contextName, String.format("list::deleteIndex(%d)", index));
});
} else {
throw createConfigurationError("Missing/invalid configuration for list");
} catch (IndexOutOfBoundsException | NumberFormatException e) {
throw createConfigurationError("List index '%s' does not exist or cannot be parsed: %s", listConfig.getDeleteIndex(), e.getMessage());
}
}

private void deleteWhere(DeleteStateParameters.ListParameters listConfig, String contextName, Map<String, Object> model) {
var property = renderTemplate(model, listConfig.getDeleteWhere().getProperty());
var value = renderTemplate(model, listConfig.getDeleteWhere().getValue());
contextManager.createOrUpdateContextList(contextName, list -> {
var iterator = list.iterator();
while (iterator.hasNext()) {
var element = iterator.next();
if (Objects.equals(element.getOrDefault(property, null), value)) {
iterator.remove();
logger().info(contextName, String.format("list::deleteWhere(property=%s)", property));
break;
}
}
});
}

private String createContextName(Map<String, Object> model, DeleteStateParameters parameters) {
var rawContext = Optional.ofNullable(parameters.getContext()).filter(StringUtils::isNotBlank).orElseThrow(() -> new ConfigurationException("no context specified"));
String context = renderTemplate(model, rawContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.util.Optional;
import java.util.stream.Collectors;

import static org.wiremock.extensions.state.internal.ExtensionLogger.logger;

/**
* Event listener to trigger state context recording.
* <p>
Expand Down Expand Up @@ -88,16 +90,31 @@ private void handleList(String contextName, Map<String, Object> model, RecordSta
Optional.ofNullable(parameters.getList())
.ifPresent(listConfiguration -> {
Optional.ofNullable(listConfiguration.getAddFirst())
.ifPresent(configuration ->
contextManager.createOrUpdateContextList(contextName, list -> list.addFirst(getPropertiesFromConfiguration(model, configuration))));
Optional.ofNullable(listConfiguration.getAddLast()).ifPresent(configuration ->
contextManager.createOrUpdateContextList(contextName, list -> list.addLast(getPropertiesFromConfiguration(model, configuration))));
.ifPresent(configuration -> addFirst(contextName, model, configuration));
Optional.ofNullable(listConfiguration.getAddLast())
.ifPresent(configuration -> addLast(contextName, model, configuration));
}
);
}

private Long addFirst(String contextName, Map<String, Object> model, Map<String, String> configuration) {
return contextManager.createOrUpdateContextList(contextName, list -> {
list.addFirst(getPropertiesFromConfiguration(model, configuration));
logger().info(contextName, "list::addFirst");
});
}

private Long addLast(String contextName, Map<String, Object> model, Map<String, String> configuration) {
return contextManager.createOrUpdateContextList(contextName, list -> {
list.addLast(getPropertiesFromConfiguration(model, configuration));
logger().info(contextName, "list::addLast");
});
}

private String createContextName(Map<String, Object> model, Parameters parameters) {
var rawContext = Optional.ofNullable(parameters.getString("context")).filter(StringUtils::isNotBlank).orElseThrow(() -> new ConfigurationException("no context specified"));
var rawContext = Optional.ofNullable(parameters.getString("context"))
.filter(StringUtils::isNotBlank)
.orElseThrow(() -> new ConfigurationException("no context specified"));
String context = renderTemplate(model, rawContext);
if (StringUtils.isBlank(context)) {
throw createConfigurationError("context cannot be blank");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.stream.Stream;

import static com.github.tomakehurst.wiremock.common.LocalNotifier.notifier;
import static org.wiremock.extensions.state.internal.ExtensionLogger.logger;

/**
* Response templating helper to access state.
Expand Down Expand Up @@ -84,7 +85,11 @@ private Optional<Object> getProperty(String contextName, String property, String
.map(it -> it.getFromContext(context))
.orElseGet(() -> context.getProperties().get(property))
)
.or(() -> convertToPropertySpecificDefault(property, defaultValue));
.or(() -> convertToPropertySpecificDefault(property, defaultValue))
.map((obj) -> {
logger().info(contextName, String.format("handlebar(property=%s)", property));
return obj;
});
}

private Optional<Object> convertToPropertySpecificDefault(String property, String defaultValue) {
Expand All @@ -104,6 +109,10 @@ private Optional<Object> getList(String contextName, String list) {
notifier().info("Path query failed: " + e.getMessage());
return Optional.empty();
}
})
.map((obj) -> {
logger().info(contextName, "handlebar(list)");
return obj;
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.util.stream.Collectors;

import static com.github.tomakehurst.wiremock.common.LocalNotifier.notifier;
import static org.wiremock.extensions.state.internal.ExtensionLogger.logger;

/**
* Request matcher for state.
Expand Down Expand Up @@ -82,6 +83,7 @@ private MatchResult hasContext(Map<String, Object> model, Parameters parameters,
.map(context -> {
List<Map.Entry<ContextMatcher, Object>> matchers = getMatches(parameters);
if (matchers.isEmpty()) {
logger().info(context, "hasContext matched");
return MatchResult.exactMatch();
} else {
return calculateMatch(model, context, matchers);
Expand All @@ -103,6 +105,7 @@ private MatchResult calculateMatch(Map<String, Object> model, Context context, L
private MatchResult hasNotContext(Map<String, Object> model, String template) {
var context = renderTemplate(model, template);
if (contextManager.getContext(context).isEmpty()) {
logger().info(context, "hasNotContext matched");
return MatchResult.exactMatch();
} else {
return MatchResult.noMatch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;

import static org.wiremock.extensions.state.internal.ExtensionLogger.logger;

public class ContextManager {

Expand All @@ -30,6 +33,11 @@ public ContextManager(Store<String, Object> store) {
this.store = store;
}

private static Supplier<Context> createNewContext(String contextName) {
logger().info(contextName, "created");
return () -> new Context(contextName);
}

public Object getState(String contextName, String property) {
synchronized (store) {
return store.get(contextName).map(it -> ((Context) it).getProperties().get(property)).orElse(null);
Expand All @@ -51,6 +59,7 @@ public Optional<Context> getContext(String contextName) {
public void deleteContext(String contextName) {
synchronized (store) {
store.remove(contextName);
logger().info(contextName, "deleted");
}
}

Expand All @@ -61,12 +70,14 @@ public Long createOrUpdateContextState(String contextName, Map<String, String> p
.map(it -> {
it.incUpdateCount();
return it;
}).orElseGet(() -> new Context(contextName));
}).orElseGet(createNewContext(contextName));
properties.forEach((k, v) -> {
if(v.equals("null")) {
if (v.equals("null")) {
context.getProperties().remove(k);
logger().info(contextName, String.format("property '%s' removed", k));
} else {
context.getProperties().put(k, v);
logger().info(contextName, String.format("property '%s' updated", k));
}
});
store.put(contextName, context);
Expand All @@ -81,7 +92,7 @@ public Long createOrUpdateContextList(String contextName, Consumer<LinkedList<Ma
.map(it -> {
it.incUpdateCount();
return it;
}).orElseGet(() -> new Context(contextName));
}).orElseGet(createNewContext(contextName));
consumer.accept(context.getList());
store.put(contextName, context);
return context.getUpdateCount();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.wiremock.extensions.state.internal;

import com.github.tomakehurst.wiremock.common.Notifier;

import static com.github.tomakehurst.wiremock.common.LocalNotifier.notifier;

public class ExtensionLogger {

private static Notifier notifier;

private ExtensionLogger() {
notifier = notifier();
}

public static ExtensionLogger logger() {
return InstanceHolder.instance;
}

public void info(Context context, String message) {
notifier.info(buildMessage(context.getContextName(), message));
}

public void error(Context context, String message) {
notifier.error(buildMessage(context.getContextName(), message));
}

public void info(String contextName, String message) {
notifier.info(buildMessage(contextName, message));
}

public void error(String contextName, String message) {
notifier.error(buildMessage(contextName, message));
}

private String buildMessage(String contextName, String message) {
return String.format("Context '%s': %s", contextName, message);
}

private static final class InstanceHolder {
private static final ExtensionLogger instance = new ExtensionLogger();
}

}

0 comments on commit 9150161

Please sign in to comment.