// Path: src/main/java/io/castle/client/model/AuthenticateAction.java
// public enum AuthenticateAction {
//     ALLOW, DENY, CHALLENGE;
// 
//     /**
//      * Returns an AuthenticateAction from a string representing its name.
//      *
//      * @param action string representing the name of the AuthenticateAction, case-insensitive
//      * @return the enum value matching the name, or null if it does not match any enum
//      */
//     public static AuthenticateAction fromAction(String action) {
//         for (AuthenticateAction kind : AuthenticateAction.class.getEnumConstants()) {
//             if (kind.name().equalsIgnoreCase(action)) {
//                 return kind;
//             }
//         }
//         return null;
//     }
// }
// 
// Path: src/main/java/io/castle/client/model/AuthenticateFailoverStrategy.java
// public class AuthenticateFailoverStrategy {
// 
//     private final AuthenticateAction defaultAction;
//     private final boolean throwTimeoutException;
// 
//     private AuthenticateFailoverStrategy(AuthenticateAction defaultAction, boolean throwTimeoutException) {
//         this.defaultAction = defaultAction;
//         this.throwTimeoutException = throwTimeoutException;
//     }
// 
//     /**
//      * Sets the default authenticationAction for failed requests.
//      *
//      * @param action the authenticateAction that will be used as a default for failed requests
//      */
//     public AuthenticateFailoverStrategy(AuthenticateAction action) {
//         this(action, false);
//     }
// 
//     /**
//      * Creates an authenticationStrategy whose policy is to throw a timeoutException.
//      */
//     public AuthenticateFailoverStrategy() {
//         this(null, true);
//     }
// 
// 
//     /**
//      * Gets the authenticateAction that this strategy uses for failover.
//      *
//      * @return the authenticateAction configured as default; null if there is no default AuthenticateAction
//      */
//     public AuthenticateAction getDefaultAction() {
//         return defaultAction;
//     }
// 
//     /**
//      * Checks whether the failover strategy is configured to throw a timeoutException.
//      *
//      * @return true if the failover strategy is set to throw a timeoutException, false otherwise
//      */
//     public boolean isThrowTimeoutException() {
//         return throwTimeoutException;
//     }
// }
// 
// Path: src/test/java/io/castle/client/utils/SDKVersion.java
// public class SDKVersion {
// 
//     private static String libraryString = "\"library\":{\"name\":\"castle-java\",\"version\":\"" + getSDKVersion() + "\",\"platform\":\"" + getJavaPlatform() + "\",\"platform_version\":\"" + getJavaVersion() + "\"}";
// 
//     private static String version = getSDKVersion();
// 
//     public static String getLibraryString() {
//         return libraryString;
//     }
// 
//     public static String getVersion() {
//         return version;
//     }
// 
//     private static String getSDKVersion() {
//         Properties versionProperties = new Properties();
//         PropertiesReader reader = new PropertiesReader();
//         InputStream resourceAsStream = Castle.class.getClassLoader().getResourceAsStream("version.properties");
//         reader.loadPropertiesFromStream(versionProperties, resourceAsStream);
//         return versionProperties.getProperty("sdk.version");
//     }
// 
//     public static String getJavaVersion() {
//         return System.getProperty("java.vm.version");
//     }
// 
//     public static String getJavaPlatform() {
//         return System.getProperty("java.vm.name");
//     }
// }
// 
// Path: src/main/java/io/castle/client/model/AsyncCallbackHandler.java
// public interface AsyncCallbackHandler<T> {
//     void onResponse(T response);
// 
//     void onException(Exception exception);
// }


import io.castle.client.model.AuthenticateAction;
import io.castle.client.model.AuthenticateFailoverStrategy;
import io.castle.client.utils.SDKVersion;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.RecordedRequest;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Assert;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.mock.web.MockHttpServletRequest;
import com.google.common.collect.ImmutableMap;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.atomic.AtomicReference;
import io.castle.client.model.AsyncCallbackHandler;
import org.assertj.core.api.Assertions;
package io.castle.client;




public class CastleMergeHttpTest extends AbstractCastleHttpLayerTest {

    public CastleMergeHttpTest() {
        super(new AuthenticateFailoverStrategy(AuthenticateAction.CHALLENGE));
    }

    @Test
    public void mergeContextIsSendOnHttp() throws InterruptedException, JSONException {
        // Given
        server.enqueue(new MockResponse().setResponseCode(200));
        String event = "any.valid.event";

        // And a mock Request
        HttpServletRequest request = new MockHttpServletRequest();

        // And a extra context
        CustomExtraContext customExtraContext = new CustomExtraContext();
        customExtraContext.setAddString("String value");
        customExtraContext.setCondition(true);
        customExtraContext.setValue(10L);
        sdk.onRequest(request).mergeContext(customExtraContext).track(event, null, null, null, ImmutableMap.builder()
            .put("x", "valueX")
            .put("y", 234567)
            .build());

        RecordedRequest recordedRequest = server.takeRequest();
        String body = recordedRequest.getBody().readUtf8();

        JSONAssert.assertEquals("{\"event\":\"any.valid.event\",\"context\":{\"active\":true,\"ip\":\"127.0.0.1\",\"headers\":{\"REMOTE_ADDR\":\"127.0.0.1\"}," + SDKVersion.getLibraryString() +",\"add_string\":\"String value\",\"condition\":true,\"value\":10},\"user_traits\":{\"x\":\"valueX\",\"y\":234567}}", body, false);
    }

    @Test
    public void mergeContextIsNull() throws InterruptedException, JSONException {
        // Given
        server.enqueue(new MockResponse().setResponseCode(200));
        String event = "any.valid.event";

        // And a mock Request
        HttpServletRequest request = new MockHttpServletRequest();

        // And null context
        sdk.onRequest(request).mergeContext(null).track(event, null, null, null);

        RecordedRequest recordedRequest = server.takeRequest();
// Path: src/main/java/io/castle/client/model/AuthenticateAction.java
// public enum AuthenticateAction {
//     ALLOW, DENY, CHALLENGE;
// 
//     /**
//      * Returns an AuthenticateAction from a string representing its name.
//      *
//      * @param action string representing the name of the AuthenticateAction, case-insensitive
//      * @return the enum value matching the name, or null if it does not match any enum
//      */
//     public static AuthenticateAction fromAction(String action) {
//         for (AuthenticateAction kind : AuthenticateAction.class.getEnumConstants()) {
//             if (kind.name().equalsIgnoreCase(action)) {
//                 return kind;
//             }
//         }
//         return null;
//     }
// }
// 
// Path: src/main/java/io/castle/client/model/AuthenticateFailoverStrategy.java
// public class AuthenticateFailoverStrategy {
// 
//     private final AuthenticateAction defaultAction;
//     private final boolean throwTimeoutException;
// 
//     private AuthenticateFailoverStrategy(AuthenticateAction defaultAction, boolean throwTimeoutException) {
//         this.defaultAction = defaultAction;
//         this.throwTimeoutException = throwTimeoutException;
//     }
// 
//     /**
//      * Sets the default authenticationAction for failed requests.
//      *
//      * @param action the authenticateAction that will be used as a default for failed requests
//      */
//     public AuthenticateFailoverStrategy(AuthenticateAction action) {
//         this(action, false);
//     }
// 
//     /**
//      * Creates an authenticationStrategy whose policy is to throw a timeoutException.
//      */
//     public AuthenticateFailoverStrategy() {
//         this(null, true);
//     }
// 
// 
//     /**
//      * Gets the authenticateAction that this strategy uses for failover.
//      *
//      * @return the authenticateAction configured as default; null if there is no default AuthenticateAction
//      */
//     public AuthenticateAction getDefaultAction() {
//         return defaultAction;
//     }
// 
//     /**
//      * Checks whether the failover strategy is configured to throw a timeoutException.
//      *
//      * @return true if the failover strategy is set to throw a timeoutException, false otherwise
//      */
//     public boolean isThrowTimeoutException() {
//         return throwTimeoutException;
//     }
// }
// 
// Path: src/test/java/io/castle/client/utils/SDKVersion.java
// public class SDKVersion {
// 
//     private static String libraryString = "\"library\":{\"name\":\"castle-java\",\"version\":\"" + getSDKVersion() + "\",\"platform\":\"" + getJavaPlatform() + "\",\"platform_version\":\"" + getJavaVersion() + "\"}";
// 
//     private static String version = getSDKVersion();
// 
//     public static String getLibraryString() {
//         return libraryString;
//     }
// 
//     public static String getVersion() {
//         return version;
//     }
// 
//     private static String getSDKVersion() {
//         Properties versionProperties = new Properties();
//         PropertiesReader reader = new PropertiesReader();
//         InputStream resourceAsStream = Castle.class.getClassLoader().getResourceAsStream("version.properties");
//         reader.loadPropertiesFromStream(versionProperties, resourceAsStream);
//         return versionProperties.getProperty("sdk.version");
//     }
// 
//     public static String getJavaVersion() {
//         return System.getProperty("java.vm.version");
//     }
// 
//     public static String getJavaPlatform() {
//         return System.getProperty("java.vm.name");
//     }
// }
// 
// Path: src/main/java/io/castle/client/model/AsyncCallbackHandler.java
// public interface AsyncCallbackHandler<T> {
//     void onResponse(T response);
// 
//     void onException(Exception exception);
// }


// Path: src/test/java/io/castle/client/CastleMergeHttpTest.java
import io.castle.client.model.AuthenticateAction;
import io.castle.client.model.AuthenticateFailoverStrategy;
import io.castle.client.utils.SDKVersion;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.RecordedRequest;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Assert;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.mock.web.MockHttpServletRequest;
import com.google.common.collect.ImmutableMap;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.atomic.AtomicReference;
import io.castle.client.model.AsyncCallbackHandler;
import org.assertj.core.api.Assertions;

package io.castle.client;




public class CastleMergeHttpTest extends AbstractCastleHttpLayerTest {

    public CastleMergeHttpTest() {
        super(new AuthenticateFailoverStrategy(AuthenticateAction.CHALLENGE));
    }

    @Test
    public void mergeContextIsSendOnHttp() throws InterruptedException, JSONException {
        // Given
        server.enqueue(new MockResponse().setResponseCode(200));
        String event = "any.valid.event";

        // And a mock Request
        HttpServletRequest request = new MockHttpServletRequest();

        // And a extra context
        CustomExtraContext customExtraContext = new CustomExtraContext();
        customExtraContext.setAddString("String value");
        customExtraContext.setCondition(true);
        customExtraContext.setValue(10L);
        sdk.onRequest(request).mergeContext(customExtraContext).track(event, null, null, null, ImmutableMap.builder()
            .put("x", "valueX")
            .put("y", 234567)
            .build());

        RecordedRequest recordedRequest = server.takeRequest();
        String body = recordedRequest.getBody().readUtf8();

        JSONAssert.assertEquals("{\"event\":\"any.valid.event\",\"context\":{\"active\":true,\"ip\":\"127.0.0.1\",\"headers\":{\"REMOTE_ADDR\":\"127.0.0.1\"}," + SDKVersion.getLibraryString() +",\"add_string\":\"String value\",\"condition\":true,\"value\":10},\"user_traits\":{\"x\":\"valueX\",\"y\":234567}}", body, false);
    }

    @Test
    public void mergeContextIsNull() throws InterruptedException, JSONException {
        // Given
        server.enqueue(new MockResponse().setResponseCode(200));
        String event = "any.valid.event";

        // And a mock Request
        HttpServletRequest request = new MockHttpServletRequest();

        // And null context
        sdk.onRequest(request).mergeContext(null).track(event, null, null, null);

        RecordedRequest recordedRequest = server.takeRequest();
        String body = recordedRequest.getBody().readUtf8();