killbill-memoizeit

Add new TestResource to manipulate the clock for integration

8/29/2013 12:46:23 AM

Details

diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
index 7812f48..8152cbe 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultEntitlementApi.java
@@ -265,21 +265,25 @@ public class DefaultEntitlementApi implements EntitlementApi {
     private LocalDate getEffectiveEndDate(final UUID accountId, final SubscriptionBase subscriptionBase, final DateTimeZone accountTimeZone, final InternalTenantContext context) {
 
         LocalDate result = null;
+        BlockingState lastEntry = null;
 
-        final BlockingState subEntitlementState = blockingStateDao.getBlockingStateForService(subscriptionBase.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
-        if (subEntitlementState != null && ENT_STATE_CANCELLED.equals(subEntitlementState.getStateName())) {
-            result = new LocalDate(subEntitlementState.getEffectiveDate(), accountTimeZone);
+        final List<BlockingState> subEntitlementState = blockingStateDao.getBlockingHistoryForService(subscriptionBase.getId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
+        lastEntry = (subEntitlementState.size() > 0) ? subEntitlementState.get(subEntitlementState.size() - 1) : null;
+        if (lastEntry != null && ENT_STATE_CANCELLED.equals(lastEntry.getStateName())) {
+            result = new LocalDate(lastEntry.getEffectiveDate(), accountTimeZone);
         }
 
-        final BlockingState bundleEntitlementState = blockingStateDao.getBlockingStateForService(subscriptionBase.getBundleId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
-        if (bundleEntitlementState != null && ENT_STATE_CANCELLED.equals(bundleEntitlementState.getStateName())) {
-            final LocalDate localDate = new LocalDate(bundleEntitlementState.getEffectiveDate(), accountTimeZone);
+        final List<BlockingState> bundleEntitlementState = blockingStateDao.getBlockingHistoryForService(subscriptionBase.getBundleId(), EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
+        lastEntry = (bundleEntitlementState.size() > 0) ? bundleEntitlementState.get(bundleEntitlementState.size() - 1) : null;
+        if (lastEntry != null && ENT_STATE_CANCELLED.equals(lastEntry.getStateName())) {
+            final LocalDate localDate = new LocalDate(lastEntry.getEffectiveDate(), accountTimeZone);
             result = ((result == null) || (localDate.compareTo(result) < 0)) ? localDate : result;
         }
 
-        final BlockingState accountEntitlementState = blockingStateDao.getBlockingStateForService(accountId, EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
-        if (accountEntitlementState != null && ENT_STATE_CANCELLED.equals(accountEntitlementState.getStateName())) {
-            final LocalDate localDate = new LocalDate(accountEntitlementState.getEffectiveDate(), accountTimeZone);
+        final List<BlockingState> accountEntitlementState = blockingStateDao.getBlockingHistoryForService(accountId, EntitlementService.ENTITLEMENT_SERVICE_NAME, context);
+        lastEntry = (accountEntitlementState.size() > 0) ? accountEntitlementState.get(accountEntitlementState.size() - 1) : null;
+        if (lastEntry != null && ENT_STATE_CANCELLED.equals(lastEntry.getStateName())) {
+            final LocalDate localDate = new LocalDate(lastEntry.getEffectiveDate(), accountTimeZone);
             result = ((result == null) || (localDate.compareTo(result) < 0)) ? localDate : result;
         }
         return result;
diff --git a/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg b/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
index dacc64f..94ad70e 100644
--- a/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
+++ b/entitlement/src/main/resources/com/ning/billing/entitlement/dao/BlockingStateSqlDao.sql.stg
@@ -70,7 +70,6 @@ from
 <tableName()>
 where blockable_id = :blockableId
 and service = :service
-and effective_date \<= :effectiveDate
 <AND_CHECK_TENANT()>
 order by record_id asc
 ;
@@ -82,7 +81,6 @@ select
 from
 <tableName()>
 where blockable_id = :blockableId
-and effective_date \<= :effectiveDate
 <AND_CHECK_TENANT()>
 order by record_id asc
 ;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java
index 5b2bb40..f4f96cd 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultEntitlement.java
@@ -90,7 +90,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
             entitlement.cancelEntitlementWithDate(cancelDate, callContext);
             final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
             assertEquals(entitlement2.getState(), EntitlementState.ACTIVE);
-            assertNull(entitlement2.getEffectiveEndDate());
+            assertEquals(entitlement2.getEffectiveEndDate(), cancelDate);
 
             clock.addDays(1);
             final Entitlement entitlement3 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
@@ -157,7 +157,7 @@ public class TestDefaultEntitlement extends EntitlementTestSuiteWithEmbeddedDB {
             final Entitlement entitlement2 = entitlementApi.getEntitlementForId(entitlement.getId(), callContext);
             final Entitlement entitlement3 = entitlement2.cancelEntitlementWithPolicy(EntitlementActionPolicy.END_OF_TERM, callContext);
             assertEquals(entitlement3.getState(), EntitlementState.ACTIVE);
-            assertNull(entitlement3.getEffectiveEndDate());
+            assertEquals(entitlement3.getEffectiveEndDate(), new LocalDate(ctd));
 
             clock.addMonths(1);
 
diff --git a/jaxrs/killbill-jaxrs.iml b/jaxrs/killbill-jaxrs.iml
index 4ac3bed..7fa52b8 100644
--- a/jaxrs/killbill-jaxrs.iml
+++ b/jaxrs/killbill-jaxrs.iml
@@ -62,7 +62,7 @@
     <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.5" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
     <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.6.3-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.0.1" level="project" />
     <orderEntry type="library" name="Maven: javax.ws.rs:jsr311-api:1.1.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-all:1.9.0" level="project" />

jaxrs/pom.xml 3(+3 -0)

diff --git a/jaxrs/pom.xml b/jaxrs/pom.xml
index fe3ccb3..f8a63f3 100644
--- a/jaxrs/pom.xml
+++ b/jaxrs/pom.xml
@@ -63,7 +63,10 @@
             <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-clock</artifactId>
             <type>test-jar</type>
+            <!--
+            Until we move ClockMock outside of test package
             <scope>test</scope>
+            -->
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/EntitlementResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/EntitlementResource.java
index ae6d628..503500c 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/EntitlementResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/EntitlementResource.java
@@ -37,7 +37,6 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriInfo;
 
-import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -51,6 +50,7 @@ import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.clock.Clock;
 import com.ning.billing.entitlement.api.Entitlement;
+import com.ning.billing.entitlement.api.Entitlement.EntitlementActionPolicy;
 import com.ning.billing.entitlement.api.Entitlement.EntitlementState;
 import com.ning.billing.entitlement.api.EntitlementApi;
 import com.ning.billing.entitlement.api.EntitlementApiException;
@@ -167,7 +167,7 @@ public class EntitlementResource extends JaxRsResourceBase {
                                           @QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
                                           @QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") final Boolean callCompletion,
                                           @QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("3") final long timeoutSec,
-                                          @QueryParam(QUERY_POLICY) final String policyString,
+                                          @QueryParam(QUERY_BILLING_POLICY) final String policyString,
                                           @HeaderParam(HDR_CREATED_BY) final String createdBy,
                                           @HeaderParam(HDR_REASON) final String reason,
                                           @HeaderParam(HDR_COMMENT) final String comment,
@@ -241,7 +241,8 @@ public class EntitlementResource extends JaxRsResourceBase {
                                           @QueryParam(QUERY_REQUESTED_DT) final String requestedDate,
                                           @QueryParam(QUERY_CALL_COMPLETION) @DefaultValue("false") final Boolean callCompletion,
                                           @QueryParam(QUERY_CALL_TIMEOUT) @DefaultValue("5") final long timeoutSec,
-                                          @QueryParam(QUERY_POLICY) final String policyString,
+                                          @QueryParam(QUERY_ENTITLEMENT_POLICY) final String entitlementPolicyString,
+                                          @QueryParam(QUERY_BILLING_POLICY) final String billingPolicyString,
                                           @HeaderParam(HDR_CREATED_BY) final String createdBy,
                                           @HeaderParam(HDR_REASON) final String reason,
                                           @HeaderParam(HDR_COMMENT) final String comment,
@@ -263,11 +264,18 @@ public class EntitlementResource extends JaxRsResourceBase {
 
                 final LocalDate inputLocalDate = toLocalDate(current.getAccountId(), requestedDate, callContext);
                 final Entitlement newEntitlement;
-                if (policyString == null) {
+                if (billingPolicyString == null && entitlementPolicyString == null) {
                     newEntitlement = current.cancelEntitlementWithDate(inputLocalDate, ctx);
+                } else if (billingPolicyString == null && entitlementPolicyString != null) {
+                    final EntitlementActionPolicy entitlementPolicy = EntitlementActionPolicy.valueOf(entitlementPolicyString);
+                    newEntitlement = current.cancelEntitlementWithPolicy(entitlementPolicy, ctx);
+                } else if (billingPolicyString != null && entitlementPolicyString == null) {
+                    final BillingActionPolicy billingPolicy = BillingActionPolicy.valueOf(billingPolicyString.toUpperCase());
+                    newEntitlement = current.cancelEntitlementWithDateOverrideBillingPolicy(inputLocalDate, billingPolicy, ctx);
                 } else {
-                    final BillingActionPolicy policy = BillingActionPolicy.valueOf(policyString.toUpperCase());
-                    newEntitlement = current.cancelEntitlementWithDateOverrideBillingPolicy(inputLocalDate, policy, ctx);
+                    final EntitlementActionPolicy entitlementPolicy = EntitlementActionPolicy.valueOf(entitlementPolicyString);
+                    final BillingActionPolicy billingPolicy = BillingActionPolicy.valueOf(billingPolicyString.toUpperCase());
+                    newEntitlement = current.cancelEntitlementWithPolicyOverrideBillingPolicy(entitlementPolicy, billingPolicy, ctx);
                 }
                 isImmediateOp = newEntitlement.getState() == EntitlementState.ACTIVE;
                 return Response.status(Status.OK).build();
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
index b4e021d..2d6d880 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxrsResource.java
@@ -59,7 +59,8 @@ public interface JaxrsResource {
     public static final String QUERY_CALL_TIMEOUT = "callTimeoutSec";
     public static final String QUERY_DRY_RUN = "dryRun";
     public static final String QUERY_TARGET_DATE = "targetDate";
-    public static final String QUERY_POLICY = "policy";
+    public static final String QUERY_BILLING_POLICY = "billingPolicy";
+    public static final String QUERY_ENTITLEMENT_POLICY = "entitlementPolicy";
 
     public static final String QUERY_ACCOUNT_WITH_BALANCE = "accountWithBalance";
     public static final String QUERY_ACCOUNT_WITH_BALANCE_AND_CBA = "accountWithBalanceAndCBA";
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TestResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TestResource.java
new file mode 100644
index 0000000..26c9138
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/TestResource.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.jaxrs.resources;
+
+import java.util.UUID;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.account.api.AccountUserApi;
+import com.ning.billing.clock.Clock;
+import com.ning.billing.clock.ClockMock;
+import com.ning.billing.jaxrs.util.Context;
+import com.ning.billing.jaxrs.util.JaxrsUriBuilder;
+import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.api.CustomFieldUserApi;
+import com.ning.billing.util.api.TagUserApi;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+//
+// Test endpoint that should not be enabled on a production system.
+// The clock manipulation will only work if the ClockMock instance was injected
+// throughout the system; if not it will throw 500 (UnsupportedOperationException)
+//
+// Note that moving the clock back and forth on a running system may cause weird side effects,
+// so to be used with great caution.
+//
+//
+@Path(JaxrsResource.PREFIX + "/test")
+public class TestResource extends JaxRsResourceBase {
+
+    private static final Logger log = LoggerFactory.getLogger(TestResource.class);
+
+    @Inject
+    public TestResource(final JaxrsUriBuilder uriBuilder, final TagUserApi tagUserApi, final CustomFieldUserApi customFieldUserApi, final AuditUserApi auditUserApi, final AccountUserApi accountUserApi, final Clock clock, final Context context) {
+        super(uriBuilder, tagUserApi, customFieldUserApi, auditUserApi, accountUserApi, clock, context);
+    }
+
+
+    public final class ClockResource {
+
+        private final DateTime currentUtcTime;
+        private final String timeZone;
+        private final LocalDate localDate;
+
+        @JsonCreator
+        public ClockResource(@JsonProperty("currentUtcTime") final DateTime currentUtcTime,
+                             @JsonProperty("timeZone") final String timeZone,
+                             @JsonProperty("localDate") final LocalDate localDate) {
+
+            this.currentUtcTime = currentUtcTime;
+            this.timeZone = timeZone;
+            this.localDate = localDate;
+        }
+
+        public DateTime getCurrentUtcTime() {
+            return currentUtcTime;
+        }
+
+        public String getTimeZone() {
+            return timeZone;
+        }
+
+        public LocalDate getLocalDate() {
+            return localDate;
+        }
+    }
+
+    @GET
+    @Path("/clock")
+    @Produces(APPLICATION_JSON)
+    public Response getCurrentTime(@QueryParam("timeZone") final String timeZoneStr) {
+        final DateTimeZone timeZone = timeZoneStr != null ? DateTimeZone.forID(timeZoneStr) : DateTimeZone.UTC;
+        final DateTime now = clock.getUTCNow();
+        final ClockResource result = new ClockResource(now, timeZone.getID(), new LocalDate(now, timeZone));
+        return Response.status(Status.OK).entity(result).build();
+    }
+
+    @POST
+    @Path("/clock")
+    @Produces(APPLICATION_JSON)
+    public Response setTestClockTime(@QueryParam(QUERY_REQUESTED_DT) final String requestedClockDate,
+                                     @QueryParam("timeZone") final String timeZoneStr) {
+
+        final ClockMock testClock = getClockMock();
+        if (requestedClockDate == null) {
+            log.info("************      RESETTING CLOCK to " + clock.getUTCNow());
+            testClock.resetDeltaFromReality();
+        } else {
+            final DateTime newTime = DATE_TIME_FORMATTER.parseDateTime(requestedClockDate);
+            testClock.setTime(newTime);
+        }
+        return getCurrentTime(timeZoneStr);
+    }
+
+
+    @PUT
+    @Path("/clock")
+    @Produces(APPLICATION_JSON)
+    public Response updateTestClockTime(@QueryParam("days") final Integer addDays,
+                                        @QueryParam("weeks") final Integer addWeeks,
+                                        @QueryParam("months") final Integer addMonths,
+                                        @QueryParam("years") final Integer addYears,
+                                        @QueryParam("timeZone") final String timeZoneStr) {
+
+        final ClockMock testClock = getClockMock();
+        if (addDays != null) {
+            testClock.addDays(addDays);
+        } else if (addWeeks != null) {
+            testClock.addWeeks(addWeeks);
+        } else if (addMonths != null) {
+            testClock.addMonths(addMonths);
+        } else if (addYears != null) {
+            testClock.addYears(addYears);
+        }
+        return getCurrentTime(timeZoneStr);
+    }
+
+
+    private ClockMock getClockMock() {
+        if (!(clock instanceof ClockMock)) {
+            throw new UnsupportedOperationException("Kill Bill has not been configured to update the time");
+        }
+        return (ClockMock) clock;
+    }
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java
index 127449d..d7ca875 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/util/JaxrsUriBuilder.java
@@ -29,7 +29,9 @@ public class JaxrsUriBuilder {
         return ri.entity(new Object() {
             @SuppressWarnings(value = "all")
             public URI getUri() {
-                final URI newUriFromResource = UriBuilder.fromResource(theClass).path(theClass, getMethodName).build(objectId);
+                final URI newUriFromResource = objectId != null ?
+                                               UriBuilder.fromResource(theClass).path(theClass, getMethodName).build(objectId) :
+                                               UriBuilder.fromResource(theClass).path(theClass, getMethodName).build();
                 return newUriFromResource;
             }
         }).build();

pom.xml 2(+1 -1)

diff --git a/pom.xml b/pom.xml
index 6c8b8c4..248e0c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <artifactId>killbill-oss-parent</artifactId>
         <groupId>com.ning.billing</groupId>
-        <version>0.4.1</version>
+        <version>0.4.2-SNAPSHOT</version>
     </parent>
     <artifactId>killbill</artifactId>
     <version>0.6.3-SNAPSHOT</version>
diff --git a/server/killbill-server.iml b/server/killbill-server.iml
index 1830ef5..6827537 100644
--- a/server/killbill-server.iml
+++ b/server/killbill-server.iml
@@ -84,6 +84,7 @@
     <orderEntry type="module" module-name="killbill-beatrix" scope="TEST" production-on-test="" />
     <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-beatrix:test-jar:tests:0.6.3-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-jaxrs" />
+    <orderEntry type="library" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: javax.ws.rs:jsr311-api:1.1.1" level="project" />
     <orderEntry type="module" module-name="killbill-osgi" />
     <orderEntry type="module" module-name="killbill-osgi-bundles-lib-killbill" />
@@ -97,7 +98,6 @@
     <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-payment:test-jar:tests:0.6.3-SNAPSHOT" level="project" />
     <orderEntry type="module" module-name="killbill-util" scope="TEST" production-on-test="" />
     <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing:killbill-util:test-jar:tests:0.6.3-SNAPSHOT" level="project" />
-    <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-clock:test-jar:tests:0.2.1" level="project" />
     <orderEntry type="library" scope="TEST" name="Maven: com.ning.billing.commons:killbill-embeddeddb:0.2.1" level="project" />
     <orderEntry type="library" name="Maven: com.ning.jetty:ning-service-skeleton-base:0.1.7" level="project" />
     <orderEntry type="library" name="Maven: com.ning:metrics.eventtracker-smile:4.1.2" level="project" />

server/pom.xml 13(+8 -5)

diff --git a/server/pom.xml b/server/pom.xml
index c2236e9..dfbe2d3 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -149,7 +149,10 @@
             <groupId>com.ning.billing.commons</groupId>
             <artifactId>killbill-clock</artifactId>
             <type>test-jar</type>
-            <scope>test</scope>
+            <!--
++            Until we move ClockMock outside of test package
+           <scope>test</scope>
+           -->
         </dependency>
         <dependency>
             <groupId>com.ning.billing.commons</groupId>
@@ -305,10 +308,10 @@
                 <executions>
                     <execution>
                         <!-- We would like to be able to run the war, jar and jettyconsole plugins at the same time;
-                         and we could, except they rely on a strict ordering (jettyconsole has to run after the war and
-                         before the jar, or jettyconsole won't find the war artifact). This could be done by relying
-                         on the declaration ordering of the various plugins (all have to be bound to the package phase),
-                         but that's fragile. Instead, ignore altogether the jar for now, until maven is smarter. -->
+                        and we could, except they rely on a strict ordering (jettyconsole has to run after the war and
+                        before the jar, or jettyconsole won't find the war artifact). This could be done by relying
+                        on the declaration ordering of the various plugins (all have to be bound to the package phase),
+                        but that's fragile. Instead, ignore altogether the jar for now, until maven is smarter. -->
                         <phase>pierre-s-hack-for-maven</phase>
                     </execution>
                 </executions>
diff --git a/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java b/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
index 4ac7aa2..923560c 100644
--- a/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
+++ b/server/src/main/java/com/ning/billing/server/listeners/KillbillGuiceListener.java
@@ -48,6 +48,7 @@ public class KillbillGuiceListener extends SetupServer {
 
     public static final Logger logger = LoggerFactory.getLogger(KillbillGuiceListener.class);
     public static final String KILLBILL_MULTITENANT_PROPERTY = "killbill.server.multitenant";
+    public static final String KILLBILL_TEST_MODE_PROPERTY = "killbill.server.test.mode";
 
     private Injector injector;
     private DefaultLifecycle killbillLifecycle;
@@ -55,7 +56,8 @@ public class KillbillGuiceListener extends SetupServer {
     private KillbillEventHandler killbilleventHandler;
 
     protected Module getModule(final ServletContext servletContext) {
-        return new KillbillServerModule(servletContext);
+        final boolean testModeEnabled = Boolean.parseBoolean(System.getProperty(KILLBILL_TEST_MODE_PROPERTY, "false"));
+        return new KillbillServerModule(servletContext, testModeEnabled);
     }
 
     private void registerMBeansForCache(final CacheManager cacheManager) {
diff --git a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
index 8113fdc..646398e 100644
--- a/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
+++ b/server/src/main/java/com/ning/billing/server/modules/KillbillServerModule.java
@@ -19,6 +19,9 @@ package com.ning.billing.server.modules;
 import javax.servlet.ServletContext;
 import javax.sql.DataSource;
 
+import com.ning.billing.clock.Clock;
+import com.ning.billing.clock.ClockMock;
+import com.ning.billing.clock.DefaultClock;
 import com.ning.billing.entitlement.glue.DefaultEntitlementModule;
 import org.skife.config.ConfigSource;
 import org.skife.config.SimplePropertyConfigSource;
@@ -30,6 +33,7 @@ import com.ning.billing.beatrix.glue.BeatrixModule;
 import com.ning.billing.catalog.glue.CatalogModule;
 import com.ning.billing.jaxrs.resources.EntitlementResource;
 import com.ning.billing.jaxrs.resources.SubscriptionResource;
+import com.ning.billing.jaxrs.resources.TestResource;
 import com.ning.billing.subscription.glue.DefaultSubscriptionModule;
 import com.ning.billing.invoice.glue.DefaultInvoiceModule;
 import com.ning.billing.jaxrs.resources.AccountResource;
@@ -77,9 +81,11 @@ import com.google.inject.AbstractModule;
 public class KillbillServerModule extends AbstractModule {
 
     protected final ServletContext servletContext;
+    private final boolean isTestModeEnabled;
 
-    public KillbillServerModule(final ServletContext servletContext) {
+    public KillbillServerModule(final ServletContext servletContext, final boolean testModeEnabled) {
         this.servletContext = servletContext;
+        this.isTestModeEnabled = testModeEnabled;
     }
 
     @Override
@@ -127,7 +133,12 @@ public class KillbillServerModule extends AbstractModule {
     }
 
     protected void installClock() {
-        install(new ClockModule());
+        if (isTestModeEnabled) {
+            bind(Clock.class).to(ClockMock.class).asEagerSingleton();
+            bind(TestResource.class).asEagerSingleton();
+        } else {
+            install(new ClockModule());
+        }
     }
 
     protected void installKillbillModules() {
@@ -161,7 +172,6 @@ public class KillbillServerModule extends AbstractModule {
         install(new KillBillShiroWebModule(servletContext));
         install(new KillBillShiroAopModule());
         install(new SecurityModule());
-
         installClock();
     }
 }
diff --git a/server/src/main/resources/killbill-server.properties b/server/src/main/resources/killbill-server.properties
index 75a99e9..abe786a 100644
--- a/server/src/main/resources/killbill-server.properties
+++ b/server/src/main/resources/killbill-server.properties
@@ -22,8 +22,13 @@ com.ning.jetty.jdbi.password=root
 # Use the SpyCarAdvanced.xml catalog
 killbill.catalog.uri=SpyCarAdvanced.xml
 
+# Set default timezone to UTC
 user.timezone=UTC
 
+# For bundles that use antlr (string template)
 ANTLR_USE_DIRECT_CLASS_LOADING=true
 
+# To enable test endpoint and have Kill Bill run with a ClockMock
+killbill.server.test.mode=true
+
 
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestEntitlement.java b/server/src/test/java/com/ning/billing/jaxrs/TestEntitlement.java
index 399e63c..330cf26 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestEntitlement.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestEntitlement.java
@@ -168,7 +168,7 @@ public class TestEntitlement extends TestJaxrsBase {
                                                                              null);
         baseJson = mapper.writeValueAsString(newInput);
         final Map<String, String> queryParams = getQueryParamsForCallCompletion(CALL_COMPLETION_TIMEOUT_SEC);
-        queryParams.put(JaxrsResource.QUERY_POLICY, "immediate");
+        queryParams.put(JaxrsResource.QUERY_BILLING_POLICY, "immediate");
         response = doPut(uri, baseJson, queryParams, DEFAULT_HTTP_TIMEOUT_SEC);
         assertEquals(response.getStatusCode(), Status.OK.getStatusCode());
         baseJson = response.getResponseBody();
diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
index d900118..ea35d00 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -26,7 +26,6 @@ import javax.inject.Inject;
 import javax.servlet.Servlet;
 import javax.servlet.ServletContext;
 
-import org.apache.shiro.web.env.EnvironmentLoaderListener;
 import org.apache.shiro.web.servlet.ShiroFilter;
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.joda.time.LocalDate;
@@ -75,7 +74,6 @@ import com.ning.billing.util.glue.CallContextModule;
 import com.ning.billing.util.glue.CustomFieldModule;
 import com.ning.billing.util.glue.ExportModule;
 import com.ning.billing.util.glue.KillBillShiroAopModule;
-import com.ning.billing.util.glue.KillBillShiroModule;
 import com.ning.billing.util.glue.NonEntityDaoModule;
 import com.ning.billing.util.glue.NotificationQueueModule;
 import com.ning.billing.util.glue.RecordIdModule;
@@ -162,7 +160,7 @@ public class TestJaxrsBase extends KillbillClient {
         private final EmbeddedDB helper;
 
         public TestKillbillServerModule(final EmbeddedDB helper, final ServletContext servletContext) {
-            super(servletContext);
+            super(servletContext, false);
             this.helper = helper;
         }