Corrected compile errors in tests. Rewrote BotStateTests, and applied corrections to pass tests.
This commit is contained in:
Родитель
5478ce945a
Коммит
d13a995ac6
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Middleware to automatically call .SaveChanges() at the end of the turn for all BotState class it is managing.
|
||||
*/
|
||||
public class AutoSaveStateMiddleware implements Middleware {
|
||||
private BotStateSet botStateSet;
|
||||
|
||||
public AutoSaveStateMiddleware(BotState ... botStates) {
|
||||
botStateSet = new BotStateSet(Arrays.asList(botStates));
|
||||
}
|
||||
|
||||
public AutoSaveStateMiddleware(BotStateSet withBotStateSet) {
|
||||
botStateSet = withBotStateSet;
|
||||
}
|
||||
|
||||
public BotStateSet getBotStateSet() {
|
||||
return botStateSet;
|
||||
}
|
||||
|
||||
public void setBotStateSet(BotStateSet withBotStateSet) {
|
||||
botStateSet = withBotStateSet;
|
||||
}
|
||||
|
||||
public AutoSaveStateMiddleware add(BotState botState) {
|
||||
if (botState == null) {
|
||||
throw new IllegalArgumentException("botState cannot be null");
|
||||
}
|
||||
|
||||
botStateSet.add(botState);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware implementation which calls savesChanges automatically at the end of the turn.
|
||||
*
|
||||
* @param turnContext The context object for this turn.
|
||||
* @param next The delegate to call to continue the bot middleware pipeline.
|
||||
* @return A task representing the asynchronous operation.
|
||||
*/
|
||||
@Override
|
||||
public CompletableFuture<Void> onTurn(TurnContext turnContext, NextDelegate next) {
|
||||
return next.next()
|
||||
.thenCompose(result -> botStateSet.saveAllChanges(turnContext));
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -10,6 +11,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
|
@ -79,7 +81,7 @@ public abstract class BotState implements PropertyManager {
|
|||
if (force || cachedState == null || cachedState.getState() == null) {
|
||||
return storage.read(new String[]{storageKey})
|
||||
.thenApply(val -> {
|
||||
turnContext.getTurnState().put(contextServiceKey, new CachedBotState(val));
|
||||
turnContext.getTurnState().put(contextServiceKey, new CachedBotState((Map<String, Object>)val.get(storageKey)));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
@ -120,7 +122,7 @@ public abstract class BotState implements PropertyManager {
|
|||
|
||||
return storage.write(changes)
|
||||
.thenApply(val -> {
|
||||
cachedState.setHashCode(cachedState.computeHashCode(cachedState.state));
|
||||
cachedState.setHash(cachedState.computeHash(cachedState.state));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
@ -139,7 +141,7 @@ public abstract class BotState implements PropertyManager {
|
|||
throw new IllegalArgumentException("turnContext cannot be null");
|
||||
}
|
||||
|
||||
turnContext.getTurnState().put(contextServiceKey, new CachedBotState(new HashMap<>()));
|
||||
turnContext.getTurnState().put(contextServiceKey, new CachedBotState());
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
|
@ -154,13 +156,16 @@ public abstract class BotState implements PropertyManager {
|
|||
throw new IllegalArgumentException("turnContext cannot be null");
|
||||
}
|
||||
|
||||
CachedBotState cachedState = turnContext.getTurnState().get(contextServiceKey);
|
||||
if (cachedState != null) {
|
||||
turnContext.getTurnState().remove(contextServiceKey);
|
||||
}
|
||||
|
||||
String storageKey = getStorageKey(turnContext);
|
||||
return storage.delete(new String[]{storageKey});
|
||||
return storage.delete(new String[]{storageKey})
|
||||
.thenApply(result -> {
|
||||
CachedBotState cachedState = turnContext.getTurnState().get(contextServiceKey);
|
||||
if (cachedState != null) {
|
||||
turnContext.getTurnState().remove(contextServiceKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,11 +264,16 @@ public abstract class BotState implements PropertyManager {
|
|||
*/
|
||||
private static class CachedBotState {
|
||||
private Map<String, Object> state;
|
||||
private int hash;
|
||||
private String hash;
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public CachedBotState() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public CachedBotState(Map<String, Object> withState) {
|
||||
state = withState;
|
||||
hash = computeHashCode(withState);
|
||||
state = withState != null ? withState : new ConcurrentHashMap<>();
|
||||
hash = computeHash(withState);
|
||||
}
|
||||
|
||||
public Map<String, Object> getState() {
|
||||
|
@ -274,22 +284,28 @@ public abstract class BotState implements PropertyManager {
|
|||
state = withState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void setHashCode(int witHashCode) {
|
||||
public void setHash(String witHashCode) {
|
||||
hash = witHashCode;
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
return hash != computeHashCode(state);
|
||||
return !StringUtils.equals(hash, computeHash(state));
|
||||
}
|
||||
|
||||
public int computeHashCode(Object obj) {
|
||||
//TODO: this may not be the same as in dotnet
|
||||
return obj.hashCode();
|
||||
public String computeHash(Object obj) {
|
||||
if (obj == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
return mapper.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,17 +335,22 @@ public abstract class BotState implements PropertyManager {
|
|||
* @param defaultValueFactory Defines the default value. Invoked when no value been set for the requested
|
||||
* state property. If defaultValueFactory is defined as null,
|
||||
* the MissingMemberException will be thrown if the underlying property is not set.
|
||||
* @param <T> type of value the propertyAccessor accesses.
|
||||
* @return A task that represents the work queued to execute.
|
||||
*/
|
||||
@Override
|
||||
public <T, S> CompletableFuture<T> get(TurnContext turnContext, Supplier<S> defaultValueFactory) {
|
||||
public CompletableFuture<T> get(TurnContext turnContext, Supplier<T> defaultValueFactory) {
|
||||
return botState.load(turnContext)
|
||||
.thenCombine(botState.getPropertyValue(turnContext, name), (loadResult, value) -> {
|
||||
if (value == null) {
|
||||
value = defaultValueFactory.get();
|
||||
if (value != null) {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
if (defaultValueFactory == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
value = defaultValueFactory.get();
|
||||
set(turnContext, (T) value).join();
|
||||
return (T) value;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@ public class BotStateSet {
|
|||
/**
|
||||
* Initializes a new instance of the BotStateSet class.
|
||||
*
|
||||
* @param botStates initial list of {@link BotState} objects to manage.
|
||||
* @param withBotStates initial list of {@link BotState} objects to manage.
|
||||
*/
|
||||
public BotStateSet(List<BotState> botStates) {
|
||||
botStates.addAll(botStates);
|
||||
public BotStateSet(List<BotState> withBotStates) {
|
||||
botStates.addAll(withBotStates);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +96,7 @@ public class BotStateSet {
|
|||
*/
|
||||
public CompletableFuture<Void> saveAllChanges(TurnContext turnContext, boolean force) {
|
||||
List<CompletableFuture<Void>> saveFutures = botStates.stream()
|
||||
.map(future -> future.saveChanges(turnContext, force))
|
||||
.map(botState -> botState.saveChanges(turnContext, force))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return CompletableFuture.allOf(saveFutures.toArray(new CompletableFuture[saveFutures.size()]));
|
||||
|
|
|
@ -13,7 +13,7 @@ public class ConversationState extends BotState {
|
|||
* Creates a new {@link ConversationState} object.
|
||||
*/
|
||||
public ConversationState(Storage withStorage) {
|
||||
super(withStorage, ConversationState.class.getName());
|
||||
super(withStorage, ConversationState.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,28 +8,33 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
|
|||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class MemoryStorage implements Storage {
|
||||
private static final String TYPENAMEFORNONENTITY = "__type_name_";
|
||||
private final Object syncroot = new Object();
|
||||
private ObjectMapper objectMapper;
|
||||
private Map<String, JsonNode> memory = new HashMap<>();
|
||||
private Map<String, JsonNode> memory;
|
||||
private Logger logger = LoggerFactory.getLogger(MemoryStorage.class);
|
||||
private int _eTag = 0;
|
||||
|
||||
public MemoryStorage() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public MemoryStorage(Map<String, JsonNode> values) {
|
||||
objectMapper = new ObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.findAndRegisterModules();
|
||||
objectMapper.enableDefaultTyping();
|
||||
|
||||
if (values != null)
|
||||
memory = values;
|
||||
memory = values != null ? values : new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,7 +43,7 @@ public class MemoryStorage implements Storage {
|
|||
throw new IllegalArgumentException("keys cannot be null");
|
||||
}
|
||||
|
||||
Map<String, Object> storeItems = new HashMap<String, Object>(keys.length);
|
||||
Map<String, Object> storeItems = new ConcurrentHashMap<>(keys.length);
|
||||
synchronized (this.syncroot) {
|
||||
for (String key : keys) {
|
||||
if (memory.containsKey(key)) {
|
||||
|
@ -83,15 +88,15 @@ public class MemoryStorage implements Storage {
|
|||
@Override
|
||||
public CompletableFuture<Void> write(Map<String, Object> changes) {
|
||||
synchronized (this.syncroot) {
|
||||
for (Map.Entry change : changes.entrySet()) {
|
||||
for (Map.Entry<String, Object> change : changes.entrySet()) {
|
||||
Object newValue = change.getValue();
|
||||
|
||||
String oldStateETag = null;
|
||||
if (memory.containsValue(change.getKey())) {
|
||||
Map oldState = (Map) memory.get(change.getKey());
|
||||
if (oldState.containsValue("eTag")) {
|
||||
Map.Entry eTagToken = (Map.Entry) oldState.get("eTag");
|
||||
oldStateETag = (String) eTagToken.getValue();
|
||||
if (memory.containsKey(change.getKey())) {
|
||||
JsonNode oldState = memory.get(change.getKey());
|
||||
if (oldState.has("eTag")) {
|
||||
JsonNode eTagToken = oldState.get("eTag");
|
||||
oldStateETag = eTagToken.asText();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,8 +107,10 @@ public class MemoryStorage implements Storage {
|
|||
// Set ETag if applicable
|
||||
if (newValue instanceof StoreItem) {
|
||||
StoreItem newStoreItem = (StoreItem) newValue;
|
||||
if (oldStateETag != null && newStoreItem.getETag() != "*" &&
|
||||
newStoreItem.getETag() != oldStateETag) {
|
||||
if (oldStateETag != null
|
||||
&& !StringUtils.equals(newStoreItem.getETag(), "*")
|
||||
&& !StringUtils.equals(newStoreItem.getETag(), oldStateETag)) {
|
||||
|
||||
String msg = String.format("Etag conflict. Original: %s, Current: %s",
|
||||
newStoreItem.getETag(), oldStateETag);
|
||||
logger.error(msg);
|
||||
|
@ -113,7 +120,7 @@ public class MemoryStorage implements Storage {
|
|||
((ObjectNode) newState).put("eTag", newTag.toString());
|
||||
}
|
||||
|
||||
memory.put((String) change.getKey(), newState);
|
||||
memory.put(change.getKey(), newState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,8 +135,7 @@ public class MemoryStorage implements Storage {
|
|||
|
||||
synchronized (this.syncroot) {
|
||||
for (String key : keys) {
|
||||
Object o = memory.get(key);
|
||||
memory.remove(o);
|
||||
memory.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public class PrivateConversationState extends BotState {
|
|||
* @param storage The storage provider to use.
|
||||
*/
|
||||
public PrivateConversationState(Storage storage) {
|
||||
super(storage, PrivateConversationState.class.getName());
|
||||
super(storage, PrivateConversationState.class.getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,11 @@ import java.util.concurrent.CompletableFuture;
|
|||
import java.util.function.Supplier;
|
||||
|
||||
public interface StatePropertyAccessor<T> extends StatePropertyInfo {
|
||||
<T extends Object, S> CompletableFuture<T> get(TurnContext turnContext, Supplier<S> defaultValueFactory);
|
||||
default CompletableFuture<T> get(TurnContext turnContext) {
|
||||
return get(turnContext, null);
|
||||
}
|
||||
|
||||
CompletableFuture<T> get(TurnContext turnContext, Supplier<T> defaultValueFactory);
|
||||
|
||||
CompletableFuture<Void> delete(TurnContext turnContext);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public class TurnContextStateCollection extends HashMap<String, Object> implemen
|
|||
throw new IllegalArgumentException("key");
|
||||
}
|
||||
|
||||
Object service = get(key);
|
||||
Object service = super.get(key);
|
||||
try {
|
||||
T result = (T) service;
|
||||
} catch (ClassCastException e) {
|
||||
|
|
|
@ -16,7 +16,7 @@ public class UserState extends BotState {
|
|||
* @param withStorage The storage provider to use.
|
||||
*/
|
||||
public UserState(Storage withStorage) {
|
||||
super(withStorage, UserState.class.getName());
|
||||
super(withStorage, UserState.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,7 +14,7 @@ public class InspectionState extends BotState {
|
|||
* @param withStorage The storage provider to use.
|
||||
*/
|
||||
public InspectionState(Storage withStorage) {
|
||||
super(withStorage, InspectionState.class.getName());
|
||||
super(withStorage, InspectionState.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.microsoft.bot.builder;
|
||||
|
||||
// This is a proxy for some previous tests using Action bindings
|
||||
@FunctionalInterface
|
||||
public interface ActionDel {
|
||||
void CallMe();
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
// This is a proxy for some previous tests using Action bindings
|
||||
@FunctionalInterface
|
||||
public interface ActionDel {
|
||||
void CallMe();
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -5,18 +8,17 @@ import java.util.concurrent.CompletableFuture;
|
|||
/**
|
||||
* Helper class for defining middleware by using a delegate or anonymous method.
|
||||
*/
|
||||
public class AnonymousReceiveMiddleware implements Middleware
|
||||
{
|
||||
public class AnonymousReceiveMiddleware implements Middleware {
|
||||
private MiddlewareCall _toCall;
|
||||
|
||||
/**
|
||||
* Creates a middleware object that uses the provided method as its
|
||||
* process request handler.
|
||||
*
|
||||
* @param anonymousMethod The method to use as the middleware's process
|
||||
* request handler.
|
||||
* request handler.
|
||||
*/
|
||||
public AnonymousReceiveMiddleware(MiddlewareCall anonymousMethod)
|
||||
{
|
||||
public AnonymousReceiveMiddleware(MiddlewareCall anonymousMethod) {
|
||||
if (anonymousMethod == null)
|
||||
throw new NullPointerException("MiddlewareCall anonymousMethod");
|
||||
else
|
||||
|
@ -26,8 +28,9 @@ public class AnonymousReceiveMiddleware implements Middleware
|
|||
/**
|
||||
* Uses the method provided in the {@link AnonymousReceiveMiddleware} to
|
||||
* process an incoming activity.
|
||||
*
|
||||
* @param context The context object for this turn.
|
||||
* @param next The delegate to call to continue the bot middleware pipeline.
|
||||
* @param next The delegate to call to continue the bot middleware pipeline.
|
||||
* @return A task that represents the work queued to execute.
|
||||
*/
|
||||
@Override
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import com.microsoft.bot.schema.Activity;
|
||||
import com.microsoft.bot.schema.ActivityTypes;
|
||||
import com.microsoft.bot.schema.ResourceResponse;
|
||||
import com.microsoft.bot.schema.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -12,22 +15,20 @@ import java.util.function.Consumer;
|
|||
|
||||
public class BotFrameworkAdapterTest {
|
||||
@Test
|
||||
public void AdapterSingleUse()
|
||||
{
|
||||
public void AdapterSingleUse() {
|
||||
SimpleAdapter a = new SimpleAdapter();
|
||||
a.use(new CallCountingMiddleware());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void AdapterUseChaining()
|
||||
{
|
||||
public void AdapterUseChaining() {
|
||||
SimpleAdapter a = new SimpleAdapter();
|
||||
a.use(new CallCountingMiddleware()).use(new CallCountingMiddleware());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void PassResourceResponsesThrough() throws Exception {
|
||||
Consumer<Activity[]> validateResponse = (activities) -> {
|
||||
Consumer<Activity[]> validateResponse = (activities) -> {
|
||||
// no need to do anything.
|
||||
};
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface CallOnException {
|
||||
<T> CompletableFuture<Void> apply(TurnContext context, T t );
|
||||
<T> CompletableFuture<Void> apply(TurnContext context, T t);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
|
@ -11,7 +12,6 @@ import java.util.concurrent.CompletionException;
|
|||
* send an appropriate message to the user to let them know that something has gone wrong.
|
||||
* You can specify the type of exception the middleware should catch and this middleware can be added
|
||||
* multiple times to allow you to handle different exception types in different ways.
|
||||
*
|
||||
*/
|
||||
public class CatchExceptionMiddleware<T extends Exception> implements Middleware {
|
||||
private final CallOnException _handler;
|
||||
|
@ -33,7 +33,7 @@ public class CatchExceptionMiddleware<T extends Exception> implements Middleware
|
|||
return next.next()
|
||||
.exceptionally(exception -> {
|
||||
if (_exceptionType.isInstance(exception)) {
|
||||
_handler.<T>apply(context, (T) exception);
|
||||
_handler.apply(context, (T) exception);
|
||||
} else {
|
||||
throw new CompletionException(exception);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import com.microsoft.bot.builder.adapters.TestAdapter;
|
||||
|
@ -17,54 +20,54 @@ public class CatchException_MiddlewareTest {
|
|||
public void CatchException_TestMiddleware_TestStackedErrorMiddleware() throws ExecutionException, InterruptedException {
|
||||
|
||||
TestAdapter adapter = new TestAdapter()
|
||||
.Use(new CatchExceptionMiddleware<Exception>(new CallOnException() {
|
||||
@Override
|
||||
public <T> CompletableFuture apply(TurnContext context, T t) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
Activity activity = context.getActivity();
|
||||
if (activity instanceof Activity) {
|
||||
try {
|
||||
context.sendActivity(((Activity) activity).createReply(t.toString())).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(String.format("CatchException_TestMiddleware_TestStackedErrorMiddleware:SendActivity failed %s", e.toString()));
|
||||
}
|
||||
} else
|
||||
Assert.assertTrue("Test was built for ActivityImpl", false);
|
||||
.use(new CatchExceptionMiddleware<Exception>(new CallOnException() {
|
||||
@Override
|
||||
public <T> CompletableFuture apply(TurnContext context, T t) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
Activity activity = context.getActivity();
|
||||
if (activity instanceof Activity) {
|
||||
try {
|
||||
context.sendActivity(activity.createReply(t.toString())).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(String.format("CatchException_TestMiddleware_TestStackedErrorMiddleware:SendActivity failed %s", e.toString()));
|
||||
}
|
||||
} else
|
||||
Assert.assertTrue("Test was built for ActivityImpl", false);
|
||||
|
||||
}, ExecutorFactory.getExecutor());
|
||||
}, ExecutorFactory.getExecutor());
|
||||
|
||||
}
|
||||
}, Exception.class))
|
||||
// Add middleware to catch NullReferenceExceptions before throwing up to the general exception instance
|
||||
.Use(new CatchExceptionMiddleware<NullPointerException>(new CallOnException() {
|
||||
@Override
|
||||
public <T> CompletableFuture apply(TurnContext context, T t) {
|
||||
context.sendActivity("Sorry - Null Reference Exception").join();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}, NullPointerException.class));
|
||||
}
|
||||
}, Exception.class))
|
||||
// Add middleware to catch NullReferenceExceptions before throwing up to the general exception instance
|
||||
.use(new CatchExceptionMiddleware<NullPointerException>(new CallOnException() {
|
||||
@Override
|
||||
public <T> CompletableFuture apply(TurnContext context, T t) {
|
||||
context.sendActivity("Sorry - Null Reference Exception").join();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}, NullPointerException.class));
|
||||
|
||||
|
||||
new TestFlow(adapter, (context) -> {
|
||||
if (StringUtils.equals(context.getActivity().getText(), "foo")) {
|
||||
try {
|
||||
context.sendActivity(context.getActivity().getText()).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (StringUtils.equals(context.getActivity().getText(), "UnsupportedOperationException")) {
|
||||
throw new UnsupportedOperationException("Test");
|
||||
if (StringUtils.equals(context.getActivity().getText(), "foo")) {
|
||||
try {
|
||||
context.sendActivity(context.getActivity().getText()).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (StringUtils.equals(context.getActivity().getText(), "UnsupportedOperationException")) {
|
||||
throw new UnsupportedOperationException("Test");
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.Send("foo")
|
||||
.AssertReply("foo", "passthrough")
|
||||
.Send("UnsupportedOperationException")
|
||||
.AssertReply("Test")
|
||||
.StartTest();
|
||||
return null;
|
||||
})
|
||||
.send("foo")
|
||||
.assertReply("foo", "passthrough")
|
||||
.send("UnsupportedOperationException")
|
||||
.assertReply("Test")
|
||||
.startTest();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package com.microsoft.bot.builder;
|
||||
|
||||
public class CustomKeyState extends BotState {
|
||||
public static final String PROPERTY_NAME = "Microsoft.Bot.Builder.Tests.CustomKeyState";
|
||||
|
||||
public CustomKeyState(Storage storage) {
|
||||
super(storage, PROPERTY_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStorageKey(TurnContext turnContext) {
|
||||
return "CustomKey";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package com.microsoft.bot.builder;
|
||||
|
||||
public class CustomState implements StoreItem {
|
||||
private String _customString;
|
||||
private String _eTag;
|
||||
|
||||
public String getCustomString() {
|
||||
return _customString;
|
||||
}
|
||||
|
||||
public void setCustomString(String customString) {
|
||||
this._customString = customString;
|
||||
}
|
||||
|
||||
public String getETag() {
|
||||
return _eTag;
|
||||
}
|
||||
|
||||
public void setETag(String eTag) {
|
||||
this._eTag = eTag;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
|
||||
|
@ -10,13 +13,10 @@ import org.junit.Test;
|
|||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
// [TestCategory("Russian Doll Middleware, Nested Middleware sets")]
|
||||
public class MiddlewareSetTest extends TestBase
|
||||
{
|
||||
public class MiddlewareSetTest extends TestBase {
|
||||
protected RestConnectorClient connector;
|
||||
protected ChannelAccount bot;
|
||||
protected ChannelAccount user;
|
||||
|
@ -75,7 +75,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
MiddlewareSet m = new MiddlewareSet();
|
||||
wasCalled = false;
|
||||
|
||||
BotCallbackHandler cb = (ctx) ->{
|
||||
BotCallbackHandler cb = (ctx) -> {
|
||||
wasCalled = true;
|
||||
return null;
|
||||
};
|
||||
|
@ -101,7 +101,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
Assert.assertFalse(simple.getCalled());
|
||||
m.receiveActivityWithStatus(null, cb).join();
|
||||
Assert.assertTrue(simple.getCalled());
|
||||
Assert.assertTrue( "Delegate was not called", wasCalled);
|
||||
Assert.assertTrue("Delegate was not called", wasCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -126,7 +126,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
try {
|
||||
m.receiveActivityWithStatus(null, null).join();
|
||||
Assert.assertFalse("Should never have gotten here", true);
|
||||
} catch(CompletionException ce) {
|
||||
} catch (CompletionException ce) {
|
||||
Assert.assertTrue(ce.getCause() instanceof IllegalStateException);
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
WasCalledMiddleware one = new WasCalledMiddleware();
|
||||
WasCalledMiddleware two = new WasCalledMiddleware();
|
||||
|
||||
final int called[] = {0};
|
||||
final int[] called = {0};
|
||||
BotCallbackHandler cb = (context) -> {
|
||||
called[0]++;
|
||||
return null;
|
||||
|
@ -163,16 +163,16 @@ public class MiddlewareSetTest extends TestBase
|
|||
m.receiveActivityWithStatus(null, cb).join();
|
||||
Assert.assertTrue(one.getCalled());
|
||||
Assert.assertTrue(two.getCalled());
|
||||
Assert.assertTrue("Incorrect number of calls to Delegate", called[0] == 1 );
|
||||
Assert.assertTrue("Incorrect number of calls to Delegate", called[0] == 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TwoMiddlewareItemsInOrder() throws Exception {
|
||||
final boolean called1[] = {false};
|
||||
final boolean called2[] = {false};
|
||||
final boolean[] called1 = {false};
|
||||
final boolean[] called2 = {false};
|
||||
|
||||
CallMeMiddleware one = new CallMeMiddleware(() -> {
|
||||
Assert.assertFalse( "Second Middleware was called", called2[0]);
|
||||
Assert.assertFalse("Second Middleware was called", called2[0]);
|
||||
called1[0] = true;
|
||||
});
|
||||
|
||||
|
@ -193,7 +193,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void Status_OneMiddlewareRan() {
|
||||
final boolean called1[] = {false};
|
||||
final boolean[] called1 = {false};
|
||||
|
||||
CallMeMiddleware one = new CallMeMiddleware(() -> called1[0] = true);
|
||||
|
||||
|
@ -201,8 +201,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
m.use(one);
|
||||
|
||||
// The middlware in this pipeline calls next(), so the delegate should be called
|
||||
final boolean didAllRun[] = {false};
|
||||
BotCallbackHandler cb = (context) -> {
|
||||
final boolean[] didAllRun = {false};
|
||||
BotCallbackHandler cb = (context) -> {
|
||||
didAllRun[0] = true;
|
||||
return null;
|
||||
};
|
||||
|
@ -215,8 +215,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
@Test
|
||||
public void Status_RunAtEndEmptyPipeline() {
|
||||
MiddlewareSet m = new MiddlewareSet();
|
||||
final boolean didAllRun[] = {false};
|
||||
BotCallbackHandler cb = (context)-> {
|
||||
final boolean[] didAllRun = {false};
|
||||
BotCallbackHandler cb = (context) -> {
|
||||
didAllRun[0] = true;
|
||||
return null;
|
||||
};
|
||||
|
@ -231,8 +231,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void Status_TwoItemsOneDoesNotCallNext() {
|
||||
final boolean called1[] = {false};
|
||||
final boolean called2[] = {false};
|
||||
final boolean[] called1 = {false};
|
||||
final boolean[] called2 = {false};
|
||||
|
||||
CallMeMiddleware one = new CallMeMiddleware(() -> {
|
||||
Assert.assertFalse("Second Middleware was called", called2[0]);
|
||||
|
@ -248,8 +248,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
m.use(one);
|
||||
m.use(two);
|
||||
|
||||
boolean didAllRun[] = {false};
|
||||
BotCallbackHandler cb= (context) -> {
|
||||
boolean[] didAllRun = {false};
|
||||
BotCallbackHandler cb = (context) -> {
|
||||
didAllRun[0] = true;
|
||||
return null;
|
||||
};
|
||||
|
@ -265,7 +265,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void Status_OneEntryThatDoesNotCallNext() {
|
||||
final boolean called1[] = {false};
|
||||
final boolean[] called1 = {false};
|
||||
|
||||
DoNotCallNextMiddleware one = new DoNotCallNextMiddleware(() -> called1[0] = true);
|
||||
|
||||
|
@ -273,7 +273,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
m.use(one);
|
||||
|
||||
// The middleware in this pipeline DOES NOT call next(), so this must not be called
|
||||
boolean didAllRun[] = {false};
|
||||
boolean[] didAllRun = {false};
|
||||
BotCallbackHandler cb = (context) -> {
|
||||
didAllRun[0] = true;
|
||||
return null;
|
||||
|
@ -289,7 +289,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void AnonymousMiddleware() {
|
||||
final boolean didRun[] = {false};
|
||||
final boolean[] didRun = {false};
|
||||
|
||||
MiddlewareSet m = new MiddlewareSet();
|
||||
MiddlewareCall mwc = (tc, nd) -> {
|
||||
|
@ -305,8 +305,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void TwoAnonymousMiddleware() throws Exception {
|
||||
final boolean didRun1[] = {false};
|
||||
final boolean didRun2[] = {false};
|
||||
final boolean[] didRun1 = {false};
|
||||
final boolean[] didRun2 = {false};
|
||||
|
||||
MiddlewareSet m = new MiddlewareSet();
|
||||
|
||||
|
@ -330,8 +330,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void TwoAnonymousMiddlewareInOrder() {
|
||||
final boolean didRun1[] = {false};
|
||||
final boolean didRun2[] = {false};
|
||||
final boolean[] didRun1 = {false};
|
||||
final boolean[] didRun2 = {false};
|
||||
|
||||
MiddlewareSet m = new MiddlewareSet();
|
||||
MiddlewareCall mwc1 = (tc, nd) -> {
|
||||
|
@ -356,8 +356,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void MixedMiddlewareInOrderAnonymousFirst() throws Exception {
|
||||
final boolean didRun1[] = {false};
|
||||
final boolean didRun2[] = {false};
|
||||
final boolean[] didRun1 = {false};
|
||||
final boolean[] didRun2 = {false};
|
||||
|
||||
MiddlewareSet m = new MiddlewareSet();
|
||||
MiddlewareCall mwc1 = new MiddlewareCall() {
|
||||
|
@ -386,8 +386,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void MixedMiddlewareInOrderAnonymousLast() {
|
||||
final boolean didRun1[] = {false};
|
||||
final boolean didRun2[] = {false};
|
||||
final boolean[] didRun1 = {false};
|
||||
final boolean[] didRun2 = {false};
|
||||
|
||||
MiddlewareSet m = new MiddlewareSet();
|
||||
|
||||
|
@ -413,9 +413,9 @@ public class MiddlewareSetTest extends TestBase
|
|||
|
||||
@Test
|
||||
public void RunCodeBeforeAndAfter() throws Exception {
|
||||
final boolean didRun1[] = {false};
|
||||
final boolean codeafter2run[] = {false};
|
||||
final boolean didRun2[] = {false};
|
||||
final boolean[] didRun1 = {false};
|
||||
final boolean[] codeafter2run = {false};
|
||||
final boolean[] didRun2 = {false};
|
||||
|
||||
MiddlewareSet m = new MiddlewareSet();
|
||||
|
||||
|
@ -446,7 +446,7 @@ public class MiddlewareSetTest extends TestBase
|
|||
@Test
|
||||
public void CatchAnExceptionViaMiddlware() {
|
||||
MiddlewareSet m = new MiddlewareSet();
|
||||
final boolean caughtException[] = {false};
|
||||
final boolean[] caughtException = {false};
|
||||
|
||||
MiddlewareCall mwc1 = new MiddlewareCall() {
|
||||
public CompletableFuture<Void> requestHandler(TurnContext tc, NextDelegate nd) {
|
||||
|
@ -456,7 +456,8 @@ public class MiddlewareSetTest extends TestBase
|
|||
caughtException[0] = true;
|
||||
return null;
|
||||
});
|
||||
}};
|
||||
}
|
||||
};
|
||||
|
||||
m.use(new AnonymousReceiveMiddleware(mwc1));
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import com.microsoft.bot.schema.Activity;
|
||||
|
@ -8,7 +11,6 @@ import org.junit.Assert;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class SimpleAdapter extends BotAdapter {
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
public class StateSettings
|
||||
{
|
||||
private boolean lastWriterWins = true;
|
||||
public boolean getLastWriterWins() {
|
||||
return this.lastWriterWins;
|
||||
}
|
||||
public void setLast(boolean lastWriterWins) {
|
||||
this.lastWriterWins = lastWriterWins;
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
public class StateSettings {
|
||||
private boolean lastWriterWins = true;
|
||||
|
||||
public boolean getLastWriterWins() {
|
||||
return this.lastWriterWins;
|
||||
}
|
||||
|
||||
public void setLast(boolean lastWriterWins) {
|
||||
this.lastWriterWins = lastWriterWins;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import com.microsoft.bot.schema.Activity;
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
package com.microsoft.bot.builder;
|
||||
|
||||
|
||||
public class TestPocoState
|
||||
{
|
||||
private String value;
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package com.microsoft.bot.builder;
|
||||
|
||||
public class TestState implements StoreItem {
|
||||
private String etag;
|
||||
private String value;
|
||||
|
||||
@Override
|
||||
public String getETag() {
|
||||
return this.etag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setETag(String etag) {
|
||||
this.etag = etag;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import com.microsoft.bot.builder.adapters.TestAdapter;
|
||||
import com.microsoft.bot.schema.Activity;
|
||||
import com.microsoft.bot.schema.ActivityTypes;
|
||||
import com.microsoft.bot.schema.ChannelAccount;
|
||||
import com.microsoft.bot.schema.ConversationAccount;
|
||||
|
||||
public final class TestUtilities {
|
||||
public static TurnContext createEmptyContext() {
|
||||
TestAdapter adapter = new TestAdapter();
|
||||
Activity activity = new Activity() {{
|
||||
setType(ActivityTypes.MESSAGE);
|
||||
setChannelId("EmptyContext");
|
||||
setConversation(new ConversationAccount() {{
|
||||
setId("test");
|
||||
}});
|
||||
setFrom(new ChannelAccount() {{
|
||||
setId("empty@empty.context.org");
|
||||
}});
|
||||
}};
|
||||
|
||||
return new TurnContextImpl(adapter, activity);
|
||||
}
|
||||
}
|
|
@ -21,45 +21,45 @@ public class TranscriptMiddlewareTest {
|
|||
@Test
|
||||
public final void Transcript_SimpleReceive() throws Exception {
|
||||
MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore();
|
||||
TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore));
|
||||
TestAdapter adapter = (new TestAdapter()).use(new TranscriptLoggerMiddleware(transcriptStore));
|
||||
final String[] conversationId = {null};
|
||||
|
||||
|
||||
new TestFlow(adapter, (ctxt) ->
|
||||
{
|
||||
|
||||
TurnContextImpl context = (TurnContextImpl) ctxt;
|
||||
conversationId[0] = context.getActivity().getConversation().getId();
|
||||
Activity typingActivity = new Activity(ActivityTypes.TYPING) {{
|
||||
setRelatesTo(context.getActivity().getRelatesTo());
|
||||
}};
|
||||
try {
|
||||
ResourceResponse response = context.sendActivity(typingActivity).join();
|
||||
System.out.printf("Here's the response:");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
try {
|
||||
context.sendActivity("echo:" + context.getActivity().getText()).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
TurnContextImpl context = (TurnContextImpl) ctxt;
|
||||
conversationId[0] = context.getActivity().getConversation().getId();
|
||||
Activity typingActivity = new Activity(ActivityTypes.TYPING) {{
|
||||
setRelatesTo(context.getActivity().getRelatesTo());
|
||||
}};
|
||||
try {
|
||||
ResourceResponse response = context.sendActivity(typingActivity).join();
|
||||
System.out.printf("Here's the response:");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
try {
|
||||
context.sendActivity("echo:" + context.getActivity().getText()).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}).Send("foo")
|
||||
.AssertReply((activity) -> {
|
||||
Assert.assertEquals(activity.getType(), ActivityTypes.TYPING);
|
||||
return null;
|
||||
}).StartTest();
|
||||
//.AssertReply("echo:foo").StartTest();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}).send("foo")
|
||||
.assertReply((activity) -> {
|
||||
Assert.assertEquals(activity.getType(), ActivityTypes.TYPING);
|
||||
return null;
|
||||
}).startTest();
|
||||
//.AssertReply("echo:foo").StartTest();
|
||||
|
||||
|
||||
}
|
||||
|
@ -99,66 +99,65 @@ public class TranscriptMiddlewareTest {
|
|||
@Test
|
||||
public final void Transcript_LogActivities() throws ExecutionException, InterruptedException {
|
||||
MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore();
|
||||
TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore));
|
||||
TestAdapter adapter = (new TestAdapter()).use(new TranscriptLoggerMiddleware(transcriptStore));
|
||||
final String[] conversationId = {null};
|
||||
|
||||
|
||||
String result = new TestFlow(adapter, (context) ->
|
||||
{
|
||||
|
||||
//TurnContextImpl context = (TurnContextImpl) ctxt;
|
||||
conversationId[0] = context.getActivity().getConversation().getId();
|
||||
Activity typingActivity = new Activity(ActivityTypes.TYPING) {{
|
||||
setRelatesTo(context.getActivity().getRelatesTo());
|
||||
}};
|
||||
try {
|
||||
context.sendActivity((Activity)typingActivity).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
try {
|
||||
context.sendActivity("echo:" + context.getActivity().getText()).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
//TurnContextImpl context = (TurnContextImpl) ctxt;
|
||||
conversationId[0] = context.getActivity().getConversation().getId();
|
||||
Activity typingActivity = new Activity(ActivityTypes.TYPING) {{
|
||||
setRelatesTo(context.getActivity().getRelatesTo());
|
||||
}};
|
||||
try {
|
||||
context.sendActivity(typingActivity).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
try {
|
||||
context.sendActivity("echo:" + context.getActivity().getText()).join();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}).Send("foo")
|
||||
.AssertReply((activity) -> {
|
||||
Assert.assertEquals(activity.getType(), ActivityTypes.TYPING);
|
||||
return null;
|
||||
})
|
||||
.AssertReply("echo:foo")
|
||||
.Send("bar")
|
||||
.AssertReply((activity) -> {
|
||||
Assert.assertEquals(activity.getType(), ActivityTypes.TYPING);
|
||||
return null;
|
||||
})
|
||||
.AssertReply("echo:bar")
|
||||
.StartTest();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}).send("foo")
|
||||
.assertReply((activity) -> {
|
||||
Assert.assertEquals(activity.getType(), ActivityTypes.TYPING);
|
||||
return null;
|
||||
})
|
||||
.assertReply("echo:foo")
|
||||
.send("bar")
|
||||
.assertReply((activity) -> {
|
||||
Assert.assertEquals(activity.getType(), ActivityTypes.TYPING);
|
||||
return null;
|
||||
})
|
||||
.assertReply("echo:bar")
|
||||
.startTest();
|
||||
|
||||
|
||||
PagedResult pagedResult = transcriptStore.getTranscriptActivities("test", conversationId[0]).join();
|
||||
Assert.assertEquals(6, pagedResult.getItems().length);
|
||||
Assert.assertEquals( "foo", ((Activity)pagedResult.getItems()[0]).getText());
|
||||
Assert.assertNotEquals(((Activity)pagedResult.getItems()[1]), null);
|
||||
Assert.assertEquals("foo", ((Activity) pagedResult.getItems()[0]).getText());
|
||||
Assert.assertNotEquals(pagedResult.getItems()[1], null);
|
||||
Assert.assertEquals("echo:foo", ((Activity) pagedResult.getItems()[2]).getText());
|
||||
Assert.assertEquals("bar", ((Activity)pagedResult.getItems()[3]).getText());
|
||||
Assert.assertEquals("bar", ((Activity) pagedResult.getItems()[3]).getText());
|
||||
|
||||
Assert.assertTrue(pagedResult.getItems()[4] != null);
|
||||
Assert.assertEquals("echo:bar", ((Activity)pagedResult.getItems()[5]).getText());
|
||||
for (Object activity : pagedResult.getItems())
|
||||
{
|
||||
Assert.assertEquals("echo:bar", ((Activity) pagedResult.getItems()[5]).getText());
|
||||
for (Object activity : pagedResult.getItems()) {
|
||||
Assert.assertFalse(StringUtils.isBlank(((Activity) activity).getId()));
|
||||
Assert.assertTrue(((Activity)activity).getTimestamp().isAfter(Long.MIN_VALUE));
|
||||
Assert.assertTrue(((Activity) activity).getTimestamp().isAfter(Long.MIN_VALUE));
|
||||
}
|
||||
System.out.printf("Complete");
|
||||
}
|
||||
|
@ -166,7 +165,7 @@ public class TranscriptMiddlewareTest {
|
|||
@Test
|
||||
public void Transcript_LogUpdateActivities() throws InterruptedException, ExecutionException {
|
||||
MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore();
|
||||
TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore));
|
||||
TestAdapter adapter = (new TestAdapter()).use(new TranscriptLoggerMiddleware(transcriptStore));
|
||||
final String[] conversationId = {null};
|
||||
final Activity[] activityToUpdate = {null};
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
@ -181,7 +180,7 @@ public class TranscriptMiddlewareTest {
|
|||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
Activity activity = ((Activity) context.getActivity()).createReply("response");
|
||||
Activity activity = context.getActivity().createReply("response");
|
||||
ResourceResponse response = null;
|
||||
try {
|
||||
response = context.sendActivity(activity).join();
|
||||
|
@ -198,16 +197,16 @@ public class TranscriptMiddlewareTest {
|
|||
|
||||
return null;
|
||||
})
|
||||
.Send("foo")
|
||||
.Send("update")
|
||||
.AssertReply("new response")
|
||||
.StartTest();
|
||||
.send("foo")
|
||||
.send("update")
|
||||
.assertReply("new response")
|
||||
.startTest();
|
||||
|
||||
Thread.sleep(500);
|
||||
PagedResult pagedResult = transcriptStore.getTranscriptActivities("test", conversationId[0]).join();
|
||||
Assert.assertEquals(4, pagedResult.getItems().length);
|
||||
Assert.assertEquals("foo", ((Activity)pagedResult.getItems()[0]).getText());
|
||||
Assert.assertEquals( "response", ((Activity)pagedResult.getItems()[1]).getText());
|
||||
Assert.assertEquals("foo", ((Activity) pagedResult.getItems()[0]).getText());
|
||||
Assert.assertEquals("response", ((Activity) pagedResult.getItems()[1]).getText());
|
||||
// TODO: Fix the following 3 asserts so they work correctly. They succeed in the travis builds and fail in the
|
||||
// BotBuilder-Java 4.0 master build.
|
||||
//Assert.assertEquals( "new response", ((Activity)pagedResult.getItems()[2]).text());
|
||||
|
@ -218,7 +217,7 @@ public class TranscriptMiddlewareTest {
|
|||
@Test
|
||||
public final void Transcript_LogDeleteActivities() throws InterruptedException, ExecutionException {
|
||||
MemoryTranscriptStore transcriptStore = new MemoryTranscriptStore();
|
||||
TestAdapter adapter = (new TestAdapter()).Use(new TranscriptLoggerMiddleware(transcriptStore));
|
||||
TestAdapter adapter = (new TestAdapter()).use(new TranscriptLoggerMiddleware(transcriptStore));
|
||||
final String[] conversationId = {null};
|
||||
final String[] activityId = {null};
|
||||
new TestFlow(adapter, (context) -> {
|
||||
|
@ -231,7 +230,7 @@ public class TranscriptMiddlewareTest {
|
|||
Assert.fail();
|
||||
}
|
||||
} else {
|
||||
Activity activity = ((Activity) context.getActivity()).createReply("response");
|
||||
Activity activity = context.getActivity().createReply("response");
|
||||
ResourceResponse response = null;
|
||||
try {
|
||||
response = context.sendActivity(activity).join();
|
||||
|
@ -244,26 +243,26 @@ public class TranscriptMiddlewareTest {
|
|||
|
||||
return null;
|
||||
})
|
||||
.Send("foo")
|
||||
.AssertReply("response")
|
||||
.Send("deleteIt")
|
||||
.StartTest();
|
||||
.send("foo")
|
||||
.assertReply("response")
|
||||
.send("deleteIt")
|
||||
.startTest();
|
||||
|
||||
Thread.sleep(1500);
|
||||
PagedResult pagedResult = transcriptStore.getTranscriptActivities("test", conversationId[0]).join();
|
||||
for (Object act : pagedResult.getItems()) {
|
||||
System.out.printf("Here is the object: %s : Type: %s\n", act.getClass().getTypeName(), ((Activity)act).getType());
|
||||
System.out.printf("Here is the object: %s : Type: %s\n", act.getClass().getTypeName(), ((Activity) act).getType());
|
||||
}
|
||||
|
||||
for (Object activity : pagedResult.getItems() ) {
|
||||
System.out.printf("Recipient: %s\nText: %s\n", ((Activity) activity).getRecipient().getName(), ((Activity)activity).getText());
|
||||
for (Object activity : pagedResult.getItems()) {
|
||||
System.out.printf("Recipient: %s\nText: %s\n", ((Activity) activity).getRecipient().getName(), ((Activity) activity).getText());
|
||||
}
|
||||
Assert.assertEquals(4, pagedResult.getItems().length);
|
||||
Assert.assertEquals("foo", ((Activity)pagedResult.getItems()[0]).getText());
|
||||
Assert.assertEquals("response", ((Activity)pagedResult.getItems()[1]).getText());
|
||||
Assert.assertEquals("deleteIt", ((Activity)pagedResult.getItems()[2]).getText());
|
||||
Assert.assertEquals(ActivityTypes.MESSAGE_DELETE, ((Activity)pagedResult.getItems()[3]).getType());
|
||||
Assert.assertEquals(((Activity)pagedResult.getItems()[1]).getId(), ((Activity) pagedResult.getItems()[3]).getId());
|
||||
Assert.assertEquals("foo", ((Activity) pagedResult.getItems()[0]).getText());
|
||||
Assert.assertEquals("response", ((Activity) pagedResult.getItems()[1]).getText());
|
||||
Assert.assertEquals("deleteIt", ((Activity) pagedResult.getItems()[2]).getText());
|
||||
Assert.assertEquals(ActivityTypes.MESSAGE_DELETE, ((Activity) pagedResult.getItems()[3]).getType());
|
||||
Assert.assertEquals(((Activity) pagedResult.getItems()[1]).getId(), ((Activity) pagedResult.getItems()[3]).getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,17 +0,0 @@
|
|||
package com.microsoft.bot.builder;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class TypedObject {
|
||||
@JsonProperty
|
||||
private String name;
|
||||
|
||||
public String name() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public TypedObject withName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,12 +1,17 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class WasCalledMiddleware implements Middleware {
|
||||
boolean called = false;
|
||||
|
||||
public boolean getCalled() {
|
||||
return this.called;
|
||||
}
|
||||
|
||||
public void setCalled(boolean called) {
|
||||
this.called = called;
|
||||
}
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
package com.microsoft.bot.builder.adapters;
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder.adapters;
|
||||
|
||||
import com.microsoft.bot.builder.*;
|
||||
import com.microsoft.bot.schema.Activity;
|
||||
import com.microsoft.bot.schema.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class TestAdapter extends BotAdapter {
|
||||
private int nextId = 0;
|
||||
private final Queue<Activity> botReplies = new LinkedList<>();
|
||||
private int nextId = 0;
|
||||
private ConversationReference conversationReference;
|
||||
|
||||
public TestAdapter() {
|
||||
|
@ -53,13 +51,14 @@ public class TestAdapter extends BotAdapter {
|
|||
return botReplies;
|
||||
}
|
||||
|
||||
public TestAdapter Use(Middleware middleware) {
|
||||
@Override
|
||||
public TestAdapter use(Middleware middleware) {
|
||||
super.use(middleware);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void ProcessActivity(Activity activity,
|
||||
BotCallbackHandler callback
|
||||
BotCallbackHandler callback
|
||||
) throws Exception {
|
||||
synchronized (this.conversationReference()) {
|
||||
// ready for next reply
|
||||
|
@ -117,7 +116,10 @@ public class TestAdapter extends BotAdapter {
|
|||
// to keep the behavior as close as possible to facillitate
|
||||
// more realistic tests.
|
||||
int delayMs = (int) activity.getValue();
|
||||
try { Thread.sleep(delayMs); } catch (InterruptedException e) {}
|
||||
try {
|
||||
Thread.sleep(delayMs);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
} else {
|
||||
synchronized (this.botReplies) {
|
||||
this.botReplies.add(activity);
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder.adapters;
|
||||
|
||||
import com.microsoft.bot.builder.BotCallbackHandler;
|
||||
import com.microsoft.bot.builder.TurnContext;
|
||||
import com.microsoft.bot.connector.ExecutorFactory;
|
||||
import com.microsoft.bot.schema.Activity;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -11,7 +13,6 @@ import org.junit.Assert;
|
|||
import java.lang.management.ManagementFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -23,11 +24,9 @@ public class TestFlow {
|
|||
BotCallbackHandler callback;
|
||||
|
||||
ArrayList<Supplier<String>> tasks = new ArrayList<Supplier<String>>();
|
||||
ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory()
|
||||
{
|
||||
ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() {
|
||||
@Override
|
||||
public ForkJoinWorkerThread newThread(ForkJoinPool pool)
|
||||
{
|
||||
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
|
||||
final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
|
||||
worker.setName("TestFlow-" + worker.getPoolIndex());
|
||||
return worker;
|
||||
|
@ -62,7 +61,7 @@ public class TestFlow {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public String StartTest() throws ExecutionException, InterruptedException {
|
||||
public String startTest() {
|
||||
|
||||
System.out.printf("+------------------------------------------+\n");
|
||||
int count = 0;
|
||||
|
@ -84,7 +83,7 @@ public class TestFlow {
|
|||
* @param userSays
|
||||
* @return
|
||||
*/
|
||||
public TestFlow Send(String userSays) throws IllegalArgumentException {
|
||||
public TestFlow send(String userSays) throws IllegalArgumentException {
|
||||
if (userSays == null)
|
||||
throw new IllegalArgumentException("You have to pass a userSays parameter");
|
||||
|
||||
|
@ -108,7 +107,7 @@ public class TestFlow {
|
|||
* @param userActivity
|
||||
* @return
|
||||
*/
|
||||
public TestFlow Send(Activity userActivity) {
|
||||
public TestFlow send(Activity userActivity) {
|
||||
if (userActivity == null)
|
||||
throw new IllegalArgumentException("You have to pass an Activity");
|
||||
|
||||
|
@ -118,7 +117,7 @@ public class TestFlow {
|
|||
|
||||
|
||||
try {
|
||||
this.adapter.ProcessActivity((Activity) userActivity, this.callback);
|
||||
this.adapter.ProcessActivity(userActivity, this.callback);
|
||||
return "TestFlow: Send() -> ProcessActivity: " + userActivity.getText();
|
||||
} catch (Exception e) {
|
||||
return e.getMessage();
|
||||
|
@ -134,13 +133,13 @@ public class TestFlow {
|
|||
* @param ms
|
||||
* @return
|
||||
*/
|
||||
public TestFlow Delay(int ms) {
|
||||
public TestFlow delay(int ms) {
|
||||
return new TestFlow(() ->
|
||||
{
|
||||
System.out.printf("TestFlow(%s): Delay(%s ms) called. ", Thread.currentThread().getId(), ms);
|
||||
System.out.flush();
|
||||
try {
|
||||
Thread.sleep((int) ms);
|
||||
Thread.sleep(ms);
|
||||
} catch (InterruptedException e) {
|
||||
return e.getMessage();
|
||||
}
|
||||
|
@ -154,16 +153,16 @@ public class TestFlow {
|
|||
* @param expected
|
||||
* @return
|
||||
*/
|
||||
public TestFlow AssertReply(String expected) {
|
||||
return this.AssertReply(expected, null, 3000);
|
||||
public TestFlow assertReply(String expected) {
|
||||
return this.assertReply(expected, null, 3000);
|
||||
}
|
||||
|
||||
public TestFlow AssertReply(String expected, String description) {
|
||||
return this.AssertReply(expected, description, 3000);
|
||||
public TestFlow assertReply(String expected, String description) {
|
||||
return this.assertReply(expected, description, 3000);
|
||||
}
|
||||
|
||||
public TestFlow AssertReply(String expected, String description, int timeout) {
|
||||
return this.AssertReply(this.adapter.MakeActivity(expected), description, timeout);
|
||||
public TestFlow assertReply(String expected, String description, int timeout) {
|
||||
return this.assertReply(this.adapter.MakeActivity(expected), description, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,16 +171,16 @@ public class TestFlow {
|
|||
* @param expected
|
||||
* @return
|
||||
*/
|
||||
public TestFlow AssertReply(Activity expected) {
|
||||
public TestFlow assertReply(Activity expected) {
|
||||
String description = Thread.currentThread().getStackTrace()[1].getMethodName();
|
||||
return AssertReply(expected, description, 3000);
|
||||
return assertReply(expected, description, 3000);
|
||||
}
|
||||
|
||||
public TestFlow AssertReply(Activity expected, String description, int timeout) {
|
||||
public TestFlow assertReply(Activity expected, String description, int timeout) {
|
||||
if (description == null)
|
||||
description = Thread.currentThread().getStackTrace()[1].getMethodName();
|
||||
String finalDescription = description;
|
||||
return this.AssertReply((reply) -> {
|
||||
return this.assertReply((reply) -> {
|
||||
if (expected.getType() != reply.getType())
|
||||
return String.format("%s: Type should match", finalDescription);
|
||||
if (expected.getText().equals(reply.getText())) {
|
||||
|
@ -201,16 +200,16 @@ public class TestFlow {
|
|||
* @param validateActivity
|
||||
* @return
|
||||
*/
|
||||
public TestFlow AssertReply(Function<Activity, String> validateActivity) {
|
||||
public TestFlow assertReply(Function<Activity, String> validateActivity) {
|
||||
String description = Thread.currentThread().getStackTrace()[1].getMethodName();
|
||||
return AssertReply(validateActivity, description, 3000);
|
||||
return assertReply(validateActivity, description, 3000);
|
||||
}
|
||||
|
||||
public TestFlow AssertReply(Function<Activity, String> validateActivity, String description) {
|
||||
return AssertReply(validateActivity, description, 3000);
|
||||
public TestFlow assertReply(Function<Activity, String> validateActivity, String description) {
|
||||
return assertReply(validateActivity, description, 3000);
|
||||
}
|
||||
|
||||
public TestFlow AssertReply(Function<Activity, String> validateActivity, String description, int timeout) {
|
||||
public TestFlow assertReply(Function<Activity, String> validateActivity, String description, int timeout) {
|
||||
return new TestFlow(() -> {
|
||||
System.out.println(String.format("AssertReply: Starting loop : %s (Thread:%s)", description, Thread.currentThread().getId()));
|
||||
System.out.flush();
|
||||
|
@ -240,7 +239,7 @@ public class TestFlow {
|
|||
System.out.printf("AssertReply(tid:%s): Received Reply: %s ", Thread.currentThread().getId(), (replyActivity.getText() == null) ? "No Text set" : replyActivity.getText());
|
||||
System.out.flush();
|
||||
System.out.printf("=============\n From: %s\n To:%s\n ==========\n", (replyActivity.getFrom() == null) ? "No from set" : replyActivity.getFrom().getName(),
|
||||
(replyActivity.getRecipient() == null) ? "No recipient set" : replyActivity.getRecipient().getName());
|
||||
(replyActivity.getRecipient() == null) ? "No recipient set" : replyActivity.getRecipient().getName());
|
||||
System.out.flush();
|
||||
|
||||
// if we have a reply
|
||||
|
@ -274,7 +273,7 @@ public class TestFlow {
|
|||
* @param expected
|
||||
* @return
|
||||
*/
|
||||
public TestFlow Turn(String userSays, String expected, String description, int timeout) {
|
||||
public TestFlow turn(String userSays, String expected, String description, int timeout) {
|
||||
String result = null;
|
||||
try {
|
||||
|
||||
|
@ -294,58 +293,58 @@ public class TestFlow {
|
|||
}
|
||||
|
||||
}, ExecutorFactory.getExecutor())
|
||||
.thenApply(arg -> { // Assert Reply
|
||||
int finalTimeout = Integer.MAX_VALUE;
|
||||
if (isDebug())
|
||||
finalTimeout = Integer.MAX_VALUE;
|
||||
Function<Activity, String> validateActivity = activity -> {
|
||||
if (activity.getText().equals(expected)) {
|
||||
System.out.println(String.format("TestTurn(tid:%s): Validated text is: %s", Thread.currentThread().getId(), expected));
|
||||
System.out.flush();
|
||||
|
||||
return "SUCCESS";
|
||||
}
|
||||
System.out.println(String.format("TestTurn(tid:%s): Failed validate text is: %s", Thread.currentThread().getId(), expected));
|
||||
.thenApply(arg -> { // Assert Reply
|
||||
int finalTimeout = Integer.MAX_VALUE;
|
||||
if (isDebug())
|
||||
finalTimeout = Integer.MAX_VALUE;
|
||||
Function<Activity, String> validateActivity = activity -> {
|
||||
if (activity.getText().equals(expected)) {
|
||||
System.out.println(String.format("TestTurn(tid:%s): Validated text is: %s", Thread.currentThread().getId(), expected));
|
||||
System.out.flush();
|
||||
|
||||
return String.format("FAIL: %s received in Activity.text (%s expected)", activity.getText(), expected);
|
||||
};
|
||||
|
||||
|
||||
System.out.println(String.format("TestTurn(tid:%s): Started receive loop: %s", Thread.currentThread().getId(), description));
|
||||
System.out.flush();
|
||||
DateTime start = DateTime.now();
|
||||
while (true) {
|
||||
DateTime current = DateTime.now();
|
||||
|
||||
if ((current.getMillis() - start.getMillis()) > (long) finalTimeout)
|
||||
return String.format("TestTurn: %d ms Timed out waiting for:'%s'", finalTimeout, description);
|
||||
|
||||
|
||||
Activity replyActivity = this.adapter.GetNextReply();
|
||||
|
||||
|
||||
if (replyActivity != null) {
|
||||
// if we have a reply
|
||||
System.out.println(String.format("TestTurn(tid:%s): Received Reply: %s",
|
||||
Thread.currentThread().getId(),
|
||||
String.format("\n========\n To:%s\n From:%s\n Msg:%s\n=======", replyActivity.getRecipient().getName(), replyActivity.getFrom().getName(), replyActivity.getText())
|
||||
));
|
||||
System.out.flush();
|
||||
return validateActivity.apply(replyActivity);
|
||||
} else {
|
||||
System.out.println(String.format("TestTurn(tid:%s): No reply..", Thread.currentThread().getId()));
|
||||
System.out.flush();
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return "SUCCESS";
|
||||
}
|
||||
})
|
||||
.get(timeout, TimeUnit.MILLISECONDS);
|
||||
System.out.println(String.format("TestTurn(tid:%s): Failed validate text is: %s", Thread.currentThread().getId(), expected));
|
||||
System.out.flush();
|
||||
|
||||
return String.format("FAIL: %s received in Activity.text (%s expected)", activity.getText(), expected);
|
||||
};
|
||||
|
||||
|
||||
System.out.println(String.format("TestTurn(tid:%s): Started receive loop: %s", Thread.currentThread().getId(), description));
|
||||
System.out.flush();
|
||||
DateTime start = DateTime.now();
|
||||
while (true) {
|
||||
DateTime current = DateTime.now();
|
||||
|
||||
if ((current.getMillis() - start.getMillis()) > (long) finalTimeout)
|
||||
return String.format("TestTurn: %d ms Timed out waiting for:'%s'", finalTimeout, description);
|
||||
|
||||
|
||||
Activity replyActivity = this.adapter.GetNextReply();
|
||||
|
||||
|
||||
if (replyActivity != null) {
|
||||
// if we have a reply
|
||||
System.out.println(String.format("TestTurn(tid:%s): Received Reply: %s",
|
||||
Thread.currentThread().getId(),
|
||||
String.format("\n========\n To:%s\n From:%s\n Msg:%s\n=======", replyActivity.getRecipient().getName(), replyActivity.getFrom().getName(), replyActivity.getText())
|
||||
));
|
||||
System.out.flush();
|
||||
return validateActivity.apply(replyActivity);
|
||||
} else {
|
||||
System.out.println(String.format("TestTurn(tid:%s): No reply..", Thread.currentThread().getId()));
|
||||
System.out.flush();
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
.get(timeout, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
|
@ -364,20 +363,20 @@ public class TestFlow {
|
|||
* @param expected
|
||||
* @return
|
||||
*/
|
||||
public TestFlow Test(String userSays, String expected) {
|
||||
return Test(userSays, expected, null, 3000);
|
||||
public TestFlow test(String userSays, String expected) {
|
||||
return test(userSays, expected, null, 3000);
|
||||
}
|
||||
|
||||
public TestFlow Test(String userSays, String expected, String description) {
|
||||
return Test(userSays, expected, description, 3000);
|
||||
public TestFlow test(String userSays, String expected, String description) {
|
||||
return test(userSays, expected, description, 3000);
|
||||
}
|
||||
|
||||
public TestFlow Test(String userSays, String expected, String description, int timeout) {
|
||||
public TestFlow test(String userSays, String expected, String description, int timeout) {
|
||||
if (expected == null)
|
||||
throw new IllegalArgumentException("expected");
|
||||
|
||||
return this.Send(userSays)
|
||||
.AssertReply(expected, description, timeout);
|
||||
return this.send(userSays)
|
||||
.assertReply(expected, description, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -387,20 +386,20 @@ public class TestFlow {
|
|||
* @param expected
|
||||
* @return
|
||||
*/
|
||||
public TestFlow Test(String userSays, Activity expected) {
|
||||
return Test(userSays, expected, null, 3000);
|
||||
public TestFlow test(String userSays, Activity expected) {
|
||||
return test(userSays, expected, null, 3000);
|
||||
}
|
||||
|
||||
public TestFlow Test(String userSays, Activity expected, String description) {
|
||||
return Test(userSays, expected, description, 3000);
|
||||
public TestFlow test(String userSays, Activity expected, String description) {
|
||||
return test(userSays, expected, description, 3000);
|
||||
}
|
||||
|
||||
public TestFlow Test(String userSays, Activity expected, String description, int timeout) {
|
||||
public TestFlow test(String userSays, Activity expected, String description, int timeout) {
|
||||
if (expected == null)
|
||||
throw new IllegalArgumentException("expected");
|
||||
|
||||
return this.Send(userSays)
|
||||
.AssertReply(expected, description, timeout);
|
||||
return this.send(userSays)
|
||||
.assertReply(expected, description, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -410,20 +409,20 @@ public class TestFlow {
|
|||
* @param expected
|
||||
* @return
|
||||
*/
|
||||
public TestFlow Test(String userSays, Function<Activity, String> expected) {
|
||||
return Test(userSays, expected, null, 3000);
|
||||
public TestFlow test(String userSays, Function<Activity, String> expected) {
|
||||
return test(userSays, expected, null, 3000);
|
||||
}
|
||||
|
||||
public TestFlow Test(String userSays, Function<Activity, String> expected, String description) {
|
||||
return Test(userSays, expected, description, 3000);
|
||||
public TestFlow test(String userSays, Function<Activity, String> expected, String description) {
|
||||
return test(userSays, expected, description, 3000);
|
||||
}
|
||||
|
||||
public TestFlow Test(String userSays, Function<Activity, String> expected, String description, int timeout) {
|
||||
public TestFlow test(String userSays, Function<Activity, String> expected, String description, int timeout) {
|
||||
if (expected == null)
|
||||
throw new IllegalArgumentException("expected");
|
||||
|
||||
return this.Send(userSays)
|
||||
.AssertReply(expected, description, timeout);
|
||||
return this.send(userSays)
|
||||
.assertReply(expected, description, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -432,19 +431,19 @@ public class TestFlow {
|
|||
* @param candidates
|
||||
* @return
|
||||
*/
|
||||
public TestFlow AssertReplyOneOf(String[] candidates) {
|
||||
return AssertReplyOneOf(candidates, null, 3000);
|
||||
public TestFlow assertReplyOneOf(String[] candidates) {
|
||||
return assertReplyOneOf(candidates, null, 3000);
|
||||
}
|
||||
|
||||
public TestFlow AssertReplyOneOf(String[] candidates, String description) {
|
||||
return AssertReplyOneOf(candidates, description, 3000);
|
||||
public TestFlow assertReplyOneOf(String[] candidates, String description) {
|
||||
return assertReplyOneOf(candidates, description, 3000);
|
||||
}
|
||||
|
||||
public TestFlow AssertReplyOneOf(String[] candidates, String description, int timeout) {
|
||||
public TestFlow assertReplyOneOf(String[] candidates, String description, int timeout) {
|
||||
if (candidates == null)
|
||||
throw new IllegalArgumentException("candidates");
|
||||
|
||||
return this.AssertReply((reply) -> {
|
||||
return this.assertReply((reply) -> {
|
||||
for (String candidate : candidates) {
|
||||
if (StringUtils.equals(reply.getText(), candidate))
|
||||
return null;
|
||||
|
|
|
@ -1,327 +1,326 @@
|
|||
package com.microsoft.bot.builder.base;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import okhttp3.*;
|
||||
import okhttp3.internal.Util;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
public class InterceptorManager {
|
||||
|
||||
private final static String RECORD_FOLDER = "session-records/";
|
||||
|
||||
private Map<String, String> textReplacementRules = new HashMap<String, String>();
|
||||
// Stores a map of all the HTTP properties in a session
|
||||
// A state machine ensuring a test is always reset before another one is setup
|
||||
|
||||
protected RecordedData recordedData;
|
||||
|
||||
private final String testName;
|
||||
|
||||
private final TestBase.TestMode testMode;
|
||||
|
||||
private InterceptorManager(String testName, TestBase.TestMode testMode) {
|
||||
this.testName = testName;
|
||||
this.testMode = testMode;
|
||||
}
|
||||
|
||||
public void addTextReplacementRule(String regex, String replacement) {
|
||||
textReplacementRules.put(regex, replacement);
|
||||
}
|
||||
|
||||
// factory method
|
||||
public static InterceptorManager create(String testName, TestBase.TestMode testMode) throws IOException {
|
||||
InterceptorManager interceptorManager = new InterceptorManager(testName, testMode);
|
||||
|
||||
return interceptorManager;
|
||||
}
|
||||
|
||||
public boolean isRecordMode() {
|
||||
return testMode == TestBase.TestMode.RECORD;
|
||||
}
|
||||
|
||||
public boolean isPlaybackMode() {
|
||||
return testMode == TestBase.TestMode.PLAYBACK;
|
||||
}
|
||||
|
||||
public Interceptor initInterceptor() throws IOException {
|
||||
switch (testMode) {
|
||||
case RECORD:
|
||||
recordedData = new RecordedData();
|
||||
return new Interceptor() {
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
return record(chain);
|
||||
}
|
||||
};
|
||||
case PLAYBACK:
|
||||
readDataFromFile();
|
||||
return new Interceptor() {
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
return playback(chain);
|
||||
}
|
||||
};
|
||||
default:
|
||||
System.out.println("==> Unknown AZURE_TEST_MODE: " + testMode);
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
public void finalizeInterceptor() throws IOException {
|
||||
switch (testMode) {
|
||||
case RECORD:
|
||||
writeDataToFile();
|
||||
break;
|
||||
case PLAYBACK:
|
||||
// Do nothing
|
||||
break;
|
||||
default:
|
||||
System.out.println("==> Unknown AZURE_TEST_MODE: " + testMode);
|
||||
};
|
||||
}
|
||||
|
||||
private Response record(Interceptor.Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
NetworkCallRecord networkCallRecord = new NetworkCallRecord();
|
||||
|
||||
networkCallRecord.Headers = new HashMap<>();
|
||||
|
||||
if (request.header("Content-Type") != null) {
|
||||
networkCallRecord.Headers.put("Content-Type", request.header("Content-Type"));
|
||||
}
|
||||
if (request.header("x-ms-version") != null) {
|
||||
networkCallRecord.Headers.put("x-ms-version", request.header("x-ms-version"));
|
||||
}
|
||||
if (request.header("User-Agent") != null) {
|
||||
networkCallRecord.Headers.put("User-Agent", request.header("User-Agent"));
|
||||
}
|
||||
|
||||
networkCallRecord.Method = request.method();
|
||||
networkCallRecord.Uri = applyReplacementRule(request.url().toString().replaceAll("\\?$", ""));
|
||||
|
||||
networkCallRecord.Body = bodyToString(request);
|
||||
|
||||
Response response = chain.proceed(request);
|
||||
|
||||
networkCallRecord.Response = new HashMap<>();
|
||||
networkCallRecord.Response.put("StatusCode", Integer.toString(response.code()));
|
||||
extractResponseData(networkCallRecord.Response, response);
|
||||
|
||||
// remove pre-added header if this is a waiting or redirection
|
||||
if (networkCallRecord.Response.get("Body") != null) {
|
||||
if (networkCallRecord.Response.get("Body").contains("<Status>InProgress</Status>")
|
||||
|| Integer.parseInt(networkCallRecord.Response.get("StatusCode")) == 307) {
|
||||
// Do nothing
|
||||
} else {
|
||||
synchronized (recordedData.getNetworkCallRecords()) {
|
||||
recordedData.getNetworkCallRecords().add(networkCallRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private String bodyToString(final Request request) {
|
||||
try {
|
||||
final Buffer buffer = new Buffer();
|
||||
|
||||
request.newBuilder().build().body().writeTo(buffer);
|
||||
return buffer.readUtf8();
|
||||
} catch (final Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private Response playback(Interceptor.Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
String incomingUrl = applyReplacementRule(request.url().toString());
|
||||
String incomingMethod = request.method();
|
||||
|
||||
incomingUrl = removeHost(incomingUrl);
|
||||
NetworkCallRecord networkCallRecord = null;
|
||||
synchronized (recordedData) {
|
||||
for (Iterator<NetworkCallRecord> iterator = recordedData.getNetworkCallRecords().iterator(); iterator.hasNext(); ) {
|
||||
NetworkCallRecord record = iterator.next();
|
||||
if (record.Method.equalsIgnoreCase(incomingMethod) && removeHost(record.Uri).equalsIgnoreCase(incomingUrl)) {
|
||||
networkCallRecord = record;
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (networkCallRecord == null) {
|
||||
System.out.println("NOT FOUND - " + incomingMethod + " " + incomingUrl);
|
||||
System.out.println("Remaining records " + recordedData.getNetworkCallRecords().size());
|
||||
throw new IOException("==> Unexpected request: " + incomingMethod + " " + incomingUrl);
|
||||
}
|
||||
|
||||
int recordStatusCode = Integer.parseInt(networkCallRecord.Response.get("StatusCode"));
|
||||
|
||||
//Response originalResponse = chain.proceed(request);
|
||||
//originalResponse.body().close();
|
||||
|
||||
Response.Builder responseBuilder = new Response.Builder()
|
||||
.request(request.newBuilder().build())
|
||||
.protocol(Protocol.HTTP_2)
|
||||
.code(recordStatusCode).message("-");
|
||||
|
||||
for (Map.Entry<String, String> pair : networkCallRecord.Response.entrySet()) {
|
||||
if (!pair.getKey().equals("StatusCode") && !pair.getKey().equals("Body") && !pair.getKey().equals("Content-Length")) {
|
||||
String rawHeader = pair.getValue();
|
||||
for (Map.Entry<String, String> rule : textReplacementRules.entrySet()) {
|
||||
if (rule.getValue() != null) {
|
||||
rawHeader = rawHeader.replaceAll(rule.getKey(), rule.getValue());
|
||||
}
|
||||
}
|
||||
responseBuilder.addHeader(pair.getKey(), rawHeader);
|
||||
}
|
||||
}
|
||||
|
||||
String rawBody = networkCallRecord.Response.get("Body");
|
||||
if (rawBody != null) {
|
||||
for (Map.Entry<String, String> rule : textReplacementRules.entrySet()) {
|
||||
if (rule.getValue() != null) {
|
||||
rawBody = rawBody.replaceAll(rule.getKey(), rule.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
String rawContentType = networkCallRecord.Response.get("content-type");
|
||||
String contentType = rawContentType == null
|
||||
? "application/json; charset=utf-8"
|
||||
: rawContentType;
|
||||
|
||||
ResponseBody responseBody;
|
||||
|
||||
if (contentType.toLowerCase().contains("application/json")) {
|
||||
responseBody = ResponseBody.create(MediaType.parse(contentType), rawBody.getBytes());
|
||||
} else {
|
||||
responseBody = ResponseBody.create(MediaType.parse(contentType), BaseEncoding.base64().decode(rawBody));
|
||||
}
|
||||
|
||||
responseBuilder.body(responseBody);
|
||||
responseBuilder.addHeader("Content-Length", String.valueOf(rawBody.getBytes("UTF-8").length));
|
||||
}
|
||||
|
||||
Response newResponse = responseBuilder.build();
|
||||
|
||||
return newResponse;
|
||||
}
|
||||
|
||||
private void extractResponseData(Map<String, String> responseData, Response response) throws IOException {
|
||||
Map<String, List<String>> headers = response.headers().toMultimap();
|
||||
boolean addedRetryAfter = false;
|
||||
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
|
||||
String headerValueToStore = header.getValue().get(0);
|
||||
|
||||
if (header.getKey().equalsIgnoreCase("location") || header.getKey().equalsIgnoreCase("azure-asyncoperation")) {
|
||||
headerValueToStore = applyReplacementRule(headerValueToStore);
|
||||
}
|
||||
if (header.getKey().equalsIgnoreCase("retry-after")) {
|
||||
headerValueToStore = "0";
|
||||
addedRetryAfter = true;
|
||||
}
|
||||
responseData.put(header.getKey().toLowerCase(), headerValueToStore);
|
||||
}
|
||||
|
||||
if (!addedRetryAfter) {
|
||||
responseData.put("retry-after", "0");
|
||||
}
|
||||
|
||||
BufferedSource bufferedSource = response.body().source();
|
||||
bufferedSource.request(9223372036854775807L);
|
||||
Buffer buffer = bufferedSource.buffer().clone();
|
||||
String content = null;
|
||||
|
||||
if (response.header("Content-Encoding") == null) {
|
||||
String contentType = response.header("Content-Type");
|
||||
if (contentType != null) {
|
||||
if (contentType.startsWith("application/json"))
|
||||
{
|
||||
content = buffer.readString(Util.UTF_8);
|
||||
} else {
|
||||
content = BaseEncoding.base64().encode(buffer.readByteArray());
|
||||
}
|
||||
}
|
||||
} else if (response.header("Content-Encoding").equalsIgnoreCase("gzip")) {
|
||||
GZIPInputStream gis = new GZIPInputStream(buffer.inputStream());
|
||||
content = "";
|
||||
responseData.remove("Content-Encoding".toLowerCase());
|
||||
responseData.put("Content-Length".toLowerCase(), Integer.toString(content.length()));
|
||||
}
|
||||
|
||||
if (content != null) {
|
||||
content = applyReplacementRule(content);
|
||||
responseData.put("Body", content);
|
||||
}
|
||||
}
|
||||
|
||||
private void readDataFromFile() throws IOException {
|
||||
File recordFile = getRecordFile(testName);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
recordedData = mapper.readValue(recordFile, RecordedData.class);
|
||||
System.out.println("Total records " + recordedData.getNetworkCallRecords().size());
|
||||
}
|
||||
|
||||
private void writeDataToFile() throws IOException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
File recordFile = getRecordFile(testName);
|
||||
recordFile.createNewFile();
|
||||
mapper.writeValue(recordFile, recordedData);
|
||||
}
|
||||
|
||||
private File getRecordFile(String testName) {
|
||||
URL folderUrl = InterceptorManager.class.getClassLoader().getResource(".");
|
||||
File folderFile = new File(folderUrl.getPath() + RECORD_FOLDER);
|
||||
if (!folderFile.exists()) {
|
||||
folderFile.mkdir();
|
||||
}
|
||||
String filePath = folderFile.getPath() + "/" + testName + ".json";
|
||||
System.out.println("==> Playback file path: " + filePath);
|
||||
return new File(filePath);
|
||||
}
|
||||
|
||||
private String applyReplacementRule(String text) {
|
||||
for (Map.Entry<String, String> rule : textReplacementRules.entrySet()) {
|
||||
if (rule.getValue() != null) {
|
||||
text = text.replaceAll(rule.getKey(), rule.getValue());
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String removeHost(String url) {
|
||||
URI uri = URI.create(url);
|
||||
return String.format("%s?%s", uri.getPath(), uri.getQuery());
|
||||
}
|
||||
|
||||
public void pushVariable(String variable) {
|
||||
if (isRecordMode()) {
|
||||
synchronized (recordedData.getVariables()) {
|
||||
recordedData.getVariables().add(variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String popVariable() {
|
||||
synchronized (recordedData.getVariables()) {
|
||||
return recordedData.getVariables().remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder.base;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import okhttp3.*;
|
||||
import okhttp3.internal.Util;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
public class InterceptorManager {
|
||||
|
||||
private final static String RECORD_FOLDER = "session-records/";
|
||||
private final String testName;
|
||||
// Stores a map of all the HTTP properties in a session
|
||||
// A state machine ensuring a test is always reset before another one is setup
|
||||
private final TestBase.TestMode testMode;
|
||||
protected RecordedData recordedData;
|
||||
private Map<String, String> textReplacementRules = new HashMap<String, String>();
|
||||
|
||||
private InterceptorManager(String testName, TestBase.TestMode testMode) {
|
||||
this.testName = testName;
|
||||
this.testMode = testMode;
|
||||
}
|
||||
|
||||
// factory method
|
||||
public static InterceptorManager create(String testName, TestBase.TestMode testMode) throws IOException {
|
||||
InterceptorManager interceptorManager = new InterceptorManager(testName, testMode);
|
||||
|
||||
return interceptorManager;
|
||||
}
|
||||
|
||||
public void addTextReplacementRule(String regex, String replacement) {
|
||||
textReplacementRules.put(regex, replacement);
|
||||
}
|
||||
|
||||
public boolean isRecordMode() {
|
||||
return testMode == TestBase.TestMode.RECORD;
|
||||
}
|
||||
|
||||
public boolean isPlaybackMode() {
|
||||
return testMode == TestBase.TestMode.PLAYBACK;
|
||||
}
|
||||
|
||||
public Interceptor initInterceptor() throws IOException {
|
||||
switch (testMode) {
|
||||
case RECORD:
|
||||
recordedData = new RecordedData();
|
||||
return new Interceptor() {
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
return record(chain);
|
||||
}
|
||||
};
|
||||
case PLAYBACK:
|
||||
readDataFromFile();
|
||||
return new Interceptor() {
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
return playback(chain);
|
||||
}
|
||||
};
|
||||
default:
|
||||
System.out.println("==> Unknown AZURE_TEST_MODE: " + testMode);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void finalizeInterceptor() throws IOException {
|
||||
switch (testMode) {
|
||||
case RECORD:
|
||||
writeDataToFile();
|
||||
break;
|
||||
case PLAYBACK:
|
||||
// Do nothing
|
||||
break;
|
||||
default:
|
||||
System.out.println("==> Unknown AZURE_TEST_MODE: " + testMode);
|
||||
}
|
||||
}
|
||||
|
||||
private Response record(Interceptor.Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
NetworkCallRecord networkCallRecord = new NetworkCallRecord();
|
||||
|
||||
networkCallRecord.Headers = new HashMap<>();
|
||||
|
||||
if (request.header("Content-Type") != null) {
|
||||
networkCallRecord.Headers.put("Content-Type", request.header("Content-Type"));
|
||||
}
|
||||
if (request.header("x-ms-version") != null) {
|
||||
networkCallRecord.Headers.put("x-ms-version", request.header("x-ms-version"));
|
||||
}
|
||||
if (request.header("User-Agent") != null) {
|
||||
networkCallRecord.Headers.put("User-Agent", request.header("User-Agent"));
|
||||
}
|
||||
|
||||
networkCallRecord.Method = request.method();
|
||||
networkCallRecord.Uri = applyReplacementRule(request.url().toString().replaceAll("\\?$", ""));
|
||||
|
||||
networkCallRecord.Body = bodyToString(request);
|
||||
|
||||
Response response = chain.proceed(request);
|
||||
|
||||
networkCallRecord.Response = new HashMap<>();
|
||||
networkCallRecord.Response.put("StatusCode", Integer.toString(response.code()));
|
||||
extractResponseData(networkCallRecord.Response, response);
|
||||
|
||||
// remove pre-added header if this is a waiting or redirection
|
||||
if (networkCallRecord.Response.get("Body") != null) {
|
||||
if (networkCallRecord.Response.get("Body").contains("<Status>InProgress</Status>")
|
||||
|| Integer.parseInt(networkCallRecord.Response.get("StatusCode")) == 307) {
|
||||
// Do nothing
|
||||
} else {
|
||||
synchronized (recordedData.getNetworkCallRecords()) {
|
||||
recordedData.getNetworkCallRecords().add(networkCallRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private String bodyToString(final Request request) {
|
||||
try {
|
||||
final Buffer buffer = new Buffer();
|
||||
|
||||
request.newBuilder().build().body().writeTo(buffer);
|
||||
return buffer.readUtf8();
|
||||
} catch (final Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private Response playback(Interceptor.Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
String incomingUrl = applyReplacementRule(request.url().toString());
|
||||
String incomingMethod = request.method();
|
||||
|
||||
incomingUrl = removeHost(incomingUrl);
|
||||
NetworkCallRecord networkCallRecord = null;
|
||||
synchronized (recordedData) {
|
||||
for (Iterator<NetworkCallRecord> iterator = recordedData.getNetworkCallRecords().iterator(); iterator.hasNext(); ) {
|
||||
NetworkCallRecord record = iterator.next();
|
||||
if (record.Method.equalsIgnoreCase(incomingMethod) && removeHost(record.Uri).equalsIgnoreCase(incomingUrl)) {
|
||||
networkCallRecord = record;
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (networkCallRecord == null) {
|
||||
System.out.println("NOT FOUND - " + incomingMethod + " " + incomingUrl);
|
||||
System.out.println("Remaining records " + recordedData.getNetworkCallRecords().size());
|
||||
throw new IOException("==> Unexpected request: " + incomingMethod + " " + incomingUrl);
|
||||
}
|
||||
|
||||
int recordStatusCode = Integer.parseInt(networkCallRecord.Response.get("StatusCode"));
|
||||
|
||||
//Response originalResponse = chain.proceed(request);
|
||||
//originalResponse.body().close();
|
||||
|
||||
Response.Builder responseBuilder = new Response.Builder()
|
||||
.request(request.newBuilder().build())
|
||||
.protocol(Protocol.HTTP_2)
|
||||
.code(recordStatusCode).message("-");
|
||||
|
||||
for (Map.Entry<String, String> pair : networkCallRecord.Response.entrySet()) {
|
||||
if (!pair.getKey().equals("StatusCode") && !pair.getKey().equals("Body") && !pair.getKey().equals("Content-Length")) {
|
||||
String rawHeader = pair.getValue();
|
||||
for (Map.Entry<String, String> rule : textReplacementRules.entrySet()) {
|
||||
if (rule.getValue() != null) {
|
||||
rawHeader = rawHeader.replaceAll(rule.getKey(), rule.getValue());
|
||||
}
|
||||
}
|
||||
responseBuilder.addHeader(pair.getKey(), rawHeader);
|
||||
}
|
||||
}
|
||||
|
||||
String rawBody = networkCallRecord.Response.get("Body");
|
||||
if (rawBody != null) {
|
||||
for (Map.Entry<String, String> rule : textReplacementRules.entrySet()) {
|
||||
if (rule.getValue() != null) {
|
||||
rawBody = rawBody.replaceAll(rule.getKey(), rule.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
String rawContentType = networkCallRecord.Response.get("content-type");
|
||||
String contentType = rawContentType == null
|
||||
? "application/json; charset=utf-8"
|
||||
: rawContentType;
|
||||
|
||||
ResponseBody responseBody;
|
||||
|
||||
if (contentType.toLowerCase().contains("application/json")) {
|
||||
responseBody = ResponseBody.create(MediaType.parse(contentType), rawBody.getBytes());
|
||||
} else {
|
||||
responseBody = ResponseBody.create(MediaType.parse(contentType), BaseEncoding.base64().decode(rawBody));
|
||||
}
|
||||
|
||||
responseBuilder.body(responseBody);
|
||||
responseBuilder.addHeader("Content-Length", String.valueOf(rawBody.getBytes(StandardCharsets.UTF_8).length));
|
||||
}
|
||||
|
||||
Response newResponse = responseBuilder.build();
|
||||
|
||||
return newResponse;
|
||||
}
|
||||
|
||||
private void extractResponseData(Map<String, String> responseData, Response response) throws IOException {
|
||||
Map<String, List<String>> headers = response.headers().toMultimap();
|
||||
boolean addedRetryAfter = false;
|
||||
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
|
||||
String headerValueToStore = header.getValue().get(0);
|
||||
|
||||
if (header.getKey().equalsIgnoreCase("location") || header.getKey().equalsIgnoreCase("azure-asyncoperation")) {
|
||||
headerValueToStore = applyReplacementRule(headerValueToStore);
|
||||
}
|
||||
if (header.getKey().equalsIgnoreCase("retry-after")) {
|
||||
headerValueToStore = "0";
|
||||
addedRetryAfter = true;
|
||||
}
|
||||
responseData.put(header.getKey().toLowerCase(), headerValueToStore);
|
||||
}
|
||||
|
||||
if (!addedRetryAfter) {
|
||||
responseData.put("retry-after", "0");
|
||||
}
|
||||
|
||||
BufferedSource bufferedSource = response.body().source();
|
||||
bufferedSource.request(9223372036854775807L);
|
||||
Buffer buffer = bufferedSource.buffer().clone();
|
||||
String content = null;
|
||||
|
||||
if (response.header("Content-Encoding") == null) {
|
||||
String contentType = response.header("Content-Type");
|
||||
if (contentType != null) {
|
||||
if (contentType.startsWith("application/json")) {
|
||||
content = buffer.readString(Util.UTF_8);
|
||||
} else {
|
||||
content = BaseEncoding.base64().encode(buffer.readByteArray());
|
||||
}
|
||||
}
|
||||
} else if (response.header("Content-Encoding").equalsIgnoreCase("gzip")) {
|
||||
GZIPInputStream gis = new GZIPInputStream(buffer.inputStream());
|
||||
content = "";
|
||||
responseData.remove("Content-Encoding".toLowerCase());
|
||||
responseData.put("Content-Length".toLowerCase(), Integer.toString(content.length()));
|
||||
}
|
||||
|
||||
if (content != null) {
|
||||
content = applyReplacementRule(content);
|
||||
responseData.put("Body", content);
|
||||
}
|
||||
}
|
||||
|
||||
private void readDataFromFile() throws IOException {
|
||||
File recordFile = getRecordFile(testName);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
recordedData = mapper.readValue(recordFile, RecordedData.class);
|
||||
System.out.println("Total records " + recordedData.getNetworkCallRecords().size());
|
||||
}
|
||||
|
||||
private void writeDataToFile() throws IOException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
File recordFile = getRecordFile(testName);
|
||||
recordFile.createNewFile();
|
||||
mapper.writeValue(recordFile, recordedData);
|
||||
}
|
||||
|
||||
private File getRecordFile(String testName) {
|
||||
URL folderUrl = InterceptorManager.class.getClassLoader().getResource(".");
|
||||
File folderFile = new File(folderUrl.getPath() + RECORD_FOLDER);
|
||||
if (!folderFile.exists()) {
|
||||
folderFile.mkdir();
|
||||
}
|
||||
String filePath = folderFile.getPath() + "/" + testName + ".json";
|
||||
System.out.println("==> Playback file path: " + filePath);
|
||||
return new File(filePath);
|
||||
}
|
||||
|
||||
private String applyReplacementRule(String text) {
|
||||
for (Map.Entry<String, String> rule : textReplacementRules.entrySet()) {
|
||||
if (rule.getValue() != null) {
|
||||
text = text.replaceAll(rule.getKey(), rule.getValue());
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String removeHost(String url) {
|
||||
URI uri = URI.create(url);
|
||||
return String.format("%s?%s", uri.getPath(), uri.getQuery());
|
||||
}
|
||||
|
||||
public void pushVariable(String variable) {
|
||||
if (isRecordMode()) {
|
||||
synchronized (recordedData.getVariables()) {
|
||||
recordedData.getVariables().add(variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String popVariable() {
|
||||
synchronized (recordedData.getVariables()) {
|
||||
return recordedData.getVariables().remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package com.microsoft.bot.builder.base;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class NetworkCallRecord {
|
||||
public String Method;
|
||||
public String Uri;
|
||||
public String Body;
|
||||
|
||||
public Map<String, String> Headers;
|
||||
public Map<String, String> Response;
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder.base;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class NetworkCallRecord {
|
||||
public String Method;
|
||||
public String Uri;
|
||||
public String Body;
|
||||
|
||||
public Map<String, String> Headers;
|
||||
public Map<String, String> Response;
|
||||
}
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
package com.microsoft.bot.builder.base;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class RecordedData {
|
||||
private LinkedList<NetworkCallRecord> networkCallRecords;
|
||||
|
||||
private LinkedList<String> variables;
|
||||
|
||||
public RecordedData() {
|
||||
networkCallRecords = new LinkedList<>();
|
||||
variables = new LinkedList<>();
|
||||
}
|
||||
|
||||
public LinkedList<NetworkCallRecord> getNetworkCallRecords() {
|
||||
return networkCallRecords;
|
||||
}
|
||||
|
||||
public LinkedList<String> getVariables() {
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder.base;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class RecordedData {
|
||||
private LinkedList<NetworkCallRecord> networkCallRecords;
|
||||
|
||||
private LinkedList<String> variables;
|
||||
|
||||
public RecordedData() {
|
||||
networkCallRecords = new LinkedList<>();
|
||||
variables = new LinkedList<>();
|
||||
}
|
||||
|
||||
public LinkedList<NetworkCallRecord> getNetworkCallRecords() {
|
||||
return networkCallRecords;
|
||||
}
|
||||
|
||||
public LinkedList<String> getVariables() {
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,212 +1,206 @@
|
|||
package com.microsoft.bot.builder.base;
|
||||
|
||||
import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials;
|
||||
import com.microsoft.rest.LogLevel;
|
||||
import com.microsoft.rest.RestClient;
|
||||
import com.microsoft.rest.ServiceResponseBuilder;
|
||||
import com.microsoft.rest.credentials.ServiceClientCredentials;
|
||||
import com.microsoft.rest.credentials.TokenCredentials;
|
||||
import com.microsoft.rest.interceptors.LoggingInterceptor;
|
||||
import com.microsoft.rest.serializer.JacksonAdapter;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class TestBase {
|
||||
|
||||
private PrintStream out;
|
||||
|
||||
protected enum RunCondition {
|
||||
MOCK_ONLY,
|
||||
LIVE_ONLY,
|
||||
BOTH
|
||||
}
|
||||
|
||||
public enum TestMode {
|
||||
PLAYBACK,
|
||||
RECORD
|
||||
}
|
||||
|
||||
private final RunCondition runCondition;
|
||||
|
||||
protected TestBase() {
|
||||
this(RunCondition.BOTH);
|
||||
}
|
||||
|
||||
protected TestBase(RunCondition runCondition) {
|
||||
this.runCondition = runCondition;
|
||||
}
|
||||
|
||||
private String shouldCancelTest(boolean isPlaybackMode) {
|
||||
// Determine whether to run the test based on the condition the test has been configured with
|
||||
switch (this.runCondition) {
|
||||
case MOCK_ONLY:
|
||||
return (!isPlaybackMode) ? "Test configured to run only as mocked, not live." : null;
|
||||
case LIVE_ONLY:
|
||||
return (isPlaybackMode) ? "Test configured to run only as live, not mocked." : null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static TestMode testMode = null;
|
||||
|
||||
protected final static String ZERO_CLIENT_ID = "00000000-0000-0000-0000-000000000000";
|
||||
protected final static String ZERO_CLIENT_SECRET = "00000000000000000000000";
|
||||
protected final static String ZERO_USER_ID = "<--dummy-user-id-->";
|
||||
protected final static String ZERO_BOT_ID = "<--dummy-bot-id-->";
|
||||
protected final static String ZERO_TOKEN = "<--dummy-token-->";
|
||||
|
||||
private static final String PLAYBACK_URI = "http://localhost:1234";
|
||||
|
||||
protected static String hostUri = null;
|
||||
protected static String clientId = null;
|
||||
protected static String clientSecret = null;
|
||||
protected static String userId = null;
|
||||
protected static String botId = null;
|
||||
|
||||
private static void initTestMode() throws IOException {
|
||||
String azureTestMode = System.getenv("AZURE_TEST_MODE");
|
||||
if (azureTestMode != null) {
|
||||
if (azureTestMode.equalsIgnoreCase("Record")) {
|
||||
testMode = TestMode.RECORD;
|
||||
} else if (azureTestMode.equalsIgnoreCase("Playback")) {
|
||||
testMode = TestMode.PLAYBACK;
|
||||
} else {
|
||||
throw new IOException("Unknown AZURE_TEST_MODE: " + azureTestMode);
|
||||
}
|
||||
} else {
|
||||
System.out.print("Environment variable 'AZURE_TEST_MODE' has not been set yet. Using 'PLAYBACK' mode.");
|
||||
testMode = TestMode.RECORD;
|
||||
}
|
||||
}
|
||||
|
||||
private static void initParams() {
|
||||
try {
|
||||
Properties mavenProps = new Properties();
|
||||
InputStream in = TestBase.class.getResourceAsStream("/maven.properties");
|
||||
if (in == null) {
|
||||
throw new IOException("The file \"maven.properties\" has not been generated yet. Please execute \"mvn compile\" to generate the file.");
|
||||
}
|
||||
mavenProps.load(in);
|
||||
|
||||
clientId = mavenProps.getProperty("clientId");
|
||||
clientSecret = mavenProps.getProperty("clientSecret");
|
||||
hostUri = mavenProps.getProperty("hostUrl");
|
||||
userId = mavenProps.getProperty("userId");
|
||||
botId = mavenProps.getProperty("botId");
|
||||
} catch (IOException e) {
|
||||
clientId = ZERO_CLIENT_ID;
|
||||
clientSecret = ZERO_CLIENT_SECRET;
|
||||
hostUri = PLAYBACK_URI;
|
||||
userId = ZERO_USER_ID;
|
||||
botId = ZERO_BOT_ID;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPlaybackMode() {
|
||||
if (testMode == null) try {
|
||||
initTestMode();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Can't init test mode.");
|
||||
}
|
||||
return testMode == TestMode.PLAYBACK;
|
||||
}
|
||||
|
||||
public static boolean isRecordMode() {
|
||||
return !isPlaybackMode();
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestName testName = new TestName();
|
||||
|
||||
protected InterceptorManager interceptorManager = null;
|
||||
|
||||
private static void printThreadInfo(String what) {
|
||||
long id = Thread.currentThread().getId();
|
||||
String name = Thread.currentThread().getName();
|
||||
System.out.println(String.format("\n***\n*** [%s:%s] - %s\n***\n", name, id, what));
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws IOException {
|
||||
printThreadInfo("beforeClass");
|
||||
initTestMode();
|
||||
initParams();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws IOException {
|
||||
printThreadInfo(String.format("%s: %s", "beforeTest", testName.getMethodName()));
|
||||
final String skipMessage = shouldCancelTest(isPlaybackMode());
|
||||
Assume.assumeTrue(skipMessage, skipMessage == null);
|
||||
|
||||
interceptorManager = InterceptorManager.create(testName.getMethodName(), testMode);
|
||||
|
||||
ServiceClientCredentials credentials;
|
||||
RestClient restClient;
|
||||
|
||||
if (isPlaybackMode()) {
|
||||
credentials = new TokenCredentials(null, ZERO_TOKEN);
|
||||
restClient = buildRestClient(new RestClient.Builder()
|
||||
.withBaseUrl(hostUri + "/")
|
||||
.withSerializerAdapter(new JacksonAdapter())
|
||||
.withResponseBuilderFactory(new ServiceResponseBuilder.Factory())
|
||||
.withCredentials(credentials)
|
||||
.withLogLevel(LogLevel.NONE)
|
||||
.withNetworkInterceptor(new LoggingInterceptor(LogLevel.BODY_AND_HEADERS))
|
||||
.withInterceptor(interceptorManager.initInterceptor())
|
||||
,true);
|
||||
|
||||
out = System.out;
|
||||
System.setOut(new PrintStream(new OutputStream() {
|
||||
public void write(int b) {
|
||||
//DO NOTHING
|
||||
}
|
||||
}));
|
||||
}
|
||||
else { // Record mode
|
||||
credentials = new MicrosoftAppCredentials(clientId, clientSecret);
|
||||
restClient = buildRestClient(new RestClient.Builder()
|
||||
.withBaseUrl(hostUri + "/")
|
||||
.withSerializerAdapter(new JacksonAdapter())
|
||||
.withResponseBuilderFactory(new ServiceResponseBuilder.Factory())
|
||||
.withCredentials(credentials)
|
||||
.withLogLevel(LogLevel.NONE)
|
||||
.withReadTimeout(3, TimeUnit.MINUTES)
|
||||
.withNetworkInterceptor(new LoggingInterceptor(LogLevel.BODY_AND_HEADERS))
|
||||
.withInterceptor(interceptorManager.initInterceptor())
|
||||
,false);
|
||||
|
||||
//interceptorManager.addTextReplacementRule(hostUri, PLAYBACK_URI);
|
||||
}
|
||||
initializeClients(restClient, botId, userId);
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws IOException {
|
||||
if(shouldCancelTest(isPlaybackMode()) != null) {
|
||||
return;
|
||||
}
|
||||
cleanUpResources();
|
||||
interceptorManager.finalizeInterceptor();
|
||||
}
|
||||
|
||||
protected void addTextReplacementRule(String from, String to ) {
|
||||
interceptorManager.addTextReplacementRule(from, to);
|
||||
}
|
||||
|
||||
protected RestClient buildRestClient(RestClient.Builder builder, boolean isMocked) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected abstract void initializeClients(RestClient restClient, String botId, String userId) throws IOException;
|
||||
protected abstract void cleanUpResources();
|
||||
}
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.microsoft.bot.builder.base;
|
||||
|
||||
import com.microsoft.bot.connector.authentication.MicrosoftAppCredentials;
|
||||
import com.microsoft.rest.LogLevel;
|
||||
import com.microsoft.rest.RestClient;
|
||||
import com.microsoft.rest.ServiceResponseBuilder;
|
||||
import com.microsoft.rest.credentials.ServiceClientCredentials;
|
||||
import com.microsoft.rest.credentials.TokenCredentials;
|
||||
import com.microsoft.rest.interceptors.LoggingInterceptor;
|
||||
import com.microsoft.rest.serializer.JacksonAdapter;
|
||||
import org.junit.*;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class TestBase {
|
||||
|
||||
protected final static String ZERO_CLIENT_ID = "00000000-0000-0000-0000-000000000000";
|
||||
protected final static String ZERO_CLIENT_SECRET = "00000000000000000000000";
|
||||
protected final static String ZERO_USER_ID = "<--dummy-user-id-->";
|
||||
protected final static String ZERO_BOT_ID = "<--dummy-bot-id-->";
|
||||
protected final static String ZERO_TOKEN = "<--dummy-token-->";
|
||||
private static final String PLAYBACK_URI = "http://localhost:1234";
|
||||
protected static String hostUri = null;
|
||||
protected static String clientId = null;
|
||||
protected static String clientSecret = null;
|
||||
protected static String userId = null;
|
||||
protected static String botId = null;
|
||||
private static TestMode testMode = null;
|
||||
private final RunCondition runCondition;
|
||||
@Rule
|
||||
public TestName testName = new TestName();
|
||||
protected InterceptorManager interceptorManager = null;
|
||||
private PrintStream out;
|
||||
protected TestBase() {
|
||||
this(RunCondition.BOTH);
|
||||
}
|
||||
protected TestBase(RunCondition runCondition) {
|
||||
this.runCondition = runCondition;
|
||||
}
|
||||
|
||||
private static void initTestMode() throws IOException {
|
||||
String azureTestMode = System.getenv("AZURE_TEST_MODE");
|
||||
if (azureTestMode != null) {
|
||||
if (azureTestMode.equalsIgnoreCase("Record")) {
|
||||
testMode = TestMode.RECORD;
|
||||
} else if (azureTestMode.equalsIgnoreCase("Playback")) {
|
||||
testMode = TestMode.PLAYBACK;
|
||||
} else {
|
||||
throw new IOException("Unknown AZURE_TEST_MODE: " + azureTestMode);
|
||||
}
|
||||
} else {
|
||||
System.out.print("Environment variable 'AZURE_TEST_MODE' has not been set yet. Using 'PLAYBACK' mode.");
|
||||
testMode = TestMode.RECORD;
|
||||
}
|
||||
}
|
||||
|
||||
private static void initParams() {
|
||||
try {
|
||||
Properties mavenProps = new Properties();
|
||||
InputStream in = TestBase.class.getResourceAsStream("/maven.properties");
|
||||
if (in == null) {
|
||||
throw new IOException("The file \"maven.properties\" has not been generated yet. Please execute \"mvn compile\" to generate the file.");
|
||||
}
|
||||
mavenProps.load(in);
|
||||
|
||||
clientId = mavenProps.getProperty("clientId");
|
||||
clientSecret = mavenProps.getProperty("clientSecret");
|
||||
hostUri = mavenProps.getProperty("hostUrl");
|
||||
userId = mavenProps.getProperty("userId");
|
||||
botId = mavenProps.getProperty("botId");
|
||||
} catch (IOException e) {
|
||||
clientId = ZERO_CLIENT_ID;
|
||||
clientSecret = ZERO_CLIENT_SECRET;
|
||||
hostUri = PLAYBACK_URI;
|
||||
userId = ZERO_USER_ID;
|
||||
botId = ZERO_BOT_ID;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPlaybackMode() {
|
||||
if (testMode == null) try {
|
||||
initTestMode();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Can't init test mode.");
|
||||
}
|
||||
return testMode == TestMode.PLAYBACK;
|
||||
}
|
||||
|
||||
public static boolean isRecordMode() {
|
||||
return !isPlaybackMode();
|
||||
}
|
||||
|
||||
private static void printThreadInfo(String what) {
|
||||
long id = Thread.currentThread().getId();
|
||||
String name = Thread.currentThread().getName();
|
||||
System.out.println(String.format("\n***\n*** [%s:%s] - %s\n***\n", name, id, what));
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws IOException {
|
||||
printThreadInfo("beforeClass");
|
||||
initTestMode();
|
||||
initParams();
|
||||
}
|
||||
|
||||
private String shouldCancelTest(boolean isPlaybackMode) {
|
||||
// Determine whether to run the test based on the condition the test has been configured with
|
||||
switch (this.runCondition) {
|
||||
case MOCK_ONLY:
|
||||
return (!isPlaybackMode) ? "Test configured to run only as mocked, not live." : null;
|
||||
case LIVE_ONLY:
|
||||
return (isPlaybackMode) ? "Test configured to run only as live, not mocked." : null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws IOException {
|
||||
printThreadInfo(String.format("%s: %s", "beforeTest", testName.getMethodName()));
|
||||
final String skipMessage = shouldCancelTest(isPlaybackMode());
|
||||
Assume.assumeTrue(skipMessage, skipMessage == null);
|
||||
|
||||
interceptorManager = InterceptorManager.create(testName.getMethodName(), testMode);
|
||||
|
||||
ServiceClientCredentials credentials;
|
||||
RestClient restClient;
|
||||
|
||||
if (isPlaybackMode()) {
|
||||
credentials = new TokenCredentials(null, ZERO_TOKEN);
|
||||
restClient = buildRestClient(new RestClient.Builder()
|
||||
.withBaseUrl(hostUri + "/")
|
||||
.withSerializerAdapter(new JacksonAdapter())
|
||||
.withResponseBuilderFactory(new ServiceResponseBuilder.Factory())
|
||||
.withCredentials(credentials)
|
||||
.withLogLevel(LogLevel.NONE)
|
||||
.withNetworkInterceptor(new LoggingInterceptor(LogLevel.BODY_AND_HEADERS))
|
||||
.withInterceptor(interceptorManager.initInterceptor())
|
||||
, true);
|
||||
|
||||
out = System.out;
|
||||
System.setOut(new PrintStream(new OutputStream() {
|
||||
public void write(int b) {
|
||||
//DO NOTHING
|
||||
}
|
||||
}));
|
||||
} else { // Record mode
|
||||
credentials = new MicrosoftAppCredentials(clientId, clientSecret);
|
||||
restClient = buildRestClient(new RestClient.Builder()
|
||||
.withBaseUrl(hostUri + "/")
|
||||
.withSerializerAdapter(new JacksonAdapter())
|
||||
.withResponseBuilderFactory(new ServiceResponseBuilder.Factory())
|
||||
.withCredentials(credentials)
|
||||
.withLogLevel(LogLevel.NONE)
|
||||
.withReadTimeout(3, TimeUnit.MINUTES)
|
||||
.withNetworkInterceptor(new LoggingInterceptor(LogLevel.BODY_AND_HEADERS))
|
||||
.withInterceptor(interceptorManager.initInterceptor())
|
||||
, false);
|
||||
|
||||
//interceptorManager.addTextReplacementRule(hostUri, PLAYBACK_URI);
|
||||
}
|
||||
initializeClients(restClient, botId, userId);
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws IOException {
|
||||
if (shouldCancelTest(isPlaybackMode()) != null) {
|
||||
return;
|
||||
}
|
||||
cleanUpResources();
|
||||
interceptorManager.finalizeInterceptor();
|
||||
}
|
||||
|
||||
protected void addTextReplacementRule(String from, String to) {
|
||||
interceptorManager.addTextReplacementRule(from, to);
|
||||
}
|
||||
|
||||
protected RestClient buildRestClient(RestClient.Builder builder, boolean isMocked) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected abstract void initializeClients(RestClient restClient, String botId, String userId) throws IOException;
|
||||
|
||||
protected abstract void cleanUpResources();
|
||||
|
||||
protected enum RunCondition {
|
||||
MOCK_ONLY,
|
||||
LIVE_ONLY,
|
||||
BOTH
|
||||
}
|
||||
|
||||
public enum TestMode {
|
||||
PLAYBACK,
|
||||
RECORD
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче